组件代码
<template>
<van-popup v-model:show="props.visible" position="bottom" @close="closePopup">
<van-picker v-bind="$attrs" :columns="columns" @change="onChange" @confirm="onConfirm" @cancel="closePopup" />
</van-popup>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs'
import { ref, computed } from 'vue'
interface IProps {
/** 窗口是否显示 */
visible: boolean
/** 时间段 */
dates?: Date[]
/** 分割符 */
apart?: string
/** 最大年限 */
maxDate?: Date
/** 最小年限 */
minDate?: Date
/** 显示的格式 */
format?: string
/** 是否显示日期 */
showDate?: boolean
/** 是否显示 小时 */
showHour?: boolean
}
type dateType = {
startYear: string
startMonth: string
startDate: string
startHour: string
startMinute: string
endYear: string
endMonth: string
endDate: string
endHour: string
endMinute: string
}
/** 最终返回的结果 */
const timeValue = ref<string[]>([])
const props = withDefaults(defineProps<IProps>(), {
apart: '~',
minDate: () => new Date('2020/01/01 00:00'),
maxDate: () => new Date('2099/12/31 23:59'),
showDate: true,
showHour: false,
format: 'YYYY-MM-DD',
dates: () => {
return [new Date(), new Date()]
}
})
const emit = defineEmits<{
(e: 'update:visible', value: Boolean): void
(e: 'confirm', value: string[]): void
}>()
/** 配置列 */
interface column {
values: string[] | number[] | string
defaultIndex: number
}
/** 根据最小数值 、最大数值 得到一个数组 */
function getArray(min: number, max: number) {
const arr: string[] = []
for (let i = min; i <= max; i++) {
arr.push((i + '').padStart(2, '0'))
}
return arr
}
/** 根据开始日期,结束日期 需要格式 */
function getResult(start: string | Date, end: string | Date): dateType {
/** 开始日期*/
const startDate = dayjs(start)
/** 结束日期 */
const endDate = dayjs(end)
return {
startYear: startDate.format('YYYY'),
startMonth: startDate.format('MM'),
startDate: startDate.format('DD'),
startHour: startDate.format('HH'),
startMinute: startDate.format('mm'),
endYear: endDate.format('YYYY'),
endMonth: endDate.format('MM'),
endDate: endDate.format('DD'),
endHour: endDate.format('HH'),
endMinute: endDate.format('mm')
} as dateType
}
/** 得到最终的格式 */
const result = computed(() => {
if (props.dates.length !== 2) throw new Error('时间格式错误')
return getResult(props.dates[0], props.dates[1])
})
const list = computed(() => {
return getResult(props.minDate, props.maxDate)
})
/** 年份 */
const years = computed(() => {
return getArray(Number(list.value.startDate), Number(list.value.endYear))
})
/** 月份 */
const months = computed(() => {
return getArray(Number(list.value.startMonth), Number(list.value.endMonth))
})
/** 天数 */
const days = computed(() => {
return getArray(Number(list.value.startDate), Number(list.value.endDate))
})
/** 小时 */
const hours = computed(() => {
return getArray(Number(list.value.startHour), Number(list.value.endHour))
})
/** 分钟 */
const minutes = computed(() => {
return getArray(Number(list.value.startMinute), Number(list.value.endMinute))
})
const columns = computed(() => {
/** 开始年份 */
const startYear: column = { values: years.value, defaultIndex: years.value.findIndex((e) => e === result.value.startYear) }
/** 结束年份 */
const endYear: column = { values: years.value, defaultIndex: years.value.findIndex((e) => e === result.value.endYear) }
/** 开始月份 */
const startMonth: column = { values: months.value, defaultIndex: Number(result.value.startMonth) - 1 }
/** 结束月份 */
const endMonth: column = { values: months.value, defaultIndex: Number(result.value.endMonth) - 1 }
/** 开始天数 */
const startDay: column = { values: days.value, defaultIndex: Number(result.value.startDate) - 1 }
/** 结束天数 */
const endDay: column = { values: days.value, defaultIndex: Number(result.value.endDate) - 1 }
/** 开始 小时 */
const startHour: column = { values: hours.value, defaultIndex: Number(result.value.startHour) }
/** 开始 小时 */
const endHour: column = { values: hours.value, defaultIndex: Number(result.value.endHour) }
/** 开始 小时 */
const startMinute: column = { values: minutes.value, defaultIndex: Number(result.value.startMinute) }
/** 开始 小时 */
const endMinute: column = { values: minutes.value, defaultIndex: Number(result.value.endMinute) }
let columns: column[] = []
if (props.showDate) {
columns = [startYear, startMonth, startDay]
}
if (props.showHour) {
columns = [...columns, startHour, startMinute]
}
columns.push({ values: [props.apart], defaultIndex: 0 })
if (props.showDate) {
columns = [...columns, endYear, endMonth, endDay]
}
if (props.showHour) {
columns = [...columns, endHour, endMinute]
}
return columns
})
/** 选择时间段取消事件 */
function closePopup() {
emit('update:visible', false)
}
/** 日期格式化 */
function dateFormat(date: string | Date) {
return dayjs(date).format(props.format)
}
/** 选择时间段确认事件 */
function onConfirm() {
if (timeValue.value.length > 0) {
emit('confirm', timeValue.value)
} else {
emit('confirm', [dateFormat(props.dates[0]), dateFormat(props.dates[1])])
}
closePopup()
}
/** 选择时间段值改变事件 */
function onChange(values: string[]) {
let start = ''
let end = ''
if (props.showDate && props.showHour) {
const [startYear, startMonth, startDate, startHour, startMinute, apart, endYear, endMonth, endDate, endHour, endMinute] = values
start = `${startYear}/${startMonth}/${startDate} ${startHour}:${startMinute}`
end = `${endYear}/${endMonth}/${endDate} ${endHour}:${endMinute}`
} else if (props.showDate && !props.showHour) {
const [startYear, startMonth, startDate, apart, endYear, endMonth, endDate] = values
start = `${startYear}/${startMonth}/${startDate}`
end = `${endYear}/${endMonth}/${endDate}`
} else if (props.showHour && !props.showDate) {
const [startHour, startMinute, apart, endHour, endMinute] = values
start = `2011/1/1 ${startHour}:${startMinute}`
end = `2011/1/1 ${endHour}:${endMinute}`
}
timeValue.value = [dateFormat(start), dateFormat(end)]
}
</script>
代码示例
<template>
<PickerDateTimeRangeVue v-model:visible="dateVisible" :dates="defaultDate" @confirm="(values:string[])=>showDate=values.join('~')" />
<template>
<script lang="ts" setup>
import { ref, watch, onBeforeMount } from 'vue'
/** 选择日期是否显示 */
const dateVisible = ref(false)
const defaultDate = ref<Date[]>([new Date(startDate), new Date(endDate)])
/** 日期查询条件 */
const startDate = dayjs().add(-7, 'days').format('YYYY-MM-DD')
const endDate = dayjs().add(-1, 'days').format('YYYY-MM-DD')
const showDate = ref(`${startDate}~${endDate}`)
</script>
ui效果
image.png
参数
参数 |
说明 |
类型 |
可选值 |
默认值 |
visible |
窗口是否显示 |
boolean |
true/false |
false |
dates |
日期段 |
Date[] |
- |
[new Date(), new Date()] |
apart |
中间分割符 |
string |
- |
~ |
maxDate |
最大日期 |
Date |
- |
new Date('2099/12/31 23:59') |
minDate |
最小日期 |
Date |
- |
new Date('2020/01/01 00:00') |
format |
日期格式化格式 |
string |
- |
YYYY-MM-DD |
showDate |
是否显示日期 |
boolean |
- |
true |
showHour |
是否显示小时 |
boolean |
- |
false |
事件
事件名称 |
说明 |
回调参数 |
update:visible |
关闭窗口 |
是否关闭窗口(true /false) |
confirm |
确认事件 |
返回一个数组 |
网友评论