H5移动端月历区间选择开始月份和结束月份

在做h5移动端app时,因业务需要,要做按日区间选择开始和结束日期,按月区间选择开始和结束月份,ui组件中有按日区间选择的,没有按月区间选择,所以结合业务自己写了一个。

<template>
  <van-action-sheet
    v-model="showDate"
    position="bottom"
    @close="closeCalendar"
    title="选择月份"
    round
    :style="{ height: '80%' }"
    ref="monthDate"
  >
    <ul class="content">
      <li v-for="(item, index) in years" :key="index" v-scroll>
        <div class="monthTitle">{{ item.year }}年</div>
        <van-row>
          <van-col
            span="6"
            v-for="(childItem, key) in item.children"
            :key="key"
            :class="childItem.monthClass"
          >
            <div
              class="monthList"
              @click="selectList(item, childItem)"
              :class="childItem.isSelect === true ? 'isSelect' : ''"
            >
              <div :class="childItem.disabledMonth == true ? 'isDisabled' : ''">
                {{ childItem.month }}月
              </div>
              <div
                class="startEnd"
                :class="
                  childItem.text == '开始' || childItem.text == '结束'
                    ? 'fontSize'
                    : ''
                "
              >
                {{ childItem.text }}
              </div>
            </div>
          </van-col>
        </van-row>
      </li>
    </ul>
    <div class="footBtn" default="footer">
      <div class="footBox">
        <van-button @click="onReset" type="primary">重 置</van-button>
        <van-button @click="onConfirm" type="primary">确 定</van-button>
      </div>
    </div>
  </van-action-sheet>
</template>

<script>
import { Toast } from "vant";
export default {
  props: {
    isAllowSameDay: {
      type: Boolean,
    },
    calendarshow: {
      type: Boolean,
    },
    yearLength: {
      type: Number,
    },
    defaultDate: {
      type: Array,
      required: true,
    },
  },
  data () {
    return {
      years: [],
      monthList: [
        "一",
        "二",
        "三",
        "四",
        "五",
        "六",
        "七",
        "八",
        "九",
        "十",
        "十一",
        "十二",
      ],
      showDate: this.calendarshow,
      selectArr: [],
      currentYear: new Date().getFullYear(), //当前年份
      currentMonth: new Date().getMonth() + 1, //当前月份
      startDefaultYear: new Date().getFullYear(), //开始年份
      startDefaultMonth: new Date().getMonth() + 1, //开始月份
      endDefaultYear: new Date().getFullYear(), //结束年份
      endDefaultMonth: new Date().getMonth() + 1, //结束月份
      startText: "开始",
      endText: "结束",
      startEndText: "开始/结束"
    };
  },
  directives: {
    // 自定义指令 月历定位到当前年份
    scroll: {
      inserted (el) {
        el.scrollIntoView();
      },
    },
  },
  watch: {
    calendarshow (val) {
      this.showDate = val; //显示隐藏月历
    },
    defaultDate (val) {
      this.startDefaultYear = val[0].getFullYear(); //开始年份
      this.startDefaultMonth = val[0].getMonth() + 1; //开始月份
      this.endDefaultYear = val[1].getFullYear(); //结束年份
      this.endDefaultMonth = val[1].getMonth() + 1; //结束月份
      this.setDefaultMonth();
    },
  },
  created () {
    this.initCalendar()
  },
  methods: {
    // 初始化月历
    initCalendar () {
      const that = this;
      for (let i = 1; i <= that.yearLength; i++) {
        const item = {
          year: that.currentYear - (that.yearLength - i),
          children: [],
        };
        for (let j = 0; j < that.monthList.length; j++) {
          let list = {
            month: that.monthList[j],
            isSelect: false,
            value: j + 1,
            text: "",
          };
          // 判断当前月之后的月份不可选
          if ((item.year == that.currentYear && j + 1 > that.currentMonth) || (item.year == that.currentYear - (that.yearLength - 1) && j + 1 < that.currentMonth)) {
            list.disabledMonth = true;
          } else {
            list.disabledMonth = false;
          }
          item.children.push(list);
        }
        that.years.push(item);
      }
    },
    // 设置默认值
    setDefaultMonth () {
      const that = this;
      const startYear = that.startDefaultYear; //默认开始年份
      const endYear = that.endDefaultYear; //默认结束年份
      const startMonth = that.startDefaultMonth;  //默认开始的年份
      const endMonth = that.endDefaultMonth;  //默认开始的年份
      that.selectArr = [];
      that.years.map((item) => {
        item.children.map((list) => {
          list.text = "";
          list.isSelect = false;
          // 当前起始年份、月份都相同
          if (startYear == endYear && startMonth == endMonth) {
            list.monthClass = "";
            if (item.year == startYear && list.value == startMonth) {
              list.text = that.startEndText;
              list.isSelect = true;
              that.monthSaveArr(startYear, startMonth, list.text);
            }
          } else {
            // 起始年份相同、月份不同
            if (item.year == startYear && list.value == startMonth) {
              list.text = that.startText;
              list.isSelect = true;
              that.monthSaveArr(item.year, list.value, list.text);
            }
            if (item.year == endYear && list.value == endMonth) {
              list.text = that.endText;
              list.isSelect = true;
              that.monthSaveArr(item.year, list.value, list.text);
            }
          }
        });
      });
    },
    // 选择的月份存入一个数组中
    monthSaveArr (year, month, text) {
      const dataItem = {
        year: year,
        month: month,
        text: text
      };
      this.selectArr.push(dataItem);
    },
    // 选择月份
    selectList (item, childItem) {
      const that = this;
      const selectStartYear = that.selectArr[0].year; //选择开始的年份
      const selectStartMonth = that.selectArr[0].month;//选择开始的月份
      // 大于当前月份不可选
      if (childItem.disabledMonth == true) {
        return;
      }
      // 开始月份  (如果数组为空 或者 已经选了开始结束月份为同一月) 选择开始月份
      if (that.selectArr.length == 0 || that.selectArr[0].text == that.startEndText) {
        that.cancelSelectMonth();
        childItem.text = that.startText;
        that.monthSaveArr(item.year, childItem.value, childItem.text);
      } else if (that.selectArr.length == 1) {
        if (item.year == selectStartYear && childItem.value == selectStartMonth) {
          // 开始、结束月份是否可选同一天
          if (that.isAllowSameDay == true) {
            childItem.isSelect = true;
            childItem.text = that.startEndText;
            that.monthSaveArr(item.year, childItem.value, childItem.text);
            return;
          } else {
            childItem.isSelect = true;
            childItem.text = that.startText;
            return;
          }
        }
        // 选择的月份不能超过12个月
        if ((item.year > this.selectArr[0].year && childItem.value >= this.selectArr[0].month) || (item.year - this.selectArr[0].year > 1)) {
          Toast("结束月份不能超过12个月");
          return;
        }
        if ((item.year == selectStartYear && childItem.value < selectStartMonth) || item.year < selectStartYear) {
          that.cancelSelectMonth();
          childItem.text = that.startText;
          that.monthSaveArr(item.year, childItem.value, childItem.text);
        } else {
          // 结束月份
          childItem.text = that.endText;
          that.monthSaveArr(item.year, childItem.value, childItem.text);
          that.setAreaBackground();
        }
      } else if (that.selectArr.length == 2) {
        that.cancelSelectMonth();
        childItem.text = that.startText;
        that.monthSaveArr(item.year, childItem.value, childItem.text);
      }
      childItem.isSelect = !childItem.isSelect;
    },
    // 取消已选中的月份
    cancelSelectMonth () {
      this.selectArr = [];
      this.years.map((item) => {
        item.children.map((ev) => {
          ev.text = "";
          ev.isSelect = false;
          ev.monthClass = "";
        });
      });
    },
    // 添加开始、结束区间的背景颜色
    setAreaBackground () {
      const startYear = this.selectArr[0].year; //开始年份
      const endYear = this.selectArr[1].year;   //结束年份
      const startMonth = this.selectArr[0].month; //开始年份
      const endMonth = this.selectArr[1].month;   //结束年份
      this.years.map((item) => {
        // 起始年份相同
        if (item.year == startYear && item.year == endYear) {
          item.children.map((ev) => {
            if (endMonth - startMonth >= 1) {
              if (ev.value == startMonth) {
                ev.monthClass = "calendarStartColor";
              } else if (ev.value == endMonth) {
                ev.monthClass = "calendarEndColor";
              } else if (ev.value > startMonth && ev.value < endMonth) {
                ev.monthClass = "calendarMiddleColor";
              }
            }
          })
        } else if (endYear > startYear) {
          // 开始年份小于结束年份
          if (item.year == startYear) {
            // 起始月份
            item.children.map((ev) => {
              if (ev.value == startMonth) {
                ev.monthClass = "calendarStartColor";
              } else if (ev.value > startMonth) {
                ev.monthClass = "calendarMiddleColor";
              }
            })
          } else if (item.year == endYear) {
            // 结束月份
            item.children.map((ev) => {
              if (ev.value == endMonth) {
                ev.monthClass = "calendarEndColor";
              } else if (ev.value < endMonth) {
                ev.monthClass = "calendarMiddleColor";
              }
            })
          } else if (item.year > startYear && item.year < endYear) {
            // 开始月份与结束月份区间的加背景色
            item.children.map((ev) => {
              ev.monthClass = "calendarMiddleColor";
            })
          }
        }
      });
    },
    // 确认
    onConfirm () {
      this.$emit("confirmMonth", this.selectArr);
    },
    // 重置日期
    onReset () {
      this.$emit("resetCalendar");
    },
    // 关闭
    closeCalendar () {
      this.$emit("closeCalendar");
    }
  }
};
</script>

<style lang="stylus" scoped>
/deep/.van-action-sheet__close {
  right: auto;
  left: 0px;
}
/deep/.van-action-sheet__header{
  font-size: 1rem;
  font-family: PingFang SC;
  font-weight: bold;
  color: #333333;
}
.content {
  font-family: PingFang SC;
  padding-bottom: 84px;

  /deep/.van-row {
    padding: 1.11rem 0 0 0;
  }

  /deep/.van-col--6 {
    margin-bottom: 1.11rem;
    position: relative;
  }
  .calendarStartColor{
    background-image: linear-gradient(to right, #fff , #e6f5fc);
  }
   .calendarEndColor{
    background-image: linear-gradient(to left,#fff , #e6f5fc);
  }
  .calendarMiddleColor {
    background-color: #e6f5fc;
  }

  .monthTitle {
    background: #E5E5E5;
    font-size: 0.83rem;
    font-weight: bold;
    color: #333333;
    padding: 0.61rem 0;
  }

  .monthList {
    width: 3rem;
    height: 2.22rem;
    display: flex;
    flex-flow: column;
    color: #333333;
    justify-items: center;
    align-items: center;
    border-radius: 0.56rem;
    margin: 0 auto;
    padding: 0 0.22rem 0.22rem 0.22rem;

    div:first-child {
      height: 0.81rem;
      line-height: 0.81rem;
      padding: 0.44rem 0 0.22rem 0;
      font-size: 0.89rem;
      font-weight: 500;
    }

    .startEnd {
      height: 0.61rem;
      line-height: 0.61rem;
      font-size: 0.53rem;
      font-weight: 500;
      color: #FFFEFE;
    }

    .fontSize {
      font-size: 0.61rem;
    }

    div {
      display: flex;
      flex-flow: row;
    }
  }

  .isDisabled {
    color: #ccc;
  }

  .isSelect {
    background: #0097E0;
    color: #fff;
  }
}

.footBtn {
  position: fixed;
  bottom: 0;
  width: 100%;
  padding: 0.66rem 0 1.53rem 0;
  display: flex;
  background: #fff;

  .footBox {
    padding: 0 16px;
    display: flex;
    flex-flow: row;
    width: 100%;
  }

  .van-button {
    border-radius: 2rem;
    height: 2.5rem;
    line-height: 2.5rem;
    flex: 1;
    margin: 0 1rem;
    font-size: 1rem;
  }

  .van-button:nth-child(1) {
    width: 80%;
    color: #000;
    font-size: 14px;
    background: white;
    border: 2px solid #666 !important;
    border-radius: 40px;
    margin: 0 1rem;
  }

  .van-button:nth-child(2) {
    width: 80%;
    color: #fff;
    font-size: 14px;
    background: white;
    border-radius: 40px;
    margin: 0 1rem;
    border: none;
    background: -webkit-gradient(linear, right top, left top, from(#0068b7), to(#0097e0));
    background: linear-gradient(-90deg, #0068b7, #0097e0);
  }
}
</style>

组件引用

<month-filter :defaultDate="monthDate.monthDefaultDate" :calendarshow="monthDate.monthCalendarShow" :isAllowSameDay="monthDate.isAllowSameDay" :yearLength="monthDate.yearLength" @closeCalendar="monthDate.monthCalendarShow = false" @confirmMonth="selectMonth" @resetCalendar="resetMonthCalendar">
</month-filter>


monthDate:{
   monthCalendarShow:false,
   yearLength:10,
   monthDefaultDate:[
    new Date(), new Date() //设置区间  
    ],
   isAllowSameDay:true     // 可选同一个月份
},

// 选择月份区间
selectMonth(data) {
  if(data.length ==2 ){
     // 这里是获取的开始和结束的值
  }else if(data.length==1){
      if(data[0].text !="开始/结束"){
        Toast("请选择正确的月份区间");
        return;
      }else{
       // 这里是开始和结束的月份相同
      }
  }
  this.monthDate.monthCalendarShow = false;
},

resetMonthCalendar(){ //重置月份}

 按月区间选择组件还可优化,欢迎大家给出意见,谢谢!

效果图如下:

开始月份到结束月份

 开始结束月份可选当月:

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

新时代超

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

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

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

打赏作者

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

抵扣说明:

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

余额充值