Files
TakeoutSaaS.TenantUI/apps/web-antd/src/views/store/staff/components/WeeklyScheduleBoard.vue

107 lines
3.0 KiB
Vue

<script setup lang="ts">
/**
* 文件职责:周排班看板。
* 1. 展示各员工周排班只读视图。
* 2. 提供“编辑排班”入口。
*/
import type { ShiftType, StaffDayShiftDto } from '#/api/store-staff';
import type { DayOption, WeekEditorRow } from '#/views/store/staff/types';
import { Button, Card, Empty } from 'ant-design-vue';
interface Props {
dayOptions: DayOption[];
getShiftClass: (shiftType: ShiftType) => string;
getShiftLabel: (shiftType: ShiftType) => string;
getShiftTimeText: (shift: StaffDayShiftDto) => string;
roleLabelResolver: (roleType: WeekEditorRow['roleType']) => string;
rows: WeekEditorRow[];
}
const props = defineProps<Props>();
const emit = defineEmits<{
(event: 'editWeek'): void;
}>();
/** 读取员工某日排班,缺失时兜底为休息。 */
function resolveDayShift(
row: WeekEditorRow,
dayOfWeek: number,
): StaffDayShiftDto {
return (
row.shifts.find((item) => item.dayOfWeek === dayOfWeek) ?? {
dayOfWeek,
shiftType: 'off',
startTime: '',
endTime: '',
}
);
}
</script>
<template>
<Card :bordered="false" class="staff-card">
<template #title>
<span class="section-title">本周排班</span>
</template>
<template #extra>
<Button @click="emit('editWeek')">编辑排班</Button>
</template>
<div v-if="props.rows.length === 0" class="schedule-empty">
<Empty description="暂无可排班员工" />
</div>
<div v-else class="schedule-board-wrap">
<table class="schedule-board-table">
<thead>
<tr>
<th>员工</th>
<th v-for="day in props.dayOptions" :key="day.dayOfWeek">
{{ day.label }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="row in props.rows" :key="row.staffId">
<td class="schedule-staff-cell">
<div class="schedule-staff-name">{{ row.staffName }}</div>
<div class="schedule-staff-role">
{{ props.roleLabelResolver(row.roleType) }}
</div>
</td>
<td
v-for="day in props.dayOptions"
:key="`${row.staffId}-${day.dayOfWeek}`"
>
<div
class="schedule-cell"
:class="
props.getShiftClass(
resolveDayShift(row, day.dayOfWeek).shiftType,
)
"
>
<span class="schedule-cell-time">
{{
props.getShiftTimeText(resolveDayShift(row, day.dayOfWeek))
}}
</span>
<span class="schedule-cell-label">
{{
props.getShiftLabel(
resolveDayShift(row, day.dayOfWeek).shiftType,
)
}}
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</Card>
</template>