From c37a0fefa1e2b44778e1ae8cc623cb68aacbe278 Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Fri, 17 Oct 2025 13:37:20 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=96=B0=E5=A2=9E=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=AE=A1=E6=89=B9=E7=9B=B8=E5=85=B3=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E5=92=8C=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 `flow-actions.vue` 审批操作按钮组件,支持撤销、编辑、删除、审批、驳回、终止、委托、转办、加签、减签等操作 - 新增 `approval-panel-drawer.vue` 审批详情抽屉组件,整合审批信息展示与操作按钮 - 新增 `task` 目录,包含任务列表页面及数据定义 - 修改 `copy-component.vue` 组件,支持自定义头像大小并优化样式 - 调整 `flow-preview.vue` 中 iframe 高度从 500px 增加到 600px - 优化 `processInstance/data.tsx` 查询条件,使用 `_nodeName` 替代 `nodeName` 避免冲突,并支持多选人员筛选 - 导出新增的审批面板抽屉组件 `ApprovalPanelDrawerComp` - 引入 `DefaultSlot` 组件用于自定义表单项渲染 - 定义 `ApprovalType` 类型用于区分不同审批场景(我的申请、审批、管理、只读) --- .../components/actions/flow-actions.vue | 423 ++++++++++++++++ .../workflow/components/actions/index.ts | 1 + .../workflow/components/approval-details.vue | 4 +- .../components/approval-panel-drawer.vue | 163 +++++++ .../workflow/components/copy-component.vue | 28 +- .../workflow/components/flow-preview.vue | 2 +- .../src/views/workflow/components/helper.tsx | 11 + .../src/views/workflow/components/index.ts | 4 +- .../views/workflow/components/task/data.tsx | 85 ++++ .../views/workflow/components/task/index.ts | 1 + .../views/workflow/components/task/task.vue | 92 ++++ .../views/workflow/components/task/types.d.ts | 18 + .../src/views/workflow/components/type.d.ts | 9 + .../views/workflow/processInstance/data.tsx | 22 +- .../views/workflow/processInstance/index.vue | 13 + .../src/views/workflow/task/myDocument.vue | 377 ++++++--------- .../src/views/workflow/task/taskCopyList.vue | 444 +++++++---------- .../src/views/workflow/task/taskFinish.vue | 444 +++++++---------- .../src/views/workflow/task/taskWaiting.vue | 452 +++++++----------- 19 files changed, 1503 insertions(+), 1090 deletions(-) create mode 100644 apps/web-antd/src/views/workflow/components/actions/flow-actions.vue create mode 100644 apps/web-antd/src/views/workflow/components/actions/index.ts create mode 100644 apps/web-antd/src/views/workflow/components/approval-panel-drawer.vue create mode 100644 apps/web-antd/src/views/workflow/components/task/data.tsx create mode 100644 apps/web-antd/src/views/workflow/components/task/index.ts create mode 100644 apps/web-antd/src/views/workflow/components/task/task.vue create mode 100644 apps/web-antd/src/views/workflow/components/task/types.d.ts create mode 100644 apps/web-antd/src/views/workflow/components/type.d.ts diff --git a/apps/web-antd/src/views/workflow/components/actions/flow-actions.vue b/apps/web-antd/src/views/workflow/components/actions/flow-actions.vue new file mode 100644 index 00000000..aa9629c9 --- /dev/null +++ b/apps/web-antd/src/views/workflow/components/actions/flow-actions.vue @@ -0,0 +1,423 @@ + + + + + + + + 撤销申请 + + + 重新编辑 + + + 删除 + + + + + 通过 + + + 终止 + + + 驳回 + + + + + delegationModalApi.open()" + > + 委托 + + transferModalApi.open()" + > + 转办 + + addSignatureModalApi.open()" + > + 加签 + + reductionSignatureModalApi.open()" + > + 减签 + + + + + 其他 + + + + + + + + + + + 流程干预 + updateAssigneeModalApi.open()"> + 修改办理人 + + + + + + + diff --git a/apps/web-antd/src/views/workflow/components/actions/index.ts b/apps/web-antd/src/views/workflow/components/actions/index.ts new file mode 100644 index 00000000..3daaedf1 --- /dev/null +++ b/apps/web-antd/src/views/workflow/components/actions/index.ts @@ -0,0 +1 @@ +export { default as FlowActions } from './flow-actions.vue'; diff --git a/apps/web-antd/src/views/workflow/components/approval-details.vue b/apps/web-antd/src/views/workflow/components/approval-details.vue index 1673e9c7..fd1579c4 100644 --- a/apps/web-antd/src/views/workflow/components/approval-details.vue +++ b/apps/web-antd/src/views/workflow/components/approval-details.vue @@ -1,6 +1,6 @@ diff --git a/apps/web-antd/src/views/workflow/components/approval-panel-drawer.vue b/apps/web-antd/src/views/workflow/components/approval-panel-drawer.vue new file mode 100644 index 00000000..592993ba --- /dev/null +++ b/apps/web-antd/src/views/workflow/components/approval-panel-drawer.vue @@ -0,0 +1,163 @@ + + + + + + + + + + + {{ currentTask.businessTitle ?? currentTask.flowName }} + + + + + + + + + {{ currentTask.createByName }} + + + + + 流程分类: {{ currentTask.categoryName }} + + + + + + + 提交时间: {{ currentTask.createTime }} + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web-antd/src/views/workflow/components/copy-component.vue b/apps/web-antd/src/views/workflow/components/copy-component.vue index d4ec395b..5ccb74e6 100644 --- a/apps/web-antd/src/views/workflow/components/copy-component.vue +++ b/apps/web-antd/src/views/workflow/components/copy-component.vue @@ -1,6 +1,6 @@ @@ -71,8 +87,9 @@ const displayedList = computed(() => { @@ -82,13 +99,14 @@ const displayedList = computed(() => { > +{{ userListModel.length - props.ellipseNumber }} - 选择人员 + 选择人员 - + diff --git a/apps/web-antd/src/views/workflow/components/helper.tsx b/apps/web-antd/src/views/workflow/components/helper.tsx index a4ec7a41..8830922e 100644 --- a/apps/web-antd/src/views/workflow/components/helper.tsx +++ b/apps/web-antd/src/views/workflow/components/helper.tsx @@ -1,3 +1,4 @@ +/* eslint-disable vue/one-component-per-file */ import { defineComponent, h, ref } from 'vue'; import { Modal } from 'ant-design-vue'; @@ -58,3 +59,13 @@ export function getDiffTimeString(dateTime: string) { const diffText = dayjs.duration(diffSeconds, 'seconds').humanize(); return diffText; } + +/** + * 使用默认插槽来定义schema + */ +export const DefaultSlot = defineComponent({ + name: 'DefaultSlot', + render() { + return {this.$slots.default?.()}; + }, +}); diff --git a/apps/web-antd/src/views/workflow/components/index.ts b/apps/web-antd/src/views/workflow/components/index.ts index 4155011d..825d8675 100644 --- a/apps/web-antd/src/views/workflow/components/index.ts +++ b/apps/web-antd/src/views/workflow/components/index.ts @@ -4,21 +4,23 @@ export { default as ApprovalCard } from './approval-card.vue'; * 审批同意 */ export { default as approvalModal } from './approval-modal.vue'; +export { default as ApprovalPanelDrawerComp } from './approval-panel-drawer.vue'; export { default as ApprovalPanel } from './approval-panel.vue'; /** * 审批驳回 */ export { default as approvalRejectionModal } from './approval-rejection-modal.vue'; export { default as ApprovalTimeline } from './approval-timeline.vue'; + /** * 选择抄送人 */ export { default as CopyComponent } from './copy-component.vue'; - /** * 详情信息 modal */ export { default as flowInfoModal } from './flow-info-modal.vue'; + /** * 流程干预 modal */ diff --git a/apps/web-antd/src/views/workflow/components/task/data.tsx b/apps/web-antd/src/views/workflow/components/task/data.tsx new file mode 100644 index 00000000..58358bdf --- /dev/null +++ b/apps/web-antd/src/views/workflow/components/task/data.tsx @@ -0,0 +1,85 @@ +import type { FormSchemaGetter } from '#/adapter/form'; +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { DictEnum } from '@vben/constants'; +import { getPopupContainer } from '@vben/utils'; + +import { getDictOptions } from '#/utils/dict'; +import { renderDict } from '#/utils/render'; + +export const querySchema: FormSchemaGetter = () => [ + { + component: 'Input', + fieldName: 'configName', + label: '参数名称', + }, + { + component: 'Input', + fieldName: 'configKey', + label: '参数键名', + }, + { + component: 'Select', + componentProps: { + getPopupContainer, + options: getDictOptions(DictEnum.SYS_YES_NO), + }, + fieldName: 'configType', + label: '系统内置', + }, + { + component: 'RangePicker', + fieldName: 'createTime', + label: '创建时间', + }, +]; + +export const columns: VxeGridProps['columns'] = [ + { + field: 'id', + title: 'ID', + }, + { + field: 'businessTitle', + title: '业务标题', + formatter: ({ cellValue }) => cellValue ?? '-', + }, + { + field: 'flowName', + title: '流程名称', + }, + { + field: 'flowCode', + title: '流程编码', + }, + { + field: 'nodeName', + title: '当前任务', + }, + { + field: 'processedByName', + title: '办理人', + formatter: ({ cellValue }) => cellValue?.split?.(',') ?? cellValue, + }, + { + field: 'flowStatus', + title: '流程状态', + slots: { + default: ({ row }) => { + return renderDict(row.flowStatus, DictEnum.WF_BUSINESS_STATUS); + }, + }, + }, + { + field: 'createTime', + title: '创建时间', + }, + // { + // field: 'action', + // fixed: 'right', + // slots: { default: 'action' }, + // title: '操作', + // resizable: false, + // width: 'auto', + // }, +]; diff --git a/apps/web-antd/src/views/workflow/components/task/index.ts b/apps/web-antd/src/views/workflow/components/task/index.ts new file mode 100644 index 00000000..1fa0e6a4 --- /dev/null +++ b/apps/web-antd/src/views/workflow/components/task/index.ts @@ -0,0 +1 @@ +export { default as TaskPage } from './task.vue'; diff --git a/apps/web-antd/src/views/workflow/components/task/task.vue b/apps/web-antd/src/views/workflow/components/task/task.vue new file mode 100644 index 00000000..af6064d0 --- /dev/null +++ b/apps/web-antd/src/views/workflow/components/task/task.vue @@ -0,0 +1,92 @@ + + + + + + tableApi.query()" /> + + diff --git a/apps/web-antd/src/views/workflow/components/task/types.d.ts b/apps/web-antd/src/views/workflow/components/task/types.d.ts new file mode 100644 index 00000000..d7ddabbb --- /dev/null +++ b/apps/web-antd/src/views/workflow/components/task/types.d.ts @@ -0,0 +1,18 @@ +import type { ApprovalType } from '../type'; + +import type { PageResult } from '#/api/common'; +import type { TaskInfo } from '#/api/workflow/task/model'; + +export {}; + +export interface TaskPageProps { + /** + * 表格显示的标题 + */ + tableTitle?: string; + /** + * 类型 + */ + type: ApprovalType; + listApi: (params?: any) => Promise>; +} diff --git a/apps/web-antd/src/views/workflow/components/type.d.ts b/apps/web-antd/src/views/workflow/components/type.d.ts new file mode 100644 index 00000000..7870f793 --- /dev/null +++ b/apps/web-antd/src/views/workflow/components/type.d.ts @@ -0,0 +1,9 @@ +export {}; + +/** + * myself 我发起的 + * readonly 只读 只用于查看 + * approve 审批 + * admin 流程监控 - 待办任务使用 + */ +export type ApprovalType = 'admin' | 'approve' | 'myself' | 'readonly'; diff --git a/apps/web-antd/src/views/workflow/processInstance/data.tsx b/apps/web-antd/src/views/workflow/processInstance/data.tsx index 6e7e711d..d3038180 100644 --- a/apps/web-antd/src/views/workflow/processInstance/data.tsx +++ b/apps/web-antd/src/views/workflow/processInstance/data.tsx @@ -1,18 +1,27 @@ import type { FormSchemaGetter } from '#/adapter/form'; import type { VxeGridProps } from '#/adapter/vxe-table'; +import { markRaw } from 'vue'; + import { DictEnum } from '@vben/constants'; import { OptionsTag } from '#/components/table'; import { renderDict } from '#/utils/render'; +import { CopyComponent } from '../components'; +import { DefaultSlot } from '../components/helper'; import { activityStatusOptions } from '../processDefinition/constant'; export const querySchema: FormSchemaGetter = () => [ + /** + * https://github.com/facebook/react/issues/6284 + * https://github.com/ant-design/ant-design/issues/2950#issuecomment-245852795 + * nodeName算一种`关键字` 会导致报错 + */ { component: 'Input', label: '任务名称', - fieldName: 'nodeName', + fieldName: '_nodeName', }, { component: 'Input', @@ -24,6 +33,17 @@ export const querySchema: FormSchemaGetter = () => [ label: '流程编码', fieldName: 'flowCode', }, + { + fieldName: 'createByIds', + defaultValue: [], + component: markRaw(DefaultSlot), + label: '申请人', + renderComponentContent: (model) => ({ + default: () => ( + + ), + }), + }, ]; export const columns: VxeGridProps['columns'] = [ diff --git a/apps/web-antd/src/views/workflow/processInstance/index.vue b/apps/web-antd/src/views/workflow/processInstance/index.vue index 653dca5e..a81ba2dd 100644 --- a/apps/web-antd/src/views/workflow/processInstance/index.vue +++ b/apps/web-antd/src/views/workflow/processInstance/index.vue @@ -13,6 +13,7 @@ import { $t } from '@vben/locales'; import { getVxePopupContainer } from '@vben/utils'; import { Modal, Popconfirm, RadioGroup, Space } from 'ant-design-vue'; +import { isArray } from 'lodash-es'; import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table'; import { @@ -95,6 +96,18 @@ const gridOptions: VxeGridProps = { Reflect.deleteProperty(formValues, 'category'); } + // 转换数据 + if (isArray(formValues.createByIds)) { + formValues.createByIds = (formValues.createByIds as Array).map( + (item) => item.userId, + ); + } + // 使用nodeName会导致选人组件hover报错 + if (formValues._nodeName) { + formValues.nodeName = formValues._nodeName; + Reflect.deleteProperty(formValues, '_nodeName'); + } + return await currentTypeApi({ pageNum: page.currentPage, pageSize: page.pageSize, diff --git a/apps/web-antd/src/views/workflow/task/myDocument.vue b/apps/web-antd/src/views/workflow/task/myDocument.vue index 12a39cf2..d3f612e7 100644 --- a/apps/web-antd/src/views/workflow/task/myDocument.vue +++ b/apps/web-antd/src/views/workflow/task/myDocument.vue @@ -1,257 +1,162 @@ - - - - - - - - - - - - - - - 搜索 - - - reload(false)" - > - - - - - - - - - - 搜索 - - - 重置 - - - - - - - - - - - - - - - - - - 没有更多数据了 - - - - - - - - - - 共 {{ taskTotal }} 条记录 - - - - - + + tableApi.query()" /> - - diff --git a/apps/web-antd/src/views/workflow/task/taskCopyList.vue b/apps/web-antd/src/views/workflow/task/taskCopyList.vue index 3505f8fe..6d557d9c 100644 --- a/apps/web-antd/src/views/workflow/task/taskCopyList.vue +++ b/apps/web-antd/src/views/workflow/task/taskCopyList.vue @@ -1,299 +1,183 @@ - - - - - - - - - - - - - - - - 搜索 - - - reload(false)" - > - - - (popoverOpen = true)" - @finish="handleFinish" - /> - - - - - - - - - - - - - - 搜索 - - - 重置 - - - - - - - - - - - - - - - - - - 没有更多数据了 - - - - - - - - - - 共 {{ taskTotal }} 条记录 - - - - - + + tableApi.query()" /> - - diff --git a/apps/web-antd/src/views/workflow/task/taskFinish.vue b/apps/web-antd/src/views/workflow/task/taskFinish.vue index d9641b0b..260b976a 100644 --- a/apps/web-antd/src/views/workflow/task/taskFinish.vue +++ b/apps/web-antd/src/views/workflow/task/taskFinish.vue @@ -1,299 +1,183 @@ - - - - - - - - - - - - - - - - 搜索 - - - reload(false)" - > - - - (popoverOpen = true)" - @finish="handleFinish" - /> - - - - - - - - - - - - - - 搜索 - - - 重置 - - - - - - - - - - - - - - - - - - 没有更多数据了 - - - - - - - - - - 共 {{ taskTotal }} 条记录 - - - - - + + tableApi.query()" /> - - diff --git a/apps/web-antd/src/views/workflow/task/taskWaiting.vue b/apps/web-antd/src/views/workflow/task/taskWaiting.vue index 4a2024af..640e1a4f 100644 --- a/apps/web-antd/src/views/workflow/task/taskWaiting.vue +++ b/apps/web-antd/src/views/workflow/task/taskWaiting.vue @@ -1,302 +1,188 @@ - - - - - - - - - - - - - - - - 搜索 - - - reload(false)" - > - - - (popoverOpen = true)" - @finish="handleFinish" - /> - - - - - - - - - - - - - - 搜索 - - - 重置 - - - - - - - - - - - - - - - - - - 没有更多数据了 - - - - - - - - - - 共 {{ taskTotal }} 条记录 - - - - - + + tableApi.query()" /> - -