Showing
4 changed files
with
0 additions
and
289 deletions
| 1 | -<script lang="ts" setup> | |
| 2 | - import { ref, computed, Ref, unref } from 'vue'; | |
| 3 | - import { Select, Switch, InputNumber } from 'ant-design-vue'; | |
| 4 | - import { latestOptions, LatestOptionsEnum } from './config'; | |
| 5 | - import { dateUtil } from '/@/utils/dateUtil'; | |
| 6 | - | |
| 7 | - type DateUnit = 'days' | 'hours' | 'minutes' | 'seconds'; | |
| 8 | - | |
| 9 | - type RangeObject = Record<DateUnit, number>; | |
| 10 | - | |
| 11 | - const emit = defineEmits(['update:value']); | |
| 12 | - | |
| 13 | - const props = withDefaults( | |
| 14 | - defineProps<{ | |
| 15 | - value?: number; | |
| 16 | - }>(), | |
| 17 | - { | |
| 18 | - value: 1000 * 60 * 60 * 24 * 30, | |
| 19 | - } | |
| 20 | - ); | |
| 21 | - | |
| 22 | - const advancedMode = ref(false); | |
| 23 | - | |
| 24 | - const getRangeObject = (milliseconds: number) => { | |
| 25 | - const methods: { method: string; key: moment.unitOfTime.Base }[] = [ | |
| 26 | - { method: 'asDays', key: 'days' }, | |
| 27 | - { method: 'asHours', key: 'hours' }, | |
| 28 | - { method: 'asMinutes', key: 'minutes' }, | |
| 29 | - { method: 'asSeconds', key: 'seconds' }, | |
| 30 | - ]; | |
| 31 | - | |
| 32 | - return methods.reduce((prev, next) => { | |
| 33 | - const { method, key } = next; | |
| 34 | - const value = dateUtil.duration(milliseconds, 'millisecond')[method]?.(); | |
| 35 | - | |
| 36 | - if (value >= 1) { | |
| 37 | - milliseconds -= dateUtil.duration(parseInt(value), key).asMilliseconds(); | |
| 38 | - } | |
| 39 | - | |
| 40 | - return { ...prev, [key]: value >= 1 ? parseInt(value) : 0 }; | |
| 41 | - }, {} as Record<DateUnit, number>); | |
| 42 | - }; | |
| 43 | - | |
| 44 | - const getMillisecondsByObject = (value: RangeObject | Ref<RangeObject>) => { | |
| 45 | - value = unref(value); | |
| 46 | - return Object.keys(unref(value)).reduce((prev, next) => { | |
| 47 | - return ( | |
| 48 | - prev + | |
| 49 | - dateUtil | |
| 50 | - .duration(value[next], next as moment.unitOfTime.DurationConstructor) | |
| 51 | - .asMilliseconds() | |
| 52 | - ); | |
| 53 | - }, 0); | |
| 54 | - }; | |
| 55 | - | |
| 56 | - const getValue = computed(() => { | |
| 57 | - const { value } = props; | |
| 58 | - const dateRange = getRangeObject(value); | |
| 59 | - const { days, hours, minutes, seconds } = dateRange; | |
| 60 | - | |
| 61 | - const filterList = latestOptions.filter((item) => value >= item.value); | |
| 62 | - return { | |
| 63 | - days, | |
| 64 | - hours, | |
| 65 | - minutes, | |
| 66 | - seconds, | |
| 67 | - selectValue: filterList[filterList.length - 1].value, | |
| 68 | - }; | |
| 69 | - }); | |
| 70 | - | |
| 71 | - const handleSyncValue = (value: LatestOptionsEnum) => { | |
| 72 | - emit('update:value', value); | |
| 73 | - }; | |
| 74 | - | |
| 75 | - const handleChange = (value: number, unit: DateUnit) => { | |
| 76 | - if (isNaN(value)) return; | |
| 77 | - let { days, hours, minutes, seconds } = unref(getValue); | |
| 78 | - const dateRangeObject: RangeObject = { | |
| 79 | - days, | |
| 80 | - hours, | |
| 81 | - minutes, | |
| 82 | - seconds, | |
| 83 | - [unit]: value, | |
| 84 | - }; | |
| 85 | - | |
| 86 | - const milliseconds = getMillisecondsByObject(dateRangeObject); | |
| 87 | - emit('update:value', milliseconds); | |
| 88 | - }; | |
| 89 | -</script> | |
| 90 | - | |
| 91 | -<template> | |
| 92 | - <section class="flex justify-center items-end gap-4 h-14 latest-date-picker"> | |
| 93 | - <section v-if="advancedMode" class="flex flex-auto custom-date-range"> | |
| 94 | - <div> | |
| 95 | - <div>天</div> | |
| 96 | - <InputNumber | |
| 97 | - :value="getValue.days" | |
| 98 | - @change="(event) => handleChange(event, 'days')" | |
| 99 | - :step="1" | |
| 100 | - :max="7300" | |
| 101 | - :min="0" | |
| 102 | - /> | |
| 103 | - </div> | |
| 104 | - <div> | |
| 105 | - <div>小时</div> | |
| 106 | - <InputNumber | |
| 107 | - :value="getValue.hours" | |
| 108 | - @change="(event) => handleChange(event, 'hours')" | |
| 109 | - :step="1" | |
| 110 | - :max="23" | |
| 111 | - :min="0" | |
| 112 | - /> | |
| 113 | - </div> | |
| 114 | - <div> | |
| 115 | - <div>分钟</div> | |
| 116 | - <InputNumber | |
| 117 | - :value="getValue.minutes" | |
| 118 | - @change="(event) => handleChange(event, 'minutes')" | |
| 119 | - :step="1" | |
| 120 | - :max="59" | |
| 121 | - :min="0" | |
| 122 | - /> | |
| 123 | - </div> | |
| 124 | - <div> | |
| 125 | - <div>秒</div> | |
| 126 | - <InputNumber | |
| 127 | - :value="getValue.seconds" | |
| 128 | - @change="(event) => handleChange(event, 'seconds')" | |
| 129 | - :step="1" | |
| 130 | - :max="59" | |
| 131 | - :min="0" | |
| 132 | - /> | |
| 133 | - </div> | |
| 134 | - </section> | |
| 135 | - <Select | |
| 136 | - v-if="!advancedMode" | |
| 137 | - class="!flex-auto" | |
| 138 | - v-model:value="getValue.selectValue" | |
| 139 | - :options="latestOptions" | |
| 140 | - placeholder="请选择最后时间段" | |
| 141 | - @change="handleSyncValue" | |
| 142 | - allow-clear | |
| 143 | - /> | |
| 144 | - <div class="w-14 flex flex-col justify-between h-full text-center"> | |
| 145 | - <div>高级</div> | |
| 146 | - <Switch class="w-14" v-model:checked="advancedMode" /> | |
| 147 | - </div> | |
| 148 | - </section> | |
| 149 | -</template> | |
| 150 | - | |
| 151 | -<style scoped lang="less"> | |
| 152 | - .latest-date-picker { | |
| 153 | - :deep(.ant-input-number) { | |
| 154 | - min-width: 0; | |
| 155 | - width: 100%; | |
| 156 | - } | |
| 157 | - | |
| 158 | - :deep(.ant-select-selection-item) { | |
| 159 | - pointer-events: none; | |
| 160 | - } | |
| 161 | - } | |
| 162 | -</style> |
src/components/Form/src/externalCompns/components/DateRangeButton/config.ts
deleted
100644 → 0
| 1 | -import { dateUtil } from '/@/utils/dateUtil'; | |
| 2 | - | |
| 3 | -export enum ModeEnum { | |
| 4 | - LATEST = 'LATEST', | |
| 5 | - RANGE = 'RANGE', | |
| 6 | - INTERVAL = 'INTERVAL', | |
| 7 | -} | |
| 8 | - | |
| 9 | -export enum ModeNameEnum { | |
| 10 | - LATEST = '最后', | |
| 11 | - RANGE = '时间段', | |
| 12 | - INTERVAL = '时间间隔', | |
| 13 | -} | |
| 14 | - | |
| 15 | -export enum UnitEnum { | |
| 16 | - SECONDS = '秒', | |
| 17 | - MINUTES = '分', | |
| 18 | - HOURS = '时', | |
| 19 | - DAYS = '天', | |
| 20 | -} | |
| 21 | - | |
| 22 | -export enum LatestOptionsEnum { | |
| 23 | - '1_SECONDS' = '1_SECONDS', | |
| 24 | - '5_SECONDS' = '5_SECONDS', | |
| 25 | - '10_SECONDS' = '10_SECONDS', | |
| 26 | - '15_SECONDS' = '15_SECONDS', | |
| 27 | - '30_SECONDS' = '30_SECONDS', | |
| 28 | - | |
| 29 | - '1_MINUTES' = '1_MINUTES', | |
| 30 | - '2_MINUTES' = '2_MINUTES', | |
| 31 | - '5_MINUTES' = '5_MINUTES', | |
| 32 | - '10_MINUTES' = '10_MINUTES', | |
| 33 | - '15_MINUTES' = '15_MINUTES', | |
| 34 | - '30_MINUTES' = '30_MINUTES', | |
| 35 | - | |
| 36 | - '1_HOURS' = '1_HOURS', | |
| 37 | - '2_HOURS' = '2_HOURS', | |
| 38 | - '5_HOURS' = '5_HOURS', | |
| 39 | - '10_HOURS' = '10_HOURS', | |
| 40 | - '12_HOURS' = '12_HOURS', | |
| 41 | - | |
| 42 | - '1_DAYS' = '1_DAYS', | |
| 43 | - '7_DAYS' = '7_DAYS', | |
| 44 | - '30_DAYS' = '30_DAYS', | |
| 45 | -} | |
| 46 | - | |
| 47 | -const getLatesetOptionLabel = (string: string) => { | |
| 48 | - const [value, unit] = string.split('_'); | |
| 49 | - return `${value} ${UnitEnum[unit]}`; | |
| 50 | -}; | |
| 51 | - | |
| 52 | -const getLatesetOptionValue = (string: string) => { | |
| 53 | - const [value, unit] = string.split('_'); | |
| 54 | - return dateUtil | |
| 55 | - .duration(Number(value), unit.toLowerCase() as moment.unitOfTime.DurationConstructor) | |
| 56 | - .asMilliseconds(); | |
| 57 | -}; | |
| 58 | - | |
| 59 | -export const latestOptions: { label: string; value: number }[] = Object.keys(LatestOptionsEnum).map( | |
| 60 | - (key) => ({ label: getLatesetOptionLabel(key), value: getLatesetOptionValue(key) }) | |
| 61 | -); | |
| 62 | - | |
| 63 | -[ | |
| 64 | - 'Yesterday', | |
| 65 | - 'Day before yesterday', | |
| 66 | - 'This day last week', | |
| 67 | - 'Previous week (Sun - Sat)', | |
| 68 | - 'Previous week (Mon - Sun)', | |
| 69 | - 'Previous month', | |
| 70 | - 'Previous year', | |
| 71 | - 'Current hour', | |
| 72 | - 'Current day', | |
| 73 | - 'Current day so far', | |
| 74 | - 'Current week (Sun - Sat)', | |
| 75 | - 'Current week (Mon - Sun)', | |
| 76 | - 'Current week so far (Sun - Sat)', | |
| 77 | - 'Current week so far (Mon - Sun)', | |
| 78 | - 'Current month', | |
| 79 | - 'Current month so far', | |
| 80 | - 'Current year', | |
| 81 | - 'Current year so far', | |
| 82 | -]; |
src/components/Form/src/externalCompns/components/DateRangeButton/index.ts
deleted
100644 → 0
| 1 | -export { default as DateRangeButton } from './index.vue'; |
src/components/Form/src/externalCompns/components/DateRangeButton/index.vue
deleted
100644 → 0
| 1 | -<script lang="ts" setup> | |
| 2 | - import { Popconfirm, Button, Radio, RadioGroup, RangePicker } from 'ant-design-vue'; | |
| 3 | - import { ref } from 'vue'; | |
| 4 | - import { Icon } from '/@/components/Icon'; | |
| 5 | - import { ModeEnum, ModeNameEnum } from './config'; | |
| 6 | - import LatestDate from './LatestDate.vue'; | |
| 7 | - | |
| 8 | - const mode = ref(ModeEnum.LATEST); | |
| 9 | - | |
| 10 | - const visible = ref(true); | |
| 11 | - | |
| 12 | - const latestValue = ref<number>(1000 * 60 * 60 * 24 * 30); | |
| 13 | -</script> | |
| 14 | - | |
| 15 | -<template> | |
| 16 | - <Popconfirm :visible="visible"> | |
| 17 | - <template #icon> | |
| 18 | - <span></span> | |
| 19 | - </template> | |
| 20 | - <template #title> | |
| 21 | - <RadioGroup v-model:value="mode" class="!flex flex-col gap-2 w-96"> | |
| 22 | - <Radio :value="ModeEnum.LATEST"> | |
| 23 | - <span>{{ ModeNameEnum.LATEST }}</span> | |
| 24 | - <LatestDate v-model:value="latestValue" v-if="mode === ModeEnum.LATEST" /> | |
| 25 | - </Radio> | |
| 26 | - <Radio :value="ModeEnum.RANGE"> | |
| 27 | - <span>{{ ModeNameEnum.RANGE }}</span> | |
| 28 | - <section v-if="mode === ModeEnum.RANGE" class="mt-2 flex flex-col justify-end"> | |
| 29 | - <RangePicker :showTime="true" /> | |
| 30 | - </section> | |
| 31 | - </Radio> | |
| 32 | - <Radio :value="ModeEnum.INTERVAL"> | |
| 33 | - <span>{{ ModeNameEnum.INTERVAL }}</span> | |
| 34 | - <section class="mt-2 flex flex-col justify-end"> | |
| 35 | - <!-- --> | |
| 36 | - </section> | |
| 37 | - </Radio> | |
| 38 | - </RadioGroup> | |
| 39 | - </template> | |
| 40 | - <Button type="primary" @click="visible = true"> | |
| 41 | - <Icon icon="mdi:clock-outline" /> | |
| 42 | - </Button> | |
| 43 | - </Popconfirm> | |
| 44 | -</template> |