赞
踩
element 组件库 关于月份范围 以及 日期范围选择器都有相对应的组件 但是年份范围选择器没有给到 因为公司业务需要 我就根据饿了么组件以及其他程序⚪的代码封装了一个年份范围选择器
相关代码
<template> <div class="year-all"> <transition name="el-zoom-in-top"> <div v-show="showPanel" ref="popover" class="el-popover" placement="bottom" popper-class="custom_year_range" trigger="manual" > <div class="_inner float-panel"> <div class="_inner left-panel"> <div class="_inner panel-head"> <i class="_inner el-icon-d-arrow-left" @click="onClickLeft" ></i> <span class="year-main"> {{ leftYearList[0] + '年 ' + '- ' + leftYearList[9] + '年' }} </span> </div> <div class="_inner panel-content"> <div v-for="item in leftYearList" :key="item" class="year-item" :class="{ oneSelected: item === startYear && oneSelected, startSelected: item === startYear, endSelected: item === endYear, betweenSelected: item > startYear && item < endYear, }" @click="onClickItem(item)" @mouseover="onHoverItem(item)" > <a :class="{ cell: true, _inner: true, selected: item === startYear || item === endYear, }" > {{ item }} </a> </div> </div> </div> <div class="_inner right-panel"> <div class="_inner panel-head"> <i class="_inner el-icon-d-arrow-right" @click="onClickRight" ></i> <span class="year-main">{{ rightYearList[0] + '年 ' + '- ' + rightYearList[9] + '年' }}</span> </div> <div class="_inner panel-content"> <div v-for="item in rightYearList" :key="item" class="year-item" :class="{ startSelected: item === startYear, endSelected: item === endYear, betweenSelected: item > startYear && item < endYear, }" > <a :class="{ cell: true, _inner: true, selected: item === endYear || item === startYear, }" @click="onClickItem(item)" @mouseover="onHoverItem(item)" > {{ item }} </a> </div> </div> </div> </div> </div> </transition> <div slot="reference"> <div ref="yearPicker" style="width: 100%" class="el-date-editor el-range-editor el-input__inner el-date-editor--daterange el-range-editor--small" @mouseover="onHoverIcon" @mouseleave="lossHoverIcon" > <img src="@/assets/image/common/icon_date.png" class="el-icon-date" @click="clickLeftIcon" > <input ref="inputLeft" v-model="startShowYear" class="_inner range_input" type="text" name="yearInput" placeholder="开始年份" readonly="readonly" @focus="onFocus" @keyup="handleInput('start')" /> <span class="el-range-separator">{{ sp }}</span> <input ref="inputRight" v-model="endShowYear" readonly="readonly" class="_inner range_input" type="text" name="yearInput" placeholder="结束年份" @focus="onFocus" @keyup="handleInput('end')" /> <!-- 删除icon --> <i v-show="isClearIconShow" class="el-input__icon el-range__close-icon el-icon-circle-close" @click="clearSelectYear" ></i> </div> </div> </div> </template> <script> import DayJs from 'dayjs' import { SELECT_STATE } from '@/utils/index.js' export default { name: 'YearPicker', props: { sp: { type: String, default: '至' }, value: { type: Object, default: null } }, data() { return { isClearIconShow: false, itemBg: {}, startShowYear: null, endShowYear: null, yearList: [], showPanel: false, startYear: null, endYear: null, curYear: 0, curSelectedYear: 0, curState: SELECT_STATE.unselect, isDisplay: false } }, computed: { oneSelected() { return this.curState === SELECT_STATE.selecting && (this.startYear === this.endYear || this.endYear == null) }, leftYearList() { return this.yearList.slice(0, 10) }, rightYearList() { return this.yearList.slice(10, 20) } }, watch: { value: { handler(val) { if (val?.length === 0) return const [first, end] = val || [] this.startShowYear = first this.endShowYear = end }, immediate: true, deep: true }, startShowYear: { handler(val) { this.$emit('input', [val, this.endShowYear || '']) }, immediate: true, deep: true }, endShowYear: { handler(val) { this.$emit('input', [this.startShowYear || '', val]) }, immediate: true, deep: true } }, created() { const [startYear, endYear] = this.value || [] if (startYear) { this.startYear = Number(startYear) this.endYear = Number(endYear) this.curState = SELECT_STATE.selected this.curYear = startYear } else { this.curYear = DayJs().year() } this.updateYearList() }, mounted() { window.Vue = this }, methods: { clickLeftIcon() { this.showPanel = true }, clearSelectYear() { this.startShowYear = undefined this.endShowYear = undefined this.startYear = '' this.endYear = '' }, handleInput(type) { switch (type) { case 'start': if (isNaN(this.startShowYear)) { this.startShowYear = this.startYear return } this.startYear = this.startShowYear * 1 break case 'end': if (isNaN(this.endShowYear)) { this.endShowYear = this.endYear return } this.endYear = this.endShowYear * 1 break } [this.startYear, this.endYear] = [this.endYear, this.startYear] this.startShowYear = this.startYear this.endShowYear = this.endYear }, onHoverItem(iYear) { if (this.curState === SELECT_STATE.selecting) { const tmpStart = this.curSelectedYear this.endYear = Math.max(tmpStart, iYear) this.startYear = Math.min(tmpStart, iYear) } }, onHoverIcon() { if (this.startShowYear !== undefined && this.endShowYear !== undefined) { this.isClearIconShow = true } else { this.isClearIconShow = false } }, lossHoverIcon() { this.isClearIconShow = false }, async onClickItem(selectYear) { if ( this.curState === SELECT_STATE.unselect || this.curState === SELECT_STATE.selected ) { this.startYear = selectYear this.curSelectedYear = selectYear this.endYear = null this.curState = SELECT_STATE.selecting } else if (this.curState === SELECT_STATE.selecting) { this.endShowYear = this.endYear || this.startYear this.startShowYear = this.startYear this.curState = SELECT_STATE.selected await this.$nextTick() this.showPanel = false } }, async onFocus() { await this.$nextTick() this.showPanel = true }, updateYearList() { const startYear = ~~(this.curYear / 10) * 10 this.yearList = [] for (let index = 0; index < 20; index++) { this.yearList.push(startYear + index) } }, onClickLeft() { this.curYear = this.curYear * 1 - 10 this.updateYearList() }, onClickRight() { this.curYear = this.curYear * 1 + 10 this.updateYearList() } } } </script> <style lang="scss" scoped> .year-all { position: relative; .el-popover { width: 644px; height: 250px; top: 44px; .float-panel { position: relative; display: flex; justify-content: space-between; .left-panel, .right-panel { width: 50%; padding: 0 16px; .panel-head { font-size: 16px; height: 46px; display: flex; align-items: center; justify-content: center; .year-main { display: flex; } .year-main:hover { color: #2F45FF; cursor: pointer; } } .panel-content { font-size: 14px; display: flex; justify-self: start; flex-wrap: wrap; .year-item { display: flex; justify-content: center; align-items: center; width: 64px; height: 32px; margin-bottom: 12px; margin-right: 4px; } .year-item:hover { cursor: pointer; background: #F4F4F7; border-radius: 2px; color: #333; } .startSelected { background: #fff !important; border: 1px solid #2F45FF; border-radius: 2px; color: #2F45FF; } .endSelected { background: #fff !important; border: 1px solid #2F45FF; border-radius: 2px; color: #2F45FF; } .year-item:active { background: #fff; border: 1px solid #2F45FF; border-radius: 2px; } } } .left-panel { border-right: 1px solid #ebeef5; } .el-icon-d-arrow-right { position: absolute; right: 0; } .el-icon-d-arrow-right:hover { color: #2F45FF; cursor: pointer; } .el-icon-d-arrow-left { position: absolute; left: 0; } .el-icon-d-arrow-left:hover { color: #2F45FF; cursor: pointer; } } } .el-icon-date { width: 18px; height: 18px; } .el-icon-date:hover { cursor: pointer; } .el-range__close-icon { display: flex; align-items: center; } .range_input { appearance: none; border: none; outline: 0; padding: 0; width: 86px; color: #606266; line-height: 40px; height: 40px; margin: 0; text-align: center; color: #646566; font-size: 14px; } .yearPicker { input:first-child { text-align: right; } .labelText { position: absolute; left: 8px; } background-color: #fff; span { padding: 0 8px; height: 32px; line-height: 32px; } border: 1px solid #eff1f3; height: 34px; line-height: 34px; border-radius: 4px; padding: 0 28px 0 8px; box-sizing: border-box; } input { width: 60px; border: none; height: 32px; line-height: 32px; box-sizing: border-box; background-color: transparent; } input:focus { outline: none; background-color: transparent; } .yearPicker:hover { border-color: #3e77fc; } .dateIcon { position: absolute; right: 16px; top: 9px; color: #adb2bc; } } </style>
使用方式
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。