| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- <template>
- <!-- 当 mode 为 date 时,使用原生 picker 组件 -->
- <picker v-if="mode === 'date'" mode="date" :fields="dateFields" :value="dateValue" :start="minDateStr" :end="maxDateStr" @change="onPickerChange">
- <view class="ut-datetime-picker" :class="{ 'ut-datetime-picker--border': border }">
- <slot></slot>
- </view>
- </picker>
- <!-- 其他模式使用 uview-plus 的 up-datetime-picker -->
- <template v-else>
- <view @click.stop="showTime = true" class="ut-datetime-picker" :class="{ 'ut-datetime-picker--border': border }">
- <slot></slot>
- </view>
- <up-datetime-picker
- v-model:show="showTime"
- :minDate="minDateTs"
- :maxDate="maxDateTs"
- ref="datetimePickerRef"
- :title="title"
- v-model="form.startTime"
- :mode="mode"
- @cancel="cancel"
- confirmColor="#2a6d52"
- @confirm="confirm"
- ></up-datetime-picker>
- </template>
- </template>
- <script setup lang="ts">
- import { parseTime } from '@/utils/ruoyi';
- type DateTimeMode = 'time' | 'datetime' | 'date' | 'year-month';
- interface Props {
- title: string;
- modelValue: string | number;
- mode: DateTimeMode;
- border: boolean;
- hasInput: boolean;
- minDate: number | string | Date;
- maxDate: number | string | Date;
- dateFields?: 'year' | 'month' | 'day';
- dateFormat?: string;
- }
- const props = withDefaults(defineProps<Props>(), {
- title: '选择时间',
- modelValue: '',
- mode: 'datetime' as DateTimeMode,
- border: false,
- hasInput: false,
- minDate: new Date(2000, 0, 1).getTime(),
- maxDate: new Date(2050, 0, 1).getTime(),
- dateFields: 'day',
- // 留空以便按粒度自动输出:year→{y},month→{y}-{m},day→{y}-{m}-{d}
- dateFormat: ''
- });
- const emit = defineEmits<{
- 'update:modelValue': [value: string | null];
- change: [value: string | null];
- }>();
- const showTime = ref(false);
- const datetimePickerRef = ref(null);
- // 统一转换为时间戳
- const toTs = (v: number | string | Date | undefined | null): number => {
- if (v === undefined || v === null) return Date.now();
- if (typeof v === 'number') return v;
- if (typeof v === 'string') return new Date(v).getTime();
- return (v as Date).getTime();
- };
- const form = ref({
- startTime: toTs(props.modelValue as any)
- });
- // 当使用原生 picker 的 date 模式时,格式化绑定和边界值(随粒度变化)
- const fieldsToFormat = (f: 'year' | 'month' | 'day') => {
- if (f === 'year') return '{y}';
- if (f === 'month') return '{y}-{m}';
- return '{y}-{m}-{d}';
- };
- const dateValue = computed(() => {
- const v = form.value.startTime as unknown as number | string | Date;
- if (!v) return '';
- const ts = toTs(v);
- return parseTime(ts, fieldsToFormat(props.dateFields!));
- });
- const minDateTs = computed(() => toTs(props.minDate));
- const maxDateTs = computed(() => toTs(props.maxDate));
- const minDateStr = computed(() => parseTime(minDateTs.value, fieldsToFormat(props.dateFields!)));
- const maxDateStr = computed(() => parseTime(maxDateTs.value, fieldsToFormat(props.dateFields!)));
- const confirm = (value?: any) => {
- const timestamp = value?.value ?? Date.now();
- const startTime = parseTime(timestamp, '{y}-{m}-{d} {h}:{i}');
- showTime.value = false;
- emit('update:modelValue', startTime);
- emit('change', startTime);
- };
- // 原生 picker 的变更事件(返回 YYYY / YYYY-MM / YYYY-MM-DD),按传入格式输出
- const onPickerChange = (e: any) => {
- const val = e?.detail?.value ?? '';
- if (!val) {
- emit('update:modelValue', '');
- emit('change', '');
- return;
- }
- let d: Date;
- if (props.dateFields === 'year') {
- const y = Number(val);
- d = new Date(y, 0, 1);
- } else if (props.dateFields === 'month') {
- const [yStr, mStr] = String(val).split('-');
- const y = Number(yStr);
- const m = Number(mStr) - 1;
- d = new Date(y, m, 1);
- } else {
- d = new Date(val);
- }
- const out = parseTime(d.getTime(), props.dateFormat || fieldsToFormat(props.dateFields!));
- emit('update:modelValue', out);
- emit('change', out);
- };
- const cancel = () => {
- showTime.value = false;
- };
- </script>
|