element-ui 包装的简单 半年时间选择器(仿日期选择器)【重置版】

没想到啊,几年前写的组件现在居然还有人用,然后很多人给我说有问题,毕竟这么多年了,我这次又重新修改下,不要再骂我了

这是效果

在这里插入图片描述
因为项目需求,需要有半年的选项,所以弄了这么个跟el日期选择器差不多的半年选项,默认禁止未来时间,你们也可以自己改改
不支持多选
返回为时间段
如图返回为['2024-07-01','2024-12-31']

以下是组件代码

<template>
  <div class="el-quarter-picker">
    <el-popover v-model="visible" placement="bottom-start" transition="el-zoom-in-top" trigger="click">
      <div class="content">
        <p>
          <button
            type="button"
            aria-label="前一年"
            class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left"
            @click="prev"
          />
          <span role="button" class="span-year">{{ year }}</span>
          <button
            type="button"
            aria-label="后一年"
            class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right"
            @click="next"
          />
        </p>
        <div class="choose-item">
          <button :class="classStyle1" :disabled="disabled1" @click="selectHalfYear('上半年',disabled1)">上半年</button>
          <button :class="classStyle2" :disabled="disabled2" @click="selectHalfYear('下半年',disabled2)">下半年</button>
        </div>
      </div>

      <el-input slot="reference" v-model="text" :placeholder="'选择半年'" size="small" @change="iptchange">
        <i slot="prefix" class="el-input__icon el-icon-date" />
      </el-input>
    </el-popover>
  </div>
</template>

<script>
export default {
  name: 'HalfYearPicker',
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    // 返回值,数组,格式为['2020-01-01','2020-06-30']
    // 如果有defaultValue,则默认[defaultValue,defaultValue]
    value: {
      type: Array,
      default: () => []
    },
    // 传入默认值
    // 格式为'2020-01-01'
    defaultValue: {
      type: String,
      default: ''
    },
    // 禁止时间,数组
    // 格式为['','2020-06-30'],1为开始时间,2为结束时间;
    // 1为空,2有值,为禁止2时间之后
    // 2为空,1有值,为禁止1时间之前
    // 1有值,2有值,为禁止1、2时间之间
    disabledDate: {
      type: Array,
      default: null
    }
  },
  data() {
    return {
      visible: false,
      text: '',
      year: new Date().getFullYear(),
      nowmonth: new Date().getMonth(),
      nowyear: new Date().getFullYear(),
      emitValue: [],
      clickyear: '',
      clickmonth: '',
      disabled1: false, // 禁止,开始时间之前
      disabled2: false // 禁止,开始时间之前
    }
  },
  computed: {
    classStyle1: function() {
      return {
        today: (this.nowyear === this.year) && (this.nowmonth < 6 || this.nowmonth) === 6,
        clickcell: (this.year === this.clickyear) && (this.clickmonth === '上半年'),
        selectMonth: true,
        'is-disabled': this.disabled1
      }
    },
    classStyle2: function() {
      return {
        today: (this.nowyear === this.year) && (this.nowmonth > 6),
        clickcell: (this.year === this.clickyear) && (this.clickmonth === '下半年'),
        selectMonth: true,
        'is-disabled': this.disabled2

      }
    }
  },
  mounted() {
    if (this.defaultValue) {
      const time = this.defaultValue.split('-')
      this.year = time[0]
      this.clickyear = time[0]
      this.clickmonth = time[1] < 7 ? '上半年' : '下半年'
      this.text = this.clickyear + this.clickmonth
      this.$emit('change', [this.defaultValue, this.defaultValue])
    }
    this.disabledDate && this.aviod(this.disabledDate)
  },
  methods: {
    // 上一年
    prev() {
      this.year = this.year * 1 - 1
      this.aviod(this.disabledDate)
    },
    // 下一年
    next() {
      this.year = this.year * 1 + 1
      this.aviod(this.disabledDate)
    },
    // 点击选项事件
    selectHalfYear(item, disabled) {
      if (disabled) return
      this.text = this.year + item
      this.clickyear = this.year
      this.clickmonth = item
      if (item === '上半年') {
        const data1 = this.year + '-01-01'
        const data2 = this.year + '-06-30'
        this.emitValue = [data1, data2]
      } else {
        const data1 = this.year + '-07-01'
        const data2 = this.year + '-12-31'
        this.emitValue = [data1, data2]
      }
      this.visible = false
      this.$emit('change', this.emitValue)
    },
    // 自主输入判断
    iptchange(val) {
      if (val !== '') {
        const year = val.slice(0, 4)
        const text = val.slice(4, 8)
        const reg = /^[0-9]{4}$/

        if (reg.test(year)) {
          if (text === '上半年' || text === '下半年') {
            this.text = val
            this.clickyear = year
            this.clickmonth = text
            this.year = year
            const data1 = this.year + '-01-01'
            const data2 = this.year + '-06-30'
            this.emitValue = [data1, data2]
            this.$emit('change', this.emitValue)
          } else {
            this.text = ''
          }
        } else {
          this.text = ''
        }
      } else {
        this.$emit('change', ['', ''])
      }
    },
    // 禁止事件
    aviod(disabledDate) {
      if (!disabledDate) return
      // 开始时间
      let timeA = disabledDate[0].split('-').map(Number)
      // 结束时间
      let timeB = disabledDate[1].split('-').map(Number)
      // 开始有值,结束有值,为禁止开始、结束时间之间(包括开始、结束)
      if (disabledDate[0].length > 0 && disabledDate[1].length > 0) {
        // 如果开始年大于结束年,交换位置
        if (timeA[0] > timeB[0]) {
          const c = timeA
          timeA = timeB
          timeB = c
        }
        // 一系列条件判断
        // 1.年份不在区间内,都不禁止
        if ((timeA[0] > this.year) || (timeB[0] < this.year)) {
          this.disabled1 = false
          this.disabled2 = false
        }
        // 2.开始小于当前
        if (timeA[0] < this.year) {
          // 2.1正常区间内
          if (timeB[0] > this.year) {
            this.disabled1 = true
            this.disabled2 = true
          }
          // 2.2结束年等于当前年
          if (timeB[0] === this.year) {
            this.disabled1 = true
            this.disabled2 = timeB[1] >= 6
          }
        }
        // 3.开始年等于当前年
        if (timeA[0] === this.year) {
          // 3.1结束大于当前
          if (timeB[0] > this.year) {
            this.disabled1 = timeA[1] < 7
            this.disabled2 = true
          }
          // 3.2两个年份相同
          if (timeB[0] === this.year) {
            // 开始月份大于结束月份,交换位置
            if (timeA[1] > timeB[2]) {
              const c = timeA
              timeA = timeB
              timeB = c
            }
            this.disabled1 = timeA[1] < 7
            this.disabled2 = timeB[1] >= 6
          }
        }
      }
      // 开始无值,结束有值,为禁止结束时间之后(包括结束)
      if (disabledDate[0].length === 0 && disabledDate[1].length > 0) {
        if (timeB[0] < this.year) {
          this.disabled1 = true
          this.disabled2 = true
        } else if (timeB[0] === this.year) {
          this.disabled1 = timeB[1] <= 6
          this.disabled2 = true
        } else {
          this.disabled1 = false
          this.disabled2 = false
        }
      }
      // 开始有值,结束无值,为禁止开始时间之前(包括开始)
      if (disabledDate[1].length === 0 && disabledDate[0].length > 0) {
        if (timeA[0] < this.year) {
          this.disabled1 = false
          this.disabled2 = false
        } else if (timeA[0] === this.year) {
          this.disabled1 = timeB[1] <= 6
          this.disabled2 = false
        } else {
          this.disabled1 = true
          this.disabled2 = true
        }
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.content {
  width: 220px;
  min-width: 220px;

  p {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: solid 1px #ebeef5;
    padding-bottom: 12px;
    font-size: 16px;

    button {
      margin-top: 0;
    }
  }

  .choose-item {
    display: flex;
    justify-content: space-around;

    .selectMonth {
      margin: 14px 10px;
      font-size: 12px;
      background: transparent;
      border: none;
    }

    .selectMonth:hover {
      color: #409eff;
      cursor: pointer;
    }

    .today {
      color: #409eff;
      font-weight: 700;
    }

    .clickcell {
      color: #409eff;
    }

    .is-disabled {
      color: #c0c4cc !important;
      cursor: not-allowed !important;
      background-color: #fff;
      border-color: #ebeef5;
    }
  }
}
</style>

页面引用

首先import一下组件,然后直接引用就是

<halfYear v-model="date" default-value="2029-01-01" :disabled-date="['2028-01-01', '2028-01-01']" />

参数

代码里面会有详细备注,这里就写个大概

参数名默认格式例子说明
value[]Array[‘2020-01-01’,‘2020-06-30’]v-model双向绑定值,父组件默认写[]
defaultValue“”String“2029-01-01”组件默认选中值
disabled-datenullArray[‘2028-01-01’, ‘2028-01-01’]禁止点击时间

注:输入框输入的时候不写日期,直接写+上半年/下半年,比如2024上半年,就会选中2024上半年

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值