SelectRangePicker/index.vue
<template>
<div class="flex justify-start items-center w-full" :value="props.value">
<div class="max-w-22">
<Select
:options="optionsValue"
v-model:value="timeSelectValue"
@change="handleSelectChange"
dropdown-class-name="time-picker-select"
:allow-clear="false"
/>
</div>
<RangePicker v-model:value="timePickerValue" @change="handlePickerChange" :show-time="true" />
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { RangePicker, Select } from 'ant-design-vue';
import { timeRangeSelectOptions, TimeRangeText, TimeRangeValues, SelectOptions } from './data';
import { getTimeRangeString, RangeValue } from './utils/time';
const props = defineProps({
value: Array as unknown as PropType<RangeValue>,
options: {
type: Array as unknown as PropType<SelectOptions[]>,
default: timeRangeSelectOptions,
},
rangeOptions: {
type: Array as unknown as PropType<Recordable>,
default: TimeRangeValues,
},
});
const emit = defineEmits(['update:value', 'change']);
const optionsValue = ref(props.options);
const timeSelectValue = ref(TimeRangeText.CUSTOM);
const timePickerValue = ref<RangeValue | undefined>(props.rangeOptions[TimeRangeText.TODAY]);
watch(
() => props.value,
() => {
if (props.value) {
timePickerValue.value = props.value;
timeSelectValue.value = TimeRangeText.CUSTOM;
for (const key of Object.keys(props.rangeOptions)) {
if (
key !== TimeRangeText.CUSTOM &&
getTimeRangeString(props.rangeOptions[key]) ===
getTimeRangeString(timePickerValue.value)
) {
timeSelectValue.value = key as TimeRangeText;
break;
}
}
}
},
);
function handleSelectChange(val: TimeRangeText) {
timePickerValue.value = props.rangeOptions[val];
emit('update:value', timePickerValue.value);
emit('change', timePickerValue.value);
}
function handlePickerChange() {
timeSelectValue.value = TimeRangeText.CUSTOM;
emit('update:value', timePickerValue.value);
emit('change', timePickerValue.value);
}
</script>
<style lang="less" scoped>
//时间选择 禁用样式
:deep(.ant-picker-disabled) {
.ant-picker-input > input[disabled] {
color: unset;
}
}
</style>
SelectRangePicker/data.ts 用于定义需要用到的时间选择类型
import { DefaultTimeRange } from '/@/utils/dataProcessing/time';
export type SelectOptions = { label: string; value: string };
export enum TimeRangeText {
BEFORE_YESTERDAY = '前天',
YESTERDAY = '昨天',
TODAY = '今天',
THREE_DAY = '近三天',
ONE_WEEK = '近一周',
TWO_WEEK = '近两周',
ONE_MONTH = '近一月',
THREE_MONTH = '近三月',
HALF_YEAR = '近半年',
ONE_YEAR = '近一年',
CUSTOM = '自定义',
ONE_HOUR = '1小时',
TWELVE_HOUR = '12小时',
TWENTY_FOUR_HOUR = '24小时',
SEVEN_DAY = '7天',
THIRTY_DAY = '30天',
}
export const TimeRangeValues = {
[TimeRangeText.TODAY]: DefaultTimeRange.TODAY,
[TimeRangeText.THREE_DAY]: DefaultTimeRange.THREE_DAY,
[TimeRangeText.ONE_WEEK]: DefaultTimeRange.ONE_WEEK,
[TimeRangeText.TWO_WEEK]: DefaultTimeRange.TWO_WEEK,
[TimeRangeText.ONE_MONTH]: DefaultTimeRange.ONE_MONTH,
[TimeRangeText.THREE_MONTH]: DefaultTimeRange.THREE_MONTH,
[TimeRangeText.HALF_YEAR]: DefaultTimeRange.HALF_YEAR,
[TimeRangeText.ONE_YEAR]: DefaultTimeRange.ONE_YEAR,
[TimeRangeText.CUSTOM]: undefined,
};
export const timeRangeSelectOptions: SelectOptions[] = [
{ label: TimeRangeText.TODAY, value: TimeRangeText.TODAY },
{ label: TimeRangeText.THREE_DAY, value: TimeRangeText.THREE_DAY },
{ label: TimeRangeText.ONE_WEEK, value: TimeRangeText.ONE_WEEK },
{ label: TimeRangeText.TWO_WEEK, value: TimeRangeText.TWO_WEEK },
{ label: TimeRangeText.ONE_MONTH, value: TimeRangeText.ONE_MONTH },
{ label: TimeRangeText.THREE_MONTH, value: TimeRangeText.THREE_MONTH },
{ label: TimeRangeText.HALF_YEAR, value: TimeRangeText.HALF_YEAR },
{ label: TimeRangeText.ONE_YEAR, value: TimeRangeText.ONE_YEAR },
{ label: TimeRangeText.CUSTOM, value: TimeRangeText.CUSTOM },
];
export const TimeRangeValuesWithBefore = {
[TimeRangeText.TODAY]: DefaultTimeRange.TODAY,
[TimeRangeText.YESTERDAY]: DefaultTimeRange.YESTERDAY,
[TimeRangeText.BEFORE_YESTERDAY]: DefaultTimeRange.BEFORE_YESTERDAY,
[TimeRangeText.THREE_DAY]: DefaultTimeRange.THREE_DAY,
[TimeRangeText.ONE_WEEK]: DefaultTimeRange.ONE_WEEK,
[TimeRangeText.TWO_WEEK]: DefaultTimeRange.TWO_WEEK,
[TimeRangeText.ONE_MONTH]: DefaultTimeRange.ONE_MONTH,
[TimeRangeText.THREE_MONTH]: DefaultTimeRange.THREE_MONTH,
[TimeRangeText.HALF_YEAR]: DefaultTimeRange.HALF_YEAR,
[TimeRangeText.ONE_YEAR]: DefaultTimeRange.ONE_YEAR,
[TimeRangeText.CUSTOM]: undefined,
};
export const timeRangeSelectOptionsWithBefore: SelectOptions[] = [
{ label: TimeRangeText.TODAY, value: TimeRangeText.TODAY },
{ label: TimeRangeText.YESTERDAY, value: TimeRangeText.YESTERDAY },
{ label: TimeRangeText.BEFORE_YESTERDAY, value: TimeRangeText.BEFORE_YESTERDAY },
{ label: TimeRangeText.THREE_DAY, value: TimeRangeText.THREE_DAY },
{ label: TimeRangeText.ONE_WEEK, value: TimeRangeText.ONE_WEEK },
{ label: TimeRangeText.TWO_WEEK, value: TimeRangeText.TWO_WEEK },
{ label: TimeRangeText.ONE_MONTH, value: TimeRangeText.ONE_MONTH },
{ label: TimeRangeText.THREE_MONTH, value: TimeRangeText.THREE_MONTH },
{ label: TimeRangeText.HALF_YEAR, value: TimeRangeText.HALF_YEAR },
{ label: TimeRangeText.ONE_YEAR, value: TimeRangeText.ONE_YEAR },
{ label: TimeRangeText.CUSTOM, value: TimeRangeText.CUSTOM },
];
export const TimeRangeValuesWithHour = {
[TimeRangeText.ONE_HOUR]: DefaultTimeRange.ONE_HOUR,
[TimeRangeText.TWELVE_HOUR]: DefaultTimeRange.TWELVE_HOUR,
[TimeRangeText.TWENTY_FOUR_HOUR]: DefaultTimeRange.TWENTY_FOUR_HOUR,
[TimeRangeText.SEVEN_DAY]: DefaultTimeRange.SEVEN_DAY,
[TimeRangeText.THIRTY_DAY]: DefaultTimeRange.THIRTY_DAY,
[TimeRangeText.CUSTOM]: undefined,
};
export const timeRangeSelectOptionsWithHour: SelectOptions[] = [
{ label: TimeRangeText.ONE_HOUR, value: TimeRangeText.ONE_HOUR },
{ label: TimeRangeText.TWELVE_HOUR, value: TimeRangeText.TWELVE_HOUR },
{ label: TimeRangeText.TWENTY_FOUR_HOUR, value: TimeRangeText.TWENTY_FOUR_HOUR },
{ label: TimeRangeText.SEVEN_DAY, value: TimeRangeText.SEVEN_DAY },
{ label: TimeRangeText.THIRTY_DAY, value: TimeRangeText.THIRTY_DAY },
{ label: TimeRangeText.CUSTOM, value: TimeRangeText.CUSTOM },
];
SelectRangePicker/utils/time 用于处理时间格式
/**
* 时间处理的相关方法
*/
import type { Dayjs } from 'dayjs';
import dayjs from 'dayjs';
import { useNow, useDateFormat } from '@vueuse/core';
export type RangeValue = [Dayjs, Dayjs];
//常用的时间区间
export const DefaultTimeRange = {
BEFORE_YESTERDAY: getTimeRange(2, 2), //前天
YESTERDAY: getTimeRange(1, 1), //昨天
TODAY: getTimeRange(0), //今天
THREE_DAY: getTimeRange(2), //近三天
ONE_WEEK: getTimeRange(6), //近一周
TWO_WEEK: getTimeRange(13), //近两周
ONE_MONTH: getTimeRange(29), //近一个月
THREE_MONTH: getTimeRange(89), //近三个月
HALF_YEAR: getTimeRange(182), //近半年
ONE_YEAR: getTimeRange(364), //近一年
ONE_HOUR: getTimeRangeInHours(1), //1小时
TWELVE_HOUR: getTimeRangeInHours(12), //12小时
TWENTY_FOUR_HOUR: getTimeRangeInHours(24), //24小时
SEVEN_DAY: getTimeRange(6), //7天
THIRTY_DAY: getTimeRange(29), //30天
};
//获取时间区间 往前推n天
export function getTimeRange(day1: number, day2 = 0): RangeValue {
return [
dayjs(`${useDateFormat(useNow(), 'YYYY-MM-DD 00:00:00').value}`).subtract(day1, 'day'),
dayjs(useDateFormat(useNow(), 'YYYY-MM-DD 23:59:59').value).subtract(day2, 'day'),
];
}
// 获取时间区间 往回推n小时
export function getTimeRangeInHours(hours1: number, hours2 = 0): RangeValue {
return [
dayjs(`${useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss').value}`).subtract(hours1, 'hour'),
dayjs(useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss').value).subtract(hours2, 'hour'),
];
}
//将时间区间 处理为 形如 time1 - time2 的字符串
export function getTimeRangeString(range: RangeValue, formatStr = 'YYYY-MM-DD HH:mm:ss'): string {
return `${dayjs(range[0]).format(formatStr)} - ${dayjs(range[1]).format(formatStr)}`;
}
//将时间区间 处理为 两个字段 的字符串数组
export function transTimeRange2FiledMap(range: RangeValue, formatStr = 'YYYY-MM-DD HH:mm:ss') {
return [dayjs(range[0]).format(formatStr), dayjs(range[1]).format(formatStr)];
}
const now = new Date();
const daysArr = [6, 0, 1, 2, 3, 4, 5];
const day = daysArr[now.getDay()]; //计算本周区间 需要往前推的天数
const today: RangeValue = [
dayjs(`${useDateFormat(useNow(), 'YYYY-MM-DD').value} 00:00:00`),
dayjs(useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss').value),
];
const week: RangeValue = [
dayjs(`${useDateFormat(useNow(), 'YYYY-MM-DD').value}`).subtract(day, 'day'),
dayjs(useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss').value),
];
const month: RangeValue = [
dayjs(`${useDateFormat(useNow(), 'YYYY-MM').value}-01 00:00:00`),
dayjs(useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss').value),
];
const year: RangeValue = [
dayjs(`${useDateFormat(useNow(), 'YYYY').value}-01-01 00:00:00`),
dayjs(useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss').value),
];
const quarter: RangeValue = [
getQuarter(),
dayjs(useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss').value),
];
//计算当前季度
function getQuarter(): Dayjs {
const currentMonth: number = new Date().getMonth();
let quarterMonth = '';
if (currentMonth < 3) {
quarterMonth = '01';
} else if (currentMonth >= 3 && currentMonth < 6) {
quarterMonth = '04';
} else if (currentMonth >= 6 && currentMonth < 9) {
quarterMonth = '07';
} else {
quarterMonth = '10';
}
const dateStr = useDateFormat(useNow(), 'YYYY').value + '-' + quarterMonth + '-01 00:00:00';
return dayjs(dateStr);
}
export const CurrentTimeRange = {
TODAY: today, //今日
THIS_WEEK: week, //本周
THIS_MONTH: month, //本月
THIS_QUARTER: quarter, //本季度
THIS_YEAR: year, //本年
};
使用方法
<SelectRangePicker
v-model:value="model[field]"
:options="timeRangeSelectOptionsWithBefore"
:range-options="TimeRangeValuesWithBefore"
/>