<script lang="ts" setup>
|
import type { MesCalScheduleDetailApi } from '#/api/mes/cal/scheduleDetail';
|
|
import { onMounted, ref } from 'vue';
|
|
import { useVbenModal } from '@vben/common-ui';
|
|
import dayjs from 'dayjs';
|
|
import {
|
Button,
|
Empty,
|
Form,
|
FormItem,
|
message,
|
RangePicker,
|
Select,
|
Spin,
|
Table,
|
Tag,
|
} from 'ant-design-vue';
|
|
import { checkCompliance } from '#/api/mes/cal/scheduleDetail';
|
import { getRangePickerDefaultProps } from '#/utils';
|
|
import { fetchUserOptions, issueTypeMap, type OptionItem } from '../data';
|
|
const userId = ref<number>();
|
const day = ref<string[]>();
|
const userOptions = ref<OptionItem[]>([]);
|
|
const loading = ref(false);
|
const checked = ref(false);
|
const items = ref<MesCalScheduleDetailApi.CheckItem[]>([]);
|
|
/** 执行合规校验 */
|
async function doCheck() {
|
if (!userId.value) {
|
message.warning('请选择员工');
|
return;
|
}
|
loading.value = true;
|
try {
|
items.value = await checkCompliance({
|
userId: userId.value,
|
startDay: day.value?.[0],
|
endDay: day.value?.[1],
|
});
|
checked.value = true;
|
} finally {
|
loading.value = false;
|
}
|
}
|
|
const columns = [
|
{
|
title: '日期',
|
dataIndex: 'day',
|
key: 'day',
|
width: 110,
|
customRender: ({ text }: { text?: string }) =>
|
text ? dayjs(text).format('YYYY-MM-DD') : '-',
|
},
|
{ title: '班次', dataIndex: 'shiftName', key: 'shiftName', width: 100 },
|
{
|
title: '时间',
|
key: 'time',
|
width: 120,
|
customRender: ({ record }: { record: MesCalScheduleDetailApi.CheckItem }) =>
|
`${record.startTime ?? '-'} ~ ${record.endTime ?? '-'}`,
|
},
|
{
|
title: '违规类型',
|
dataIndex: 'issueType',
|
key: 'issueType',
|
width: 100,
|
},
|
{ title: '问题描述', dataIndex: 'issue', key: 'issue' },
|
];
|
|
/** 同日可能多班次,用行号作为 key */
|
function rowIndexKey(_record: MesCalScheduleDetailApi.CheckItem, index?: number) {
|
return index ?? 0;
|
}
|
|
const [Modal, modalApi] = useVbenModal({
|
showConfirmButton: false,
|
cancelText: '关闭',
|
onOpenChange(isOpen: boolean) {
|
if (!isOpen) {
|
checked.value = false;
|
items.value = [];
|
return;
|
}
|
// 支持从列表行传入员工编号,自动发起校验
|
const data = modalApi.getData<{ userId?: number }>();
|
if (data?.userId) {
|
userId.value = data.userId;
|
doCheck();
|
}
|
},
|
});
|
|
onMounted(async () => {
|
userOptions.value = await fetchUserOptions();
|
});
|
</script>
|
|
<template>
|
<Modal title="员工排班合规校验" class="w-3/5">
|
<Form layout="inline" class="mb-2.5">
|
<FormItem label="员工">
|
<Select
|
v-model:value="userId"
|
allow-clear
|
show-search
|
placeholder="请选择员工"
|
class="!w-[200px]"
|
:options="userOptions"
|
:filter-option="
|
(input: string, option: OptionItem) =>
|
(option?.label ?? '').includes(input)
|
"
|
/>
|
</FormItem>
|
<FormItem label="日期">
|
<RangePicker
|
v-model:value="day"
|
class="!w-[260px]"
|
v-bind="getRangePickerDefaultProps()"
|
/>
|
</FormItem>
|
<FormItem>
|
<Button type="primary" :loading="loading" @click="doCheck">校验</Button>
|
</FormItem>
|
</Form>
|
<Spin :spinning="loading">
|
<Table
|
v-if="!checked || items.length > 0"
|
size="small"
|
:row-key="rowIndexKey"
|
:columns="columns"
|
:data-source="items"
|
:pagination="false"
|
:scroll="{ y: 360 }"
|
>
|
<template #bodyCell="{ column, record }">
|
<template v-if="column.key === 'issueType'">
|
<Tag v-if="record.issueType" :color="record.issueType === 1 ? 'red' : 'orange'">
|
{{ issueTypeMap[record.issueType as number] }}
|
</Tag>
|
<Tag v-else color="green">合规</Tag>
|
</template>
|
<template v-else-if="column.key === 'issue'">
|
{{ record.issue || '无异常' }}
|
</template>
|
</template>
|
</Table>
|
<Empty v-else description="未发现违规排班记录,该员工排班合规" />
|
</Spin>
|
</Modal>
|
</template>
|