From 523aca6b75c533a66ed38cf733e91ff0305088c0 Mon Sep 17 00:00:00 2001 From: AN <1983933789@qq.com> Date: Sun, 13 Jul 2025 22:07:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(projects):=20=E6=96=B0=E5=A2=9E=E6=8A=84?= =?UTF-8?q?=E9=80=81=E3=80=81=E4=B8=8B=E4=B8=80=E5=AE=A1=E6=89=B9=E4=BA=BA?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=80=9A=E7=94=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/custom/group-tag.vue | 25 +- src/components/custom/user-select-modal.vue | 65 +++- .../custom/workflow/flow-intervene-modal.vue | 2 + .../workflow/flow-task-approval-modal.vue | 277 +++++++++++++++--- src/service/api/workflow/task.ts | 9 + src/typings/api/system.api.d.ts | 1 + src/typings/api/workflow.api.d.ts | 47 +++ 7 files changed, 377 insertions(+), 49 deletions(-) diff --git a/src/components/custom/group-tag.vue b/src/components/custom/group-tag.vue index 02787c70..14ca840c 100644 --- a/src/components/custom/group-tag.vue +++ b/src/components/custom/group-tag.vue @@ -7,19 +7,31 @@ interface Props { type?: NaiveUI.ThemeColor; size?: 'small' | 'medium' | 'large'; placeholder?: string; + closable?: boolean; } const props = withDefaults(defineProps(), { type: 'info', size: 'small', - placeholder: '无' + placeholder: '无', + closable: false }); +interface Emits { + (e: 'close', index?: number): void; +} + +const emit = defineEmits(); + // 统一解析 value 成数组 const tags = computed(() => { if (!props.value) return []; return Array.isArray(props.value) ? props.value : props.value.split(','); }); + +function handleClose(index?: number) { + emit('close', index); +} @@ -41,7 +53,14 @@ const tags = computed(() => { {{ tags[0] }}...({{ tags.length }}) - + {{ tag }} diff --git a/src/components/custom/user-select-modal.vue b/src/components/custom/user-select-modal.vue index 8684e94a..e7f80cc3 100644 --- a/src/components/custom/user-select-modal.vue +++ b/src/components/custom/user-select-modal.vue @@ -19,16 +19,20 @@ interface Props { multiple?: boolean; /** 禁选用户ID */ disabledIds?: CommonType.IdType[]; + rowKeys?: CommonType.IdType[]; + searchUserIds?: string | null; } const props = withDefaults(defineProps(), { title: '用户选择', multiple: false, - disabledIds: () => [] + disabledIds: () => [], + rowKeys: () => [], + searchUserIds: null }); interface Emits { - (e: 'confirm', value: CommonType.IdType[]): void; + (e: 'confirm', value: CommonType.IdType[], rows?: Api.System.User[]): void; } const emit = defineEmits(); @@ -128,6 +132,23 @@ const { const { checkedRowKeys } = useTableOperate(data, getData); +// 存储所有页面的用户数据,用于跨页选择 +const allPagesData = ref([]); + +// 更新allPagesData,保存当前页数据 +function updateAllPagesData() { + // 将当前页数据添加到allPagesData中,避免重复 + data.value.forEach(user => { + const existIndex = allPagesData.value.findIndex(item => item.userId === user.userId); + if (existIndex === -1) { + allPagesData.value.push(user); + } else { + // 更新已存在的数据 + allPagesData.value[existIndex] = user; + } + }); +} + const { loading: treeLoading, startLoading: startTreeLoading, endLoading: endTreeLoading } = useLoading(); const deptPattern = ref(); const deptData = ref([]); @@ -165,38 +186,64 @@ function handleResetSearch() { } function closeModal() { + checkedRowKeys.value = []; + allPagesData.value = []; visible.value = false; } function handleConfirm() { - emit('confirm', checkedRowKeys.value); + // 获取选中行对应的用户对象(从所有页面数据中筛选) + const selectedUsers = allPagesData.value.filter(item => checkedRowKeys.value.includes(item.userId.toString())); + emit('confirm', checkedRowKeys.value, selectedUsers); closeModal(); } function getRowProps(row: Api.System.User) { return { - onClick: () => { + onClick: (e: MouseEvent) => { + const target = e.target as HTMLElement; + if (target.closest('.n-data-table-td--selection')) { + return; + } if (props.disabledIds.includes(row.userId.toString())) { return; } + + // 将userId转为字符串 + const userId = row.userId.toString(); + if (props.multiple) { - const index = checkedRowKeys.value.findIndex(key => key === row.userId); + const index = checkedRowKeys.value.findIndex(key => key === userId); if (index > -1) { checkedRowKeys.value.splice(index, 1); } else { - checkedRowKeys.value.push(row.userId); + checkedRowKeys.value.push(userId); } } else { - checkedRowKeys.value = [row.userId]; + checkedRowKeys.value = [userId]; } } }; } +// 监听数据变化(页面切换时) +watch( + data, + () => { + updateAllPagesData(); + }, + { deep: true } +); + watch(visible, () => { if (visible.value) { getTreeData(); - getData(); + if (props.searchUserIds) { + searchParams.userIds = props.searchUserIds; + } + allPagesData.value = []; + getDataByPage(); + checkedRowKeys.value = [...props.rowKeys]; } }); @@ -273,7 +320,7 @@ watch(visible, () => { :loading="loading" :row-props="getRowProps" remote - :row-key="row => row.userId" + :row-key="row => row.userId.toString()" :pagination="mobilePagination" class="h-full lt-sm:max-h-300px" /> diff --git a/src/components/custom/workflow/flow-intervene-modal.vue b/src/components/custom/workflow/flow-intervene-modal.vue index b85fe1b0..c878ace5 100644 --- a/src/components/custom/workflow/flow-intervene-modal.vue +++ b/src/components/custom/workflow/flow-intervene-modal.vue @@ -64,6 +64,7 @@ function handleTransferConfirm(ids: CommonType.IdType[]) { return; } model.userId = ids[0]; + model.taskId = props.taskId; window.$dialog?.warning({ title: '提示', content: '是否确认转办?', @@ -107,6 +108,7 @@ function handleAddSignatureConfirm(ids: CommonType.IdType[]) { } function handleTerminate() { + terminateModel.taskId = props.taskId; window.$dialog?.warning({ title: '提示', content: '是否确认中止?', diff --git a/src/components/custom/workflow/flow-task-approval-modal.vue b/src/components/custom/workflow/flow-task-approval-modal.vue index 9d932422..6138727a 100644 --- a/src/components/custom/workflow/flow-task-approval-modal.vue +++ b/src/components/custom/workflow/flow-task-approval-modal.vue @@ -1,8 +1,9 @@ diff --git a/src/service/api/workflow/task.ts b/src/service/api/workflow/task.ts index 1a2bbf17..028bbd82 100644 --- a/src/service/api/workflow/task.ts +++ b/src/service/api/workflow/task.ts @@ -17,6 +17,15 @@ export function fetchGetTask(taskId: CommonType.IdType) { }); } +/** 获取任务下一个节点 */ +export function fetchGetkNextNode(data: Api.Workflow.TaskNextNodeSearchParams) { + return request({ + url: '/workflow/task/getNextNodeList', + method: 'post', + data + }); +} + /** 完成任务 */ export function fetchCompleteTask(data: Api.Workflow.CompleteTaskOperateParams) { return request({ diff --git a/src/typings/api/system.api.d.ts b/src/typings/api/system.api.d.ts index 8e779f31..0568907e 100644 --- a/src/typings/api/system.api.d.ts +++ b/src/typings/api/system.api.d.ts @@ -128,6 +128,7 @@ declare namespace Api { type UserSearchParams = CommonType.RecordNullable< Pick & { roleId: CommonType.IdType; + userIds: string; } & Common.CommonSearchParams >; diff --git a/src/typings/api/workflow.api.d.ts b/src/typings/api/workflow.api.d.ts index 1299e70a..b7c60886 100644 --- a/src/typings/api/workflow.api.d.ts +++ b/src/typings/api/workflow.api.d.ts @@ -428,6 +428,10 @@ declare namespace Api { createByIds: CommonType.IdType[]; } >; + type TaskNextNodeSearchParams = CommonType.RecordNullable<{ + taskId: CommonType.IdType; + taskVariables: { [key: string]: any }; + }>; /** 消息类型 */ type MessageType = '1' | '2' | '3'; @@ -455,5 +459,48 @@ declare namespace Api { /** 扩展字段 */ ext: string; }>; + + /** 工作流节点 */ + type FlowNode = Common.CommonRecord<{ + /** 节点ID */ + id: CommonType.IdType; + /** 删除标志 */ + delFlag: string; + /** 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) */ + nodeType: WorkflowNodeType; + /** 流程定义ID */ + definitionId: CommonType.IdType; + /** 节点编码 */ + nodeCode: string; + /** 节点名称 */ + nodeName: string; + /** 权限标识 */ + permissionFlag: string; + /** 流程签署比例值 */ + nodeRatio: string; + /** 节点坐标 */ + coordinate: string; + /** 流程版本号 */ + version: string; + /** 是否允许任意节点跳转 */ + anyNodeSkip: string; + /** 监听器类型 */ + listenerType: string; + /** 监听器路径 */ + listenerPath: string; + /** 处理器类型 */ + handlerType: string; + /** 处理器路径 */ + handlerPath: string; + /** 审批表单是否自定义(Y是 N否) */ + formCustom: Api.Common.YesOrNoStatus; + /** 审批表单路径 */ + formPath: string; + /** 扩展字段 */ + ext: string; + }>; + + /** 工作流节点列表 */ + type FlowNodeList = FlowNode[]; } }