// 周元件 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> </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>
// 指定年份,返回,指定年份的周列表 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; }
// 年元件 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>