美文网首页
vuejs项目,el-date-picker封装一个选择季度范围

vuejs项目,el-date-picker封装一个选择季度范围

作者: 蓦然回味 | 来源:发表于2024-04-01 10:54 被阅读0次

    1、创建一个quarter-rang-picker.vue组件,并引入封装好的quarter-picker.vue(见2)。

    <template>
      <div class="quarter-range-picker">
        <!-- 透明遮罩 -->
        <div class="mark" v-if="show_quarter_range_picker" @click.stop="handleClosePicker"></div>
    
        <!-- 结果显示框 -->
        <el-date-picker :value="showValue" popper-class="quarter-range-picker-date-popper" type="monthrange"
          format="yyyy-QM" class="mo-date-picker" range-separator="至" @focus="handleOpenPicker" size="mini"
          @change="handleChange" start-placeholder="开始季度" end-placeholder="结束季度">
        </el-date-picker>
    
        <!-- 弹出选框 -->
        <el-collapse-transition>
          <el-card class="quarter-range-picker__box-card" v-show="show_quarter_range_picker">
            <div class="quarter-range-picker__content">
              <QuarterPicker :year.sync="start_year" :quarter="start_quarter" :showRight="start_show_right"
                @on-quarter-click="handleStartQuarterClick" @on-year-change="handleStartYearChange"></QuarterPicker>
              <QuarterPicker :year.sync="end_year" :showLeft="end_show_left" :quarter.sync="end_quarter"
                @on-quarter-click="handleEndQuarterClick" @on-year-change="handleEndYearChange"></QuarterPicker>
            </div>
          </el-card>
        </el-collapse-transition>
      </div>
    </template>
    <script>
      /**
       * 季节选择组件
       */
      import QuarterPicker from './quarter-picker.vue'
      import dayjs from 'dayjs'
      import { getQuarterOptionMonths } from './config.js'
    
      export default {
        name: 'mo-quarter-range-picker',
    
        components: {
          QuarterPicker
        },
    
        props: {
          // [起始日期,结束日期]
          value: {
            type: Array,
            default: null,
          },
        },
    
        data() {
          let now = dayjs()
    
          return {
    
            show_quarter_range_picker: false,
    
            // 开始
            start_year: now.year(),
            start_quarter: [],
            // 结束
            end_year: now.year() + 1,
            end_quarter: [],
    
            // 整合后的月份 {year, quarter}
            quarter: []
          }
        },
    
        computed: {
          start_show_right() {
            return this.start_year < this.end_year - 1
          },
    
          end_show_left() {
            return this.end_year > this.start_year + 1
          },
    
          showValue() {
            if (this.value.length) {
              console.log(this.value)
              let start_date = dayjs(this.value[0])
              let end_date = dayjs(this.value[1])
    
              return [`${start_date.year()}-${start_date.quarter()}`, `${end_date.year()}-${end_date.quarter()}`]
            } else {
              return null
            }
          },
        },
    
        created() {
    
        },
    
        methods: {
          handleOpenPicker() {
            let start_date = dayjs()
            let end_date = dayjs().add(1, 'years')
            if (this.value) {
              start_date = dayjs(this.value[0])
              end_date = dayjs(this.value[1])
              this.start_quarter = [`${start_date.year()}-${start_date.quarter()}`, `${end_date.year()}-${end_date.quarter()}`]
              this.end_quarter = [`${start_date.year()}-${start_date.quarter()}`, `${end_date.year()}-${end_date.quarter()}`]
            }
    
            this.start_year = start_date.year()
            // 结束
            this.end_year = end_date.year()
            if (this.start_year >= this.end_year) {
              this.end_year = this.start_year + 1
            }
    
            // 清空已选中
            this.quarter.splice(0, this.quarter.length)
    
            this.show_quarter_range_picker = true
          },
    
          handleClosePicker() {
            this.show_quarter_range_picker = false
          },
    
          handleStartYearChange(year) {
            this.start_year = year
          },
    
          handleStartQuarterClick(quarter_item) {
            if (this.quarter.length == 0) {
              this.start_quarter.splice(0, this.start_quarter.length)
              this.end_quarter.splice(0, this.end_quarter.length)
            }
    
            let index = this.start_quarter.indexOf(quarter_item.value)
            if (index > -1) {
              this.start_quarter.splice(index, 1)
            } else {
              this.start_quarter.push(quarter_item.value)
            }
    
            this.quarter.push(quarter_item)
    
            this.handleCheckQuarterRange()
          },
    
          handleEndQuarterClick(quarter_item) {
            if (this.quarter.length == 0) {
              this.start_quarter.splice(0, this.start_quarter.length)
              this.end_quarter.splice(0, this.end_quarter.length)
            }
    
            let index = this.end_quarter.indexOf(quarter_item.value)
    
            if (index > -1) {
              this.end_quarter.splice(index, 1)
            } else {
              this.end_quarter.push(quarter_item.value)
            }
    
            this.quarter.push(quarter_item)
            console.log(this.quarter)
    
            this.handleCheckQuarterRange()
          },
    
          handleCheckQuarterRange() {
            console.log('quarter', this.quarter);
    
            if (this.quarter.length == 2) {
              // 排序
              this.quarter.sort((a, b) => {
                if (a.year == b.year) {
                  return a.quarter - b.quarter
                } else {
                  return a.year - b.year
                }
              })
    
              let result = []
              for (let item of this.quarter) {
                // 开始日期
                // let start_quarter = this.quarter[0];
                let months = getQuarterOptionMonths(item.quarter)
                let start_quarter_month = months[0]
                let end_quarter_month = months[months.length - 1]
    
                // 月份从 0 开始索引
                let start_date = dayjs(`${item.year}-${start_quarter_month}`).startOf('month').format('YYYY-MM-DD')
                let end_date = dayjs(`${item.year}-${end_quarter_month}`).endOf('month').format('YYYY-MM-DD')
    
                result.push({
                  ...item,
                  start_date,
                  end_date
                })
              }
              // console.log('result', [result[0].start_date, result[1].end_date]);
    
              this.$emit('update:value', [result[0].start_date, result[1].end_date])
              this.$emit('on-change', result)
    
              this.show_quarter_range_picker = false
            }
          },
    
          handleEndYearChange() {
            // this.end_quarter.splice(0, this.start_quarter.length);
          },
    
          handleChange(val) {
            // console.log('handleClear', val)
            // 清空操作
            if (!val) {
              this.start_quarter.splice(0, this.start_quarter.length)
              this.end_quarter.splice(0, this.end_quarter.length)
    
              this.$emit('update:value', [])
            }
          },
        },
      }
    </script>
    
    <style lang="scss">
      .mark {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        background: rgba(0, 0, 0, 0);
        z-index: 999;
      }
    
      .quarter-range-picker {
        display: inline-block;
        /* position: relative; */
    
        .el-card__body {
          padding: 0;
        }
    
        .quarter-range-picke__value {
          position: absolute;
          left: 0;
          right: 0;
          width: 100%;
          height: 100%;
        }
    
        .el-range-editor--mini.el-input__inner {
          width: 240px;
        }
      }
    
      .quarter-range-picker__box-card {
        // width: 500px;
        // padding: 0 3px 20px;
        margin-top: 10px;
        position: absolute;
        z-index: 9999;
        /* left: 0; */
      }
    
      .quarter-range-picker__content {
        display: flex;
        justify-content: space-between;
      }
    
      // 隐藏原有的选择器
      .quarter-range-picker-date-popper {
        display: none;
      }
    </style>
    

    2、再创建一个quarter-picker.vue组件,此组件

    <template>
      <div class="quarter-picker">
        <div class="quarter-picker-inner">
          <div class="quarter-picker__header">
            <!-- 左边按钮 -->
            <i class="el-icon-d-arrow-left" @click="handlePrevYear" v-if="showLeft"></i>
            <span v-else class="empty-arrow"></span>
    
            <div class="quarter-picker__title">{{ year }}</div>
    
            <!-- 右边按钮 -->
            <i class="el-icon-d-arrow-right" @click="handleNextYear" v-if="showRight"></i>
            <span v-else class="empty-arrow"></span>
          </div>
    
          <div class="quarter-picker__options">
            <template v-for="item in options">
              <div class="quarter-picker__item" v-bind:key="item.value" :data-value="item.value"
                @click="handleItemClick(item)" :class="{
                   'quarter-picker__item__today': item.value == now_quarter,
                   'quarter-picker__item--active': quarter.includes(item.value),
                 }">
                <div class="quarter-picker__item__label">{{ item.label }}</div>
              </div>
            </template>
          </div>
        </div>
      </div>
    </template>
    
    <script>
      import dayjs from 'dayjs'
      import { quarter_options } from './config.js'
      var quarterOfYear = require('dayjs/plugin/quarterOfYear')
      dayjs.extend(quarterOfYear)
    
      export default {
        name: 'quarter-picker',
    
        props: {
          // 当前年
          year: {
            type: Number,
            default: () => {
              return dayjs().year()
            }
          },
    
          // 当前季度 ['2022-1']
          quarter: {
            type: Array,
            default: () => {
              return []
            }
          },
    
          // 当前日期
          // value: {
          //   type: Array,
          //   default: () => { return [] },
          // },
    
          // 显示左边按钮
          showLeft: {
            type: Boolean,
            default: true
          },
          // 显示右边按钮
          showRight: {
            type: Boolean,
            default: true
          }
        },
    
        components: {},
    
        data() {
          let now = dayjs()
          let now_year = now.year()
          let now_quarter = `${now_year}-${now.quarter()}`
    
          return {
            now_year,
            now_quarter
    
          }
        },
    
        computed: {
          options() {
            return quarter_options.map((item) => {
              return {
                label: item.label,
                value: `${this.year}-${item.value}`,
                year: this.year,
                quarter: item.value
              }
            })
          }
        },
    
        methods: {
          async getData() { },
    
          handleItemClick(item) {
            this.$emit('on-quarter-click', item)
          },
    
          handlePrevYear() {
            let year = this.year - 1
            this.$emit('update:year', year)
            this.$emit('on-year-change', year)
          },
    
          handleNextYear() {
            let year = this.year + 1
            this.$emit('update:year', year)
            this.$emit('on-year-change', year)
          }
        },
    
        created() {
          this.getData()
          console.log(this.quarter)
        }
      }
    </script>
    
    <style lang="scss">
      .quarter-picker {
        border-right: 1px solid #e5e6eb;
      }
    
      .quarter-picker-inner {
        padding: 8px 16px;
      }
    
      .quarter-picker__header {
        display: flex;
        justify-content: space-between;
        font-size: 12px;
    
        // padding: 8px 16px;
        border-bottom: 1px solid #e5e6eb;
    
        .el-icon-d-arrow-left,
        .el-icon-d-arrow-right,
        .empty-arrow {
          cursor: pointer;
          width: 24px;
          height: 24px;
          font-size: 12px;
          line-height: 24px;
          text-align: center;
          border-radius: 50%;
          transition: all 0.1s cubic-bezier(0, 0, 1, 1);
          user-select: none;
    
          &:hover {
            background-color: #e5e6eb;
          }
        }
    
        .empty-arrow {
          cursor: auto;
    
          &:hover {
            background-color: transparent;
          }
        }
    
        .quarter-picker__title {
          flex: 1;
          color: #1d2129;
          font-size: 14px;
          line-height: 24px;
          text-align: center;
        }
      }
    
      .quarter-picker__options {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        padding: 14px 16px;
      }
    
      .quarter-picker__item {
        padding: 4px;
        cursor: pointer;
        position: relative;
      }
    
      .quarter-picker__item__label {
        border-radius: 24px;
        color: #000;
        background-color: #fff;
        // font-weight: 500;
        height: 24px;
        font-size: 14px;
        line-height: 24px;
        text-align: center;
        width: 50px;
      }
    
      .quarter-picker__item--active .quarter-picker__item__label,
      .quarter-picker__item:hover .quarter-picker__item__label {
        background-color: #FF0035;
        color: #fff;
      }
    
      .quarter-picker__item__today:after {
        position: absolute;
        bottom: -2px;
        left: 50%;
        display: block;
        width: 4px;
        height: 4px;
        margin-left: -2px;
        background-color: #FF0035;
        border-radius: 50%;
        content: '';
      }
    </style>
    

    3、创建config.js文件,里面包含,季度选项,以Q代表季度,一年有四个季度,分别为Q1/Q2/Q3/Q4,名称可自定。

    // 季节对应筛选项
    export const quarter_options = [
      {
        label: 'Q1',
        value: 1,
        months: [1, 2, 3]
      },
      {
        label: 'Q2',
        value: 2,
        months: [4, 5, 6]
      },
      {
        label: 'Q3',
        value: 3,
        months: [7, 8, 9]
      },
      {
        label: 'Q4',
        value: 4,
        months: [10, 11, 12]
      }
    ]
    
    /**
     * 获取季度对应的月份
     * @returns
     */
    export function getQuarterOptionMonths (value) {
      for (let item of quarter_options) {
        if (item.value == value) {
          return item.months
        }
      }
    }
    
    /**
     * 获取日期对应季度
     * @returns
     */
    export function getQuarterItemOfMonth (month) {
      for (let item of quarter_options) {
        if (item.months.includes(month)) {
          return item
        }
      }
    }
    
    

    4、最后在index.vue中引入quarter-range-picker.vue(见1)

    <template>
      <div>
         <!-- 季度选择器 -->
         <quarterPicker  :value.sync="quarterData" @on-change="handleChange"></quarterPicker>
      </div>
    </template>
    <script>
    export default({
      data () {
        return {
           quarterData: [],
        }
      },
      methods:{
        // 季度选择
        handleChange (value) {
          this.removeData()
          // console.log('this.quarterData', this.quarterData)
          // console.log('value', value)
        },
      }
    });
    </script>
    

    相关文章

      网友评论

          本文标题:vuejs项目,el-date-picker封装一个选择季度范围

          本文链接:https://www.haomeiwen.com/subject/sgzugdtx.html