241 lines
6.7 KiB
Vue
241 lines
6.7 KiB
Vue
<script setup lang="ts">
|
|
import type { HolidayFormState } from '../types';
|
|
|
|
import type { HolidayType } from '#/api/store-hours';
|
|
|
|
import {
|
|
Button,
|
|
DatePicker,
|
|
Drawer,
|
|
RangePicker,
|
|
TimePicker,
|
|
} from 'ant-design-vue';
|
|
|
|
interface Props {
|
|
holidayForm: HolidayFormState;
|
|
holidayTypeClosed: HolidayType;
|
|
holidayTypeSpecial: HolidayType;
|
|
isHolidaySubmitting: boolean;
|
|
onSetDateMode: (mode: 'range' | 'single') => void;
|
|
onSetEndTime: (value: string) => void;
|
|
onSetRangeEnd: (value: string) => void;
|
|
onSetRangeStart: (value: string) => void;
|
|
onSetReason: (value: string) => void;
|
|
onSetRemark: (value: string) => void;
|
|
onSetSingleDate: (value: string) => void;
|
|
onSetStartTime: (value: string) => void;
|
|
onSetType: (type: HolidayType) => void;
|
|
open: boolean;
|
|
submitText: string;
|
|
title: string;
|
|
}
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
const emit = defineEmits<{
|
|
(event: 'submit'): void;
|
|
(event: 'update:open', value: boolean): void;
|
|
}>();
|
|
|
|
function getInputValue(event: Event) {
|
|
const target = event.target as HTMLInputElement | HTMLTextAreaElement | null;
|
|
return target?.value ?? '';
|
|
}
|
|
|
|
function hasFormatMethod(
|
|
value: unknown,
|
|
): value is { format: (pattern: string) => string } {
|
|
return Boolean(
|
|
value &&
|
|
typeof value === 'object' &&
|
|
'format' in value &&
|
|
typeof (value as { format?: unknown }).format === 'function',
|
|
);
|
|
}
|
|
|
|
function readDateValue(value: unknown) {
|
|
if (typeof value === 'string') return value;
|
|
if (hasFormatMethod(value)) return value.format('YYYY-MM-DD');
|
|
return '';
|
|
}
|
|
|
|
function readDateRangeValue(value: unknown): [string, string] {
|
|
if (!Array.isArray(value) || value.length < 2) return ['', ''];
|
|
return [readDateValue(value[0]), readDateValue(value[1])];
|
|
}
|
|
|
|
function getRangePickerValue(): [string, string] | undefined {
|
|
const { rangeStart, rangeEnd } = props.holidayForm;
|
|
if (!rangeStart || !rangeEnd) return undefined;
|
|
const rangeValue: [string, string] = [rangeStart, rangeEnd];
|
|
return rangeValue;
|
|
}
|
|
|
|
function handleRangeChange(value: unknown) {
|
|
const [start, end] = readDateRangeValue(value);
|
|
props.onSetRangeStart(start);
|
|
props.onSetRangeEnd(end);
|
|
}
|
|
|
|
function readTimeValue(value: unknown) {
|
|
if (typeof value === 'string') return value;
|
|
if (hasFormatMethod(value)) return value.format('HH:mm');
|
|
return '';
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<Drawer
|
|
class="holiday-drawer-wrap"
|
|
:open="props.open"
|
|
:title="props.title"
|
|
:width="480"
|
|
:mask-closable="true"
|
|
@update:open="(value) => emit('update:open', value)"
|
|
>
|
|
<div class="form-block">
|
|
<label class="form-label required">类型</label>
|
|
<div class="type-pill-group">
|
|
<button
|
|
type="button"
|
|
class="type-pill ht-closed"
|
|
:class="{
|
|
active: props.holidayForm.type === props.holidayTypeClosed,
|
|
}"
|
|
@click="props.onSetType(props.holidayTypeClosed)"
|
|
>
|
|
休息
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="type-pill ht-special"
|
|
:class="{
|
|
active: props.holidayForm.type === props.holidayTypeSpecial,
|
|
}"
|
|
@click="props.onSetType(props.holidayTypeSpecial)"
|
|
>
|
|
特殊营业
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-block">
|
|
<label class="form-label required">日期</label>
|
|
<div class="date-mode-row">
|
|
<button
|
|
type="button"
|
|
class="date-mode-pill"
|
|
:class="{ active: props.holidayForm.dateMode === 'single' }"
|
|
@click="props.onSetDateMode('single')"
|
|
>
|
|
单日
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="date-mode-pill"
|
|
:class="{ active: props.holidayForm.dateMode === 'range' }"
|
|
@click="props.onSetDateMode('range')"
|
|
>
|
|
日期范围
|
|
</button>
|
|
</div>
|
|
|
|
<template v-if="props.holidayForm.dateMode === 'single'">
|
|
<DatePicker
|
|
:value="props.holidayForm.singleDate"
|
|
value-format="YYYY-MM-DD"
|
|
format="YYYY-MM-DD"
|
|
:allow-clear="false"
|
|
class="native-picker"
|
|
input-read-only
|
|
@update:value="(value) => props.onSetSingleDate(readDateValue(value))"
|
|
/>
|
|
</template>
|
|
<template v-else>
|
|
<div class="date-range-row">
|
|
<RangePicker
|
|
:value="getRangePickerValue()"
|
|
value-format="YYYY-MM-DD"
|
|
format="YYYY-MM-DD"
|
|
:allow-clear="false"
|
|
class="native-picker native-range-picker"
|
|
input-read-only
|
|
@update:value="handleRangeChange"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<div
|
|
v-if="props.holidayForm.type === props.holidayTypeSpecial"
|
|
class="form-block"
|
|
>
|
|
<label class="form-label">营业时间</label>
|
|
<div class="time-grid">
|
|
<div class="form-block">
|
|
<label class="form-sub-label">开始</label>
|
|
<TimePicker
|
|
:value="props.holidayForm.startTime"
|
|
value-format="HH:mm"
|
|
format="HH:mm"
|
|
:allow-clear="false"
|
|
class="native-picker"
|
|
input-read-only
|
|
@update:value="
|
|
(value) => props.onSetStartTime(readTimeValue(value))
|
|
"
|
|
/>
|
|
</div>
|
|
<div class="form-block">
|
|
<label class="form-sub-label">结束</label>
|
|
<TimePicker
|
|
:value="props.holidayForm.endTime"
|
|
value-format="HH:mm"
|
|
format="HH:mm"
|
|
:allow-clear="false"
|
|
class="native-picker"
|
|
input-read-only
|
|
@update:value="(value) => props.onSetEndTime(readTimeValue(value))"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="time-hint">特殊营业日的营业时间段</div>
|
|
</div>
|
|
|
|
<div class="form-block">
|
|
<label class="form-label required">原因</label>
|
|
<input
|
|
:value="props.holidayForm.reason"
|
|
type="text"
|
|
class="native-input"
|
|
placeholder="如:春节假期、情人节延长营业"
|
|
@input="(event) => props.onSetReason(getInputValue(event))"
|
|
/>
|
|
</div>
|
|
|
|
<div class="form-block">
|
|
<label class="form-label">备注</label>
|
|
<textarea
|
|
:value="props.holidayForm.remark"
|
|
rows="2"
|
|
class="native-textarea"
|
|
placeholder="可选"
|
|
@input="(event) => props.onSetRemark(getInputValue(event))"
|
|
></textarea>
|
|
</div>
|
|
|
|
<template #footer>
|
|
<div class="drawer-footer">
|
|
<Button @click="emit('update:open', false)">取消</Button>
|
|
<Button
|
|
type="primary"
|
|
:loading="props.isHolidaySubmitting"
|
|
@click="emit('submit')"
|
|
>
|
|
{{ props.holidayForm.id ? '保存修改' : '新增并保存' }}
|
|
</Button>
|
|
</div>
|
|
</template>
|
|
</Drawer>
|
|
</template>
|