日历单击选则不同日期,也可范围选择日期

这是我再一个博主的基础上改的

详情请看:https://blog.csdn.net/weixin_41277748/article/details/122847305

 我是单独写了一个组件!

<template>
  <div class="w-calender-container">
    <div class="select_date">选择日期</div>
    <div class="w-top">
      
      <div class="w-top-date">
        <div @click="handleShowLastMonth">
          <i class="el-icon-arrow-left"></i>
        </div>
        <div style="margin: 0 15px">
          {{ year }}年{{ `${month > 9 ? month : "0" + month}` }}月
        </div>
        <div @click="handleShowNextMonth">
          <i class="el-icon-arrow-right"></i>
        </div>
      </div>
     
    </div>
    <div class="w-date_wrap">
      <ul class="w-week">
        <li>日</li>
        <li>一</li>
        <li>二</li>
        <li>三</li>
        <li>四</li>
        <li>五</li>
        <li>六</li>
      </ul>
      <ul class="w-day">
        <li
          v-for="(item, index) in days"
          :class="{
            'c-isCurMonth': item.isNextMonth || item.isLastMonth,
            'c-isCurToday': item.isCurToday,
            'c-isActive': item.isActive,
            'c-is-previous-date': item.isPreviousDate,
          }"
          :key="index"
          @click="handleChooseDay(item)"
        >
          <span>
            {{ item.day }}
          </span>
          <span v-if="item.isShowPoint" class="w-point"></span>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
// import { getCurDay } from "@/util/MyTools";

export default {
  name: "calender",
  props: {
    //是否是多选
    isMultipleChoice: {
      type: Boolean,
      default: true,
    },
    //是否显示清除按钮
    isShowClear: {
      type: Boolean,
      default: true,
    },
    //选择的月份
    Month: {
      type: String,
    },
    //需要加圆点的数据
    //数据格式为map { new Date(2022-02-11).getTime():true}: 用年月日的时间戳为key
    pointMap: {
      type: Object,
      default: () => {
        return {};
      },
    },
    //是否禁止选择以前的日期 默认为空表示没有限制 注:如果只有数字则 默认时间是当天时间
    //{1:['2022-02-11']}表示2022-02-11以前的日期不能选择;1:表示小于该时间的禁止选择,必填
    //{2:['2022-02-11']}表示2022-02-11以后的日期不能选择;2:表示大于该时间的禁止选择,必填
    //{3:['2022-02-11','2022-03-11']}表示2022-02-11到2022-03-11之间的日期可以选择;3:表示两个时间内的时间可以选择,必填
    //{4:['2022-02-11','2022-03-11']}表示2022-02-11到2022-03-11之外的日期可以选择;4:表示两个时间之外的可以选择,必填
    restrictDate: {
      type: Object,
      default: () => {
        return null;
      },
    },
  },
  watch: {
    Month: {
      handler(val) {
        if (val) {
          const date = val.split("-").map(Number);
          this.year = date[0];
          this.month = date[1];
          this.days = [];
          //选择月份后重新跟更新时间
          this.dealDate();
        }
      },
      immediate: true,
    },
    pointMap: {
      handler(val) {
        if (val) {
          this.dealDate();
        }
      },
      immediate: true,
    },
  },
  data() {
    return {
      year: "", //年
      month: "", //月
      days: [], //日期
      //是否已经选择了开始时间
      isChooseOne: false,
      endTime: null,
      startTime: null,
      monthValue: "", //选择的月份
      chooseDateList: {}, //如果是单选 则把选择的保存
    };
  },
  methods: {
    //得到当前年这个月分有多少天
    getDays(Y, M) {
      return new Date(Y, M, 0).getDate();
    },
    //得到当前年,这个月的一号是周几
    getWeek(Y, M) {
      let now = new Date();
      now.setFullYear(this.year);
      now.setMonth(this.month - 1);
      now.setDate(1);
      return now.getDay();
    },
    /**
     * 获取本月日期
     */
    pushDays() {
      //将这个月多少天加入数组days
      const m = `${this.month > 9 ? this.month : "0" + this.month}`;
      for (let i = 1; i <= this.getDays(this.year, this.month); i++) {
        const d = `${i > 9 ? i : "0" + i}`,
          date = `${this.year}-${m}-${d}`;
        this.days.push({
          day: d,
          isActive: false,
          month: m,
          year: `${this.year}`,
          date,
          timestamp: new Date(date).getTime(), //转换时间戳
        });
      }
      //获取上个月的日期
      this.getLastMonthDays();
      //获取下个月的日期
      this.getNextMonthDays();
    },
    /**
     * 获取下个月的日期
     */
    getNextMonthDays() {
      const m = this.month < 12 ? this.month + 1 : 1,
        y = this.month < 12 ? this.year : this.year + 1,
        len =
          42 -
          this.getDays(this.year, this.month) -
          this.getWeek(this.year, this.month),
        _m = `${m > 9 ? m : "0" + m}`;
      //将下个月要显示的天数加入days
      for (let i = 1; i <= len; i++) {
        const _d = `${i > 9 ? i : "0" + i}`,
          date = `${y}-${_m}-${_d}`;
        this.days.push({
          day: _d,
          month: _m,
          year: `${y}`,
          isActive: false,
          isNextMonth: true,
          date,
          timestamp: new Date(date).getTime(),
        });
      }
    },
    /**
     * 获取上个月的日期
     */
    getLastMonthDays() {
      const m = this.month > 1 ? this.month - 1 : this.year > 1970 ? 12 : 1,
        y =
          this.month > 1 ? this.year : this.year > 1970 ? this.year - 1 : 1970,
        len = this.getWeek(this.year, this.month),
        lastMonthDays = this.getDays(this.year, this.month - 1);
      //将上个月要显示的天数加入days
      for (let i = 0; i < len; i++) {
        const _m = `${m > 9 ? m : "0" + m}`,
          date = `${y}-${_m}-${lastMonthDays - i}`;
        this.days.unshift({
          day: `${lastMonthDays - i}`,
          month: _m,
          year: `${y}`,
          isActive: false,
          isLastMonth: true,
          date,
          timestamp: new Date(date).getTime(),
        });
      }
    },
    /**
     * 上个月
     */
    handleShowLastMonth() {
      if (this.month > 1) {
        this.month = this.month - 1;
      } else if (this.year > 1970) {
        this.month = 12;
        this.year = this.year - 1;
      }
      this.dealDate();
    },
    /**
     * 下个月
     */
    handleShowNextMonth() {
      this.days = [];
      if (this.month < 12) {
        this.month = this.month + 1;
      } else {
        this.month = this.month = 1;
        this.year = this.year + 1;
      }
      this.dealDate();
    },
    /**
     * 当天
     */
    handleShowToday() {
      let now = new Date();
      this.year = now.getFullYear();
      this.month = now.getMonth() + 1;
      this.dealDate();
    },
    // 获取当天日期
    getCurDay() {
      var datetime = new Date();
      var year = datetime.getFullYear();
      var month =
        datetime.getMonth() + 1 < 10
          ? "0" + (datetime.getMonth() + 1)
          : datetime.getMonth() + 1;
      var date =
        datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
      return `${year}-${month}-${date}`;
    },
    /**
     * 处理时间
     */
    dealDate() {
      this.days = [];
      console.log(44);
      console.log(5555, this.getCurDay());
      const curDate = this.getCurDay();
      this.pushDays();
      // 判断 是否需要禁止选择某些时间段的时间
      if (this.restrictDate) {
        const keys = Object.keys(this.restrictDate);
        let day, timestamp;
        switch (keys[0]) {
          case "1":
            day =
              (this.restrictDate[keys[0]] && this.restrictDate[keys[0]]) ||
              curDate;
            timestamp = new Date(day).getTime(); //转换时间戳
            this.days.forEach((item) => {
              item.isCurToday = item.date === curDate;
              item.isPreviousDate = item.timestamp < timestamp;
            });
            break;
          case "2":
            day =
              (this.restrictDate[keys[0]] && this.restrictDate[keys[0]]) ||
              curDate;
            timestamp = new Date(day).getTime(); //转换时间戳
            this.days.forEach((item) => {
              item.isCurToday = item.date === curDate;
              item.isPreviousDate = item.timestamp > timestamp;
            });
            break;
          case "3":
            const s_d =
              (this.restrictDate[keys[0]] && this.restrictDate[keys[0]][1]) ||
              curDate;
            const e_d =
              (this.restrictDate[keys[0]] && this.restrictDate[keys[0]][2]) ||
              curDate;
            let s = new Date(s_d).getTime(),
              e = new Date(e_d).getTime();
            if (s > e) {
              [s, e] = [e, s];
            }
            this.days.forEach((item) => {
              item.isCurToday = item.date === curDate;
              item.isPreviousDate = item.timestamp > s && item.timestamp < e;
            });
            break;
          case "4":
            const st_d =
              (this.restrictDate[keys[0]] && this.restrictDate[keys[0]][1]) ||
              curDate;
            const en_d =
              (this.restrictDate[keys[0]] && this.restrictDate[keys[0]][2]) ||
              curDate;
            let st = new Date(st_d).getTime(),
              en = new Date(en_d).getTime();
            if (st > en) {
              [st, en] = [en, st];
            }
            this.days.forEach((item) => {
              item.isCurToday = item.date === curDate;
              item.isPreviousDate = item.timestamp < st || item.timestamp > en;
            });
            break;
          default:
            this.days.forEach((item) => {
              item.isCurToday = item.date === curDate;
            });
        }
      } else {
        this.days.forEach((item) => {
          item.isCurToday = item.date === curDate;
        });
      }
      this.getActiveDay();
    },
    /**
     * 清空选择
     */
    handleClear() {
      this.isChooseOne = false;
      this.startTime = null;
      this.endTime = null;
      this.chooseDateList = {};
      this.days.forEach((item) => {
        item.isActive = false;
      });
    },

    /**
     * 选择时间
     * @param time
     */
    handleChooseDay(time = {}) {
      // 判断 是否是禁止选择的日期 是否是
      if (this.restrictDate && time.isPreviousDate) {
        return;
      }
      //是否是多选
      if (this.isMultipleChoice) {
        this.chooseDateList = {};
        //选择开始时间-结束时间
        if (this.isChooseOne) {
          this.endTime = time;
          const { timestamp } = this.startTime || {};
          //如果 选择的开始日期大于结束日期 则调换开始日期与结束日期
          if (timestamp > time.timestamp) {
            [this.startTime, this.endTime] = [this.endTime, this.startTime];
          }
          this.getActiveDay();
          this.isChooseOne = false;
          this.$emit("chooseDays", this.chooseDateList);
        } else {
          this.isChooseOne = true;
          this.startTime = time;
          //给选择的时间范围选中
          this.days.forEach((item) => {
            item.isActive = item.timestamp === this.startTime.timestamp;
          });
        }
      } else {
        this.days.forEach((item) => {
          if (item.timestamp === time.timestamp) {
            item.isActive = !time.isActive;
            if (time.isActive) {
              const { date, day, month, timestamp, year } = item;
              this.chooseDateList[time.timestamp] = {
                date,
                day,
                month,
                timestamp,
                year,
              };
            } else {
              delete this.chooseDateList[time.timestamp];
            }
          }
        });

        this.$emit("chooseDays", this.chooseDateList);
      }
    },
    /**
     * 给选择的日期范围加上选中状态
     */
    getActiveDay() {
      if (this.isMultipleChoice) {
        if (!this.startTime || !this.endTime) {
          return;
        }
        //给选择的时间范围选中
        const { timestamp } = this.startTime || {};
        const { timestamp: endTimestamp } = this.endTime || {};
        this.days.forEach((item) => {
          item.isActive =
            item.timestamp >= timestamp &&
            item.timestamp <= endTimestamp &&
            !item.isPreviousDate;
          //是否显示点
          item.isShowPoint = this.pointMap[item.timestamp];
          if (
            item.timestamp >= timestamp &&
            item.timestamp <= endTimestamp &&
            !item.isPreviousDate
          ) {
            const { date, day, month, timestamp, year } = item;
            this.chooseDateList[item.timestamp] = {
              date,
              day,
              month,
              timestamp,
              year,
            };
          } else {
            delete this.chooseDateList[item.timestamp];
          }
        });
      } else {
        this.days.forEach((item) => {
          //是否显示点
          item.isShowPoint = this.pointMap[item.timestamp];
          //已选择的数据加上状态
          item.isActive = !!this.chooseDateList[item.timestamp];
        });
      }
    },
  },
  mounted() {
    this.handleShowToday();
  },
};
</script>
<style>
ul {
  list-style: none;
}

.w-calender-container {
  margin: auto;
  width: 550px;
  height: 500px;
  /* border: 1px solid #ddd; */
  box-sizing: border-box;
}
.select_date {
  width: 100%;
  text-align: center;
  font-size: 14px;
  color: #000;
  font-weight: 600;
}
.w-top {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1% 0;
  /* border-bottom: 1px solid #ddd; */
  box-sizing: border-box;
}

.w-top .w-top-date {
  display: flex;
  align-content: center;
  white-space: nowrap;
}

.w-top .w-btn-wrap {
  min-width: 200px;
  display: flex;
  justify-content: space-around;
  color: #f26520;
}

.w-btn-wrap span {
  flex: 1;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 16px;
}

.w-btn-wrap span:last-child {
  color: #ff6200;
}

.w-date_wrap {
  width: 100%;
  height: auto;
}

.w-date_wrap .w-week {
  width: 100%;
  display: flex;
  flex-direction: row;
  padding: 10px 0 10px 40px;
  font-size: 16px;
  box-sizing: border-box;
}

.w-date_wrap .w-week li {
  width: 14.28%;
}

.w-date_wrap .w-day {
  width: 100%;
  display: flex;
  flex-direction: row;
  padding: 0 20px;
  font-size: 16px;
  flex-wrap: wrap;
  box-sizing: border-box;
}

.w-day li {
  position: relative;
  cursor: pointer;
  width: 14.28%;
  padding: 4%;
  /* border: 1px solid #ddd; */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
}

.w-day li .w-point {
  position: absolute;
  bottom: 26%;
  background: #ff0000;
  display: flex;
  width: 4px;
  height: 4px;
  border-radius: 50%;
}

.w-day li:nth-child(n + 8) {
  border-top: none;
}

.w-day li:nth-child(n + 1) {
  border-right: none;
}

.w-day li:nth-child(7n) {
  /* border-right: 1px solid #ddd; */
}

.c-isCurMonth {
  background: #fff;
  color: #c0c4cc;
}

.c-isCurToday {
  background: #fff;
  color: #f26520;
}

.c-isActive {
  background: #f26520;
  color: #f2f8fe;
}

.chooseMonth {
  width: 120px;
}

.isCurYearDay {
  cursor: not-allowed !important;
  opacity: 0.6;
}

.c-isCurMonth.c-isActive {
  background: #f26520;
}

.c-is-previous-date {
  background: rgba(192, 196, 204, 0.2);
  color: #c0c4cc;
  cursor: not-allowed !important;
}
</style>

父组件:

 <el-dialog
      title="请选择时间"
      v-if="dialogTimeVisible"
      custom-class="timeDialog"
      :visible.sync="dialogTimeVisible"
      width="45%"
    >
      <dayTime @chooseDays="chooseDays"></dayTime>
      <div class="btn_cir">
        <el-button>取消</el-button>
        <el-button type="primary" @click="onCirmentClick">确定</el-button>
      </div>
    </el-dialog>
  chooseDays(v) {
      let list = Object.values(v);
      if (this.timeState == 1) {
        this.timevalue = `${list[0].date} - ${list[list.length - 1].date}`;
      } else {
        this.inputTimeVlue = `${list[0].date} - ${list[list.length - 1].date}`;
      }
      // 拿到对象中的第一条数据
      // let day = v[Object.keys(v)[0]];
      // 对象转换成数组
    },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值