From 59d83d29cbbb39f79fee70ceddb59b76c46ddb39 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Wed, 31 Dec 2025 11:00:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20[bpm][ele]=20bpm=20oa=20=E8=AF=B7?= =?UTF-8?q?=E5=81=87=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/bpm/oa/leave/create.vue | 70 +++-- .../src/router/routes/modules/leave.ts | 45 +++ .../web-ele/src/views/bpm/oa/leave/create.vue | 282 ++++++++++++++++++ apps/web-ele/src/views/bpm/oa/leave/data.ts | 205 +++++++++++++ .../web-ele/src/views/bpm/oa/leave/detail.vue | 50 ++++ apps/web-ele/src/views/bpm/oa/leave/index.vue | 198 ++++++++++++ 6 files changed, 818 insertions(+), 32 deletions(-) create mode 100644 apps/web-ele/src/router/routes/modules/leave.ts create mode 100644 apps/web-ele/src/views/bpm/oa/leave/create.vue create mode 100644 apps/web-ele/src/views/bpm/oa/leave/data.ts create mode 100644 apps/web-ele/src/views/bpm/oa/leave/detail.vue create mode 100644 apps/web-ele/src/views/bpm/oa/leave/index.vue diff --git a/apps/web-antd/src/views/bpm/oa/leave/create.vue b/apps/web-antd/src/views/bpm/oa/leave/create.vue index be0fc678f..6079d004e 100644 --- a/apps/web-antd/src/views/bpm/oa/leave/create.vue +++ b/apps/web-antd/src/views/bpm/oa/leave/create.vue @@ -26,6 +26,7 @@ const { closeCurrentTab } = useTabs(); const { query } = useRoute(); const formLoading = ref(false); // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const processTimeLineLoading = ref(false); // 审批流的加载中 const processDefineKey = 'oa_leave'; // 流程定义 Key const startUserSelectTasks = ref([]); // 发起人需要选择审批人的用户任务列表 @@ -120,38 +121,43 @@ function onBack() { /** 审批相关:获取审批详情 */ async function getApprovalDetail() { - const data = await getApprovalDetailApi({ - processDefinitionId: processDefinitionId.value, - // TODO 小北:可以支持 processDefinitionKey 查询 - activityId: BpmNodeIdEnum.START_USER_NODE_ID, - processVariablesStr: JSON.stringify({ - day: dayjs(formData.value?.startTime).diff( - dayjs(formData.value?.endTime), - 'day', - ), - }), // 解决 GET 无法传递对象的问题,后端 String 再转 JSON - }); - if (!data) { - message.error('查询不到审批详情信息!'); - return; - } - // 获取审批节点,显示 Timeline 的数据 - activityNodes.value = data.activityNodes; - - // 获取发起人自选的任务 - startUserSelectTasks.value = data.activityNodes?.filter( - (node: BpmProcessInstanceApi.ApprovalNodeInfo) => - BpmCandidateStrategyEnum.START_USER_SELECT === node.candidateStrategy, - ); - // 恢复之前的选择审批人 - if (startUserSelectTasks.value?.length > 0) { - for (const node of startUserSelectTasks.value) { - startUserSelectAssignees.value[node.id] = - tempStartUserSelectAssignees.value[node.id] && - tempStartUserSelectAssignees.value[node.id].length > 0 - ? tempStartUserSelectAssignees.value[node.id] - : []; + processTimeLineLoading.value = true; + try { + const data = await getApprovalDetailApi({ + processDefinitionId: processDefinitionId.value, + // TODO 小北:可以支持 processDefinitionKey 查询 + activityId: BpmNodeIdEnum.START_USER_NODE_ID, + processVariablesStr: JSON.stringify({ + day: dayjs(formData.value?.startTime).diff( + dayjs(formData.value?.endTime), + 'day', + ), + }), // 解决 GET 无法传递对象的问题,后端 String 再转 JSON + }); + if (!data) { + message.error('查询不到审批详情信息!'); + return; } + // 获取审批节点,显示 Timeline 的数据 + activityNodes.value = data.activityNodes; + + // 获取发起人自选的任务 + startUserSelectTasks.value = data.activityNodes?.filter( + (node: BpmProcessInstanceApi.ApprovalNodeInfo) => + BpmCandidateStrategyEnum.START_USER_SELECT === node.candidateStrategy, + ); + // 恢复之前的选择审批人 + if (startUserSelectTasks.value?.length > 0) { + for (const node of startUserSelectTasks.value) { + startUserSelectAssignees.value[node.id] = + tempStartUserSelectAssignees.value[node.id] && + tempStartUserSelectAssignees.value[node.id].length > 0 + ? tempStartUserSelectAssignees.value[node.id] + : []; + } + } + } finally { + processTimeLineLoading.value = false; } } @@ -253,7 +259,7 @@ onMounted(async () => { - + import('#/views/bpm/oa/leave/index.vue'), + meta: { + title: '请假列表', + activePath: '/bpm/oa/leave', + }, + }, + { + path: 'leave/create', + name: 'OALeaveCreate', + component: () => import('#/views/bpm/oa/leave/create.vue'), + meta: { + title: '创建请假', + activePath: '/bpm/oa/leave', + }, + }, + { + path: 'leave/detail', + name: 'OALeaveDetail', + component: () => import('#/views/bpm/oa/leave/detail.vue'), + meta: { + title: '请假详情', + activePath: '/bpm/oa/leave', + }, + }, + ], + }, +]; + +export default routes; diff --git a/apps/web-ele/src/views/bpm/oa/leave/create.vue b/apps/web-ele/src/views/bpm/oa/leave/create.vue new file mode 100644 index 000000000..bac9b7936 --- /dev/null +++ b/apps/web-ele/src/views/bpm/oa/leave/create.vue @@ -0,0 +1,282 @@ + + + diff --git a/apps/web-ele/src/views/bpm/oa/leave/data.ts b/apps/web-ele/src/views/bpm/oa/leave/data.ts new file mode 100644 index 000000000..9570f422d --- /dev/null +++ b/apps/web-ele/src/views/bpm/oa/leave/data.ts @@ -0,0 +1,205 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { formatDate } from '@vben/utils'; + +import { DictTag } from '#/components/dict-tag'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'type', + label: '请假类型', + component: 'Select', + componentProps: { + placeholder: '请选择请假类型', + options: getDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE, 'number'), + allowClear: true, + }, + rules: 'required', + }, + + { + fieldName: 'startTime', + label: '开始时间', + component: 'DatePicker', + componentProps: { + placeholder: '请选择开始时间', + showTime: true, + valueFormat: 'x', + format: 'YYYY-MM-DD HH:mm:ss', + }, + rules: 'required', + }, + { + fieldName: 'endTime', + label: '结束时间', + component: 'DatePicker', + componentProps: { + placeholder: '请选择结束时间', + showTime: true, + valueFormat: 'x', + format: 'YYYY-MM-DD HH:mm:ss', + }, + rules: 'required', + }, + { + fieldName: 'reason', + label: '原因', + component: 'Textarea', + componentProps: { + placeholder: '请输入原因', + }, + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'type', + label: '请假类型', + component: 'Select', + componentProps: { + placeholder: '请选择请假类型', + options: getDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE, 'number'), + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'status', + label: '审批结果', + component: 'Select', + componentProps: { + placeholder: '请选择审批结果', + allowClear: true, + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, + 'number', + ), + }, + }, + { + fieldName: 'reason', + label: '原因', + component: 'Input', + componentProps: { + placeholder: '请输入原因', + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '申请编号', + minWidth: 100, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS }, + }, + }, + { + field: 'startTime', + title: '开始时间', + minWidth: 180, + formatter: 'formatDate', + }, + { + field: 'endTime', + title: '结束时间', + minWidth: 180, + formatter: 'formatDate', + }, + { + field: 'type', + title: '请假类型', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_OA_LEAVE_TYPE }, + }, + }, + { + field: 'reason', + title: '原因', + minWidth: 150, + }, + { + field: 'createTime', + title: '申请时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 240, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 详情 */ +export function useDetailFormSchema(): DescriptionItemSchema[] { + return [ + { + label: '请假类型', + field: 'type', + render: (val) => + h(DictTag, { + type: DICT_TYPE.BPM_OA_LEAVE_TYPE, + value: val, + }), + }, + { + label: '开始时间', + field: 'startTime', + render: (val) => formatDate(val) as string, + }, + { + label: '结束时间', + field: 'endTime', + render: (val) => formatDate(val) as string, + }, + { + label: '原因', + field: 'reason', + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/oa/leave/detail.vue b/apps/web-ele/src/views/bpm/oa/leave/detail.vue new file mode 100644 index 000000000..cb340240a --- /dev/null +++ b/apps/web-ele/src/views/bpm/oa/leave/detail.vue @@ -0,0 +1,50 @@ + + + diff --git a/apps/web-ele/src/views/bpm/oa/leave/index.vue b/apps/web-ele/src/views/bpm/oa/leave/index.vue new file mode 100644 index 000000000..e23c56372 --- /dev/null +++ b/apps/web-ele/src/views/bpm/oa/leave/index.vue @@ -0,0 +1,198 @@ + + +