目录
功能点
组件图示
常用
自定义
源码
TDatePicker
TRangePicker
调用方式
参数列表
常用快捷日期文本对应
自定义日期
功能点
- 支持快速选择常用的日期或日期范围
- 可自定义选择的日期范围
- 手动选择想要的日期范围
组件图示
常用

自定义

源码
TDatePicker
<!--TDatePicker--> <template> <div class="date_body"> <div class="tangent-date-picker" ref="tangentDatePicker" style="width: 100%"> <a-popover trigger="click" placement="bottomLeft" v-model:visible="visible" overlayClassName="popover-range-picker-dropdown" :getPopupContainer="(node) => node.parentNode || document.body" > <template #content> <TRangePicker :prop-dynamic="dynamic" :prop-range-date="rangeDate" :prop-dynamic-type="dynamicType" :prop-cus-date-active="customizeActive" @changeDate="changeDate" /> </template> <a-input readOnly @click="showDatePicker" v-model:value="value" :bordered="false" size="small" class="inputClass" :placeholder="placeholder" :style="{ fontSize: inputSpanFontSize }" /> </a-popover> </div> </div> </template> <script lang="ts"> import { defineComponent, ref, watch } from 'vue'; import dayjs from 'dayjs'; import TRangePicker from './TRangePicker.vue'; export default defineComponent({ name: 'TDatePicker', components: { TRangePicker }, props: { // 左侧常用快捷数据 propDynamic: { type: String, default: '', }, // 快捷日期类型:常用|自定义 propDynamicType: { type: String, default: 'common', }, // 自定义快捷日期高亮 propCusDateActive: { type: String, default: '', }, // 日期 propRangeDate: { type: Array, default: () => { return [ dayjs(dayjs().startOf('day').subtract(6, 'days').format('YYYY-MM-DD')), dayjs(dayjs().format('YYYY-MM-DD')), ]; }, }, placeholder: { type: String, default: ' - ', }, inputSpanFontSize: { type: String, default: '12px', }, }, setup(props, context) { // 初始近7日 const rangeDate = ref(); let tempDate = JSON.parse(JSON.stringify(props.propRangeDate)); if (tempDate[0] !== '' && tempDate[1] !== '') { rangeDate.value = [ dayjs(tempDate[0]).format('YYYY-MM-DD'), dayjs(tempDate[1]).format('YYYY-MM-DD'), ]; } else { rangeDate.value = ['', '']; } const value = ref<string>(''); // 日期范围 if (rangeDate.value[0] && rangeDate.value[1]) { value.value = rangeDate.value.join(' - '); } // 初始快捷日期,包含常用和自定义 const dynamic = ref(''); dynamic.value = JSON.parse(JSON.stringify(props.propDynamic)); // 是常用还是自定义日期 const dynamicType = ref('common'); dynamicType.value = JSON.parse(JSON.stringify(props.propDynamicType)); // 自定义日期高亮文本 const customizeActive = ref(''); customizeActive.value = JSON.parse(JSON.stringify(props.propCusDateActive)); // 点击显示日期选择器 const visible = ref(false); function showDatePicker() { visible.value = true; } function hideDatePicker() { visible.value = false; } // 子组件日期选择反馈 function changeDate(tempVal, isHideDatePicker) { if (isHideDatePicker) { hideDatePicker(); } dynamic.value = tempVal.dynamic; rangeDate.value = tempVal.rangeDate; dynamicType.value = tempVal.dynamicType; customizeActive.value = tempVal.customizeActive ? tempVal.customizeActive : ''; value.value = tempVal.rangeDate.join(' - '); // 将选择的日期反馈回父组件 context.emit('changeDate', tempVal); } function setDateInfo() { let tempDate = JSON.parse(JSON.stringify(props.propRangeDate)); if (tempDate[0] !== '' && tempDate[1] !== '') { rangeDate.value = [ dayjs(tempDate[0]).format('YYYY-MM-DD'), dayjs(tempDate[1]).format('YYYY-MM-DD'), ]; } else { rangeDate.value = ['', '']; } // 日期范围 if (rangeDate.value[0] && rangeDate.value[1]) { value.value = rangeDate.value.join(' - '); } else { value.value = ''; } dynamic.value = JSON.parse(JSON.stringify(props.propDynamic)); dynamicType.value = JSON.parse(JSON.stringify(props.propDynamicType)); customizeActive.value = JSON.parse(JSON.stringify(props.propCusDateActive)); } watch( () => props.propRangeDate, () => { setDateInfo(); }, ); return { value, rangeDate, dynamic, dynamicType, customizeActive, changeDate, // 日期选择器的显示与隐藏 visible, showDatePicker, hideDatePicker, }; }, }); </script> <style scoped> .date_body { display: inline-block; border: 1px solid #d9d9d9; background-color: #fff; height: 32px; border-radius: 4px; line-height: 32px; margin-left: 5px; /*text-align: center;*/ /*width: 150px;*/ width: 260px; text-align: left; &:hover { border: 1px solid #85a5ff; } } .tangent-date-picker .ant-input { border-top-color: transparent !important; border-left-color: transparent !important; border-right-color: transparent !important; /*border-bottom: 1px solid #d9d9d9 !important;*/ border-top: 0 !important; border-left: 0 !important; border-right: 0 !important; } .tangent-date-picker .ant-input:hover { border-top-color: transparent !important; border-left-color: transparent !important; border-right-color: transparent !important; border-bottom-color: rgb(89, 126, 247) !important; border-top: 0 !important; border-left: 0 !important; border-right: 0 !important; } /*:deep(.tangent-date-picker .ant-popover-inner-content) {*/ /* color: rgba(0, 0, 0, 0.85);*/ /* padding: 12px 16px 0px 16px !important;*/ /*}*/ :deep(.popover-range-picker-dropdown .ant-popover-inner) { background-color: #fff; background-clip: padding-box; border-radius: 2px; box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05); box-shadow: 0 0 8px rgba(0, 0, 0, 0.15) \9; } :deep(.popover-range-picker-dropdown .ant-popover-inner-content) { color: rgba(0, 0, 0, 0.85); } </style>
复制
TRangePicker
<!--TRangePicker--> <template> <div class="range-picker" ref="rangePicker"> <div class="quick-date date-packer-opt"> <a-tabs :default-active-key='"common"' v-model:activeKey="activeKey" :centered="true" @change="changeActive" class='tabsClass' size="small"> <a-tab-pane tab='常用' key='common'> <template v-for="(item, index) in commonOptData" :key="index"> <div v-if="index % 2 === 0"> <span class='common-opt' style='margin-right: 8%' @click='commonOptSelect(commonOptData[index])' :class='{"common-opt-select": commonOptActive === commonOptData[index]}'> {{ commonOptData[index] }} </span> <span class='common-opt' @click='commonOptSelect(commonOptData[index + 1])' :class='{"common-opt-select": commonOptActive === commonOptData[index + 1]}'> {{ commonOptData[index + 1] }} </span> </div> </template> </a-tab-pane> <a-tab-pane tab='自定义' key='customize'> <!-- 近n日 --> <div class='Customize-opt' :class='{"Customize-opt-select": customizeActive == "近n日"}'> 近 <span> <a-input size="small" type='text' placeholder='n' v-model:value='customizeDate[0]' @input="customizeChange('近n日')" style="display: inline-block; width: 45px;" class='Customize-opt-input' /> </span> 日 </div> <!-- 过去n日 --> <div class='Customize-opt' :class='{"Customize-opt-select": customizeActive == "过去n日"}'> 过去 <span> <a-input no-border size="small" type='text' placeholder='n' v-model:value='customizeDate[1]' @input="customizeChange('过去n日')" style="display: inline-block; width: 45px;" class='Customize-opt-input' /> </span> 日 </div> <!-- 过去n-m日 --> <div class='Customize-opt' :class='{"Customize-opt-select": customizeActive == "过去n-m日"}'> 过去 <span> <a-input no-border size="small" type='text' placeholder='n' v-model:value='customizeDate[2]' @input="customizeChange('过去n-m日')" style="display: inline-block; width: 45px;" class='Customize-opt-input' /> </span> - <span> <a-input no-border size="small" type='text' placeholder='m' v-model:value='customizeDate[3]' @input="customizeChange('过去n-m日')" style="display: inline-block; width: 45px;" class='Customize-opt-input' /> </span> 日 </div> <!-- 近n月 --> <div class='Customize-opt' :class='{"Customize-opt-select": customizeActive == "近n月"}'> 近 <span> <a-input no-border size="small" type='text' placeholder='n' v-model:value='customizeDate[4]' @input="customizeChange('近n月')" style="display: inline-block; width: 45px;" class='Customize-opt-input' /> </span> 月 </div> <!-- 过去n月 --> <div class='Customize-opt' :class='{"Customize-opt-select": customizeActive == "过去n月"}'> 过去 <span> <a-input no-border size="small" type='text' placeholder='n' v-model:value='customizeDate[5]' @input="customizeChange('过去n月')" style="display: inline-block; width: 45px;" class='Customize-opt-input' /> </span> 月 </div> <!-- 近n年 --> <div class='Customize-opt' :class='{"Customize-opt-select": customizeActive == "近n年"}'> 近 <span> <a-input no-border size="small" type='text' placeholder='n' v-model:value='customizeDate[6]' @input="customizeChange('近n年')" style="display: inline-block; width: 45px;" class='Customize-opt-input' /> </span> 年 </div> <!-- 过去n年 --> <div class='Customize-opt' :class='{"Customize-opt-select": customizeActive == "过去n年"}'> 过去 <span> <a-input no-border size="small" type='text' placeholder='n' v-model:value='customizeDate[7]' @input="customizeChange('过去n年')" style="display: inline-block; width: 45px;" class='Customize-opt-input' /> </span> 年 </div> </a-tab-pane> </a-tabs> </div> <div style="display: inline-flex; border: 1px; margin-top: 5px; height: 270px"> <n-config-provider :locale="zhCN" :date-locale="dateZhCN"> <n-date-picker dropdownClassName="range-picker-dropdown" panel type="daterange" :actions="null" :is-date-disabled="disabledDate" :first-day-of-week="6" @update:value="changeDate" :getPopupContainer="(node) => node.parentNode || document.body" v-model:value="dateValue" /> </n-config-provider> </div> </div> </template> <script> import { NDatePicker, NConfigProvider, zhCN, dateZhCN } from 'naive-ui'; import { defineComponent, ref, onMounted } from 'vue'; import dayjs from 'dayjs'; import { message } from "ant-design-vue"; import locale from "ant-design-vue/es/date-picker/locale/zh_CN"; export default defineComponent({ name: "TRangePicker", components: { NDatePicker, NConfigProvider }, props: { // 左侧常用快捷数据 propDynamic: { type: String, default: '' }, // 快捷日期类型:常用|自定义 propDynamicType: { type: String, default: 'common' }, // 自定义快捷日期高亮 propCusDateActive: { type: String, default: '' }, // 日期值 propRangeDate: { type: Array, default: () => { return [dayjs(dayjs().startOf('day').subtract(6, 'days').format('YYYY-MM-DD')), dayjs(dayjs().format('YYYY-MM-DD'))] } } }, setup(props, context) { // 常用按钮文本数据 const commonOptData = ref() commonOptData.value = [ '今日', '昨日', '本周', '上周', '本月', '上月', '今年', '去年', '近30日', '过去30日', '近90日', '过去90日', ] // 不可选择日期 const disabledDate = (ts) => { // 无法选择今天之后的天数 return ts && ts > dayjs().endOf('day'); }; // 日期 const dateValue = ref() let tempDate = JSON.parse(JSON.stringify(props.propRangeDate)) if (tempDate[0] !== '' && tempDate[1] !== '') { dateValue.value = [dayjs(tempDate[0]).valueOf(), dayjs(tempDate[1]).valueOf()] } else { dateValue.value = null } // const activeKey = ref('common') activeKey.value = JSON.parse(JSON.stringify(props.propDynamicType)) // 常用快捷日期高亮文本 const commonOptActive = ref('') // 自定义日期 const customizeActive = ref('') const customizeDate = ref(['', '', '', '', '', '', '', '']) customizeActive.value = JSON.parse(JSON.stringify(props.propCusDateActive)) // 常用动态日期文本 const dynamicDate = ref('') let tempDynamic = JSON.parse(JSON.stringify(props.propDynamic)) dynamicDate.value = tempDynamic // 根据不同的类型回显 if (activeKey.value === 'common') { // 根据传入的常用快捷日期回显 switchByDynamicText(dynamicDate.value) } else { switchByDynamicTextInCus(dynamicDate.value, customizeActive.value) } // 切换面板的回调 function changeActive(value) { activeKey.value = value } // 常用快捷日期按钮选择 function commonOptSelect(value) { commonOptActive.value = value // 根据选择的快捷常用按钮计算具体的日期值 calculationDateByCommonOpt(value) // 将自定义日期输入框的值置空 customizeDate.value = ['', '', '', '', '', '', '', ''] // 将自定义日期高亮文本置空 customizeActive.value = '' } // 根据选择的快捷常用按钮计算具体的日期值 function calculationDateByCommonOpt (value) { const startDate = ref() const endDate = ref() switch (value) { case '今日': startDate.value = dayjs().format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'near,day,1' break case '昨日': startDate.value = dayjs().startOf('day').subtract(1, 'days').format('YYYY-MM-DD') endDate.value = dayjs().startOf('day').subtract(1, 'days').format('YYYY-MM-DD') dynamicDate.value = 'past,day,1' break case '本周': startDate.value = dayjs().startOf('week').format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'this week' break case '上周': startDate.value = dayjs().startOf('week').subtract(1, 'weeks').format('YYYY-MM-DD') endDate.value = dayjs().endOf('week').subtract(1, 'weeks').format('YYYY-MM-DD') dynamicDate.value = 'last week' break case '本月': startDate.value = dayjs().startOf('month').format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'near,month,1' break case '上月': startDate.value = dayjs().startOf('month').subtract(1, 'months').format('YYYY-MM-DD') endDate.value = dayjs().subtract(1, 'months').endOf('month').format('YYYY-MM-DD') dynamicDate.value = 'past,month,1' break case '今年': startDate.value = dayjs().startOf('year').format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'near,year,1' break case '去年': startDate.value = dayjs().startOf('year').subtract(1, 'years').format('YYYY-MM-DD') endDate.value = dayjs().startOf('year').subtract(1, 'days').format('YYYY-MM-DD') dynamicDate.value = 'past,year,1' break case '近30日': startDate.value = dayjs().startOf('day').subtract(29, 'days').format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'near,day,30' break case '过去30日': startDate.value = dayjs().startOf('day').subtract(30, 'days').format('YYYY-MM-DD') endDate.value = dayjs().startOf('day').subtract(1, 'days').format('YYYY-MM-DD') dynamicDate.value = 'past,day,30' break case '近90日': startDate.value = dayjs().startOf('day').subtract(89, 'days').format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'near,day,90' break case '过去90日': startDate.value = dayjs().startOf('day').subtract(90, 'days').format('YYYY-MM-DD') endDate.value = dayjs().startOf('day').subtract(1, 'days').format('YYYY-MM-DD') dynamicDate.value = 'past,day,90' break default: break } // 右侧日期选择器的绑定值 dateValue.value = [dayjs(startDate.value).valueOf(), dayjs(endDate.value).valueOf()] // 传回父组件响应 let param = { rangeDate: [startDate.value, endDate.value], dynamic: dynamicDate.value, dynamicType: activeKey.value } context.emit('changeDate', param, true) } // 根据传入的常用快捷日期回显 function switchByDynamicText (value) { switch (value) { case 'near,day,1': commonOptActive.value = '今日' break case 'past,day,1': commonOptActive.value = '昨日' break case 'this week': commonOptActive.value = '本周' break case 'last week': commonOptActive.value = '上周' break case 'near,month,1': commonOptActive.value = '本月' break case 'past,month,1': commonOptActive.value = '上月' break case 'near,year,1': commonOptActive.value = '今年' break case 'past,year,1': commonOptActive.value = '去年' break case 'near,day,30': commonOptActive.value = '近30日' break case 'past,day,30': commonOptActive.value = '过去30日' break case 'near,day,90': commonOptActive.value = '近90日' break case 'past,day,90': commonOptActive.value = '过去90日' break default: break } } // 根据传入的自定义快捷日期回显 function customizeChange (inputVal) { // 校验规则 let test = '' const startDate = ref() const endDate = ref() // 输入内容 let tempDateNum = '' switch (inputVal) { case '近n日': tempDateNum = customizeDate.value[0] // 校验是否是正整数 test = tempDateNum.replace(/[^\d]/g, '') if (test !== '' && test === tempDateNum && parseInt(tempDateNum) > 0) { startDate.value = dayjs().startOf('day').subtract(parseInt(tempDateNum) - 1, 'days').format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'near,day,' + tempDateNum customizeDate.value = [tempDateNum, '', '', '', '', '', '', ''] } else { if (tempDateNum !== '') { customizeDate.value[0] = '' message.warning('请输入正整数!') } } break case '过去n日': tempDateNum = customizeDate.value[1] // 校验是否是正整数 test = tempDateNum.replace(/[^\d]/g, '') if (test !== '' && test === tempDateNum && parseInt(tempDateNum) > 0) { startDate.value = dayjs().startOf('day').subtract(parseInt(tempDateNum), 'days').format('YYYY-MM-DD') endDate.value = dayjs().startOf('day').subtract(1, 'days').format('YYYY-MM-DD') dynamicDate.value = 'past,day,' + tempDateNum customizeDate.value = ['', tempDateNum, '', '', '', '', '', ''] } else { if (tempDateNum !== '') { customizeDate.value[1] = '' message.warning('请输入正整数!') } } break case '过去n-m日': let tempDateNum3 = customizeDate.value[2] let tempDateNum4 = customizeDate.value[3] // 校验是否是正整数 let test3 = tempDateNum3.replace(/[^\d]/g, '') let test4 = tempDateNum4.replace(/[^\d]/g, '') if ((test3 !== '' && test3 === tempDateNum3 && parseInt(tempDateNum3) > 0) || (test4 !== '' && test4 === tempDateNum4 && parseInt(tempDateNum3) > 0)) { if (tempDateNum3 !== '' && tempDateNum4 !== '' && parseInt(tempDateNum3) > 0 && parseInt(tempDateNum3) > 0) { let min = Math.min(parseInt(tempDateNum3), parseInt(tempDateNum4)) let max = Math.max(parseInt(tempDateNum3), parseInt(tempDateNum4)) startDate.value = dayjs().startOf('day').subtract(max, 'days').format('YYYY-MM-DD') endDate.value = dayjs().startOf('day').subtract(min, 'days').format('YYYY-MM-DD') customizeActive.value = inputVal dynamicDate.value = 'past,day,' + min + ',' + max customizeDate.value = ['', '', tempDateNum3, tempDateNum4, '', '', '', ''] // 将常用日期高亮文本置空 commonOptActive.value = '' // 右侧日期选择器的绑定值 dateValue.value = [dayjs(startDate.value).valueOf(), dayjs(endDate.value).valueOf()] // 传回父组件响应 let param = { rangeDate: [startDate.value, endDate.value], dynamic: dynamicDate.value, dynamicType: activeKey.value } context.emit('changeDate', param, false) } } else { if (tempDateNum3 !== '' || tempDateNum4 !== '') { customizeDate.value[2] = test3 === '' || test3 !== tempDateNum3 || parseInt(tempDateNum3) <= 0 ? '' : customizeDate.value[2] customizeDate.value[3] = test4 === '' || test4 !== tempDateNum4 || parseInt(tempDateNum4) <= 0 ? '' : customizeDate.value[3] message.warning('请输入正整数!') } } break case '近n月': tempDateNum = customizeDate.value[4] // 校验是否是正整数 test = tempDateNum.replace(/[^\d]/g, '') if (test !== '' && test === tempDateNum && parseInt(tempDateNum) > 0) { startDate.value = dayjs().startOf('month').subtract(parseInt(customizeDate.value[4]) - 1, 'months').format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'near,month,' + tempDateNum customizeDate.value = ['', '', '', '', tempDateNum, '', '', ''] } else { if (tempDateNum !== '') { customizeDate.value[4] = '' message.warning('请输入正整数!') } } break case '过去n月': tempDateNum = customizeDate.value[5] // 校验是否是正整数 test = tempDateNum.replace(/[^\d]/g, '') if (test !== '' && test === tempDateNum && parseInt(tempDateNum) > 0) { startDate.value = dayjs().startOf('month').subtract(parseInt(tempDateNum), 'months').format('YYYY-MM-DD') endDate.value = dayjs().startOf('month').subtract(0, 'months').subtract(1, 'days').format('YYYY-MM-DD') dynamicDate.value = 'past,month,' + tempDateNum customizeDate.value = ['', '', '', '', '', tempDateNum, '', ''] } else { if (tempDateNum !== '') { customizeDate.value[5] = '' message.warning('请输入正整数!') } } break case '近n年': tempDateNum = customizeDate.value[6] // 校验是否是正整数 test = tempDateNum.replace(/[^\d]/g, '') if (test !== '' && test === tempDateNum && parseInt(tempDateNum) > 0) { startDate.value = dayjs().startOf('year').subtract(parseInt(tempDateNum) - 1, 'years').format('YYYY-MM-DD') endDate.value = dayjs().format('YYYY-MM-DD') dynamicDate.value = 'near,year,' + tempDateNum customizeDate.value = ['', '', '', '', '', '', tempDateNum, ''] } else { if (tempDateNum !== '') { customizeDate.value[6] = '' message.warning('请输入正整数!') } } break case '过去n年': tempDateNum = customizeDate.value[7] // 校验是否是正整数 test = tempDateNum.replace(/[^\d]/g, '') if (test !== '' && test === tempDateNum && parseInt(tempDateNum) > 0) { startDate.value = dayjs().startOf('year').subtract(parseInt(tempDateNum), 'years').format('YYYY-MM-DD') endDate.value = dayjs().startOf('year').subtract(0, 'years').subtract(1, 'days').format('YYYY-MM-DD') dynamicDate.value = 'past,year,' + tempDateNum customizeDate.value = ['', '', '', '', '', '', '', tempDateNum] } else { if (tempDateNum !== '') { customizeDate.value[7] = '' message.warning('请输入正整数!') } } break default: break } // 校验通过才能继续 if (test !== '' && test === tempDateNum && inputVal !== '过去n-m日') { // 右侧日期选择器的绑定值 dateValue.value = [dayjs(startDate.value).valueOf(), dayjs(endDate.value).valueOf()] customizeActive.value = inputVal // 将常用日期高亮文本置空 commonOptActive.value = '' // 传回父组件响应 let param = { rangeDate: [startDate.value, endDate.value], dynamic: dynamicDate.value, dynamicType: activeKey.value, customizeActive: customizeActive.value } context.emit('changeDate', param, false) } } // 根据传入的自定义快捷日期回显 function switchByDynamicTextInCus (tempDate, activeVal) { let tempText = tempDate.split(',') switch (activeVal) { case '近n日': dynamicDate.value = 'near,day,' + tempText[2] customizeDate.value = [tempText[2], '', '', '', '', '', '', ''] break case '过去n日': dynamicDate.value = 'past,day,' + tempText[2] customizeDate.value = ['', tempText[2], '', '', '', '', '', ''] break case '过去n-m日': dynamicDate.value = 'past,day,' + tempText[2] + ',' + tempText[3] customizeDate.value = ['', '', tempText[3], tempText[2], '', '', '', ''] break case '近n月': dynamicDate.value = 'near,month,' + tempText[2] customizeDate.value = ['', '', '', '', tempText[2], '', '', ''] break case '过去n月': dynamicDate.value = 'past,month,' + tempText[2] customizeDate.value = ['', '', '', '', '', tempText[2], '', ''] break case '近n年': dynamicDate.value = 'near,year,' + tempText[2] customizeDate.value = ['', '', '', '', '', '', tempText[2], ''] break case '过去n年': dynamicDate.value = 'past,year,' + tempText[2] customizeDate.value = ['', '', '', '', '', '', '', tempText[2]] break default: break } } // 右侧的日期选择器日期发生变化的回调 function changeDate (date, dateString) { // 常用快捷日期按钮选择置空 commonOptActive.value = '' dynamicDate.value = '' // console.log(date) // console.log(dateString) // 传回父组件响应 let param = { rangeDate: dateString, dynamic: dynamicDate.value } context.emit('changeDate', param, false) } function panelChange(value) { console.log(value) } onMounted(() => { }) return { zhCN, dateZhCN, locale, dateValue, // 不可选择日期 disabledDate, // 日期发生变化的回调 changeDate, panelChange, // 标签页绑定值 activeKey, changeActive, // 当前选择的常用按钮 commonOptActive, // 常用快捷按钮文本 commonOptData, // 快捷常用按钮日期选择 commonOptSelect, // 自定义日期 customizeChange, customizeActive, customizeDate } } }); </script> <style scoped> /*--------------------------------左侧快捷选择日期模块样式-----------------------------*/ .quick-date { width: 200px; height: 270px; display: inline-flex; position: relative; } .date-packer-opt { background: #ecf3f8; border-right: 1px solid #e4eaf1; overflow: hidden; padding: 5px; -webkit-box-sizing: border-box; box-sizing: border-box; z-index: 0; /*box-shadow: 0px 0px 18px 0 rgba(0,0,0,.14);*/ position: relative; top: 0px; } /*------------------------标签页 样式 开始------------------------*/ .tabsClass { background-color: #ECF3F8; padding-left:10px; font-size: 13px; width: 100%; /*margin-top: 5px;*/ } :deep(.tabsClass .ant-tabs-nav) { position: relative; display: flex; flex: none; align-items: center; height: 30px !important; margin: 0 0 6px 0 !important; } /*-----------标签页文本------------*/ :deep(.tabsClass .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) { color: #597EF7 !important; text-shadow: 0 0 0.25px currentcolor; /*padding: 0 17px;*/ } /*-----------标签页激活的下杠线------------*/ :deep(.tabsClass .ant-tabs-ink-bar) { position: absolute; background: #597EF7 !important; pointer-events: none; } /*-----------常用标签页内的按钮样式------------*/ .common-opt { display: inline-block; width: 43%; padding: 3px 0; margin: 6px 0; cursor: pointer; font-size: 12px; background-color: #fff; text-align: center; border-radius: 20px; } .common-opt:hover{ background-color: #688ff4; color: #FFFFFF; } .common-opt-select { display: inline-block; width: 43%; padding: 3px 0; margin: 6px 0; cursor: pointer; font-size: 12px; background-color: #688FF4; color: white; text-align: center; border-radius: 20px; } /*------------------------常用标签页的按钮 样式 结束------------------------*/ /*------------------------自定义标签页的按钮 样式 开始------------------------*/ .Customize-opt { background-color: #fff; height: 25px; width: 179px; text-align:center; border-radius:20px; margin-bottom: 8px } .Customize-opt-select { background-color: #fff; height: 25px; width: 179px; text-align: center; border-radius: 20px; margin-bottom: 8px; border: 1px solid #688FF4; } /*-------输入框边框只留下bottom--------*/ .Customize-opt-input { display: inline-block; width: 45px; border-right: none; border-top: none; border-left: none; } /*-------自定义输入框文本居中显示--------*/ .ant-input { text-align: center; } /*-------自定义输入框提示语n居中显示--------*/ .ant-input:placeholder-shown { text-overflow: ellipsis; text-align: center; } /*-------------------------------右侧日期面板样式-----------------------------------*/ /*----------------当天日期的右上角圆点-------------------*/ :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--current .n-date-panel-date__sup) { position: absolute; top: 1px; right: 1px; content: ""; height: 5px; width: 5px; border-radius: 50%; background-color: #688ff4; } :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date--excluded) { /*opacity: 0;*/ } /*--------------选择择的开始、结束日期样式-----------------*/ :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--selected:not(.n-date-panel-date--excluded)::after) { background-color: #688ff4 !important; } :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--selected.n-date-panel-date--start:not(.n-date-panel-date--excluded)::after) { background-color: #688ff4 !important; margin-right: -1px; } :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--selected.n-date-panel-date--end:not(.n-date-panel-date--excluded)::after) { background-color: #688ff4 !important; margin-left: -1px; } /*-----------选择的开始日期左半圆----------*/ :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date--start:not(.n-date-panel-date--excluded)) { border-bottom-left-radius: 50%; border-top-left-radius: 50%; } /*-----------选择的结束日期右半圆----------*/ :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date--end:not(.n-date-panel-date--excluded)) { border-bottom-right-radius: 50%; border-top-right-radius: 50%; } /*-----------选择的非开始、结束日期的背景颜色----------*/ :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--covered:not(.n-date-panel-date--excluded)::before) { background-color: #688ff4 !important; margin-left: 7px; padding: 0 1px; width: 26px; } :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--start:not(.n-date-panel-date--excluded)::before) { background-color: #688ff4 !important; display: none; } :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--end:not(.n-date-panel-date--excluded)::before) { background-color: #688ff4 !important; display: none; } /*-----------选择的非开始、结束日期的文本颜色----------*/ :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date--covered:not(.n-date-panel-date--excluded)) { color: #ffffff; } /*-----------面板宽度----------*/ :deep(.n-date-panel .n-date-panel-calendar) { width: 210px; } /*-----------面板首行年月行样式----------*/ :deep(.n-date-panel .n-date-panel-month) { width: 195px; margin-bottom: 7px; font-size: 13px; margin-top: -5px; } :deep(.n-date-panel .n-date-panel-month .n-date-panel-month__month-year .n-date-panel-month__text) { padding: 0; font-size: 12px; color: #4C6072; font-family: sans-serif; } /*-----------面板星期行样式----------*/ :deep(.n-date-panel .n-date-panel-weekdays) { display: block; margin-bottom: 3px; border: unset; } :deep(.n-date-panel .n-date-panel-weekdays .n-date-panel-weekdays__day) { width: 26px; display: inline-flex; color: #c5ced8; font-size: 13px; } /*-----------面板具体日期样式----------*/ :deep(.n-date-panel .n-date-panel-dates) { margin: auto; display: flex; align-items: center; justify-items: center; flex-wrap: wrap; width: 200px; height: 200px; } :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date) { width: 26px; display: inline-table; } /*-----------两个面板之间的竖线隐藏----------*/ :deep(.n-date-panel .n-date-panel__vertical-divider) { display: none; } /*-----------不可选日期样式----------*/ :deep(.n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--disabled) { cursor: not-allowed; color: #C5CED8; background-color: #ECF3F8; } </style>
复制
调用方式
<TDatePicker :input-span-font-size="'14px'" :prop-dynamic="dynamic" :prop-cus-date-active="customizeActive" :prop-dynamic-type="dynamicType" :prop-range-date="rangeDate" @changeDate="changeDate" /> <!-- js部分--> // 初始快捷日期,包含常用和自定义,例如 'near,day,30',表示近30日 const dynamic = ref(''); // 快捷日期类型:常用common|自定义customize const dynamicType = ref('common'); // 自定义快捷日期高亮文本,例如 '近n日' const customizeActive = ref(''); // 日期,初始为近7日 const rangeDate = ref([ dayjs().startOf('day').subtract(6, 'days').format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD'), ]); // 选择日期后的回显 function changeDate(tempVal) { dynamic.value = tempVal.dynamic; customizeActive.value = tempVal.customizeActive ? tempVal.customizeActive : ''; dynamicType.value = tempVal.dynamicType; rangeDate.value = tempVal.rangeDate; }
复制
参数列表
参数名 | 类型 | 必传 | 说明 |
propRangeDate | array | ✔️ | 日期,例如['2023-01-01', '2023-03-01'] |
propDynamicType | String | ✔️ | 快捷日期类型:常用common|自定义customize |
propDynamic | String | ✔️ | 快捷日期数据,例如 'near,day,30',表示近30日 |
propCusDateActive | String | ✔️ | 自定义快捷日期高亮,例如 '近n日',用于高亮样式显示 |
使用到的组件:除了日期面板外,都是使用的ant-design-vue中的组件;日期面板使用的是Naive UI
组件 | 图示 | 备注 |
Popover 气泡卡片 | 如上示的效果图的悬浮显示效果 | |
Tabs 标签页 | | |
n-date-picker 日期选择框 | 如上效果图右侧的日期选择 | Naive UI提供了只使用面板的属性;更改部分样式 |
Input 输入框 | ![]() | 设置为只读输入框,且将样式处理为只有下边框的样式; 自定义日期里的输入框依旧是可输入的,且将样式处理为只有下边框的样式 |
常用快捷日期文本对应
显示文本 | 传给后台的值 |
今日 | near,day,1 |
昨日 | past,day,1 |
本周 | this week |
上周 | last week |
本月 | near,month,1 |
上月 | past,month,1 |
今年 | near,year,1 |
去年 | past,year,1 |
近30日 | near,day,30 |
过去30日 | past,day,30 |
近90日 | near,day,90 |
过去90日 | past,day,90 |
自定义日期
- 过去n-m日:past,day,min,max (min、max分别为输入的两个数值,小的在前,大的在后)
- 其他的与常用类似,比如 过去n日,也就是 past,day,n ; 近n月,也就是 near,month,n (n为输入的数组)
- 这里的所有输入框均设置了校验,只能输入正整数