From 77ba1ee68ff076ebead6505c55637ef53241d77c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 21 Oct 2025 09:41:25 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E3=80=90ele=E3=80=91bpm=20task=20?= =?UTF-8?q?=E7=9A=84=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-ele/src/api/bpm/definition/index.ts | 4 + apps/web-ele/src/api/bpm/model/index.ts | 2 +- .../src/api/bpm/processInstance/index.ts | 8 +- apps/web-ele/src/api/bpm/task/index.ts | 8 + apps/web-ele/src/views/bpm/task/copy/data.ts | 92 +++++++++++ .../web-ele/src/views/bpm/task/copy/index.vue | 85 ++++++++++ apps/web-ele/src/views/bpm/task/done/data.ts | 154 ++++++++++++++++++ .../web-ele/src/views/bpm/task/done/index.vue | 114 +++++++++++++ .../src/views/bpm/task/manager/data.ts | 104 ++++++++++++ .../src/views/bpm/task/manager/index.vue | 79 +++++++++ apps/web-ele/src/views/bpm/task/todo/data.ts | 131 +++++++++++++++ .../web-ele/src/views/bpm/task/todo/index.vue | 89 ++++++++++ 12 files changed, 867 insertions(+), 3 deletions(-) create mode 100644 apps/web-ele/src/views/bpm/task/copy/data.ts create mode 100644 apps/web-ele/src/views/bpm/task/copy/index.vue create mode 100644 apps/web-ele/src/views/bpm/task/done/data.ts create mode 100644 apps/web-ele/src/views/bpm/task/done/index.vue create mode 100644 apps/web-ele/src/views/bpm/task/manager/data.ts create mode 100644 apps/web-ele/src/views/bpm/task/manager/index.vue create mode 100644 apps/web-ele/src/views/bpm/task/todo/data.ts create mode 100644 apps/web-ele/src/views/bpm/task/todo/index.vue diff --git a/apps/web-ele/src/api/bpm/definition/index.ts b/apps/web-ele/src/api/bpm/definition/index.ts index befd60650..502d5e366 100644 --- a/apps/web-ele/src/api/bpm/definition/index.ts +++ b/apps/web-ele/src/api/bpm/definition/index.ts @@ -6,7 +6,10 @@ export namespace BpmProcessDefinitionApi { /** 流程定义 */ export interface ProcessDefinition { id: string; + key?: string; version: number; + name: string; + description: string; deploymentTime: number; suspensionState: number; modelType: number; @@ -15,6 +18,7 @@ export namespace BpmProcessDefinitionApi { bpmnXml?: string; simpleModel?: string; formFields?: string[]; + icon?: string; } } diff --git a/apps/web-ele/src/api/bpm/model/index.ts b/apps/web-ele/src/api/bpm/model/index.ts index 443b85c5e..cd2afbc84 100644 --- a/apps/web-ele/src/api/bpm/model/index.ts +++ b/apps/web-ele/src/api/bpm/model/index.ts @@ -52,7 +52,7 @@ export interface ModelCategoryInfo { } /** 获取流程模型列表 */ -export async function getModelList(name: string | undefined) { +export async function getModelList(name?: string) { return requestClient.get('/bpm/model/list', { params: { name }, }); diff --git a/apps/web-ele/src/api/bpm/processInstance/index.ts b/apps/web-ele/src/api/bpm/processInstance/index.ts index 369e0dddd..32e0075b9 100644 --- a/apps/web-ele/src/api/bpm/processInstance/index.ts +++ b/apps/web-ele/src/api/bpm/processInstance/index.ts @@ -1,5 +1,8 @@ +import type { + BpmCandidateStrategyEnum, + BpmNodeTypeEnum, +} from '@vben/constants'; import type { PageParam, PageResult } from '@vben/request'; -import type { BpmCandidateStrategyEnum, BpmNodeTypeEnum } from '@vben/utils'; import type { BpmTaskApi } from '../task'; @@ -35,11 +38,12 @@ export namespace BpmProcessInstanceApi { candidateStrategy?: BpmCandidateStrategyEnum; candidateUsers?: User[]; endTime?: Date; - id: number; + id: string; name: string; nodeType: BpmNodeTypeEnum; startTime?: Date; status: number; + processInstanceId?: string; tasks: ApprovalTaskInfo[]; } diff --git a/apps/web-ele/src/api/bpm/task/index.ts b/apps/web-ele/src/api/bpm/task/index.ts index 510ea1747..63e1af886 100644 --- a/apps/web-ele/src/api/bpm/task/index.ts +++ b/apps/web-ele/src/api/bpm/task/index.ts @@ -13,6 +13,7 @@ export namespace BpmTaskApi { status: number; // 监听器状态 event: string; // 监听事件 valueType: string; // 监听器值类型 + processInstance?: BpmProcessInstanceApi.ProcessInstance; // 流程实例 } // 流程任务 @@ -130,3 +131,10 @@ export const getChildrenTaskList = async (id: string) => { `/bpm/task/list-by-parent-task-id?parentTaskId=${id}`, ); }; + +// 撤回任务 +export const withdrawTask = async (taskId: string) => { + return await requestClient.put('/bpm/task/withdraw', null, { + params: { taskId }, + }); +}; diff --git a/apps/web-ele/src/views/bpm/task/copy/data.ts b/apps/web-ele/src/views/bpm/task/copy/data.ts new file mode 100644 index 000000000..202887d73 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/copy/data.ts @@ -0,0 +1,92 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '流程名称', + component: 'Input', + componentProps: { + placeholder: '请输入流程名称', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '抄送时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'processInstanceName', + title: '流程名称', + minWidth: 200, + }, + { + field: 'summary', + title: '摘要', + minWidth: 200, + formatter: ({ cellValue }) => { + return cellValue && cellValue.length > 0 + ? cellValue + .map((item: any) => `${item.key} : ${item.value}`) + .join('\n') + : '-'; + }, + }, + { + field: 'startUser.nickname', + title: '流程发起人', + minWidth: 120, + }, + { + field: 'processInstanceStartTime', + title: '流程发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'activityName', + title: '抄送节点', + minWidth: 120, + }, + { + field: 'createUser.nickname', + title: '抄送人', + minWidth: 120, + formatter: ({ cellValue }) => { + return cellValue || '-'; + }, + }, + { + field: 'reason', + title: '抄送意见', + minWidth: 180, + }, + { + field: 'createTime', + title: '抄送时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/task/copy/index.vue b/apps/web-ele/src/views/bpm/task/copy/index.vue new file mode 100644 index 000000000..b60a02c3f --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/copy/index.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/bpm/task/done/data.ts b/apps/web-ele/src/views/bpm/task/done/data.ts new file mode 100644 index 000000000..3c5e9f678 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/done/data.ts @@ -0,0 +1,154 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getCategorySimpleList } from '#/api/bpm/category'; +import { getSimpleProcessDefinitionList } from '#/api/bpm/definition'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '任务名称', + component: 'Input', + componentProps: { + placeholder: '请输入任务名称', + allowClear: true, + }, + }, + { + fieldName: 'processDefinitionKey', + label: '所属流程', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择流程定义', + allowClear: true, + api: getSimpleProcessDefinitionList, + labelField: 'name', + valueField: 'key', + }, + }, + { + fieldName: 'category', + label: '流程分类', + component: 'ApiSelect', + componentProps: { + placeholder: '请输入流程分类', + allowClear: true, + api: getCategorySimpleList, + labelField: 'name', + valueField: 'code', + }, + }, + { + fieldName: 'status', + label: '审批状态', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.BPM_TASK_STATUS, 'number'), + placeholder: '请选择审批状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '发起时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'processInstance.name', + title: '流程', + minWidth: 200, + }, + { + field: 'processInstance.summary', + title: '摘要', + minWidth: 200, + formatter: ({ cellValue }) => { + return cellValue && cellValue.length > 0 + ? cellValue + .map((item: any) => `${item.key} : ${item.value}`) + .join('\n') + : '-'; + }, + }, + { + field: 'processInstance.startUser.nickname', + title: '发起人', + minWidth: 120, + }, + { + field: 'processInstance.createTime', + title: '发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'name', + title: '当前任务', + minWidth: 180, + }, + { + field: 'createTime', + title: '任务开始时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '任务结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'status', + title: '审批状态', + minWidth: 180, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_TASK_STATUS }, + }, + }, + { + field: 'reason', + title: '审批建议', + minWidth: 180, + }, + { + field: 'durationInMillis', + title: '耗时', + minWidth: 180, + formatter: 'formatPast2', + }, + { + field: 'processInstanceId', + title: '流程编号', + minWidth: 280, + }, + { + field: 'id', + title: '任务编号', + minWidth: 280, + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/task/done/index.vue b/apps/web-ele/src/views/bpm/task/done/index.vue new file mode 100644 index 000000000..cc1aba780 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/done/index.vue @@ -0,0 +1,114 @@ + + + diff --git a/apps/web-ele/src/views/bpm/task/manager/data.ts b/apps/web-ele/src/views/bpm/task/manager/data.ts new file mode 100644 index 000000000..947982b23 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/manager/data.ts @@ -0,0 +1,104 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '任务名称', + component: 'Input', + componentProps: { + placeholder: '请输入任务名称', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'processInstance.name', + title: '流程', + minWidth: 200, + }, + { + field: 'processInstance.startUser.nickname', + title: '发起人', + minWidth: 120, + }, + { + field: 'name', + title: '当前任务', + minWidth: 180, + }, + { + field: 'createTime', + title: '任务开始时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '任务结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'assigneeUser.nickname', + title: '审批人', + minWidth: 180, + }, + { + field: 'status', + title: '审批状态', + minWidth: 180, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_TASK_STATUS }, + }, + }, + { + field: 'reason', + title: '审批建议', + minWidth: 180, + }, + { + field: 'durationInMillis', + title: '耗时', + minWidth: 180, + formatter: 'formatPast2', + }, + { + field: 'processInstanceId', + title: '流程编号', + minWidth: 280, + }, + { + field: 'id', + title: '任务编号', + minWidth: 280, + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/task/manager/index.vue b/apps/web-ele/src/views/bpm/task/manager/index.vue new file mode 100644 index 000000000..9490665dd --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/manager/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/apps/web-ele/src/views/bpm/task/todo/data.ts b/apps/web-ele/src/views/bpm/task/todo/data.ts new file mode 100644 index 000000000..0b1efd71c --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/todo/data.ts @@ -0,0 +1,131 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { getCategorySimpleList } from '#/api/bpm/category'; +import { getSimpleProcessDefinitionList } from '#/api/bpm/definition'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '任务名称', + component: 'Input', + componentProps: { + placeholder: '请输入任务名称', + allowClear: true, + }, + }, + { + fieldName: 'processDefinitionKey', + label: '所属流程', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择流程定义', + allowClear: true, + api: getSimpleProcessDefinitionList, + labelField: 'name', + valueField: 'key', + }, + }, + { + fieldName: 'category', + label: '流程分类', + component: 'ApiSelect', + componentProps: { + placeholder: '请输入流程分类', + allowClear: true, + api: getCategorySimpleList, + labelField: 'name', + valueField: 'code', + }, + }, + { + fieldName: 'status', + label: '流程状态', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, + 'number', + ), + placeholder: '请选择流程状态', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '发起时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'processInstance.name', + title: '流程', + minWidth: 200, + }, + { + field: 'processInstance.summary', + title: '摘要', + minWidth: 200, + formatter: ({ cellValue }) => { + return cellValue && cellValue.length > 0 + ? cellValue + .map((item: any) => `${item.key} : ${item.value}`) + .join('\n') + : '-'; + }, + }, + { + field: 'processInstance.startUser.nickname', + title: '发起人', + minWidth: 120, + }, + { + field: 'processInstance.createTime', + title: '发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'name', + title: '当前任务', + minWidth: 180, + }, + { + field: 'createTime', + title: '任务时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'processInstanceId', + title: '流程编号', + minWidth: 280, + }, + { + field: 'id', + title: '任务编号', + minWidth: 280, + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/bpm/task/todo/index.vue b/apps/web-ele/src/views/bpm/task/todo/index.vue new file mode 100644 index 000000000..d80830739 --- /dev/null +++ b/apps/web-ele/src/views/bpm/task/todo/index.vue @@ -0,0 +1,89 @@ + + +