目录
功能点
组件图示
常用
自定义
源码
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 标签页 | ![](https://i-blog.csdnimg.cn/blog_migrate/bd0fbf4c6057cfe118e228b6c1a857c1.png) | |
n-date-picker 日期选择框 | 如上效果图右侧的日期选择 | Naive UI提供了只使用面板的属性;更改部分样式 |
Input 输入框 | ![](https://i-blog.csdnimg.cn/blog_migrate/affc18ed277675e147fca711c92d05b7.png) | 设置为只读输入框,且将样式处理为只有下边框的样式; 自定义日期里的输入框依旧是可输入的,且将样式处理为只有下边框的样式 |
常用快捷日期文本对应
显示文本 | 传给后台的值 |
今日 | 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为输入的数组)
- 这里的所有输入框均设置了校验,只能输入正整数