Bladeren bron

!172 合并 warmflow 功能分支
* update 优化 流程定义页面 点击复制之后跳转到未发布列表
* update 优化 流程定义页面 增加加载loading层
* fix: v-model处理有延迟 需要手动处理
* update 调整流程定义查询
* Merge remote-tracking branch 'origin/dev' into warm-flw-future
* update 调整可驳回的节点
* update: 调整文案
* update: 激活/挂起改为switch操作
* update 优化 代码删除无用输出
* update 统一抄送人使用昵称展示
* update 调整分类接口
* update 统一业务id参数
* update 删除默认顶节点
* !168 优化流程分类
* update 恢复误删除代码
* update 优化流程分类
* update 修复 路由跳转未改全
* [update]
* fix 修复一些问题
* update 重构流程分类表
* update 流程定义增加表单路径与编辑功能 修复一些其他bug
* fix 修复 一些问题
* update 变量统一命名
* add 增加示例
* Merge branch 'warm-flw-future' of https://gitee.com/JavaLionLi/plus-ui…
* update 调整办理人
* Merge remote-tracking branch 'origin/dev' into warm-flw-future
* add 增加示例
* update 调整审批记录 添加流程导出
* remove 删除无用代码
* remove 删除无用代码
* [update]
* [fix]
* 流程干预删除委托
* 增加附件
* 附件修改
* 申请人查询修改
* 1.修改查询条件
* !167 fix 修复 import路径修改不全问题
* fix 修复 import路径修改不全问题
* !166 update 清除 ProcessPreview 引用
* update 清除 ProcessPreview 引用
* remove 删除 bpmn.js 设计器
* remove 删除 bpmn.js 设计器
* remove 删除 bpmn.js 设计器
* remove 删除 bpmn.js 设计器
* fix 修复 前端路径修改不全问题
* update 优化接口请求路径
* add 添加作废
* add 添加流程干预
* update 调整加签,减签
* update 调整加签,减签
* add 增加流程查看
* update 调整委托,转办
* update 调整流程变量显示
* update 调整办理人修改
* update 调整流程实例状态页面
* update 调整已办页面
* add 添加流程撤销
* update 调整任务,流程实例 ,流程定义页面
* Merge branch 'dev' into warm-flw-future
* update 调整流程定义页面
* add 添加流程变量查看
* update 调整设计器路由名称
* update 调整办理人
* update 调整设计器uri
* update 调整设计器请求uri 调整待办状态
* update 调整办理 驳回 终止等状态
* add 添加模型新增
* add 添加warm-ui设计器,删除无用代码
* Merge remote-tracking branch 'origin/dev' into warm-flw-future
* add 添加流程设计
* update 调整驳回
* update 调整视图类型错误
* Merge branch 'warm-flw-future' of https://gitee.com/JavaLionLi/plus-ui…
* 添加已办,未办
* Merge remote-tracking branch 'origin/dev' into warm-flw-future
* update 调整流程实例,待办查询
* add 添加代办人,调整提交按钮校验
* update 调整流程定义查询
* add添加流程定义激活 挂起
* add 添加流程文件部署 调整流程发布
* update 优化 时间搜索组件统一
* Merge remote-tracking branch 'origin/dev' into warm-flw-future
* fix 修复 用户管理编辑安全权限错误问题
* Merge remote-tracking branch 'origin/dev' into warm-flw-future
* update 优化 类型报错问题
* update 优化 切换租户后刷新首页
* update 优化 实现表格行选中切换
* update 优化 使用 vueuse 重构 websocket 实现
* update 优化 使用 vueuse 重构 websocket 实现
* fix 修复 登出后重新登录 sse推送报错问题
* reset 回滚 代码修改 采用其他方案
* fix 修复 登出后重新登录 sse推送报错问题
* update 优化 删除无用代码
* update element-plus 2.7.5 => 2.7.8
* reset 回滚 错误修复
* update 优化 代码生成器编辑页禁用缓存 防止同步后页面不更新问题
* fix 修复 代码生成同步点击取消报错问题
* 初始化添加warm-flow

疯狂的狮子Li 1 jaar geleden
bovenliggende
commit
e423d8afcf
78 gewijzigde bestanden met toevoegingen van 1947 en 8754 verwijderingen
  1. 0 1
      package.json
  2. 13 2
      src/api/system/dept/index.ts
  3. 20 7
      src/api/workflow/category/index.ts
  4. 33 28
      src/api/workflow/category/types.ts
  5. 170 0
      src/api/workflow/definition/index.ts
  6. 31 0
      src/api/workflow/definition/types.ts
  7. 0 49
      src/api/workflow/definitionConfig/index.ts
  8. 0 102
      src/api/workflow/definitionConfig/types.ts
  9. 0 76
      src/api/workflow/formManage/index.ts
  10. 0 69
      src/api/workflow/formManage/types.ts
  11. 101 0
      src/api/workflow/instance/index.ts
  12. 26 0
      src/api/workflow/instance/types.ts
  13. 0 104
      src/api/workflow/model/index.ts
  14. 0 66
      src/api/workflow/model/types.ts
  15. 0 38
      src/api/workflow/nodeConfig/types.ts
  16. 0 114
      src/api/workflow/processDefinition/index.ts
  17. 0 24
      src/api/workflow/processDefinition/types.ts
  18. 0 136
      src/api/workflow/processInstance/index.ts
  19. 0 27
      src/api/workflow/processInstance/types.ts
  20. 28 112
      src/api/workflow/task/index.ts
  21. 33 34
      src/api/workflow/task/types.ts
  22. 9 23
      src/api/workflow/workflowCommon/index.ts
  23. 6 9
      src/api/workflow/workflowCommon/types.ts
  24. 0 10
      src/assets/styles/variables.module.scss
  25. 0 23
      src/bpmn/assets/defaultXML.ts
  26. 0 126
      src/bpmn/assets/lang/zh.ts
  27. 0 1250
      src/bpmn/assets/moddle/flowable.ts
  28. 0 138
      src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts
  29. 0 109
      src/bpmn/assets/module/Palette/CustomPaletteProvider.ts
  30. 0 56
      src/bpmn/assets/module/Renderer/CustomRenderer.ts
  31. 0 15
      src/bpmn/assets/module/Translate/index.ts
  32. 0 17
      src/bpmn/assets/module/index.ts
  33. 0 50
      src/bpmn/assets/showConfig.ts
  34. 0 284
      src/bpmn/assets/style/index.scss
  35. 0 145
      src/bpmn/hooks/usePanel.ts
  36. 0 34
      src/bpmn/hooks/useParseElement.ts
  37. 0 496
      src/bpmn/index.vue
  38. 0 68
      src/bpmn/panel/GatewayPanel.vue
  39. 0 68
      src/bpmn/panel/ParticipantPanel.vue
  40. 0 71
      src/bpmn/panel/ProcessPanel.vue
  41. 0 95
      src/bpmn/panel/SequenceFlowPanel.vue
  42. 0 67
      src/bpmn/panel/StartEndPanel.vue
  43. 0 193
      src/bpmn/panel/SubProcessPanel.vue
  44. 0 491
      src/bpmn/panel/TaskPanel.vue
  45. 0 110
      src/bpmn/panel/index.vue
  46. 0 252
      src/bpmn/panel/property/DueDate.vue
  47. 0 308
      src/bpmn/panel/property/ExecutionListener.vue
  48. 0 121
      src/bpmn/panel/property/ListenerParam.vue
  49. 0 310
      src/bpmn/panel/property/TaskListener.vue
  50. 0 71
      src/components/BpmnDesign/index.vue
  51. 0 411
      src/components/BpmnView/index.vue
  52. 52 28
      src/components/Process/approvalRecord.vue
  53. 0 378
      src/components/Process/multiInstanceUser.vue
  54. 207 0
      src/components/Process/processMeddle.vue
  55. 139 87
      src/components/Process/submitVerify.vue
  56. 4 4
      src/components/UserSelect/index.vue
  57. 0 17
      src/enums/bpmn/IndexEnums.ts
  58. 14 0
      src/router/index.ts
  59. 0 76
      src/store/modules/modeler.ts
  60. 0 13
      src/types/bpmn/editor/global.d.ts
  61. 0 15
      src/types/bpmn/index.d.ts
  62. 0 37
      src/types/bpmn/moddle.d.ts
  63. 0 92
      src/types/bpmn/panel.d.ts
  64. 94 100
      src/views/workflow/category/index.vue
  65. 0 243
      src/views/workflow/formManage/index.vue
  66. 28 34
      src/views/workflow/leave/index.vue
  67. 63 7
      src/views/workflow/leave/leaveEdit.vue
  68. 0 383
      src/views/workflow/model/index.vue
  69. 0 45
      src/views/workflow/processDefinition/components/processPreview.vue
  70. 52 0
      src/views/workflow/processDefinition/design.vue
  71. 284 300
      src/views/workflow/processDefinition/index.vue
  72. 205 152
      src/views/workflow/processInstance/index.vue
  73. 118 153
      src/views/workflow/task/allTaskWaiting.vue
  74. 64 74
      src/views/workflow/task/myDocument.vue
  75. 21 36
      src/views/workflow/task/taskCopyList.vue
  76. 70 27
      src/views/workflow/task/taskFinish.vue
  77. 62 33
      src/views/workflow/task/taskWaiting.vue
  78. 0 10
      vite.config.ts

+ 0 - 1
package.json

@@ -27,7 +27,6 @@
     "animate.css": "4.1.1",
     "await-to-js": "3.0.0",
     "axios": "1.7.8",
-    "bpmn-js": "16.4.0",
     "crypto-js": "4.2.0",
     "diagram-js": "12.3.0",
     "didi": "9.0.2",

+ 13 - 2
src/api/system/dept/index.ts

@@ -1,6 +1,6 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
-import { DeptForm, DeptQuery, DeptVO } from './types';
+import {DeptForm, DeptQuery, DeptTreeVO, DeptVO} from './types';
 
 // 查询部门列表
 export const listDept = (query?: DeptQuery) => {
@@ -11,6 +11,17 @@ export const listDept = (query?: DeptQuery) => {
   });
 };
 
+/**
+ * 通过deptIds查询部门
+ * @param deptIds
+ */
+export const optionSelect = (deptIds: (number | string)[]): AxiosPromise<DeptVO[]> => {
+  return request({
+    url: '/system/dept/optionselect?deptIds=' + deptIds,
+    method: 'get'
+  });
+};
+
 // 查询部门列表(排除节点)
 export const listDeptExcludeChild = (deptId: string | number): AxiosPromise<DeptVO[]> => {
   return request({
@@ -28,7 +39,7 @@ export const getDept = (deptId: string | number): AxiosPromise<DeptVO> => {
 };
 
 // 查询部门下拉树结构
-export const treeselect = (): AxiosPromise<DeptVO[]> => {
+export const treeselect = (): AxiosPromise<DeptTreeVO[]> => {
   return request({
     url: '/system/dept/treeselect',
     method: 'get'

+ 20 - 7
src/api/workflow/category/index.ts

@@ -1,6 +1,6 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
-import { CategoryVO, CategoryForm, CategoryQuery } from '@/api/workflow/category/types';
+import { CategoryVO, CategoryForm, CategoryQuery, CategoryTreeVO } from '@/api/workflow/category/types';
 
 /**
  * 查询流程分类列表
@@ -18,11 +18,11 @@ export const listCategory = (query?: CategoryQuery): AxiosPromise<CategoryVO[]>
 
 /**
  * 查询流程分类详细
- * @param id
+ * @param categoryId
  */
-export const getCategory = (id: string | number): AxiosPromise<CategoryVO> => {
+export const getCategory = (categoryId: string | number): AxiosPromise<CategoryVO> => {
   return request({
-    url: '/workflow/category/' + id,
+    url: '/workflow/category/' + categoryId,
     method: 'get'
   });
 };
@@ -53,11 +53,24 @@ export const updateCategory = (data: CategoryForm) => {
 
 /**
  * 删除流程分类
- * @param id
+ * @param categoryId
  */
-export const delCategory = (id: string | number | Array<string | number>) => {
+export const delCategory = (categoryId: string | number | Array<string | number>) => {
   return request({
-    url: '/workflow/category/' + id,
+    url: '/workflow/category/' + categoryId,
     method: 'delete'
   });
 };
+
+/**
+ * 获取流程分类树列表
+ * @param query 流程实例id
+ * @returns
+ */
+export const categoryTree = (query?: CategoryForm): AxiosPromise<CategoryTreeVO[]> => {
+  return request({
+    url: `/workflow/category/categoryTree`,
+    method: 'get',
+    params: query
+  });
+};

+ 33 - 28
src/api/workflow/category/types.ts

@@ -1,67 +1,72 @@
+export interface CategoryTreeVO {
+  id: number | string;
+  label: string;
+  parentId: number | string;
+  weight: number;
+  children: CategoryTreeVO[];
+}
 export interface CategoryVO {
+
   /**
-   * 主键
+   * 流程分类ID
    */
-  id: string;
+  categoryId: string | number;
 
   /**
-   * 分类名称
+   * 父级id
    */
-  categoryName: string;
+  parentId: string | number;
 
   /**
-   * 分类编码
+   * 流程分类名称
    */
-  categoryCode: string;
+  categoryName: string;
 
   /**
-   * 父级id
+   * 显示顺序
    */
-  parentId: string | number;
+  orderNum: number;
 
   /**
-   * 排序
+   * 创建时间
    */
-  sortNum: number;
+  createTime: string;
 
-  children?: CategoryVO[];
+  /**
+   * 子对象
+   */
+  children: CategoryVO[];
 }
 
 export interface CategoryForm extends BaseEntity {
-  /**
-   * 主键
-   */
-  id?: string | number;
 
   /**
-   * 分类名称
+   * 流程分类ID
    */
-  categoryName?: string;
+  categoryId?: string | number;
 
   /**
-   * 分类编码
+   * 流程分类名称
    */
-  categoryCode?: string;
+  categoryName?: string;
 
   /**
-   * 父id
+   * 父流程分类id
    */
   parentId?: string | number;
 
   /**
-   * 
+   * 显示顺
    */
-  sortNum?: number;
+  orderNum?: number;
+
 }
 
-export interface CategoryQuery extends PageQuery {
+export interface CategoryQuery {
+
   /**
-   * 分类名称
+   * 流程分类名称
    */
   categoryName?: string;
 
-  /**
-   * 分类编码
-   */
-  categoryCode?: string;
 }

+ 170 - 0
src/api/workflow/definition/index.ts

@@ -0,0 +1,170 @@
+import request from '@/utils/request';
+import { FlowDefinitionQuery, definitionXmlVO, FlowDefinitionForm, FlowDefinitionVo } from '@/api/workflow/definition/types';
+import { AxiosPromise } from 'axios';
+
+/**
+ * 获取流程定义列表
+ * @param query 流程实例id
+ * @returns
+ */
+export const listDefinition = (query: FlowDefinitionQuery): AxiosPromise<FlowDefinitionVo[]> => {
+  return request({
+    url: `/workflow/definition/list`,
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询未发布的流程定义列表
+ * @param query 流程实例id
+ * @returns
+ */
+export const unPublishList = (query: FlowDefinitionQuery): AxiosPromise<FlowDefinitionVo[]> => {
+  return request({
+    url: `/workflow/definition/unPublishList`,
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 通过流程定义id获取xml
+ * @param definitionId 流程定义id
+ * @returns
+ */
+export const definitionXml = (definitionId: string): AxiosPromise<definitionXmlVO> => {
+  return request({
+    url: `/workflow/definition/definitionXml/${definitionId}`,
+    method: 'get'
+  });
+};
+
+/**
+ * 删除流程定义
+ * @param id 流程定义id
+ * @returns
+ */
+export const deleteDefinition = (id: string | string[]) => {
+  return request({
+    url: `/workflow/definition/${id}`,
+    method: 'delete'
+  });
+};
+
+/**
+ * 挂起/激活
+ * @param definitionId 流程定义id
+ * @param activityStatus 状态
+ * @returns
+ */
+export const active = (definitionId: string, activityStatus: boolean) => {
+  return request({
+    url: `/workflow/definition/active/${definitionId}`,
+    method: 'put',
+    params: {
+      active: activityStatus
+    }
+  });
+};
+
+/**
+ * 通过zip或xml部署流程定义
+ * @returns
+ */
+export function importDef(data: any) {
+  return request({
+    url: '/workflow/definition/importDef',
+    method: 'post',
+    data: data,
+    headers: {
+      repeatSubmit: false
+    }
+  });
+}
+
+/**
+ * 发布流程定义
+ * @param id 流程定义id
+ * @returns
+ */
+export const publish = (id: string) => {
+  return request({
+    url: `/workflow/definition/publish/${id}`,
+    method: 'put'
+  });
+};
+
+/**
+ * 取消发布流程定义
+ * @param id 流程定义id
+ * @returns
+ */
+export const unPublish = (id: string) => {
+  return request({
+    url: `/workflow/definition/unPublish/${id}`,
+    method: 'put'
+  });
+};
+
+/**
+ * 获取流程定义xml字符串
+ * @param id 流程定义id
+ * @returns
+ */
+export const xmlString = (id: string) => {
+  return request({
+    url: `/workflow/definition/xmlString/${id}`,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增
+ * @param data 参数
+ * @returns
+ */
+export const add = (data: FlowDefinitionForm) => {
+  return request({
+    url: `/workflow/definition`,
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改
+ * @param data 参数
+ * @returns
+ */
+export const edit = (data: FlowDefinitionForm) => {
+  return request({
+    url: `/workflow/definition`,
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 查询详情
+ * @param id 参数
+ * @returns
+ */
+export const getInfo = (id: number | string) => {
+  return request({
+    url: `/workflow/definition/${id}`,
+    method: 'get'
+  });
+};
+
+/**
+ * 复制流程定义
+ * @param id 流程定义id
+ * @returns
+ */
+export const copy = (id: string) => {
+  return request({
+    url: `/workflow/definition/copy/${id}`,
+    method: 'post'
+  });
+};

+ 31 - 0
src/api/workflow/definition/types.ts

@@ -0,0 +1,31 @@
+export interface FlowDefinitionQuery extends PageQuery {
+  flowCode?: string;
+  flowName?: string;
+  category: string | number;
+  isPublish?: number;
+}
+
+export interface FlowDefinitionVo {
+  id: string;
+  flowName: string;
+  flowCode: string;
+  formPath: string;
+  version: string;
+  isPublish: number;
+  activityStatus: number;
+  createTime: Date;
+  updateTime: Date;
+}
+
+export interface FlowDefinitionForm {
+  id: string;
+  flowName: string;
+  flowCode: string;
+  category: string;
+  formPath: string;
+}
+
+export interface definitionXmlVO {
+  xml: string[];
+  xmlStr: string;
+}

+ 0 - 49
src/api/workflow/definitionConfig/index.ts

@@ -1,49 +0,0 @@
-import request from '@/utils/request';
-import { AxiosPromise } from 'axios';
-import { DefinitionConfigVO, DefinitionConfigForm } from '@/api/workflow/definitionConfig/types';
-
-/**
- * 查询表单配置详细
- * @param definitionId
- */
-export const getByDefId = (definitionId: string | number): AxiosPromise<DefinitionConfigVO> => {
-  return request({
-    url: '/workflow/definitionConfig/getByDefId/' + definitionId,
-    method: 'get'
-  });
-};
-
-/**
- * 新增表单配置
- * @param data
- */
-export const saveOrUpdate = (data: DefinitionConfigForm) => {
-  return request({
-    url: '/workflow/definitionConfig/saveOrUpdate',
-    method: 'post',
-    data: data
-  });
-};
-
-/**
- * 删除表单配置
- * @param id
- */
-export const deldefinitionConfig = (id: string | number | Array<string | number>) => {
-  return request({
-    url: '/workflow/definitionConfig/' + id,
-    method: 'delete'
-  });
-};
-
-/**
- * 查询流程定义配置排除当前查询的流程定义
- * @param tableName
- * @param definitionId
- */
-export const getByTableNameNotDefId = (tableName: string, definitionId: string | number) => {
-  return request({
-    url: `/workflow/definitionConfig/getByTableNameNotDefId/${tableName}/${definitionId}`,
-    method: 'get'
-  });
-};

+ 0 - 102
src/api/workflow/definitionConfig/types.ts

@@ -1,102 +0,0 @@
-import { FormManageVO } from '@/api/workflow/formManage/types';
-
-export interface DefinitionConfigVO {
-  /**
-   * 主键
-   */
-  id: string | number;
-
-  /**
-   * 表名
-   */
-  tableName?: string;
-
-  /**
-   * 流程定义ID
-   */
-  definitionId: string | number;
-
-  /**
-   * 流程KEY
-   */
-  processKey: string;
-
-  /**
-   * 流程版本
-   */
-  version?: string | number;
-
-  /**
-   * 备注
-   */
-  remark: string;
-
-  /**
-   * 表单管理
-   */
-  wfFormManageVo: FormManageVO;
-}
-
-export interface DefinitionConfigForm extends BaseEntity {
-  /**
-   * 主键
-   */
-  id?: string | number;
-
-  /**
-   * 表名
-   */
-  tableName?: string;
-
-  /**
-   * 流程定义ID
-   */
-  definitionId?: string | number;
-
-  /**
-   * 流程KEY
-   */
-  processKey?: string;
-
-  /**
-   * 流程版本
-   */
-  version?: string | number;
-
-  /**
-   * 备注
-   */
-  remark?: string;
-
-  /**
-   * 表单管理
-   */
-  wfFormManageVo?: FormManageVO;
-}
-
-export interface DefinitionConfigQuery extends PageQuery {
-  /**
-   * 表名
-   */
-  tableName?: string;
-
-  /**
-   * 流程定义ID
-   */
-  definitionId?: string | number;
-
-  /**
-   * 流程KEY
-   */
-  processKey?: string;
-
-  /**
-   * 流程版本
-   */
-  version?: string | number;
-
-  /**
-   * 表单管理
-   */
-  wfFormManageVo: FormManageVO;
-}

+ 0 - 76
src/api/workflow/formManage/index.ts

@@ -1,76 +0,0 @@
-import request from '@/utils/request';
-import { AxiosPromise } from 'axios';
-import { FormManageVO, FormManageForm, FormManageQuery } from '@/api/workflow/formManage/types';
-
-/**
- * 查询表单管理列表
- * @param query
- * @returns {*}
- */
-
-export const listFormManage = (query?: FormManageQuery): AxiosPromise<FormManageVO[]> => {
-  return request({
-    url: '/workflow/formManage/list',
-    method: 'get',
-    params: query
-  });
-};
-
-/**
- * 查询表单管理列表
- * @param query
- * @returns {*}
- */
-
-export const selectListFormManage = (): AxiosPromise<FormManageVO[]> => {
-  return request({
-    url: '/workflow/formManage/list/selectList',
-    method: 'get'
-  });
-};
-
-/**
- * 查询表单管理详细
- * @param id
- */
-export const getFormManage = (id: string | number): AxiosPromise<FormManageVO> => {
-  return request({
-    url: '/workflow/formManage/' + id,
-    method: 'get'
-  });
-};
-
-/**
- * 新增表单管理
- * @param data
- */
-export const addFormManage = (data: FormManageForm) => {
-  return request({
-    url: '/workflow/formManage',
-    method: 'post',
-    data: data
-  });
-};
-
-/**
- * 修改表单管理
- * @param data
- */
-export const updateFormManage = (data: FormManageForm) => {
-  return request({
-    url: '/workflow/formManage',
-    method: 'put',
-    data: data
-  });
-};
-
-/**
- * 删除表单管理
- * @param id
- */
-export const delFormManage = (id: string | number | Array<string | number>) => {
-  return request({
-    url: '/workflow/formManage/' + id,
-    method: 'delete'
-  });
-};

+ 0 - 69
src/api/workflow/formManage/types.ts

@@ -1,69 +0,0 @@
-export interface FormManageVO {
-  /**
-   * 主键
-   */
-  id: string | number;
-
-  /**
-   * 表单名称
-   */
-  formName: string;
-
-  /**
-   * 表单类型
-   */
-  formType: string;
-  /**
-   * 表单类型名称
-   */
-  formTypeName: string;
-
-  /**
-   * 路由地址/表单ID
-   */
-  router: string;
-
-  /**
-   * 备注
-   */
-  remark: string;
-}
-
-export interface FormManageForm extends BaseEntity {
-  /**
-   * 主键
-   */
-  id?: string | number;
-
-  /**
-   * 表单名称
-   */
-  formName?: string;
-
-  /**
-   * 表单类型
-   */
-  formType?: string;
-
-  /**
-   * 路由地址/表单ID
-   */
-  router?: string;
-
-  /**
-   * 备注
-   */
-  remark?: string;
-}
-
-export interface FormManageQuery extends PageQuery {
-  /**
-   * 表单名称
-   */
-  formName?: string;
-
-  /**
-   * 表单类型
-   */
-  formType?: string;
-}

+ 101 - 0
src/api/workflow/instance/index.ts

@@ -0,0 +1,101 @@
+import request from '@/utils/request';
+import { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types';
+import { AxiosPromise } from 'axios';
+
+/**
+ * 查询运行中实例列表
+ * @param query
+ * @returns {*}
+ */
+export const pageByRunning = (query: FlowInstanceQuery): AxiosPromise<FlowInstanceVO[]> => {
+  return request({
+    url: '/workflow/instance/pageByRunning',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询已完成实例列表
+ * @param query
+ * @returns {*}
+ */
+export const pageByFinish = (query: FlowInstanceQuery): AxiosPromise<FlowInstanceVO[]> => {
+  return request({
+    url: '/workflow/instance/pageByFinish',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 通过业务id获取历史流程图
+ */
+export const flowImage = (businessId: string | number) => {
+  return request({
+    url: `/workflow/instance/flowImage/${businessId}` + '?t' + Math.random(),
+    method: 'get'
+  });
+};
+
+/**
+ * 分页查询当前登录人单据
+ * @param query
+ * @returns {*}
+ */
+export const pageByCurrent = (query: FlowInstanceQuery): AxiosPromise<FlowInstanceVO[]> => {
+  return request({
+    url: '/workflow/instance/pageByCurrent',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 撤销流程
+ * @param data 参数
+ * @returns
+ */
+export const cancelProcessApply = (data: any) => {
+  return request({
+    url: `/workflow/instance/cancelProcessApply`,
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 获取流程变量
+ * @param instanceId 实例id
+ * @returns
+ */
+export const instanceVariable = (instanceId: string | number) => {
+  return request({
+    url: `/workflow/instance/instanceVariable/${instanceId}`,
+    method: 'get'
+  });
+};
+
+/**
+ * 删除
+ * @param instanceIds 流程实例id
+ * @returns
+ */
+export const deleteByInstanceIds = (instanceIds: Array<string | number> | string | number) => {
+  return request({
+    url: `/workflow/instance/deleteByInstanceIds/${instanceIds}`,
+    method: 'delete'
+  });
+};
+/**
+ * 作废流程
+ * @param data 参数
+ * @returns
+ */
+export const invalid = (data: any) => {
+  return request({
+    url: `/workflow/instance/invalid`,
+    method: 'post',
+    data: data
+  });
+};

+ 26 - 0
src/api/workflow/instance/types.ts

@@ -0,0 +1,26 @@
+import { FlowTaskVO } from '@/api/workflow/task/types';
+
+export interface FlowInstanceQuery extends PageQuery {
+  category?: string | number;
+  nodeName?: string;
+  flowCode?: string;
+  flowName?: string;
+  createByIds?: string[] | number[];
+  businessId?: string;
+}
+
+export interface FlowInstanceVO extends BaseEntity {
+  id: string | number;
+  definitionId: string;
+  flowName: string;
+  flowCode: string;
+  version: string;
+  businessId: string;
+  activityStatus: number;
+  tenantId: string;
+  createTime: string;
+  createBy: string;
+  flowStatus: string;
+  flowStatusName: string;
+  flowTaskList: FlowTaskVO[];
+}

+ 0 - 104
src/api/workflow/model/index.ts

@@ -1,104 +0,0 @@
-import request from '@/utils/request';
-import { AxiosPromise } from 'axios';
-import { ModelForm, ModelQuery, ModelVO } from '@/api/workflow/model/types';
-
-/**
- * 查询模型列表
- * @param query
- * @returns {*}
- */
-export const listModel = (query: ModelQuery): AxiosPromise<ModelVO[]> => {
-  return request({
-    url: '/workflow/model/list',
-    method: 'get',
-    params: query
-  });
-};
-
-/**
- * 查询模型信息
- * @param query
- * @returns {*}
- */
-export const getInfo = (id: string): AxiosPromise<ModelForm> => {
-  return request({
-    url: '/workflow/model/getInfo/' + id,
-    method: 'get'
-  });
-};
-
-/**
- * 新增模型
- * @param data
- * @returns {*}
- */
-export const addModel = (data: ModelForm): AxiosPromise<void> => {
-  return request({
-    url: '/workflow/model/save',
-    method: 'post',
-    data: data
-  });
-};
-
-/**
- * 修改模型信息
- * @param data
- * @returns {*}
- */
-export function update(data: ModelForm): AxiosPromise<void> {
-  return request({
-    url: '/workflow/model/update',
-    method: 'put',
-    data: data
-  });
-}
-
-/**
- * 修改模型信息
- * @param data
- * @returns {*}
- */
-export function editModelXml(data: ModelForm): AxiosPromise<void> {
-  return request({
-    url: '/workflow/model/editModelXml',
-    method: 'put',
-    data: data
-  });
-}
-
-/**
- * 按id删除模型
- * @returns {*}
- * @param id 模型id
- */
-export function delModel(id: string | string[]): AxiosPromise<void> {
-  return request({
-    url: '/workflow/model/' + id,
-    method: 'delete'
-  });
-}
-
-/**
- * 模型部署
- * @returns {*}
- * @param id 模型id
- */
-export const modelDeploy = (id: string): AxiosPromise<void> => {
-  return request({
-    url: `/workflow/model/modelDeploy/${id}`,
-    method: 'post'
-  });
-};
-
-/**
- * 复制模型
- * @param data
- * @returns {*}
- */
-export const copyModel = (data: ModelForm): AxiosPromise<void> => {
-  return request({
-    url: '/workflow/model/copyModel',
-    method: 'post',
-    data: data
-  });
-};

+ 0 - 66
src/api/workflow/model/types.ts

@@ -1,66 +0,0 @@
-export interface ModelForm {
-  id: string;
-  name: string;
-  key: string;
-  categoryCode: string;
-  xml: string;
-  svg: string;
-  description: string;
-}
-
-export interface ModelQuery extends PageQuery {
-  name?: string;
-  key?: string;
-  categoryCode?: string;
-}
-
-export interface OriginalPersistentState {
-  metaInfo: string;
-  editorSourceValueId: string;
-  createTime: string;
-  deploymentId?: string;
-  name: string;
-  tenantId: string;
-  category?: string;
-  version: number;
-  editorSourceExtraValueId?: string;
-  key: string;
-  lastUpdateTime: string;
-}
-
-export interface PersistentState {
-  metaInfo: string;
-  editorSourceValueId: string;
-  createTime: string;
-  deploymentId?: string;
-  name: string;
-  tenantId: string;
-  category?: string;
-  version: number;
-  editorSourceExtraValueId?: string;
-  key: string;
-  lastUpdateTime: string;
-}
-
-export interface ModelVO {
-  id: string;
-  revision: number;
-  originalPersistentState: OriginalPersistentState;
-  name: string;
-  key: string;
-  category?: string;
-  createTime: string;
-  lastUpdateTime: string;
-  version: number;
-  metaInfo: string;
-  deploymentId?: string;
-  editorSourceValueId: string;
-  editorSourceExtraValueId?: string;
-  tenantId: string;
-  persistentState: PersistentState;
-  revisionNext: number;
-  idPrefix: string;
-  inserted: boolean;
-  updated: boolean;
-  deleted: boolean;
-}

+ 0 - 38
src/api/workflow/nodeConfig/types.ts

@@ -1,38 +0,0 @@
-import { FormManageVO } from '@/api/workflow/formManage/types';
-
-export interface NodeConfigVO {
-  /**
-   * 主键
-   */
-  id: string | number;
-
-  /**
-   * 表单id
-   */
-  formId: string | number;
-
-  /**
-   * 表单类型
-   */
-  formType: string;
-
-  /**
-   * 节点名称
-   */
-  nodeName: string;
-
-  /**
-   * 节点id
-   */
-  nodeId: string | number;
-
-  /**
-   * 流程定义id
-   */
-  definitionId: string | number;
-
-  /**
-   * 表单管理
-   */
-  wfFormManageVo: FormManageVO;
-}

+ 0 - 114
src/api/workflow/processDefinition/index.ts

@@ -1,114 +0,0 @@
-import request from '@/utils/request';
-import { ProcessDefinitionQuery, ProcessDefinitionVO, definitionXmlVO } from '@/api/workflow/processDefinition/types';
-import { AxiosPromise } from 'axios';
-
-/**
- * 获取流程定义列表
- * @param query 流程实例id
- * @returns
- */
-export const listProcessDefinition = (query: ProcessDefinitionQuery): AxiosPromise<ProcessDefinitionVO[]> => {
-  return request({
-    url: `/workflow/processDefinition/list`,
-    method: 'get',
-    params: query
-  });
-};
-/**
- * 按照流程定义key获取流程定义
- * @param processInstanceId 流程实例id
- * @returns
- */
-export const getListByKey = (key: string) => {
-  return request({
-    url: `/workflow/processDefinition/getListByKey/${key}`,
-    method: 'get'
-  });
-};
-
-/**
- * 通过流程定义id获取流程图
- */
-export const definitionImage = (processDefinitionId: string): AxiosPromise<any> => {
-  return request({
-    url: `/workflow/processDefinition/definitionImage/${processDefinitionId}` + '?t' + Math.random(),
-    method: 'get'
-  });
-};
-
-/**
- * 通过流程定义id获取xml
- * @param processDefinitionId 流程定义id
- * @returns
- */
-export const definitionXml = (processDefinitionId: string): AxiosPromise<definitionXmlVO> => {
-  return request({
-    url: `/workflow/processDefinition/definitionXml/${processDefinitionId}`,
-    method: 'get'
-  });
-};
-
-/**
- * 删除流程定义
- * @param deploymentId 部署id
- * @param processDefinitionId 流程定义id
- * @returns
- */
-export const deleteProcessDefinition = (deploymentId: string | string[], processDefinitionId: string | string[]) => {
-  return request({
-    url: `/workflow/processDefinition/${deploymentId}/${processDefinitionId}`,
-    method: 'delete'
-  });
-};
-
-/**
- * 挂起/激活
- * @param processDefinitionId 流程定义id
- * @returns
- */
-export const updateDefinitionState = (processDefinitionId: string) => {
-  return request({
-    url: `/workflow/processDefinition/updateDefinitionState/${processDefinitionId}`,
-    method: 'put'
-  });
-};
-
-/**
- * 流程定义转换为模型
- * @param processDefinitionId 流程定义id
- * @returns
- */
-export const convertToModel = (processDefinitionId: string) => {
-  return request({
-    url: `/workflow/processDefinition/convertToModel/${processDefinitionId}`,
-    method: 'put'
-  });
-};
-
-/**
- * 通过zip或xml部署流程定义
- * @returns
- */
-export function deployProcessFile(data: any) {
-  return request({
-    url: '/workflow/processDefinition/deployByFile',
-    method: 'post',
-    data: data,
-    headers: {
-      repeatSubmit: false
-    }
-  });
-}
-
-/**
- * 迁移流程
- * @param currentProcessDefinitionId
- * @param fromProcessDefinitionId
- * @returns
- */
-export const migrationDefinition = (currentProcessDefinitionId: string, fromProcessDefinitionId: string) => {
-  return request({
-    url: `/workflow/processDefinition/migrationDefinition/${currentProcessDefinitionId}/${fromProcessDefinitionId}`,
-    method: 'put'
-  });
-};

+ 0 - 24
src/api/workflow/processDefinition/types.ts

@@ -1,24 +0,0 @@
-import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types';
-export interface ProcessDefinitionQuery extends PageQuery {
-  key?: string;
-  name?: string;
-  categoryCode?: string;
-}
-
-export interface ProcessDefinitionVO extends BaseEntity {
-  id: string;
-  name: string;
-  key: string;
-  version: number;
-  suspensionState: number;
-  resourceName: string;
-  diagramResourceName: string;
-  deploymentId: string;
-  deploymentTime: string;
-  wfDefinitionConfigVo: DefinitionConfigVO;
-}
-
-export interface definitionXmlVO {
-  xml: string[];
-  xmlStr: string;
-}

+ 0 - 136
src/api/workflow/processInstance/index.ts

@@ -1,136 +0,0 @@
-import request from '@/utils/request';
-import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types';
-import { AxiosPromise } from 'axios';
-
-/**
- * 查询运行中实例列表
- * @param query
- * @returns {*}
- */
-export const getPageByRunning = (query: ProcessInstanceQuery): AxiosPromise<ProcessInstanceVO[]> => {
-  return request({
-    url: '/workflow/processInstance/getPageByRunning',
-    method: 'get',
-    params: query
-  });
-};
-
-/**
- * 查询已完成实例列表
- * @param query
- * @returns {*}
- */
-export const getPageByFinish = (query: ProcessInstanceQuery): AxiosPromise<ProcessInstanceVO[]> => {
-  return request({
-    url: '/workflow/processInstance/getPageByFinish',
-    method: 'get',
-    params: query
-  });
-};
-
-/**
- * 通过业务id获取历史流程图
- */
-export const getHistoryImage = (businessKey: string) => {
-  return request({
-    url: `/workflow/processInstance/getHistoryImage/${businessKey}` + '?t' + Math.random(),
-    method: 'get'
-  });
-};
-
-/**
- * 通过业务id获取历史流程图运行中,历史等节点
- */
-export const getHistoryList = (businessKey: string): AxiosPromise<Record<string, any>> => {
-  return request({
-    url: `/workflow/processInstance/getHistoryList/${businessKey}` + '?t' + Math.random(),
-    method: 'get'
-  });
-};
-
-/**
- * 获取审批记录
- * @param businessKey 业务id
- * @returns
- */
-export const getHistoryRecord = (businessKey: string | number) => {
-  return request({
-    url: `/workflow/processInstance/getHistoryRecord/${businessKey}`,
-    method: 'get'
-  });
-};
-
-/**
- * 作废
- * @param data 参数
- * @returns
- */
-export const deleteRunInstance = (data: object) => {
-  return request({
-    url: `/workflow/processInstance/deleteRunInstance`,
-    method: 'post',
-    data: data
-  });
-};
-
-/**
- * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
- * @param businessKey 业务id
- * @returns
- */
-export const deleteRunAndHisInstance = (businessKey: string | string[]) => {
-  return request({
-    url: `/workflow/processInstance/deleteRunAndHisInstance/${businessKey}`,
-    method: 'delete'
-  });
-};
-
-/**
- * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
- * @param businessKey 业务id
- * @returns
- */
-export const deleteFinishAndHisInstance = (businessKey: string | string[]) => {
-  return request({
-    url: `/workflow/processInstance/deleteFinishAndHisInstance/${businessKey}`,
-    method: 'delete'
-  });
-};
-
-/**
- * 分页查询当前登录人单据
- * @param query
- * @returns {*}
- */
-export const getPageByCurrent = (query: ProcessInstanceQuery): AxiosPromise<ProcessInstanceVO[]> => {
-  return request({
-    url: '/workflow/processInstance/getPageByCurrent',
-    method: 'get',
-    params: query
-  });
-};
-
-/**
- * 撤销流程
- * @param businessKey 业务id
- * @returns
- */
-export const cancelProcessApply = (businessKey: string) => {
-  return request({
-    url: `/workflow/processInstance/cancelProcessApply/${businessKey}`,
-    method: 'post'
-  });
-};
-
-export default {
-  getPageByRunning,
-  getPageByFinish,
-  getHistoryImage,
-  getHistoryList,
-  getHistoryRecord,
-  deleteRunInstance,
-  deleteRunAndHisInstance,
-  deleteFinishAndHisInstance,
-  getPageByCurrent,
-  cancelProcessApply
-};

+ 0 - 27
src/api/workflow/processInstance/types.ts

@@ -1,27 +0,0 @@
-import { TaskVO } from '@/api/workflow/task/types';
-
-export interface ProcessInstanceQuery extends PageQuery {
-  categoryCode?: string;
-  name?: string;
-  key?: string;
-  startUserId?: string;
-  businessKey?: string;
-}
-
-export interface ProcessInstanceVO extends BaseEntity {
-  id: string;
-  processDefinitionId: string;
-  processDefinitionName: string;
-  processDefinitionKey: string;
-  processDefinitionVersion: string;
-  deploymentId: string;
-  businessKey: string;
-  isSuspended?: any;
-  tenantId: string;
-  startTime: string;
-  endTime?: string;
-  startUserId: string;
-  businessStatus: string;
-  businessStatusName: string;
-  taskVoList: TaskVO[];
-}

+ 28 - 112
src/api/workflow/task/index.ts

@@ -1,15 +1,15 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
-import { TaskQuery, TaskVO } from '@/api/workflow/task/types';
+import { TaskQuery, FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types';
 
 /**
  * 查询待办列表
  * @param query
  * @returns {*}
  */
-export const getPageByTaskWait = (query: TaskQuery): AxiosPromise<TaskVO[]> => {
+export const pageByTaskWait = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => {
   return request({
-    url: '/workflow/task/getPageByTaskWait',
+    url: '/workflow/task/pageByTaskWait',
     method: 'get',
     params: query
   });
@@ -20,9 +20,9 @@ export const getPageByTaskWait = (query: TaskQuery): AxiosPromise<TaskVO[]> => {
  * @param query
  * @returns {*}
  */
-export const getPageByTaskFinish = (query: TaskQuery): AxiosPromise<TaskVO[]> => {
+export const pageByTaskFinish = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => {
   return request({
-    url: '/workflow/task/getPageByTaskFinish',
+    url: '/workflow/task/pageByTaskFinish',
     method: 'get',
     params: query
   });
@@ -33,9 +33,9 @@ export const getPageByTaskFinish = (query: TaskQuery): AxiosPromise<TaskVO[]> =>
  * @param query
  * @returns {*}
  */
-export const getPageByTaskCopy = (query: TaskQuery): AxiosPromise<TaskVO[]> => {
+export const pageByTaskCopy = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => {
   return request({
-    url: '/workflow/task/getPageByTaskCopy',
+    url: '/workflow/task/pageByTaskCopy',
     method: 'get',
     params: query
   });
@@ -46,9 +46,9 @@ export const getPageByTaskCopy = (query: TaskQuery): AxiosPromise<TaskVO[]> => {
  * @param query
  * @returns {*}
  */
-export const getPageByAllTaskWait = (query: TaskQuery): AxiosPromise<TaskVO[]> => {
+export const pageByAllTaskWait = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => {
   return request({
-    url: '/workflow/task/getPageByAllTaskWait',
+    url: '/workflow/task/pageByAllTaskWait',
     method: 'get',
     params: query
   });
@@ -59,9 +59,9 @@ export const getPageByAllTaskWait = (query: TaskQuery): AxiosPromise<TaskVO[]> =
  * @param query
  * @returns {*}
  */
-export const getPageByAllTaskFinish = (query: TaskQuery): AxiosPromise<TaskVO[]> => {
+export const pageByAllTaskFinish = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => {
   return request({
-    url: '/workflow/task/getPageByAllTaskFinish',
+    url: '/workflow/task/pageByAllTaskFinish',
     method: 'get',
     params: query
   });
@@ -93,30 +93,6 @@ export const completeTask = (data: object) => {
   });
 };
 
-/**
- * 认领任务
- * @param taskId
- * @returns {*}
- */
-export const claim = (taskId: string): any => {
-  return request({
-    url: '/workflow/task/claim/' + taskId,
-    method: 'post'
-  });
-};
-
-/**
- * 归还任务
- * @param taskId
- * @returns {*}
- */
-export const returnTask = (taskId: string): any => {
-  return request({
-    url: '/workflow/task/returnTask/' + taskId,
-    method: 'post'
-  });
-};
-
 /**
  * 任务驳回
  * @param data
@@ -135,61 +111,24 @@ export const backProcess = (data: any): any => {
  * @param taskId
  * @returns
  */
-export const getTaskById = (taskId: string) => {
+export const getTask = (taskId: string) => {
   return request({
-    url: '/workflow/task/getTaskById/' + taskId,
+    url: '/workflow/task/getTask/' + taskId,
     method: 'get'
   });
 };
 
-/**
- * 加签
- * @param data
- * @returns
- */
-export const addMultiInstanceExecution = (data: any) => {
-  return request({
-    url: '/workflow/task/addMultiInstanceExecution',
-    method: 'post',
-    data: data
-  });
-};
-
-/**
- * 减签
- * @param data
- * @returns
- */
-export const deleteMultiInstanceExecution = (data: any) => {
-  return request({
-    url: '/workflow/task/deleteMultiInstanceExecution',
-    method: 'post',
-    data: data
-  });
-};
-
 /**
  * 修改任务办理人
- * @param taskIds
+ * @param taskIdList
  * @param userId
  * @returns
  */
-export const updateAssignee = (taskIds: Array<string>, userId: string) => {
-  return request({
-    url: `/workflow/task/updateAssignee/${taskIds}/${userId}`,
-    method: 'put'
-  });
-};
-
-/**
- * 转办任务
- * @returns
- */
-export const transferTask = (data: any) => {
+export const updateAssignee = (taskIdList: Array<string>, userId: string) => {
   return request({
-    url: `/workflow/task/transferTask`,
-    method: 'post',
-    data: data
+    url: `/workflow/task/updateAssignee/${userId}`,
+    method: 'put',
+    data: taskIdList
   });
 };
 
@@ -205,60 +144,37 @@ export const terminationTask = (data: any) => {
   });
 };
 
-/**
- * 查询流程变量
- * @returns
- */
-export const getInstanceVariable = (taskId: string) => {
-  return request({
-    url: `/workflow/task/getInstanceVariable/${taskId}`,
-    method: 'get'
-  });
-};
-
 /**
  * 获取可驳回得任务节点
  * @returns
  */
-export const getTaskNodeList = (processInstanceId: string) => {
+export const getBackTaskNode = (definitionId: string, nodeCode: string) => {
   return request({
-    url: `/workflow/task/getTaskNodeList/${processInstanceId}`,
+    url: `/workflow/task/getBackTaskNode/${definitionId}/${nodeCode}`,
     method: 'get'
   });
 };
 
 /**
- * 委托任务
+ * 任务操作 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature
  * @returns
  */
-export const delegateTask = (data: any) => {
+export const taskOperation = (data: TaskOperationBo, operation: string) => {
   return request({
-    url: `/workflow/task/delegateTask`,
+    url: `/workflow/task/taskOperation/${operation}`,
     method: 'post',
     data: data
   });
 };
 
 /**
- * 查询工作流任务用户选择加签人员
- * @param taskId
- * @returns {*}
- */
-export const getTaskUserIdsByAddMultiInstance = (taskId: string) => {
-  return request({
-    url: '/workflow/task/getTaskUserIdsByAddMultiInstance/' + taskId,
-    method: 'get'
-  });
-};
-
-/**
- * 查询工作流选择减签人员
- * @param taskId
- * @returns {*}
+ * 获取当前任务办理人
+ * @param taskId 任务id
+ * @returns
  */
-export const getListByDeleteMultiInstance = (taskId: string) => {
+export const currentTaskAllUser = (taskId: string | number) => {
   return request({
-    url: '/workflow/task/getListByDeleteMultiInstance/' + taskId,
+    url: `/workflow/task/currentTaskAllUser/${taskId}`,
     method: 'get'
   });
 };

+ 33 - 34
src/api/workflow/task/types.ts

@@ -1,9 +1,8 @@
-import { NodeConfigVO } from '@/api/workflow/nodeConfig/types';
-import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types';
 export interface TaskQuery extends PageQuery {
-  name?: string;
-  processDefinitionKey?: string;
-  processDefinitionName?: string;
+  nodeName?: string;
+  flowCode?: string;
+  flowName?: string;
+  createByIds?: string[] | number[];
 }
 
 export interface ParticipantVo {
@@ -12,38 +11,38 @@ export interface ParticipantVo {
   candidateName: string[];
   claim: boolean;
 }
-
-export interface TaskVO extends BaseEntity {
-  id: string;
-  name: string;
-  description?: string;
-  priority: number;
-  owner?: string;
-  assignee?: string | number;
-  assigneeName?: string;
-  processInstanceId: string;
-  executionId: string;
-  taskDefinitionId?: any;
-  processDefinitionId: string;
-  endTime?: string;
-  taskDefinitionKey: string;
-  dueDate?: string;
-  category?: any;
-  parentTaskId?: any;
-  tenantId: string;
-  claimTime?: string;
-  businessStatus?: string;
-  businessStatusName?: string;
-  processDefinitionName?: string;
-  processDefinitionKey?: string;
-  participantVo?: ParticipantVo;
-  multiInstance?: boolean;
-  businessKey?: string;
-  wfNodeConfigVo?: NodeConfigVO;
-  wfDefinitionConfigVo?: DefinitionConfigVO;
+export interface FlowTaskVO {
+  id: string | number;
+  createTime?: Date;
+  updateTime?: Date;
+  tenantId?: string;
+  definitionId?: string;
+  instanceId: string;
+  flowName: string;
+  businessId: string;
+  nodeCode: string;
+  nodeName: string;
+  flowCode: string;
+  flowStatus: string;
+  formCustom: string;
+  formPath: string;
+  nodeType: number;
+  nodeRatio: string | number;
+  version?: string;
 }
 
 export interface VariableVo {
   key: string;
   value: string;
 }
+
+export interface TaskOperationBo {
+  //委派/转办人的用户ID(必填,准对委派/转办人操作)
+  userId?: string;
+  //加签/减签人的用户ID列表(必填,针对加签/减签操作)
+  userIds?: string[];
+  //任务ID(必填)
+  taskId: string | number;
+  //意见或备注信息(可选)
+  message?: string;
+}

+ 9 - 23
src/api/workflow/workflowCommon/index.ts

@@ -2,28 +2,14 @@ import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
 
 export default {
   routerJump(routerJumpVo: RouterJumpVo, proxy) {
-    if (routerJumpVo.wfNodeConfigVo && routerJumpVo.wfNodeConfigVo.formType === 'static' && routerJumpVo.wfNodeConfigVo.wfFormManageVo) {
-      proxy.$tab.closePage(proxy.$route);
-      proxy.$router.push({
-        path: `${routerJumpVo.wfNodeConfigVo.wfFormManageVo.router}`,
-        query: {
-          id: routerJumpVo.businessKey,
-          type: routerJumpVo.type,
-          taskId: routerJumpVo.taskId
-        }
-      });
-    } else if (routerJumpVo.wfNodeConfigVo && routerJumpVo.wfNodeConfigVo.formType === 'dynamic' && routerJumpVo.wfNodeConfigVo.wfFormManageVo) {
-      proxy.$tab.closePage(proxy.$route);
-      proxy.$router.push({
-        path: `${routerJumpVo.wfNodeConfigVo.wfFormManageVo.router}`,
-        query: {
-          id: routerJumpVo.businessKey,
-          type: routerJumpVo.type,
-          taskId: routerJumpVo.taskId
-        }
-      });
-    } else {
-      proxy?.$modal.msgError('请到模型配置菜单!');
-    }
+    proxy.$tab.closePage(proxy.$route);
+    proxy.$router.push({
+      path: routerJumpVo.formPath,
+      query: {
+        id: routerJumpVo.businessId,
+        type: routerJumpVo.type,
+        taskId: routerJumpVo.taskId
+      }
+    });
   }
 };

+ 6 - 9
src/api/workflow/workflowCommon/types.ts

@@ -1,16 +1,13 @@
-import { NodeConfigVO } from '@/api/workflow/nodeConfig/types';
-import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types';
-
 export interface RouterJumpVo {
-  wfNodeConfigVo: NodeConfigVO;
-  wfDefinitionConfigVo: DefinitionConfigVO;
-  businessKey: string;
-  taskId: string;
+  businessId: string;
+  taskId: string | number;
   type: string;
+  formCustom: string;
+  formPath: string;
 }
 
 export interface StartProcessBo {
-  businessKey: string | number;
-  tableName: string;
+  businessId: string | number;
+  flowCode: string;
   variables: any;
 }

+ 0 - 10
src/assets/styles/variables.module.scss

@@ -14,11 +14,6 @@
   --tableHeaderBg: #f8f8f9;
   --tableHeaderTextColor: #515a6e;
 
-  // 工作流
-  --bpmn-panel-border: #eeeeee;
-  --bpmn-panel-box-shadow: #cccccc;
-  --bpmn-panel-bar-background-color: #f5f7fa;
-
   // ele
   --brder-color: #e8e8e8;
 
@@ -78,11 +73,6 @@ html.dark {
   --vxe-table-border-color: #37373a;
   --vxe-toolbar-background-color: #37373a;
 
-  // 工作流
-  --bpmn-panel-border: #37373a;
-  --bpmn-panel-box-shadow: #37373a;
-  --bpmn-panel-bar-background-color: #37373a;
-
   // ele
   --brder-color: #37373a;
 }

+ 0 - 23
src/bpmn/assets/defaultXML.ts

@@ -1,23 +0,0 @@
-function generateRandomValue() {
-  // 生成一个随机数
-  const randomValue = Math.random().toString(36).slice(2, 12);
-  return `Process_${randomValue}`;
-}
-
-const cartage: string = 'default';
-export default `<?xml version="1.0" encoding="UTF-8"?>
-<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.flowable.org/processdef">
-  <process id="process_${generateRandomValue()}" name="name_${generateRandomValue()}">
-    <startEvent id="startNode1" name="开始" />
-  </process>
-  <bpmndi:BPMNDiagram id="BPMNDiagram_flow">
-    <bpmndi:BPMNPlane id="BPMNPlane_flow" bpmnElement="T-2d89e7a3-ba79-4abd-9f64-ea59621c258c">
-      <bpmndi:BPMNShape id="BPMNShape_startNode1" bpmnElement="startNode1" bioc:stroke="">
-        <omgdc:Bounds x="240" y="200" width="30" height="30" />
-        <bpmndi:BPMNLabel>
-          <omgdc:Bounds x="242" y="237" width="23" height="14" />
-        </bpmndi:BPMNLabel>
-      </bpmndi:BPMNShape>
-    </bpmndi:BPMNPlane>
-  </bpmndi:BPMNDiagram>
-</definitions>`;

+ 0 - 126
src/bpmn/assets/lang/zh.ts

@@ -1,126 +0,0 @@
-export const NodeName = {
-  'bpmn:Process': '流程',
-  'bpmn:StartEvent': '开始事件',
-  'bpmn:IntermediateThrowEvent': '中间事件',
-  'bpmn:Task': '任务',
-  'bpmn:SendTask': '发送任务',
-  'bpmn:ReceiveTask': '接收任务',
-  'bpmn:UserTask': '用户任务',
-  'bpmn:ManualTask': '手工任务',
-  'bpmn:BusinessRuleTask': '业务规则任务',
-  'bpmn:ServiceTask': '服务任务',
-  'bpmn:ScriptTask': '脚本任务',
-  'bpmn:EndEvent': '结束事件',
-  'bpmn:SequenceFlow': '流程线',
-  'bpmn:ExclusiveGateway': '互斥网关',
-  'bpmn:ParallelGateway': '并行网关',
-  'bpmn:InclusiveGateway': '相容网关',
-  'bpmn:ComplexGateway': '复杂网关',
-  'bpmn:EventBasedGateway': '事件网关',
-  'bpmn:Participant': '池/参与者',
-  'bpmn:SubProcess': '子流程',
-  'bpmn:DataObjectReference': '数据对象引用',
-  'bpmn:DataStoreReference': '数据存储引用',
-  'bpmn:Group': '组'
-};
-
-export default {
-  'Activate hand tool': '启动手动工具',
-  'Activate lasso tool': '启动 Lasso 工具',
-  'Activate create/remove space tool': '启动创建/删除空间工具',
-  'Activate global connect tool': '启动全局连接工具',
-  'Ad-hoc': 'Ad-hoc',
-  'Add lane above': '在上方添加泳道',
-  'Add lane below': '在下方添加泳道',
-  'Business rule task': '规则任务',
-  'Call activity': '引用流程',
-  'Compensation end event': '结束补偿事件',
-  'Compensation intermediate throw event': '中间补偿抛出事件',
-  'Complex gateway': '复杂网关',
-  'Conditional intermediate catch event': '中间条件捕获事件',
-  'Conditional start event (non-interrupting)': '条件启动事件 (非中断)',
-  'Conditional start event': '条件启动事件',
-  'Connect using association': '文本关联',
-  'Connect using sequence/message flow or association': '消息关联',
-  'Change element': '更改元素',
-  'Change type': '更改类型',
-  'Create data object reference': '创建数据对象引用',
-  'Create data store reference': '创建数据存储引用',
-  'Create expanded sub-process': '创建可折叠子流程',
-  'Create pool/participant': '创建池/参与者',
-  'Collection': '集合',
-  'Connect using data input association': '数据输入关联',
-  'Data store reference': '数据存储引用',
-  'Data object reference': '数据对象引用',
-  'Divide into two lanes': '分成两个泳道',
-  'Divide into three lanes': '分成三个泳道',
-  'End event': '结束事件',
-  'Error end event': '结束错误事件',
-  'Escalation end event': '结束升级事件',
-  'Escalation intermediate throw event': '中间升级抛出事件',
-  'Event sub-process': '事件子流程',
-  'Event-based gateway': '事件网关',
-  'Exclusive gateway': '互斥网关',
-  'Empty pool/participant (removes content)': '清空池/参与者 (删除内容)',
-  'Empty pool/participant': '清空池/参与者',
-  'Expanded pool/participant': '展开池/参与者',
-  'Inclusive gateway': '相容网关',
-  'Intermediate throw event': '中间抛出事件',
-  'Loop': '循环',
-  'Link intermediate catch event': '中间链接捕获事件',
-  'Link intermediate throw event': '中间链接抛出事件',
-  'Manual task': '手动任务',
-  'Message end event': '结束消息事件',
-  'Message intermediate catch event': '中间消息捕获事件',
-  'Message intermediate throw event': '中间消息抛出事件',
-  'Message start event': '消息启动事件',
-  'Parallel gateway': '并行网关',
-  'Parallel multi-instance': '并行多实例',
-  'Participant multiplicity': '参与者多重性',
-  'Receive task': '接受任务',
-  'Remove': '移除',
-  'Script task': '脚本任务',
-  'Send task': '发送任务',
-  'Sequential multi-instance': '串行多实例',
-  'Service task': '服务任务',
-  'Signal end event': '结束信号事件',
-  'Signal intermediate catch event': '中间信号捕获事件',
-  'Signal intermediate throw event': '中间信号抛出事件',
-  'Signal start event (non-interrupting)': '信号启动事件 (非中断)',
-  'Signal start event': '信号启动事件',
-  'Start event': '开始事件',
-  'Sub-process (collapsed)': '可折叠子流程',
-  'Sub-process (expanded)': '可展开子流程',
-  'Sub rocess': '子流程',
-  'Task': '任务',
-  'Transaction': '事务',
-  'Terminate end event': '终止边界事件',
-  'Timer intermediate catch event': '中间定时捕获事件',
-  'Timer start event (non-interrupting)': '定时启动事件 (非中断)',
-  'Timer start event': '定时启动事件',
-  'User task': '用户任务',
-  'Create start event': '创建开始事件',
-  'Create gateway': '创建网关',
-  'Create intermediate/boundary event': '创建中间/边界事件',
-  'Create end event': '创建结束事件',
-  'Create group': '创建组',
-  'Create startEvent': '开始节点',
-  'Create endEvent': '结束节点',
-  'Create exclusiveGateway': '互斥网关',
-  'Create parallelGateway': '并行网关',
-  'Create task': '任务节点',
-  'Create userTask': '用户任务节点',
-  'Condition type': '条件类型',
-  'Append end event': '追加结束事件节点',
-  'Append gateway': '追加网关节点',
-  'Append task': '追加任务',
-  'Append user task': '追加用户任务节点',
-  'Append text annotation': '追加文本注释',
-  'Append intermediate/boundary event': '追加中间或边界事件',
-  'Append receive task': '追加接收任务节点',
-  'Append message intermediate catch event': '追加中间消息捕获事件',
-  'Append timer intermediate catch event': '追加中间定时捕获事件',
-  'Append conditional intermediate catch event': '追加中间条件捕获事件',
-  'Append signal intermediate catch event': '追加中间信号捕获事件',
-  'flow elements must be children of pools/participants': '流程元素必须是池/参与者的子元素'
-};

+ 0 - 1250
src/bpmn/assets/moddle/flowable.ts

@@ -1,1250 +0,0 @@
-export default {
-  'name': 'Flowable',
-  'uri': 'http://flowable.org/bpmn',
-  'prefix': 'flowable',
-  'xml': {
-    'tagAlias': 'lowerCase'
-  },
-  'associations': [],
-  'types': [
-    {
-      'name': 'flowable:extCandidateUsers',
-      'isAbstract': true,
-      'extends': [],
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['*']
-      },
-      'properties': [
-        {
-          'name': 'body',
-          'type': 'String',
-          'isBody': true
-        }
-      ]
-    },
-    {
-      'name': 'flowable:extAssignee',
-      'isAbstract': true,
-      'extends': [],
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['*']
-      },
-      'properties': [
-        {
-          'name': 'body',
-          'type': 'String',
-          'isBody': true
-        }
-      ]
-    },
-    {
-      'name': 'flowable:property',
-      'superClass': ['Element'],
-      'properties': [
-        {
-          'name': 'id',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'name',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'value',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'flowable:properties',
-      'isAbstract': true,
-      'extends': [],
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['*']
-      },
-      'properties': [
-        {
-          'name': 'values',
-          'type': 'flowable:property',
-          'isMany': true
-        }
-      ]
-    },
-    {
-      'name': 'InOutBinding',
-      'superClass': ['Element'],
-      'isAbstract': true,
-      'properties': [
-        {
-          'name': 'source',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'sourceExpression',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'target',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'businessKey',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'local',
-          'isAttr': true,
-          'type': 'Boolean',
-          'default': false
-        },
-        {
-          'name': 'variables',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'In',
-      'superClass': ['InOutBinding'],
-      'meta': {
-        'allowedIn': ['bpmn:CallActivity']
-      }
-    },
-    {
-      'name': 'Out',
-      'superClass': ['InOutBinding'],
-      'meta': {
-        'allowedIn': ['bpmn:CallActivity']
-      }
-    },
-    {
-      'name': 'AsyncCapable',
-      'isAbstract': true,
-      'extends': ['bpmn:Activity', 'bpmn:Gateway', 'bpmn:Event'],
-      'properties': [
-        {
-          'name': 'async',
-          'isAttr': true,
-          'type': 'Boolean',
-          'default': false
-        },
-        {
-          'name': 'asyncBefore',
-          'isAttr': true,
-          'type': 'Boolean',
-          'default': false
-        },
-        {
-          'name': 'asyncAfter',
-          'isAttr': true,
-          'type': 'Boolean',
-          'default': false
-        },
-        {
-          'name': 'exclusive',
-          'isAttr': true,
-          'type': 'Boolean',
-          'default': true
-        }
-      ]
-    },
-    {
-      'name': 'flowable:in',
-      'superClass': ['Element'],
-      'properties': [
-        {
-          'name': 'source',
-          'type': 'string',
-          'isAttr': true
-        },
-        {
-          'name': 'target',
-          'type': 'string',
-          'isAttr': true
-        }
-      ]
-    },
-    {
-      'name': 'flowable:out',
-      'superClass': ['Element'],
-      'properties': [
-        {
-          'name': 'source',
-          'type': 'string',
-          'isAttr': true
-        },
-        {
-          'name': 'target',
-          'type': 'string',
-          'isAttr': true
-        }
-      ]
-    },
-    {
-      'name': 'BoundaryEvent',
-      'superClass': ['CatchEvent'],
-      'properties': [
-        {
-          'name': 'cancelActivity',
-          'default': true,
-          'isAttr': true,
-          'type': 'Boolean'
-        },
-        {
-          'name': 'attachedToRef',
-          'type': 'Activity',
-          'isAttr': true,
-          'isReference': true
-        }
-      ]
-    },
-    {
-      'name': 'JobPriorized',
-      'isAbstract': true,
-      'extends': ['bpmn:Process', 'flowable:AsyncCapable'],
-      'properties': [
-        {
-          'name': 'jobPriority',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'SignalEventDefinition',
-      'isAbstract': true,
-      'extends': ['bpmn:SignalEventDefinition'],
-      'properties': [
-        {
-          'name': 'async',
-          'isAttr': true,
-          'type': 'Boolean',
-          'default': false
-        }
-      ]
-    },
-    {
-      'name': 'ErrorEventDefinition',
-      'isAbstract': true,
-      'extends': ['bpmn:ErrorEventDefinition'],
-      'properties': [
-        {
-          'name': 'errorCodeVariable',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'errorMessageVariable',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'Error',
-      'isAbstract': true,
-      'extends': ['bpmn:Error'],
-      'properties': [
-        {
-          'name': 'flowable:errorMessage',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'PotentialStarter',
-      'superClass': ['Element'],
-      'properties': [
-        {
-          'name': 'resourceAssignmentExpression',
-          'type': 'bpmn:ResourceAssignmentExpression'
-        }
-      ]
-    },
-    {
-      'name': 'UserTask',
-      'isAbstract': true,
-      'extends': ['bpmn:UserTask'],
-      'properties': [
-        {
-          'name': 'timerEventDefinition',
-          'type': 'Expression'
-        },
-        {
-          'name': 'multiInstanceLoopCharacteristics',
-          'type': 'MultiInstanceLoopCharacteristics'
-        }
-      ]
-    },
-    {
-      'name': 'StartEvent',
-      'isAbstract': true,
-      'extends': ['bpmn:StartEvent'],
-      'properties': [
-        {
-          'name': 'timerEventDefinition',
-          'type': 'Expression'
-        }
-      ]
-    },
-    {
-      'name': 'FormSupported',
-      'isAbstract': true,
-      'extends': ['bpmn:StartEvent', 'bpmn:UserTask'],
-      'properties': [
-        {
-          'name': 'formHandlerClass',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'formKey',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'TemplateSupported',
-      'isAbstract': true,
-      'extends': ['bpmn:Process', 'bpmn:FlowElement'],
-      'properties': [
-        {
-          'name': 'modelerTemplate',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'Initiator',
-      'isAbstract': true,
-      'extends': ['bpmn:StartEvent'],
-      'properties': [
-        {
-          'name': 'initiator',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'ScriptTask',
-      'isAbstract': true,
-      'extends': ['bpmn:ScriptTask'],
-      'properties': [
-        {
-          'name': 'resultVariable',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'resource',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'Process',
-      'isAbstract': true,
-      'extends': ['bpmn:Process'],
-      'properties': [
-        {
-          'name': 'candidateStarterGroups',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'candidateStarterUsers',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'versionTag',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'historyTimeToLive',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'isStartableInTasklist',
-          'isAttr': true,
-          'type': 'Boolean',
-          'default': true
-        }
-      ]
-    },
-    {
-      'name': 'EscalationEventDefinition',
-      'isAbstract': true,
-      'extends': ['bpmn:EscalationEventDefinition'],
-      'properties': [
-        {
-          'name': 'escalationCodeVariable',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'FormalExpression',
-      'isAbstract': true,
-      'extends': ['bpmn:FormalExpression'],
-      'properties': [
-        {
-          'name': 'resource',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'Assignable',
-      'extends': ['bpmn:UserTask'],
-      'properties': [
-        {
-          'name': 'candidateGroups',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'dueDate',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'followUpDate',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'priority',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'CallActivity',
-      'extends': ['bpmn:CallActivity'],
-      'properties': [
-        {
-          'name': 'calledElementBinding',
-          'isAttr': true,
-          'type': 'String',
-          'default': 'latest'
-        },
-        {
-          'name': 'calledElementVersion',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'calledElementVersionTag',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'calledElementTenantId',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'caseRef',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'caseBinding',
-          'isAttr': true,
-          'type': 'String',
-          'default': 'latest'
-        },
-        {
-          'name': 'caseVersion',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'caseTenantId',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'variableMappingClass',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'variableMappingDelegateExpression',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'ServiceTaskLike',
-      'extends': ['bpmn:ServiceTask', 'bpmn:BusinessRuleTask', 'bpmn:SendTask', 'bpmn:MessageEventDefinition'],
-      'properties': [
-        {
-          'name': 'expression',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'class',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'delegateExpression',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'resultVariable',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'ExclusiveGateway',
-      'isAbstract': true,
-      'extends': ['bpmn:ExclusiveGateway'],
-      'properties': [
-        {
-          'name': 'serviceClass',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'DmnCapable',
-      'extends': ['bpmn:BusinessRuleTask'],
-      'properties': [
-        {
-          'name': 'decisionRef',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'decisionRefBinding',
-          'isAttr': true,
-          'type': 'String',
-          'default': 'latest'
-        },
-        {
-          'name': 'decisionRefVersion',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'mapDecisionResult',
-          'isAttr': true,
-          'type': 'String',
-          'default': 'resultList'
-        },
-        {
-          'name': 'decisionRefTenantId',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'ExternalCapable',
-      'extends': ['flowable:ServiceTaskLike'],
-      'properties': [
-        {
-          'name': 'type',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'topic',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'TaskPriorized',
-      'extends': ['bpmn:Process', 'flowable:ExternalCapable'],
-      'properties': [
-        {
-          'name': 'taskPriority',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'Properties',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['*']
-      },
-      'properties': [
-        {
-          'name': 'values',
-          'type': 'Property',
-          'isMany': true
-        }
-      ]
-    },
-    {
-      'name': 'Property',
-      'superClass': ['Element'],
-      'properties': [
-        {
-          'name': 'id',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'name',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'value',
-          'type': 'String',
-          'isAttr': true
-        }
-      ]
-    },
-    {
-      'name': 'Connector',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['flowable:ServiceTaskLike']
-      },
-      'properties': [
-        {
-          'name': 'inputOutput',
-          'type': 'InputOutput'
-        },
-        {
-          'name': 'connectorId',
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'InputOutput',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['bpmn:FlowNode', 'flowable:Connector']
-      },
-      'properties': [
-        {
-          'name': 'inputOutput',
-          'type': 'InputOutput'
-        },
-        {
-          'name': 'connectorId',
-          'type': 'String'
-        },
-        {
-          'name': 'inputParameters',
-          'isMany': true,
-          'type': 'InputParameter'
-        },
-        {
-          'name': 'outputParameters',
-          'isMany': true,
-          'type': 'OutputParameter'
-        }
-      ]
-    },
-    {
-      'name': 'InputOutputParameter',
-      'properties': [
-        {
-          'name': 'name',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'value',
-          'isBody': true,
-          'type': 'String'
-        },
-        {
-          'name': 'definition',
-          'type': 'InputOutputParameterDefinition'
-        }
-      ]
-    },
-    {
-      'name': 'InputOutputParameterDefinition',
-      'isAbstract': true
-    },
-    {
-      'name': 'List',
-      'superClass': ['InputOutputParameterDefinition'],
-      'properties': [
-        {
-          'name': 'items',
-          'isMany': true,
-          'type': 'InputOutputParameterDefinition'
-        }
-      ]
-    },
-    {
-      'name': 'Map',
-      'superClass': ['InputOutputParameterDefinition'],
-      'properties': [
-        {
-          'name': 'entries',
-          'isMany': true,
-          'type': 'Entry'
-        }
-      ]
-    },
-    {
-      'name': 'Entry',
-      'properties': [
-        {
-          'name': 'key',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'value',
-          'isBody': true,
-          'type': 'String'
-        },
-        {
-          'name': 'definition',
-          'type': 'InputOutputParameterDefinition'
-        }
-      ]
-    },
-    {
-      'name': 'Value',
-      'superClass': ['InputOutputParameterDefinition'],
-      'properties': [
-        {
-          'name': 'id',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'name',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'value',
-          'isBody': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'Script',
-      'superClass': ['InputOutputParameterDefinition'],
-      'properties': [
-        {
-          'name': 'scriptFormat',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'resource',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'value',
-          'isBody': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'Field',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['flowable:ServiceTaskLike', 'flowable:ExecutionListener', 'flowable:TaskListener']
-      },
-      'properties': [
-        {
-          'name': 'name',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'expression',
-          'isAttr': true,
-          'type': 'expression'
-        },
-        {
-          'name': 'string',
-          'type': 'string'
-        },
-        {
-          'name': 'stringValue',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'string',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['flowable:Field']
-      },
-      'properties': [
-        {
-          'name': 'body',
-          'isBody': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'expression',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['flowable:Field']
-      },
-      'properties': [
-        {
-          'name': 'body',
-          'isBody': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'InputParameter',
-      'superClass': ['InputOutputParameter']
-    },
-    {
-      'name': 'OutputParameter',
-      'superClass': ['InputOutputParameter']
-    },
-    {
-      'name': 'Collectable',
-      'isAbstract': true,
-      'extends': ['bpmn:MultiInstanceLoopCharacteristics'],
-      'superClass': ['flowable:AsyncCapable'],
-      'properties': [
-        {
-          'name': 'collection',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'elementVariable',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'SequenceFlow',
-      'superClass': ['FlowElement'],
-      'properties': [
-        {
-          'name': 'isImmediate',
-          'isAttr': true,
-          'type': 'Boolean'
-        },
-        {
-          'name': 'conditionExpression',
-          'type': 'Expression'
-        },
-        {
-          'name': 'sourceRef',
-          'type': 'FlowNode',
-          'isAttr': true,
-          'isReference': true
-        },
-        {
-          'name': 'targetRef',
-          'type': 'FlowNode',
-          'isAttr': true,
-          'isReference': true
-        }
-      ]
-    },
-    {
-      'name': 'MultiInstanceLoopCharacteristics',
-      'superClass': ['LoopCharacteristics'],
-      'properties': [
-        {
-          'name': 'isSequential',
-          'default': false,
-          'isAttr': true,
-          'type': 'Boolean'
-        },
-        {
-          'name': 'behavior',
-          'type': 'MultiInstanceBehavior',
-          'default': 'All',
-          'isAttr': true
-        },
-        {
-          'name': 'loopCardinality',
-          'type': 'Expression',
-          'xml': {
-            'serialize': 'xsi:type'
-          }
-        },
-        {
-          'name': 'loopDataInputRef',
-          'type': 'ItemAwareElement',
-          'isReference': true
-        },
-        {
-          'name': 'loopDataOutputRef',
-          'type': 'ItemAwareElement',
-          'isReference': true
-        },
-        {
-          'name': 'inputDataItem',
-          'type': 'DataInput',
-          'xml': {
-            'serialize': 'property'
-          }
-        },
-        {
-          'name': 'outputDataItem',
-          'type': 'DataOutput',
-          'xml': {
-            'serialize': 'property'
-          }
-        },
-        {
-          'name': 'complexBehaviorDefinition',
-          'type': 'ComplexBehaviorDefinition',
-          'isMany': true
-        },
-        {
-          'name': 'completionCondition',
-          'type': 'Expression',
-          'xml': {
-            'serialize': 'xsi:type'
-          }
-        },
-        {
-          'name': 'oneBehaviorEventRef',
-          'type': 'EventDefinition',
-          'isAttr': true,
-          'isReference': true
-        },
-        {
-          'name': 'noneBehaviorEventRef',
-          'type': 'EventDefinition',
-          'isAttr': true,
-          'isReference': true
-        }
-      ]
-    },
-    {
-      'name': 'FailedJobRetryTimeCycle',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['flowable:AsyncCapable', 'bpmn:MultiInstanceLoopCharacteristics']
-      },
-      'properties': [
-        {
-          'name': 'body',
-          'isBody': true,
-          'type': 'String'
-        }
-      ]
-    },
-    {
-      'name': 'ExecutionListener',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': [
-          'bpmn:Task',
-          'bpmn:ServiceTask',
-          'bpmn:UserTask',
-          'bpmn:BusinessRuleTask',
-          'bpmn:ScriptTask',
-          'bpmn:ReceiveTask',
-          'bpmn:ManualTask',
-          'bpmn:ExclusiveGateway',
-          'bpmn:SequenceFlow',
-          'bpmn:ParallelGateway',
-          'bpmn:InclusiveGateway',
-          'bpmn:EventBasedGateway',
-          'bpmn:StartEvent',
-          'bpmn:IntermediateCatchEvent',
-          'bpmn:IntermediateThrowEvent',
-          'bpmn:EndEvent',
-          'bpmn:BoundaryEvent',
-          'bpmn:CallActivity',
-          'bpmn:SubProcess',
-          'bpmn:Process'
-        ]
-      },
-      'properties': [
-        {
-          'name': 'expression',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'class',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'delegateExpression',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'event',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'script',
-          'type': 'Script'
-        },
-        {
-          'name': 'fields',
-          'type': 'Field',
-          'isMany': true
-        }
-      ]
-    },
-    {
-      'name': 'TaskListener',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['bpmn:UserTask']
-      },
-      'properties': [
-        {
-          'name': 'expression',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'class',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'delegateExpression',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'event',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'script',
-          'type': 'Script'
-        },
-        {
-          'name': 'fields',
-          'type': 'Field',
-          'isMany': true
-        }
-      ]
-    },
-    {
-      'name': 'FormProperty',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['bpmn:StartEvent', 'bpmn:UserTask']
-      },
-      'properties': [
-        {
-          'name': 'id',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'name',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'type',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'required',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'readable',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'writable',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'variable',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'expression',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'datePattern',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'default',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'values',
-          'type': 'Value',
-          'isMany': true
-        }
-      ]
-    },
-    {
-      'name': 'FormData',
-      'superClass': ['Element'],
-      'meta': {
-        'allowedIn': ['bpmn:StartEvent', 'bpmn:UserTask']
-      },
-      'properties': [
-        {
-          'name': 'fields',
-          'type': 'FormField',
-          'isMany': true
-        },
-        {
-          'name': 'businessKey',
-          'type': 'String',
-          'isAttr': true
-        }
-      ]
-    },
-    {
-      'name': 'FormField',
-      'superClass': ['Element'],
-      'properties': [
-        {
-          'name': 'id',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'label',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'type',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'datePattern',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'defaultValue',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'properties',
-          'type': 'Properties'
-        },
-        {
-          'name': 'validation',
-          'type': 'Validation'
-        },
-        {
-          'name': 'values',
-          'type': 'Value',
-          'isMany': true
-        }
-      ]
-    },
-    {
-      'name': 'Validation',
-      'superClass': ['Element'],
-      'properties': [
-        {
-          'name': 'constraints',
-          'type': 'Constraint',
-          'isMany': true
-        }
-      ]
-    },
-    {
-      'name': 'Constraint',
-      'superClass': ['Element'],
-      'properties': [
-        {
-          'name': 'name',
-          'type': 'String',
-          'isAttr': true
-        },
-        {
-          'name': 'config',
-          'type': 'String',
-          'isAttr': true
-        }
-      ]
-    },
-    {
-      'name': 'ConditionalEventDefinition',
-      'isAbstract': true,
-      'extends': ['bpmn:ConditionalEventDefinition'],
-      'properties': [
-        {
-          'name': 'variableName',
-          'isAttr': true,
-          'type': 'String'
-        },
-        {
-          'name': 'variableEvent',
-          'isAttr': true,
-          'type': 'String'
-        }
-      ]
-    }
-  ],
-  'emumerations': []
-};

+ 0 - 138
src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts

@@ -1,138 +0,0 @@
-import ContextPadProvider from 'bpmn-js/lib/features/context-pad/ContextPadProvider';
-import { Injector } from 'didi';
-import EventBus from 'diagram-js/lib/core/EventBus';
-import ContextPad from 'diagram-js/lib/features/context-pad/ContextPad';
-import Modeling from 'bpmn-js/lib/features/modeling/Modeling.js';
-import ElementFactory from 'bpmn-js/lib/features/modeling/ElementFactory';
-import Connect from 'diagram-js/lib/features/connect/Connect';
-import Create from 'diagram-js/lib/features/create/Create';
-import PopupMenu from 'diagram-js/lib/features/popup-menu/PopupMenu';
-import Canvas from 'diagram-js/lib/core/Canvas';
-import Rules from 'diagram-js/lib/features/rules/Rules';
-import { Element, Shape } from 'diagram-js/lib/model/Types';
-import BpmnFactory from 'bpmn-js/lib/features/modeling/BpmnFactory';
-import modeler from '@/store/modules/modeler';
-
-// @Description: 增强元素连线事件
-
-class CustomContextPadProvider extends ContextPadProvider {
-  private _contextPad: ContextPad;
-  private _modeling: Modeling;
-  private _elementFactory: ElementFactory;
-  private _autoPlace: any;
-  private _connect: Connect;
-  private _create: Create;
-  private _popupMenu: PopupMenu;
-  private _canvas: Canvas;
-  private _rules: Rules;
-
-  constructor(
-    config: any,
-    injector: Injector,
-    eventBus: EventBus,
-    contextPad: ContextPad,
-    modeling: Modeling,
-    elementFactory: ElementFactory,
-    connect: Connect,
-    create: Create,
-    popupMenu: PopupMenu,
-    canvas: Canvas,
-    rules: Rules,
-    translate
-  ) {
-    // @ts-expect-error 忽略异常
-    super(config, injector, eventBus, contextPad, modeling, elementFactory, connect, create, popupMenu, canvas, rules, translate);
-
-    this._contextPad = contextPad;
-    this._modeling = modeling;
-    this._elementFactory = elementFactory;
-    this._connect = connect;
-    this._create = create;
-    this._popupMenu = popupMenu;
-    this._canvas = canvas;
-    this._rules = rules;
-
-    this._autoPlace = injector.get('autoPlace', false);
-  }
-
-  getContextPadEntries(element: Element) {
-    const actions: Record<string, any> = {};
-
-    const appendUserTask = (event: Event, element: Shape) => {
-      const shape = this._elementFactory.createShape({ type: 'bpmn:UserTask' });
-      this._create.start(event, shape, {
-        source: element
-      });
-    };
-
-    const appendMultiInstanceUserTask = (event: Event, element: Shape) => {
-      const store = modeler();
-      const bpmnFactory = store.getModeler().get('bpmnFactory') as BpmnFactory;
-      const businessObject = bpmnFactory.create('bpmn:UserTask', {
-        // name: '多实例用户任务',
-        isForCompensation: false
-      });
-      businessObject.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics');
-      // 创建 Shape
-      const shape = this._elementFactory.createShape({
-        type: 'bpmn:UserTask',
-        businessObject: businessObject
-      });
-      this._create.start(event, shape, { source: element });
-    };
-
-    const appendTask = this._autoPlace
-      ? (event, element) => {
-          const bpmnFactory: BpmnFactory | undefined = modeler().getModeler().get('bpmnFactory');
-          const businessObject = bpmnFactory.create('bpmn:UserTask', {
-            // name: '多实例用户任务',// 右键创建显示
-            isForCompensation: false
-          });
-
-          // 创建多实例属性并分配给用户任务的 loopCharacteristics
-          businessObject.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics');
-
-          // 创建 Shape
-          const shape = this._elementFactory.createShape({
-            type: 'bpmn:UserTask',
-            businessObject: businessObject
-          });
-
-          this._autoPlace.append(element, shape);
-        }
-      : appendMultiInstanceUserTask;
-
-    const append = this._autoPlace
-      ? (event: Event, element: Shape) => {
-          const shape = this._elementFactory.createShape({ type: 'bpmn:UserTask' });
-          this._autoPlace.append(element, shape);
-        }
-      : appendUserTask;
-
-    // // 添加创建用户任务按钮
-    actions['append.append-user-task'] = {
-      group: 'model',
-      className: 'bpmn-icon-user-task',
-      title: '用户任务',
-      action: {
-        dragstart: appendUserTask,
-        click: append
-      }
-    };
-
-    // 添加创建多实例用户任务按钮
-    actions['append.append-multi-instance-user-task'] = {
-      group: 'model',
-      className: 'bpmn-icon-user', // 你可以使用多实例用户任务的图标  bpmn-icon-user   bpmn-icon-user-task
-      title: '多实例用户任务',
-      action: {
-        dragstart: appendMultiInstanceUserTask,
-        click: appendTask
-      }
-    };
-
-    return actions;
-  }
-}
-
-export default CustomContextPadProvider;

+ 0 - 109
src/bpmn/assets/module/Palette/CustomPaletteProvider.ts

@@ -1,109 +0,0 @@
-import { assign } from 'min-dash';
-import PaletteProvider from 'bpmn-js/lib/features/palette/PaletteProvider';
-import ElementFactory from 'bpmn-js/lib/features/modeling/ElementFactory';
-import Create from 'diagram-js/lib/features/create/Create';
-import SpaceTool from 'diagram-js/lib/features/space-tool/SpaceTool';
-import LassoTool from 'diagram-js/lib/features/lasso-tool/LassoTool';
-import HandTool from 'diagram-js/lib/features/hand-tool/HandTool';
-import GlobalConnect from 'diagram-js/lib/features/global-connect/GlobalConnect';
-import Palette from 'diagram-js/lib/features/palette/Palette';
-import modeler from '@/store/modules/modeler';
-import BpmnFactory from 'bpmn-js/lib/features/modeling/BpmnFactory';
-
-// @Description: 增强左侧面板
-class CustomPaletteProvider extends PaletteProvider {
-  private readonly _palette: Palette;
-  private readonly _create: Create;
-  private readonly _elementFactory: ElementFactory;
-  private readonly _spaceTool: SpaceTool;
-  private readonly _lassoTool: LassoTool;
-  private readonly _handTool: HandTool;
-  private readonly _globalConnect: GlobalConnect;
-  private readonly _translate: any;
-
-  constructor(palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate) {
-    super(palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate);
-    this._palette = palette;
-    this._create = create;
-    this._elementFactory = elementFactory;
-    this._spaceTool = spaceTool;
-    this._lassoTool = lassoTool;
-    this._handTool = handTool;
-    this._globalConnect = globalConnect;
-    this._translate = translate;
-  }
-
-  getPaletteEntries() {
-    const actions = {},
-      create = this._create,
-      elementFactory = this._elementFactory,
-      translate = this._translate;
-
-    function createAction(type: string, group: string, className: string, title: string, options?: object) {
-      function createListener(event) {
-        const shape = elementFactory.createShape(assign({ type: type }, options));
-        if (options) {
-          !shape.businessObject.di && (shape.businessObject.di = {});
-          shape.businessObject.di.isExpanded = (options as { [key: string]: any }).isExpanded;
-        }
-        create.start(event, shape, null);
-      }
-      const shortType = type.replace(/^bpmn:/, '');
-      return {
-        group: group,
-        className: className,
-        title: title || translate('Create {type}', { type: shortType }),
-        action: {
-          dragstart: createListener,
-          click: createListener
-        }
-      };
-    }
-
-    function createMultiInstanceUserTask(event) {
-      const bpmnFactory: BpmnFactory | undefined = modeler().getBpmnFactory();
-      // 创建一个 bpmn:UserTask
-      const userTask = bpmnFactory.create('bpmn:UserTask', {
-        // name: '多实例用户任务', // 在画板中显示字段
-        isForCompensation: false
-      });
-      // 将多实例属性分配给 bpmn:UserTask 的 loopCharacteristics
-      userTask.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics');
-      const customUserTask = elementFactory.createShape({
-        type: 'bpmn:UserTask',
-        businessObject: userTask // 分配创建的 userTask 到 businessObject
-      });
-      create.start(event, customUserTask, {});
-    }
-
-    assign(actions, {
-      'create.parallel-gateway': createAction('bpmn:ParallelGateway', 'gateway', 'bpmn-icon-gateway-parallel', '并行网关'),
-      'create.event-base-gateway': createAction('bpmn:EventBasedGateway', 'gateway', 'bpmn-icon-gateway-eventbased', '事件网关'),
-      // 分组线
-      'gateway-separator': {
-        group: 'gateway',
-        separator: true
-      },
-      'create.user-task': createAction('bpmn:UserTask', 'activity', 'bpmn-icon-user-task', '创建用户任务'),
-      'create.multi-instance-user-task': {
-        group: 'activity',
-        type: 'bpmn:UserTask',
-        className: 'bpmn-icon-user task-multi-instance',
-        title: '创建多实例用户任务',
-        action: {
-          click: createMultiInstanceUserTask,
-          dragstart: createMultiInstanceUserTask
-        }
-      },
-      'task-separator': {
-        group: 'activity',
-        separator: true
-      }
-    });
-    return actions;
-  }
-}
-
-CustomPaletteProvider['$inject'] = ['palette', 'create', 'elementFactory', 'spaceTool', 'lassoTool', 'handTool', 'globalConnect', 'translate'];
-
-export default CustomPaletteProvider;

+ 0 - 56
src/bpmn/assets/module/Renderer/CustomRenderer.ts

@@ -1,56 +0,0 @@
-import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
-import {
-  append as svgAppend,
-  attr as svgAttr,
-  create as svgCreate,
-  select as svgSelect,
-  selectAll as svgSelectAll,
-  clone as svgClone,
-  clear as svgClear,
-  remove as svgRemove
-} from 'tiny-svg';
-
-const HIGH_PRIORITY = 1500;
-export default class CustomRenderer extends BaseRenderer {
-  bpmnRenderer: BaseRenderer;
-  modeling: any;
-  constructor(eventBus, bpmnRenderer, modeling) {
-    super(eventBus, HIGH_PRIORITY);
-    this.bpmnRenderer = bpmnRenderer;
-    this.modeling = modeling;
-  }
-  canRender(element) {
-    // ignore labels
-    return !element.labelTarget;
-  }
-
-  /**
-   * 自定义节点图形
-   * @param {*} parentNode 当前元素的svgNode
-   * @param {*} element
-   * @returns
-   */
-  drawShape(parentNode, element) {
-    const shape = this.bpmnRenderer.drawShape(parentNode, element);
-    const { type, width, height } = element;
-    // 开始 填充绿色
-    if (type === 'bpmn:StartEvent') {
-      svgAttr(shape, { fill: '#77DF6D' });
-      return shape;
-    }
-    if (type === 'bpmn:EndEvent') {
-      svgAttr(shape, { fill: '#EE7B77' });
-      return shape;
-    }
-    if (type === 'bpmn:UserTask') {
-      svgAttr(shape, { fill: '#A9C4F8' });
-      return shape;
-    }
-    return shape;
-  }
-
-  getShapePath(shape) {
-    return this.bpmnRenderer.getShapePath(shape);
-  }
-}
-CustomRenderer['$inject'] = ['eventBus', 'bpmnRenderer'];

+ 0 - 15
src/bpmn/assets/module/Translate/index.ts

@@ -1,15 +0,0 @@
-import zh from '../../lang/zh';
-
-const customTranslate = (template: any, replacements: any) => {
-  replacements = replacements || {};
-  template = zh[template] || template;
-  return template.replace(/{([^}]+)}/g, function (_: any, key: any) {
-    return replacements[key] || '{' + key + '}';
-  });
-};
-
-export const translateModule = {
-  translate: ['value', customTranslate]
-};
-
-export default translateModule;

+ 0 - 17
src/bpmn/assets/module/index.ts

@@ -1,17 +0,0 @@
-// 翻译模块
-import TranslationModule from './Translate';
-import { ModuleDeclaration } from 'didi';
-import CustomPaletteProvider from './Palette/CustomPaletteProvider';
-import CustomRenderer from './Renderer/CustomRenderer';
-import CustomContextPadProvider from './ContextPad/CustomContextPadProvider';
-
-const Module: ModuleDeclaration[] = [
-  {
-    __init__: ['customPaletteProvider', 'customContextPadProvider', 'customRenderer'],
-    customPaletteProvider: ['type', CustomPaletteProvider],
-    customRenderer: ['type', CustomRenderer],
-    customContextPadProvider: ['type', CustomContextPadProvider]
-  },
-  TranslationModule
-];
-export default Module;

+ 0 - 50
src/bpmn/assets/showConfig.ts

@@ -1,50 +0,0 @@
-export default {
-  'bpmn:EndEvent': {},
-  'bpmn:StartEvent': {
-    initiator: true,
-    formKey: true
-  },
-  'bpmn:UserTask': {
-    allocationType: true,
-    specifyDesc: true,
-    multipleUserAuditType: true,
-    async: true,
-    priority: true,
-    skipExpression: true,
-    dueDate: true,
-    taskListener: true,
-    executionListener: true
-  },
-  'bpmn:ServiceTask': {
-    async: true,
-    skipExpression: true,
-    isForCompensation: true,
-    triggerable: true,
-    class: true
-  },
-  'bpmn:ScriptTask': {
-    async: true,
-    isForCompensation: true,
-    autoStoreVariables: true
-  },
-  'bpmn:ManualTask': {
-    async: true,
-    isForCompensation: true
-  },
-  'bpmn:ReceiveTask': {
-    async: true,
-    isForCompensation: true
-  },
-  'bpmn:SendTask': {
-    async: true,
-    isForCompensation: true
-  },
-  'bpmn:BusinessRuleTask': {
-    async: true,
-    isForCompensation: true,
-    ruleVariablesInput: true,
-    rules: true,
-    resultVariable: true,
-    exclude: true
-  }
-};

+ 0 - 284
src/bpmn/assets/style/index.scss

@@ -1,284 +0,0 @@
-.djs-palette {
-  width: 300px;
-
-  .bpmn-icon-hand-tool:hover {
-    &:after {
-      content: '启动手动工具';
-      position: absolute;
-      left: 45px;
-      width: 120px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-lasso-tool:hover {
-    &:after {
-      content: '启动套索工具';
-      position: absolute;
-      left: 100px;
-      width: 120px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-space-tool:hover {
-    &:after {
-      content: '启动创建/删除空间工具';
-      position: absolute;
-      left: 45px;
-      width: 170px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-connection-multi:hover {
-    &:after {
-      content: '启动全局连接工具';
-      position: absolute;
-      left: 100px;
-      width: 140px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-start-event-none:hover {
-    &:after {
-      content: '创建开始事件';
-      position: absolute;
-      left: 45px;
-      width: 120px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-intermediate-event-none:hover {
-    &:after {
-      content: '创建中间/边界事件';
-      position: absolute;
-      left: 100px;
-      width: 140px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-end-event-none:hover {
-    &:after {
-      content: '创建结束事件';
-      position: absolute;
-      left: 45px;
-      width: 120px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-gateway-none:hover {
-    &:after {
-      content: '创建网关';
-      position: absolute;
-      left: 100px;
-      width: 90px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-gateway-parallel:hover {
-    &:after {
-      content: '创建并行网关';
-      position: absolute;
-      left: 45px;
-      width: 120px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-gateway-eventbased:hover {
-    &:after {
-      content: '创建事件网关';
-      position: absolute;
-      left: 100px;
-      width: 120px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-task:hover {
-    &:after {
-      content: '创建任务';
-      position: absolute;
-      left: 45px;
-      width: 80px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-subprocess-expanded:hover {
-    &:after {
-      content: '创建可折叠子流程';
-      position: absolute;
-      left: 100px;
-      width: 140px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-user-task:hover {
-    &:after {
-      content: '创建用户任务';
-      position: absolute;
-      left: 45px;
-      width: 120px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-
-  .task-multi-instance:hover {
-    &:after {
-      content: '创建多实例用户任务';
-      position: absolute;
-      left: 100px;
-      width: 160px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-participant:hover {
-    &:after {
-      content: '创建泳池/泳道';
-      position: absolute;
-      left: 45px;
-      width: 120px;
-      font-size: 15px;
-      font-weight: bold;
-      color: #3a84de;
-      border-radius: 2px;
-      border: 1px solid #cccccc;
-      background-color: #fafafa;
-      opacity: 0.8;
-    }
-  }
-  .bpmn-icon-data-object {
-    display: none;
-    &:hover {
-      &:after {
-        content: '创建数据对象';
-        position: absolute;
-        left: 45px;
-        width: 120px;
-        font-size: 15px;
-        font-weight: bold;
-        color: #3a84de;
-        border-radius: 2px;
-        border: 1px solid #cccccc;
-        background-color: #fafafa;
-        opacity: 0.8;
-      }
-    }
-  }
-  .bpmn-icon-data-store {
-    display: none;
-    &:hover {
-      &:after {
-        content: '创建数据存储';
-        position: absolute;
-        left: 100px;
-        width: 120px;
-        font-size: 15px;
-        font-weight: bold;
-        color: #3a84de;
-        border-radius: 2px;
-        border: 1px solid #cccccc;
-        background-color: #fafafa;
-        opacity: 0.8;
-      }
-    }
-  }
-  .bpmn-icon-group {
-    display: none;
-    &:hover {
-      &:after {
-        content: '创建分组';
-        position: absolute;
-        left: 100px;
-        width: 100px;
-        font-size: 15px;
-        font-weight: bold;
-        color: #3a84de;
-        border-radius: 2px;
-        border: 1px solid #cccccc;
-        background-color: #fafafa;
-        opacity: 0.8;
-      }
-    }
-  }
-}

+ 0 - 145
src/bpmn/hooks/usePanel.ts

@@ -1,145 +0,0 @@
-import showConfig from '../assets/showConfig';
-import type { ModdleElement } from 'bpmn';
-import useModelerStore from '@/store/modules/modeler';
-import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums';
-interface Options {
-  element: ModdleElement;
-}
-
-export default (ops: Options) => {
-  const { element } = ops;
-  const { getModeling, getModdle } = useModelerStore();
-  const modeling = getModeling();
-  const moddle = getModdle();
-
-  /**
-   * 当前节点类型
-   */
-  const elementType = computed(() => {
-    const bizObj = element.businessObject;
-    return bizObj.eventDefinitions ? bizObj.eventDefinitions[0].$type : bizObj.$type;
-  });
-
-  /**
-   * 用于控制面板字段显示与隐藏的配置
-   */
-  const config = computed(() => showConfig[elementType.value] || {});
-
-  /**
-   * 创建一个节点
-   * @param elementType 节点类型
-   * @param properties 属性
-   * @param parent 父节点
-   */
-  const createModdleElement = (elementType: string, properties: any, parent: ModdleElement) => {
-    const element = moddle.create(elementType, properties);
-    parent && (element.$parent = parent);
-    return element;
-  };
-
-  /**
-   * 获取扩展属性,如果不存在会自动创建
-   */
-  const getExtensionElements = (create = true) => {
-    let extensionElements = element.businessObject.get<ModdleElement>('extensionElements');
-    if (!extensionElements && create) {
-      extensionElements = createModdleElement('bpmn:ExtensionElements', { values: [] }, element.businessObject);
-      modeling.updateModdleProperties(element, element.businessObject, { extensionElements });
-    }
-    return extensionElements;
-  };
-
-  /**
-   * 获取extensionElements下的properties
-   * @param extensionElements 可选参数,默认获取当前Element下的extensionElements下的Properties
-   */
-  const getPropertiesElements = (extensionElements?: ModdleElement) => {
-    if (!extensionElements) {
-      extensionElements = getExtensionElements();
-    }
-    let propertiesElements = extensionElements.values.find((item) => item.$type === 'flowable:properties');
-    if (!propertiesElements) {
-      propertiesElements = createModdleElement('flowable:properties', { values: [] }, extensionElements);
-      modeling.updateModdleProperties(element, extensionElements, {
-        values: [...extensionElements.get<[]>('values'), propertiesElements]
-      });
-    }
-    return propertiesElements;
-  };
-
-  /**
-   * 更新节点属性
-   * @param properties 属性值
-   */
-  const updateProperties = (properties: any) => {
-    modeling.updateProperties(element, properties);
-  };
-
-  /**
-   * 更新节点信息
-   * @param updateElement 需要更新的节点
-   * @param properties 属性
-   */
-  const updateModdleProperties = (updateElement, properties: any) => {
-    modeling.updateModdleProperties(element, updateElement, properties);
-  };
-
-  /**
-   * 更新Property属性
-   * @param name key值
-   * @param value 值
-   */
-  const updateProperty = (name: string, value: string) => {
-    const propertiesElements = getPropertiesElements();
-
-    let propertyElements = propertiesElements.values.find((item) => item.name === name);
-    if (!propertyElements) {
-      propertyElements = createModdleElement('flowable:property', { name: name, value: value }, propertiesElements);
-      modeling.updateModdleProperties(element, propertiesElements, {
-        values: [...propertiesElements.get('values'), propertyElements]
-      });
-    } else {
-      propertyElements.name = name;
-      propertyElements.value = value;
-    }
-    return propertyElements;
-  };
-
-  const idChange = (newVal: string) => {
-    if (newVal) {
-      updateProperties({ id: newVal });
-    }
-  };
-  const nameChange = (newVal: string) => {
-    if (newVal) {
-      updateProperties({ name: newVal });
-    }
-  };
-  const formKeyChange = (newVal: string) => {
-    updateProperties({ formKey: newVal });
-  };
-  const constant = {
-    MultiInstanceType: [
-      { id: '373d4b81-a0d1-4eb8-8685-0d2fb1b468e2', label: '无', value: MultiInstanceTypeEnum.NONE },
-      { id: 'b5acea7c-b7e5-46b0-8778-390db091bdab', label: '串行', value: MultiInstanceTypeEnum.SERIAL },
-      { id: 'b4f0c683-1ccc-43c4-8380-e1b998986caf', label: '并行', value: MultiInstanceTypeEnum.PARALLEL }
-    ]
-  };
-
-  return {
-    elementType,
-    constant,
-    showConfig: config,
-
-    updateProperties,
-    updateProperty,
-    updateModdleProperties,
-
-    createModdleElement,
-    idChange,
-    nameChange,
-    formKeyChange,
-    getExtensionElements,
-    getPropertiesElements
-  };
-};

+ 0 - 34
src/bpmn/hooks/useParseElement.ts

@@ -1,34 +0,0 @@
-import type { ModdleElement } from 'bpmn';
-
-interface Options {
-  element: ModdleElement;
-}
-
-interface Data {
-  id: string;
-}
-
-export default (ops: Options) => {
-  const { element } = ops;
-
-  const parseData = <T>(): T => {
-    const result = {
-      ...element.businessObject,
-      ...element.businessObject.$attrs
-    };
-
-    // 移除flowable前缀,格式化数组
-    for (const key in result) {
-      if (key.indexOf('flowable:') === 0) {
-        const newKey = key.replace('flowable:', '');
-        result[newKey] = result[key];
-        delete result[key];
-      }
-    }
-    return { ...result } as T;
-  };
-
-  return {
-    parseData
-  };
-};

+ 0 - 496
src/bpmn/index.vue

@@ -1,496 +0,0 @@
-<template>
-  <div class="containers-bpmn">
-    <!-- dark模式下 连接线的箭头样式 -->
-    <svg width="0" height="0" style="position: absolute">
-      <defs>
-        <marker id="markerArrow-dark-mode" viewBox="0 0 20 20" refX="11" refY="10" markerWidth="10" markerHeight="10" orient="auto">
-          <path d="M 1 5 L 11 10 L 1 15 Z" class="arrow-dark" />
-        </marker>
-      </defs>
-    </svg>
-    <div v-loading="loading" class="app-containers-bpmn">
-      <el-container class="h-full">
-        <el-container style="align-items: stretch">
-          <el-header>
-            <div class="process-toolbar">
-              <el-space wrap :size="10">
-                <el-tooltip effect="dark" content="自适应屏幕" placement="bottom">
-                  <el-button size="small" icon="Rank" @click="fitViewport" />
-                </el-tooltip>
-                <el-tooltip effect="dark" content="放大" placement="bottom">
-                  <el-button size="small" icon="ZoomIn" @click="zoomViewport(true)" />
-                </el-tooltip>
-                <el-tooltip effect="dark" content="缩小" placement="bottom">
-                  <el-button size="small" icon="ZoomOut" @click="zoomViewport(false)" />
-                </el-tooltip>
-                <el-tooltip effect="dark" content="后退" placement="bottom">
-                  <el-button size="small" icon="Back" @click="bpmnModeler.get('commandStack').undo()" />
-                </el-tooltip>
-                <el-tooltip effect="dark" content="前进" placement="bottom">
-                  <el-button size="small" icon="Right" @click="bpmnModeler.get('commandStack').redo()" />
-                </el-tooltip>
-              </el-space>
-              <el-space wrap :size="10" style="float: right; padding-right: 10px">
-                <el-button size="small" type="primary" @click="saveXml">保 存</el-button>
-                <el-dropdown size="small">
-                  <el-button size="small" type="primary"> 预 览 </el-button>
-                  <template #dropdown>
-                    <el-dropdown-menu>
-                      <el-dropdown-item icon="Document" @click="previewXML">XML预览</el-dropdown-item>
-                      <el-dropdown-item icon="View" @click="previewSVG"> SVG预览</el-dropdown-item>
-                    </el-dropdown-menu>
-                  </template>
-                </el-dropdown>
-                <el-dropdown size="small">
-                  <el-button size="small" type="primary"> 下 载 </el-button>
-                  <template #dropdown>
-                    <el-dropdown-menu>
-                      <el-dropdown-item icon="Download" @click="downloadXML">下载XML</el-dropdown-item>
-                      <el-dropdown-item icon="Download" @click="downloadSVG"> 下载SVG</el-dropdown-item>
-                    </el-dropdown-menu>
-                  </template>
-                </el-dropdown>
-              </el-space>
-            </div>
-          </el-header>
-          <div ref="canvas" class="canvas" />
-        </el-container>
-        <div :class="{ 'process-panel': true, 'hide': panelFlag }">
-          <div class="process-panel-bar" @click="panelBarClick">
-            <div class="open-bar">
-              <el-link type="default" :underline="false">
-                <svg-icon class-name="open-bar" :icon-class="panelFlag ? 'caret-back' : 'caret-forward'"></svg-icon>
-              </el-link>
-            </div>
-          </div>
-          <transition enter-active-class="animate__animated animate__fadeIn">
-            <div v-show="showPanel" v-if="bpmnModeler" class="panel-content">
-              <PropertyPanel :modeler="bpmnModeler" />
-            </div>
-          </transition>
-        </div>
-      </el-container>
-    </div>
-  </div>
-  <div>
-    <el-dialog v-model="perviewXMLShow" title="XML预览" width="80%" append-to-body>
-      <highlightjs :code="xmlStr" language="XML" />
-    </el-dialog>
-  </div>
-  <div>
-    <el-dialog v-model="perviewSVGShow" title="SVG预览" width="80%" append-to-body>
-      <div style="text-align: center" v-html="svgData" />
-    </el-dialog>
-  </div>
-</template>
-
-<script lang="ts" setup name="BpmnDesign">
-import 'bpmn-js/dist/assets/diagram-js.css';
-import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
-import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
-import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
-import './assets/style/index.scss';
-import type { Canvas, Modeler } from 'bpmn';
-import PropertyPanel from './panel/index.vue';
-import BpmnModeler from 'bpmn-js/lib/Modeler.js';
-import defaultXML from './assets/defaultXML';
-import flowableModdle from './assets/moddle/flowable';
-import Modules from './assets/module/index';
-import useModelerStore from '@/store/modules/modeler';
-import useDialog from '@/hooks/useDialog';
-
-const emit = defineEmits(['closeCallBack', 'saveCallBack']);
-
-const { visible, title, openDialog, closeDialog } = useDialog({
-  title: '编辑流程'
-});
-const modelerStore = useModelerStore();
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const panelFlag = ref(false);
-const showPanel = ref(true);
-const canvas = ref<HTMLDivElement>();
-const panel = ref<HTMLDivElement>();
-const bpmnModeler = ref<Modeler>();
-const zoom = ref(1);
-const perviewXMLShow = ref(false);
-const perviewSVGShow = ref(false);
-const xmlStr = ref('');
-const svgData = ref('');
-const loading = ref(false);
-
-const panelBarClick = () => {
-  // 延迟执行,否则会导致面板收起时,属性面板不显示
-  panelFlag.value = !panelFlag.value;
-  setTimeout(() => {
-    showPanel.value = !panelFlag.value;
-  }, 100);
-};
-
-/**
- * 初始化Canvas
- */
-const initCanvas = () => {
-  bpmnModeler.value = new BpmnModeler({
-    container: canvas.value,
-    // 键盘
-    keyboard: {
-      bindTo: window // 或者window,注意与外部表单的键盘监听事件是否冲突
-    },
-    propertiesPanel: {
-      parent: panel.value
-    },
-    additionalModules: Modules,
-    moddleExtensions: {
-      flowable: flowableModdle
-    }
-  });
-};
-
-/**
- * 初始化Model
- */
-const initModel = () => {
-  if (modelerStore.getModeler()) {
-    modelerStore.getModeler().destroy();
-    modelerStore.setModeler(undefined);
-  }
-  modelerStore.setModeler(bpmnModeler.value);
-};
-
-/**
- * 新建
- */
-const newDiagram = async () => {
-  await proxy?.$modal.confirm('是否确认新建');
-  initDiagram();
-};
-
-/**
- * 初始化
- */
-const initDiagram = (xml?: string) => {
-  if (!xml) xml = defaultXML;
-  bpmnModeler.value.importXML(xml);
-};
-
-/**
- * 自适应屏幕
- */
-const fitViewport = () => {
-  zoom.value = bpmnModeler.value.get<Canvas>('canvas').zoom('fit-viewport');
-  const bbox = document.querySelector<SVGGElement>('.app-containers-bpmn .viewport').getBBox();
-  const currentViewBox = bpmnModeler.value.get<Canvas>('canvas').viewbox();
-  const elementMid = {
-    x: bbox.x + bbox.width / 2 - 65,
-    y: bbox.y + bbox.height / 2
-  };
-  bpmnModeler.value.get<Canvas>('canvas').viewbox({
-    x: elementMid.x - currentViewBox.width / 2,
-    y: elementMid.y - currentViewBox.height / 2,
-    width: currentViewBox.width,
-    height: currentViewBox.height
-  });
-  zoom.value = (bbox.width / currentViewBox.width) * 1.8;
-};
-/**
- * 放大或者缩小
- * @param zoomIn true 放大 | false 缩小
- */
-const zoomViewport = (zoomIn = true) => {
-  zoom.value = bpmnModeler.value.get<Canvas>('canvas').zoom();
-  zoom.value += zoomIn ? 0.1 : -0.1;
-  bpmnModeler.value.get<Canvas>('canvas').zoom(zoom.value);
-};
-
-/**
- * 下载XML
- */
-const downloadXML = async () => {
-  try {
-    const { xml } = await bpmnModeler.value.saveXML({ format: true });
-    downloadFile(`${getProcessElement().name}.bpmn20.xml`, xml, 'application/xml');
-  } catch (e) {
-    proxy?.$modal.msgError(e);
-  }
-};
-
-/**
- * 下载SVG
- */
-const downloadSVG = async () => {
-  try {
-    const { svg } = await bpmnModeler.value.saveSVG();
-    downloadFile(getProcessElement().name, svg, 'image/svg+xml');
-  } catch (e) {
-    proxy?.$modal.msgError(e);
-  }
-};
-
-/**
- * XML预览
- */
-const previewXML = async () => {
-  try {
-    const { xml } = await bpmnModeler.value.saveXML({ format: true });
-    xmlStr.value = xml;
-    perviewXMLShow.value = true;
-  } catch (e) {
-    proxy?.$modal.msgError(e);
-  }
-};
-
-/**
- * SVG预览
- */
-const previewSVG = async () => {
-  try {
-    const { svg } = await bpmnModeler.value.saveSVG();
-    svgData.value = svg;
-    perviewSVGShow.value = true;
-  } catch (e) {
-    proxy?.$modal.msgError(e);
-  }
-};
-
-const curNodeInfo = reactive({
-  curType: '', // 任务类型 用户任务
-  curNode: '',
-  expValue: '' //多用户和部门角色实现
-});
-
-const downloadFile = (fileName: string, data: any, type: string) => {
-  const a = document.createElement('a');
-  const url = window.URL.createObjectURL(new Blob([data], { type: type }));
-  a.href = url;
-  a.download = fileName;
-  a.click();
-  window.URL.revokeObjectURL(url);
-};
-
-const getProcessElement = () => {
-  const rootElements = bpmnModeler.value?.getDefinitions().rootElements;
-  for (let i = 0; i < rootElements.length; i++) {
-    if (rootElements[i].$type === 'bpmn:Process') return rootElements[i];
-  }
-};
-
-const getProcess = () => {
-  const element = getProcessElement();
-  return {
-    id: element.id,
-    name: element.name
-  };
-};
-
-const saveXml = async () => {
-  const { xml } = await bpmnModeler.value.saveXML({ format: true });
-  const { svg } = await bpmnModeler.value.saveSVG();
-  const process = getProcess();
-  let data = {
-    xml: xml,
-    svg: svg,
-    key: process.id,
-    name: process.name,
-    loading: loading
-  };
-  emit('saveCallBack', data);
-};
-
-const open = (xml?: string) => {
-  openDialog();
-  nextTick(() => {
-    initDiagram(xml);
-  });
-};
-const close = () => {
-  closeDialog();
-};
-
-onMounted(() => {
-  nextTick(() => {
-    initCanvas();
-    initModel();
-  });
-});
-
-/**
- * 对外暴露子组件方法
- */
-defineExpose({
-  initDiagram,
-  saveXml,
-  open,
-  close
-});
-</script>
-
-<style lang="scss">
-/** 夜间模式 线条的颜色 */
-$stroke-color-dark: white;
-$bpmn-font-size: 12px;
-/** 日间模式 字体颜色 */
-$bpmn-font-color-dark: white;
-/** 夜间模式 字体颜色 */
-$bpmn-font-color-light: #222;
-
-/* 背景网格 */
-@mixin djs-container {
-  background-image: linear-gradient(90deg, hsl(0deg 0% 78.4% / 15%) 10%, transparent 0), linear-gradient(hsl(0deg 0% 78.4% / 15%) 10%, transparent 0) !important;
-  background-size: 10px 10px !important;
-}
-
-html[class='light'] {
-  /** 从左侧拖动时的背景图 */
-  svg.new-parent {
-    @include djs-container;
-  }
-
-  /** 双击编辑元素时样式保持一致 */
-  div.djs-direct-editing-parent {
-    border-radius: 10px;
-    background-color: transparent !important;
-    color: $bpmn-font-color-light;
-  }
-
-  g.djs-visual {
-    .djs-label {
-      fill: $bpmn-font-color-light !important;
-      font-size: $bpmn-font-size !important;
-    }
-  }
-}
-
-html[class='dark'] {
-  /** dark模式下 连接线的箭头样式 */
-  .arrow-dark {
-    stroke-width: 1px;
-    stroke-linecap: round;
-    stroke: $stroke-color-dark;
-    fill: $stroke-color-dark;
-    stroke-linejoin: round;
-  }
-
-  /** 从左侧拖动时的背景图 */
-  svg.new-parent {
-    background-color: black !important;
-    @include djs-container;
-  }
-
-  /** 双击编辑元素时样式保持一致 */
-  div.djs-direct-editing-parent {
-    border-radius: 10px;
-    background-color: transparent !important;
-    color: $bpmn-font-color-dark;
-  }
-
-  /** 元素相关设置 */
-  g.djs-visual {
-    /** 元素边框 需要去除文字(.djs-label) */
-    & > *:first-child:not(.djs-label) {
-      stroke: $stroke-color-dark !important;
-    }
-
-    /** 字体颜色 */
-    .djs-label {
-      fill: $bpmn-font-color-dark !important;
-      font-size: $bpmn-font-size !important;
-    }
-
-    /* 连接线样式 */
-    path[data-corner-radius] {
-      stroke: $stroke-color-dark !important;
-      marker-end: url('#markerArrow-dark-mode') !important;
-    }
-  }
-}
-
-.containers-bpmn {
-  height: 100%;
-  .app-containers-bpmn {
-    width: 100%;
-    height: 100%;
-    .canvas {
-      width: 100%;
-      height: 100%;
-      @include djs-container;
-    }
-    .el-header {
-      height: 35px;
-      padding: 0;
-    }
-
-    .process-panel {
-      transition: width 0.25s ease-in;
-      .process-panel-bar {
-        width: 34px;
-        height: 40px;
-        .open-bar {
-          width: 34px;
-          line-height: 40px;
-        }
-      }
-      // 收起面板样式
-      &.hide {
-        width: 34px;
-        overflow: hidden;
-        padding: 0;
-        .process-panel-bar {
-          width: 34px;
-          height: 100%;
-          box-sizing: border-box;
-          display: block;
-          text-align: left;
-          line-height: 34px;
-        }
-        .process-panel-bar:hover {
-          background-color: var(--bpmn-panel-bar-background-color);
-        }
-      }
-    }
-  }
-}
-pre {
-  margin: 0;
-  height: 100%;
-  max-height: calc(80vh - 32px);
-  overflow-x: hidden;
-  overflow-y: auto;
-  .hljs {
-    word-break: break-word;
-    white-space: pre-wrap;
-    padding: 0.5em;
-  }
-}
-
-.open-bar {
-  font-size: 20px;
-  cursor: pointer;
-  text-align: center;
-}
-.process-panel {
-  box-sizing: border-box;
-  padding: 0 8px 0 8px;
-  border-left: 1px solid var(--bpmn-panel-border);
-  box-shadow: var(--bpmn-panel-box-shadow) 0 0 8px;
-  max-height: 100%;
-  width: 25%;
-  height: calc(100vh - 100px);
-  .el-collapse {
-    height: calc(100vh - 182px);
-    overflow: auto;
-  }
-}
-
-// 任务栏 透明度
-//:deep(.djs-palette) {
-//  opacity: 0.3;
-//  transition: all 1s;
-//}
-//
-//:deep(.djs-palette:hover) {
-//  opacity: 1;
-//  transition: all 1s;
-//}
-</style>

+ 0 - 68
src/bpmn/panel/GatewayPanel.vue

@@ -1,68 +0,0 @@
-<template>
-  <div>
-    <el-collapse v-model="currentCollapseItem">
-      <el-collapse-item name="1">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <InfoFilled />
-            </el-icon>
-            常规
-          </div>
-        </template>
-        <div>
-          <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
-            <el-form-item prop="id" label="节点 ID">
-              <el-input v-model="formData.id" @change="idChange"> </el-input>
-            </el-form-item>
-            <el-form-item prop="name" label="节点名称">
-              <el-input v-model="formData.name" @change="nameChange"> </el-input>
-            </el-form-item>
-          </el-form>
-        </div>
-      </el-collapse-item>
-
-      <el-collapse-item name="2">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <BellFilled />
-            </el-icon>
-            执行监听器
-          </div>
-        </template>
-        <div>
-          <ExecutionListener :element="element"></ExecutionListener>
-        </div>
-      </el-collapse-item>
-    </el-collapse>
-  </div>
-</template>
-<script setup lang="ts">
-import useParseElement from '../hooks/useParseElement';
-import usePanel from '../hooks/usePanel';
-import type { Modeler, ModdleElement } from 'bpmn';
-import type { GatewayPanel } from 'bpmnDesign';
-import ExecutionListener from './property/ExecutionListener.vue';
-
-interface PropType {
-  element: ModdleElement;
-}
-const props = withDefaults(defineProps<PropType>(), {});
-const { nameChange, idChange } = usePanel({
-  element: toRaw(props.element)
-});
-const { parseData } = useParseElement({
-  element: toRaw(props.element)
-});
-const currentCollapseItem = ref(['1', '2']);
-const formData = ref(parseData<GatewayPanel>());
-
-const formRules = ref<ElFormRules>({
-  processCategory: [{ required: true, message: '请选择', trigger: 'blur' }],
-  id: [{ required: true, message: '请输入', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 68
src/bpmn/panel/ParticipantPanel.vue

@@ -1,68 +0,0 @@
-<template>
-  <div>
-    <el-collapse v-model="currentCollapseItem">
-      <el-collapse-item name="1">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <InfoFilled />
-            </el-icon>
-            常规
-          </div>
-        </template>
-        <div>
-          <el-form ref="formRef" :model="formData" :rules="formRules" label-width="90px">
-            <el-form-item prop="id" label="节点 ID">
-              <el-input v-model="formData.id" @change="idChange"></el-input>
-            </el-form-item>
-            <el-form-item prop="name" label="节点名称">
-              <el-input v-model="formData.name" @change="nameChange"></el-input>
-            </el-form-item>
-          </el-form>
-        </div>
-      </el-collapse-item>
-
-      <el-collapse-item name="2">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <BellFilled />
-            </el-icon>
-            执行监听器
-          </div>
-        </template>
-        <div>
-          <ExecutionListener :element="element"></ExecutionListener>
-        </div>
-      </el-collapse-item>
-    </el-collapse>
-  </div>
-</template>
-<script setup lang="ts">
-import useParseElement from '../hooks/useParseElement';
-import usePanel from '../hooks/usePanel';
-import ExecutionListener from './property/ExecutionListener.vue';
-import type { ModdleElement } from 'bpmn';
-import type { ParticipantPanel } from 'bpmnDesign';
-
-interface PropType {
-  element: ModdleElement;
-}
-
-const props = withDefaults(defineProps<PropType>(), {});
-const { nameChange, idChange } = usePanel({
-  element: toRaw(props.element)
-});
-const { parseData } = useParseElement({
-  element: toRaw(props.element)
-});
-
-const formData = ref(parseData<ParticipantPanel>());
-const currentCollapseItem = ref(['1', '2']);
-const formRules = ref<ElFormRules>({
-  id: [{ required: true, message: '请输入', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 71
src/bpmn/panel/ProcessPanel.vue

@@ -1,71 +0,0 @@
-<template>
-  <div>
-    <el-collapse v-model="currentCollapseItem">
-      <el-collapse-item name="1">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <InfoFilled />
-            </el-icon>
-            常规
-          </div>
-        </template>
-        <div>
-          <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
-            <el-form-item label="流程标识" prop="id">
-              <el-input v-model="formData.id" @change="idChange"></el-input>
-            </el-form-item>
-            <el-form-item label="流程名称" prop="name">
-              <el-input v-model="formData.name" @change="nameChange"></el-input>
-            </el-form-item>
-          </el-form>
-        </div>
-      </el-collapse-item>
-
-      <el-collapse-item name="2">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <BellFilled />
-            </el-icon>
-            执行监听器
-          </div>
-        </template>
-        <div>
-          <ExecutionListener :element="element"></ExecutionListener>
-        </div>
-      </el-collapse-item>
-    </el-collapse>
-  </div>
-</template>
-
-<script setup lang="ts">
-import ExecutionListener from './property/ExecutionListener.vue';
-import useParseElement from '../hooks/useParseElement';
-import usePanel from '../hooks/usePanel';
-import type { Modeler, ModdleElement } from 'bpmn';
-import type { ProcessPanel } from 'bpmnDesign';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-interface PropType {
-  element: ModdleElement;
-}
-const props = withDefaults(defineProps<PropType>(), {});
-
-const { parseData } = useParseElement({
-  element: toRaw(props.element)
-});
-const { idChange, nameChange } = usePanel({
-  element: toRaw(props.element)
-});
-const currentCollapseItem = ref(['1', '2']);
-const formData = ref<ProcessPanel>(parseData<ProcessPanel>());
-
-const formRules = ref<ElFormRules>({
-  id: [{ required: true, message: '请输入', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-</script>
-
-<style scoped lang="scss"></style>

+ 0 - 95
src/bpmn/panel/SequenceFlowPanel.vue

@@ -1,95 +0,0 @@
-<template>
-  <div>
-    <el-collapse v-model="currentCollapseItem">
-      <el-collapse-item name="1">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <InfoFilled />
-            </el-icon>
-            常规
-          </div>
-        </template>
-        <div>
-          <el-form ref="formRef" :model="formData" :rules="formRules" label-width="90px">
-            <el-form-item prop="id" label="节点 ID">
-              <el-input v-model="formData.id" @change="idChange"> </el-input>
-            </el-form-item>
-            <el-form-item prop="name" label="节点名称">
-              <el-input v-model="formData.name" @change="nameChange"> </el-input>
-            </el-form-item>
-            <el-form-item prop="conditionExpression" label="跳转条件">
-              <el-input v-model="formData.conditionExpressionValue" @change="conditionExpressionChange"> </el-input>
-            </el-form-item>
-            <el-form-item prop="skipExpression" label="跳过表达式">
-              <el-input v-model="formData.skipExpression" @change="skipExpressionChange"> </el-input>
-            </el-form-item>
-          </el-form>
-        </div>
-      </el-collapse-item>
-
-      <el-collapse-item name="2">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <BellFilled />
-            </el-icon>
-            执行监听器
-          </div>
-        </template>
-        <div>
-          <ExecutionListener :element="element"></ExecutionListener>
-        </div>
-      </el-collapse-item>
-    </el-collapse>
-  </div>
-</template>
-<script setup lang="ts">
-import useParseElement from '../hooks/useParseElement';
-import useModelerStore from '@/store/modules/modeler';
-import usePanel from '../hooks/usePanel';
-import ExecutionListener from './property/ExecutionListener.vue';
-import type { Modeler, ModdleElement } from 'bpmn';
-import type { SequenceFlowPanel } from 'bpmnDesign';
-
-interface PropType {
-  element: ModdleElement;
-}
-const props = withDefaults(defineProps<PropType>(), {});
-const { nameChange, idChange, updateProperties } = usePanel({
-  element: toRaw(props.element)
-});
-const { parseData } = useParseElement({
-  element: toRaw(props.element)
-});
-const moddle = useModelerStore().getModdle();
-const currentCollapseItem = ref(['1', '2']);
-const formData = ref(parseData<SequenceFlowPanel>());
-
-const formRules = ref<ElFormRules>({
-  processCategory: [{ required: true, message: '请选择', trigger: 'blur' }],
-  id: [{ required: true, message: '请输入', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-
-const conditionExpressionChange = (val: string) => {
-  if (val) {
-    const newCondition = moddle.create('bpmn:FormalExpression', { body: val });
-    updateProperties({ conditionExpression: newCondition });
-  } else {
-    updateProperties({ conditionExpression: null });
-  }
-};
-
-const skipExpressionChange = (val: string) => {
-  updateProperties({ 'flowable:skipExpression': val });
-};
-
-onBeforeMount(() => {
-  if (formData.value.conditionExpression) {
-    formData.value.conditionExpressionValue = formData.value.conditionExpression.body;
-  }
-});
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 67
src/bpmn/panel/StartEndPanel.vue

@@ -1,67 +0,0 @@
-<template>
-  <div>
-    <el-collapse v-model="currentCollapseItem">
-      <el-collapse-item name="1">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <InfoFilled />
-            </el-icon>
-            常规
-          </div>
-        </template>
-        <div>
-          <el-form ref="formRef" :model="formData" :rules="formRules" label-width="90px">
-            <el-form-item prop="id" label="节点 ID">
-              <el-input v-model="formData.id" @change="idChange"> </el-input>
-            </el-form-item>
-            <el-form-item prop="name" label="节点名称">
-              <el-input v-model="formData.name" @change="nameChange"> </el-input>
-            </el-form-item>
-          </el-form>
-        </div>
-      </el-collapse-item>
-
-      <el-collapse-item name="2">
-        <template #title>
-          <div class="collapse__title">
-            <el-icon>
-              <BellFilled />
-            </el-icon>
-            执行监听器
-          </div>
-        </template>
-        <div>
-          <ExecutionListener :element="element"></ExecutionListener>
-        </div>
-      </el-collapse-item>
-    </el-collapse>
-  </div>
-</template>
-<script setup lang="ts">
-import ExecutionListener from './property/ExecutionListener.vue';
-import useParseElement from '../hooks/useParseElement';
-import usePanel from '../hooks/usePanel';
-import type { Modeler, ModdleElement } from 'bpmn';
-import type { StartEndPanel } from 'bpmnDesign';
-
-interface PropType {
-  element: ModdleElement;
-}
-const props = withDefaults(defineProps<PropType>(), {});
-const { nameChange, idChange } = usePanel({
-  element: toRaw(props.element)
-});
-const { parseData } = useParseElement({
-  element: toRaw(props.element)
-});
-
-const formData = ref(parseData<StartEndPanel>());
-const currentCollapseItem = ref(['1', '2']);
-const formRules = ref<ElFormRules>({
-  id: [{ required: true, message: '请输入', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 193
src/bpmn/panel/SubProcessPanel.vue

@@ -1,193 +0,0 @@
-<template>
-  <div>
-    <el-form ref="formRef" :model="formData" :rules="formRules" label-width="90px">
-      <el-collapse v-model="currentCollapseItem">
-        <el-collapse-item name="1">
-          <template #title>
-            <div class="collapse__title">
-              <el-icon>
-                <InfoFilled />
-              </el-icon>
-              常规
-            </div>
-          </template>
-          <div>
-            <el-form-item prop="id" label="节点 ID">
-              <el-input v-model="formData.id" @change="idChange"> </el-input>
-            </el-form-item>
-            <el-form-item prop="name" label="节点名称">
-              <el-input v-model="formData.name" @change="nameChange"> </el-input>
-            </el-form-item>
-          </div>
-        </el-collapse-item>
-
-        <el-collapse-item name="2">
-          <template #title>
-            <div class="collapse__title">
-              <el-icon>
-                <BellFilled />
-              </el-icon>
-              执行监听器
-            </div>
-          </template>
-          <div>
-            <ExecutionListener :element="element"></ExecutionListener>
-          </div>
-        </el-collapse-item>
-        <el-collapse-item name="3">
-          <template #title>
-            <div class="collapse__title">
-              <el-icon>
-                <HelpFilled />
-              </el-icon>
-              多实例
-            </div>
-          </template>
-          <div>
-            <el-form-item label="多实例类型">
-              <el-select v-model="formData.multiInstanceType" @change="multiInstanceTypeChange">
-                <el-option v-for="item in constant.MultiInstanceType" :key="item.id" :value="item.value" :label="item.label"> </el-option>
-              </el-select>
-            </el-form-item>
-
-            <div v-if="formData.multiInstanceType !== MultiInstanceTypeEnum.NONE">
-              <el-form-item label="集合">
-                <template #label>
-                  <span>
-                    集合
-                    <el-tooltip placement="top">
-                      <el-icon><QuestionFilled /></el-icon>
-                      <template #content>
-                        属性会作为表达式进行解析。如果表达式解析为字符串而不是一个集合,<br />
-                        不论是因为本身配置的就是静态字符串值,还是表达式计算结果为字符串,<br />
-                        这个字符串都会被当做变量名,并从流程变量中用于获取实际的集合。
-                      </template>
-                    </el-tooltip>
-                  </span>
-                </template>
-                <el-input v-model="formData.collection" @change="collectionChange"></el-input>
-              </el-form-item>
-              <el-form-item label="元素变量">
-                <template #label>
-                  <span>
-                    元素变量
-                    <el-tooltip placement="top">
-                      <el-icon><QuestionFilled /></el-icon>
-                      <template #content>
-                        每创建一个用户任务前,先以该元素变量为label,集合中的一项为value,<br />
-                        创建(局部)流程变量,该局部流程变量被用于指派用户任务。<br />
-                        一般来说,该字符串应与指定人员变量相同。
-                      </template>
-                    </el-tooltip>
-                  </span>
-                </template>
-                <el-input v-model="formData.elementVariable" @change="elementVariableChange"> </el-input>
-              </el-form-item>
-              <el-form-item label="完成条件">
-                <template #label>
-                  <span>
-                    完成条件
-                    <el-tooltip placement="top">
-                      <el-icon><QuestionFilled /></el-icon>
-                      <template #content>
-                        多实例活动在所有实例都完成时结束,然而也可以指定一个表达式,在每个实例<br />
-                        结束时进行计算。当表达式计算为true时,将销毁所有剩余的实例,并结束多实例<br />
-                        活动,继续执行流程。例如 ${nrOfCompletedInstances/nrOfInstances >= 0.6 },<br />
-                        表示当任务完成60%时,该节点就算完成
-                      </template>
-                    </el-tooltip>
-                  </span>
-                </template>
-                <el-input v-model="formData.completionCondition" @change="completionConditionChange"> </el-input>
-              </el-form-item>
-            </div>
-          </div>
-        </el-collapse-item>
-      </el-collapse>
-    </el-form>
-  </div>
-</template>
-<script setup lang="ts">
-import ExecutionListener from './property/ExecutionListener.vue';
-import useParseElement from '../hooks/useParseElement';
-import usePanel from '../hooks/usePanel';
-import type { ModdleElement } from 'bpmn';
-import type { SubProcessPanel } from 'bpmnDesign';
-import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums';
-
-interface PropType {
-  element: ModdleElement;
-}
-const props = withDefaults(defineProps<PropType>(), {});
-const { nameChange, idChange, updateProperties, createModdleElement, constant } = usePanel({
-  element: toRaw(props.element)
-});
-const { parseData } = useParseElement({
-  element: toRaw(props.element)
-});
-
-const formData = ref(parseData<SubProcessPanel>());
-const currentCollapseItem = ref(['1', '2', '3']);
-
-const multiInstanceTypeChange = (newVal) => {
-  if (newVal !== MultiInstanceTypeEnum.NONE) {
-    let loopCharacteristics = props.element.businessObject.get('loopCharacteristics');
-    if (!loopCharacteristics) {
-      loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject);
-    }
-    loopCharacteristics.isSequential = newVal === MultiInstanceTypeEnum.SERIAL;
-    updateProperties({ loopCharacteristics: loopCharacteristics });
-  } else {
-    updateProperties({ loopCharacteristics: undefined });
-  }
-};
-const collectionChange = (newVal) => {
-  let loopCharacteristics = props.element.businessObject.get('loopCharacteristics');
-  if (!loopCharacteristics) {
-    loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject);
-  }
-  loopCharacteristics.collection = newVal && newVal.length > 0 ? newVal : undefined;
-  updateProperties({ loopCharacteristics: loopCharacteristics });
-};
-const elementVariableChange = (newVal) => {
-  let loopCharacteristics = props.element.businessObject.get('loopCharacteristics');
-  if (!loopCharacteristics) {
-    loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject);
-  }
-  loopCharacteristics.elementVariable = newVal && newVal.length > 0 ? newVal : undefined;
-  updateProperties({ loopCharacteristics: loopCharacteristics });
-};
-const completionConditionChange = (newVal) => {
-  let loopCharacteristics = props.element.businessObject.get<ModdleElement>('loopCharacteristics');
-  if (!loopCharacteristics) {
-    loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject);
-  }
-  if (newVal && newVal.length > 0) {
-    if (!loopCharacteristics.completionCondition) {
-      loopCharacteristics.completionCondition = createModdleElement('bpmn:Expression', { body: newVal }, loopCharacteristics);
-    } else {
-      loopCharacteristics.completionCondition.body = newVal;
-    }
-  } else {
-    loopCharacteristics.completionCondition = undefined;
-  }
-  updateProperties({ loopCharacteristics: loopCharacteristics });
-};
-
-onBeforeMount(() => {
-  if (formData.value.loopCharacteristics) {
-    const loopCharacteristics = formData.value.loopCharacteristics;
-    formData.value.collection = loopCharacteristics.collection || '';
-    formData.value.elementVariable = loopCharacteristics.elementVariable || '';
-    formData.value.completionCondition = loopCharacteristics.completionCondition?.body || '';
-    formData.value.multiInstanceType = loopCharacteristics.isSequential ? MultiInstanceTypeEnum.SERIAL : MultiInstanceTypeEnum.PARALLEL;
-  }
-});
-
-const formRules = ref<ElFormRules>({
-  id: [{ required: true, message: '请输入', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 491
src/bpmn/panel/TaskPanel.vue

@@ -1,491 +0,0 @@
-<template>
-  <div>
-    <el-form ref="formRef" size="default" :model="formData" :rules="formRules" label-width="100px">
-      <el-collapse v-model="currentCollapseItem">
-        <el-collapse-item name="1">
-          <template #title>
-            <div class="collapse__title">
-              <el-icon>
-                <InfoFilled />
-              </el-icon>
-              常规
-            </div>
-          </template>
-          <div>
-            <el-form-item prop="id" label="节点 ID">
-              <el-input v-model="formData.id" @change="idChange"> </el-input>
-            </el-form-item>
-            <el-form-item prop="name" label="节点名称">
-              <el-input v-model="formData.name" @change="nameChange"> </el-input>
-            </el-form-item>
-            <el-form-item v-if="showConfig.skipExpression" prop="skipExpression" label="跳过表达式">
-              <el-input v-model="formData.skipExpression" @change="skipExpressionChange"> </el-input>
-            </el-form-item>
-            <el-form-item v-loading="formManageListLoading" prop="formKey" label="表单地址">
-              <el-select v-model="formData.formKey" clearable filterable placeholder="请选择表单" style="width: 260px" @change="formKeyChange">
-                <el-option
-                  v-for="item in formManageList"
-                  :key="item.id"
-                  :label="item.formTypeName + ':' + item.formName"
-                  :value="item.formType + ':' + item.id"
-                />
-              </el-select>
-            </el-form-item>
-          </div>
-        </el-collapse-item>
-        <el-collapse-item name="2">
-          <template #title>
-            <div class="collapse__title">
-              <el-icon>
-                <Checked />
-              </el-icon>
-              任务
-            </div>
-          </template>
-          <div>
-            <el-form-item v-if="showConfig.async" prop="sync" label="是否异步">
-              <el-switch v-model="formData.async" inline-prompt active-text="是" inactive-text="否" @change="syncChange" />
-            </el-form-item>
-
-            <el-tabs tab-position="left" class="demo-tabs">
-              <el-tab-pane label="身份存储">
-                <el-form-item label="分配人员">
-                  <el-input v-model="formData.assignee" @blur="blurAssignee(formData.assignee)">
-                    <template #append>
-                      <el-button icon="Search" type="primary" @click="openSingleUserSelect" />
-                    </template>
-                  </el-input>
-                </el-form-item>
-                <el-form-item label="候选人员">
-                  <el-badge :value="selectUserLength" :max="99">
-                    <el-button size="small" type="primary" @click="openUserSelect">选择人员</el-button>
-                  </el-badge>
-                </el-form-item>
-                <el-form-item label="候选组">
-                  <el-badge :value="selectRoleLength" :max="99">
-                    <el-button size="small" type="primary" @click="openRoleSelect">选择组</el-button>
-                  </el-badge>
-                </el-form-item>
-              </el-tab-pane>
-
-              <!-- <el-tab-pane label="固定值">
-                <el-form-item prop="auditUserType" label="分配类型">
-                  <el-select v-model="formData.allocationType">
-                    <el-option v-for="item in AllocationTypeSelect" :key="item.id" :value="item.value" :label="item.label"> </el-option>
-                  </el-select>
-                </el-form-item>
-                <el-form-item v-if="formData.allocationType === AllocationTypeEnum.USER" label="分配人员">
-                  <el-input v-model="formData.assignee">
-                    <template #append>
-                      <el-button icon="Search" type="primary" @click="openSingleUserSelect" />
-                    </template>
-                  </el-input>
-                </el-form-item>
-                <div v-if="formData.allocationType === AllocationTypeEnum.CANDIDATE">
-                  <el-form-item label="候选人员">
-                    <el-badge :value="selectUserLength" :max="99">
-                      <el-button size="small" type="primary" @click="openUserSelect">选择人员</el-button>
-                    </el-badge>
-                  </el-form-item>
-                  <el-form-item label="候选组">
-                    <el-badge :value="selectRoleLength" :max="99">
-                      <el-button size="small" type="primary" @click="openRoleSelect">选择组</el-button>
-                    </el-badge>
-                  </el-form-item>
-                </div>
-                <el-form-item v-if="formData.allocationType === AllocationTypeEnum.SPECIFY && showConfig.specifyDesc" style="">
-                  <el-radio-group v-model="formData.specifyDesc" class="ml-4">
-                    <el-radio v-for="item in SpecifyDesc" :key="item.id" :value="item.value" size="large">{{ item.label }}</el-radio>
-                  </el-radio-group>
-                </el-form-item>
-              </el-tab-pane> -->
-            </el-tabs>
-
-            <el-form-item v-if="showConfig.dueDate" prop="dueDate" label="到期时间">
-              <el-input v-model="formData.dueDate" clearable @change="dueDateChange" @click="openDueDate">
-                <template #append>
-                  <el-button icon="Search" type="primary" @click="openDueDate" />
-                </template>
-              </el-input>
-            </el-form-item>
-            <el-form-item v-if="showConfig.priority" prop="priority" label="优先级">
-              <el-input-number v-model="formData.priority" :min="0" @change="priorityChange"> </el-input-number>
-            </el-form-item>
-          </div>
-        </el-collapse-item>
-        <el-collapse-item name="3">
-          <template #title>
-            <div class="collapse__title">
-              <el-icon>
-                <HelpFilled />
-              </el-icon>
-              多实例
-            </div>
-          </template>
-          <div>
-            <el-form-item label="多实例类型">
-              <el-select v-model="formData.multiInstanceType" @change="multiInstanceTypeChange">
-                <el-option v-for="item in constant.MultiInstanceType" :key="item.id" :value="item.value" :label="item.label"> </el-option>
-              </el-select>
-            </el-form-item>
-
-            <div v-if="formData.multiInstanceType !== MultiInstanceTypeEnum.NONE">
-              <el-form-item label="集合">
-                <template #label>
-                  <span>
-                    集合
-                    <el-tooltip placement="top">
-                      <el-icon><QuestionFilled /></el-icon>
-                      <template #content>
-                        属性会作为表达式进行解析。如果表达式解析为字符串而不是一个集合,<br />
-                        不论是因为本身配置的就是静态字符串值,还是表达式计算结果为字符串,<br />
-                        这个字符串都会被当做变量名,并从流程变量中用于获取实际的集合。
-                      </template>
-                    </el-tooltip>
-                  </span>
-                </template>
-                <el-input v-model="formData.collection" @change="collectionChange"></el-input>
-              </el-form-item>
-              <el-form-item label="元素变量">
-                <template #label>
-                  <span>
-                    元素变量
-                    <el-tooltip placement="top">
-                      <el-icon><QuestionFilled /></el-icon>
-                      <template #content>
-                        每创建一个用户任务前,先以该元素变量为label,集合中的一项为value,<br />
-                        创建(局部)流程变量,该局部流程变量被用于指派用户任务。<br />
-                        一般来说,该字符串应与指定人员变量相同。
-                      </template>
-                    </el-tooltip>
-                  </span>
-                </template>
-                <el-input v-model="formData.elementVariable" @change="elementVariableChange"> </el-input>
-              </el-form-item>
-              <el-form-item label="完成条件">
-                <template #label>
-                  <span>
-                    完成条件
-                    <el-tooltip placement="top">
-                      <el-icon><QuestionFilled /></el-icon>
-                      <template #content>
-                        多实例活动在所有实例都完成时结束,然而也可以指定一个表达式,在每个实例<br />
-                        结束时进行计算。当表达式计算为true时,将销毁所有剩余的实例,并结束多实例<br />
-                        活动,继续执行流程。例如 ${nrOfCompletedInstances/nrOfInstances >= 0.6 },<br />
-                        表示当任务完成60%时,该节点就算完成
-                      </template>
-                    </el-tooltip>
-                  </span>
-                </template>
-                <el-input v-model="formData.completionCondition" @change="completionConditionChange"> </el-input>
-              </el-form-item>
-            </div>
-          </div>
-        </el-collapse-item>
-        <el-collapse-item v-if="showConfig.taskListener" name="4">
-          <template #title>
-            <div class="collapse__title">
-              <el-icon>
-                <BellFilled />
-              </el-icon>
-              任务监听器
-            </div>
-          </template>
-          <div>
-            <TaskListener v-if="showConfig.taskListener" :element="element"></TaskListener>
-          </div>
-        </el-collapse-item>
-        <el-collapse-item v-if="showConfig.executionListener" name="5">
-          <template #title>
-            <div class="collapse__title">
-              <el-icon>
-                <BellFilled />
-              </el-icon>
-              执行监听器
-            </div>
-          </template>
-          <div>
-            <ExecutionListener v-if="showConfig.executionListener" :element="element"></ExecutionListener>
-          </div>
-        </el-collapse-item>
-
-        <el-form-item v-if="showConfig.isForCompensation" prop="isForCompensation" label="是否为补偿">
-          <el-switch v-model="formData.isForCompensation" inline-prompt active-text="是" inactive-text="否" />
-        </el-form-item>
-        <el-form-item v-if="showConfig.triggerServiceTask" prop="triggerServiceTask" label="服务任务可触发">
-          <el-switch v-model="formData.triggerServiceTask" inline-prompt active-text="是" inactive-text="否" />
-        </el-form-item>
-        <el-form-item v-if="showConfig.autoStoreVariables" prop="autoStoreVariables" label="自动存储变量">
-          <el-switch v-model="formData.autoStoreVariables" inline-prompt active-text="是" inactive-text="否" />
-        </el-form-item>
-        <el-form-item v-if="showConfig.ruleVariablesInput" prop="skipExpression" label="输入变量">
-          <el-input v-model="formData.ruleVariablesInput"> </el-input>
-        </el-form-item>
-        <el-form-item v-if="showConfig.exclude" prop="exclude" label="排除">
-          <el-switch v-model="formData.exclude" inline-prompt active-text="是" inactive-text="否" />
-        </el-form-item>
-        <el-form-item v-if="showConfig.class" prop="class" label="类">
-          <el-input v-model="formData.class"> </el-input>
-        </el-form-item>
-      </el-collapse>
-    </el-form>
-    <UserSelect ref="userSelectRef" :data="formData.candidateUsers" @confirm-call-back="userSelectCallBack"></UserSelect>
-    <UserSelect ref="singleUserSelectRef" :data="formData.assignee" :multiple="false" @confirm-call-back="singleUserSelectCallBack"></UserSelect>
-    <RoleSelect ref="roleSelectRef" :data="formData.candidateGroups" @confirm-call-back="roleSelectCallBack"></RoleSelect>
-    <DueDate ref="dueDateRef" v-model="formData.dueDate" :data="formData.dueDate" @confirm-call-back="dueDateCallBack"></DueDate>
-  </div>
-</template>
-<script setup lang="ts">
-import useParseElement from '../hooks/useParseElement';
-import usePanel from '../hooks/usePanel';
-import UserSelect from '@/components/UserSelect';
-import RoleSelect from '@/components/RoleSelect';
-import ExecutionListener from './property/ExecutionListener.vue';
-import TaskListener from './property/TaskListener.vue';
-import DueDate from './property/DueDate.vue';
-import type { ModdleElement } from 'bpmn';
-import type { TaskPanel } from 'bpmnDesign';
-import { AllocationTypeEnum, MultiInstanceTypeEnum, SpecifyDescEnum } from '@/enums/bpmn/IndexEnums';
-import { UserVO } from '@/api/system/user/types';
-import { RoleVO } from '@/api/system/role/types';
-import { selectListFormManage } from '@/api/workflow/formManage';
-import { FormManageVO } from '@/api/workflow/formManage/types';
-const formManageList = ref<FormManageVO[]>([]);
-const formManageListLoading = ref(false);
-interface PropType {
-  element: ModdleElement;
-}
-const props = withDefaults(defineProps<PropType>(), {});
-const { showConfig, nameChange, formKeyChange, idChange, updateProperties, getExtensionElements, createModdleElement, constant } = usePanel({
-  element: toRaw(props.element)
-});
-const { parseData } = useParseElement({
-  element: toRaw(props.element)
-});
-
-const initFormData = {
-  id: '',
-  name: '',
-  dueDate: '',
-  multiInstanceType: MultiInstanceTypeEnum.NONE,
-  allocationType: AllocationTypeEnum.USER,
-  specifyDesc: SpecifyDescEnum.SPECIFY_SINGLE
-};
-const formData = ref({ ...initFormData, ...parseData<TaskPanel>() });
-const assignee = ref<Partial<UserVO>>({
-  userName: ''
-});
-const currentCollapseItem = ref(['1', '2']);
-const userSelectRef = ref<InstanceType<typeof UserSelect>>();
-const singleUserSelectRef = ref<InstanceType<typeof UserSelect>>();
-const roleSelectRef = ref<InstanceType<typeof RoleSelect>>();
-const dueDateRef = ref<InstanceType<typeof DueDate>>();
-
-const openUserSelect = () => {
-  userSelectRef.value.open();
-};
-const openSingleUserSelect = () => {
-  if (formData.value.assignee?.includes('$')) {
-    formData.value.assignee = '';
-  }
-  singleUserSelectRef.value.open();
-};
-const openRoleSelect = () => {
-  roleSelectRef.value.open();
-};
-const openDueDate = (e) => {
-  dueDateRef.value.openDialog();
-};
-const blurAssignee = (assignee) => {
-  updateProperties({ 'flowable:assignee': assignee ? assignee : undefined });
-};
-const singleUserSelectCallBack = (data: UserVO[]) => {
-  const user: UserVO = data.length !== 0 ? data[0] : undefined;
-  updateProperties({ 'flowable:assignee': user?.userId });
-  assignee.value = user ? user : { userName: '' };
-  formData.value.assignee = String(user?.userId);
-  let extensionElements = getExtensionElements();
-  extensionElements.values = extensionElements.get('values').filter((item) => item.$type !== 'flowable:extAssignee');
-  if (user) {
-    const extAssigneeElement = createModdleElement('flowable:extAssignee', { body: '' }, extensionElements);
-    extensionElements.get('values').push(extAssigneeElement);
-    extAssigneeElement.body = JSON.stringify({ userName: user.userName, userId: user.userId });
-  }
-  if (extensionElements.values.length === 0) {
-    extensionElements = undefined;
-  }
-  updateProperties({ extensionElements: extensionElements });
-};
-const userSelectCallBack = (data: UserVO[]) => {
-  let extensionElements = getExtensionElements();
-  extensionElements.values = extensionElements.values.filter((item) => item.$type !== 'flowable:extCandidateUsers');
-  if (data.length === 0) {
-    formData.value.candidateUsers = undefined;
-    updateProperties({ 'flowable:candidateUsers': undefined });
-  } else {
-    const userIds = data.map((item) => item.userId).join(',');
-    formData.value.candidateUsers = userIds;
-    updateProperties({ 'flowable:candidateUsers': userIds });
-    const extCandidateUsersElement = createModdleElement('flowable:extCandidateUsers', { body: '' }, extensionElements);
-    extensionElements.values.push(extCandidateUsersElement);
-    const users = data.map((item) => {
-      return {
-        userId: item.userId,
-        userName: item.userName
-      };
-    });
-    extCandidateUsersElement.body = JSON.stringify(users);
-  }
-  if (extensionElements.values.length === 0) {
-    extensionElements = undefined;
-  }
-  updateProperties({ extensionElements: extensionElements });
-};
-const roleSelectCallBack = (data: RoleVO[]) => {
-  if (data.length === 0) {
-    formData.value.candidateGroups = '';
-    updateProperties({ 'flowable:candidateGroups': undefined });
-  } else {
-    const roleIds = data.map((item) => item.roleId).join(',');
-    formData.value.candidateGroups = roleIds;
-    updateProperties({ 'flowable:candidateGroups': roleIds });
-  }
-};
-const dueDateCallBack = (data: string) => {
-  updateProperties({ 'flowable:dueDate': data });
-};
-
-const taskTabClick = (e) => {
-  formData.value.candidateGroups = '';
-  formData.value.candidateUsers = '';
-  formData.value.assignee = '';
-  // formData.value.fixedAssignee = '';
-  assignee.value = {};
-};
-
-const syncChange = (newVal) => {
-  updateProperties({ 'flowable:async': newVal });
-};
-const skipExpressionChange = (newVal) => {
-  updateProperties({ 'flowable:skipExpression': newVal && newVal.length > 0 ? newVal : undefined });
-};
-const priorityChange = (newVal) => {
-  updateProperties({ 'flowable:priority': newVal });
-};
-const fixedAssigneeChange = (newVal) => {
-  updateProperties({ 'flowable:assignee': newVal && newVal.length > 0 ? newVal : undefined });
-};
-const multiInstanceTypeChange = (newVal) => {
-  if (newVal !== MultiInstanceTypeEnum.NONE) {
-    let loopCharacteristics = props.element.businessObject.get('loopCharacteristics');
-    if (!loopCharacteristics) {
-      loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject);
-    }
-    loopCharacteristics.isSequential = newVal === MultiInstanceTypeEnum.SERIAL;
-    updateProperties({ loopCharacteristics: loopCharacteristics });
-  } else {
-    updateProperties({ loopCharacteristics: undefined });
-  }
-};
-const collectionChange = (newVal) => {
-  let loopCharacteristics = props.element.businessObject.get('loopCharacteristics');
-  if (!loopCharacteristics) {
-    loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject);
-  }
-  loopCharacteristics.collection = newVal && newVal.length > 0 ? newVal : undefined;
-  updateProperties({ loopCharacteristics: loopCharacteristics });
-};
-const elementVariableChange = (newVal) => {
-  let loopCharacteristics = props.element.businessObject.get('loopCharacteristics');
-  if (!loopCharacteristics) {
-    loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject);
-  }
-  loopCharacteristics.elementVariable = newVal && newVal.length > 0 ? newVal : undefined;
-  updateProperties({ loopCharacteristics: loopCharacteristics });
-};
-const completionConditionChange = (newVal) => {
-  let loopCharacteristics = props.element.businessObject.get<ModdleElement>('loopCharacteristics');
-  if (!loopCharacteristics) {
-    loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject);
-  }
-  if (newVal && newVal.length > 0) {
-    if (!loopCharacteristics.completionCondition) {
-      loopCharacteristics.completionCondition = createModdleElement('bpmn:Expression', { body: newVal }, loopCharacteristics);
-    } else {
-      loopCharacteristics.completionCondition.body = newVal;
-    }
-  } else {
-    loopCharacteristics.completionCondition = undefined;
-  }
-  updateProperties({ loopCharacteristics: loopCharacteristics });
-};
-const dueDateChange = (newVal) => {
-  updateProperties({ 'flowable:dueDate': newVal && newVal.length > 0 ? newVal : undefined });
-};
-const selectUserLength = computed(() => {
-  if (formData.value.candidateUsers) {
-    return formData.value.candidateUsers.split(',').length;
-  } else {
-    return 0;
-  }
-});
-const selectRoleLength = computed(() => {
-  if (formData.value.candidateGroups) {
-    return formData.value.candidateGroups.split(',').length;
-  } else {
-    return 0;
-  }
-});
-
-onBeforeMount(() => {
-  const extensionElements = getExtensionElements(false);
-  if (extensionElements && extensionElements.get('values')) {
-    let extAssigneeElement = extensionElements.get('values').find((item) => item.$type === 'flowable:extAssignee');
-    if (extAssigneeElement) {
-      assignee.value = JSON.parse(extAssigneeElement.body);
-    }
-  }
-
-  if (formData.value.loopCharacteristics) {
-    const loopCharacteristics = formData.value.loopCharacteristics;
-    formData.value.collection = loopCharacteristics.collection || '';
-    formData.value.elementVariable = loopCharacteristics.elementVariable || '';
-    formData.value.completionCondition = loopCharacteristics.completionCondition?.body || '';
-    formData.value.multiInstanceType = loopCharacteristics.isSequential ? MultiInstanceTypeEnum.SERIAL : MultiInstanceTypeEnum.PARALLEL;
-  }
-
-  if (formData.value.assignee) {
-    formData.value.fixedAssignee = formData.value.assignee;
-  }
-});
-
-const formRules = ref<ElFormRules>({
-  id: [{ required: true, message: '请输入', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-
-const AllocationTypeSelect = [
-  { id: 'b9cdf970-dd91-47c0-819f-42a7010ca2a6', label: '指定人员', value: AllocationTypeEnum.USER },
-  { id: '3f7ccbcd-c464-4602-bb9d-e96649d10585', label: '候选人员', value: AllocationTypeEnum.CANDIDATE },
-  { id: 'c49065e0-7f2d-4c09-aedb-ab2d47d9a454', label: '发起人自己', value: AllocationTypeEnum.YOURSELF },
-  { id: '6ef40a03-7e9a-4898-89b2-c88fe9064542', label: '发起人指定', value: AllocationTypeEnum.SPECIFY }
-];
-const SpecifyDesc = [
-  { id: 'fa253b34-4335-458c-b1bc-b039e2a2b7a6', label: '指定一个人', value: 'specifySingle' },
-  { id: '7365ff54-2e05-4312-9bfb-0b8edd779c5b', label: '指定多个人', value: 'specifyMultiple' }
-];
-
-const listFormManage = async () => {
-  formManageListLoading.value = true;
-  const res = await selectListFormManage();
-  formManageList.value = res.data;
-  formManageListLoading.value = false;
-};
-onMounted(() => {
-  nextTick(() => {
-    listFormManage();
-  });
-});
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 110
src/bpmn/panel/index.vue

@@ -1,110 +0,0 @@
-<template>
-  <div ref="propertyPanel">
-    <div v-if="nodeName" class="node-name">{{ nodeName }}</div>
-    <component :is="component" v-if="element" :element="element" />
-  </div>
-</template>
-<script setup lang="ts" name="PropertyPanel">
-import { NodeName } from '../assets/lang/zh';
-import TaskPanel from './TaskPanel.vue';
-import ProcessPanel from './ProcessPanel.vue';
-import StartEndPanel from './StartEndPanel.vue';
-import GatewayPanel from './GatewayPanel.vue';
-import SequenceFlowPanel from './SequenceFlowPanel.vue';
-import ParticipantPanel from './ParticipantPanel.vue';
-import SubProcessPanel from './SubProcessPanel.vue';
-import type { Modeler, ModdleElement } from 'bpmn';
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-interface propsType {
-  modeler: Modeler;
-}
-const props = withDefaults(defineProps<propsType>(), {});
-
-const element = ref<ModdleElement>();
-const processElement = ref<ModdleElement>();
-
-const startEndType = ['bpmn:IntermediateThrowEvent', 'bpmn:StartEvent', 'bpmn:EndEvent'];
-const taskType = [
-  'bpmn:UserTask',
-  'bpmn:Task',
-  'bpmn:SendTask',
-  'bpmn:ReceiveTask',
-  'bpmn:ManualTask',
-  'bpmn:BusinessRuleTask',
-  'bpmn:ServiceTask',
-  'bpmn:ScriptTask'
-];
-const sequenceType = ['bpmn:SequenceFlow'];
-const gatewayType = ['bpmn:InclusiveGateway', 'bpmn:ExclusiveGateway', 'bpmn:ParallelGateway', 'bpmn:EventBasedGateway', 'bpmn:ComplexGateway'];
-const processType = ['bpmn:Process'];
-
-// 组件计算
-const component = computed(() => {
-  if (!element.value) return null;
-  const type = element.value.type;
-  if (startEndType.includes(type)) return StartEndPanel;
-  if (taskType.includes(type)) return TaskPanel;
-  if (sequenceType.includes(type)) return SequenceFlowPanel;
-  if (gatewayType.includes(type)) return GatewayPanel;
-  if (processType.includes(type)) return ProcessPanel;
-  if (type === 'bpmn:Participant') return ParticipantPanel;
-  if (type === 'bpmn:SubProcess') return SubProcessPanel;
-  //return proxy?.$modal.msgWarning('面板开发中....');
-  return undefined;
-});
-
-const nodeName = computed(() => {
-  if (element.value) {
-    const bizObj = element.value.businessObject;
-    const type = bizObj?.eventDefinitions && bizObj?.eventDefinitions.length > 0 ? bizObj.eventDefinitions[0].$type : bizObj.$type;
-    return NodeName[type] || type;
-  }
-  return '';
-});
-
-const handleModeler = () => {
-  props.modeler.on('root.added', (e: any) => {
-    element.value = null;
-    if (e.element.type === 'bpmn:Process') {
-      nextTick(() => {
-        element.value = e.element;
-        processElement.value = e.element;
-      });
-    }
-  });
-  props.modeler.on('element.click', (e: any) => {
-    if (e.element.type === 'bpmn:Process') {
-      nextTick(() => {
-        element.value = e.element;
-        processElement.value = e.element;
-      });
-    }
-  });
-  props.modeler.on('selection.changed', (e: any) => {
-    // 先给null为了让vue刷新
-    element.value = null;
-    const newElement = e.newSelection[0];
-    if (newElement) {
-      nextTick(() => {
-        element.value = newElement;
-      });
-    } else {
-      nextTick(() => {
-        element.value = processElement.value;
-      });
-    }
-  });
-};
-
-onMounted(() => {
-  handleModeler();
-});
-</script>
-
-<style scoped lang="scss">
-.node-name {
-  font-size: 16px;
-  font-weight: bold;
-  padding: 10px;
-}
-</style>

+ 0 - 252
src/bpmn/panel/property/DueDate.vue

@@ -1,252 +0,0 @@
-<template>
-  <div>
-    <el-dialog v-model="visible" :title="title" width="600px" append-to-body>
-      <el-form label-width="100px">
-        <el-form-item label="小时">
-          <el-radio-group v-model="hourValue" @change="hourChange">
-            <el-radio-button label="4" value="4" />
-            <el-radio-button label="8" value="8" />
-            <el-radio-button label="12" value="12" />
-            <el-radio-button label="24" value="24" />
-            <el-radio-button label="自定义" value="自定义" />
-            <el-input-number v-show="hourValue === '自定义'" v-model="customHourValue" :min="1" @change="customHourValueChange"></el-input-number>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="天">
-          <el-radio-group v-model="dayValue" @change="dayChange">
-            <el-radio-button label="1" value="1" />
-            <el-radio-button label="2" value="2" />
-            <el-radio-button label="3" value="3" />
-            <el-radio-button label="4" value="4" />
-            <el-radio-button label="自定义" value="自定义" />
-            <el-input-number v-show="dayValue === '自定义'" v-model="customDayValue" :min="1" @change="customDayValueChange"></el-input-number>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="周">
-          <el-radio-group v-model="weekValue" @change="weekChange">
-            <el-radio-button label="1" value="1" />
-            <el-radio-button label="2" value="2" />
-            <el-radio-button label="3" value="3" />
-            <el-radio-button label="4" value="4" />
-            <el-radio-button label="自定义" value="自定义" />
-            <el-input-number v-show="weekValue === '自定义'" v-model="customWeekValue" :min="1" @change="customWeekValueChange"></el-input-number>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="月">
-          <el-radio-group v-model="monthValue" @change="monthChange">
-            <el-radio-button label="1" value="1" />
-            <el-radio-button label="2" value="2" />
-            <el-radio-button label="3" value="3" />
-            <el-radio-button label="4" value="4" />
-            <el-radio-button label="自定义" value="自定义" />
-            <el-input-number v-show="monthValue === '自定义'" v-model="customMonthValue" :min="1" @change="customMonthValueChange"></el-input-number>
-          </el-radio-group>
-        </el-form-item>
-      </el-form>
-
-      <template #footer>
-        <div>
-          <el-button @click="closeDialog">取消</el-button>
-          <el-button type="primary" @click="confirm">确定</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-import useDialog from '@/hooks/useDialog';
-
-interface PropType {
-  modelValue?: string;
-  data?: string;
-}
-const prop = withDefaults(defineProps<PropType>(), {
-  modelValue: '',
-  data: ''
-});
-const emit = defineEmits(['update:modelValue', 'confirmCallBack']);
-
-const { title, visible, openDialog, closeDialog } = useDialog({
-  title: '设置任务到期时间'
-});
-const formValue = ref();
-const valueType = ref();
-
-const hourValue = ref('');
-const dayValue = ref('');
-const weekValue = ref('');
-const monthValue = ref('');
-
-const customHourValue = ref(1);
-const customDayValue = ref(1);
-const customWeekValue = ref(1);
-const customMonthValue = ref(1);
-
-const hourValueConst = ['4', '8', '12', '24'];
-const dayAndWeekAndMonthValueConst = ['1', '2', '3', '4'];
-
-const initValue = () => {
-  formValue.value = prop.data;
-  if (prop.data) {
-    const lastStr = prop.data.substring(prop.data.length - 1);
-    if (lastStr === 'H') {
-      const hourValueValue = prop.data.substring(2, prop.data.length - 1);
-      if (hourValueConst.includes(hourValueValue)) {
-        hourValue.value = hourValueValue;
-      } else {
-        hourValue.value = '自定义';
-        customHourValue.value = Number(hourValueValue);
-      }
-    }
-    const dayAndWeekAndMonthValue = prop.data.substring(1, prop.data.length - 1);
-    if (lastStr === 'D') {
-      if (dayAndWeekAndMonthValueConst.includes(dayAndWeekAndMonthValue)) {
-        dayValue.value = dayAndWeekAndMonthValue;
-      } else {
-        dayValue.value = '自定义';
-        customDayValue.value = Number(dayAndWeekAndMonthValue);
-      }
-    }
-    if (lastStr === 'W') {
-      if (dayAndWeekAndMonthValueConst.includes(dayAndWeekAndMonthValue)) {
-        weekValue.value = dayAndWeekAndMonthValue;
-      } else {
-        weekValue.value = '自定义';
-        customWeekValue.value = Number(dayAndWeekAndMonthValue);
-      }
-    }
-    if (lastStr === 'M') {
-      if (dayAndWeekAndMonthValueConst.includes(dayAndWeekAndMonthValue)) {
-        monthValue.value = dayAndWeekAndMonthValue;
-      } else {
-        monthValue.value = '自定义';
-        customMonthValue.value = Number(dayAndWeekAndMonthValue);
-      }
-    }
-  }
-};
-
-const confirm = () => {
-  emit('update:modelValue', formValue.value);
-  emit('confirmCallBack', formValue.value);
-  closeDialog();
-};
-
-const customHourValueChange = (customHourValue) => {
-  formValue.value = `PT${customHourValue}H`;
-
-  dayValue.value = '';
-  weekValue.value = '';
-  monthValue.value = '';
-  customDayValue.value = 1;
-  customWeekValue.value = 1;
-  customMonthValue.value = 1;
-};
-const customDayValueChange = (customDayValue) => {
-  formValue.value = `P${customDayValue}D`;
-  hourValue.value = '';
-  weekValue.value = '';
-  monthValue.value = '';
-
-  customHourValue.value = 1;
-  customWeekValue.value = 1;
-  customMonthValue.value = 1;
-};
-
-const customWeekValueChange = (customWeekValue) => {
-  formValue.value = `P${customWeekValue}W`;
-  hourValue.value = '';
-  dayValue.value = '';
-  monthValue.value = '';
-
-  customHourValue.value = 1;
-  customDayValue.value = 1;
-  customMonthValue.value = 1;
-};
-
-const customMonthValueChange = (customMonthValue) => {
-  formValue.value = `P${customMonthValue}M`;
-  hourValue.value = '';
-  dayValue.value = '';
-  weekValue.value = '';
-
-  customHourValue.value = 1;
-  customDayValue.value = 1;
-  customWeekValue.value = 1;
-};
-
-const hourChange = (hourValue) => {
-  if (hourValue === '自定义') {
-    formValue.value = `PT${customHourValue.value}H`;
-  } else {
-    formValue.value = `PT${hourValue}H`;
-  }
-
-  dayValue.value = '';
-  weekValue.value = '';
-  monthValue.value = '';
-  customDayValue.value = 1;
-  customWeekValue.value = 1;
-  customMonthValue.value = 1;
-};
-const dayChange = (dayValue) => {
-  if (dayValue === '自定义') {
-    formValue.value = `P${customDayValue.value}D`;
-  } else {
-    formValue.value = `P${dayValue}D`;
-  }
-
-  hourValue.value = '';
-  weekValue.value = '';
-  monthValue.value = '';
-
-  customHourValue.value = 1;
-  customWeekValue.value = 1;
-  customMonthValue.value = 1;
-};
-const weekChange = (weekValue) => {
-  if (weekValue === '自定义') {
-    formValue.value = `P${customWeekValue.value}W`;
-  } else {
-    formValue.value = `P${weekValue}W`;
-  }
-
-  hourValue.value = '';
-  dayValue.value = '';
-  monthValue.value = '';
-
-  customHourValue.value = 1;
-  customDayValue.value = 1;
-  customMonthValue.value = 1;
-};
-const monthChange = (monthValue) => {
-  if (monthValue === '自定义') {
-    formValue.value = `P${customMonthValue.value}M`;
-  } else {
-    formValue.value = `P${monthValue}M`;
-  }
-
-  hourValue.value = '';
-  dayValue.value = '';
-  weekValue.value = '';
-
-  customHourValue.value = 1;
-  customDayValue.value = 1;
-  customWeekValue.value = 1;
-};
-
-watch(
-  () => visible.value,
-  () => {
-    if (visible.value) {
-      initValue();
-    }
-  }
-);
-
-defineExpose({
-  openDialog,
-  closeDialog
-});
-</script>

+ 0 - 308
src/bpmn/panel/property/ExecutionListener.vue

@@ -1,308 +0,0 @@
-<template>
-  <div>
-    <vxe-toolbar>
-      <template #buttons>
-        <el-button type="primary" link size="small" @click="insertEvent">新增</el-button>
-        <el-button type="primary" link size="small" @click="removeSelectRowEvent">删除</el-button>
-      </template>
-    </vxe-toolbar>
-    <vxe-table
-      ref="tableRef"
-      size="mini"
-      height="100px"
-      border
-      show-overflow
-      keep-source
-      :data="tableData"
-      :menu-config="menuConfig"
-      @cell-dblclick="cellDBLClickEvent"
-      @menu-click="contextMenuClickEvent"
-    >
-      <vxe-column type="checkbox" width="40"></vxe-column>
-      <vxe-column type="seq" width="40"></vxe-column>
-      <vxe-column field="event" title="事件" min-width="100px">
-        <template #default="slotParams">
-          <span>{{ eventSelect.find((e) => e.value === slotParams.row.event)?.label }}</span>
-        </template>
-      </vxe-column>
-      <vxe-column field="type" title="类型" min-width="100px">
-        <template #default="slotParams">
-          <span>{{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}</span>
-        </template>
-      </vxe-column>
-      <vxe-column field="className" title="Java 类名" min-width="100px"> </vxe-column>
-    </vxe-table>
-
-    <el-dialog
-      v-model="formDialog.visible.value"
-      :title="formDialog.title.value"
-      width="600px"
-      :close-on-click-modal="false"
-      :close-on-press-escape="false"
-      :show-close="false"
-      append-to-body
-    >
-      <el-form ref="formRef" :model="formData" :rules="tableRules" label-width="100px">
-        <el-form-item label="事件" prop="event">
-          <el-select v-model="formData.event">
-            <el-option v-for="item in eventSelect" :key="item.id" :value="item.value" :label="item.label"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="类型" prop="type">
-          <template #label>
-            <span>
-              类型
-              <el-tooltip placement="top">
-                <el-icon><QuestionFilled /></el-icon>
-                <template #content>
-                  类:示例 com.company.MyCustomListener,自定义类必须实现 org.flowable.engine.delegate.TaskListener 接口<br />
-                  表达式:示例 ${myObject.callMethod(task, task.eventName)}<br />
-                  委托表达式:示例 ${myListenerSpringBean} ,该 springBean 需要实现 org.flowable.engine.delegate.TaskListener 接口
-                </template>
-              </el-tooltip>
-            </span>
-          </template>
-          <el-select v-model="formData.type">
-            <el-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item
-          :label="typeSelect.filter((e) => e.value === formData.type)[0] ? typeSelect.filter((e) => e.value === formData.type)[0]?.label : '表达式'"
-          prop="className"
-        >
-          <el-input v-model="formData.className" type="text"></el-input>
-        </el-form-item>
-      </el-form>
-      <el-tabs type="border-card">
-        <el-tab-pane label="参数">
-          <ListenerParam ref="listenerParamRef" :table-data="formData.params" />
-        </el-tab-pane>
-      </el-tabs>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="formDialog.closeDialog">取 消</el-button>
-          <el-button type="primary" @click="submitEvent">确 定</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-<script setup lang="ts">
-import ListenerParam from './ListenerParam.vue';
-import { VxeTableEvents, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
-import type { ExecutionListenerVO } from 'bpmnDesign';
-import type { Moddle, Modeler, ModdleElement } from 'bpmn';
-
-import usePanel from '../../hooks/usePanel';
-import useDialog from '@/hooks/useDialog';
-import useModelerStore from '@/store/modules/modeler';
-
-const emit = defineEmits(['close']);
-interface PropType {
-  element: ModdleElement;
-}
-const props = withDefaults(defineProps<PropType>(), {});
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const selectRow = ref<ExecutionListenerVO | null>();
-const formDialog = useDialog({
-  title: selectRow.value ? '编辑&保存' : '新增&保存'
-});
-
-const { showConfig, elementType, updateProperties } = usePanel({
-  element: toRaw(props.element)
-});
-const { getModdle } = useModelerStore();
-const moddle = getModdle();
-
-const listenerParamRef = ref<InstanceType<typeof ListenerParam>>();
-const tableRef = ref<VxeTableInstance<ExecutionListenerVO>>();
-const formRef = ref<ElFormInstance>();
-
-const initData: ExecutionListenerVO = {
-  event: '',
-  type: '',
-  className: '',
-  params: []
-};
-const formData = ref<ExecutionListenerVO>({ ...initData });
-const tableData = ref<ExecutionListenerVO[]>([]);
-const tableRules = ref<ElFormRules>({
-  event: [{ required: true, message: '请选择', trigger: 'blur' }],
-  type: [{ required: true, message: '请选择', trigger: 'blur' }],
-  className: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-
-const submitEvent = async () => {
-  const error = await listenerParamRef.value.validate();
-  await formRef.value.validate((validate) => {
-    if (validate && !error) {
-      const $table = tableRef.value;
-      if ($table) {
-        formData.value.params = listenerParamRef.value.getTableData();
-        if (selectRow.value) {
-          Object.assign(selectRow.value, formData.value);
-        } else {
-          $table.insertAt({ ...formData.value }, -1);
-        }
-        updateElement();
-        formDialog.closeDialog();
-      }
-    }
-  });
-};
-
-const removeSelectRowEvent = async () => {
-  const $table = tableRef.value;
-  if ($table) {
-    const selectCount = $table.getCheckboxRecords().length;
-    if (selectCount === 0) {
-      proxy?.$modal.msgWarning('请选择行');
-    } else {
-      await $table.removeCheckboxRow();
-      updateElement();
-    }
-  }
-};
-const insertEvent = async () => {
-  Object.assign(formData.value, initData);
-  selectRow.value = null;
-  formDialog.openDialog();
-};
-
-const editEvent = (row: ExecutionListenerVO) => {
-  Object.assign(formData.value, row);
-  selectRow.value = row;
-  formDialog.openDialog();
-};
-
-const removeEvent = async (row: ExecutionListenerVO) => {
-  await proxy?.$modal.confirm('您确定要删除该数据?');
-  const $table = tableRef.value;
-  if ($table) {
-    await $table.remove(row);
-    updateElement();
-  }
-};
-const updateElement = () => {
-  const $table = tableRef.value;
-  const data = $table.getTableData().fullData;
-  if (data.length) {
-    let extensionElements = props.element.businessObject.get('extensionElements');
-    if (!extensionElements) {
-      extensionElements = moddle.create('bpmn:ExtensionElements');
-    }
-    // 清除旧值
-    extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:ExecutionListener') ?? [];
-    data.forEach((item) => {
-      const executionListener = moddle.create('flowable:ExecutionListener');
-      executionListener['event'] = item.event;
-      executionListener[item.type] = item.className;
-      if (item.params && item.params.length) {
-        item.params.forEach((field) => {
-          const fieldElement = moddle.create('flowable:Field');
-          fieldElement['name'] = field.name;
-          fieldElement[field.type] = field.value;
-          executionListener.get('fields').push(fieldElement);
-        });
-      }
-      extensionElements.get('values').push(executionListener);
-    });
-    updateProperties({ extensionElements: extensionElements });
-  } else {
-    const extensionElements = props.element.businessObject[`extensionElements`];
-    if (extensionElements) {
-      extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:ExecutionListener') ?? [];
-    }
-  }
-};
-
-const cellDBLClickEvent: VxeTableEvents.CellDblclick<ExecutionListenerVO> = ({ row }) => {
-  editEvent(row);
-};
-
-const menuConfig = reactive<VxeTablePropTypes.MenuConfig<ExecutionListenerVO>>({
-  body: {
-    options: [
-      [
-        { code: 'edit', name: '编辑', prefixIcon: 'vxe-icon-edit', disabled: false },
-        { code: 'remove', name: '删除', prefixIcon: 'vxe-icon-delete', disabled: false }
-      ]
-    ]
-  },
-  visibleMethod({ options, column }) {
-    const isDisabled = !column;
-    options.forEach((list) => {
-      list.forEach((item) => {
-        item.disabled = isDisabled;
-      });
-    });
-    return true;
-  }
-});
-const contextMenuClickEvent: VxeTableEvents.MenuClick<ExecutionListenerVO> = ({ menu, row, column }) => {
-  const $table = tableRef.value;
-  if ($table) {
-    switch (menu.code) {
-      case 'edit':
-        editEvent(row);
-        break;
-      case 'remove':
-        removeEvent(row);
-        break;
-    }
-  }
-};
-
-const initTableData = () => {
-  tableData.value =
-    props.element.businessObject.extensionElements?.values
-      .filter((item) => item.$type === 'flowable:ExecutionListener')
-      .map((item) => {
-        let type;
-        if ('class' in item) type = 'class';
-        if ('expression' in item) type = 'expression';
-        if ('delegateExpression' in item) type = 'delegateExpression';
-        return {
-          event: item.event,
-          type: type,
-          className: item[type],
-          params:
-            item.fields?.map((field) => {
-              let fieldType;
-              if ('stringValue' in field) fieldType = 'stringValue';
-              if ('expression' in field) fieldType = 'expression';
-              return {
-                name: field.name,
-                type: fieldType,
-                value: field[fieldType]
-              };
-            }) ?? []
-        };
-      }) ?? [];
-};
-
-onMounted(() => {
-  initTableData();
-});
-
-const typeSelect = [
-  { id: '742fdeb7-23b4-416b-ac66-cd4ec8b901b7', label: '类', value: 'class' },
-  { id: '660c9c46-8fae-4bae-91a0-0335420019dc', label: '表达式', value: 'expression' },
-  { id: '4b8135ab-6bc3-4a0f-80be-22f58bc6c5fd', label: '委托表达式', value: 'delegateExpression' }
-];
-const eventSelect = [
-  { id: 'e6e0a51a-2d5d-4dc4-b847-b5c14f43a6ab', label: '开始', value: 'start' },
-  { id: '6da97c1e-15fc-4445-8943-75d09f49778e', label: '结束', value: 'end' },
-  { id: '6a2cbcec-e026-4f11-bef7-fff0b5c871e2', label: '启用', value: 'take' }
-];
-</script>
-
-<style scoped lang="scss">
-.el-badge {
-  :deep(.el-badge__content) {
-    top: 10px;
-  }
-}
-</style>

+ 0 - 121
src/bpmn/panel/property/ListenerParam.vue

@@ -1,121 +0,0 @@
-<template>
-  <vxe-toolbar>
-    <template #buttons>
-      <el-button icon="Plus" @click="insertRow">新增</el-button>
-    </template>
-  </vxe-toolbar>
-  <vxe-table
-    ref="tableRef"
-    :height="height"
-    border
-    show-overflow
-    keep-source
-    :data="tableData"
-    :edit-rules="tableRules"
-    :edit-config="{ trigger: 'click', mode: 'row', showStatus: true }"
-  >
-    <vxe-column type="seq" width="40"></vxe-column>
-    <vxe-column field="type" title="类型" :edit-render="{}">
-      <template #default="slotParams">
-        <span>{{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}</span>
-      </template>
-      <template #edit="slotParams">
-        <vxe-select v-model="slotParams.row.type">
-          <vxe-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></vxe-option>
-        </vxe-select>
-      </template>
-    </vxe-column>
-    <vxe-column field="name" title="名称" :edit-render="{}">
-      <template #edit="slotParams">
-        <vxe-input v-model="slotParams.row.name" type="text"></vxe-input>
-      </template>
-    </vxe-column>
-    <vxe-column field="value" title="值" :edit-render="{}">
-      <template #edit="slotParams">
-        <vxe-input v-model="slotParams.row.value" type="text"></vxe-input>
-      </template>
-    </vxe-column>
-    <vxe-column title="操作" width="100" show-overflow align="center">
-      <template #default="slotParams">
-        <el-tooltip content="删除" placement="top">
-          <el-button link type="danger" icon="Delete" @click="removeRow(slotParams.row)"></el-button>
-        </el-tooltip>
-      </template>
-    </vxe-column>
-  </vxe-table>
-</template>
-
-<script setup lang="ts">
-import { VXETable, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
-import type { ParamVO } from 'bpmnDesign';
-import useDialog from '@/hooks/useDialog';
-
-interface PropType {
-  height?: string;
-  tableData?: ParamVO[];
-}
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const props = withDefaults(defineProps<PropType>(), {
-  height: '200px',
-  tableData: () => []
-});
-
-const tableRules = ref<VxeTablePropTypes.EditRules>({
-  type: [{ required: true, message: '请选择', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }],
-  value: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-
-const { title, visible, openDialog, closeDialog } = useDialog({
-  title: '监听器参数'
-});
-const typeSelect = [
-  { id: '742fdeb7-23b4-416b-ac66-cd4ec8b901b7', label: '字符串', value: 'stringValue' },
-  { id: '660c9c46-8fae-4bae-91a0-0335420019dc', label: '表达式', value: 'expression' }
-];
-
-const tableRef = ref<VxeTableInstance<ParamVO>>();
-
-const getTableData = () => {
-  const $table = tableRef.value;
-  if ($table) {
-    return $table.getTableData().fullData;
-  }
-  return [];
-};
-
-const insertRow = async () => {
-  const $table = tableRef.value;
-  if ($table) {
-    const { row: newRow } = await $table.insertAt({}, -1);
-    // 插入一条数据并触发校验
-    await $table.validate(newRow);
-  }
-};
-
-const removeRow = async (row: ParamVO) => {
-  await proxy?.$modal.confirm('您确定要删除该数据?');
-  const $table = tableRef.value;
-  if ($table) {
-    await $table.remove(row);
-  }
-};
-
-const validate = async () => {
-  const $table = tableRef.value;
-  if ($table) {
-    return await $table.validate(true);
-  }
-};
-
-defineExpose({
-  closeDialog,
-  openDialog,
-  validate,
-  getTableData
-});
-</script>
-
-<style scoped lang="scss"></style>

+ 0 - 310
src/bpmn/panel/property/TaskListener.vue

@@ -1,310 +0,0 @@
-<template>
-  <div>
-    <vxe-toolbar>
-      <template #buttons>
-        <el-button type="primary" link size="small" @click="insertEvent">新增</el-button>
-        <el-button type="primary" link size="small" @click="removeSelectRowEvent">删除</el-button>
-      </template>
-    </vxe-toolbar>
-    <vxe-table
-      ref="tableRef"
-      size="mini"
-      height="100px"
-      border
-      show-overflow
-      keep-source
-      :data="tableData"
-      :menu-config="menuConfig"
-      @cell-dblclick="cellDBLClickEvent"
-      @menu-click="contextMenuClickEvent"
-    >
-      <vxe-column type="checkbox" width="40"></vxe-column>
-      <vxe-column type="seq" width="40"></vxe-column>
-      <vxe-column field="event" title="事件" min-width="100px">
-        <template #default="slotParams">
-          <span>{{ eventSelect.find((e) => e.value === slotParams.row.event)?.label }}</span>
-        </template>
-      </vxe-column>
-      <vxe-column field="type" title="类型" min-width="100px">
-        <template #default="slotParams">
-          <span>{{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}</span>
-        </template>
-      </vxe-column>
-      <vxe-column field="className" title="Java 类名" min-width="100px"> </vxe-column>
-    </vxe-table>
-
-    <el-dialog
-      v-model="formDialog.visible.value"
-      :title="formDialog.title.value"
-      width="600px"
-      :close-on-click-modal="false"
-      :close-on-press-escape="false"
-      :show-close="false"
-      append-to-body
-    >
-      <el-form ref="formRef" :model="formData" :rules="tableRules" label-width="100px">
-        <el-form-item label="事件" prop="event">
-          <template #label>
-            <span>
-              事件
-              <el-tooltip placement="top">
-                <el-icon><QuestionFilled /></el-icon>
-                <template #content>
-                  create(创建):当任务已经创建,并且所有任务参数都已经设置时触发。<br />
-                  assignment(指派):当任务已经指派给某人时触发。请注意:当流程执行到达用户任务时,在触发create事件之前,会首先触发assignment事件。<br />
-                  complete(完成):当任务已经完成,从运行时数据中删除前触发。<br />
-                  delete(删除):在任务即将被删除前触发。请注意任务由completeTask正常完成时也会触发。
-                </template>
-              </el-tooltip>
-            </span>
-          </template>
-          <el-select v-model="formData.event">
-            <el-option v-for="item in eventSelect" :key="item.id" :value="item.value" :label="item.label"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="类型" prop="type">
-          <el-select v-model="formData.type">
-            <el-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item
-          :label="typeSelect.filter((e) => e.value === formData.type)[0] ? typeSelect.filter((e) => e.value === formData.type)[0]?.label : '表达式'"
-          prop="className"
-        >
-          <el-input v-model="formData.className" type="text"></el-input>
-        </el-form-item>
-      </el-form>
-      <el-tabs type="border-card">
-        <el-tab-pane label="参数">
-          <ListenerParam ref="listenerParamRef" :table-data="formData.params" />
-        </el-tab-pane>
-      </el-tabs>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="formDialog.closeDialog">取 消</el-button>
-          <el-button type="primary" @click="submitEvent">确 定</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-<script setup lang="ts">
-import ListenerParam from './ListenerParam.vue';
-import { VxeTableEvents, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
-import type { TaskListenerVO } from 'bpmnDesign';
-import type { ModdleElement } from 'bpmn';
-
-import usePanel from '../../hooks/usePanel';
-import useDialog from '@/hooks/useDialog';
-import useModelerStore from '@/store/modules/modeler';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-interface PropType {
-  element: ModdleElement;
-}
-const props = withDefaults(defineProps<PropType>(), {});
-
-const selectRow = ref<TaskListenerVO | null>();
-const formDialog = useDialog({
-  title: selectRow.value ? '编辑&保存' : '新增&保存'
-});
-const { showConfig, elementType, updateProperties } = usePanel({
-  element: toRaw(props.element)
-});
-const { getModdle } = useModelerStore();
-const moddle = getModdle();
-
-const listenerParamRef = ref<InstanceType<typeof ListenerParam>>();
-const tableRef = ref<VxeTableInstance<TaskListenerVO>>();
-const formRef = ref<ElFormInstance>();
-
-const initData: TaskListenerVO = {
-  event: '',
-  type: '',
-  className: '',
-  name: '',
-  params: []
-};
-const formData = ref<TaskListenerVO>({ ...initData });
-const currentIndex = ref(0);
-const tableData = ref<TaskListenerVO[]>([]);
-const tableRules = ref<VxeTablePropTypes.EditRules>({
-  event: [{ required: true, message: '请选择', trigger: 'blur' }],
-  type: [{ required: true, message: '请选择', trigger: 'blur' }],
-  name: [{ required: true, message: '请输入', trigger: 'blur' }],
-  className: [{ required: true, message: '请输入', trigger: 'blur' }]
-});
-
-const submitEvent = async () => {
-  const error = await listenerParamRef.value.validate();
-  await formRef.value.validate((validate) => {
-    if (validate && !error) {
-      const $table = tableRef.value;
-      if ($table) {
-        formData.value.params = listenerParamRef.value.getTableData();
-        if (selectRow.value) {
-          Object.assign(selectRow.value, formData.value);
-        } else {
-          $table.insertAt({ ...formData.value }, -1);
-        }
-        updateElement();
-        formDialog.closeDialog();
-      }
-    }
-  });
-};
-
-const insertEvent = async () => {
-  Object.assign(formData.value, initData);
-  selectRow.value = null;
-  formDialog.openDialog();
-};
-
-const editEvent = (row: TaskListenerVO) => {
-  Object.assign(formData.value, row);
-  selectRow.value = row;
-  formDialog.openDialog();
-};
-const removeEvent = async (row: TaskListenerVO) => {
-  await proxy?.$modal.confirm('您确定要删除该数据?');
-  const $table = tableRef.value;
-  if ($table) {
-    await $table.remove(row);
-    updateElement();
-  }
-};
-
-const removeSelectRowEvent = async () => {
-  const $table = tableRef.value;
-  if ($table) {
-    const selectCount = $table.getCheckboxRecords().length;
-    if (selectCount === 0) {
-      proxy?.$modal.msgWarning('请选择行');
-    } else {
-      await $table.removeCheckboxRow();
-      updateElement();
-    }
-  }
-};
-const updateElement = () => {
-  const $table = tableRef.value;
-  const data = $table.getTableData().fullData;
-  if (data.length) {
-    let extensionElements = props.element.businessObject.get('extensionElements');
-    if (!extensionElements) {
-      extensionElements = moddle.create('bpmn:ExtensionElements');
-    }
-    // 清除旧值
-    extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:TaskListener') ?? [];
-    data.forEach((item) => {
-      const taskListener = moddle.create('flowable:TaskListener');
-      taskListener['event'] = item.event;
-      taskListener[item.type] = item.className;
-      if (item.params && item.params.length) {
-        item.params.forEach((field) => {
-          const fieldElement = moddle.create('flowable:Field');
-          fieldElement['name'] = field.name;
-          fieldElement[field.type] = field.value;
-          taskListener.get('fields').push(fieldElement);
-        });
-      }
-      extensionElements.get('values').push(taskListener);
-    });
-    updateProperties({ extensionElements: extensionElements });
-  } else {
-    const extensionElements = props.element.businessObject[`extensionElements`];
-    if (extensionElements) {
-      extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:TaskListener') ?? [];
-    }
-  }
-};
-
-const cellDBLClickEvent: VxeTableEvents.CellDblclick<TaskListenerVO> = ({ row }) => {
-  editEvent(row);
-};
-
-const menuConfig = reactive<VxeTablePropTypes.MenuConfig<TaskListenerVO>>({
-  body: {
-    options: [
-      [
-        { code: 'edit', name: '编辑', prefixIcon: 'vxe-icon-edit', disabled: false },
-        { code: 'remove', name: '删除', prefixIcon: 'vxe-icon-delete', disabled: false }
-      ]
-    ]
-  },
-  visibleMethod({ options, column }) {
-    const isDisabled = !column;
-    options.forEach((list) => {
-      list.forEach((item) => {
-        item.disabled = isDisabled;
-      });
-    });
-    return true;
-  }
-});
-const contextMenuClickEvent: VxeTableEvents.MenuClick<TaskListenerVO> = ({ menu, row, column }) => {
-  const $table = tableRef.value;
-  if ($table) {
-    switch (menu.code) {
-      case 'edit':
-        editEvent(row);
-        break;
-      case 'remove':
-        removeEvent(row);
-        break;
-    }
-  }
-};
-const initTableData = () => {
-  tableData.value =
-    props.element.businessObject.extensionElements?.values
-      .filter((item) => item.$type === 'flowable:TaskListener')
-      .map((item) => {
-        let type;
-        if ('class' in item) type = 'class';
-        if ('expression' in item) type = 'expression';
-        if ('delegateExpression' in item) type = 'delegateExpression';
-        return {
-          event: item.event,
-          type: type,
-          className: item[type],
-          params:
-            item.fields?.map((field) => {
-              let fieldType;
-              if ('stringValue' in field) fieldType = 'stringValue';
-              if ('expression' in field) fieldType = 'expression';
-              return {
-                name: field.name,
-                type: fieldType,
-                value: field[fieldType]
-              };
-            }) ?? []
-        };
-      }) ?? [];
-};
-
-onMounted(() => {
-  initTableData();
-});
-
-const typeSelect = [
-  { id: '742fdeb7-23b4-416b-ac66-cd4ec8b901b7', label: '类', value: 'class' },
-  { id: '660c9c46-8fae-4bae-91a0-0335420019dc', label: '表达式', value: 'expression' },
-  { id: '4b8135ab-6bc3-4a0f-80be-22f58bc6c5fd', label: '委托表达式', value: 'delegateExpression' }
-];
-const eventSelect = [
-  { id: 'e6e0a51a-2d5d-4dc4-b847-b5c14f43a6ab', label: '创建', value: 'create' },
-  { id: '6da97c1e-15fc-4445-8943-75d09f49778e', label: '指派', value: 'assignment' },
-  { id: '6a2cbcec-e026-4f11-bef7-fff0b5c871e2', label: '完成', value: 'complete' },
-  { id: '68801972-85f1-482f-bd86-1fad015c26ed', label: '删除', value: 'delete' }
-];
-</script>
-
-<style scoped lang="scss">
-.el-badge {
-  :deep(.el-badge__content) {
-    top: 10px;
-  }
-}
-</style>

+ 0 - 71
src/components/BpmnDesign/index.vue

@@ -1,71 +0,0 @@
-<template>
-  <div class="design">
-    <el-dialog v-model="visible" width="100%" fullscreen :title="title">
-      <div class="modeler">
-        <bpmn-design ref="bpmnDesignRef" @save-call-back="saveCallBack"></bpmn-design>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-
-<script lang="ts" setup name="Design">
-import { getInfo, editModelXml } from '@/api/workflow/model';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-import { ModelForm } from '@/api/workflow/model/types';
-import BpmnDesign from '@/bpmn/index.vue';
-import useDialog from '@/hooks/useDialog';
-const bpmnDesignRef = ref<InstanceType<typeof BpmnDesign>>();
-const modelForm = ref<ModelForm>();
-const emit = defineEmits(['closeCallBack']);
-const { visible, title } = useDialog({
-  title: '编辑流程'
-});
-const modelId = ref('');
-const open = async (id) => {
-  visible.value = true;
-  modelId.value = id;
-  const { data } = await getInfo(id);
-  modelForm.value = data;
-  bpmnDesignRef.value.initDiagram(modelForm.value.xml);
-};
-//保存模型
-const saveCallBack = async (data) => {
-  await proxy?.$modal.confirm('是否确认保存?');
-  data.loading.value = true;
-  modelForm.value.id = modelId.value;
-  modelForm.value.xml = data.xml;
-  modelForm.value.svg = data.svg;
-  modelForm.value.key = data.key;
-  modelForm.value.name = data.name;
-  editModelXml(modelForm.value).then((res) => {
-    if (res.code === 200) {
-      visible.value = false;
-      proxy?.$modal.msgSuccess('保存成功');
-      emit('closeCallBack', data);
-    }
-  });
-  data.loading.value = false;
-};
-
-/**
- * 对外暴露子组件方法
- */
-defineExpose({
-  open
-});
-</script>
-
-<style lang="scss" scoped>
-.design {
-  :deep(.el-dialog .el-dialog__body) {
-    max-height: 100% !important;
-    min-height: calc(100vh - 80px);
-    padding: 10px 0 10px 0 !important;
-  }
-  :deep(.el-dialog__header) {
-    padding: 0 0 5px 0 !important;
-  }
-}
-</style>

+ 0 - 411
src/components/BpmnView/index.vue

@@ -1,411 +0,0 @@
-<template>
-  <div v-loading="loading" class="bpmnDialogContainers">
-    <el-header style="border-bottom: 1px solid rgb(218 218 218); height: auto">
-      <div class="header-div">
-        <div>
-          <el-tooltip effect="dark" content="自适应屏幕" placement="bottom">
-            <el-button size="small" icon="Rank" @click="fitViewport" />
-          </el-tooltip>
-          <el-tooltip effect="dark" content="放大" placement="bottom">
-            <el-button size="small" icon="ZoomIn" @click="zoomViewport(true)" />
-          </el-tooltip>
-          <el-tooltip effect="dark" content="缩小" placement="bottom">
-            <el-button size="small" icon="ZoomOut" @click="zoomViewport(false)" />
-          </el-tooltip>
-        </div>
-        <div>
-          <div class="tips-label">
-            <div class="un-complete">未完成</div>
-            <div class="in-progress">进行中</div>
-            <div class="complete">已完成</div>
-          </div>
-        </div>
-      </div>
-    </el-header>
-    <div class="flow-containers">
-      <el-container class="bpmn-el-container" style="align-items: stretch">
-        <el-main style="padding: 0">
-          <div ref="canvas" class="canvas" />
-        </el-main>
-      </el-container>
-    </div>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import BpmnViewer from 'bpmn-js/lib/Viewer';
-import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
-import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
-import { ModuleDeclaration } from 'didi';
-import type { Canvas, ModdleElement } from 'bpmn';
-import EventBus from 'diagram-js/lib/core/EventBus';
-import Overlays from 'diagram-js/lib/features/overlays/Overlays';
-import processApi from '@/api/workflow/processInstance/index';
-
-const canvas = ref<HTMLElement>();
-const modeler = ref<BpmnViewer>();
-const taskList = ref([]);
-const zoom = ref(1);
-const xml = ref('');
-const loading = ref(false);
-const bpmnVisible = ref(true);
-const historyList = ref([]);
-
-const init = (businessKey) => {
-  loading.value = true;
-  bpmnVisible.value = true;
-  nextTick(async () => {
-    if (modeler.value) modeler.value.destroy();
-    modeler.value = new BpmnViewer({
-      container: canvas.value,
-      additionalModules: [
-        {
-          //禁止滚轮滚动
-          zoomScroll: ['value', '']
-        },
-        ZoomScrollModule,
-        MoveCanvasModule
-      ] as ModuleDeclaration[]
-    });
-    const resp = await processApi.getHistoryList(businessKey);
-    xml.value = resp.data.xml;
-    taskList.value = resp.data.taskList;
-    historyList.value = resp.data.historyList;
-    await createDiagram(xml.value);
-    loading.value = false;
-  });
-};
-
-const initXml = (xmlStr: string) => {
-  loading.value = true;
-  bpmnVisible.value = true;
-  nextTick(async () => {
-    if (modeler.value) modeler.value.destroy();
-    modeler.value = new BpmnViewer({
-      container: canvas.value,
-      additionalModules: [
-        {
-          //禁止滚轮滚动
-          zoomScroll: ['value', '']
-        },
-        ZoomScrollModule,
-        MoveCanvasModule
-      ] as ModuleDeclaration[]
-    });
-    xml.value = xmlStr;
-    await createDiagram(xml.value);
-    loading.value = false;
-  });
-};
-
-const createDiagram = async (data) => {
-  try {
-    await modeler.value.importXML(data);
-    fitViewport();
-    fillColor();
-    loading.value = false;
-    addEventBusListener();
-  } catch (err) {
-    console.log(err);
-  }
-};
-const addEventBusListener = () => {
-  const eventBus = modeler.value.get<EventBus>('eventBus');
-  const overlays = modeler.value.get<Overlays>('overlays');
-  eventBus.on<ModdleElement>('element.hover', (e) => {
-    let data = historyList.value.find((t) => t.taskDefinitionKey === e.element.id);
-    if (e.element.type === 'bpmn:UserTask' && data) {
-      setTimeout(() => {
-        genNodeDetailBox(e, overlays, data);
-      }, 10);
-    }
-  });
-  eventBus.on('element.out', (e) => {
-    overlays.clear();
-  });
-};
-const genNodeDetailBox = (e, overlays, data) => {
-  overlays.add(e.element.id, {
-    position: { top: e.element.height, left: 0 },
-    html: `<div class="verlays">
-                    <p>审批人员: ${data.nickName || ''}<p/>
-                    <p>节点状态:${data.status || ''}</p>
-                    <p>开始时间:${data.startTime || ''}</p>
-                    <p>结束时间:${data.endTime || ''}</p>
-                    <p>审批耗时:${data.runDuration || ''}</p>
-                    <p>流程版本:v${data.version || ''}</p>
-                   </div>`
-  });
-};
-// 让图能自适应屏幕
-const fitViewport = () => {
-  zoom.value = modeler.value.get<Canvas>('canvas').zoom('fit-viewport');
-  const bbox = document.querySelector<SVGGElement>('.flow-containers .viewport').getBBox();
-  const currentViewBox = modeler.value.get('canvas').viewbox();
-  const elementMid = {
-    x: bbox.x + bbox.width / 2 - 65,
-    y: bbox.y + bbox.height / 2
-  };
-  modeler.value.get<Canvas>('canvas').viewbox({
-    x: elementMid.x - currentViewBox.width / 2,
-    y: elementMid.y - currentViewBox.height / 2,
-    width: currentViewBox.width,
-    height: currentViewBox.height
-  });
-  zoom.value = (bbox.width / currentViewBox.width) * 1.8;
-};
-// 放大缩小
-const zoomViewport = (zoomIn = true) => {
-  zoom.value = modeler.value.get<Canvas>('canvas').zoom();
-  zoom.value += zoomIn ? 0.1 : -0.1;
-  modeler.value.get<Canvas>('canvas').zoom(zoom.value);
-};
-//上色
-const fillColor = () => {
-  const canvas = modeler.value.get<Canvas>('canvas');
-  bpmnNodeList(modeler.value._definitions.rootElements[0].flowElements, canvas);
-};
-//递归上色
-const bpmnNodeList = (flowElements, canvas) => {
-  flowElements.forEach((n) => {
-    if (n.$type === 'bpmn:UserTask') {
-      const completeTask = taskList.value.find((m) => m.key === n.id);
-      if (completeTask) {
-        canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo');
-        n.outgoing?.forEach((nn) => {
-          const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id);
-          if (targetTask) {
-            canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo');
-          } else if (nn.targetRef.$type === 'bpmn:ExclusiveGateway') {
-            canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo');
-            canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo');
-            nn.targetRef.outgoing.forEach((e) => {
-              gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed);
-            });
-          } else if (nn.targetRef.$type === 'bpmn:ParallelGateway') {
-            canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo');
-            canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo');
-            nn.targetRef.outgoing.forEach((e) => {
-              gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed);
-            });
-          } else if (nn.targetRef.$type === 'bpmn:InclusiveGateway') {
-            canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo');
-            canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo');
-            nn.targetRef.outgoing.forEach((e) => {
-              gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed);
-            });
-          }
-        });
-      }
-    } else if (n.$type === 'bpmn:ExclusiveGateway') {
-      n.outgoing.forEach((nn) => {
-        const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id);
-        if (targetTask) {
-          canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo');
-        }
-      });
-    } else if (n.$type === 'bpmn:ParallelGateway') {
-      n.outgoing.forEach((nn) => {
-        const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id);
-        if (targetTask) {
-          canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo');
-        }
-      });
-    } else if (n.$type === 'bpmn:InclusiveGateway') {
-      n.outgoing.forEach((nn) => {
-        const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id);
-        if (targetTask) {
-          canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo');
-        }
-      });
-    } else if (n.$type === 'bpmn:SubProcess') {
-      const completeTask = taskList.value.find((m) => m.key === n.id);
-      if (completeTask) {
-        canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo');
-      }
-      bpmnNodeList(n.flowElements, canvas);
-    } else if (n.$type === 'bpmn:StartEvent') {
-      canvas.addMarker(n.id, 'startEvent');
-      if (n.outgoing) {
-        n.outgoing.forEach((nn) => {
-          const completeTask = taskList.value.find((m) => m.key === nn.targetRef.id);
-          if (completeTask) {
-            canvas.addMarker(nn.id, 'highlight');
-            canvas.addMarker(n.id, 'highlight');
-          }
-        });
-      }
-    } else if (n.$type === 'bpmn:EndEvent') {
-      canvas.addMarker(n.id, 'endEvent');
-      const completeTask = taskList.value.find((m) => m.key === n.id);
-      if (completeTask) {
-        canvas.addMarker(completeTask.key, 'highlight');
-        canvas.addMarker(n.id, 'highlight');
-        return;
-      }
-    }
-  });
-};
-const gateway = (id, targetRefType, targetRefId, canvas, completed) => {
-  if (targetRefType === 'bpmn:ExclusiveGateway') {
-    canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo');
-    canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo');
-  }
-  if (targetRefType === 'bpmn:ParallelGateway') {
-    canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo');
-    canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo');
-  }
-  if (targetRefType === 'bpmn:InclusiveGateway') {
-    canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo');
-    canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo');
-  }
-};
-defineExpose({
-  init,
-  initXml
-});
-</script>
-
-<style lang="scss" scoped>
-.canvas {
-  width: 100%;
-  height: 100%;
-}
-
-.header-div {
-  display: flex;
-  padding: 10px 0;
-  justify-content: space-between;
-
-  .tips-label {
-    display: flex;
-    div {
-      margin-right: 10px;
-      padding: 5px;
-      font-size: 12px;
-    }
-    .un-complete {
-      border: 1px solid #000;
-    }
-    .in-progress {
-      background-color: rgb(255, 237, 204);
-      border: 1px dashed orange;
-    }
-    .complete {
-      background-color: rgb(204, 230, 204);
-      border: 1px solid green;
-    }
-  }
-}
-
-.view-mode {
-  .el-header,
-  .el-aside,
-  .djs-palette,
-  .bjs-powered-by {
-    display: none;
-  }
-  .el-loading-mask {
-    background-color: initial;
-  }
-  .el-loading-spinner {
-    display: none;
-  }
-}
-.bpmn-el-container {
-  height: calc(100vh - 350px);
-}
-.flow-containers {
-  width: 100%;
-  height: 100%;
-  overflow-y: auto;
-  .canvas {
-    width: 100%;
-    height: 100%;
-  }
-  .load {
-    margin-right: 10px;
-  }
-  :deep(.el-form-item__label) {
-    font-size: 13px;
-  }
-
-  :deep(.djs-palette) {
-    left: 0 !important;
-    top: 0;
-    border-top: none;
-  }
-
-  :deep(.djs-container svg) {
-    min-height: 650px;
-  }
-
-  :deep(.startEvent.djs-shape .djs-visual > :nth-child(1)) {
-    fill: #77df6d !important;
-  }
-  :deep(.endEvent.djs-shape .djs-visual > :nth-child(1)) {
-    fill: #ee7b77 !important;
-  }
-  :deep(.highlight.djs-shape .djs-visual > :nth-child(1)) {
-    fill: green !important;
-    stroke: green !important;
-    fill-opacity: 0.2 !important;
-  }
-  :deep(.highlight.djs-shape .djs-visual > :nth-child(2)) {
-    fill: green !important;
-  }
-  :deep(.highlight.djs-shape .djs-visual > path) {
-    fill: green !important;
-    fill-opacity: 0.2 !important;
-    stroke: green !important;
-  }
-  :deep(.highlight.djs-connection > .djs-visual > path) {
-    stroke: green !important;
-  }
-
-  // 边框滚动动画
-  @keyframes path-animation {
-    from {
-      stroke-dashoffset: 100%;
-    }
-
-    to {
-      stroke-dashoffset: 0%;
-    }
-  }
-
-  :deep(.highlight-todo.djs-connection > .djs-visual > path) {
-    animation: path-animation 60s;
-    animation-timing-function: linear;
-    animation-iteration-count: infinite;
-    stroke-dasharray: 4px !important;
-    stroke: orange !important;
-    fill-opacity: 0.2 !important;
-    marker-end: url('#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr');
-  }
-
-  :deep(.highlight-todo.djs-shape .djs-visual > :nth-child(1)) {
-    animation: path-animation 60s;
-    animation-timing-function: linear;
-    animation-iteration-count: infinite;
-    stroke-dasharray: 4px !important;
-    stroke: orange !important;
-    fill: orange !important;
-    fill-opacity: 0.2 !important;
-  }
-}
-:deep(.verlays) {
-  width: 250px;
-  background: rgb(102, 102, 102);
-  border-radius: 4px;
-  border: 1px solid #ebeef5;
-  color: #fff;
-  padding: 15px 10px;
-  p {
-    line-height: 28px;
-    margin: 0;
-    padding: 0;
-  }
-  cursor: pointer;
-}
-</style>

+ 52 - 28
src/components/Process/approvalRecord.vue

@@ -2,39 +2,49 @@
   <div class="container">
     <el-dialog v-model="visible" draggable title="审批记录" :width="props.width" :height="props.height" :close-on-click-modal="false">
       <el-tabs v-model="tabActiveName" class="demo-tabs">
-        <el-tab-pane label="流程图" name="bpmn">
-          <BpmnView ref="bpmnViewRef"></BpmnView>
+        <el-tab-pane v-loading="loading" label="流程图" name="bpmn">
+          <img :src="imgUrl" width="100%" style="margin: 0 auto" />
         </el-tab-pane>
         <el-tab-pane v-loading="loading" label="审批信息" name="info">
           <div>
             <el-table :data="historyList" style="width: 100%" border fit>
               <el-table-column type="index" label="序号" align="center" width="60"></el-table-column>
-              <el-table-column prop="name" label="任务名称" sortable align="center"></el-table-column>
-              <el-table-column prop="nickName" :show-overflow-tooltip="true" label="办理人" sortable align="center">
+              <el-table-column prop="nodeName" label="任务名称" sortable align="center"></el-table-column>
+              <el-table-column prop="approveName" :show-overflow-tooltip="true" label="办理人" sortable align="center">
                 <template #default="scope">
-                  <el-tag type="success">{{ scope.row.nickName || '无' }}</el-tag>
+                  <template v-if="scope.row.approveName">
+                    <el-tag v-for="(item, index) in scope.row.approveName.split(',')" :key="index" type="success">{{ item }}</el-tag>
+                  </template>
+                  <template v-else> <el-tag type="success">无</el-tag></template>
                 </template>
               </el-table-column>
-              <el-table-column label="状态" sortable align="center">
+              <el-table-column prop="flowStatus" label="状态" width="80" sortable align="center">
                 <template #default="scope">
-                  <el-tag type="success">{{ scope.row.statusName }}</el-tag>
+                  <dict-tag :options="wf_task_status" :value="scope.row.flowStatus"></dict-tag>
                 </template>
               </el-table-column>
-              <el-table-column prop="comment" label="审批意见" sortable align="center"></el-table-column>
-              <el-table-column prop="startTime" label="开始时间" sortable align="center"></el-table-column>
-              <el-table-column prop="endTime" label="结束时间" sortable align="center"></el-table-column>
-              <el-table-column prop="runDuration" label="运行时长" sortable align="center"></el-table-column>
-              <el-table-column prop="attachmentList" label="附件" sortable align="center">
+              <el-table-column prop="message" label="审批意见" :show-overflow-tooltip="true" sortable align="center"></el-table-column>
+              <el-table-column prop="createTime" label="开始时间" width="160" :show-overflow-tooltip="true" sortable align="center"></el-table-column>
+              <el-table-column prop="updateTime" label="结束时间" width="160" :show-overflow-tooltip="true" sortable align="center"></el-table-column>
+              <el-table-column
+                prop="runDuration"
+                label="运行时常"
+                width="140"
+                :show-overflow-tooltip="true"
+                sortable
+                align="center"
+              ></el-table-column>
+              <el-table-column prop="attachmentList" width="120" label="附件" align="center">
                 <template #default="scope">
                   <el-popover v-if="scope.row.attachmentList && scope.row.attachmentList.length > 0" placement="right" :width="310" trigger="click">
                     <template #reference>
-                      <el-button style="margin-right: 16px">附件</el-button>
+                      <el-button type="primary" style="margin-right: 16px">附件</el-button>
                     </template>
                     <el-table border :data="scope.row.attachmentList">
-                      <el-table-column prop="name" width="202" :show-overflow-tooltip="true" label="附件名称"></el-table-column>
+                      <el-table-column prop="originalName" width="202" :show-overflow-tooltip="true" label="附件名称"></el-table-column>
                       <el-table-column prop="name" width="80" align="center" :show-overflow-tooltip="true" label="操作">
                         <template #default="tool">
-                          <el-button type="text" @click="handleDownload(tool.row.contentId)">下载</el-button>
+                          <el-button type="text" @click="handleDownload(tool.row.ossId)">下载</el-button>
                         </template>
                       </el-table-column>
                     </el-table>
@@ -49,37 +59,51 @@
   </div>
 </template>
 <script lang="ts" setup>
-import BpmnView from '@/components/BpmnView/index.vue';
-import processApi from '@/api/workflow/processInstance';
+import { flowImage } from '@/api/workflow/instance';
 import { propTypes } from '@/utils/propTypes';
+import { listByIds } from '@/api/system/oss';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
+const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status'));
 const props = defineProps({
-  width: propTypes.string.def('70%'),
+  width: propTypes.string.def('80%'),
   height: propTypes.string.def('100%')
 });
 const loading = ref(false);
 const visible = ref(false);
 const historyList = ref<Array<any>>([]);
 const tabActiveName = ref('bpmn');
-
-const bpmnViewRef = ref<BpmnView>();
+const imgUrl = ref('');
 
 //初始化查询审批记录
-const init = async (businessKey: string | number) => {
+const init = async (businessId: string | number) => {
   visible.value = true;
   loading.value = true;
   tabActiveName.value = 'bpmn';
   historyList.value = [];
-  processApi.getHistoryRecord(businessKey).then((resp) => {
-    historyList.value = resp.data;
-    loading.value = false;
-  });
-  await nextTick(() => {
-    bpmnViewRef.value.init(businessKey);
+  flowImage(businessId).then((resp) => {
+    if (resp.data) {
+      historyList.value = resp.data.list;
+      imgUrl.value = 'data:image/gif;base64,' + resp.data.image;
+      if (historyList.value.length > 0) {
+        historyList.value.forEach((item) => {
+          if (item.ext) {
+            getIds(item.ext).then((res) => {
+              item.attachmentList = res.data;
+            });
+          } else {
+            item.attachmentList = [];
+          }
+        });
+      }
+      loading.value = false;
+    }
   });
 };
+const getIds = async (ids: string | number) => {
+  const res = await listByIds(ids);
+  return res;
+};
 
 /** 下载按钮操作 */
 const handleDownload = (ossId: string) => {

+ 0 - 378
src/components/Process/multiInstanceUser.vue

@@ -1,378 +0,0 @@
-<template>
-  <el-dialog v-model="visible" draggable :title="title" :width="width" :height="height" append-to-body :close-on-click-modal="false">
-    <div v-if="multiInstance === 'add'" class="p-2">
-      <el-row :gutter="20">
-        <!-- 部门树 -->
-        <el-col :lg="4" :xs="24" style="">
-          <el-card shadow="hover">
-            <el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
-            <el-tree
-              ref="deptTreeRef"
-              class="mt-2"
-              node-key="id"
-              :data="deptOptions"
-              :props="{ label: 'label', children: 'children' }"
-              :expand-on-click-node="false"
-              :filter-node-method="filterNode"
-              highlight-current
-              default-expand-all
-              @node-click="handleNodeClick"
-            ></el-tree>
-          </el-card>
-        </el-col>
-        <el-col :lg="20" :xs="24">
-          <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-            <div v-show="showSearch" class="search">
-              <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-                <el-form-item label="用户名称" prop="userName">
-                  <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="手机号码" prop="phonenumber">
-                  <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item>
-                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-                </el-form-item>
-              </el-form>
-            </div>
-          </transition>
-
-          <el-card shadow="hover">
-            <template #header>
-              <el-row :gutter="10">
-                <right-toolbar v-model:show-search="showSearch" :search="true" @query-table="handleQuery"></right-toolbar>
-              </el-row>
-            </template>
-
-            <el-table ref="multipleTableRef" v-loading="loading" :data="userList" row-key="userId" @selection-change="handleSelectionChange">
-              <el-table-column type="selection" width="50" align="center" />
-              <el-table-column key="userId" label="用户编号" align="center" prop="userId" />
-              <el-table-column key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
-              <el-table-column key="nickName" label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" />
-              <el-table-column key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" />
-              <el-table-column label="创建时间" align="center" prop="createTime" width="160">
-                <template #default="scope">
-                  <span>{{ scope.row.createTime }}</span>
-                </template>
-              </el-table-column>
-            </el-table>
-
-            <pagination
-              v-show="total > 0"
-              v-model:page="queryParams.pageNum"
-              v-model:limit="queryParams.pageSize"
-              :total="total"
-              @pagination="handleQuery"
-            />
-          </el-card>
-          <el-card shadow="hover">
-            <el-tag v-for="(user, index) in chooseUserList" :key="user.userId" style="margin: 2px" closable @close="handleCloseTag(user, index)"
-              >{{ user.userName }}
-            </el-tag>
-          </el-card>
-        </el-col>
-      </el-row>
-    </div>
-    <div v-if="multiInstance === 'delete'" class="p-2">
-      <el-table v-loading="loading" :data="taskList" @selection-change="handleTaskSelection">
-        <el-table-column type="selection" width="55" />
-        <el-table-column prop="name" label="任务名称" />
-        <el-table-column prop="assigneeName" label="办理人" />
-      </el-table>
-    </div>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button type="primary" @click="submitFileForm">确 定</el-button>
-        <el-button @click="visible = false">取 消</el-button>
-      </div>
-    </template>
-  </el-dialog>
-</template>
-
-<script setup name="User" lang="ts">
-import { deptTreeSelect, listUser, optionSelect } from '@/api/system/user';
-import {
-  addMultiInstanceExecution,
-  deleteMultiInstanceExecution,
-  getTaskUserIdsByAddMultiInstance,
-  getListByDeleteMultiInstance
-} from '@/api/workflow/task';
-import { UserVO } from '@/api/system/user/types';
-import { DeptVO } from '@/api/system/dept/types';
-import { ComponentInternalInstance } from 'vue';
-import { ElTree, ElTable } from 'element-plus';
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const props = defineProps({
-  // 宽
-  width: {
-    type: String,
-    default: '70%'
-  },
-  // 高
-  height: {
-    type: String,
-    default: '100%'
-  },
-  // 标题
-  title: {
-    type: String,
-    default: '加签人员'
-  },
-  //是否多选
-  multiple: {
-    type: Boolean,
-    default: true
-  },
-  //回显用户id
-  userIdList: {
-    type: Array,
-    default: () => []
-  }
-});
-const deptTreeRef = ref(ElTree);
-const multipleTableRef = ref(ElTable);
-
-const userList = ref<UserVO[]>();
-const taskList = ref<Array<any>[]>();
-const loading = ref(true);
-const showSearch = ref(true);
-const selectionTask = ref<Array<any>[]>();
-const visible = ref(false);
-const total = ref(0);
-const deptName = ref('');
-const deptOptions = ref<DeptVO[]>([]);
-const chooseUserList = ref(ref<UserVO[]>());
-const userIds = ref<Array<number | string>>([]);
-//加签或者减签
-const multiInstance = ref('');
-const queryParams = ref<Record<string, any>>({
-  pageNum: 1,
-  pageSize: 10,
-  userName: '',
-  nickName: '',
-  taskId: ''
-});
-/** 查询用户列表 */
-const getAddMultiInstanceList = async (taskId: string, userIdList: Array<number | string>) => {
-  deptOptions.value = [];
-  getTreeSelect();
-  multiInstance.value = 'add';
-  userIds.value = userIdList;
-  visible.value = true;
-  queryParams.value.taskId = taskId;
-  loading.value = true;
-  const res1 = await getTaskUserIdsByAddMultiInstance(taskId);
-  queryParams.value.excludeUserIds = res1.data;
-  const res = await listUser(queryParams.value);
-  loading.value = false;
-  userList.value = res.rows;
-  total.value = res.total;
-  if (userList.value && userIds.value.length > 0) {
-    const data = await optionSelect(userIds.value);
-    if (data.data && data.data.length > 0) {
-      chooseUserList.value = data.data;
-      data.data.forEach((user: UserVO) => {
-        multipleTableRef.value!.toggleRowSelection(
-          userList.value.find((item) => {
-            return item.userId == user.userId;
-          }),
-          true
-        );
-      });
-    }
-  }
-};
-
-const getList = async () => {
-  loading.value = true;
-  const res1 = await getTaskUserIdsByAddMultiInstance(queryParams.value.taskId);
-  queryParams.value.excludeUserIds = res1.data;
-  const res = await listUser(queryParams.value);
-  loading.value = false;
-  userList.value = res.rows;
-  total.value = res.total;
-  if (userList.value && userIds.value.length > 0) {
-    const data = await optionSelect(userIds.value);
-    if (data.data && data.data.length > 0) {
-      chooseUserList.value = data.data;
-      data.data.forEach((user: UserVO) => {
-        multipleTableRef.value!.toggleRowSelection(
-          userList.value.find((item) => {
-            return item.userId == user.userId;
-          }),
-          true
-        );
-      });
-    }
-  }
-};
-
-const getDeleteMultiInstanceList = async (taskId: string) => {
-  deptOptions.value = [];
-  loading.value = true;
-  queryParams.value.taskId = taskId;
-  multiInstance.value = 'delete';
-  visible.value = true;
-  const res = await getListByDeleteMultiInstance(taskId);
-  taskList.value = res.data;
-  loading.value = false;
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getAddMultiInstanceList(queryParams.value.taskId, userIds.value);
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryParams.value.pageNum = 1;
-  queryParams.value.deptId = undefined;
-  queryParams.value.userName = undefined;
-  queryParams.value.nickName = undefined;
-  deptTreeRef.value.setCurrentKey(null);
-  handleQuery();
-};
-
-/** 选择条数  */
-const handleSelectionChange = (selection: UserVO[]) => {
-  if (props.multiple) {
-    chooseUserList.value = selection.filter((element, index, self) => {
-      return self.findIndex((x) => x.userId === element.userId) === index;
-    });
-    selection.forEach((u) => {
-      if (chooseUserList.value && !chooseUserList.value.includes(u)) {
-        multipleTableRef.value!.toggleRowSelection(u, undefined);
-      }
-    });
-    userIds.value = chooseUserList.value.map((item) => {
-      return item.userId;
-    });
-  } else {
-    chooseUserList.value = selection;
-    if (selection.length > 1) {
-      let delRow = selection.shift();
-      multipleTableRef.value!.toggleRowSelection(delRow, undefined);
-    }
-    if (selection.length === 0) {
-      chooseUserList.value = [];
-    }
-  }
-};
-/** 选择条数  */
-const handleTaskSelection = (selection: any) => {
-  selectionTask.value = selection;
-};
-
-/** 查询部门下拉树结构 */
-const getTreeSelect = async () => {
-  const res = await deptTreeSelect();
-  deptOptions.value = res.data;
-};
-
-/** 通过条件过滤节点  */
-const filterNode = (value: string, data: any) => {
-  if (!value) return true;
-  return data.label.indexOf(value) !== -1;
-};
-/** 根据名称筛选部门树 */
-watchEffect(
-  () => {
-    if (visible.value && deptOptions.value && deptOptions.value.length > 0) {
-      deptTreeRef.value.filter(deptName.value);
-    }
-  },
-  {
-    flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
-  }
-);
-/** 节点单击事件 */
-const handleNodeClick = (data: DeptVO) => {
-  queryParams.value.deptId = data.id;
-  getList();
-};
-//删除tag
-const handleCloseTag = (user: UserVO, index: any) => {
-  if (multipleTableRef.value.selection && multipleTableRef.value.selection.length > 0) {
-    multipleTableRef.value.selection.forEach((u: UserVO, i: number) => {
-      if (user.userId === u.userId) {
-        multipleTableRef.value.selection.splice(i, 1);
-      }
-    });
-  }
-  if (chooseUserList.value && chooseUserList.value.length > 0) {
-    chooseUserList.value.splice(index, 1);
-  }
-  multipleTableRef.value.toggleRowSelection(user, undefined);
-
-  if (userIds.value && userIds.value.length > 0) {
-    userIds.value.forEach((userId, i) => {
-      if (userId === user.userId) {
-        userIds.value.splice(i, 1);
-      }
-    });
-  }
-};
-const submitFileForm = async () => {
-  if (multiInstance.value === 'add') {
-    if (chooseUserList.value && chooseUserList.value.length > 0) {
-      loading.value = true;
-      let userIds = chooseUserList.value.map((item) => {
-        return item.userId;
-      });
-      let nickNames = chooseUserList.value.map((item) => {
-        return item.nickName;
-      });
-      let params = {
-        taskId: queryParams.value.taskId,
-        assignees: userIds,
-        assigneeNames: nickNames
-      };
-      await addMultiInstanceExecution(params);
-      emits('submitCallback');
-      loading.value = false;
-      proxy?.$modal.msgSuccess('操作成功');
-      visible.value = false;
-    }
-  } else {
-    if (selectionTask.value && selectionTask.value.length > 0) {
-      loading.value = true;
-      let taskIds = selectionTask.value.map((item: any) => {
-        return item.id;
-      });
-      let executionIds = selectionTask.value.map((item: any) => {
-        return item.executionId;
-      });
-      let assigneeIds = selectionTask.value.map((item: any) => {
-        return item.assignee;
-      });
-      let assigneeNames = selectionTask.value.map((item: any) => {
-        return item.assigneeName;
-      });
-      let params = {
-        taskId: queryParams.value.taskId,
-        taskIds: taskIds,
-        executionIds: executionIds,
-        assigneeIds: assigneeIds,
-        assigneeNames: assigneeNames
-      };
-      await deleteMultiInstanceExecution(params);
-      emits('submitCallback');
-      loading.value = false;
-      proxy?.$modal.msgSuccess('操作成功');
-      visible.value = false;
-    }
-  }
-};
-//事件
-const emits = defineEmits(['submitCallback']);
-
-/**
- * 对外暴露子组件方法
- */
-defineExpose({
-  getAddMultiInstanceList,
-  getDeleteMultiInstanceList
-});
-</script>

+ 207 - 0
src/components/Process/processMeddle.vue

@@ -0,0 +1,207 @@
+<template>
+  <el-dialog v-model="visible" draggable title="流程干预" :width="props.width" :height="props.height" :close-on-click-modal="false">
+    <el-descriptions v-loading="loading" class="margin-top" :title="`${task.flowName}(${task.flowCode})`" :column="2" border>
+      <el-descriptions-item label="任务名称">{{ task.nodeName }}</el-descriptions-item>
+      <el-descriptions-item label="节点编码">{{ task.nodeCode }}</el-descriptions-item>
+      <el-descriptions-item label="开始时间">{{ task.createTime }}</el-descriptions-item>
+      <el-descriptions-item label="流程实例ID">{{ task.instanceId }}</el-descriptions-item>
+      <el-descriptions-item label="版本号">{{ task.version }}.0</el-descriptions-item>
+      <el-descriptions-item label="业务ID">{{ task.businessId }}</el-descriptions-item>
+    </el-descriptions>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 转办 </el-button>
+        <el-button
+          v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
+          :disabled="buttonDisabled"
+          type="primary"
+          @click="openMultiInstanceUser"
+        >
+          加签
+        </el-button>
+        <el-button
+          v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
+          :disabled="buttonDisabled"
+          type="primary"
+          @click="handleTaskUser"
+        >
+          减签
+        </el-button>
+        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 终止 </el-button>
+      </span>
+    </template>
+    <!-- 转办 -->
+    <UserSelect ref="transferTaskRef" :multiple="false" @confirm-call-back="handleTransferTask"></UserSelect>
+    <!-- 加签组件 -->
+    <UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect>
+    <el-dialog v-model="deleteSignatureVisible" draggable title="减签人员" width="700px" height="400px" append-to-body :close-on-click-modal="false"
+      ><div>
+        <el-table :data="deleteUserList" border>
+          <el-table-column prop="nodeName" label="任务名称" />
+          <el-table-column prop="nickName" label="办理人" />
+          <el-table-column label="操作" align="center" width="160">
+            <template #default="scope">
+              <el-button type="danger" size="small" icon="Delete" @click="deleteMultiInstanceUser(scope.row)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </el-dialog>
+  </el-dialog>
+</template>
+<script lang="ts" setup>
+import { propTypes } from '@/utils/propTypes';
+import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types';
+import UserSelect from '@/components/UserSelect';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+import { getTask, taskOperation, currentTaskAllUser, terminationTask } from '@/api/workflow/task';
+const props = defineProps({
+  width: propTypes.string.def('50%'),
+  height: propTypes.string.def('100%')
+});
+const emits = defineEmits(['submitCallback']);
+const transferTaskRef = ref<InstanceType<typeof UserSelect>>();
+const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>();
+//遮罩层
+const loading = ref(true);
+//按钮
+const buttonDisabled = ref(true);
+const visible = ref(false);
+//减签弹窗
+const deleteSignatureVisible = ref(false);
+//可减签的人员
+const deleteUserList = ref<any>([]);
+//任务
+const task = ref<FlowTaskVO>({
+  id: undefined,
+  createTime: undefined,
+  updateTime: undefined,
+  tenantId: undefined,
+  definitionId: undefined,
+  instanceId: undefined,
+  flowName: undefined,
+  businessId: undefined,
+  nodeCode: undefined,
+  nodeName: undefined,
+  flowCode: undefined,
+  flowStatus: undefined,
+  nodeType: undefined,
+  nodeRatio: undefined,
+  version: undefined
+});
+
+const open = (taskId: string) => {
+  visible.value = true;
+  getTask(taskId).then((response) => {
+    loading.value = false;
+    buttonDisabled.value = false;
+    task.value = response.data;
+  });
+};
+
+//打开转办
+const openTransferTask = () => {
+  transferTaskRef.value.open();
+};
+//转办
+const handleTransferTask = async (data) => {
+  if (data && data.length > 0) {
+    const taskOperationBo = reactive<TaskOperationBo>({
+      userId: data[0].userId,
+      taskId: task.value.id,
+      message: ''
+    });
+    await proxy?.$modal.confirm('是否确认提交?');
+    loading.value = true;
+    buttonDisabled.value = true;
+    await taskOperation(taskOperationBo, 'transferTask').finally(() => {
+      loading.value = false;
+      buttonDisabled.value = false;
+    });
+    visible.value = false;
+    emits('submitCallback');
+    proxy?.$modal.msgSuccess('操作成功');
+  } else {
+    proxy?.$modal.msgWarning('请选择用户!');
+  }
+};
+//加签
+const openMultiInstanceUser = async () => {
+  multiInstanceUserRef.value.open();
+};
+//加签
+const addMultiInstanceUser = async (data) => {
+  if (data && data.length > 0) {
+    const taskOperationBo = reactive<TaskOperationBo>({
+      userIds: data.map((e) => e.userId),
+      taskId: task.value.id,
+      message: ''
+    });
+    await proxy?.$modal.confirm('是否确认提交?');
+    loading.value = true;
+    buttonDisabled.value = true;
+    await taskOperation(taskOperationBo, 'addSignature').finally(() => {
+      loading.value = false;
+      buttonDisabled.value = false;
+    });
+    visible.value = false;
+    emits('submitCallback');
+    proxy?.$modal.msgSuccess('操作成功');
+  } else {
+    proxy?.$modal.msgWarning('请选择用户!');
+  }
+};
+//减签
+const deleteMultiInstanceUser = async (row) => {
+  await proxy?.$modal.confirm('是否确认提交?');
+  loading.value = true;
+  buttonDisabled.value = true;
+  const taskOperationBo = reactive<TaskOperationBo>({
+    userIds: [row.userId],
+    taskId: task.value.id,
+    message: ''
+  });
+  await taskOperation(taskOperationBo, 'reductionSignature').finally(() => {
+    loading.value = false;
+    buttonDisabled.value = false;
+  });
+  visible.value = false;
+  emits('submitCallback');
+  proxy?.$modal.msgSuccess('操作成功');
+};
+//获取办理人
+const handleTaskUser = async () => {
+  let data = await currentTaskAllUser(task.value.id);
+  deleteUserList.value = data.data;
+  if (deleteUserList.value && deleteUserList.value.length > 0) {
+    deleteUserList.value.forEach((e) => {
+      e.nodeName = task.value.nodeName;
+    });
+  }
+  deleteSignatureVisible.value = true;
+};
+
+//终止任务
+const handleTerminationTask = async () => {
+  let params = {
+    taskId: task.value.id,
+    comment: ''
+  };
+  await proxy?.$modal.confirm('是否确认终止?');
+  loading.value = true;
+  buttonDisabled.value = true;
+  await terminationTask(params).finally(() => {
+    loading.value = false;
+    buttonDisabled.value = false;
+  });
+  visible.value = false;
+  emits('submitCallback');
+  proxy?.$modal.msgSuccess('操作成功');
+};
+/**
+ * 对外暴露子组件方法
+ */
+defineExpose({
+  open
+});
+</script>

+ 139 - 87
src/components/Process/submitVerify.vue

@@ -3,47 +3,47 @@
     <el-form v-loading="loading" :model="form" label-width="120px">
       <el-form-item label="消息提醒">
         <el-checkbox-group v-model="form.messageType">
-          <el-checkbox label="1" name="type" disabled>站内信</el-checkbox>
-          <el-checkbox label="2" name="type">邮件</el-checkbox>
-          <el-checkbox label="3" name="type">短信</el-checkbox>
+          <el-checkbox value="1" name="type" disabled>站内信</el-checkbox>
+          <el-checkbox value="2" name="type">邮件</el-checkbox>
+          <el-checkbox value="3" name="type">短信</el-checkbox>
         </el-checkbox-group>
       </el-form-item>
-      <el-form-item v-if="task.businessStatus === 'waiting'" label="附件">
-        <fileUpload v-model="form.fileId" :file-type="['doc', 'xls', 'ppt', 'txt', 'pdf', 'xlsx', 'docx', 'zip']" :file-size="'20'" />
+      <el-form-item v-if="task.flowStatus === 'waiting'" label="附件">
+        <fileUpload v-model="form.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" />
       </el-form-item>
       <el-form-item label="抄送">
         <el-button type="primary" icon="Plus" circle @click="openUserSelectCopy" />
         <el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
-          {{ user.userName }}
+          {{ user.nickName }}
         </el-tag>
       </el-form-item>
-      <el-form-item v-if="task.businessStatus === 'waiting'" label="审批意见">
+      <el-form-item v-if="task.flowStatus === 'waiting'" label="审批意见">
         <el-input v-model="form.message" type="textarea" resize="none" />
       </el-form-item>
     </el-form>
     <template #footer>
       <span class="dialog-footer">
         <el-button :disabled="buttonDisabled" type="primary" @click="handleCompleteTask"> 提交 </el-button>
-        <el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openDelegateTask"> 委托 </el-button>
-        <el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 转办 </el-button>
+        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openDelegateTask"> 委托 </el-button>
+        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 转办 </el-button>
         <el-button
-          v-if="task.businessStatus === 'waiting' && task.multiInstance"
+          v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
           :disabled="buttonDisabled"
           type="primary"
-          @click="addMultiInstanceUser"
+          @click="openMultiInstanceUser"
         >
           加签
         </el-button>
         <el-button
-          v-if="task.businessStatus === 'waiting' && task.multiInstance"
+          v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
           :disabled="buttonDisabled"
           type="primary"
-          @click="deleteMultiInstanceUser"
+          @click="handleTaskUser"
         >
           减签
         </el-button>
-        <el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 终止 </el-button>
-        <el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen"> 退回 </el-button>
+        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 终止 </el-button>
+        <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen"> 退回 </el-button>
         <el-button :disabled="buttonDisabled" @click="cancel">取消</el-button>
       </span>
     </template>
@@ -54,14 +54,14 @@
     <!-- 委托 -->
     <UserSelect ref="delegateTaskRef" :multiple="false" @confirm-call-back="handleDelegateTask"></UserSelect>
     <!-- 加签组件 -->
-    <multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback="closeDialog" />
+    <UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect>
 
     <!-- 驳回开始 -->
     <el-dialog v-model="backVisible" draggable title="驳回" width="40%" :close-on-click-modal="false">
-      <el-form v-if="task.businessStatus === 'waiting'" v-loading="backLoading" :model="backForm" label-width="120px">
+      <el-form v-if="task.flowStatus === 'waiting'" v-loading="backLoading" :model="backForm" label-width="120px">
         <el-form-item label="驳回节点">
-          <el-select v-model="backForm.targetActivityId" clearable placeholder="请选择" style="width: 300px">
-            <el-option v-for="item in taskNodeList" :key="item.nodeId" :label="item.nodeName" :value="item.nodeId" />
+          <el-select v-model="backForm.nodeCode" clearable placeholder="请选择" style="width: 300px">
+            <el-option v-for="item in taskNodeList" :key="item.nodeCode" :label="item.nodeName" :value="item.nodeCode" />
           </el-select>
         </el-form-item>
         <el-form-item label="消息提醒">
@@ -83,6 +83,19 @@
       </template>
     </el-dialog>
     <!-- 驳回结束 -->
+    <el-dialog v-model="deleteSignatureVisible" draggable title="减签人员" width="700px" height="400px" append-to-body :close-on-click-modal="false">
+      <div>
+        <el-table :data="deleteUserList" border>
+          <el-table-column prop="nodeName" label="任务名称" />
+          <el-table-column prop="nickName" label="办理人" />
+          <el-table-column label="操作" align="center" width="160">
+            <template #default="scope">
+              <el-button type="danger" size="small" icon="Delete" @click="deleteMultiInstanceUser(scope.row)">删除 </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </el-dialog>
   </el-dialog>
 </template>
 
@@ -90,18 +103,17 @@
 import { ref } from 'vue';
 import { ComponentInternalInstance } from 'vue';
 import { ElForm } from 'element-plus';
-import { completeTask, backProcess, getTaskById, transferTask, terminationTask, getTaskNodeList, delegateTask } from '@/api/workflow/task';
+import { completeTask, backProcess, getTask, taskOperation, terminationTask, getBackTaskNode, currentTaskAllUser } from '@/api/workflow/task';
 import UserSelect from '@/components/UserSelect';
-import MultiInstanceUser from '@/components/Process/multiInstanceUser.vue';
+
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 import { UserVO } from '@/api/system/user/types';
-import { TaskVO } from '@/api/workflow/task/types';
+import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types';
+
 const userSelectCopyRef = ref<InstanceType<typeof UserSelect>>();
 const transferTaskRef = ref<InstanceType<typeof UserSelect>>();
 const delegateTaskRef = ref<InstanceType<typeof UserSelect>>();
-
-//加签组件
-const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>();
+const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>();
 
 const props = defineProps({
   taskVariables: {
@@ -119,65 +131,53 @@ const taskId = ref<string>('');
 const selectCopyUserList = ref<UserVO[]>([]);
 //抄送人id
 const selectCopyUserIds = ref<string>(undefined);
-// 驳回是否显示
+//可减签的人员
+const deleteUserList = ref<any>([]);
+//驳回是否显示
 const backVisible = ref(false);
 const backLoading = ref(true);
 const backButtonDisabled = ref(true);
 // 可驳回得任务节点
 const taskNodeList = ref([]);
 //任务
-const task = ref<TaskVO>({
+const task = ref<FlowTaskVO>({
   id: undefined,
-  name: undefined,
-  description: undefined,
-  priority: undefined,
-  owner: undefined,
-  assignee: undefined,
-  assigneeName: undefined,
-  processInstanceId: undefined,
-  executionId: undefined,
-  taskDefinitionId: undefined,
-  processDefinitionId: undefined,
-  endTime: undefined,
-  taskDefinitionKey: undefined,
-  dueDate: undefined,
-  category: undefined,
-  parentTaskId: undefined,
+  createTime: undefined,
+  updateTime: undefined,
   tenantId: undefined,
-  claimTime: undefined,
-  businessStatus: undefined,
-  businessStatusName: undefined,
-  processDefinitionName: undefined,
-  processDefinitionKey: undefined,
-  participantVo: undefined,
-  multiInstance: undefined,
-  businessKey: undefined,
-  wfNodeConfigVo: undefined
+  definitionId: undefined,
+  instanceId: undefined,
+  flowName: undefined,
+  businessId: undefined,
+  nodeCode: undefined,
+  nodeName: undefined,
+  flowCode: undefined,
+  flowStatus: undefined,
+  formCustom: undefined,
+  formPath: undefined,
+  nodeType: undefined,
+  nodeRatio: undefined
 });
-//加签 减签标题
-const title = ref('');
 const dialog = reactive<DialogOption>({
   visible: false,
   title: '提示'
 });
-
+//减签弹窗
+const deleteSignatureVisible = ref(false);
 const form = ref<Record<string, any>>({
   taskId: undefined,
   message: undefined,
   variables: {},
   messageType: ['1'],
-  wfCopyList: []
+  flowCopyList: []
 });
 const backForm = ref<Record<string, any>>({
   taskId: undefined,
-  targetActivityId: undefined,
+  nodeCode: undefined,
   message: undefined,
   variables: {},
   messageType: ['1']
 });
-const closeDialog = () => {
-  dialog.visible = false;
-};
 //打开弹窗
 const openDialog = (id?: string) => {
   selectCopyUserIds.value = undefined;
@@ -189,7 +189,7 @@ const openDialog = (id?: string) => {
   loading.value = true;
   buttonDisabled.value = true;
   nextTick(() => {
-    getTaskById(taskId.value).then((response) => {
+    getTask(taskId.value).then((response) => {
       task.value = response.data;
       loading.value = false;
       buttonDisabled.value = false;
@@ -205,15 +205,15 @@ const handleCompleteTask = async () => {
   form.value.taskId = taskId.value;
   form.value.taskVariables = props.taskVariables;
   if (selectCopyUserList.value && selectCopyUserList.value.length > 0) {
-    let wfCopyList = [];
+    let flowCopyList = [];
     selectCopyUserList.value.forEach((e) => {
       let copyUser = {
         userId: e.userId,
         userName: e.nickName
       };
-      wfCopyList.push(copyUser);
+      flowCopyList.push(copyUser);
     });
-    form.value.wfCopyList = wfCopyList;
+    form.value.flowCopyList = flowCopyList;
   }
   await proxy?.$modal.confirm('是否确认提交?');
   loading.value = true;
@@ -236,11 +236,11 @@ const handleBackProcessOpen = async () => {
   backVisible.value = true;
   backLoading.value = true;
   backButtonDisabled.value = true;
-  let data = await getTaskNodeList(task.value.processInstanceId);
+  let data = await getBackTaskNode(task.value.definitionId, task.value.nodeCode);
   taskNodeList.value = data.data;
   backLoading.value = false;
   backButtonDisabled.value = false;
-  backForm.value.targetActivityId = taskNodeList.value[0].nodeId;
+  backForm.value.nodeCode = taskNodeList.value[0].nodeCode;
 };
 /** 驳回流程 */
 const handleBackProcess = async () => {
@@ -249,7 +249,10 @@ const handleBackProcess = async () => {
   loading.value = true;
   backLoading.value = true;
   backButtonDisabled.value = true;
-  await backProcess(backForm.value).finally(() => (loading.value = false));
+  await backProcess(backForm.value).finally(() => {
+    loading.value = false;
+    buttonDisabled.value = false;
+  });
   dialog.visible = false;
   backLoading.value = false;
   backButtonDisabled.value = false;
@@ -282,18 +285,48 @@ const handleCopyCloseTag = (user: UserVO) => {
   selectCopyUserIds.value = selectCopyUserList.value.map((item) => item.userId).join(',');
 };
 //加签
-const addMultiInstanceUser = () => {
-  if (multiInstanceUserRef.value) {
-    title.value = '加签人员';
-    multiInstanceUserRef.value.getAddMultiInstanceList(taskId.value, []);
+const openMultiInstanceUser = async () => {
+  multiInstanceUserRef.value.open();
+};
+//加签
+const addMultiInstanceUser = async (data) => {
+  if (data && data.length > 0) {
+    const taskOperationBo = reactive<TaskOperationBo>({
+      userIds: data.map((e) => e.userId),
+      taskId: taskId.value,
+      message: form.value.message
+    });
+    await proxy?.$modal.confirm('是否确认提交?');
+    loading.value = true;
+    buttonDisabled.value = true;
+    await taskOperation(taskOperationBo, 'addSignature').finally(() => {
+      loading.value = false;
+      buttonDisabled.value = false;
+    });
+    dialog.visible = false;
+    emits('submitCallback');
+    proxy?.$modal.msgSuccess('操作成功');
+  } else {
+    proxy?.$modal.msgWarning('请选择用户!');
   }
 };
 //减签
-const deleteMultiInstanceUser = () => {
-  if (multiInstanceUserRef.value) {
-    title.value = '减签人员';
-    multiInstanceUserRef.value.getDeleteMultiInstanceList(taskId.value);
-  }
+const deleteMultiInstanceUser = async (row) => {
+  await proxy?.$modal.confirm('是否确认提交?');
+  loading.value = true;
+  buttonDisabled.value = true;
+  const taskOperationBo = reactive<TaskOperationBo>({
+    userIds: [row.userId],
+    taskId: taskId.value,
+    message: form.value.message
+  });
+  await taskOperation(taskOperationBo, 'reductionSignature').finally(() => {
+    loading.value = false;
+    buttonDisabled.value = false;
+  });
+  dialog.visible = false;
+  emits('submitCallback');
+  proxy?.$modal.msgSuccess('操作成功');
 };
 //打开转办
 const openTransferTask = () => {
@@ -302,15 +335,18 @@ const openTransferTask = () => {
 //转办
 const handleTransferTask = async (data) => {
   if (data && data.length > 0) {
-    let params = {
-      taskId: taskId.value,
+    const taskOperationBo = reactive<TaskOperationBo>({
       userId: data[0].userId,
-      comment: form.value.message
-    };
+      taskId: taskId.value,
+      message: form.value.message
+    });
     await proxy?.$modal.confirm('是否确认提交?');
     loading.value = true;
     buttonDisabled.value = true;
-    await transferTask(params).finally(() => (loading.value = false));
+    await taskOperation(taskOperationBo, 'transferTask').finally(() => {
+      loading.value = false;
+      buttonDisabled.value = false;
+    });
     dialog.visible = false;
     emits('submitCallback');
     proxy?.$modal.msgSuccess('操作成功');
@@ -326,15 +362,18 @@ const openDelegateTask = () => {
 //委托
 const handleDelegateTask = async (data) => {
   if (data && data.length > 0) {
-    let params = {
-      taskId: taskId.value,
+    const taskOperationBo = reactive<TaskOperationBo>({
       userId: data[0].userId,
-      nickName: data[0].nickName
-    };
+      taskId: taskId.value,
+      message: form.value.message
+    });
     await proxy?.$modal.confirm('是否确认提交?');
     loading.value = true;
     buttonDisabled.value = true;
-    await delegateTask(params).finally(() => (loading.value = false));
+    await taskOperation(taskOperationBo, 'delegateTask').finally(() => {
+      loading.value = false;
+      buttonDisabled.value = false;
+    });
     dialog.visible = false;
     emits('submitCallback');
     proxy?.$modal.msgSuccess('操作成功');
@@ -343,7 +382,7 @@ const handleDelegateTask = async (data) => {
   }
 };
 //终止任务
-const handleTerminationTask = async (data) => {
+const handleTerminationTask = async () => {
   let params = {
     taskId: taskId.value,
     comment: form.value.message
@@ -351,11 +390,24 @@ const handleTerminationTask = async (data) => {
   await proxy?.$modal.confirm('是否确认终止?');
   loading.value = true;
   buttonDisabled.value = true;
-  await terminationTask(params).finally(() => (loading.value = false));
+  await terminationTask(params).finally(() => {
+    loading.value = false;
+    buttonDisabled.value = false;
+  });
   dialog.visible = false;
   emits('submitCallback');
   proxy?.$modal.msgSuccess('操作成功');
 };
+const handleTaskUser = async () => {
+  let data = await currentTaskAllUser(taskId.value);
+  deleteUserList.value = data.data;
+  if (deleteUserList.value && deleteUserList.value.length > 0) {
+    deleteUserList.value.forEach((e) => {
+      e.nodeName = task.value.nodeName;
+    });
+  }
+  deleteSignatureVisible.value = true;
+};
 
 /**
  * 对外暴露子组件方法

+ 4 - 4
src/components/UserSelect/index.vue

@@ -43,7 +43,7 @@
           <el-card shadow="hover">
             <template v-if="prop.multiple" #header>
               <el-tag v-for="user in selectUserList" :key="user.userId" closable style="margin: 2px" @close="handleCloseTag(user)">
-                {{ user.userName }}
+                {{ user.nickName }}
               </el-tag>
             </template>
 
@@ -100,14 +100,14 @@
 <script setup lang="ts">
 import api from '@/api/system/user';
 import { UserQuery, UserVO } from '@/api/system/user/types';
-import { DeptVO } from '@/api/system/dept/types';
+import { DeptTreeVO, DeptVO } from '@/api/system/dept/types';
 import { VxeTableInstance } from 'vxe-table';
 import useDialog from '@/hooks/useDialog';
 
 interface PropType {
   modelValue?: UserVO[] | UserVO | undefined;
   multiple?: boolean;
-  data?: string | number | (string | number)[];
+  data?: string | number | (string | number)[] | undefined;
 }
 const prop = withDefaults(defineProps<PropType>(), {
   multiple: true,
@@ -125,7 +125,7 @@ const showSearch = ref(true);
 const total = ref(0);
 const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
 const deptName = ref('');
-const deptOptions = ref<DeptVO[]>([]);
+const deptOptions = ref<DeptTreeVO[]>([]);
 const selectUserList = ref<UserVO[]>([]);
 
 const deptTreeRef = ref<ElTreeInstance>();

+ 0 - 17
src/enums/bpmn/IndexEnums.ts

@@ -1,17 +0,0 @@
-export enum AllocationTypeEnum {
-  USER = 'user',
-  CANDIDATE = 'candidate',
-  YOURSELF = 'yourself',
-  SPECIFY = 'specify'
-}
-
-export enum SpecifyDescEnum {
-  SPECIFY_MULTIPLE = 'specifyMultiple',
-  SPECIFY_SINGLE = 'specifySingle'
-}
-
-export enum MultiInstanceTypeEnum {
-  SERIAL = 'serial',
-  PARALLEL = 'parallel',
-  NONE = 'none'
-}

+ 14 - 0
src/router/index.ts

@@ -176,6 +176,20 @@ export const dynamicRoutes: RouteRecordRaw[] = [
         meta: { title: '请假申请', activeMenu: '/workflow/leave', noCache: true }
       }
     ]
+  },
+  {
+    path: '/workflow/design',
+    component: Layout,
+    hidden: true,
+    permissions: ['workflow:leave:edit'],
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/workflow/processDefinition/design.vue'),
+        name: 'design',
+        meta: { title: '流程设计', activeMenu: '/workflow/processDefinition', noCache: true }
+      }
+    ]
   }
 ];
 

+ 0 - 76
src/store/modules/modeler.ts

@@ -1,76 +0,0 @@
-import type { Modeler, Modeling, Canvas, ElementRegistry, Moddle, BpmnFactory } from 'bpmn';
-
-type ModelerStore = {
-  modeler: Modeler | undefined;
-  moddle: Moddle | undefined;
-  modeling: Modeling | undefined;
-  canvas: Canvas | undefined;
-  elementRegistry: ElementRegistry | undefined;
-  bpmnFactory: BpmnFactory | undefined;
-  // 流程定义根节点信息
-  procDefId: string | undefined;
-  procDefName: string | undefined;
-};
-
-const defaultState: ModelerStore = {
-  modeler: undefined,
-  moddle: undefined,
-  modeling: undefined,
-  canvas: undefined,
-  elementRegistry: undefined,
-  bpmnFactory: undefined,
-  procDefId: undefined,
-  procDefName: undefined
-};
-export const useModelerStore = defineStore('modeler', () => {
-  let modeler = defaultState.modeler;
-  let moddle = defaultState.moddle;
-  let modeling = defaultState.modeling;
-  let canvas = defaultState.canvas;
-  let elementRegistry = defaultState.elementRegistry;
-  let bpmnFactory = defaultState.bpmnFactory;
-  const procDefId = ref(defaultState.procDefId);
-  const procDefName = ref(defaultState.procDefName);
-
-  const getModeler = () => modeler;
-  const getModdle = () => moddle;
-  const getModeling = (): Modeling | undefined => modeling;
-  const getCanvas = (): Canvas | undefined => canvas;
-  const getElRegistry = (): ElementRegistry | undefined => elementRegistry;
-  const getBpmnFactory = (): BpmnFactory | undefined => bpmnFactory;
-  const getProcDefId = (): string | undefined => procDefId.value;
-  const getProcDefName = (): string | undefined => procDefName.value;
-
-  // 设置根节点
-  const setModeler = (modelers: Modeler | undefined) => {
-    if (modelers) {
-      modeler = modelers;
-      modeling = modelers.get<Modeling>('modeling');
-      moddle = modelers.get<Moddle>('moddle');
-      canvas = modelers.get<Canvas>('canvas');
-      bpmnFactory = modelers.get<BpmnFactory>('bpmnFactory');
-      elementRegistry = modelers.get<ElementRegistry>('elementRegistry');
-    } else {
-      modeling = moddle = canvas = elementRegistry = bpmnFactory = undefined;
-    }
-  };
-  // 设置流程定义根节点信息
-  const setProcDef = (modeler: Modeler | undefined) => {
-    procDefId.value = modeler.get<Canvas>('canvas').getRootElement().businessObject.get('id');
-    procDefName.value = modeler.get<Canvas>('canvas').getRootElement().businessObject.get('name');
-  };
-
-  return {
-    getModeler,
-    getModdle,
-    getModeling,
-    getCanvas,
-    getElRegistry,
-    getBpmnFactory,
-    getProcDefId,
-    getProcDefName,
-    setModeler,
-    setProcDef
-  };
-});
-export default useModelerStore;

+ 0 - 13
src/types/bpmn/editor/global.d.ts

@@ -1,13 +0,0 @@
-import { MessageApiInjection } from 'naive-ui/lib/message/src/MessageProvider';
-
-declare global {
-  interface Window {
-    bpmnInstances: any;
-    __messageBox: MessageApiInjection;
-    URL: any;
-  }
-}
-
-declare interface Window {
-  bpmnInstances: any;
-}

+ 0 - 15
src/types/bpmn/index.d.ts

@@ -1,15 +0,0 @@
-declare module 'bpmn' {
-  import type modeler from 'bpmn-js/lib/Modeler';
-  import type modeling from 'bpmn-js/lib/features/modeling/Modeling';
-  import type canvas from 'diagram-js/lib/core/Canvas';
-  import type elementRegistry from 'diagram-js/lib/core/ElementRegistry';
-  import type bpmnFactory from 'bpmn-js/lib/features/modeling/BpmnFactory';
-
-  export type Modeler = modeler;
-  export type Modeling = modeling;
-  export type Canvas = canvas;
-  export type ElementRegistry = elementRegistry;
-  export type Moddle = import('moddle').Moddle;
-  export type ModdleElement = import('moddle').ModdleElement;
-  export type BpmnFactory = bpmnFactory;
-}

+ 0 - 37
src/types/bpmn/moddle.d.ts

@@ -1,37 +0,0 @@
-declare module 'moddle' {
-  import type { Element as element } from 'bpmn-js/lib/model/Types';
-
-  export type Element = {
-    get<T>(name: string): T;
-
-    set(name: string, value: any): void;
-  } & element;
-
-  export interface ModdleElement extends Element {
-    $model: Moddle;
-    readonly $type: string;
-    $attrs: object | {};
-    $parent: any;
-    businessObject: ModdleElement;
-    type: string;
-
-    [field: string]: any;
-
-    hasType(element: ModdleElement, type?: string): boolean;
-  }
-
-  export interface Package {
-    name: string;
-    prefix: string;
-  }
-
-  export interface Moddle {
-    typeCache: Record<string, ModdleElement>;
-
-    getPackage: typeof Registry.prototype.getPackage;
-
-    getPackages: typeof Registry.prototype.getPackages;
-
-    create(type: string, attrs?: any): ModdleElement;
-  }
-}

+ 0 - 92
src/types/bpmn/panel.d.ts

@@ -1,92 +0,0 @@
-declare module 'bpmnDesign' {
-  import { AllocationTypeEnum, SpecifyDescEnum, MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums';
-
-  export interface ParamVO {
-    type: string;
-    name: string;
-    value: string;
-  }
-
-  export interface TaskListenerVO {
-    event: string;
-    type: string;
-    name: string;
-    className: string;
-    params: ParamVO[];
-  }
-
-  export interface ExecutionListenerVO {
-    event: string;
-    type: string;
-    className: string;
-    params: ParamVO[];
-  }
-
-  interface BasePanel {
-    id: string;
-    name: string;
-  }
-  export interface ProcessPanel extends BasePanel {}
-
-  export interface TaskPanel extends BasePanel {
-    allocationType: AllocationTypeEnum;
-    specifyDesc: SpecifyDescEnum;
-    multiInstanceType: MultiInstanceTypeEnum;
-    async?: boolean;
-    priority?: number;
-    formKey?: string;
-    skipExpression?: string;
-    isForCompensation?: boolean;
-    triggerServiceTask?: boolean;
-    autoStoreVariables?: boolean;
-    ruleVariablesInput?: string;
-    excludeTaskListener?: boolean;
-    exclude?: boolean;
-    class?: string;
-    dueDate?: string;
-    fixedAssignee?: string;
-
-    candidateUsers?: string;
-    assignee?: string;
-    candidateGroups?: string;
-    collection?: string;
-    elementVariable?: string;
-    completionCondition?: string;
-    isSequential?: boolean;
-
-    loopCharacteristics?: {
-      collection: string;
-      elementVariable: string;
-      isSequential: boolean;
-      completionCondition: {
-        body: string;
-      };
-    };
-  }
-
-  export interface StartEndPanel extends BasePanel {}
-  export interface GatewayPanel extends BasePanel {}
-  export interface SequenceFlowPanel extends BasePanel {
-    conditionExpression: {
-      body: string;
-    };
-    conditionExpressionValue: string;
-    skipExpression: string;
-  }
-
-  export interface ParticipantPanel extends BasePanel {}
-  export interface SubProcessPanel extends BasePanel {
-    multiInstanceType: MultiInstanceTypeEnum;
-    collection?: string;
-    elementVariable?: string;
-    completionCondition?: string;
-    loopCharacteristics?: {
-      collection: string;
-      elementVariable: string;
-      isSequential: boolean;
-      completionCondition: {
-        body: string;
-      };
-    };
-  }
-}

+ 94 - 100
src/views/workflow/category/index.vue

@@ -6,9 +6,6 @@
           <el-form-item label="分类名称" prop="categoryName">
             <el-input v-model="queryParams.categoryName" placeholder="请输入分类名称" clearable @keyup.enter="handleQuery" />
           </el-form-item>
-          <el-form-item label="分类编码" prop="categoryCode">
-            <el-input v-model="queryParams.categoryCode" placeholder="请输入分类编码" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
           <el-form-item>
             <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
             <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -21,64 +18,66 @@
       <template #header>
         <el-row :gutter="10" class="mb8">
           <el-col :span="1.5">
-            <el-button v-hasPermi="['workflow:category:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
+            <el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['workflow:category:add']">新增</el-button>
           </el-col>
           <el-col :span="1.5">
             <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
           </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
+          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
         </el-row>
       </template>
       <el-table
         ref="categoryTableRef"
         v-loading="loading"
         :data="categoryList"
-        row-key="id"
+        row-key="categoryId"
         :default-expand-all="isExpandAll"
         :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
       >
-        <el-table-column label="分类名称" prop="categoryName" />
-        <el-table-column label="分类编码" align="center" prop="categoryCode" />
-        <el-table-column label="排序" align="center" prop="sortNum" />
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <el-table-column label="分类名称" prop="categoryName" width="260"/>
+        <el-table-column label="显示顺序" align="center" prop="orderNum" width="200" />
+        <el-table-column label="创建时间" align="center" prop="createTime" width="180" />
+        <el-table-column label="操作" fixed="right" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
             <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['workflow:category:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
+              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['workflow:category:edit']" />
             </el-tooltip>
             <el-tooltip content="新增" placement="top">
-              <el-button v-hasPermi="['workflow:category:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" />
+              <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['workflow:category:add']" />
             </el-tooltip>
             <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['workflow:category:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" />
+              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['workflow:category:remove']" />
             </el-tooltip>
           </template>
         </el-table-column>
       </el-table>
     </el-card>
-    <!-- 添加或修改流程分类对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="categoryFormRef" v-loading="loading" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="父级分类" prop="parentId">
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
+      <el-form ref="categoryFormRef" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="上级分类" prop="parentId">
           <el-tree-select
             v-model="form.parentId"
             :data="categoryOptions"
-            :props="{ value: 'id', label: 'categoryName', children: 'children' }"
-            value-key="id"
-            placeholder="请选择父级id"
+            :props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
+            value-key="categoryId"
+            placeholder="请选择上级分类"
             check-strictly
           />
         </el-form-item>
-        <el-form-item label="分类名称" prop="categoryName">
-          <el-input v-model="form.categoryName" placeholder="请输入分类名称" />
-        </el-form-item>
-        <el-form-item label="分类编码" prop="categoryCode">
-          <el-input v-model="form.categoryCode" placeholder="请输入分类编码" />
-        </el-form-item>
-        <el-form-item label="排序" prop="sortNum">
-          <el-input-number v-model="form.sortNum" placeholder="请输入排序" controls-position="right" :min="0" />
-        </el-form-item>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="分类名称" prop="categoryName">
+              <el-input v-model="form.categoryName" placeholder="请输入分类名称" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="排序" prop="orderNum">
+              <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
+            </el-form-item>
+          </el-col>
+        </el-row>
       </el-form>
-      <template #footer>
+    <template #footer>
         <div class="dialog-footer">
           <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
           <el-button @click="cancel">取 消</el-button>
@@ -89,16 +88,17 @@
 </template>
 
 <script setup name="Category" lang="ts">
-import { listCategory, getCategory, delCategory, addCategory, updateCategory } from '@/api/workflow/category';
+import { listCategory, getCategory, delCategory, addCategory, updateCategory } from "@/api/workflow/category";
 import { CategoryVO, CategoryQuery, CategoryForm } from '@/api/workflow/category/types';
 
 type CategoryOption = {
-  id: number;
+  categoryId: number;
   categoryName: string;
   children?: CategoryOption[];
-};
+}
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;;
 
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
 const categoryList = ref<CategoryVO[]>([]);
 const categoryOptions = ref<CategoryOption[]>([]);
@@ -109,34 +109,32 @@ const loading = ref(false);
 
 const queryFormRef = ref<ElFormInstance>();
 const categoryFormRef = ref<ElFormInstance>();
-const categoryTableRef = ref<ElTableInstance>();
+const categoryTableRef = ref<ElTableInstance>()
 
 const dialog = reactive<DialogOption>({
   visible: false,
   title: ''
 });
 
+
 const initFormData: CategoryForm = {
-  id: undefined,
-  categoryName: undefined,
-  categoryCode: undefined,
+  categoryId: undefined,
+  categoryName: "",
   parentId: undefined,
-  sortNum: 0
-};
+  orderNum: 0,
+}
 
 const data = reactive<PageData<CategoryForm, CategoryQuery>>({
-  form: { ...initFormData },
+  form: {...initFormData},
   queryParams: {
-    pageNum: 1,
-    pageSize: 10,
     categoryName: undefined,
-    categoryCode: undefined
   },
   rules: {
-    id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
-    categoryName: [{ required: true, message: '分类名称不能为空', trigger: 'blur' }],
-    categoryCode: [{ required: true, message: '分类编码不能为空', trigger: 'blur' }],
-    parentId: [{ required: true, message: '父级id不能为空', trigger: 'blur' }]
+    categoryId: [
+      { required: true, message: "流程分类ID不能为空", trigger: "blur" }
+    ],
+    parentId: [{ required: true, message: "请选择上级分类", trigger: "change" }],
+    categoryName: [{ required: true, message: "请输入分类名称", trigger: "blur" }]
   }
 });
 
@@ -146,116 +144,112 @@ const { queryParams, form, rules } = toRefs(data);
 const getList = async () => {
   loading.value = true;
   const res = await listCategory(queryParams.value);
-  const data = proxy?.handleTree<CategoryVO>(res.data, 'id', 'parentId');
+  const data = proxy?.handleTree<CategoryVO>(res.data, "categoryId", "parentId");
   if (data) {
     categoryList.value = data;
     loading.value = false;
   }
-};
+}
 
 /** 查询流程分类下拉树结构 */
 const getTreeselect = async () => {
   const res = await listCategory();
   categoryOptions.value = [];
-  const data: CategoryOption = { id: 0, categoryName: '顶级节点', children: [] };
-  data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId');
-  categoryOptions.value.push(data);
+  // 处理树形数据
+  const data = proxy?.handleTree<CategoryOption>(res.data, "categoryId", "parentId");
+  if (data) {
+    categoryOptions.value = data; // 将处理后的树形数据赋值
+  }
 };
 
 // 取消按钮
 const cancel = () => {
   reset();
   dialog.visible = false;
-};
+}
 
 // 表单重置
 const reset = () => {
-  form.value = { ...initFormData };
+  form.value = {...initFormData}
   categoryFormRef.value?.resetFields();
-};
+}
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
   getList();
-};
+}
 
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
   handleQuery();
-};
+}
 
 /** 新增按钮操作 */
 const handleAdd = (row?: CategoryVO) => {
+  reset();
+  getTreeselect();
+  if (row?.categoryId) {
+    form.value.parentId = row.categoryId;
+  } else {
+    form.value.parentId = undefined;
+  }
   dialog.visible = true;
-  dialog.title = '添加流程分类';
-  nextTick(() => {
-    reset();
-    getTreeselect();
-    if (row != null && row.id) {
-      form.value.parentId = row.id;
-    } else {
-      form.value.parentId = 0;
-    }
-  });
-};
+  dialog.title = "添加流程分类";
+}
 
 /** 展开/折叠操作 */
 const handleToggleExpandAll = () => {
   isExpandAll.value = !isExpandAll.value;
-  toggleExpandAll(categoryList.value, isExpandAll.value);
-};
+  toggleExpandAll(categoryList.value, isExpandAll.value)
+}
 
 /** 展开/折叠操作 */
 const toggleExpandAll = (data: CategoryVO[], status: boolean) => {
   data.forEach((item) => {
-    categoryTableRef.value?.toggleRowExpansion(item, status);
-    if (item.children && item.children.length > 0) toggleExpandAll(item.children, status);
-  });
-};
+    categoryTableRef.value?.toggleRowExpansion(item, status)
+    if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
+  })
+}
 
 /** 修改按钮操作 */
-const handleUpdate = (row: CategoryVO) => {
-  loading.value = true;
+const handleUpdate = async (row: CategoryVO) => {
+  reset();
+  await getTreeselect();
+  if (row != null) {
+    form.value.parentId = row.parentId;
+  }
+  const res = await getCategory(row.categoryId);
+  Object.assign(form.value, res.data);
   dialog.visible = true;
-  dialog.title = '修改流程分类';
-  nextTick(async () => {
-    reset();
-    await getTreeselect();
-    if (row != null) {
-      form.value.parentId = row.id;
-    }
-    const res = await getCategory(row.id);
-    loading.value = false;
-    Object.assign(form.value, res.data);
-  });
-};
+  dialog.title = "修改流程分类";
+}
 
 /** 提交按钮 */
 const submitForm = () => {
-  categoryFormRef.value.validate(async (valid: boolean) => {
+  categoryFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
       buttonLoading.value = true;
-      if (form.value.id) {
-        await updateCategory(form.value).finally(() => (buttonLoading.value = false));
+      if (form.value.categoryId) {
+        await updateCategory(form.value).finally(() => buttonLoading.value = false);
       } else {
-        await addCategory(form.value).finally(() => (buttonLoading.value = false));
+        await addCategory(form.value).finally(() => buttonLoading.value = false);
       }
-      proxy?.$modal.msgSuccess('操作成功');
+      proxy?.$modal.msgSuccess("操作成功");
       dialog.visible = false;
-      await getList();
+      getList();
     }
   });
-};
+}
 
 /** 删除按钮操作 */
 const handleDelete = async (row: CategoryVO) => {
-  await proxy?.$modal.confirm('是否确认删除流程分类编号为"' + row.id + '"的数据项?');
+  await proxy?.$modal.confirm('是否确认删除"' + row.categoryName + '"的分类?');
   loading.value = true;
-  await delCategory(row.id).finally(() => (loading.value = false));
+  await delCategory(row.categoryId).finally(() => loading.value = false);
   await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
+  proxy?.$modal.msgSuccess("删除成功");
+}
 
 onMounted(() => {
   getList();

+ 0 - 243
src/views/workflow/formManage/index.vue

@@ -1,243 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="search">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-          <el-form-item label="表单名称" prop="formName">
-            <el-input v-model="queryParams.formName" placeholder="请输入表单名称" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-    </transition>
-
-    <el-card shadow="never">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['workflow:formManage:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['workflow:formManage:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
-              >修改</el-button
-            >
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['workflow:formManage:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
-              >删除</el-button
-            >
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['workflow:formManage:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" :data="formManageList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="表单名称" align="center" prop="formName" />
-        <el-table-column label="表单类型" align="center">
-          <template #default="scope">
-            <dict-tag :options="wf_form_type" :value="scope.row.formType"></dict-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="地址" align="center" prop="router" />
-        <el-table-column label="备注" align="center" prop="remark" />
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['workflow:formManage:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['workflow:formManage:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改表单管理对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="formManageFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="表单名称" prop="formName">
-          <el-input v-model="form.formName" placeholder="请输入表单名称" />
-        </el-form-item>
-        <el-form-item label="表单类型" prop="formType">
-          <el-radio-group v-model="form.formType" @change="form.router = ''">
-            <el-radio v-for="dict in wf_form_type" :key="dict.value" border :value="dict.value">{{ dict.label }}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item v-if="form.formType === 'static'" label="路由地址" prop="router">
-          <el-input v-model="form.router" placeholder="请输入路由地址" />
-        </el-form-item>
-        <el-form-item v-else label="表单" prop="router">
-          <el-input v-model="form.router" disabled placeholder="请选择表单">
-            <template #append>
-              <el-button icon="Search" />
-            </template>
-          </el-input>
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="FormManage" lang="ts">
-import { listFormManage, getFormManage, delFormManage, addFormManage, updateFormManage } from '@/api/workflow/formManage';
-import { FormManageVO, FormManageQuery, FormManageForm } from '@/api/workflow/formManage/types';
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { wf_form_type } = toRefs<any>(proxy?.useDict('wf_form_type'));
-
-const formManageList = ref<FormManageVO[]>([]);
-const buttonLoading = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-
-const queryFormRef = ref<ElFormInstance>();
-const formManageFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: FormManageForm = {
-  id: undefined,
-  formName: undefined,
-  formType: 'static',
-  remark: undefined
-};
-const data = reactive<PageData<FormManageForm, FormManageQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    formName: undefined,
-    formType: undefined
-  },
-  rules: {
-    id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
-    formName: [{ required: true, message: '表单名称不能为空', trigger: 'blur' }],
-    formType: [{ required: true, message: '表单类型不能为空', trigger: 'change' }],
-    router: [{ required: true, message: '不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询表单管理列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listFormManage(queryParams.value);
-  formManageList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  formManageFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: FormManageVO[]) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加表单管理';
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: FormManageVO) => {
-  reset();
-  const _id = row?.id || ids.value[0];
-  const res = await getFormManage(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改表单管理';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  formManageFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.id) {
-        await updateFormManage(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addFormManage(form.value).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: FormManageVO) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除表单管理编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
-  await delFormManage(_ids);
-  proxy?.$modal.msgSuccess('删除成功');
-  await getList();
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'workflow/formManage/export',
-    {
-      ...queryParams.value
-    },
-    `formManage_${new Date().getTime()}.xlsx`
-  );
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 28 - 34
src/views/workflow/leave/index.vue

@@ -31,7 +31,7 @@
         </el-row>
       </template>
 
-      <el-table v-loading="loading" :data="leaveList" @selection-change="handleSelectionChange">
+      <el-table v-loading="loading" border :data="leaveList" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column v-if="false" label="主键" align="center" prop="id" />
         <el-table-column label="请假类型" align="center">
@@ -56,38 +56,28 @@
             <dict-tag :options="wf_business_status" :value="scope.row.status"></dict-tag>
           </template>
         </el-table-column>
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <el-table-column label="操作" align="center" width="162">
           <template #default="scope">
-            <el-button
-              v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"
-              v-hasPermi="['workflow:leave:edit']"
-              size="small"
-              link
-              type="primary"
-              icon="Edit"
-              @click="handleUpdate(scope.row)"
-              >修改</el-button
-            >
-            <el-button
-              v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"
-              v-hasPermi="['workflow:leave:remove']"
-              size="small"
-              link
-              type="primary"
-              icon="Delete"
-              @click="handleDelete(scope.row)"
-              >删除</el-button
-            >
-            <el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
-            <el-button
-              v-if="scope.row.status === 'waiting'"
-              link
-              size="small"
-              type="primary"
-              icon="Notification"
-              @click="handleCancelProcessApply(scope.row.id)"
-              >撤销</el-button
-            >
+            <el-row :gutter="10" class="mb8">
+              <el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'">
+                <el-button v-hasPermi="['workflow:leave:edit']" size="small" type="primary" icon="Edit" @click="handleUpdate(scope.row)"
+                  >修改</el-button
+                >
+              </el-col>
+              <el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'">
+                <el-button v-hasPermi="['workflow:leave:remove']" size="small" type="primary" icon="Delete" @click="handleDelete(scope.row)"
+                  >删除</el-button
+                >
+              </el-col>
+            </el-row>
+            <el-row :gutter="10" class="mb8">
+              <el-col :span="1.5">
+                <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
+              </el-col>
+              <el-col :span="1.5" v-if="scope.row.status === 'waiting'">
+                <el-button size="small" type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.id)">撤销</el-button>
+              </el-col>
+            </el-row>
           </template>
         </el-table-column>
       </el-table>
@@ -99,7 +89,7 @@
 
 <script setup name="Leave" lang="ts">
 import { delLeave, listLeave } from '@/api/workflow/leave';
-import { cancelProcessApply } from '@/api/workflow/processInstance';
+import { cancelProcessApply } from '@/api/workflow/instance';
 import { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -232,7 +222,11 @@ const handleExport = () => {
 const handleCancelProcessApply = async (id: string) => {
   await proxy?.$modal.confirm('是否确认撤销当前单据?');
   loading.value = true;
-  await cancelProcessApply(id).finally(() => (loading.value = false));
+  let data = {
+    businessId: id,
+    message: '申请人撤销流程!'
+  };
+  await cancelProcessApply(data).finally(() => (loading.value = false));
   await getList();
   proxy?.$modal.msgSuccess('撤销成功');
 };

+ 63 - 7
src/views/workflow/leave/leaveEdit.vue

@@ -44,6 +44,17 @@
     <submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
     <!-- 审批记录 -->
     <approvalRecord ref="approvalRecordRef" />
+    <el-dialog v-model="dialogVisible.visible" :title="dialogVisible.title" :before-close="handleClose" width="500">
+      <el-select v-model="flowCode" placeholder="Select" style="width: 240px">
+        <el-option v-for="item in flowCodeOptions" :key="item.value" :label="item.label" :value="item.value" />
+      </el-select>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="handleClose">取消</el-button>
+          <el-button type="primary" @click="submitFlow()"> 确认 </el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -80,6 +91,35 @@ const options = [
     label: '婚假'
   }
 ];
+const flowCodeOptions = [
+  {
+    value: 'leave1',
+    label: '请假申请-普通'
+  },
+  {
+    value: 'leave2',
+    label: '请假申请-排他网关'
+  },
+  {
+    value: 'leave3',
+    label: '请假申请-并行网关'
+  },
+  {
+    value: 'leave4',
+    label: '请假申请-会签'
+  },
+  {
+    value: 'leave5',
+    label: '请假申请-并行会签网关'
+  }
+];
+
+const flowCode = ref<string>('');
+
+const dialogVisible = reactive<DialogOption>({
+  visible: false,
+  title: '流程定义'
+});
 //提交组件
 const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
 //审批记录组件
@@ -88,8 +128,8 @@ const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
 const leaveFormRef = ref<ElFormInstance>();
 
 const submitFormData = ref<StartProcessBo>({
-  businessKey: '',
-  tableName: '',
+  businessId: '',
+  flowCode: '',
   variables: {}
 });
 const taskVariables = ref<Record<string, any>>({});
@@ -119,6 +159,11 @@ const data = reactive<PageData<LeaveForm, LeaveQuery>>({
   }
 });
 
+const handleClose = () => {
+  dialogVisible.visible = false;
+  flowCode.value = '';
+  buttonLoading.value = false;
+};
 const { form, rules } = toRefs(data);
 
 /** 表单重置 */
@@ -174,6 +219,15 @@ const submitForm = (status: string) => {
           proxy.$tab.closePage(proxy.$route);
           proxy.$router.go(-1);
         } else {
+          if ((form.value.status === 'draft' && (flowCode.value === '' || flowCode.value === null)) || routeParams.value.type === 'add') {
+            flowCode.value = flowCodeOptions[0].value;
+            dialogVisible.visible = true;
+            return;
+          }
+          //说明启动过先随意穿个参数
+          if (flowCode.value === '' || flowCode.value === null) {
+            flowCode.value = 'xx';
+          }
           await handleStartWorkFlow(res.data);
         }
       }
@@ -183,17 +237,19 @@ const submitForm = (status: string) => {
   }
 };
 
+const submitFlow = async () => {
+  handleStartWorkFlow(form.value);
+  dialogVisible.visible = false;
+};
 //提交申请
 const handleStartWorkFlow = async (data: LeaveVO) => {
   try {
-    submitFormData.value.tableName = 'test_leave';
-    submitFormData.value.businessKey = data.id;
+    submitFormData.value.flowCode = flowCode.value;
+    submitFormData.value.businessId = data.id;
     //流程变量
     taskVariables.value = {
-      entity: data,
       leaveDays: data.leaveDays,
-      userList: ['1', '3'],
-      userList2: ['1', '3']
+      userList: ['1', '3', '4']
     };
     submitFormData.value.variables = taskVariables.value;
     const resp = await startWorkFlow(submitFormData.value);

+ 0 - 383
src/views/workflow/model/index.vue

@@ -1,383 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-row :gutter="20">
-      <!-- 流程分类树 -->
-      <el-col :lg="4" :xs="24" style="">
-        <el-card shadow="hover">
-          <el-input v-model="categoryName" placeholder="请输入流程分类名" prefix-icon="Search" clearable />
-          <el-tree
-            ref="categoryTreeRef"
-            class="mt-2"
-            node-key="id"
-            :data="categoryOptions"
-            :props="{ label: 'categoryName', children: 'children' }"
-            :expand-on-click-node="false"
-            :filter-node-method="filterNode"
-            highlight-current
-            default-expand-all
-            @node-click="handleNodeClick"
-          ></el-tree>
-        </el-card>
-      </el-col>
-      <el-col :lg="20" :xs="24">
-        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-          <div v-show="showSearch" class="mb-[10px]">
-            <el-card shadow="hover">
-              <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-                <el-form-item label="模型名称" prop="name">
-                  <el-input v-model="queryParams.name" placeholder="请输入模型名称" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="模型KEY" prop="key">
-                  <el-input v-model="queryParams.key" placeholder="请输入模型KEY" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item>
-                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-                </el-form-item>
-              </el-form>
-            </el-card>
-          </div>
-        </transition>
-        <el-card shadow="hover">
-          <template #header>
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">修改</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">删除</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="primary" plain :disabled="multiple" icon="Download" @click="clickExportZip()">导出</el-button>
-              </el-col>
-              <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-            </el-row>
-          </template>
-
-          <el-table v-loading="loading" border :data="modelList" @selection-change="handleSelectionChange">
-            <el-table-column type="selection" width="55" align="center" />
-            <el-table-column fixed align="center" type="index" label="序号" width="80"></el-table-column>
-            <el-table-column align="center" :show-overflow-tooltip="true" prop="name" label="模型名称" width="200"></el-table-column>
-            <el-table-column align="center" prop="key" label="模型KEY"></el-table-column>
-            <el-table-column align="center" prop="version" label="版本号" width="90">
-              <template #default="scope"> v{{ scope.row.version }}.0</template>
-            </el-table-column>
-            <el-table-column align="center" prop="metaInfo" label="备注说明" min-width="130"></el-table-column>
-            <el-table-column align="center" :show-overflow-tooltip="true" prop="createTime" label="创建时间" width="160"></el-table-column>
-            <el-table-column align="center" :show-overflow-tooltip="true" prop="lastUpdateTime" label="更新时间" width="160"></el-table-column>
-            <el-table-column fixed="right" label="操作" align="center" width="170" class-name="small-padding fixed-width">
-              <template #default="scope">
-                <el-row :gutter="10" class="mb8">
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="Pointer" @click="clickDesign(scope.row.id)">设计流程</el-button>
-                  </el-col>
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
-                  </el-col>
-                </el-row>
-                <el-row :gutter="10" class="mb8">
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="ScaleToOriginal" @click="clickDeploy(scope.row.id, scope.row.key)">
-                      流程部署
-                    </el-button>
-                  </el-col>
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="CopyDocument" @click="handleCopy(scope.row)"> 复制模型 </el-button>
-                  </el-col>
-                </el-row>
-              </template>
-            </el-table-column>
-          </el-table>
-          <pagination
-            v-show="total > 0"
-            v-model:page="queryParams.pageNum"
-            v-model:limit="queryParams.pageSize"
-            :total="total"
-            @pagination="getList"
-          />
-        </el-card>
-      </el-col>
-    </el-row>
-    <!-- 设计流程开始 -->
-    <Design ref="designRef" @close-call-back="handleQuery"></Design>
-    <!-- 设计流程结束 -->
-    <!-- 添加模型对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="650px" append-to-body :close-on-click-modal="false">
-      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
-        <el-form-item label="模型名称:" prop="name">
-          <el-input v-model="form.name" :disabled="ids && ids.length > 0 && billType === 'update'" maxlength="20" show-word-limit />
-        </el-form-item>
-        <el-form-item label="模型KEY:" prop="key">
-          <el-input v-model="form.key" :disabled="ids && ids.length > 0 && billType === 'update'" maxlength="20" show-word-limit />
-        </el-form-item>
-        <el-form-item label="流程分类" prop="categoryCode">
-          <el-tree-select
-            v-model="form.categoryCode"
-            :data="categoryOptions"
-            :props="{ value: 'categoryCode', label: 'categoryName', children: 'children' }"
-            value-key="categoryCode"
-            placeholder="请选择流程分类"
-            check-strictly
-          />
-        </el-form-item>
-        <el-form-item label="备注:" prop="description">
-          <el-input v-model="form.description" type="textarea" maxlength="200" show-word-limit></el-input>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </span>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script lang="ts" setup name="Model">
-import Design from '../../../components/BpmnDesign/index.vue';
-import { listModel, addModel, delModel, modelDeploy, getInfo, update } from '@/api/workflow/model';
-import { ModelQuery, ModelForm, ModelVO } from '@/api/workflow/model/types';
-import { listCategory } from '@/api/workflow/category';
-import { copyModel } from '@/api/workflow/model';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const formRef = ref<ElFormInstance>();
-const queryFormRef = ref<ElFormInstance>();
-const categoryTreeRef = ref<ElTreeInstance>();
-const designRef = ref<InstanceType<typeof Design>>();
-
-type CategoryOption = {
-  categoryCode: string;
-  categoryName: string;
-  children?: CategoryOption[];
-};
-
-const buttonLoading = ref(false);
-const loading = ref(true);
-const ids = ref<string[]>([]);
-const single = ref(true);
-const multiple = ref(true);
-const showSearch = ref(true);
-const total = ref(0);
-const modelList = ref<ModelVO[]>([]);
-const categoryOptions = ref<CategoryOption[]>([]);
-const categoryName = ref('');
-const billType = ref<string>('');
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: ModelForm = {
-  id: '',
-  name: '',
-  key: '',
-  categoryCode: '',
-  xml: '',
-  svg: '',
-  description: ''
-};
-const data = reactive<PageData<ModelForm, ModelQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    name: '',
-    key: '',
-    categoryCode: ''
-  },
-  rules: {
-    name: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
-    key: [{ required: true, message: '模型KEY不能为空', trigger: 'blur' }],
-    categoryCode: [{ required: true, message: '流程分类不能为空', trigger: 'blur' }]
-  }
-});
-const { queryParams, form, rules } = toRefs(data);
-
-onMounted(() => {
-  getList();
-  getTreeselect();
-});
-
-/** 节点单击事件 */
-const handleNodeClick = (data: ModelForm) => {
-  queryParams.value.categoryCode = data.categoryCode;
-  if (data.categoryCode === 'ALL') {
-    queryParams.value.categoryCode = '';
-  }
-  handleQuery();
-};
-/** 通过条件过滤节点  */
-const filterNode = (value: string, data: any) => {
-  if (!value) return true;
-  return data.categoryName.indexOf(value) !== -1;
-};
-/** 根据名称筛选部门树 */
-watchEffect(
-  () => {
-    categoryTreeRef.value?.filter(categoryName.value);
-  },
-  {
-    flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
-  }
-);
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.categoryCode = '';
-  queryParams.value.pageNum = 1;
-  queryParams.value.pageSize = 10;
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: ModelVO[]) => {
-  ids.value = selection.map((item: ModelVO) => item.id);
-  single.value = selection.length !== 1;
-  multiple.value = !selection.length;
-};
-//分页
-const getList = async () => {
-  loading.value = true;
-  const resp = await listModel(queryParams.value);
-  modelList.value = resp.rows;
-  total.value = resp.total;
-  loading.value = false;
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: ModelVO) => {
-  const id = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除模型id为【' + id + '】的数据项?');
-  loading.value = true;
-  await delModel(id).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-// 流程部署
-const clickDeploy = async (id: string, key: string) => {
-  await proxy?.$modal.confirm('是否部署模型key为【' + key + '】流程?');
-  loading.value = true;
-  await modelDeploy(id).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('部署成功');
-};
-//新增打开
-const handleAdd = () => {
-  billType.value = 'add';
-  ids.value = [];
-  getTreeselect();
-  form.value = { ...initFormData };
-  dialog.visible = true;
-  dialog.title = '新增模型';
-};
-//修改打开
-const handleUpdate = () => {
-  billType.value = 'update';
-  dialog.title = '修改模型';
-  nextTick(async () => {
-    await getTreeselect();
-    const _id = ids.value[0];
-    const res = await getInfo(_id);
-    Object.assign(form.value, res.data);
-    dialog.visible = true;
-  });
-};
-
-//复制打开
-const handleCopy = (row?: ModelVO) => {
-  billType.value = 'copy';
-  dialog.title = '复制模型';
-  nextTick(async () => {
-    await getTreeselect();
-    form.value = { ...initFormData };
-    form.value.id = row.id;
-    dialog.visible = true;
-  });
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  formRef.value.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if ('copy' === billType.value) {
-        await copyModel(form.value);
-        proxy?.$modal.msgSuccess('操作成功');
-      } else if (ids.value && ids.value.length > 0 && 'update' === billType.value) {
-        form.value.id = ids.value[0];
-        await update(form.value);
-        proxy?.$modal.msgSuccess('操作成功');
-      } else {
-        initXml(form.value.key, form.value.name);
-        form.value.xml = xml.value;
-        await addModel(form.value);
-        proxy?.$modal.msgSuccess('操作成功');
-      }
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  formRef.value.resetFields();
-};
-
-// 打开设计流程
-const clickDesign = async (id: string) => {
-  await designRef.value.open(id);
-};
-// 导出流程模型
-const clickExportZip = () => {
-  proxy?.$download.zip('/workflow/model/export/zip/' + ids.value, '模型');
-};
-/** 查询流程分类下拉树结构 */
-const getTreeselect = async () => {
-  const res = await listCategory();
-  categoryOptions.value = [];
-  const data: CategoryOption = { categoryCode: 'ALL', categoryName: '顶级节点', children: [] };
-  data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId');
-  categoryOptions.value.push(data);
-};
-
-const xml = ref<string>('');
-
-const initXml = async (key: string, name: string) => {
-  xml.value = `<?xml version="1.0" encoding="UTF-8"?>
-<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.flowable.org/processdef">
-  <process id="${key}" name="${name}">
-    <startEvent id="startNode1" name="开始" />
-  </process>
-  <bpmndi:BPMNDiagram id="BPMNDiagram_flow">
-    <bpmndi:BPMNPlane id="BPMNPlane_flow" bpmnElement="T-2d89e7a3-ba79-4abd-9f64-ea59621c258c">
-      <bpmndi:BPMNShape id="BPMNShape_startNode1" bpmnElement="startNode1" bioc:stroke="">
-        <omgdc:Bounds x="240" y="200" width="30" height="30" />
-        <bpmndi:BPMNLabel>
-          <omgdc:Bounds x="242" y="237" width="23" height="14" />
-        </bpmndi:BPMNLabel>
-      </bpmndi:BPMNShape>
-    </bpmndi:BPMNPlane>
-  </bpmndi:BPMNDiagram>
-</definitions>`;
-  return xml;
-};
-</script>

+ 0 - 45
src/views/workflow/processDefinition/components/processPreview.vue

@@ -1,45 +0,0 @@
-<template>
-  <el-dialog v-model="data.visible" title="预览" width="70%" append-to-body destroy-on-close>
-    <div v-if="data.type === 'bpmn' && data.xmlStr">
-      <BpmnViewer ref="bpmnViewerRef"></BpmnViewer>
-    </div>
-    <div v-if="data.type === 'xml' && data.xmlStr">
-      <highlightjs language="xml" :code="data.xmlStr" />
-    </div>
-    <template #footer>
-      <span v-if="data.type === 'xml'" class="dialog-footer"> </span>
-    </template>
-  </el-dialog>
-</template>
-
-<script setup lang="ts">
-import BpmnViewer from '@/components/BpmnView/index.vue';
-
-const data = reactive({
-  visible: false,
-  type: '',
-  xmlStr: ''
-});
-
-const bpmnViewerRef = ref<InstanceType<typeof BpmnViewer>>();
-type PreviewType = 'xml' | 'bpmn';
-//打开
-const openDialog = (xmlStr: string, type: PreviewType) => {
-  data.visible = true;
-  data.xmlStr = xmlStr;
-  data.type = type;
-  /** 流程图 */
-  if (type === 'bpmn') {
-    /** 必须放在nextTick 否则第一次打开为空 */
-    nextTick(() => {
-      bpmnViewerRef.value?.initXml(data.xmlStr);
-    });
-  }
-};
-/**
- * 对外暴露子组件方法
- */
-defineExpose({
-  openDialog
-});
-</script>

+ 52 - 0
src/views/workflow/processDefinition/design.vue

@@ -0,0 +1,52 @@
+<template>
+  <div ref="container" class="container">
+    <iframe ref="iframe" :src="iframeUrl" frameborder="0" width="100%" height="100%"></iframe>
+  </div>
+</template>
+
+<script setup name="WarmFlow">
+const { proxy } = getCurrentInstance();
+import { onMounted } from 'vue';
+// definitionId为需要查询的流程定义id,
+// disabled为是否可编辑, 例如:查看的时候不可编辑,不可保存
+const iframeUrl = ref('');
+const baseUrl = import.meta.env.VITE_APP_BASE_API;
+import { getToken } from '@/utils/auth';
+const iframeLoaded = () => {
+  // iframe监听组件内设计器保存事件
+  window.onmessage = (event) => {
+    switch (event.data.method) {
+      case 'close':
+        close();
+        break;
+    }
+  };
+};
+const open = async (definitionId, disabled) => {
+  let url = baseUrl + `/warm-flow-ui/index.html?id=${definitionId}&disabled=${disabled}`;
+  iframeUrl.value = url + '&Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID;
+};
+/** 关闭按钮 */
+function close() {
+  const obj = { path: '/workflow/processDefinition' };
+  proxy.$tab.closeOpenPage(obj);
+}
+
+onMounted(() => {
+  iframeLoaded();
+  open(proxy.$route.query.definitionId, proxy.$route.query.disabled);
+});
+/**
+ * 对外暴露子组件方法
+ */
+defineExpose({
+  open
+});
+</script>
+
+<style scoped>
+.container {
+  width: 100%;
+  height: calc(100vh - 84px);
+}
+</style>

+ 284 - 300
src/views/workflow/processDefinition/index.vue

@@ -10,7 +10,7 @@
             class="mt-2"
             node-key="id"
             :data="categoryOptions"
-            :props="{ label: 'categoryName', children: 'children' }"
+            :props="{ label: 'label', children: 'children' }"
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             highlight-current
@@ -24,11 +24,11 @@
           <div v-show="showSearch" class="mb-[10px]">
             <el-card shadow="hover">
               <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
-                <el-form-item label="流程定义名称" prop="name">
-                  <el-input v-model="queryParams.name" placeholder="请输入流程定义名称" clearable @keyup.enter="handleQuery" />
+                <el-form-item label="流程定义名称" prop="flowName">
+                  <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" clearable @keyup.enter="handleQuery" />
                 </el-form-item>
-                <el-form-item label="流程定义KEY" prop="key">
-                  <el-input v-model="queryParams.key" placeholder="请输入流程定义KEY" clearable @keyup.enter="handleQuery" />
+                <el-form-item label="流程定义KEY" prop="flowCode">
+                  <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义KEY" clearable @keyup.enter="handleQuery" />
                 </el-form-item>
                 <el-form-item>
                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -41,94 +41,87 @@
         <el-card shadow="hover">
           <template #header>
             <el-row :gutter="10" class="mb8">
+              <el-col :span="1.5">
+                <el-button type="primary" icon="Plus" @click="handleAdd()">添加</el-button>
+              </el-col>
+              <el-col :span="1.5">
+                <el-button type="success" icon="Edit" :disabled="single" @click="handleUpdate()">修改</el-button>
+              </el-col>
               <el-col :span="1.5">
                 <el-button type="danger" icon="Delete" :disabled="multiple" @click="handleDelete()">删除</el-button>
               </el-col>
               <el-col :span="1.5">
                 <el-button type="primary" icon="UploadFilled" @click="uploadDialog.visible = true">部署流程文件</el-button>
               </el-col>
+              <el-col :span="1.5">
+                <el-button type="warning" icon="Download" :disabled="single" @click="handleExportDef">导出</el-button>
+              </el-col>
               <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
             </el-row>
           </template>
-
-          <el-table v-loading="loading" border :data="processDefinitionList" @selection-change="handleSelectionChange">
-            <el-table-column type="selection" width="55" align="center" />
-            <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-            <el-table-column align="center" prop="name" label="流程定义名称" :show-overflow-tooltip="true"></el-table-column>
-            <el-table-column align="center" prop="key" label="标识KEY" width="80"></el-table-column>
-            <el-table-column align="center" prop="version" label="版本号" width="80">
-              <template #default="scope"> v{{ scope.row.version }}.0</template>
-            </el-table-column>
-            <el-table-column align="center" prop="resourceName" label="流程XML" width="100" :show-overflow-tooltip="true">
-              <template #default="scope">
-                <el-link type="primary" @click="clickPreview(scope.row.id, 'xml')">{{ scope.row.resourceName }}</el-link>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" prop="diagramResourceName" label="流程图片" width="100" :show-overflow-tooltip="true">
-              <template #default="scope">
-                <el-link type="primary" @click="clickPreview(scope.row.id, 'bpmn')">{{ scope.row.diagramResourceName }}</el-link>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" prop="suspensionState" label="状态" width="80">
-              <template #default="scope">
-                <el-tag v-if="scope.row.suspensionState == 1" type="success">激活</el-tag>
-                <el-tag v-else type="danger">挂起</el-tag>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" prop="deploymentTime" label="部署时间" width="120" :show-overflow-tooltip="true"></el-table-column>
-            <el-table-column align="center" label="表名/表单KEY" width="120" :show-overflow-tooltip="true">
-              <template #default="scope">
-                <span v-if="scope.row.wfDefinitionConfigVo">
-                  {{ scope.row.wfDefinitionConfigVo.tableName }}
-                </span>
-              </template>
-            </el-table-column>
-            <el-table-column fixed="right" label="操作" align="center" width="220" class-name="small-padding fixed-width">
-              <template #default="scope">
-                <el-row :gutter="10" class="mb8">
-                  <el-col :span="1.5">
-                    <el-button
-                      link
-                      type="primary"
-                      size="small"
-                      :icon="scope.row.suspensionState === 1 ? 'Lock' : 'Unlock'"
-                      @click="handleProcessDefState(scope.row)"
-                    >
-                      {{ scope.row.suspensionState === 1 ? '挂起流程' : '激活流程' }}
-                    </el-button>
-                  </el-col>
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="Document" @click="getProcessDefinitionHitoryList(scope.row.id, scope.row.key)">
-                      历史版本
-                    </el-button>
-                  </el-col>
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
-                  </el-col>
-                </el-row>
-                <el-row :gutter="10" class="mb8">
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="Sort" @click="handleConvertToModel(scope.row)"> 转换模型 </el-button>
-                  </el-col>
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="Tickets" @click="handleDefinitionConfigOpen(scope.row)">绑定业务</el-button>
-                  </el-col>
-                </el-row>
-              </template>
-            </el-table-column>
-          </el-table>
-          <pagination
-            v-show="total > 0"
-            v-model:page="queryParams.pageNum"
-            v-model:limit="queryParams.pageSize"
-            :total="total"
-            @pagination="getList"
-          />
+          <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+            <el-tab-pane label="已发布" name="0"></el-tab-pane>
+            <el-tab-pane label="未发布" name="1"></el-tab-pane>
+            <el-table v-loading="loading" border :data="processDefinitionList" @selection-change="handleSelectionChange">
+              <el-table-column type="selection" width="55" align="center" />
+              <el-table-column align="center" prop="id" label="主键" v-if="false"></el-table-column>
+              <el-table-column align="center" prop="flowName" label="流程定义名称" :show-overflow-tooltip="true"></el-table-column>
+              <el-table-column align="center" prop="flowCode" label="标识KEY" :show-overflow-tooltip="true"></el-table-column>
+              <el-table-column align="center" prop="version" label="版本号" width="80">
+                <template #default="scope"> v{{ scope.row.version }}.0</template>
+              </el-table-column>
+              <el-table-column align="center" prop="activityStatus" label="激活状态" width="130">
+                <template #default="scope">
+                  <el-switch
+                    v-model="scope.row.activityStatus"
+                    :active-value="1"
+                    :inactive-value="0"
+                    @change="(status) => handleProcessDefState(scope.row, status)"
+                  />
+                </template>
+              </el-table-column>
+              <el-table-column align="center" prop="isPublish" label="发布状态" width="100">
+                <template #default="scope">
+                  <el-tag v-if="scope.row.isPublish == 0" type="danger">未发布</el-tag>
+                  <el-tag v-else-if="scope.row.isPublish == 1" type="success">已发布</el-tag>
+                  <el-tag v-else type="danger">失效</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column fixed="right" label="操作" align="center" width="170" class-name="small-padding fixed-width">
+                <template #default="scope">
+                  <el-row :gutter="10" class="mb8">
+                    <el-col :span="1.5">
+                      <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除流程</el-button>
+                    </el-col>
+                    <el-col :span="1.5">
+                      <el-button link type="primary" size="small" icon="CopyDocument" @click="handleCopyDef(scope.row)">复制流程</el-button>
+                    </el-col>
+                  </el-row>
+                  <el-row :gutter="10" class="mb8">
+                    <el-col :span="1.5">
+                      <el-button link type="primary" v-if="scope.row.isPublish === 0" icon="Pointer" size="small" @click="design(scope.row)"
+                        >流程设计</el-button
+                      >
+                      <el-button link type="primary" v-else icon="View" size="small" @click="designView(scope.row)">查看流程</el-button>
+                    </el-col>
+                    <el-col v-if="scope.row.isPublish !== 1" :span="1.5">
+                      <el-button link type="primary" size="small" icon="CircleCheck" @click="handlePublish(scope.row)">发布流程</el-button>
+                    </el-col>
+                  </el-row>
+                </template>
+              </el-table-column>
+            </el-table>
+            <pagination
+              v-show="total > 0"
+              v-model:page="queryParams.pageNum"
+              v-model:limit="queryParams.pageSize"
+              :total="total"
+              @pagination="handleQuery"
+            />
+          </el-tabs>
         </el-card>
       </el-col>
     </el-row>
-    <!-- 预览图片或xml -->
-    <process-preview ref="previewRef" />
 
     <!-- 部署文件 -->
     <el-dialog v-if="uploadDialog.visible" v-model="uploadDialog.visible" :title="uploadDialog.title" width="30%">
@@ -138,9 +131,9 @@
           <el-tree-select
             v-model="selectCategory"
             :data="categoryOptions"
-            :props="{ value: 'categoryCode', label: 'categoryName', children: 'children' }"
+            :props="{ value: 'id', label: 'label', children: 'children' }"
             filterable
-            value-key="categoryCode"
+            value-key="id"
             :render-after-expand="false"
             check-strictly
             style="width: 240px"
@@ -152,7 +145,7 @@
           multiple
           accept="application/zip,application/xml,.bpmn"
           :before-upload="handlerBeforeUpload"
-          :http-request="handerDeployProcessFile"
+          :http-request="handlerImportDefinition"
         >
           <el-icon class="UploadFilled"><upload-filled /></el-icon>
           <div class="el-upload__text"><em>点击上传,选择BPMN流程文件</em></div>
@@ -162,88 +155,35 @@
       </div>
     </el-dialog>
 
-    <!-- 历史版本 -->
-    <el-dialog v-if="processDefinitionDialog.visible" v-model="processDefinitionDialog.visible" :title="processDefinitionDialog.title" width="70%">
-      <el-table v-loading="loading" :data="processDefinitionHistoryList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column align="center" prop="name" label="流程定义名称" :show-overflow-tooltip="true" min-width="80"></el-table-column>
-        <el-table-column align="center" prop="key" label="标识KEY"></el-table-column>
-        <el-table-column align="center" prop="version" label="版本号" width="90">
-          <template #default="scope"> v{{ scope.row.version }}.0</template>
-        </el-table-column>
-        <el-table-column align="center" prop="resourceName" label="流程XML" min-width="80" :show-overflow-tooltip="true">
-          <template #default="scope">
-            <el-link type="primary" @click="clickPreviewXML(scope.row.id)">{{ scope.row.resourceName }}</el-link>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="diagramResourceName" label="流程图片" min-width="80" :show-overflow-tooltip="true">
-          <template #default="scope">
-            <el-link type="primary" @click="clickPreviewImg(scope.row.id)">{{ scope.row.diagramResourceName }}</el-link>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="suspensionState" label="状态" min-width="70">
-          <template #default="scope">
-            <el-tag v-if="scope.row.suspensionState == 1" type="success">激活</el-tag>
-            <el-tag v-else type="danger">挂起</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="deploymentTime" label="部署时间" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column fixed="right" label="操作" align="center" width="200" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button
-                  link
-                  type="primary"
-                  size="small"
-                  :icon="scope.row.suspensionState === 1 ? 'Lock' : 'Unlock'"
-                  @click="handleProcessDefState(scope.row)"
-                >
-                  {{ scope.row.suspensionState === 1 ? '挂起流程' : '激活流程' }}
-                </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="text" size="small" icon="Tickets" @click="handleDefinitionConfigOpen(scope.row)">绑定业务</el-button>
-              </el-col>
-            </el-row>
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button link type="primary" icon="Sort" size="small" @click="handleConvertToModel(scope.row)"> 转换模型 </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button link type="primary" icon="Delete" size="small" @click="handleDelete(scope.row)">删除</el-button>
-              </el-col>
-            </el-row>
-          </template>
-        </el-table-column>
-      </el-table>
-    </el-dialog>
-
-    <!-- 表单配置 -->
-    <el-dialog
-      v-model="definitionConfigDialog.visible"
-      :title="definitionConfigDialog.title"
-      width="650px"
-      append-to-body
-      :close-on-click-modal="false"
-    >
-      <el-form :model="definitionConfigForm" label-width="auto">
-        <el-form-item label="流程KEY">
-          <el-input v-model="definitionConfigForm.processKey" disabled />
-        </el-form-item>
-        <el-form-item label="表名" prop="formId">
-          <el-input v-model="definitionConfigForm.tableName" placeholder="示例:test_leave" />
-        </el-form-item>
-        <el-form-item label="备注">
-          <el-input v-model="definitionConfigForm.remark" type="textarea" resize="none" />
-        </el-form-item>
-      </el-form>
-
+    <!-- 新增/编辑流程定义 -->
+    <el-dialog v-model="modelDialog.visible" :title="modelDialog.title" width="650px" append-to-body :close-on-click-modal="false">
       <template #footer>
+        <el-form ref="defFormRef" :model="form" :rules="rules" label-width="110px">
+          <el-form-item label="流程类别" prop="category">
+            <el-tree-select
+              v-model="form.category"
+              :data="categoryOptions"
+              :props="{ value: 'id', label: 'label', children: 'children' }"
+              filterable
+              value-key="id"
+              :render-after-expand="false"
+              check-strictly
+              style="width: 100%"
+            />
+          </el-form-item>
+          <el-form-item label="流程编码" prop="flowCode">
+            <el-input v-model="form.flowCode" placeholder="请输入流程编码" maxlength="40" show-word-limit />
+          </el-form-item>
+          <el-form-item label="流程名称" prop="flowName">
+            <el-input v-model="form.flowName" placeholder="请输入流程名称" maxlength="100" show-word-limit />
+          </el-form-item>
+          <el-form-item label="表单路径" prop="flowName">
+            <el-input v-model="form.formPath" placeholder="请输入表单路径" maxlength="100" show-word-limit />
+          </el-form-item>
+        </el-form>
         <div class="dialog-footer">
-          <el-button @click="definitionConfigDialog.visible = false">取消</el-button>
-          <el-button type="primary" @click="handlerSaveForm">保存</el-button>
+          <el-button @click="modelDialog.visible = false">取消</el-button>
+          <el-button type="primary" @click="handleSubmit">保存</el-button>
         </div>
       </template>
     </el-dialog>
@@ -251,53 +191,32 @@
 </template>
 
 <script lang="ts" setup name="processDefinition">
-import {
-  listProcessDefinition,
-  definitionImage,
-  definitionXml,
-  deleteProcessDefinition,
-  updateDefinitionState,
-  convertToModel,
-  deployProcessFile,
-  getListByKey
-} from '@/api/workflow/processDefinition';
-import { getByTableNameNotDefId, getByDefId, saveOrUpdate } from '@/api/workflow/definitionConfig';
-import ProcessPreview from './components/processPreview.vue';
-import { listCategory } from '@/api/workflow/category';
-import { CategoryVO } from '@/api/workflow/category/types';
-import { ProcessDefinitionQuery, ProcessDefinitionVO } from '@/api/workflow/processDefinition/types';
-import { DefinitionConfigForm } from '@/api/workflow/definitionConfig/types';
-import { UploadRequestOptions, ElMessage, ElMessageBox } from 'element-plus';
+import { listDefinition, deleteDefinition, active, importDef, unPublishList, publish, add, edit, getInfo, copy } from '@/api/workflow/definition';
+import { categoryTree } from '@/api/workflow/category';
+import { CategoryTreeVO } from '@/api/workflow/category/types';
+import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types';
+import { UploadRequestOptions, TabsPaneContext } from 'element-plus';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
-const previewRef = ref<InstanceType<typeof ProcessPreview>>();
 const queryFormRef = ref<ElFormInstance>();
 const categoryTreeRef = ref<ElTreeInstance>();
-const definitionConfigForm = ref<DefinitionConfigForm>({});
-
-type CategoryOption = {
-  categoryCode: string;
-  categoryName: string;
-  children?: CategoryOption[];
-};
 
 const loading = ref(true);
 const ids = ref<Array<any>>([]);
-const deploymentIds = ref<Array<any>>([]);
-const keys = ref<Array<any>>([]);
+const flowCodeList = ref<Array<any>>([]);
 const single = ref(true);
 const multiple = ref(true);
 const showSearch = ref(true);
 const total = ref(0);
 const uploadDialogLoading = ref(false);
-const processDefinitionList = ref<ProcessDefinitionVO[]>([]);
-const processDefinitionHistoryList = ref<ProcessDefinitionVO[]>([]);
-const categoryOptions = ref<CategoryOption[]>([]);
+const processDefinitionList = ref<FlowDefinitionVo[]>([]);
+const categoryOptions = ref<CategoryTreeVO[]>([]);
 const categoryName = ref('');
 /** 部署文件分类选择 */
 const selectCategory = ref();
-
+const defFormRef = ref<ElFormInstance>();
+const activeName = ref('0');
 const uploadDialog = reactive<DialogOption>({
   visible: false,
   title: '部署流程文件'
@@ -308,30 +227,49 @@ const processDefinitionDialog = reactive<DialogOption>({
   title: '历史版本'
 });
 
-const definitionConfigDialog = reactive<DialogOption>({
+const modelDialog = reactive<DialogOption>({
   visible: false,
-  title: '流程定义配置'
+  title: ''
 });
 
 // 查询参数
-const queryParams = ref<ProcessDefinitionQuery>({
+const queryParams = ref<FlowDefinitionQuery>({
   pageNum: 1,
   pageSize: 10,
-  name: undefined,
-  key: undefined,
-  categoryCode: undefined
+  flowName: undefined,
+  flowCode: undefined,
+  category: undefined
+});
+const rules = {
+  category: [{ required: true, message: '分类名称不能为空', trigger: 'blur' }],
+  flowName: [{ required: true, message: '流程定义名称不能为空', trigger: 'blur' }],
+  flowCode: [{ required: true, message: '流程定义编码不能为空', trigger: 'blur' }]
+};
+const initFormData: FlowDefinitionForm = {
+  id: '',
+  flowName: '',
+  flowCode: '',
+  category: '',
+  formPath: ''
+};
+//流程定义参数
+const form = ref<FlowDefinitionForm>({
+  id: '',
+  flowName: '',
+  flowCode: '',
+  category: '',
+  formPath: ''
 });
-
 onMounted(() => {
-  getList();
+  handleQuery();
   getTreeselect();
 });
 
 /** 节点单击事件 */
-const handleNodeClick = (data: CategoryVO) => {
-  queryParams.value.categoryCode = data.categoryCode;
-  if (data.categoryCode === 'ALL') {
-    queryParams.value.categoryCode = '';
+const handleNodeClick = (data: CategoryTreeVO) => {
+  queryParams.value.category = data.id;
+  if (data.id === '0') {
+    queryParams.value.category = '';
   }
   handleQuery();
 };
@@ -352,22 +290,27 @@ watchEffect(
 
 /** 查询流程分类下拉树结构 */
 const getTreeselect = async () => {
-  const res = await listCategory();
-  categoryOptions.value = [];
-  const data: CategoryOption = { categoryCode: 'ALL', categoryName: '顶级节点', children: [] };
-  data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId');
-  categoryOptions.value.push(data);
+  const res = await categoryTree();
+  categoryOptions.value = res.data;
+};
+const handleClick = (tab: TabsPaneContext, event: Event) => {
+  // v-model处理有延迟 需要手动处理
+  activeName.value = tab.index;
+  handleQuery();
 };
-
 /** 搜索按钮操作 */
 const handleQuery = () => {
   queryParams.value.pageNum = 1;
-  getList();
+  if (activeName.value === '0') {
+    getList();
+  } else {
+    getUnPublishList();
+  }
 };
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
-  queryParams.value.categoryCode = '';
+  queryParams.value.category = '';
   queryParams.value.pageNum = 1;
   queryParams.value.pageSize = 10;
   handleQuery();
@@ -375,73 +318,69 @@ const resetQuery = () => {
 // 多选框选中数据
 const handleSelectionChange = (selection: any) => {
   ids.value = selection.map((item: any) => item.id);
-  deploymentIds.value = selection.map((item: any) => item.deploymentId);
-  keys.value = selection.map((item: any) => item.key);
+  flowCodeList.value = selection.map((item: any) => item.flowCode);
   single.value = selection.length !== 1;
   multiple.value = !selection.length;
 };
 //分页
 const getList = async () => {
   loading.value = true;
-  const resp = await listProcessDefinition(queryParams.value);
+  const resp = await listDefinition(queryParams.value);
   processDefinitionList.value = resp.rows;
   total.value = resp.total;
   loading.value = false;
 };
-//获取历史流程定义
-const getProcessDefinitionHitoryList = async (id: string, key: string) => {
-  processDefinitionDialog.visible = true;
+//查询未发布的流程定义列表
+const getUnPublishList = async () => {
   loading.value = true;
-  const resp = await getListByKey(key);
-  if (resp.data && resp.data.length > 0) {
-    processDefinitionHistoryList.value = resp.data.filter((item: any) => item.id !== id);
-  }
+  const resp = await unPublishList(queryParams.value);
+  processDefinitionList.value = resp.rows;
+  total.value = resp.total;
   loading.value = false;
 };
 
-type PreviewType = 'xml' | 'bpmn';
-//预览 公共方法
-const clickPreview = async (id: string, type: PreviewType) => {
-  loading.value = true;
-  const resp = await definitionXml(id);
-  if (previewRef.value) {
-    const xmlStr = resp.data.xmlStr;
-    loading.value = false;
-    previewRef.value.openDialog(xmlStr, type);
-  }
-};
-
 /** 删除按钮操作 */
-const handleDelete = async (row?: ProcessDefinitionVO) => {
+const handleDelete = async (row?: FlowDefinitionVo) => {
   const id = row?.id || ids.value;
-  const deployIds = row?.deploymentId || deploymentIds.value;
-  const defKeys = row?.key || keys.value;
-  await proxy?.$modal.confirm('是否确认删除流程定义KEY为【' + defKeys + '】的数据项?');
+  const defList = processDefinitionList.value.filter((x) => id.indexOf(x.id) != -1).map((x) => x.flowCode);
+  await proxy?.$modal.confirm('是否确认删除流程定义KEY为【' + defList + '】的数据项?');
   loading.value = true;
-  await deleteProcessDefinition(deployIds, id).finally(() => (loading.value = false));
-  await getList();
+  await deleteDefinition(id).finally(() => (loading.value = false));
+  await handleQuery();
   proxy?.$modal.msgSuccess('删除成功');
 };
+
+/** 发布流程定义 */
+const handlePublish = async (row?: FlowDefinitionVo) => {
+  await proxy?.$modal.confirm(
+    '是否确认发布流程定义KEY为【' + row.flowCode + '】版本为【' + row.version + '】的数据项?,发布后会将已发布流程定义改为失效!'
+  );
+  loading.value = true;
+  await publish(row.id).finally(() => (loading.value = false));
+  processDefinitionDialog.visible = false;
+  await handleQuery();
+  proxy?.$modal.msgSuccess('发布成功');
+};
 /** 挂起/激活 */
-const handleProcessDefState = async (row: ProcessDefinitionVO) => {
+const handleProcessDefState = async (row: FlowDefinitionVo, status: number | string | boolean) => {
   let msg: string;
-  if (row.suspensionState === 1) {
-    msg = `暂停后,此流程下的所有任务都不允许往后流转,您确定挂起【${row.name || row.key}】吗?`;
+  if (status === 0) {
+    msg = `暂停后,此流程下的所有任务都不允许往后流转,您确定挂起【${row.flowName || row.flowCode}】吗?`;
   } else {
-    msg = `启动后,此流程下的所有任务都允许往后流转,您确定激活【${row.name || row.key}】吗?`;
+    msg = `启动后,此流程下的所有任务都允许往后流转,您确定激活【${row.flowName || row.flowCode}】吗?`;
+  }
+  try {
+    loading.value = true;
+    await proxy?.$modal.confirm(msg);
+    await active(row.id, !!status);
+    await handleQuery();
+    proxy?.$modal.msgSuccess('操作成功');
+  } catch (error) {
+    row.activityStatus = status === 0 ? 1 : 0;
+    console.error(error);
+  } finally {
+    loading.value = false;
   }
-  await proxy?.$modal.confirm(msg);
-  loading.value = true;
-  await updateDefinitionState(row.id).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('操作成功');
-};
-/** 流程定义转换为模型 */
-const handleConvertToModel = async (row: ProcessDefinitionVO) => {
-  await proxy?.$modal.confirm('是否确认转换流程定义key为【' + row.key + '】的数据项?');
-  await convertToModel(row.id).finally(() => (loading.value = false));
-  getList();
-  proxy?.$modal.msgSuccess('操作成功');
 };
 
 //上传文件前的钩子
@@ -456,12 +395,12 @@ const handlerBeforeUpload = () => {
   }
 };
 //部署文件
-const handerDeployProcessFile = (data: UploadRequestOptions): XMLHttpRequest => {
+const handlerImportDefinition = (data: UploadRequestOptions): XMLHttpRequest => {
   let formData = new FormData();
   uploadDialogLoading.value = true;
   formData.append('file', data.file);
-  formData.append('categoryCode', selectCategory.value);
-  deployProcessFile(formData)
+  formData.append('category', selectCategory.value);
+  importDef(formData)
     .then(() => {
       uploadDialog.visible = false;
       proxy?.$modal.msgSuccess('部署成功');
@@ -472,46 +411,91 @@ const handerDeployProcessFile = (data: UploadRequestOptions): XMLHttpRequest =>
     });
   return;
 };
-//打开流程定义配置
-const handleDefinitionConfigOpen = async (row: ProcessDefinitionVO) => {
-  definitionConfigDialog.visible = true;
-  definitionConfigForm.value.processKey = row.key;
-  definitionConfigForm.value.definitionId = row.id;
-  definitionConfigForm.value.version = row.version;
-  const resp = await getByDefId(row.id);
-  if (resp.data) {
-    definitionConfigForm.value = resp.data;
-  } else {
-    definitionConfigForm.value.tableName = undefined;
-    definitionConfigForm.value.remark = undefined;
-  }
+/**
+ * 设计流程
+ * @param row
+ */
+const design = async (row: FlowDefinitionVo) => {
+  proxy.$router.push({
+    path: `/workflow/design/index`,
+    query: {
+      definitionId: row.id,
+      disabled: false
+    }
+  });
+};
+
+/**
+ * 查看流程
+ * @param row
+ */
+const designView = async (row: FlowDefinitionVo) => {
+  proxy.$router.push({
+    path: `/workflow/design/index`,
+    query: {
+      definitionId: row.id,
+      disabled: true
+    }
+  });
 };
-//保存表单
-const handlerSaveForm = async () => {
-  getByTableNameNotDefId(definitionConfigForm.value.tableName, definitionConfigForm.value.definitionId).then((res) => {
-    if (res.data && res.data.length > 0) {
-      ElMessageBox.confirm('表名已被【' + res.data[0].processKey + '】版本v' + res.data[0].version + '.0绑定确认后将会删除绑定的流程KEY!', '提示', {
-        confirmButtonText: '确认',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        saveOrUpdate(definitionConfigForm.value).then((resp) => {
-          if (resp.code === 200) {
-            proxy?.$modal.msgSuccess('操作成功');
-            definitionConfigDialog.visible = false;
-            getList();
-          }
-        });
-      });
-    } else {
-      saveOrUpdate(definitionConfigForm.value).then((resp) => {
-        if (resp.code === 200) {
-          proxy?.$modal.msgSuccess('操作成功');
-          definitionConfigDialog.visible = false;
-          getList();
-        }
-      });
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  defFormRef.value?.resetFields();
+};
+/**
+ * 新增
+ */
+const handleAdd = async () => {
+  reset();
+  modelDialog.visible = true;
+  modelDialog.title = '新增流程';
+};
+/** 修改按钮操作 */
+const handleUpdate = async (row?: FlowDefinitionVo) => {
+  reset();
+  const id = row?.id || ids.value[0];
+  const res = await getInfo(id);
+  Object.assign(form.value, res.data);
+  modelDialog.visible = true;
+  modelDialog.title = '修改流程';
+};
+
+const handleSubmit = async () => {
+  defFormRef.value.validate(async (valid: boolean) => {
+    if (valid) {
+      loading.value = true;
+      if (form.value.id) {
+        await edit(form.value).finally(() => loading.value = false);
+      } else {
+        await add(form.value).finally(() => loading.value = false);
+      }
+      proxy?.$modal.msgSuccess('操作成功');
+      modelDialog.visible = false;
+      handleQuery();
     }
   });
 };
+//复制
+const handleCopyDef = async (row: FlowDefinitionVo) => {
+  ElMessageBox.confirm(`是否确认复制【${row.flowCode}】版本为【${row.version}】的流程定义!`, '提示', {
+    confirmButtonText: '确认',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    loading.value = true;
+    copy(row.id).then((resp) => {
+      if (resp.code === 200) {
+        proxy?.$modal.msgSuccess('操作成功');
+        activeName.value = "1"
+        handleQuery();
+      }
+    }).finally(() => loading.value = false);
+  });
+};
+
+/** 导出按钮操作 */
+const handleExportDef = () => {
+  proxy?.download(`/workflow/definition/exportDef/${ids.value[0]}`, {}, `${flowCodeList.value[0]}.xml`);
+};
 </script>

+ 205 - 152
src/views/workflow/processInstance/index.vue

@@ -10,7 +10,7 @@
             class="mt-2"
             node-key="id"
             :data="categoryOptions"
-            :props="{ label: 'categoryName', children: 'children' }"
+            :props="{ label: 'label', children: 'children' }"
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             highlight-current
@@ -20,23 +20,31 @@
         </el-card>
       </el-col>
       <el-col :lg="20" :xs="24">
-        <div class="mb-[10px]">
-          <el-card shadow="hover" class="text-center">
-            <el-radio-group v-model="tab" @change="changeTab(tab)">
-              <el-radio-button value="running">运行中</el-radio-button>
-              <el-radio-button value="finish">已完成</el-radio-button>
-            </el-radio-group>
-          </el-card>
-        </div>
+        <!--        <div class="mb-[10px]">
+                  <el-card shadow="hover" class="text-center">
+                    <el-radio-group v-model="tab" @change="changeTab(tab)">
+                      <el-radio-button value="running">运行中</el-radio-button>
+                      <el-radio-button value="finish">已完成</el-radio-button>
+                    </el-radio-group>
+                  </el-card>
+                </div>-->
         <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
           <div v-show="showSearch" class="mb-[10px]">
             <el-card shadow="hover">
-              <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
-                <el-form-item label="流程定义名称" prop="name">
-                  <el-input v-model="queryParams.name" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
+              <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
+                <el-form-item>
+                  <el-badge :value="userSelectCount" :max="10" class="item">
+                    <el-button type="primary" @click="openUserSelect">选择申请人</el-button>
+                  </el-badge>
+                </el-form-item>
+                <el-form-item label="任务名称" prop="nodeName">
+                  <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
+                </el-form-item>
+                <el-form-item label="流程定义名称" label-width="100" prop="flowName">
+                  <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
                 </el-form-item>
-                <el-form-item label="流程定义KEY" prop="key">
-                  <el-input v-model="queryParams.key" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" />
+                <el-form-item label="流程定义编码" label-width="100" prop="flowCode">
+                  <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
                 </el-form-item>
                 <el-form-item>
                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -55,66 +63,74 @@
               <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
             </el-row>
           </template>
-
-          <el-table v-loading="loading" border :data="processInstanceList" @selection-change="handleSelectionChange">
-            <el-table-column type="selection" width="55" align="center" />
-            <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-            <el-table-column :show-overflow-tooltip="true" align="center" label="流程定义名称">
-              <template #default="scope">
-                <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column>
-            <el-table-column align="center" prop="processDefinitionVersion" label="版本号" width="90">
-              <template #default="scope"> v{{ scope.row.processDefinitionVersion }}.0</template>
-            </el-table-column>
-            <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="状态" min-width="70">
-              <template #default="scope">
-                <el-tag v-if="!scope.row.isSuspended" type="success">激活</el-tag>
-                <el-tag v-else type="danger">挂起</el-tag>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" label="流程状态" min-width="70">
-              <template #default="scope">
-                <dict-tag :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" prop="startTime" label="启动时间" width="160"></el-table-column>
-            <el-table-column v-if="tab === 'finish'" align="center" prop="endTime" label="结束时间" width="160"></el-table-column>
-            <el-table-column label="操作" align="center" :width="130">
-              <template #default="scope">
-                <el-row v-if="tab === 'running'" :gutter="10" class="mb8">
-                  <el-col :span="1.5">
-                    <el-popover :ref="`popoverRef${scope.$index}`" trigger="click" placement="left" :width="300">
-                      <el-input v-model="deleteReason" resize="none" :rows="3" type="textarea" placeholder="请输入作废原因" />
-                      <div style="text-align: right; margin: 5px 0px 0px 0px">
-                        <el-button size="small" text @click="cancelPopover(scope.$index)">取消</el-button>
-                        <el-button size="small" type="primary" @click="handleInvalid(scope.row)">确认</el-button>
-                      </div>
-                      <template #reference>
-                        <el-button link type="primary" size="small" icon="CircleClose">作废</el-button>
-                      </template>
-                    </el-popover>
-                  </el-col>
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
-                  </el-col>
-                </el-row>
-                <el-row :gutter="10" class="mb8">
-                  <el-col :span="1.5">
-                    <el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
-                  </el-col>
-                </el-row>
-              </template>
-            </el-table-column>
-          </el-table>
-          <pagination
-            v-show="total > 0"
-            v-model:page="queryParams.pageNum"
-            v-model:limit="queryParams.pageSize"
-            :total="total"
-            @pagination="handleQuery"
-          />
+          <el-tabs v-model="tab" @tab-click="changeTab">
+            <el-tab-pane name="running" label="运行中"></el-tab-pane>
+            <el-tab-pane name="finish" label="已完成"></el-tab-pane>
+            <el-table v-loading="loading" border :data="processInstanceList" @selection-change="handleSelectionChange">
+              <el-table-column type="selection" width="55" align="center" />
+              <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
+              <el-table-column :show-overflow-tooltip="true" align="center" label="流程定义名称">
+                <template #default="scope">
+                  <span>{{ scope.row.flowName }}v{{ scope.row.version }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
+              <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
+              <el-table-column align="center" prop="createByName" label="申请人"></el-table-column>
+              <el-table-column align="center" prop="version" label="版本号" width="90">
+                <template #default="scope"> v{{ scope.row.version }}.0</template>
+              </el-table-column>
+              <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="状态" min-width="70">
+                <template #default="scope">
+                  <el-tag v-if="!scope.row.isSuspended" type="success">激活</el-tag>
+                  <el-tag v-else type="danger">挂起</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column align="center" label="流程状态" min-width="70">
+                <template #default="scope">
+                  <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
+                </template>
+              </el-table-column>
+              <el-table-column align="center" prop="createTime" label="启动时间" width="160"></el-table-column>
+              <el-table-column v-if="tab === 'finish'" align="center" prop="updateTime" label="结束时间" width="160"></el-table-column>
+              <el-table-column label="操作" align="center" :width="162">
+                <template #default="scope">
+                  <el-row v-if="tab === 'running'" :gutter="10" class="mb8">
+                    <el-col :span="1.5">
+                      <el-popover :ref="`popoverRef${scope.$index}`" trigger="click" placement="left" :width="300">
+                        <el-input v-model="deleteReason" resize="none" :rows="3" type="textarea" placeholder="请输入作废原因" />
+                        <div style="text-align: right; margin: 5px 0px 0px 0px">
+                          <el-button size="small" text @click="cancelPopover(scope.$index)">取消</el-button>
+                          <el-button size="small" type="primary" @click="handleInvalid(scope.row)">确认</el-button>
+                        </div>
+                        <template #reference>
+                          <el-button type="danger" size="small" icon="CircleClose">作废</el-button>
+                        </template>
+                      </el-popover>
+                    </el-col>
+                    <el-col :span="1.5">
+                      <el-button type="danger" size="small" icon="Delete" @click="handleDelete(scope.row)">删除 </el-button>
+                    </el-col>
+                  </el-row>
+                  <el-row :gutter="10" class="mb8">
+                    <el-col :span="1.5">
+                      <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
+                    </el-col>
+                    <el-col :span="1.5">
+                      <el-button type="primary" size="small" icon="Document" @click="handleInstanceVariable(scope.row)"> 变量 </el-button>
+                    </el-col>
+                  </el-row>
+                </template>
+              </el-table-column>
+            </el-table>
+            <pagination
+              v-show="total > 0"
+              v-model:page="queryParams.pageNum"
+              v-model:limit="queryParams.pageSize"
+              :total="total"
+              @pagination="handleQuery"
+            />
+          </el-tabs>
         </el-card>
       </el-col>
     </el-row>
@@ -122,6 +138,7 @@
       <el-table v-loading="loading" :data="processDefinitionHistoryList">
         <el-table-column fixed align="center" type="index" label="序号" width="60"></el-table-column>
         <el-table-column fixed align="center" prop="name" label="流程定义名称"></el-table-column>
+        <el-table-column fixed align="center" prop="nodeName" label="任务名称"></el-table-column>
         <el-table-column align="center" prop="key" label="标识Key"></el-table-column>
         <el-table-column align="center" prop="version" label="版本号" width="90">
           <template #default="scope"> v{{ scope.row.version }}.0</template>
@@ -133,42 +150,55 @@
           </template>
         </el-table-column>
         <el-table-column align="center" prop="deploymentTime" label="部署时间" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column fixed="right" label="操作" align="center" width="200" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-button link type="primary" size="small" icon="Sort" @click="handleChange(scope.row.id)">切换</el-button>
-          </template>
-        </el-table-column>
       </el-table>
     </el-dialog>
+    <!-- 流程变量开始 -->
+    <el-dialog v-model="variableVisible" draggable title="流程变量" width="60%" :close-on-click-modal="false">
+      <el-card v-loading="variableLoading" class="box-card">
+        <template #header>
+          <div class="clearfix">
+            <span
+              >流程定义名称:<el-tag>{{ processDefinitionName }}</el-tag></span
+            >
+          </div>
+        </template>
+        <div class="max-h-500px overflow-y-auto">
+          <VueJsonPretty :data="formatToJsonObject(variables)" />
+        </div>
+      </el-card>
+    </el-dialog>
+    <!-- 流程变量结束 -->
+
+    <!-- 申请人 -->
+    <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
   </div>
 </template>
 
 <script lang="ts" setup>
-import {
-  getPageByRunning,
-  getPageByFinish,
-  deleteRunAndHisInstance,
-  deleteFinishAndHisInstance,
-  deleteRunInstance
-} from '@/api/workflow/processInstance';
-import { getListByKey, migrationDefinition } from '@/api/workflow/processDefinition';
-import { listCategory } from '@/api/workflow/category';
-import { CategoryVO } from '@/api/workflow/category/types';
-import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types';
+import { pageByRunning, pageByFinish, deleteByInstanceIds, instanceVariable, invalid } from '@/api/workflow/instance';
+import { categoryTree } from '@/api/workflow/category';
+import { CategoryTreeVO } from '@/api/workflow/category/types';
+import { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
+import VueJsonPretty from 'vue-json-pretty';
+import 'vue-json-pretty/lib/styles.css';
+import UserSelect from '@/components/UserSelect/index.vue';
 //审批记录组件
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
 const queryFormRef = ref<ElFormInstance>();
 const categoryTreeRef = ref<ElTreeInstance>();
+import { ref } from 'vue';
+import { UserVO } from '@/api/system/user/types';
 
+const userSelectRef = ref<InstanceType<typeof UserSelect>>();
 // 遮罩层
 const loading = ref(true);
 // 选中数组
 const ids = ref<Array<any>>([]);
-// 选中业务id数组
-const businessKeys = ref<Array<any>>([]);
+// 选中实例id数组
+const instanceIds = ref<Array<number | string>>([]);
 // 非单个禁用
 const single = ref(true);
 // 非多个禁用
@@ -177,10 +207,15 @@ const multiple = ref(true);
 const showSearch = ref(true);
 // 总条数
 const total = ref(0);
-// 流程定义id
-const processDefinitionId = ref<string>('');
+
+// 流程变量是否显示
+const variableVisible = ref(false);
+const variableLoading = ref(true);
+const variables = ref<string>('');
+//流程定义名称
+const processDefinitionName = ref();
 // 模型定义表格数据
-const processInstanceList = ref<ProcessInstanceVO[]>([]);
+const processInstanceList = ref<FlowInstanceVO[]>([]);
 const processDefinitionHistoryList = ref<Array<any>>([]);
 const categoryOptions = ref<CategoryOption[]>([]);
 const categoryName = ref('');
@@ -191,7 +226,7 @@ const processDefinitionDialog = reactive<DialogOption>({
 });
 
 type CategoryOption = {
-  categoryCode: string;
+  id: string;
   categoryName: string;
   children?: CategoryOption[];
 };
@@ -199,20 +234,27 @@ type CategoryOption = {
 const tab = ref('running');
 // 作废原因
 const deleteReason = ref('');
+
+//申请人id
+const selectUserIds = ref<Array<number | string>>([]);
+//申请人选择数量
+const userSelectCount = ref(0);
 // 查询参数
-const queryParams = ref<ProcessInstanceQuery>({
+const queryParams = ref<FlowInstanceQuery>({
   pageNum: 1,
   pageSize: 10,
-  name: undefined,
-  key: undefined,
-  categoryCode: undefined
+  nodeName: undefined,
+  flowName: undefined,
+  flowCode: undefined,
+  createByIds: [],
+  category: undefined
 });
 
 /** 节点单击事件 */
-const handleNodeClick = (data: CategoryVO) => {
-  queryParams.value.categoryCode = data.categoryCode;
-  if (data.categoryCode === 'ALL') {
-    queryParams.value.categoryCode = '';
+const handleNodeClick = (data: CategoryTreeVO) => {
+  queryParams.value.category = data.id;
+  if (data.id === '0') {
+    queryParams.value.category = '';
   }
   handleQuery();
 };
@@ -233,11 +275,8 @@ watchEffect(
 
 /** 查询流程分类下拉树结构 */
 const getTreeselect = async () => {
-  const res = await listCategory();
-  categoryOptions.value = [];
-  const data: CategoryOption = { categoryCode: 'ALL', categoryName: '顶级节点', children: [] };
-  data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId');
-  categoryOptions.value.push(data);
+  const res = await categoryTree();
+  categoryOptions.value = res.data;
 };
 
 /** 搜索按钮操作 */
@@ -251,22 +290,24 @@ const handleQuery = () => {
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
-  queryParams.value.categoryCode = '';
+  queryParams.value.category = '';
   queryParams.value.pageNum = 1;
   queryParams.value.pageSize = 10;
+  queryParams.value.createByIds = [];
+  userSelectCount.value = 0;
   handleQuery();
 };
 // 多选框选中数据
-const handleSelectionChange = (selection: ProcessInstanceVO[]) => {
+const handleSelectionChange = (selection: FlowInstanceVO[]) => {
   ids.value = selection.map((item: any) => item.id);
-  businessKeys.value = selection.map((item: any) => item.businessKey);
+  instanceIds.value = selection.map((item: FlowInstanceVO) => item.id);
   single.value = selection.length !== 1;
   multiple.value = !selection.length;
 };
 //分页
 const getProcessInstanceRunningList = () => {
   loading.value = true;
-  getPageByRunning(queryParams.value).then((resp) => {
+  pageByRunning(queryParams.value).then((resp) => {
     processInstanceList.value = resp.rows;
     total.value = resp.total;
     loading.value = false;
@@ -275,7 +316,7 @@ const getProcessInstanceRunningList = () => {
 //分页
 const getProcessInstanceFinishList = () => {
   loading.value = true;
-  getPageByFinish(queryParams.value).then((resp) => {
+  pageByFinish(queryParams.value).then((resp) => {
     processInstanceList.value = resp.rows;
     total.value = resp.total;
     loading.value = false;
@@ -283,15 +324,15 @@ const getProcessInstanceFinishList = () => {
 };
 
 /** 删除按钮操作 */
-const handleDelete = async (row: any) => {
-  const businessKey = row.businessKey || businessKeys.value;
-  await proxy?.$modal.confirm('是否确认删除业务id为【' + businessKey + '】的数据项?');
+const handleDelete = async (row: FlowInstanceVO) => {
+  const instanceIdList = row.id || instanceIds.value;
+  await proxy?.$modal.confirm('是否确认删除?');
   loading.value = true;
   if ('running' === tab.value) {
-    await deleteRunAndHisInstance(businessKey).finally(() => (loading.value = false));
+    await deleteByInstanceIds(instanceIdList).finally(() => (loading.value = false));
     getProcessInstanceRunningList();
   } else {
-    await deleteFinishAndHisInstance(businessKey).finally(() => (loading.value = false));
+    await deleteByInstanceIds(instanceIdList).finally(() => (loading.value = false));
     getProcessInstanceFinishList();
   }
   proxy?.$modal.msgSuccess('删除成功');
@@ -299,22 +340,22 @@ const handleDelete = async (row: any) => {
 const changeTab = async (data: string) => {
   processInstanceList.value = [];
   queryParams.value.pageNum = 1;
-  if ('running' === data) {
+  if ('running' === data.paneName) {
     getProcessInstanceRunningList();
   } else {
     getProcessInstanceFinishList();
   }
 };
 /** 作废按钮操作 */
-const handleInvalid = async (row: ProcessInstanceVO) => {
-  await proxy?.$modal.confirm('是否确认作废业务id为【' + row.businessKey + '】的数据项?');
+const handleInvalid = async (row: FlowInstanceVO) => {
+  await proxy?.$modal.confirm('是否确认作废?');
   loading.value = true;
   if ('running' === tab.value) {
     let param = {
-      businessKey: row.businessKey,
-      deleteReason: deleteReason.value
+      id: row.id,
+      comment: deleteReason.value
     };
-    await deleteRunInstance(param).finally(() => (loading.value = false));
+    await invalid(param).finally(() => (loading.value = false));
     getProcessInstanceRunningList();
     proxy?.$modal.msgSuccess('操作成功');
   }
@@ -322,41 +363,53 @@ const handleInvalid = async (row: ProcessInstanceVO) => {
 const cancelPopover = async (index: any) => {
   (proxy?.$refs[`popoverRef${index}`] as any).hide(); //关闭弹窗
 };
-//获取流程定义
-const getProcessDefinitionHitoryList = (id: string, key: string) => {
-  processDefinitionDialog.visible = true;
-  processDefinitionId.value = id;
-  loading.value = true;
-  getListByKey(key).then((resp) => {
-    if (resp.data && resp.data.length > 0) {
-      processDefinitionHistoryList.value = resp.data.filter((item: any) => item.id !== id);
-    }
-    loading.value = false;
-  });
-};
-//切换流程版本
-const handleChange = async (id: string) => {
-  await proxy?.$modal.confirm('是否确认切换?');
-  loading.value = true;
-  migrationDefinition(processDefinitionId.value, id).then((resp) => {
-    proxy?.$modal.msgSuccess('操作成功');
-    getProcessInstanceRunningList();
-    processDefinitionDialog.visible = false;
-    loading.value = false;
-  });
-};
 /** 查看按钮操作 */
 const handleView = (row) => {
   const routerJumpVo = reactive<RouterJumpVo>({
-    wfDefinitionConfigVo: row.wfDefinitionConfigVo,
-    wfNodeConfigVo: row.wfNodeConfigVo,
-    businessKey: row.businessKey,
+    businessId: row.businessId,
     taskId: row.id,
-    type: 'view'
+    type: 'view',
+    formCustom: row.formCustom,
+    formPath: row.formPath
   });
   workflowCommon.routerJump(routerJumpVo, proxy);
 };
 
+//查询流程变量
+const handleInstanceVariable = async (row: FlowInstanceVO) => {
+  variableLoading.value = true;
+  variableVisible.value = true;
+  processDefinitionName.value = row.flowName;
+  let data = await instanceVariable(row.id);
+  variables.value = data.data.variable;
+  variableLoading.value = false;
+};
+
+/**
+ * json转为对象
+ * @param data 原始数据
+ */
+function formatToJsonObject(data: string) {
+  try {
+    return JSON.parse(data);
+  } catch (error) {
+    return data;
+  }
+}
+
+//打开申请人选择
+const openUserSelect = () => {
+  userSelectRef.value.open();
+};
+//确认选择申请人
+const userSelectCallBack = (data: UserVO[]) => {
+  userSelectCount.value = 0;
+  if (data && data.length > 0) {
+    userSelectCount.value = data.length;
+    selectUserIds.value = data.map((item) => item.userId);
+    queryParams.value.createByIds = selectUserIds.value;
+  }
+};
 onMounted(() => {
   getProcessInstanceRunningList();
   getTreeselect();

+ 118 - 153
src/views/workflow/task/allTaskWaiting.vue

@@ -1,25 +1,19 @@
 <template>
   <div class="p-2">
-    <div class="mb-[10px]">
-      <el-card shadow="hover" class="text-center">
-        <el-radio-group v-model="tab" @change="changeTab(tab)">
-          <el-radio-button value="waiting">待办任务</el-radio-button>
-          <el-radio-button value="finish">已办任务</el-radio-button>
-        </el-radio-group>
-      </el-card>
-    </div>
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="任务名称" prop="name">
-              <el-input v-model="queryParams.name" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
+            <el-form-item>
+              <el-badge :value="userSelectCount" :max="10" class="item">
+                <el-button type="primary" @click="openUserSelect">选择申请人</el-button>
+              </el-badge>
             </el-form-item>
-            <el-form-item label="流程定义名称" label-width="100" prop="processDefinitionName">
-              <el-input v-model="queryParams.processDefinitionName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
+            <el-form-item label="任务名称" prop="nodeName">
+              <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="流程定义KEY" label-width="100" prop="processDefinitionKey">
-              <el-input v-model="queryParams.processDefinitionKey" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" />
+            <el-form-item label="流程定义名称" label-width="100" prop="flowName">
+              <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -32,122 +26,103 @@
     <el-card shadow="hover">
       <template #header>
         <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Edit" :disabled="multiple" @click="handleUpdate">修改办理人</el-button>
+          <el-col :span="1.5" v-if="tab === 'waiting'">
+            <el-button type="primary" plain icon="Edit" :disabled="multiple" @click="handleUpdate">修改办理人 </el-button>
           </el-col>
           <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
         </el-row>
       </template>
-
-      <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" align="center" label="流程定义名称">
-          <template #default="scope">
-            <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column>
-        <el-table-column align="center" prop="name" label="任务名称"></el-table-column>
-        <el-table-column align="center" prop="assigneeName" label="办理人">
-          <template v-if="tab === 'waiting'" #default="scope">
-            <template v-if="scope.row.participantVo && scope.row.assignee === null">
-              <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success">
-                {{ item }}
-              </el-tag>
+      <el-tabs v-model="tab" @tab-click="changeTab">
+        <el-tab-pane name="waiting" label="待办任务"> </el-tab-pane>
+        <el-tab-pane name="finish" label="已办任务"> </el-tab-pane>
+        <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
+          <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"></el-table-column>
+          <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
+          <el-table-column align="center" prop="version" label="版本号" width="90">
+            <template #default="scope"> v{{ scope.row.version }}.0</template>
+          </el-table-column>
+          <el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
+          <el-table-column align="center" prop="createByName" label="申请人"></el-table-column>
+          <el-table-column align="center" label="办理人">
+            <template #default="scope">
+              <template v-if="tab === 'waiting'">
+                <template v-if="scope.row.assigneeNames">
+                  <el-tag v-for="(name, index) in scope.row.assigneeNames.split(',')" :key="index" type="success">
+                    {{ name }}
+                  </el-tag>
+                </template>
+                <template v-else>
+                  <el-tag type="success"> 无</el-tag>
+                </template>
+              </template>
+              <template v-else>
+                <el-tag type="success"> {{ scope.row.approveName }}</el-tag>
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" label="流程状态" prop="flowStatus" min-width="70">
+            <template #default="scope">
+              <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
             </template>
-            <template v-else>
-              <el-tag type="success">
-                {{ scope.row.assigneeName || '无' }}
-              </el-tag>
+          </el-table-column>
+          <el-table-column v-if="tab === 'finish'" align="center" label="任务状态" prop="flowTaskStatus" min-width="70">
+            <template #default="scope">
+              <dict-tag :options="wf_task_status" :value="scope.row.flowTaskStatus"></dict-tag>
             </template>
-          </template>
-          <template v-else-if="tab === 'finish'" #default="scope">
-            <el-tag type="success">
-              {{ scope.row.assigneeName || '无' }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" label="流程状态" min-width="70">
-          <template #default="scope">
-            <dict-tag v-if="tab === 'waiting'" :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag>
-            <el-tag v-else type="success">已完成</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column v-if="tab === 'waiting'" align="center" prop="createTime" label="创建时间" width="160"></el-table-column>
-        <el-table-column v-if="tab === 'finish'" align="center" prop="startTime" label="创建时间" width="160"></el-table-column>
-        <el-table-column label="操作" align="center" :width="tab === 'finish' ? '80' : '151'">
-          <template #default="scope">
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
-              </el-col>
-              <el-col v-if="tab === 'waiting'" :span="1.5">
-                <el-button link type="primary" size="small" icon="Document" @click="handleInstanceVariable(scope.row)">流程变量</el-button>
-              </el-col>
-            </el-row>
-            <el-row v-if="scope.row.multiInstance" :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button link type="primary" size="small" icon="Remove" @click="deleteMultiInstanceUser(scope.row)">减签</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button link type="primary" size="small" icon="CirclePlus" @click="addMultiInstanceUser(scope.row)">加签</el-button>
-              </el-col>
-            </el-row>
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination
-        v-show="total > 0"
-        v-model:page="queryParams.pageNum"
-        v-model:limit="queryParams.pageSize"
-        :total="total"
-        @pagination="handleQuery"
-      />
+          </el-table-column>
+          <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column>
+          <el-table-column label="操作" align="center" :width="tab === 'finish' ? '88' : '188'">
+            <template #default="scope">
+              <el-row :gutter="10" class="mb8">
+                <el-col :span="1.5" v-if="tab === 'waiting' || tab === 'finish'">
+                  <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
+                </el-col>
+                <el-col :span="1.5" v-if="tab === 'waiting'">
+                  <el-button type="primary" size="small" icon="Setting" @click="handleMeddle(scope.row)">流程干预 </el-button>
+                </el-col>
+              </el-row>
+            </template>
+          </el-table-column>
+        </el-table>
+        <pagination
+          v-show="total > 0"
+          v-model:page="queryParams.pageNum"
+          v-model:limit="queryParams.pageSize"
+          :total="total"
+          @pagination="handleQuery"
+        />
+      </el-tabs>
     </el-card>
-    <!-- 加签组件 -->
-    <multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback="handleQuery" />
     <!-- 选人组件 -->
     <UserSelect ref="userSelectRef" :multiple="false" @confirm-call-back="submitCallback"></UserSelect>
-    <!-- 流程变量开始 -->
-    <el-dialog v-model="variableVisible" draggable title="流程变量" width="60%" :close-on-click-modal="false">
-      <el-card v-loading="variableLoading" class="box-card">
-        <template #header>
-          <div class="clearfix">
-            <span
-              >流程定义名称:<el-tag>{{ processDefinitionName }}</el-tag></span
-            >
-          </div>
-        </template>
-        <div v-for="(v, index) in variableList" :key="index">
-          <el-form v-if="v.key !== '_FLOWABLE_SKIP_EXPRESSION_ENABLED'" :label-position="'right'" label-width="150px">
-            <el-form-item :label="v.key + ':'">
-              {{ v.value }}
-            </el-form-item>
-          </el-form>
-        </div>
-      </el-card>
-    </el-dialog>
-    <!-- 流程变量结束 -->
+    <!-- 选人组件 -->
+    <processMeddle ref="processMeddleRef" @submitCallback="getWaitingList"></processMeddle>
+    <!-- 申请人 -->
+    <UserSelect ref="applyUserSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { getPageByAllTaskWait, getPageByAllTaskFinish, updateAssignee, getInstanceVariable } from '@/api/workflow/task';
-import MultiInstanceUser from '@/components/Process/multiInstanceUser.vue';
+import { pageByAllTaskWait, pageByAllTaskFinish, updateAssignee } from '@/api/workflow/task';
 import UserSelect from '@/components/UserSelect';
-import { TaskQuery, TaskVO, VariableVo } from '@/api/workflow/task/types';
+import { TaskQuery } from '@/api/workflow/task/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
-//审批记录组件
-//加签组件
-const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>();
+import processMeddle from '@/components/Process/processMeddle';
+import { UserVO } from '@/api/system/user/types';
+import { TabsPaneContext } from 'element-plus';
 //选人组件
 const userSelectRef = ref<InstanceType<typeof UserSelect>>();
-
+//流程干预组件
+const processMeddleRef = ref<InstanceType<typeof processMeddle>>();
+//选人组件
+const applyUserSelectRef = ref<InstanceType<typeof UserSelect>>();
 const queryFormRef = ref<ElFormInstance>();
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
+const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status'));
 // 遮罩层
 const loading = ref(true);
 // 选中数组
@@ -163,40 +138,21 @@ const total = ref(0);
 // 模型定义表格数据
 const taskList = ref([]);
 const title = ref('');
-// 流程变量是否显示
-const variableVisible = ref(false);
-const variableLoading = ref(true);
-// 流程变量
-const variableList = ref<VariableVo>({
-  key: '',
-  value: ''
-});
-//流程定义名称
-const processDefinitionName = ref();
+//申请人id
+const selectUserIds = ref<Array<number | string>>([]);
+//申请人选择数量
+const userSelectCount = ref(0);
 // 查询参数
 const queryParams = ref<TaskQuery>({
   pageNum: 1,
   pageSize: 10,
-  name: undefined,
-  processDefinitionName: undefined,
-  processDefinitionKey: undefined
+  nodeName: undefined,
+  flowName: undefined,
+  flowCode: undefined,
+  createByIds: []
 });
 const tab = ref('waiting');
 
-//加签
-const addMultiInstanceUser = (row: TaskVO) => {
-  if (multiInstanceUserRef.value) {
-    title.value = '加签人员';
-    multiInstanceUserRef.value.getAddMultiInstanceList(row.id, []);
-  }
-};
-//减签
-const deleteMultiInstanceUser = (row: TaskVO) => {
-  if (multiInstanceUserRef.value) {
-    title.value = '减签人员';
-    multiInstanceUserRef.value.getDeleteMultiInstanceList(row.id);
-  }
-};
 /** 搜索按钮操作 */
 const handleQuery = () => {
   if ('waiting' === tab.value) {
@@ -210,6 +166,8 @@ const resetQuery = () => {
   queryFormRef.value?.resetFields();
   queryParams.value.pageNum = 1;
   queryParams.value.pageSize = 10;
+  queryParams.value.createByIds = [];
+  userSelectCount.value = 0;
   handleQuery();
 };
 // 多选框选中数据
@@ -218,10 +176,10 @@ const handleSelectionChange = (selection: any) => {
   single.value = selection.length !== 1;
   multiple.value = !selection.length;
 };
-const changeTab = async (data: string) => {
+const changeTab = async (data: TabsPaneContext) => {
   taskList.value = [];
   queryParams.value.pageNum = 1;
-  if ('waiting' === data) {
+  if ('waiting' === data.paneName) {
     getWaitingList();
   } else {
     getFinishList();
@@ -230,7 +188,7 @@ const changeTab = async (data: string) => {
 //分页
 const getWaitingList = () => {
   loading.value = true;
-  getPageByAllTaskWait(queryParams.value).then((resp) => {
+  pageByAllTaskWait(queryParams.value).then((resp) => {
     taskList.value = resp.rows;
     total.value = resp.total;
     loading.value = false;
@@ -238,7 +196,7 @@ const getWaitingList = () => {
 };
 const getFinishList = () => {
   loading.value = true;
-  getPageByAllTaskFinish(queryParams.value).then((resp) => {
+  pageByAllTaskFinish(queryParams.value).then((resp) => {
     taskList.value = resp.rows;
     total.value = resp.total;
     loading.value = false;
@@ -260,26 +218,33 @@ const submitCallback = async (data) => {
     proxy?.$modal.msgWarning('请选择用户!');
   }
 };
-//查询流程变量
-const handleInstanceVariable = async (row: TaskVO) => {
-  variableLoading.value = true;
-  variableVisible.value = true;
-  processDefinitionName.value = row.processDefinitionName;
-  let data = await getInstanceVariable(row.id);
-  variableList.value = data.data;
-  variableLoading.value = false;
-};
 /** 查看按钮操作 */
 const handleView = (row) => {
   const routerJumpVo = reactive<RouterJumpVo>({
-    wfDefinitionConfigVo: row.wfDefinitionConfigVo,
-    wfNodeConfigVo: row.wfNodeConfigVo,
-    businessKey: row.businessKey,
+    businessId: row.businessId,
     taskId: row.id,
-    type: 'view'
+    type: 'view',
+    formCustom: row.formCustom,
+    formPath: row.formPath
   });
   workflowCommon.routerJump(routerJumpVo, proxy);
 };
+const handleMeddle = (row) => {
+  processMeddleRef.value.open(row.id);
+};
+//打开申请人选择
+const openUserSelect = () => {
+  applyUserSelectRef.value.open();
+};
+//确认选择申请人
+const userSelectCallBack = (data: UserVO[]) => {
+  userSelectCount.value = 0;
+  if (data && data.length > 0) {
+    userSelectCount.value = data.length;
+    selectUserIds.value = data.map((item) => item.userId);
+    queryParams.value.createByIds = selectUserIds.value;
+  }
+};
 onMounted(() => {
   getWaitingList();
 });

+ 64 - 74
src/views/workflow/task/myDocument.vue

@@ -10,7 +10,7 @@
             class="mt-2"
             node-key="id"
             :data="categoryOptions"
-            :props="{ label: 'categoryName', children: 'children' }"
+            :props="{ label: 'label', children: 'children' }"
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             highlight-current
@@ -24,8 +24,8 @@
           <div v-show="showSearch" class="mb-[10px]">
             <el-card shadow="hover">
               <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
-                <el-form-item label="流程定义名称" prop="name">
-                  <el-input v-model="queryParams.name" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
+                <el-form-item label="流程定义编码" prop="flowCode">
+                  <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
                 </el-form-item>
                 <el-form-item>
                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -46,14 +46,10 @@
             <el-table-column type="selection" width="55" align="center" />
             <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
             <el-table-column v-if="false" align="center" prop="id" label="id"></el-table-column>
-            <el-table-column :show-overflow-tooltip="true" align="center" label="流程定义名称">
-              <template #default="scope">
-                <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column>
-            <el-table-column align="center" prop="processDefinitionVersion" label="版本号" width="90">
-              <template #default="scope"> v{{ scope.row.processDefinitionVersion }}.0</template>
+            <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"> </el-table-column>
+            <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
+            <el-table-column align="center" prop="version" label="版本号" width="90">
+              <template #default="scope"> v{{ scope.row.version }}.0</template>
             </el-table-column>
             <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="状态" min-width="70">
               <template #default="scope">
@@ -63,33 +59,30 @@
             </el-table-column>
             <el-table-column align="center" label="流程状态" min-width="70">
               <template #default="scope">
-                <dict-tag :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag>
+                <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
               </template>
             </el-table-column>
-            <el-table-column align="center" prop="startTime" label="启动时间" width="160"></el-table-column>
-            <el-table-column v-if="tab === 'finish'" align="center" prop="endTime" label="结束时间" width="160"></el-table-column>
-            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+            <el-table-column align="center" prop="createTime" label="启动时间" width="160"></el-table-column>
+            <el-table-column label="操作" align="center" width="162">
               <template #default="scope">
-                <el-tooltip
-                  v-if="scope.row.businessStatus === 'draft' || scope.row.businessStatus === 'cancel' || scope.row.businessStatus === 'back'"
-                  content="修改"
-                  placement="top"
-                >
-                  <el-button link type="primary" icon="Edit" @click="handleOpen(scope.row, 'update')"></el-button>
-                </el-tooltip>
-                <el-tooltip
-                  v-if="scope.row.businessStatus === 'draft' || scope.row.businessStatus === 'cancel' || scope.row.businessStatus === 'back'"
-                  content="删除"
-                  placement="top"
-                >
-                  <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-                </el-tooltip>
-                <el-tooltip placement="top" content="查看">
-                  <el-button link type="primary" icon="View" @click="handleOpen(scope.row, 'view')"></el-button>
-                </el-tooltip>
-                <el-tooltip v-if="scope.row.businessStatus === 'waiting'" content="撤销" placement="top">
-                  <el-button link type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.businessKey)"></el-button>
-                </el-tooltip>
+                <el-row :gutter="10" class="mb8">
+                  <el-col :span="1.5" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'cancel' || scope.row.flowStatus === 'back'">
+                    <el-button type="primary" size="small" icon="Edit" @click="handleOpen(scope.row, 'update')">编辑</el-button>
+                  </el-col>
+                  <el-col :span="1.5" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'cancel' || scope.row.flowStatus === 'back'">
+                    <el-button type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
+                  </el-col>
+                </el-row>
+                <el-row :gutter="10" class="mb8">
+                  <el-col :span="1.5">
+                    <el-button type="primary" size="small" icon="View" @click="handleOpen(scope.row, 'view')">查看</el-button>
+                  </el-col>
+                  <el-col :span="1.5" v-if="scope.row.flowStatus === 'waiting'">
+                    <el-button type="primary" size="small" icon="Notification" @click="handleCancelProcessApply(scope.row.businessId)"
+                      >撤销</el-button
+                    >
+                  </el-col>
+                </el-row>
               </template>
             </el-table-column>
           </el-table>
@@ -109,10 +102,10 @@
 </template>
 
 <script lang="ts" setup>
-import { getPageByCurrent, deleteRunAndHisInstance, cancelProcessApply } from '@/api/workflow/processInstance';
-import { listCategory } from '@/api/workflow/category';
-import { CategoryVO } from '@/api/workflow/category/types';
-import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types';
+import { pageByCurrent, deleteByInstanceIds, cancelProcessApply } from '@/api/workflow/instance';
+import { categoryTree } from '@/api/workflow/category';
+import { CategoryTreeVO } from '@/api/workflow/category/types';
+import { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -123,7 +116,8 @@ const categoryTreeRef = ref<ElTreeInstance>();
 // 遮罩层
 const loading = ref(true);
 // 选中数组
-const businessKeys = ref<Array<any>>([]);
+const businessIds = ref<Array<number | string>>([]);
+const instanceIds = ref<Array<number | string>>([]);
 // 非单个禁用
 const single = ref(true);
 // 非多个禁用
@@ -133,24 +127,18 @@ const showSearch = ref(true);
 // 总条数
 const total = ref(0);
 // 模型定义表格数据
-const processInstanceList = ref<ProcessInstanceVO[]>([]);
+const processInstanceList = ref<FlowInstanceVO[]>([]);
 
-const categoryOptions = ref<CategoryOption[]>([]);
+const categoryOptions = ref<CategoryTreeVO[]>([]);
 const categoryName = ref('');
 
-interface CategoryOption {
-  categoryCode: string;
-  categoryName: string;
-  children?: CategoryOption[];
-}
-
 const tab = ref('running');
 // 查询参数
-const queryParams = ref<ProcessInstanceQuery>({
+const queryParams = ref<FlowInstanceQuery>({
   pageNum: 1,
   pageSize: 10,
-  name: undefined,
-  categoryCode: undefined
+  flowCode: undefined,
+  category: undefined
 });
 
 onMounted(() => {
@@ -159,10 +147,10 @@ onMounted(() => {
 });
 
 /** 节点单击事件 */
-const handleNodeClick = (data: CategoryVO) => {
-  queryParams.value.categoryCode = data.categoryCode;
-  if (data.categoryCode === 'ALL') {
-    queryParams.value.categoryCode = '';
+const handleNodeClick = (data: CategoryTreeVO) => {
+  queryParams.value.category = data.id;
+  if (data.id === '0') {
+    queryParams.value.category = '';
   }
   handleQuery();
 };
@@ -183,11 +171,8 @@ watchEffect(
 
 /** 查询流程分类下拉树结构 */
 const getTreeselect = async () => {
-  const res = await listCategory();
-  categoryOptions.value = [];
-  const data: CategoryOption = { categoryCode: 'ALL', categoryName: '顶级节点', children: [] };
-  data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId');
-  categoryOptions.value.push(data);
+  const res = await categoryTree();
+  categoryOptions.value = res.data;
 };
 
 /** 搜索按钮操作 */
@@ -197,21 +182,22 @@ const handleQuery = () => {
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
-  queryParams.value.categoryCode = '';
+  queryParams.value.category = '';
   queryParams.value.pageNum = 1;
   queryParams.value.pageSize = 10;
   handleQuery();
 };
 // 多选框选中数据
-const handleSelectionChange = (selection: ProcessInstanceVO[]) => {
-  businessKeys.value = selection.map((item: any) => item.businessKey);
+const handleSelectionChange = (selection: FlowInstanceVO[]) => {
+  businessIds.value = selection.map((item: any) => item.businessId);
+  instanceIds.value = selection.map((item: FlowInstanceVO) => item.id);
   single.value = selection.length !== 1;
   multiple.value = !selection.length;
 };
 //分页
 const getList = () => {
   loading.value = true;
-  getPageByCurrent(queryParams.value).then((resp) => {
+  pageByCurrent(queryParams.value).then((resp) => {
     processInstanceList.value = resp.rows;
     total.value = resp.total;
     loading.value = false;
@@ -219,23 +205,27 @@ const getList = () => {
 };
 
 /** 删除按钮操作 */
-const handleDelete = async (row: ProcessInstanceVO) => {
-  const businessKey = row.businessKey || businessKeys.value;
-  await proxy?.$modal.confirm('是否确认删除业务id为【' + businessKey + '】的数据项?');
+const handleDelete = async (row: FlowInstanceVO) => {
+  const instanceIdList = row.id || instanceIds.value;
+  await proxy?.$modal.confirm('是否确认删除?');
   loading.value = true;
   if ('running' === tab.value) {
-    await deleteRunAndHisInstance(businessKey).finally(() => (loading.value = false));
+    await deleteByInstanceIds(instanceIdList).finally(() => (loading.value = false));
     getList();
   }
   proxy?.$modal.msgSuccess('删除成功');
 };
 
 /** 撤销按钮操作 */
-const handleCancelProcessApply = async (businessKey: string) => {
+const handleCancelProcessApply = async (businessId: string) => {
   await proxy?.$modal.confirm('是否确认撤销当前单据?');
   loading.value = true;
   if ('running' === tab.value) {
-    await cancelProcessApply(businessKey).finally(() => (loading.value = false));
+    let data = {
+      businessId: businessId,
+      message: '申请人撤销流程!'
+    };
+    await cancelProcessApply(data).finally(() => (loading.value = false));
     getList();
   }
   proxy?.$modal.msgSuccess('撤销成功');
@@ -244,11 +234,11 @@ const handleCancelProcessApply = async (businessKey: string) => {
 //办理
 const handleOpen = async (row, type) => {
   const routerJumpVo = reactive<RouterJumpVo>({
-    wfDefinitionConfigVo: row.wfDefinitionConfigVo,
-    wfNodeConfigVo: row.wfNodeConfigVo,
-    businessKey: row.businessKey,
+    businessId: row.businessId,
     taskId: row.id,
-    type: type
+    type: type,
+    formCustom: row.formCustom,
+    formPath: row.formPath
   });
   workflowCommon.routerJump(routerJumpVo, proxy);
 };

+ 21 - 36
src/views/workflow/task/taskCopyList.vue

@@ -4,14 +4,14 @@
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="任务名称" prop="name">
-              <el-input v-model="queryParams.name" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
+            <el-form-item label="任务名称" prop="nodeName">
+              <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="流程定义名称" label-width="100" prop="processDefinitionName">
-              <el-input v-model="queryParams.processDefinitionName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
+            <el-form-item label="流程定义名称" label-width="100" prop="flowName">
+              <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="流程定义KEY" label-width="100" prop="processDefinitionKey">
-              <el-input v-model="queryParams.processDefinitionKey" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" />
+            <el-form-item label="流程定义编码" label-width="100" prop="flowCode">
+              <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -31,30 +31,15 @@
       <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" align="center" label="流程定义名称">
-          <template #default="scope">
-            <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column>
-        <el-table-column align="center" prop="name" label="任务名称"></el-table-column>
-        <el-table-column align="center" prop="assigneeName" label="办理人">
-          <template #default="scope">
-            <template v-if="scope.row.participantVo && scope.row.assignee === null">
-              <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success">
-                {{ item }}
-              </el-tag>
-            </template>
-            <template v-else>
-              <el-tag type="success">
-                {{ scope.row.assigneeName || '无' }}
-              </el-tag>
-            </template>
-          </template>
+        <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"></el-table-column>
+        <el-table-column align="center" prop="flowCode" label="流程定义KEY"></el-table-column>
+        <el-table-column align="center" prop="version" label="版本号" width="90">
+          <template #default="scope"> v{{ scope.row.version }}.0</template>
         </el-table-column>
+        <el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
         <el-table-column align="center" label="流程状态" min-width="70">
           <template #default="scope">
-            <dict-tag :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag>
+            <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
           </template>
         </el-table-column>
         <el-table-column label="操作" align="center" width="200">
@@ -75,7 +60,7 @@
 </template>
 
 <script lang="ts" setup>
-import { getPageByTaskCopy } from '@/api/workflow/task';
+import { pageByTaskCopy } from '@/api/workflow/task';
 import { TaskQuery } from '@/api/workflow/task/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
@@ -101,9 +86,9 @@ const taskList = ref([]);
 const queryParams = ref<TaskQuery>({
   pageNum: 1,
   pageSize: 10,
-  name: undefined,
-  processDefinitionName: undefined,
-  processDefinitionKey: undefined
+  nodeName: undefined,
+  flowName: undefined,
+  flowCode: undefined
 });
 /** 搜索按钮操作 */
 const handleQuery = () => {
@@ -125,7 +110,7 @@ const handleSelectionChange = (selection: any) => {
 //分页
 const getTaskCopyList = () => {
   loading.value = true;
-  getPageByTaskCopy(queryParams.value).then((resp) => {
+  pageByTaskCopy(queryParams.value).then((resp) => {
     taskList.value = resp.rows;
     total.value = resp.total;
     loading.value = false;
@@ -135,11 +120,11 @@ const getTaskCopyList = () => {
 /** 查看按钮操作 */
 const handleView = (row) => {
   const routerJumpVo = reactive<RouterJumpVo>({
-    wfDefinitionConfigVo: row.wfDefinitionConfigVo,
-    wfNodeConfigVo: row.wfNodeConfigVo,
-    businessKey: row.businessKey,
+    businessId: row.businessId,
     taskId: row.id,
-    type: 'view'
+    type: 'view',
+    formCustom: row.formCustom,
+    formPath: row.formPath
   });
   workflowCommon.routerJump(routerJumpVo, proxy);
 };

+ 70 - 27
src/views/workflow/task/taskFinish.vue

@@ -4,14 +4,19 @@
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="任务名称" prop="name">
-              <el-input v-model="queryParams.name" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
+            <el-form-item>
+              <el-badge :value="userSelectCount" :max="10" class="item">
+                <el-button type="primary" @click="openUserSelect">选择申请人</el-button>
+              </el-badge>
+            </el-form-item>
+            <el-form-item label="任务名称" prop="nodeName">
+              <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="流程定义名称" label-width="100" prop="processDefinitionName">
-              <el-input v-model="queryParams.processDefinitionName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
+            <el-form-item label="流程定义名称" label-width="100" prop="flowName">
+              <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="流程定义KEY" label-width="100" prop="processDefinitionKey">
-              <el-input v-model="queryParams.processDefinitionKey" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" />
+            <el-form-item label="流程定义编码" label-width="100" prop="flowCode">
+              <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -31,21 +36,31 @@
       <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" align="center" label="流程定义名称">
-          <template #default="scope">
-            <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span>
-          </template>
+        <el-table-column align="center" prop="flowName" label="流程定义名称"></el-table-column>
+        <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
+        <el-table-column align="center" prop="version" label="版本号" width="90">
+          <template #default="scope"> v{{ scope.row.version }}.0</template>
         </el-table-column>
-        <el-table-column align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column>
-        <el-table-column align="center" prop="name" label="任务名称"></el-table-column>
-        <el-table-column align="center" prop="assigneeName" label="办理人">
+        <el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
+        <el-table-column align="center" prop="createByName" label="申请人"></el-table-column>
+        <el-table-column align="center" prop="approverName" label="办理人">
           <template #default="scope">
             <el-tag type="success">
-              {{ scope.row.assigneeName || '无' }}
+              {{ scope.row.approveName || '无' }}
             </el-tag>
           </template>
         </el-table-column>
-        <el-table-column align="center" prop="startTime" label="创建时间" width="160"></el-table-column>
+        <el-table-column align="center" label="流程状态" prop="flowStatus" min-width="70">
+          <template #default="scope">
+            <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
+          </template>
+        </el-table-column>
+        <el-table-column align="center" label="任务状态" prop="flowTaskStatus" min-width="70">
+          <template #default="scope">
+            <dict-tag :options="wf_task_status" :value="scope.row.flowTaskStatus"></dict-tag>
+          </template>
+        </el-table-column>
+        <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column>
         <el-table-column label="操作" align="center" width="200">
           <template #default="scope">
             <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
@@ -60,17 +75,26 @@
         @pagination="handleQuery"
       />
     </el-card>
+    <!-- 申请人 -->
+    <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { getPageByTaskFinish } from '@/api/workflow/task';
-import { TaskQuery, TaskVO } from '@/api/workflow/task/types';
+import { pageByTaskFinish } from '@/api/workflow/task';
+import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
 //审批记录组件
 const queryFormRef = ref<ElFormInstance>();
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
+const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status'));
+import UserSelect from '@/components/UserSelect';
+import { ref } from 'vue';
+import { UserVO } from '@/api/system/user/types';
+
+const userSelectRef = ref<InstanceType<typeof UserSelect>>();
 // 遮罩层
 const loading = ref(true);
 // 选中数组
@@ -89,10 +113,15 @@ const taskList = ref([]);
 const queryParams = ref<TaskQuery>({
   pageNum: 1,
   pageSize: 10,
-  name: undefined,
-  processDefinitionName: undefined,
-  processDefinitionKey: undefined
+  nodeName: undefined,
+  flowName: undefined,
+  flowCode: undefined,
+  createByIds: []
 });
+//申请人id
+const selectUserIds = ref<Array<number | string>>([]);
+//申请人选择数量
+const userSelectCount = ref(0);
 /** 搜索按钮操作 */
 const handleQuery = () => {
   getFinishList();
@@ -102,6 +131,8 @@ const resetQuery = () => {
   queryFormRef.value?.resetFields();
   queryParams.value.pageNum = 1;
   queryParams.value.pageSize = 10;
+  queryParams.value.createByIds = [];
+  userSelectCount.value = 0;
   handleQuery();
 };
 // 多选框选中数据
@@ -112,24 +143,36 @@ const handleSelectionChange = (selection: any) => {
 };
 const getFinishList = () => {
   loading.value = true;
-  getPageByTaskFinish(queryParams.value).then((resp) => {
+  pageByTaskFinish(queryParams.value).then((resp) => {
     taskList.value = resp.rows;
     total.value = resp.total;
     loading.value = false;
   });
 };
 /** 查看按钮操作 */
-const handleView = (row: TaskVO) => {
+const handleView = (row: FlowTaskVO) => {
   const routerJumpVo = reactive<RouterJumpVo>({
-    wfDefinitionConfigVo: row.wfDefinitionConfigVo,
-    wfNodeConfigVo: row.wfNodeConfigVo,
-    businessKey: row.businessKey,
+    businessId: row.businessId,
     taskId: row.id,
-    type: 'view'
+    type: 'view',
+    formCustom: row.formCustom,
+    formPath: row.formPath
   });
   workflowCommon.routerJump(routerJumpVo, proxy);
 };
-
+//打开申请人选择
+const openUserSelect = () => {
+  userSelectRef.value.open();
+};
+//确认选择申请人
+const userSelectCallBack = (data: UserVO[]) => {
+  userSelectCount.value = 0;
+  if (data && data.length > 0) {
+    userSelectCount.value = data.length;
+    selectUserIds.value = data.map((item) => item.userId);
+    queryParams.value.createByIds = selectUserIds.value;
+  }
+};
 onMounted(() => {
   getFinishList();
 });

+ 62 - 33
src/views/workflow/task/taskWaiting.vue

@@ -4,14 +4,19 @@
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="任务名称" prop="name">
-              <el-input v-model="queryParams.name" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
+            <el-form-item>
+              <el-badge :value="userSelectCount" :max="10" class="item">
+                <el-button type="primary" @click="openUserSelect">选择申请人</el-button>
+              </el-badge>
+            </el-form-item>
+            <el-form-item label="任务名称" prop="nodeName">
+              <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="流程定义名称" label-width="100" prop="processDefinitionName">
-              <el-input v-model="queryParams.processDefinitionName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
+            <el-form-item label="流程定义名称" label-width="100" prop="flowName">
+              <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="流程定义KEY" label-width="100" prop="processDefinitionKey">
-              <el-input v-model="queryParams.processDefinitionKey" placeholder="请输入流程定义KEY" @keyup.enter="handleQuery" />
+            <el-form-item label="流程定义编码" label-width="100" prop="flowCode">
+              <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -31,30 +36,25 @@
       <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" align="center" label="流程定义名称">
-          <template #default="scope">
-            <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="processDefinitionKey" label="流程定义KEY"></el-table-column>
-        <el-table-column align="center" prop="name" label="任务名称"></el-table-column>
-        <el-table-column align="center" prop="assigneeName" label="办理人">
+        <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"></el-table-column>
+        <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
+        <el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
+        <el-table-column align="center" prop="createByName" label="申请人"></el-table-column>
+        <el-table-column align="center" label="办理人">
           <template #default="scope">
-            <template v-if="scope.row.participantVo && scope.row.assignee === null">
-              <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success">
-                {{ item }}
+            <template v-if="scope.row.assigneeNames">
+              <el-tag v-for="(name, index) in scope.row.assigneeNames.split(',')" :key="index" type="success">
+                {{ name }}
               </el-tag>
             </template>
             <template v-else>
-              <el-tag type="success">
-                {{ scope.row.assigneeName || '无' }}
-              </el-tag>
+              <el-tag type="success"> 无</el-tag>
             </template>
           </template>
         </el-table-column>
-        <el-table-column align="center" label="流程状态" min-width="70">
+        <el-table-column align="center" label="流程状态" prop="flowStatusName" min-width="70">
           <template #default="scope">
-            <dict-tag :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag>
+            <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
           </template>
         </el-table-column>
         <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column>
@@ -72,16 +72,24 @@
         @pagination="handleQuery"
       />
     </el-card>
+    <!-- 申请人 -->
+    <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { getPageByTaskWait } from '@/api/workflow/task';
-import { TaskQuery, TaskVO } from '@/api/workflow/task/types';
+import { pageByTaskWait } from '@/api/workflow/task';
+import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
 import workflowCommon from '@/api/workflow/workflowCommon';
 import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
+
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
+import UserSelect from '@/components/UserSelect';
+import { ref } from 'vue';
+import { UserVO } from '@/api/system/user/types';
+
+const userSelectRef = ref<InstanceType<typeof UserSelect>>();
 //提交组件
 const queryFormRef = ref<ElFormInstance>();
 // 遮罩层
@@ -98,13 +106,19 @@ const showSearch = ref(true);
 const total = ref(0);
 // 模型定义表格数据
 const taskList = ref([]);
+
+//申请人id
+const selectUserIds = ref<Array<number | string>>([]);
+//申请人选择数量
+const userSelectCount = ref(0);
 // 查询参数
 const queryParams = ref<TaskQuery>({
   pageNum: 1,
   pageSize: 10,
-  name: undefined,
-  processDefinitionName: undefined,
-  processDefinitionKey: undefined
+  nodeName: undefined,
+  flowName: undefined,
+  flowCode: undefined,
+  createByIds: []
 });
 onMounted(() => {
   getWaitingList();
@@ -118,6 +132,8 @@ const resetQuery = () => {
   queryFormRef.value?.resetFields();
   queryParams.value.pageNum = 1;
   queryParams.value.pageSize = 10;
+  queryParams.value.createByIds = [];
+  userSelectCount.value = 0;
   handleQuery();
 };
 // 多选框选中数据
@@ -129,21 +145,34 @@ const handleSelectionChange = (selection: any) => {
 //分页
 const getWaitingList = () => {
   loading.value = true;
-  getPageByTaskWait(queryParams.value).then((resp) => {
+  pageByTaskWait(queryParams.value).then((resp) => {
     taskList.value = resp.rows;
     total.value = resp.total;
     loading.value = false;
   });
 };
 //办理
-const handleOpen = async (row: TaskVO) => {
+const handleOpen = async (row: FlowTaskVO) => {
   const routerJumpVo = reactive<RouterJumpVo>({
-    wfDefinitionConfigVo: row.wfDefinitionConfigVo,
-    wfNodeConfigVo: row.wfNodeConfigVo,
-    businessKey: row.businessKey,
+    businessId: row.businessId,
     taskId: row.id,
-    type: 'approval'
+    type: 'approval',
+    formCustom: row.formCustom,
+    formPath: row.formPath
   });
   workflowCommon.routerJump(routerJumpVo, proxy);
 };
+//打开申请人选择
+const openUserSelect = () => {
+  userSelectRef.value.open();
+};
+//确认选择申请人
+const userSelectCallBack = (data: UserVO[]) => {
+  userSelectCount.value = 0;
+  if (data && data.length > 0) {
+    userSelectCount.value = data.length;
+    selectUserIds.value = data.map((item) => item.userId);
+    queryParams.value.createByIds = selectUserIds.value;
+  }
+};
 </script>

+ 0 - 10
vite.config.ts

@@ -64,16 +64,6 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
         'echarts',
         'vue-i18n',
         '@vueup/vue-quill',
-        'bpmn-js/lib/Viewer',
-        'bpmn-js/lib/Modeler.js',
-        'bpmn-js-properties-panel',
-        'min-dash',
-        'diagram-js/lib/navigation/movecanvas',
-        'diagram-js/lib/navigation/zoomscroll',
-        'bpmn-js/lib/features/palette/PaletteProvider',
-        'bpmn-js/lib/features/context-pad/ContextPadProvider',
-        'diagram-js/lib/draw/BaseRenderer',
-        'tiny-svg',
         'image-conversion',
         'element-plus/es/components/**/css'
       ]