时间选择器vue+antd实现近三天/近一周/近一个月/自定义

这个组件是基于vue和antd封装的,里面使用了ts语法,如果不需要可以改成js的写法

效果图

在这里插入图片描述

组件代码

html代码

<template>
  <div class="dateTemplate">
    <div class="time">
   <div v-for="(item,index) in dateList" :key="index" :class="{ istime: activedTimeDate == index }" @click="activedTime(index,item)" v-show="(item.name!='自定义')">
        {{ item.name }}
      </div>
      <div @click="activedTime(dateList.length-1,dateList[dateList.length-1])" v-show="(dateList[dateList.length-1].name=='自定义')">
        <div v-if="isdata">
          {{ dateList[dateList.length-1].name }}
          <img width="6" height="4" src="@/assets/images/sanjiao.png" />
        </div>
        <div :class="{ istime: activedTimeDate == dateList.length-1 }" v-else class="dataBox">
          <p>{{ startDate }}</p>
          <p>{{ endDate }}</p>
          <img width="6" height="4" src="@/assets/images/redsanjiao.png" alt="" />
        </div>
      </div>
    </div>
    <div class="date" v-if="show">
      <div class="xuanze" @click="clickData">
        <div class="left" :class="{ actived: isActived }" @click="actived(0)">
          {{ startDate }}
        </div>
        <span>至</span>
        <div class="left right" :class="{ actived: !isActived }" @click="actived(1)">
          {{ endDate }}
        </div>
      </div>
      <van-datetime-picker v-model="currentDate" type="date" title="日期筛选" :max-date="maxDate" :min-date="minDate" :formatter="formatter" @change="change" @cancel="cancel" @confirm="confirm"></van-datetime-picker>
    </div>
    <van-overlay :show="show" @click="overlay"></van-overlay>
    <div class="overlayimg" v-show="showoverlay">
      <img width="55" height="55" src="@/assets/images/tanhao1.png" alt="" />
      <p>无效的日期</p>
    </div>
  </div>
</template>

js代码

//自己定义的接口(ts语法)
// import { DateListPop } from '@/models/simulationMargin';
import { PropType } from 'vue/types/v3-component-props';
export interface DateListPop {
  value: number;
  type: string;
  name:string
}
<script lang="ts">
export default {
  name: 'DateTemplate',
  components: {},
  data() {
    return {
      minDate: '' as string,
      maxDate: '' as string,
      currentDate: '' as string,
      isActived: true as boolean,
      startDate: '' as string,
      endDate: '' as string,
      isActivedNumber: 0 as number,
      active: 1 as number,
      istime: true as boolean,
      activedTimeDate: 0 as number,
      show: false as boolean,
      showoverlay: false as boolean,
      isdata: true as boolean,
      getTime: '' as string
    };
  },
 props: {
    // type:day 天 month 月 year 年 custom 自定义
    dateList: {
      type: Array as PropType<DateListPop[]>,
      default: () => [
        { value: 3, type: 'day', name: '近三天' },
        { value: 7, type: 'day', name: '近一周' },
        { value: 1, type: 'month', name: '近一月' },
        // { value: 1, type: 'year', name: '近一年' },
        { value: 0, type: 'custom', name: '自定义' }
      ]
    },

    initDate: {
      type: Object,
      default: () => ({ value: 1, type: 'year' })
    },

    minDatePop: {
      type: Object,
      default: () => ({ value: 3, type: 'year' })
    },
    maxDatePop: {
      type: Object,
      default: () => ({ value: 0, type: 'year' })
    }
  },
  mounted() {
    this.get5();
  },
  methods: {
    // 获取时间
    get5() {               
		 this.getTime = new Date();
          if (this.maxDatePop.type == 'year') {
            this.maxDate = new Date(this.getRecentYear_Date(this.maxDatePop.value).split(' ')[0]);
          } else if (this.maxDatePop.type == 'month') {
            this.maxDate = new Date(this.getRecentMonth_Date(this.maxDatePop.value).split(' ')[0]);
          } else if (this.maxDatePop.type == 'day') {
            this.maxDate = new Date(this.getRecentDay_Date(this.maxDatePop.value).split(' ')[0]);
          }
          if (this.minDatePop.type == 'year') {
            this.minDate = new Date(this.getRecentYear_Date(this.minDatePop.value).split(' ')[0]);
          } else if (this.minDatePop.type == 'month') {
            this.minDate = new Date(this.getRecentMonth_Date(this.minDatePop.value).split(' ')[0]);
          } else if (this.minDatePop.type == 'day') {
            this.minDate = new Date(this.getRecentDay_Date(this.minDatePop.value).split(' ')[0]);
          }
          this.currentDate = new Date();
          this.activedTime(0, this.dateList[0]);
    
      });
    },

    overlay() {
      this.show = false;
      this.showoverlay = false;
    },
   // 时间转换成yy-mm-dd
    getYYMMDD(val: any) {
      const time = val;
      const year = time.getFullYear().toString().padStart(4, '0');
      const mon = (time.getMonth() + 1).toString().padStart(2, '0');
      const day = time.getDate().toString().padStart(2, '0');
      const curTime = year + '-' + mon + '-' + day;
      return curTime;
    },

    formatter(type: string, val: any) {
      if (type === 'year') {
        return `${val}年`;
      } else if (type === 'month') {
        return `${val}月`;
      } else if (type === 'day') {
        return `${val}日`;
      }
      return val;
    },

    cancel() {
      this.show = false;
      this.showoverlay = false;
    },
    confirm() {
      if (new Date(this.startDate) > new Date(this.endDate)) {
        this.show = true;
        this.showoverlay = true;
        setTimeout(() => {
          this.showoverlay = false;
        }, 1.5 * 1000);
      } else {
        this.cancel();
        this.$emit('activedTime', {
          startDate: this.startDate,
          endDate: this.endDate
        });
        this.isdata = false;
      }
    },
    /**
     *获取近n天的日期
     *{param:number } dayNum 天数
     */
    getRecentDay_Date(dayNum: number) {
      let result = '';
      const dd = new Date(this.getTime.getTime() - 3600 * 1000 * 24 * dayNum);
      const y = dd.getFullYear();
      const m = (dd.getMonth() + 1).toString().padStart(2, '0'); //获取当前月份的日期
      const d = dd.getDate().toString().padStart(2, '0');
      const day = y + '-' + m + '-' + d;
      const curTime = this.getYYMMDD(this.getTime);
      result += day + ' ';
      result += curTime;
      return result;
    },
    /**
     *获取近n月的日期
     *{param:number } monthNum 月数
     */
    getRecentMonth_Date(monthNum: number) {
      let result = '';
      let datenow = this.getTime;
      const dateend = datenow.getFullYear().toString() + '-' + (datenow.getMonth() + 1).toString().padStart(2, '0') + '-' + datenow.getDate().toString().padStart(2, '0');

      const dateArr = dateend.split('-');
      const year: any = dateArr[0]; //获取当前日期的年份
      const month: any = dateArr[1]; //获取当前日期的月份
      const day: any = dateArr[2]; //获取当前日期的日
      let days: any = new Date(year, month, 0);
      days = days.getDate(); //获取当前日期中月的天数
      let year2 = year;
      let month2: any = parseInt(month) - monthNum;
      if (month2 <= 0) {
        var absM: any = Math.abs(month2);
        year2 = parseInt(year2) - Math.ceil(absM / 12 == 0 ? 1 : parseInt(absM) / 12);
        month2 = 12 - (absM % 12);
      }
      let day2 = day;
      let days2: any = new Date(year2, month2, 0);
      days2 = days2.getDate();
      if (day2 > days2) {
        day2 = days2;
      }
      if (month2 < 10) {
        month2 = '0' + month2;
      }
      var t2 = year2 + '-' + month2.toString().padStart(2, '0') + '-' + day2.toString().padStart(2, '0');
      result += t2 + ' ';
      result += dateend;
      return result;
    },
    /**
     *获取近n年的日期
     *{param:number } yearNum 年数
     */
    getRecentYear_Date(yearNum: number) {
      let result = '';
      const dd = new Date(this.getTime);
      dd.setFullYear(dd.getFullYear() - yearNum);
      const y = dd.getFullYear();
      const m = (dd.getMonth() + 1).toString().padStart(2, '0');
      const d = dd.getDate().toString().padStart(2, '0');
      const curTime = this.getYYMMDD(this.getTime);
      const day = y + '-' + m + '-' + d;
      result += day + ' ';
      result += curTime;
      return result;
    },
    activedTime(val: number, item?: any) {
      console.log(val, item, item == undefined, 'val=======点击');
      this.activedTimeDate = val;
      this.isdata = true;
      this.show = false;
      let dateval = [];
      // type:day 天 month 月 year 年 custom 自定义
      if (item.type == 'day') {
        dateval = this.getRecentDay_Date(item.value).split(' ');
      } else if (item.type == 'month') {
        dateval = this.getRecentMonth_Date(item.value).split(' ');
      } else if (item.type == 'year') {
        dateval = this.getRecentYear_Date(item.value).split(' ');
      } else if (item.type == 'custom') {
        this.show = true;
        //自定义时间默认显示一年
        if (this.initDate.type == 'year') {
          dateval = this.getRecentYear_Date(this.initDate.value).split(' ');
        } else if (this.initDate.type == 'month') {
          dateval = this.getRecentMonth_Date(this.initDate.value).split(' ');
        } else if (this.initDate.type == 'day') {
          dateval = this.getRecentDay_Date(this.initDate.value).split(' ');
        }
        if (this.isActivedNumber == 0) {
          this.currentDate = new Date(dateval[0]);
        } else {
          this.currentDate = new Date(dateval[1]);
        }
      }
      this.startDate = dateval[0];
      this.endDate = dateval[1];
      if (item.type != 'custom') {
        this.$emit('activedTime', {
          startDate: this.startDate,
          endDate: this.endDate
        });
      }
    },
    actived(val: number) {
      this.isActived = !this.isActived;
      this.isActivedNumber = val;
      if (val == 0) {
        this.currentDate = new Date(this.startDate);
      } else {
        this.currentDate = new Date(this.endDate);
      }
    },
    change() {
      let curTime = this.getYYMMDD(this.currentDate);
      if (this.isActivedNumber == 0) {
        this.startDate = curTime;
      } else {
        this.endDate = curTime;
      }
    },
    clickData() {
      this.showoverlay = false;
    }
  },

};
</script>

css代码

<style scoped lang="scss">
.dateTemplate {
  .overlayimg {
    width: 140px;
    height: 140px;
    line-height: 140px;
    vertical-align: middle;
    text-align: center;
    background: rgba(0, 0, 0, 0.75);
    border-radius: 8px;
    backdrop-filter: blur(20px);
    position: absolute;
    top: 33%;
    left: 30%;
    z-index: 1002;
    img {
      display: inline-block;
      margin-top: -22px;
    }
    p {
      text-align: center;
      height: 21px;
      font-size: 15px;
      font-weight: 400;
      color: #ffffff;
      line-height: 21px;
      margin-top: -40px;
    }
  }
  .time {
    display: flex;
    justify-content: space-around;
    height: 40px;
    line-height: 40px;
    vertical-align: middle;
    background: #ffffff;
    font-size: 15px;
    font-weight: 400;
    color: #252525;
    .dataBox {
      height: 14px;
      font-size: 11px;
      font-weight: 500;
      line-height: 14px;
      vertical-align: middle;
      margin-top: 5px;
      img {
        position: relative;
        top: -22px;
        right: -70px;
      }
    }
    img {
      display: inline-block;
    }
    .istime {
      color: #d02541 !important;
    }
  }

  .date {
    position: fixed;
    width: 100%;
    bottom: 0;
    z-index: 1002;
    :deep .van-picker {
      border-radius: 10px 10px 0px 0px;
    }
    :deep .van-picker__cancel {
      font-size: 17px;
      font-weight: 400;
      color: #252525;
    }
    :deep .van-picker__confirm {
      font-size: 17px;
      font-weight: 400;
      color: #d02541;
    }
    :deep .van-picker__toolbar {
      height: 50px;
      background: #ffffff;
      box-shadow: inset 0px -0.5px 0px 0px #e8e8e8;
      border-radius: 10px 10px 0px 0px;
    }
    :deep .van-picker__columns {
      margin-top: 60px;
      left: 43px;
      margin-right: 86px;
    }
    :deep .van-picker__title {
      font-size: 18px;
      font-weight: 500;
      color: #252525;
    }
    :deep .van-picker-column__item {
      font-size: 17px;
      font-weight: 400;
      color: #252525;
    }
    :deep .van-picker__frame {
      left: 0;
      right: 0;
    }

    .xuanze {
      background: #fff;
      display: flex;
      justify-content: space-between;
      padding: 0 45px;
      position: absolute;
      top: 50px;
      width: 100%;
      height: 70px;
      line-height: 70px;
      vertical-align: middle;
      z-index: 3;
      font-size: 15px;
      font-weight: 500;
      color: #252525;
      // border-top: 1px solid #e8e8e8;
      // box-shadow: inset 0px -1px 0px 0px #e8e8e8;
      .actived {
        color: #d02541;
        border-bottom: 1px solid #d02541 !important;
      }
      .left {
        width: 100%;
        border-bottom: 1px solid #e8e8e8;
        text-align: center;
      }

      span {
        display: inline-block;
        width: 23px;
        font-size: 12px;
        font-weight: 400;
        color: #666666;
      }
    }
  }
  :deep .van-overlay {
    background-color: rgba(0, 0, 0, 0.4);
    z-index: 1000;
  }
}
</style>

组件应用

//页面直接使用

 <date-template @activedTime="activedTime"></date-template>

// 下面是引入组件和组件名称,自己命名就行了

import DateTemplate from '@/components/DateTemplate.vue';
 components: { DateTemplate },

打印出来的res值就是拿到的时间,直接在页面使用就行了

  methods: {
    activedTime(res: any) {
      console.log(res, 'val====');
    }
  }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值