element 季度选择器组件

本文介绍了如何在Vue中创建一个自定义的季度选择器组件,用户可以预览并选择未来时间段,同时组件会与父组件进行数据交互,传递选定的季度信息。
摘要由CSDN通过智能技术生成

效果图:

在这里插入图片描述
未来时间禁选(可选的)
在这里插入图片描述

回传给父组件的值:

在这里插入图片描述

季度选择器组件代码:

<template>
  <el-form>
    <el-form-item>
      <mark
        class="mark"
        v-show="showSeason"
        @click.stop="showSeason = false"
      ></mark>
      <el-input
        placeholder="请选择季度"
        readonly
        v-model="showValue"
        size="small"
        @focus="showSeason = true"
      >
        <i slot="prefix" class="el-input__icon el-icon-date"></i>
      </el-input>
      <el-card class="box-card" v-show="showSeason">
        <div slot="header" class="year-btn">
          <button
            type="button"
            aria-label="前一年"
            class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left"
            @click="prev"
          ></button>
          <span role="button">{{ year }}年</span>
          <button
            type="button"
            aria-label="后一年"
            @click="next"
            class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right"
          ></button>
        </div>
        <div class="season-list">
          <div
            v-for="btn in buttonList"
            :key="year + '-' + btn"
            :class="{
              'season-item': true,
              'is-active': showValue === `${year}年第${['', '一', '二', '三', '四'][btn]}季度`,
              'is-disabled': getDisable(year, btn)
            }"
            @click="selectSeason(btn)"
          >
          {{ `第${['', '一', '二', '三', '四'][btn]}季度` }}
          </div>
        </div>
      </el-card>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: 'CustomQuarterPicker',
  props: {
    defaultValue: {
      default: '', //  '2024年第二季度'
      type: String,
    },
    disabledFeature: { // 未来时间禁选
      type: Boolean,
      default: false,
    }
  },

  data() {
    this.buttonList = [1, 2, 3, 4]
    return {
      showSeason: false,
      season: '',
      year: new Date().getFullYear(),
      showValue: '',
      nowObj: {}
    }
  },

  created() {
    const now = new Date()
    let nowObj ={
      year: now.getFullYear(),
      season: (now.getMonth() + 1)
    }
    if(nowObj.season <= 3) {
      nowObj.season = 1
    } else if(nowObj.season <= 6) {
      nowObj.season = 2
    } else if(nowObj.season <= 9) {
      nowObj.season = 3
    } else {
      nowObj.season = 4
    }
    this.nowObj = nowObj
  },
  watch: {
    defaultValue: {
      handler(value) {
        if (value) {
          this.year = value.substr(0, 4)
          this.showValue = value
        }
      },
      immediate: true,
    },
  },
  methods: {
    prev() {
      this.year = +this.year - 1
    },
    next() {
      this.year = +this.year + 1
    },
    selectSeason(num) {
      if(this.getDisable(this.year, num)) return
      this.season = num
      this.showSeason = false
      this.showValue = `${this.year}年第${['', '一', '二', '三', '四'][num]}季度`
      this.sendMsg()
    },
    getDisable(year, btn) {
      return this.disabledFeature && (
        year > this.nowObj.year || 
        (year == this.nowObj.year && btn > this.nowObj.season)
      )
    },

    sendMsg() {
      const dateArr = [
        ['01-01', '03-31'],
        ['04-01', '06-30'],
        ['07-01', '09-30'],
        ['10-01', '12-31'],
      ]
      const result = {
        value: this.showValue,
        year: this.year,
        season: this.season,
        dateRange: [
          `${this.year}-${dateArr[this.season - 1][0]}`,
          `${this.year}-${dateArr[this.season - 1][1]}`,
        ],
        dateTimeRange: [
          `${this.year}-${dateArr[this.season - 1][0]} 00:00:00`,
          `${this.year}-${dateArr[this.season - 1][1]} 23:59:59`,
        ],
      }
      this.$emit('func', result)
    },
  },
}
</script>

<style lang="scss" scoped>
.el-form-item {
  margin-bottom: 0;
  height: 32px;
}
::v-deep .el-form-item__content {
  height: 32px;
  line-height: 32px;
}
.box-card {
  width: 322px;
  padding: 0;
  margin-top: 10px;
  position: absolute;
  z-index: 9999;
}
::v-deep .el-card__header {
  height: 30px;
  padding: 0 0 12px 0;
  box-sizing: content-box;
  margin: 12px 12px 0 12px;
}
::v-deep .el-card__body {
  padding: 10px 0;
}
.el-input {
  width: 220px !important;
  height: 32px;
}
.mark {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0);
  z-index: 999;
}

.year-btn {
  text-align: center;
  padding: 0;
}

.season-list {
  .season-item {
    display: inline-block;
    width: 50%;
    color: #606266;
    text-align: center;
    cursor: pointer;
    &:hover {
      color: #409eff;
    }
    &.is-active {
      color: #409eff;
      border-color: rgba(255, 255, 255, 0); // 隐藏边框
    }
    &.is-disabled {
      // background-color: #F5F7FA;
      color: #C0C4CC;
      cursor: no-drop;
    }
  }
}
</style>


父组件使用案例

            <customQuarterPicker v-show="dateType === 'quarter'" @func="getMsgQuarter" :defaultValue="dateValueQuarter" />
            
		    getMsgQuarter(val) {
		      console.log('val----', val)
		      this.dateValueQuarter = val?.value || ''
		    },
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

#老程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值