季度选择组件和上下半年度选择组件的功能实现

一. 前言

众所周知,前端童靴们在日常开发中,不管是使用 Element 还是Iview 的组件库过程中,遇到季度选择器或者是上下半年度选择器的需求的时候,都会陷入思索---该如何开发呢?因为世面上的大多组件库都未提供季度选择或者是上下半年度选择(PS:Arco Design 倒是提供了季度选择器,可是适配Vue3,不兼容Vue2)。所以本文就以上两种选择器提供一种实现方案附:组件源码),后续也会将它们封装成拿来即用的轮子,方便大家使用。

二. 季度选择器

  • 效果图:

  • 组件源代码:
<template>
  <div>
    <!--背景-点击可关闭卡片-->
    <mark
      class="bgCard"
      v-if="showQuarter"
      @click.stop="showQuarter = false"
    ></mark>
    <span>
      <el-input
        v-model="choseQuarter"
        prefix-icon="el-icon-date"
        :clearable="false"
        placeholder="请选择季度"
        @clear="clearClick"
        @focus="focusClick"
      />
    </span>
    <div v-show="showQuarter" class="show1">
      <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>
        <span
          v-for="(item, index) in fullMonth"
          :key="index"
          :class="[
            'selectMonth',
            choseQuarter.split('-')[1] === item ? 'is-active' : '',
          ]"
          @click="selectQuarter(item)"
          >{
   
   { item }}</span
        >
      </div>
    </div>
  </div>
</template>
 
<script>
export default {
  name: "quarterzj",
  props: {
    searchQuarter: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      showQuarter: false, //显隐该季度组件
      year: new Date().getFullYear(),
      fullMonth: ["第一季度", "第二季度", "第三季度", "第四季度"],
      choseQuarter: new Date().getFullYear().toString() + "-" + "第一季度", //input双向绑定的内容
    };
  },
  watch: {
    //为了展开组件时人性化对上现有年份或者是还原当前年份
    showQuarter(bool) {
      if (bool) {
        if (this.choseQuarter) {
          this.year = this.choseQuarter.split("-")[0];
        } else {
          this.year = new Date().getFullYear().toString();
        }
      }
    },
    //父组件还原检索清空时同步给季度组件
    searchQuarter(val){
      console.log('val',val);
      if(val){
        this.choseQuarter = val;
      }else{
        this.choseQuarter = new Date().getFullYear().toString() + "-" + "第一季度";
      }
    }
  },
  methods: {
    // 点击季度按钮
    quarterTime() {
      this.choseQuarter = "";
      this.fullMonth = ["第一季度", "第二季度", "第三季度", "第四季度"];
    },
    // input框聚焦
    focusClick() {
      this.showQuarter = true;
    },
    // 上一年
    prev() {
      this.year = this.year * 1 - 1;
    },
    // 下一年
    next() {
      this.year = this.year * 1 + 1;
    },
    //清空
    clearClick() {
      this.choseQuarter = "";
      this.showQuarter = false;
      this.$emit("getYearValue", this.choseQuarter);
    },
    // 点击选项事件
    selectQuarter(item) {
      switch (item) {
        case "第一季度":
          this.choseQuarter = this.year + "-" + "第一季度";
          break;
        case "第二季度":
          this.choseQuarter = this.year + "-" + "第二季度";
          break;
        case "第三季度":
          this.choseQuarter = this.year + "-" + "第三季度";
          break;
        case "第四季度":
          this.choseQuarter = this.year + "-" + "第四季度";
          break;
        default:
          this.choseQuarter = "";
      }
      this.showQuarter = false;
      this.$emit("getYearValue", this.choseQuarter);
    },
  },
};
</script>
<style lang="less" scoped>
.bgCard {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0);
  z-index: 999;
}
.show1 {
  width: 320px;
  margin-top: 5px;
  position: absolute;
  z-index: 999;
  height: auto;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  background: #fff;
  padding: 5px;
  font-size: 14px;
  color: #606266;
}
.show1 p:nth-child(1) {
  width: 100%;
  height: 40px;
  border-bottom: 1px solid #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 10px;
}
.show1 > div {
  width: 100%;
  height: auto;
}
.show1 > div span {
  width: 50%;
}
.selectMonth {
  display: inline-block;
  float: left;
  width: 78px;
  height: 40px;
  line-height: 40px;
  text-align: center;
}
.selectMonth:hover {
  background: rgba(19, 131, 255, 0.052);
}
.span-year {
  width: 90%;
  margin: 0 auto;
  display: inline-block;
  text-align: center;
  line-height: 40px;
}
.is-active {
  color: #02bca5 !important;
  border: hidden;
}
</style>
  • 组件引入使用:

 

 

三 .上下半年度选择器

  • 效果图:

  • 组件源代码:
<template>
  <div>
    <!--背景-点击可关闭卡片-->
    <mark
      class="bgCard"
      v-if="showSeason"
      @click.stop="showSeason = false"
    ></mark>
    <el-input
      placeholder="请选择上下半年度"
      v-model="showValue"
      style="width: 200px"
      :clearable="false"
      @clear="clearClick"
      @focus="focusClick"
    >
      <i slot="prefix" class="el-input__icon el-icon-date"></i>
    </el-input>
    <!-- 上下半年选择器卡片 -->
    <el-collapse-transition>
      <el-card class="box-card" v-if="showSeason">
        <!-- 年份选择器 -->
        <div
          slot="header"
          class="clearfix"
          style="text-align: center; padding: 0"
        >
          <button
            type="button"
            aria-label="前一年"
            class="
              el-picker-panel__icon-btn
              el-date-picker__prev-btn
              el-icon-d-arrow-left
            "
            @click="prevSub"
          ></button>
          <span role="button" class="el-date-picker__header-label"
            >{
   
   { year }}年</span
          >
          <button
            type="button"
            aria-label="后一年"
            @click="nextAdd"
            class="
              el-picker-panel__icon-btn
              el-date-picker__next-btn
              el-icon-d-arrow-right
            "
          ></button>
        </div>
        <!-- 上下半年选择器 -->
        <div class="quarter-block">
          <div class="text-item">
            <el-button
              type="text"
              size="medium"
              :class="[
                'common-quarter',
                'quarter-one',
                showValue.split('-')[1] === '上半年' ? 'is-active' : '',
              ]"
              @click="selectQuarter('上半年')"
              >上半年</el-button
            >
            <el-button
              type="text"
              size="medium"
              :class="[
                'common-quarter',
                'quarter-two',
                showValue.split('-')[1] === '下半年' ? 'is-active' : '',
              ]"
              @click="selectQuarter('下半年')"
              >下半年</el-button
            >
          </div>
        </div>
      </el-card>
    </el-collapse-transition>
  </div>
</template>

<script>
export default {
  name: "yearzj",
  props: {
    searchYear: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      showSeason: false, //组件显隐
      year: new Date().getFullYear(), //默认当前年
      showValue: new Date().getFullYear().toString() + "-" + '上半年', //input双向绑定的内容
      rules: {
        showValue: [{ required: true, message: "不能为空", trigger: "change" }],
      },
    };
  },
  watch: {
    //为了展开组件时人性化对上现有年份或者是还原当前年份
    showSeason(bool){
      if(bool){
        if(this.showValue){
          this.year = this.showValue.split('-')[0];
        }else{
          this.year = new Date().getFullYear().toString();
        }
      }
    },
    //父组件还原检索清空时同步给上下半年度组件
    searchYear(val){
      if(val){
        this.showValue = val;
      }else{
        this.showValue = new Date().getFullYear().toString() + "-" + '上半年';
      }
    }
  },
  methods: {
    // 上一年
    prevSub() {
      this.year = this.year * 1 - 1;
    },
    // 下一年
    nextAdd() {
      this.year = this.year * 1 + 1;
    },
    // 上下半年选择
    selectQuarter(quarter) {
      this.showValue = `${this.year}-${quarter}`;
      this.$emit("getQuarterValue", this.showValue);
      this.showSeason = false;
    },
    // 清除
    clearClick() {
      this.showValue = "";
      this.$emit("getQuarterValue", this.showValue);
      this.showSeason = false;
    },
    // 聚焦触发,若是年已存在,则不需要重新赋值
    focusClick() {
      if (!this.year) {
        this.year = new Date().getFullYear().toString();
      }
      this.showSeason = true;
    },
  },
  created() {
    this.showValue = this.searchYear;
  },
};
</script>

<style lang="less" scoped>
.bgCard {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0);
  z-index: 999;
}
.box-card {
  width: 220px;
  padding: 0 3px 0px;
  margin-top: 10px;

  position: fixed;
  z-index: 9999;
}
.common-quarter {
  width: 40%;
  color: #606266;
}
.quarter-one,
.quarter-three {
  float: left;
}
.quarter-two,
.quarter-four {
  float: right;
}
.text-item {
  text-align: center;
}
.quarter-block {
  display: flex;
  flex-direction: column;
}
.is-active {
  color: #02bca5 !important;
  border: hidden;
}
</style>
  • 组件引入使用:

 

 

 

猜你喜欢

转载自blog.csdn.net/Yi2008yi/article/details/125792101