feat: 完成员工排班模块并统一门店抽屉底部操作样式
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 文件职责:班次模板卡片。
|
||||
* 1. 提供早班/晚班/全天模板时间编辑。
|
||||
* 2. 透出保存与重置事件。
|
||||
*/
|
||||
import type { Dayjs } from 'dayjs';
|
||||
|
||||
import type { ShiftType, StoreShiftTemplatesDto } from '#/api/store-staff';
|
||||
|
||||
import { Button, Card, TimePicker } from 'ant-design-vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
interface Props {
|
||||
isSaving: boolean;
|
||||
onSetTemplateTime: (payload: {
|
||||
field: 'endTime' | 'startTime';
|
||||
shiftType: Exclude<ShiftType, 'off'>;
|
||||
value: string;
|
||||
}) => void;
|
||||
templates: StoreShiftTemplatesDto;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'reset'): void;
|
||||
(event: 'save'): void;
|
||||
}>();
|
||||
|
||||
const templateRows: Array<{
|
||||
colorClass: string;
|
||||
label: string;
|
||||
shiftType: Exclude<ShiftType, 'off'>;
|
||||
}> = [
|
||||
{ shiftType: 'morning', label: '早班', colorClass: 'template-dot-morning' },
|
||||
{ shiftType: 'evening', label: '晚班', colorClass: 'template-dot-evening' },
|
||||
{ shiftType: 'full', label: '全天', colorClass: 'template-dot-full' },
|
||||
];
|
||||
|
||||
/** 将 HH:mm 字符串转换为时间组件值。 */
|
||||
function toPickerValue(time: string) {
|
||||
if (!time) return null;
|
||||
return dayjs(`2000-01-01 ${time}`);
|
||||
}
|
||||
|
||||
/** 将时间组件值转换为 HH:mm 字符串。 */
|
||||
function toTimeText(value: Dayjs | null) {
|
||||
return value ? value.format('HH:mm') : '';
|
||||
}
|
||||
|
||||
/** 处理模板时间变更。 */
|
||||
function handleTemplateTimeChange(payload: {
|
||||
field: 'endTime' | 'startTime';
|
||||
shiftType: Exclude<ShiftType, 'off'>;
|
||||
value: Dayjs | null;
|
||||
}) {
|
||||
props.onSetTemplateTime({
|
||||
shiftType: payload.shiftType,
|
||||
field: payload.field,
|
||||
value: toTimeText(payload.value),
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card :bordered="false" class="staff-card">
|
||||
<template #title>
|
||||
<span class="section-title">班次模板</span>
|
||||
</template>
|
||||
|
||||
<div class="template-list">
|
||||
<div
|
||||
v-for="row in templateRows"
|
||||
:key="row.shiftType"
|
||||
class="template-row"
|
||||
>
|
||||
<span class="template-dot" :class="row.colorClass"></span>
|
||||
<span class="template-label">{{ row.label }}</span>
|
||||
|
||||
<div class="template-time-group">
|
||||
<TimePicker
|
||||
:value="toPickerValue(props.templates[row.shiftType].startTime)"
|
||||
format="HH:mm"
|
||||
:allow-clear="false"
|
||||
@update:value="
|
||||
(value) =>
|
||||
handleTemplateTimeChange({
|
||||
shiftType: row.shiftType,
|
||||
field: 'startTime',
|
||||
value,
|
||||
})
|
||||
"
|
||||
/>
|
||||
<span class="template-time-separator">~</span>
|
||||
<TimePicker
|
||||
:value="toPickerValue(props.templates[row.shiftType].endTime)"
|
||||
format="HH:mm"
|
||||
:allow-clear="false"
|
||||
@update:value="
|
||||
(value) =>
|
||||
handleTemplateTimeChange({
|
||||
shiftType: row.shiftType,
|
||||
field: 'endTime',
|
||||
value,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="template-tip">
|
||||
调整模板后,个人排班和周排班中的同类型班次会同步到新的时间段。
|
||||
</div>
|
||||
|
||||
<div class="staff-card-actions">
|
||||
<Button :disabled="props.isSaving" @click="emit('reset')">重置</Button>
|
||||
<Button type="primary" :loading="props.isSaving" @click="emit('save')">
|
||||
保存模板
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</template>
|
||||
Reference in New Issue
Block a user