From 2705fb7a4d5e9793784017f87ebd99eea7b1d470 Mon Sep 17 00:00:00 2001 From: ziye <278898052@qq.com> Date: Mon, 12 May 2025 00:53:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=87=8D=E6=9E=84=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=92=8C=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=EF=BC=8C=E6=9B=B4=E6=96=B0API=E5=91=BD?= =?UTF-8?q?=E5=90=8D=EF=BC=8C=E5=A2=9E=E5=BC=BA=E7=94=A8=E6=88=B7=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E5=BC=B9=E7=AA=97=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E7=94=A8=E6=88=B7=E9=80=89=E6=8B=A9=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E7=95=8C=E9=9D=A2=E3=80=82=20feat:=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E6=B5=81=E7=A8=8B=E5=AE=9A=E4=B9=89=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E3=80=81=E5=AE=8C=E5=96=84=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=20feat:=20=E5=AE=8C=E5=96=84OA=E8=AF=B7?= =?UTF-8?q?=E5=81=87=E6=A8=A1=E5=9D=97=20feat:=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E4=B8=AD=E5=BF=83=E3=80=81=E5=8F=91=E8=B5=B7?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E3=80=81=E6=9F=A5=E7=9C=8B=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E3=80=81=E5=B7=A5=E4=BD=9C=E6=B5=81=E6=95=B4=E4=BD=93=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=2040%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/api/bpm/definition/index.ts | 30 +- apps/web-antd/src/api/bpm/oa/leave/index.ts | 40 ++ .../src/api/bpm/processInstance/index.ts | 6 +- apps/web-antd/src/api/bpm/task/index.ts | 108 ++++ .../user-select-modal/user-select-modal.vue | 23 +- .../web-antd/src/router/routes/modules/bpm.ts | 19 + .../src/router/routes/modules/leave.ts | 45 ++ apps/web-antd/src/utils/constants.ts | 39 +- .../src/views/bpm/oa/leave/create.vue | 269 +++++++++ apps/web-antd/src/views/bpm/oa/leave/data.ts | 200 +++++++ .../src/views/bpm/oa/leave/detail.vue | 11 + .../web-antd/src/views/bpm/oa/leave/index.vue | 179 +++++- .../bpm/processInstance/create/index.vue | 329 +++++------ .../processInstance/create/modules/form.vue | 354 +++++++++++ .../src/views/bpm/processInstance/data.ts | 173 ++++++ .../bpm/processInstance/detail/index.vue | 26 +- .../detail/modules/time-line.vue | 551 +++++++++--------- .../src/views/bpm/processInstance/index.vue | 193 +++++- 18 files changed, 2065 insertions(+), 530 deletions(-) create mode 100644 apps/web-antd/src/api/bpm/oa/leave/index.ts create mode 100644 apps/web-antd/src/api/bpm/task/index.ts create mode 100644 apps/web-antd/src/router/routes/modules/leave.ts create mode 100644 apps/web-antd/src/views/bpm/oa/leave/create.vue create mode 100644 apps/web-antd/src/views/bpm/oa/leave/data.ts create mode 100644 apps/web-antd/src/views/bpm/oa/leave/detail.vue create mode 100644 apps/web-antd/src/views/bpm/processInstance/data.ts diff --git a/apps/web-antd/src/api/bpm/definition/index.ts b/apps/web-antd/src/api/bpm/definition/index.ts index 85cdecaf6..3a59b9875 100644 --- a/apps/web-antd/src/api/bpm/definition/index.ts +++ b/apps/web-antd/src/api/bpm/definition/index.ts @@ -3,19 +3,21 @@ import type { PageParam, PageResult } from '@vben/request'; import { requestClient } from '#/api/request'; /** 流程定义 */ -export namespace BpmDefinitionApi { +export namespace BpmProcessDefinitionApi { export interface ProcessDefinitionVO { id: string; version: number; deploymentTime: number; suspensionState: number; formType?: number; + bpmnXml?: string; + simpleModel?: string; } } /** 查询流程定义 */ export async function getProcessDefinition(id?: string, key?: string) { - return requestClient.get( + return requestClient.get( '/bpm/process-definition/get', { params: { id, key }, @@ -25,25 +27,23 @@ export async function getProcessDefinition(id?: string, key?: string) { /** 分页查询流程定义 */ export async function getProcessDefinitionPage(params: PageParam) { - return requestClient.get>( - '/bpm/process-definition/page', - { params }, - ); + return requestClient.get< + PageResult + >('/bpm/process-definition/page', { params }); } /** 查询流程定义列表 */ export async function getProcessDefinitionList(params: any) { - return requestClient.get>( - '/bpm/process-definition/list', - { - params, - }, - ); + return requestClient.get< + PageResult + >('/bpm/process-definition/list', { + params, + }); } /** 查询流程定义列表(简单列表) */ export async function getSimpleProcessDefinitionList() { - return requestClient.get>( - '/bpm/process-definition/simple-list', - ); + return requestClient.get< + PageResult + >('/bpm/process-definition/simple-list'); } diff --git a/apps/web-antd/src/api/bpm/oa/leave/index.ts b/apps/web-antd/src/api/bpm/oa/leave/index.ts new file mode 100644 index 000000000..4172ffbd0 --- /dev/null +++ b/apps/web-antd/src/api/bpm/oa/leave/index.ts @@ -0,0 +1,40 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace BpmOALeaveApi { + export interface LeaveVO { + id: number; + status: number; + type: number; + reason: string; + processInstanceId: string; + startTime: number; + endTime: number; + createTime: Date; + startUserSelectAssignees?: Record; + } +} + +/** 创建请假申请 */ +export async function createLeave(data: BpmOALeaveApi.LeaveVO) { + return requestClient.post('/bpm/oa/leave/create', data); +} + +/** 更新请假申请 */ +export async function updateLeave(data: BpmOALeaveApi.LeaveVO) { + return requestClient.post('/bpm/oa/leave/update', data); +} + +/** 获得请假申请 */ +export async function getLeave(id: number) { + return requestClient.get(`/bpm/oa/leave/get?id=${id}`); +} + +/** 获得请假申请分页 */ +export async function getLeavePage(params: PageParam) { + return requestClient.get>( + '/bpm/oa/leave/page', + { params }, + ); +} diff --git a/apps/web-antd/src/api/bpm/processInstance/index.ts b/apps/web-antd/src/api/bpm/processInstance/index.ts index f287ee0be..23afa8c30 100644 --- a/apps/web-antd/src/api/bpm/processInstance/index.ts +++ b/apps/web-antd/src/api/bpm/processInstance/index.ts @@ -1,7 +1,7 @@ import type { PageParam, PageResult } from '@vben/request'; import type { BpmModelApi } from '#/api/bpm/model'; -import type { CandidateStrategyEnum, NodeTypeEnum } from '#/utils'; +import type { BpmCandidateStrategyEnum, BpmNodeTypeEnum } from '#/utils'; import { requestClient } from '#/api/request'; @@ -29,12 +29,12 @@ export namespace BpmProcessInstanceApi { // 审批节点信息 export type ApprovalNodeInfo = { - candidateStrategy?: CandidateStrategyEnum; + candidateStrategy?: BpmCandidateStrategyEnum; candidateUsers?: User[]; endTime?: Date; id: number; name: string; - nodeType: NodeTypeEnum; + nodeType: BpmNodeTypeEnum; startTime?: Date; status: number; tasks: ApprovalTaskInfo[]; diff --git a/apps/web-antd/src/api/bpm/task/index.ts b/apps/web-antd/src/api/bpm/task/index.ts new file mode 100644 index 000000000..4054b8f6a --- /dev/null +++ b/apps/web-antd/src/api/bpm/task/index.ts @@ -0,0 +1,108 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; + +export namespace BpmTaskApi { + /** BPM 流程监听器 VO */ + export interface TaskVO { + id: number; // 编号 + name: string; // 监听器名字 + type: string; // 监听器类型 + status: number; // 监听器状态 + event: string; // 监听事件 + valueType: string; // 监听器值类型 + value: string; // 监听器值 + } +} + +/** 查询待办任务分页 */ +export async function getTaskTodoPage(params: PageParam) { + return requestClient.get>( + '/bpm/task/todo-page', + { + params, + }, + ); +} + +/** 查询已办任务分页 */ +export async function getTaskDonePage(params: PageParam) { + return requestClient.get>( + '/bpm/task/done-page', + { + params, + }, + ); +} + +/** 查询任务管理分页 */ +export async function getTaskManagerPage(params: PageParam) { + return requestClient.get>( + '/bpm/task/manager-page', + { params }, + ); +} + +/** 审批任务 */ +export const approveTask = async (data: any) => { + return await requestClient.put('/bpm/task/approve', data); +}; + +/** 驳回任务 */ +export const rejectTask = async (data: any) => { + return await requestClient.put('/bpm/task/reject', data); +}; + +/** 根据流程实例 ID 查询任务列表 */ +export const getTaskListByProcessInstanceId = async (data: any) => { + return await requestClient.get('/bpm/task/list-by-process-instance-id', data); +}; + +/** 获取所有可退回的节点 */ +export const getTaskListByReturn = async (data: any) => { + return await requestClient.get('/bpm/task/list-by-return', data); +}; + +/** 退回 */ +export const returnTask = async (data: any) => { + return await requestClient.put('/bpm/task/return', data); +}; + +// 委派 +export const delegateTask = async (data: any) => { + return await requestClient.put('/bpm/task/delegate', data); +}; + +// 转派 +export const transferTask = async (data: any) => { + return await requestClient.put('/bpm/task/transfer', data); +}; + +// 加签 +export const signCreateTask = async (data: any) => { + return await requestClient.put('/bpm/task/create-sign', data); +}; + +// 减签 +export const signDeleteTask = async (data: any) => { + return await requestClient.delete('/bpm/task/delete-sign', data); +}; + +// 抄送 +export const copyTask = async (data: any) => { + return await requestClient.put('/bpm/task/copy', data); +}; + +// 获取我的待办任务 +export const myTodoTask = async (processInstanceId: string) => { + return await requestClient.get( + `/bpm/task/my-todo?processInstanceId=${processInstanceId}`, + ); +}; + +// 获取加签任务列表 +export const getChildrenTaskList = async (id: string) => { + return await requestClient.get( + `/bpm/task/list-by-parent-task-id?parentTaskId=${id}`, + ); +}; diff --git a/apps/web-antd/src/components/user-select-modal/user-select-modal.vue b/apps/web-antd/src/components/user-select-modal/user-select-modal.vue index 198bad308..6b03d3086 100644 --- a/apps/web-antd/src/components/user-select-modal/user-select-modal.vue +++ b/apps/web-antd/src/components/user-select-modal/user-select-modal.vue @@ -53,7 +53,7 @@ const props = withDefaults( const emit = defineEmits<{ cancel: []; closed: []; - confirm: [value: number[]]; + confirm: [value: SystemUserApi.User[]]; 'update:value': [value: number[]]; }>(); @@ -265,7 +265,7 @@ const resetData = () => { }; // 打开弹窗 -const open = async () => { +const open = async (userIds: string[]) => { resetData(); loading.value = true; try { @@ -280,13 +280,13 @@ const open = async () => { await loadUserData(1, leftListState.value.pagination.pageSize); // 设置已选用户 - if (props.value?.length) { - selectedUserIds.value = props.value.map(String); - // 加载已选用户的完整信息 + if (userIds?.length) { + selectedUserIds.value = userIds.map(String); + // 加载已选用户的完整信息 TODO 目前接口暂不支持 多个用户ID 查询, 需要后端支持 const { list } = await getUserPage({ pageNo: 1, - pageSize: props.value.length, - userIds: props.value, + pageSize: 100, // 临时使用固定值确保能加载所有已选用户 + userIds, }); // 使用 Map 来去重,以用户 ID 为 key const userMap = new Map(userList.value.map((user) => [user.id, user])); @@ -358,7 +358,12 @@ const handleConfirm = () => { message.warning('请选择用户'); return; } - emit('confirm', selectedUserIds.value.map(Number)); + emit( + 'confirm', + userList.value.filter((user) => + selectedUserIds.value.includes(String(user.id)), + ), + ); modalApi.close(); }; @@ -436,7 +441,7 @@ defineExpose({ @search="handleUserSearch" >