DateRangePicker 日期范围选择器,基于 el-date-picker 封装,默认按月选择,自动补齐首尾日期。
快速使用
bash
<DateRangePicker v-model="dateRange" />
<DateRangePicker v-model="dateRange" type="daterange" />
<DateRangePicker v-model="dateRange" type="yearrange" />
Props
bash
modelValue Array v-model 绑定值,格式 ['YYYY-MM-DD', 'YYYY-MM-DD']
type String 选择类型:'monthrange'(默认) | 'daterange' | 'yearrange'
valueFormat String 输出日期格式,默认 'YYYY-MM-DD'
clearable Boolean 是否可清空,默认 false
autoDefault Boolean 无值时自动填入本年度,默认 true;设为 false 则不填
startPlaceholder String 开始日期占位,默认 '开始日期'
endPlaceholder String 结束日期占位,默认 '结束日期'
默认行为
bash
- 默认选中本年度(1月1日 ~ 12月31日)
- 月模式:选中"1月→3月"自动返回 ['2026-01-01', '2026-03-31']
- 年模式:选中"2024→2025"自动返回 ['2024-01-01', '2025-12-31']
- 不可清空(可传入 clearable 开启)
- 支持 $attrs 透传(disabledDate、size 等原生属性)
bash
<template>
<el-date-picker
v-model="innerValue"
:type="type"
:value-format="innerValueFormat"
:clearable="clearable"
range-separator="-"
:start-placeholder="startPlaceholder"
:end-placeholder="endPlaceholder"
v-bind="$attrs"
/>
</template>
<script setup>
import { computed, onMounted } from 'vue';
defineOptions({ name: 'DateRangePicker' });
const props = defineProps({
modelValue: { type: Array, default: () => [] },
// 类型:monthrange(默认按月) | daterange(按日) | yearrange(按年)
type: { type: String, default: 'monthrange' },
valueFormat: { type: String, default: 'YYYY-MM-DD' },
clearable: { type: Boolean, default: false },
autoDefault: { type: Boolean, default: true }, // 是否自动填入本年度默认值
startPlaceholder: { type: String, default: '开始日期' },
endPlaceholder: { type: String, default: '结束日期' },
});
const emit = defineEmits(['update:modelValue']);
const now = new Date();
const currentYear = now.getFullYear();
// 默认值:本年度 1月1日 ~ 12月31日
const defaultRange = computed(() => {
if (props.type === 'yearrange') return [`${currentYear}`, `${currentYear}`];
return [`${currentYear}-01-01`, `${currentYear}-12-31`];
});
onMounted(() => {
if (props.autoDefault && (!props.modelValue || props.modelValue.length < 2)) {
emit('update:modelValue', [...defaultRange.value]);
}
});
// 内部传给 el-date-picker 的 format
const innerValueFormat = computed(() => {
if (props.type === 'monthrange') return 'YYYY-MM';
if (props.type === 'yearrange') return 'YYYY';
return props.valueFormat;
});
// 获取某月的最后一天
const lastDayOfMonth = (year, month) => new Date(year, month, 0).getDate();
const innerValue = computed({
get() {
if (!props.modelValue || props.modelValue.length < 2) {
if (!props.autoDefault) return null;
// 默认本年度
if (props.type === 'monthrange') return [`${currentYear}-01`, `${currentYear}-12`];
if (props.type === 'yearrange') return [`${currentYear}`, `${currentYear}`];
return [`${currentYear}-01-01`, `${currentYear}-12-31`];
}
if (props.type === 'monthrange') {
// YYYY-MM-DD → YYYY-MM
return props.modelValue.map(v => (v || '').substring(0, 7));
}
if (props.type === 'yearrange') {
// YYYY-MM-DD → YYYY
return props.modelValue.map(v => (v || '').substring(0, 4));
}
return props.modelValue;
},
set(val) {
if (!val || val.length < 2) {
emit('update:modelValue', []);
return;
}
if (props.type === 'monthrange') {
// val = ['2024-01', '2024-03'] → ['2024-01-01', '2024-03-31']
const [endYear, endMonth] = val[1].split('-').map(Number);
const start = `${val[0]}-01`;
const end = `${val[1]}-${String(lastDayOfMonth(endYear, endMonth)).padStart(2, '0')}`;
emit('update:modelValue', [start, end]);
} else if (props.type === 'yearrange') {
// val = ['2024', '2025'] → ['2024-01-01', '2025-12-31']
emit('update:modelValue', [`${val[0]}-01-01`, `${val[1]}-12-31`]);
} else {
emit('update:modelValue', val);
}
}
});
</script>