效果图
1.子组件
<template> <div class="el-quarter-wrap"> <el-popover title="" content="" width="320" v-model="visible"> <template #reference> <el-input v-model="quarterDate" placeholder="请选择季度" clearable :prefix-icon="Calendar" readonly @click.stop.native="visible = true" @change="quarterDateChange"> <template #suffix> <el-icon v-if="quarterDate" class="el-quarter-clear" @click="clearData"> <Close /> </el-icon> </template> </el-input> </template> <div class="el-quarter__header"> <span class="el-quarter-btn el-quarter-btn__pre" @click="changeShowYear(-1)"> <el-icon> <DArrowLeft /> </el-icon> </span> <div class="el-quarter__header-text" @click="showYearList"> {{ quarterTitle }} </div> <span class="el-quarter-btn el-quarter-btn__next" @click="changeShowYear(1)"> <el-icon> <DArrowRight /> </el-icon> </span> </div> <div class="el-quarter__content" v-if="!isEditYear"> <div class="el-quarter__row"> <span class="quarter-index" :class="{ 'is-active': showYear === pickerYear && quarterIndex === 1 }" @click="pickerQuarte(1)">第一季度</span> <span class="quarter-index" :class="{ 'is-active': showYear === pickerYear && quarterIndex === 2 }" @click="pickerQuarte(2)">第二季度</span> </div> <div class="el-quarter__row"> <span class="quarter-index" :class="{ 'is-active': showYear === pickerYear && quarterIndex === 3 }" @click="pickerQuarte(3)">第三季度</span> <span class="quarter-index" :class="{ 'is-active': showYear === pickerYear && quarterIndex === 4 }" @click="pickerQuarte(4)">第四季度</span> </div> </div> <div class="el-year__content" v-else> <div class="el-year-item" v-for="item in yearList"> <div class="cell" :class="{ 'is-active': showYear == item }" @click="selectYear(item)"> {{ item }} </div> </div> </div> </el-popover> </div> </template>
<script lang="ts" setup> import { DArrowLeft, DArrowRight, Close, Calendar } from '@element-plus/icons-vue' import { computed, onMounted, reactive, ref } from 'vue' let visible = ref(false) const props = defineProps({ modelValue:{ type: String, default: '' } }) const emits = defineEmits(['update:modelValue', 'change']) // 绑定日期 let quarterDate = ref('') // 选择的年 let pickerYear = ref('') as any // 展示的年 let showYear = ref('') as any // 选择的季度 let quarterIndex = ref(0) // 是否展示年份列表 let isEditYear = ref(false) // 年份列表开始年份 let startYear = ref('') as any // 年份列表 let yearList = reactive([] as any) const quarterTitle = computed(() => { if(isEditYear.value) { return startYear.value+ "年 - " + (startYear.value + 9) + "年" } else { return showYear.value + '年' } }) // 选择某季度 function pickerQuarte(index:number) { quarterIndex.value = index pickerYear.value = showYear.value let oldValue = quarterDate.value // 记录上一次数据 quarterDate.value = pickerYear.value + "-Q" + index emits('update:modelValue', quarterDate.value) // 新老数据不一致,触发change时间 if(oldValue !== quarterDate.value) { emits('change', quarterDate.value) } } // 更改展示的年 function changeShowYear(num: number) { if(isEditYear.value) { startYear.value = startYear.value + (num * 10) // console.log('startYear.value', startYear.value) changeYearList() } else { showYear.value = showYear.value + num } } // 清空选择的数据 function clearData() { quarterDate.value = '' pickerYear.value = '' showYear.value = new Date().getFullYear() quarterIndex.value = 0 } // 选择的数据 function quarterDateChange(value:any) { const splitArray = value.split('-Q') if (splitArray.length < 2) { pickerYear.value = '' showYear.value = new Date().getFullYear() quarterIndex.value = 0 } else { pickerYear.value = splitArray[0] showYear.value = splitArray[0] quarterIndex.value = splitArray[1] } } // 更改年份列表函数 function changeYearList() { yearList = [] let year = startYear.value for (let i = 0; i < 10; i++) { yearList.push(year++) } } // 切换展示年份列表 和 季度 function showYearList() { if(!isEditYear.value) { startYear.value = Number(Math.floor(showYear.value / 10) + '0') changeYearList() isEditYear.value = true } else { isEditYear.value = false } } // 选中某个年份列表 function selectYear(item:any) { showYear.value = item isEditYear.value = false } onMounted(() => { // 初始化展示的年为当前年份 showYear.value = new Date().getFullYear() startYear.value = Number(Math.floor(showYear.value / 10) + '0') changeYearList() }) </script>
<style lang="less"> .el-quarter__header { padding-bottom: 12px; border-bottom: 1px solid #ebeef5; display: flex; align-items: center; justify-content: space-between; .el-quarter-btn { font-size: 12px; } .el-quarter__header-text { font-size: 16px; font-weight: 500; text-align: center; cursor: pointer; } } .el-quarter__content { min-height: 100px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: space-around; .el-quarter__row { display: flex; justify-content: space-around; .quarter-index { display: flex; padding: 4px 10px; width: fit-content; cursor: pointer; &:hover { color: #337ecc } } .is-active { color: #409eff } } } .el-quarter-clear { position: relative; color: #909399; display: none; height: 12px; width: 12px; cursor: pointer; &::after { content: ''; position: absolute; height: 14px; width: 14px; margin: auto; border-radius: 50%; border: 1px solid #909399 } } .el-input { &:hover { .el-quarter-clear { display: flex; } } } .el-year__content { min-height: 100px; display: flex; padding: 10px 0; flex-wrap: wrap; .el-year-item { width: calc(100% / 4); display: flex; align-items: center; justify-content: center; .cell { padding: 4px 10px; width: fit-content; cursor: pointer; cursor: pointer; white-space: nowrap; &:hover { color: #337ecc } } .is-active { color: #409eff } } }</style>
2.父组件
<ElQuarter style="width: 320px;" v-model="quarteDate" @change="quarterChange" />
- 季度 element vue3 vue季度element vue3 vue vue3-element-admin vue3-element-plus element vue3 plus vue element-plus element eslint vue3 element-icon element vue3 icon element-plus element vue3 plus vue3-element-admin lint-staged commitlint commitizen element-plus表格element vue3 vue3-element-admin element-plus typescript后台