组件:
<!--* @Author: liuyu liuyu@xizhengtech.com* @Date: 2023-02-01 16:57:27* @LastEditors: wangping wangping@xizhengtech.com* @LastEditTime: 2023-06-30 17:25:14* @Description: 时间选择年 - 年
-->
<template><div class="yearPicker" ref="yearPicker" :width="width"><input class="_inner" :style="bindInputStyle" ref="inputLeft" v-model="startShowYear" @focus="onFocus" @blur="onBlur" type="text" name="yearInput" @keyup="checkStartInput($event)" placeholder="开始年份" /><span>{{ sp }}</span><input class="_inner" :style="bindInputStyle" ref="inputRight" v-model="endShowYear" @focus="onFocus" @blur="onBlur" type="text" name="yearInput" @keyup="checkEndInput($event)" placeholder="结束年份" /><!-- <i class="dateIcon el-icon-date"></i> 按照自己标准库里面的图标设置--><!-- <span class="_inner labelText"></span> --><i class="_inner labelText el-icon-date"></i><div class="_inner floatPanel" v-if="showPanel"><div class="_inner leftPanel"><div class="_inner panelHead"><i class="_inner el-icon-d-arrow-left" @click="onClickLeft"></i>{{ leftYearList[0] + " - " + leftYearList[9] }}</div><div class="_inner panelContent"><div :class="{oneSelected: item === startYear && oneSelected,startSelected: item === startYear,endSelected: item === endYear,betweenSelected: item > startYear && item < endYear,}" v-for="item in leftYearList" :key="item"><a :class="{cell: true,_inner: true,selected: item === startYear || item === endYear,}" @click="onClickItem(item)" @mouseover="onHoverItem(item)">{{ item }}</a></div></div></div><div class="line"></div><div class="_inner rightPanel"><div class="_inner panelHead"><i class="_inner el-icon-d-arrow-right" @click="onClickRight"></i>{{ rightYearList[0] + " - " + rightYearList[9] }}</div><div class="_inner panelContent"><div :class="{startSelected: item === startYear,endSelected: item === endYear,betweenSelected: item > startYear && item < endYear,}" v-for="item in rightYearList" :key="item"><a :class="{cell: true,_inner: true,selected: item === endYear || item === startYear,}" @click="onClickItem(item)" @mouseover="onHoverItem(item)">{{ item }}</a></div></div></div></div></div>
</template><script>
import moment from "moment";
const SELECT_STATE = {unselect: 0,selecting: 1,selected: 2,
};
export default {name: "yearPicker",computed: {bindInputStyle() {return {"--placeholderColor": "#c0c4cc",};},oneSelected() {return (this.curState === SELECT_STATE.selecting &&(this.startYear === this.endYear || this.endYear == null));},startDate() {return this.startYear;},leftYearList() {return this.yearList.slice(0, 10);},rightYearList() {return this.yearList.slice(10, 20);},startYearFormat() {if (this._.isNil(this.startYear)) {return null;}return moment(this.startYear).startOf("year").format("yyyy");},endYearFormat() {if (this._.isNil(this.endYear)) {return null;}return moment(this.endYear).endOf("year").format("yyyy");},},props: {width: {default: 200,},labelWidth: {default: 40,},sp: {default: "-",},initYear: {default: null,},},data() {return {itemBg: {},startShowYear: null,endShowYear: null,yearList: [],showPanel: false,startYear: null,endYear: null,curYear: 0,curSelectedYear: 0,curState: SELECT_STATE.unselect,};},methods: {checkStartInput(event) {if (isNaN(this.startShowYear)) {this.startShowYear = this.startYear;} else {this.startYear = this.startShowYear * 1;this.changeYear();}},checkEndInput() {if (isNaN(this.endShowYear)) {this.endShowYear = this.endYear;} else {this.endYear = this.endShowYear * 1;this.changeYear();}},changeYear() {if (this.startYear > this.endYear) {let tmp = this.endYear;this.endYear = this.startYear;this.startYear = tmp;this.startShowYear = this.startYear;this.endShowYear = this.endYear;}if (this.startYear && this.endYear) {this.$emit("updateTimeRange", {startYear: moment(this.startYear + "").startOf("year").valueOf(),endYear:moment(this.endYear + "").endOf("year").valueOf() + 1,});} else {console.warn("WARN:年份不合法", this.startYear, this.endYear);}},onHoverItem(iYear) {if (this.curState === SELECT_STATE.selecting) {let tmpStart = this.curSelectedYear;this.endYear = Math.max(tmpStart, iYear);this.startYear = Math.min(tmpStart, iYear);}},onClickItem(iYear) {if (this.curState === SELECT_STATE.unselect ||this.curState === SELECT_STATE.selected) {this.startYear = iYear;this.curSelectedYear = iYear;this.endYear = null;this.curState = SELECT_STATE.selecting;} else if (this.curState === SELECT_STATE.selecting) {this.endShowYear = this.endYear;this.startShowYear = this.startYear;this.curState = SELECT_STATE.selected;this.$emit("updateTimeRange", {startYear: moment(this.startYear + "").startOf("year").valueOf(),endYear:moment(this.endYear + "").endOf("year").valueOf() + 1,});setTimeout(() => {this.showPanel = false;}, 300);}},onFocus() {this.$nextTick(() => {this.showPanel = true;});},onBlur() {},updateYearList() {let iStart = Math.floor(this.curYear / 10) * 10 - 10;iStart = iStart < 0 ? 0 : iStart;this.yearList = [];for (let index = 0; index < 20; index++) {this.yearList.push(iStart + index);}},closePanel(e) {if (!this.showPanel) {return;}if (typeof e.target.className !== "string") {this.$nextTick(() => {this.showPanel = false;});return;}if (e.target.className.indexOf("_inner") === -1 ||(e.target.name === "yearInput" &&e.target !== this.$refs.inputLeft &&e.target !== this.$refs.inputRight)) {this.$nextTick(() => {this.showPanel = false;});}e.stopPropagation();return false;},onClickLeft() {this.curYear = this.curYear * 1 - 10;this.updateYearList();},onClickRight() {this.curYear = this.curYear * 1 + 10;this.updateYearList();},setYear(startYearStamp, endYearStamp) {if (!isNaN(startYearStamp) && !isNaN(endYearStamp)) {let startYear = moment(startYearStamp).format("yyyy");let endYear = moment(endYearStamp).format("yyyy");this.startYear = startYear * 1;this.endYear = endYear * 1;this.endShowYear = endYear * 1;this.startShowYear = startYear * 1;}},},created() {this.curYear = moment().format("yyyy");this.updateYearList();},beforeUnmount() {document.removeEventListener("click", this.closePanel.bind(this));},mounted() {this.$refs.yearPicker.style = "padding-left:" + this.labelWidth + "px";document.addEventListener("click", this.closePanel.bind(this));},
};
</script>
<style lang="scss" scoped>
.yearPicker {font-size: 14px;display: flex;position: relative;transition: all 0.3s;input {&::placeholder {color: var(--placeholderColor); }}input:first-child {text-align: center;}.labelText {position: absolute;left: 10px;top: 10px;color: #c4c6d1;}background-color: #fff;span {padding: 0 8px;height: 36px;line-height: 36px;}border: 1px solid #eff1f3;height: 36px;line-height: 36px;border-radius: 4px;padding: 0 28px 0 8px;box-sizing: border-box;.floatPanel {> div {width: 50%;}position: absolute;display: flex;background-color: #fff;z-index: 9999 !important;border-radius: 4px;height: 252px;top: 50px;left: 0px;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);border: 1px solid #dfe4ed;.panelContent {display: grid;grid-template-columns: 25% 25% 25% 25%;width: 100%;height: calc(100% - 15px);margin-top: 8px;.oneSelected {border-top-right-radius: 24px;border-bottom-right-radius: 24px;}.startSelected {background-color: #f2f6fc;border-top-left-radius: 24px;border-bottom-left-radius: 24px;}.endSelected {background-color: #f2f6fc;border-top-right-radius: 24px;border-bottom-right-radius: 24px;}.betweenSelected {background-color: #f2f6fc;}> div {width: 75px;height: 48px;line-height: 48px;margin: 6px 0;text-align: center;a {display: inline-block;width: 60px;height: 36px;cursor: pointer;line-height: 36px;border-radius: 18px;color: #606266;}.selected {background-color: #1890ff;color: #fff;}}}.panelHead {height: 38px;line-height: 38px;position: relative;text-align: center;font-size: 16px;border-bottom: 1px solid #dfe4ed;i {position: absolute;cursor: pointer;&:hover {color: #1890ff;}}}.rightPanel {margin: 16px;display: flex;flex-direction: column;}.line {width: 1px;height: 100%;background: #dfe4ed;}.leftPanel {margin: 16px;display: flex;flex-direction: column;}.leftPanel .panelHead i {left: 0px;top: 10px;font-size: 14px;color: #717273;}.rightPanel .panelHead i {right: 0px;top: 8px;}.leftPanel .panelHead i:hover,.rightPanel .panelHead i:hover {cursor: pointer;}}.floatPanel::before {content: "";border-bottom: 6.5px solid #797979;border-left: 6.5px solid transparent;border-right: 6.5px solid transparent;position: absolute;left: 44px;-webkit-transform: translateX(-50%);transform: translateX(-50%);top: -5.5px;border-radius: 5px;}.floatPanel::after {content: "";border-bottom: 8px solid #fff;border-left: 8px solid transparent;border-right: 8px solid transparent;position: absolute;left: 44px;-webkit-transform: translateX(-50%);transform: translateX(-50%);top: -5px;border-radius: 5px;}
}
input {width: 100px;border: none;height: 37px;line-height: 37px;box-sizing: border-box;background-color: transparent;text-align: center;color: #606266;
}
input:focus {outline: none;background-color: transparent;
}
.yearPicker:hover {border-color: #1890ff;
}
.dateIcon {position: absolute;right: 16px;top: 9px;color: #adb2bc;
}
</style>
使用:
<YearYear1 style="width:300px" :initYear="dateValue2" @updateTimeRange="updateStatisticYear" />dateValue2: [],updateStatisticYear(val) {console.log("年", val);
},