klren0312 / daliy_knowledge

知识积累,正确使用方式是watch
21 stars 4 forks source link

elementui周选择器, 选中后展示日期范围 #464

Open klren0312 opened 3 years ago

klren0312 commented 3 years ago

1630395809(1)

<template>
  <div class="week-picker">
    <el-date-picker
      v-model="week"
      type="week"
      placeholder="选择周"
      :picker-options="{
        firstDayOfWeek: 1
      }"
      size="small"
      @change="changeWeekSelect"
    >
    </el-date-picker>
    <div class="week-div">
      <span class="week-text" :class="{ placeholder: value.length === 0 }">
        {{ value.length > 0 ? value[0] : '开始日期' }}
      </span>
      <span class="week-divide">至</span>
      <span class="week-text" :class="{ placeholder: value.length === 0 }">
        {{ value.length > 0 ? value[1] : '结束日期' }}
      </span>
    </div>
  </div>
</template>
<script>
export default {
  name: 'WeekPicker',
  props: {
    value: {
      type: Array,
      default: () => []
    }
  },
  model: {
    prop: 'value',
    event: 'update'
  },
  data() {
    return {
      week: '',
      weekDate: []
    }
  },
  mounted() {
    if (this.value.length !== 0) {
      this.week = new Date(this.value[0])
      this.weekDate = this.value
    }
  },
  methods: {
    changeWeekSelect(v) {
      if (!v) {
        this.weekDate = []
        this.$emit('update', this.weekDate)
        return
      }
      const oneDay = 86400000
      const startDate = new Date(v).getTime() - oneDay
      const endDate = new Date(v).getTime() + 5 * oneDay
      this.weekDate = [
        this.getFormatDate(new Date(startDate)).date,
        this.getFormatDate(new Date(endDate)).date
      ]
      this.$emit('update', this.weekDate)
    },
    /**
     * 获取格式化后的日期
     * @param {String} date 日期
     */
    getFormatDate(date = new Date()) {
      const year = this.addZero(date.getFullYear())
      const month = this.addZero(date.getMonth() + 1)
      const day = this.addZero(date.getDate())
      const hour = this.addZero(date.getHours())
      const minute = this.addZero(date.getMinutes())
      return {
        format: `${year}-${month}-${day} ${hour}:${minute}:00`,
        date: `${year}-${month}-${day}`,
        time: `${hour}:${minute}:00`
      }
    },
    /**
     * 单位数字转为两位数字
     * @param {number} num 数字
     * @returns {number} 转换后的数字
     */
    addZero(num) {
      if (num < 10) {
        return '0' + num
      } else {
        return num
      }
    }
  },
  watch: {
    value: {
      handler: function (nv) {
        if (nv.length > 0) {
          this.week = new Date(nv[0])
          this.weekDate = this.value
        }
      },
      deep: true
    }
  }
}
</script>
<style lang="scss">
.week-picker {
  position: relative;
  width: 260px;
  .el-date-editor.el-input,
  .el-date-editor.el-input__inner {
    width: 260px;
  }
  .el-date-editor {
    z-index: 1;
  }

  .el-input__inner {
    opacity: 0;
  }
  .el-input__icon {
    font-size: 14px;
  }

  .week-div {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    margin: 0 auto;
    width: 260px;
    text-align: center;
    font-size: 13px;
    color: #606266;
    border-radius: 4px;
    border: 1px solid #dcdfe6;
    box-sizing: border-box;
    .week-text {
      vertical-align: middle;
    }
    .week-divide {
      margin: 0 12px;
      color: #303133;
      vertical-align: middle;
    }
    .placeholder {
      margin: 0 8px;
      color: #c0c4cc;
      vertical-align: middle;
    }
  }
}
</style>
klren0312 commented 3 years ago

elementui 日期范围选择器 制作周选择

<template>
  <el-date-picker
    v-model="dateRange"
    type="daterange"
    placeholder="选择日期时间"
    :picker-options="weekOption"
    :editable="false"
    :clearable="false"
    format="yyyy-MM-dd"
    value-format="yyyy-MM-dd"
    size="small"
    range-separator="至"
    start-placeholder="开始日期"
    end-placeholder="结束日期"
  >
  </el-date-picker>
</template>
<script>
export default {
  name: 'WeekSelect',
  props: {
    dates: {
      // 当前选择的起始结束日期数组
      type: Array,
      default: () => ['', '']
    },
    showToday: {
      // 是否可选今天
      type: Boolean,
      default: false
    }
  },
  model: {
    prop: 'dates',
    event: 'update'
  },
  data() {
    return {
      startDate: '',
      weekOption: {
        firstDayOfWeek: 1,
        disabledDate: date => {
          const minus = this.showToday > 0 ? 0 : 24 * 60 * 60 * 1000
          if (!this.startDate) {
            return date && date.valueOf() >= new Date() - minus
          }
          // 周选择器只能选一季度
          const one = 90 * 24 * 3600 * 1000
          const minTime = this.startDate - one
          const maxTime = this.startDate + one
          // 前后只能选七天的倍数
          let isTrue = false
          // 判断结束时间是否是在一周七天内
          const dateTime = new Date(date)
          dateTime.setHours(0, 0, 0, 0)
          if (dateTime - this.startDate < 0) {
            // 前六天
            const prev6Date = new Date(this.startDate - 6 * 24 * 60 * 60 * 1000)
            prev6Date.setHours(0, 0, 0, 0)
            isTrue = (dateTime - prev6Date) % (7 * 24 * 60 * 60 * 1000) === 0
          } else {
            // 后六天
            const next6Date = new Date(this.startDate + 6 * 24 * 60 * 60 * 1000)
            next6Date.setHours(0, 0, 0, 0)
            isTrue = (dateTime - next6Date) % (7 * 24 * 60 * 60 * 1000) === 0
          }
          // 由于上面的规则会使起始时间的前一天变成可选状态, 所以要把前一天去除
          const yesterday =
            new Date(this.startDate).setHours(0, 0, 0, 0) - minus

          return (
            (date && date.valueOf() >= new Date() - minus) ||
            !isTrue ||
            yesterday === dateTime.getTime() ||
            date.getTime() < minTime ||
            date.getTime() > maxTime
          )
        },
        onPick: obj => {
          if (obj.minDate && !obj.maxDate) {
            this.startDate = obj.minDate.getTime()
          } else if (obj.maxDate) {
            this.startDate = null
          }
        }
      }
    }
  },
  computed: {
    dateRange: {
      get() {
        return this.dates
      },
      set(v) {
        this.$emit('update', v)
      }
    }
  }
}
</script>