自定义周选择组件、年选择组件

代码里面用到的ui-xxx组件,属于内部自定义组件,仅供参考,直接复制粘贴使用,失败

// 周组件 weekSelect

<!-- 周选择组件 -->
<template>
  <div ref="viYearSelect" class="vi-year-select">
    <ui-input
            v-model="selectVal"
            :placeholder="placeholder"
            :disabled="disabled"
            readonly
      :clearable="clearable"
            @click.native.stop="showSelect"
            :suffix="selectShow ? 'ios-arrow-up' : 'ios-arrow-down'"
    />
    <div class="zTreeSelect" :style="{ width: width }" v-show="selectShow" @click.stop>
        <div class="panel-top">
          <span @click="prevYear">
            <ui-icon type="ios-arrow-back" size="16" color="#001F45" />
          </span>
          <div class="week-info">
            <span>{{defaultYear}}</span>&nbsp;
          </div>
          <span @click="nextYear">
            <ui-icon type="ios-arrow-forward" size="16" color="#001F45" />
          </span>
        </div>
        <div class="panel-info">
          <div class="option"
            v-for="(wItem,wIndex) in this.weekList"
            :key="wIndex"
            :title="wItem[0]+' 至 '+wItem[wItem.length-1]"
            :class="{'disabledCls': disabledCls(defaultYear, wIndex)}"
            @click="selectOption(wItem,wIndex,defaultYear)"
          >
            <span class="option-info">第{{wIndex*1+1*1}}周</span>
          </div>
        </div>
    </div>
  </div>
</template>
<script>
import { weekFormat } from "@/utils/index";
export default {
  name: "viWeekSelect",
  props: {
    model: {
      type: String
    },
    clearable: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: "请选择",
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    disabledValR: { // 大于当前的值,禁止选择,值格式为: YYYY 第N周
      type: String,
      default: ""
    },
    disabledValL: { // 小于当前的值,禁止选择,值格式为: YYYY 第N周
      type: String,
      default: ""
    },
  },
  // model中:prop代表着我要和props的指定变量(model)相对应,event表示着事件,我触发事件(change)的时候会改变父组件v-model的值
  model: {
    prop: "model",
    event: ""
  },
  watch: {
    model: {
      deep: true,
      immediate: true,
      handler(val) {
        this.selectVal = val;
      }
    }
  },
  computed: {
    // 周,禁止选择项判断
    disabledCls() {
      return function (dyear, wIndex) {
        try {
          dyear = Number(dyear);
          wIndex = Number(wIndex);
          if (this.disabledValR) {
            const year = Number(this.disabledValR.split(" ")[0]);
            const weekStr = this.disabledValR.split(" ")[1];
            const week = Number(weekStr.slice(1, weekStr.length - 1));
            if ((dyear > year) || (dyear == year && week < Number(wIndex * 1 + 1 * 1))) {
              return true;
            } else {
              return false;
            }
          } else if (this.disabledValL) {
            const year = Number(this.disabledValL.split(" ")[0]);
            const weekStr = this.disabledValL.split(" ")[1];
            const week = Number(weekStr.slice(1, weekStr.length - 1));
            if ((dyear < year) || (dyear == year && week > Number(wIndex * 1 + 1 * 1))) {
              return true;
            } else {
              return false;
            }
          } else {
            return false;
          }
        } catch (e) {}
      };
    }
  },
  data() {
    const curY = this.$moment().format("YYYY");// 获取今年
    return {
      selectVal: "",
      selectShow: false,
      width: 0,
      //
      defaultYear: curY,
      stepYear: 1,
      weekList: [],
    };
  },
  mounted() {
    this.initYear(this.defaultYear);
    this.initEvent();
  },
  methods: {
    initYear(initY) {
      this.defaultYear = Number(initY);
      this.weekList = weekFormat(initY);
    },
    resetWidth() {
      const width = this.$refs.viYearSelect.offsetWidth;
      this.width = `${width}px`;
    },
    prevYear() {
      this.defaultYear -= 1 * this.stepYear;
      this.initYear(this.defaultYear);
    },
    nextYear() {
      this.defaultYear += 1 * this.stepYear;
      this.initYear(this.defaultYear);
    },
    // 年组件选择
    selectOption(wItem, wIndex, dyear) {
      const bool = this.disabledCls(dyear, wIndex);
      if (bool) {
        // console.log("禁止选择时间段");
        return false;
      }
      this.selectShow = false;
      let rsp = {
        startTime: `${wItem[0]} 00:00:00`,
        endTime: `${wItem[wItem.length - 1]} 23:59:59`
      };
      this.$emit("change", rsp, "week");
      this.selectVal = `${this.defaultYear} 第${wIndex * 1 + 1 * 1}周`;
    },
    showSelect() {
      if (!this.disabled) {
        this.selectShow = !this.selectShow;
        this.resetWidth();
      }
    },
    initEvent() {
      document.addEventListener("click", () => {
        this.selectShow = false;
      });
    },
  },
};
</script>

<style lang="less" scoped>
.vi-year-select {
  position:relative;
}
.search-form .vi-year-select .zTreeSelect {
  position: fixed !important;
}
  .zTreeSelect {
    background-color: #fff;
    height: 220px;
    max-width: 400px;
    overflow: auto;
    position: absolute;
    z-index: 10;
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
    border-radius: 4px;
    margin-top: 5px;
    z-index: 99;
    .option {
      text-align: center;
      cursor: pointer;
      margin: 0;
      line-height: normal;
      padding: 7px 0px;
      clear: both;
      color: #515a6e;
      font-size: 14px;
      white-space: nowrap;
      list-style: none;
      cursor: pointer;
      transition: background 0.2s ease-in-out;
      width: 50%;
      display: inline-block;
    }
    .option:hover{
        background: #f3f3f3;
    }
    .option.disabledCls {
      color: #AEB8C4;
      cursor: not-allowed;
    }
  }
  .panel-top {
    height: 30px;
    border-bottom: 1px solid #DCDEE2;
    display: flex;
    justify-content: space-around;
    &:last-child, &:first-child {
        cursor: pointer;
    }
  }
  .panel-info {
    height: 190px;
    overflow: auto;
  }
  .month-info {
    font-weight: 600;
  }
  .week-list{
    padding: 2px 0px;
    &:hover{
        background: #f3f3f3;
    }
  }
</style>
View Code
// 指定年份,返回,指定年份的周列表
function weekFormat(initY) {
  let weekList = [];
  let weekIdx = 0;
  weekList[weekIdx] = [];
  const monthDay = [31, ((initY % 4) == 0 ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // 每年的月份
  for (let i = 1; i <= monthDay.length; i++) {
    let month =  i > 9 ? i : `0${i}`;
    for (let j = 1; j <= monthDay[i - 1]; j++) {
      const day = j > 9 ? j : `0${j}`;
      const monthFirst = `${initY}-${month}-${day}`;
      let weekN = moment(`${monthFirst}`).format("dddd"); // 获取当天星期几
      weekList[weekIdx].push(monthFirst);
      if (weekN == "Sunday") {
        weekIdx++;
        weekList[weekIdx] = [];
      }
    }
  }
  return weekList;
}
View Code

 

 // 年组件 yearSelect

<template>
  <div ref="viYearSelect" class="vi-year-select">
    <ui-input
            v-model="selectVal"
            :placeholder="placeholder"
            :disabled="disabled"
            readonly
      :clearable="clearable"
            @click.native.stop="showSelect"
            :suffix="selectShow ? 'ios-arrow-up' : 'ios-arrow-down'"
    />
    <div class="zTreeSelect" :style="{ width: width }" v-show="selectShow" @click.stop>
      <div>
        <div class="panel-top">
          <span @click="prevYear">
            <ui-icon type="ios-arrow-back" size="16" color="#001F45" />
          </span>
          <span>{{defaultYear}}</span>
          <span @click="nextYear">
            <ui-icon type="ios-arrow-forward" size="16" color="#001F45" />
          </span>
        </div>
        <div>
          <div
            class="option"
            :class="{'disabledCls':disabledCls(item)}"
            v-for="item in yearList"
            :key="item"
            @click="selectOption(item)"
          >
          {{item}}年</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>

export default {
  name: "viYearSelect",
  props: {
    model: {
      type: String
    },
    clearable: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: "请选择",
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    disabledValR: { // 大于当前的值,禁止选择,值格式为: YYYY
      type: String,
      default: ""
    },
    disabledValL: { // 小于当前的值,禁止选择,值格式为: YYYY
      type: String,
      default: ""
    },
    type: { // 下拉类型,年(year)、星期(week)、季度
      type: String,
      default: "year"
    },
    rspType: {  // 返回类型,range,"",,range例如选择了年,那么就返回今年的开始时间和结束时间
      type: String,
      default: "range"
    }
  },
  // model中:prop代表着我要和props的指定变量(model)相对应,event表示着事件,我触发事件(change)的时候会改变父组件v-model的值
  model: {
    prop: "model",
    event: ""
  },
  watch: {
    model: {
      deep: true,
      immediate: true,
      handler(val) {
        this.selectVal = val;
      }
    },
    disabledValR: {
      deep: true,
      immediate: true,
      handler() {}
    },
    disabledValL: {
      deep: true,
      immediate: true,
      handler() {}
    }
  },
  computed: {
    // 年,禁止选择项判断
    disabledCls() {
      return function (item) {
        let bool = (this.disabledValR && item > this.disabledValR) || (this.disabledValL && item < this.disabledValL);
        return bool;
      };
    }
  },
  data() {
    return {
      selectVal: "",
      selectShow: false,
      width: 0,
      defaultYear: "",
      stepYear: 10,
      yearList: [],
    };
  },
  mounted() {
    const curY = this.$moment().format("YYYY");// 获取今年
    this.initYear(curY);
    this.initEvent();
  },
  methods: {
    initYear(initY) {
      this.defaultYear = Math.floor(initY / this.stepYear) * this.stepYear;
      this.yearList = [];
      for (let i = this.defaultYear; i < this.defaultYear * 1 + this.stepYear; i++) {
        this.yearList.push(i);
      }
    },
    resetWidth() {
      const width = this.$refs.viYearSelect.offsetWidth;
      this.width = `${width}px`;
    },
    prevYear() {
      this.defaultYear -= this.stepYear;
      this.initYear(this.defaultYear);
    },
    nextYear() {
      this.defaultYear += this.stepYear;
      this.initYear(this.defaultYear);
    },
    // 年组件选择
    selectOption(item) {
      const bool = this.disabledCls(item);
      if (bool) {
        // console.log("禁止选择时间段");
        return false;
      }
      this.selectShow = false;
      if (this.rspType == "range") {
        let rsp = {
          startTime: `${item}-01-01 00:00:00`,
          endTime: `${item}-12-31 23:59:59`
        };
        this.$emit("change", rsp, "year");
      } else {
        this.$emit("change", item, "year");
      }
      this.selectVal = item;
    },
    showSelect() {
      if (!this.disabled) {
        this.selectShow = !this.selectShow;
        this.resetWidth();
      }
    },
    initEvent() {
      document.addEventListener("click", () => {
        this.selectShow = false;
      });
    },
  },
};
</script>

<style lang="less" scoped>
.vi-year-select {
  position:relative;
}
.search-form .vi-year-select .zTreeSelect {
  position: fixed !important;
}
  .zTreeSelect {
    background-color: #fff;
    height: 200px;
    max-width: 400px;
    overflow: auto;
    position: absolute;
    z-index: 10;
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
    border-radius: 4px;
    margin-top: 5px;
    z-index: 99;
    .option {
        text-align: center;
        cursor: pointer;
        margin: 0;
        line-height: normal;
        padding: 7px 0px;
        clear: both;
        color: #515a6e;
        font-size: 14px;
        white-space: nowrap;
        list-style: none;
        cursor: pointer;
        transition: background 0.2s ease-in-out;
        width: 50%;
        display: inline-block;
    }
    .option:hover{
        background: #f3f3f3;
    }
    .option.disabledCls {
      color: #AEB8C4;
      cursor: not-allowed;
    }
  }
  .panel-top {
      height: 30px;
      border-bottom: 1px solid #DCDEE2;
      display: flex;
      justify-content: space-around;
      &:last-child, &:first-child {
          cursor: pointer;
      }
  }
</style>
View Code

 

// 常见时间转换,

根据年月,返回该月的周情况
/** 根据年月,返回该月的周情况
 * @param {*} yearMonth 格式,YYYY-MM,表示需要计算的月份
 * @param {*} rspFormat ,格式,String,是返回时间格式分割符,可以为:/ -
 * @returns [],返回指定月份的周情况
 */
function weekByMonth(yearMonth, splitSym = "YYYY-MM-DD") {
  const lastDay = Number(moment(yearMonth).endOf("month").format("D"));  // 最后一天
  let weekStart = moment(`${yearMonth}-01`).day();  // 获取1号属于星期几
  weekStart = weekStart == 0 ? 7 : weekStart; // weekStart=0,表示周日
  const weekEnd = moment(`${yearMonth}-${lastDay}`).day(); // 获取最后一天属于星期几
  const fullMonthDay = Number(lastDay) + (weekStart - 1) + (7 - weekEnd);
  const forNum = Math.ceil(fullMonthDay / 7); // 获取for循环遍历次数
  const ary = [];
  for (let i = 1; i <= forNum; i++) {
    let weekSDay = null;
    let weekE = null;
    if (i == 1) {
      weekSDay = 1;
      weekE = weekSDay + (7 - weekStart); // weekStart=0,表示周日
    } else {
      weekSDay = ary[ary.length - 1]["weekE"] + 1;
      weekE = (Number(weekSDay) + 6) <= Number(lastDay) ? Number(weekSDay) + 6 : lastDay;
    };
    const weekStartDay = moment(`${yearMonth}-${weekSDay}`).format(splitSym);
    const weekEndtDay = moment(`${yearMonth}-${weekE}`).format(splitSym);
    ary.push({
      name: `第${i}周`,
      value: `${weekStartDay}, ${weekEndtDay}`,
      weekSDay,
      weekE,
      weekStartDay,
      weekEndtDay
    });
  }
  return ary;
}
View Code

 

根据当前日期,返回所属第几周的信息
/** 根据当前日期,返回所属第几周的信息
 * @param {*} yearMonth 格式,YYYY-MM-DD,表示需要计算的日期,yearMonthDay为空情况下,默认当天
 * @param {*} rspFormat ,格式,String,是返回时间格式分割符,可以为:/ -
 * @returns [],返回指定月份的周情况
 */
function dayByWeKMonth(YMD) {
  const yearMonthDay = YMD || moment(new Date()).format("YYYY-MM-DD");
  const ary = weekByMonth(moment(yearMonthDay).format("YYYY-MM"));
  const dd = Number(moment(yearMonthDay).format("DD"));
  let rsp = {};
  for (let i = 0; i < ary.length; i++) {
    const item = ary[i];
    if (dd >= Number(item.weekSDay) && dd <= Number(item.weekE)) {
      rsp = item;
      break;   // break跳出整个循环
    }
  }
  return rsp;
}
View Code

 

指定年份,返回,指定年份的周列表
// 指定年份,返回,指定年份的周列表
function weekFormat(initY) {
  let weekList = [];
  let weekIdx = 0;
  weekList[weekIdx] = [];
  const monthDay = [31, ((initY % 4) == 0 ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // 每年的月份
  for (let i = 1; i <= monthDay.length; i++) {
    let month =  i > 9 ? i : `0${i}`;
    for (let j = 1; j <= monthDay[i - 1]; j++) {
      const day = j > 9 ? j : `0${j}`;
      const monthFirst = `${initY}-${month}-${day}`;
      let weekN = moment(`${monthFirst}`).format("dddd"); // 获取当天星期几
      weekList[weekIdx].push(monthFirst);
      if (weekN == "Sunday") {
        weekIdx++;
        weekList[weekIdx] = [];
      }
    }
  }
  return weekList;
}
View Code

 

// 根据年月日"YYYY-MM-DD",返回所属年份的第几周
function dayToWeekFormat(initDay) {
  let year = moment(initDay).format("YYYY");
  let weebList = weekFormat(year);
  let rspStr = "";
  for (let i = 0; i < weebList.length; i++) {
    let idx = weebList[i].indexOf(initDay);
    if (idx > -1) {
      rspStr = `${year} 第${i * 1 + 1 * 1}周`;
      break;
    }
  }
  return rspStr;
}
View Code

 

根据年月日"YYYY-MM-DD",返回所属年份的第几周
// 根据年月日"YYYY-MM-DD",返回所属年份的第几周
function dayToWeekFormat(initDay) {
  let year = moment(initDay).format("YYYY");
  let weebList = weekFormat(year);
  let rspStr = "";
  for (let i = 0; i < weebList.length; i++) {
    let idx = weebList[i].indexOf(initDay);
    if (idx > -1) {
      rspStr = `${year} 第${i * 1 + 1 * 1}周`;
      break;
    }
  }
  return rspStr;
}
View Code

 

posted on 2024-08-09 17:08  紫藤萝yu  阅读(28)  评论(0编辑  收藏  举报