兰宝车间质量管理系统-前端
疯狂的狮子Li
2024-06-06 e354db74a7e57be88215ddba2ea11d3cbc944321
!121 ♥️发布 2.2.0-BETA 公测版本
Merge pull request !121 from 疯狂的狮子Li/dev
已修改33个文件
已删除1个文件
476 ■■■■ 文件已修改
.env.production 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/workflow/leave/index.ts 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/workflow/leave/types.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/workflow/processInstance/index.ts 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/workflow/workflowCommon/index.ts 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/hooks/usePanel.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/hooks/useParseElement.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/GatewayPanel.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/ParticipantPanel.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/ProcessPanel.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/SequenceFlowPanel.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/StartEndPanel.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/SubProcessPanel.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/TaskPanel.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/property/ExecutionListener.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/property/ListenerParam.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bpmn/panel/property/TaskListener.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/BpmnView/index.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Process/approvalRecord.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Process/submitVerify.vue 187 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/modeler.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/global.d.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/oss/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tool/build/index.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/workflow/leave/index.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/workflow/leave/leaveEdit.vue 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/workflow/processInstance/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/workflow/task/myDocument.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.production
@@ -11,7 +11,7 @@
VITE_APP_MONITRO_ADMIN = '/admin/applications'
# SnailJob æŽ§åˆ¶å°åœ°å€
VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
VITE_APP_SNAILJOB_ADMIN = '/snail-job'
# ç”Ÿäº§çŽ¯å¢ƒ
VITE_APP_BASE_API = '/prod-api'
package.json
@@ -20,15 +20,12 @@
  "dependencies": {
    "@element-plus/icons-vue": "2.3.1",
    "@highlightjs/vue-plugin": "2.1.0",
    "@lezer/common": "1.2.1",
    "@vueup/vue-quill": "1.2.0",
    "@vueuse/core": "10.9.0",
    "animate.css": "4.1.1",
    "await-to-js": "3.0.0",
    "axios": "1.6.8",
    "bpmn-js": "16.4.0",
    "camunda-bpmn-js-behaviors": "1.2.2",
    "camunda-bpmn-moddle": "7.0.1",
    "crypto-js": "4.2.0",
    "diagram-js": "12.3.0",
    "didi": "9.0.2",
@@ -40,21 +37,15 @@
    "image-conversion": "^2.1.1",
    "js-cookie": "3.0.5",
    "jsencrypt": "3.3.2",
    "moddle": "6.2.3",
    "nprogress": "0.2.0",
    "path-browserify": "1.0.1",
    "path-to-regexp": "6.2.1",
    "pinia": "2.1.7",
    "preact": "10.19.7",
    "screenfull": "6.0.2",
    "vform3-builds": "3.0.10",
    "vue": "3.4.25",
    "vue-cropper": "1.1.1",
    "vue-i18n": "9.10.2",
    "vue-router": "4.3.2",
    "vue-types": "5.1.1",
    "vxe-table": "4.5.22",
    "zeebe-bpmn-moddle": "1.0.0"
    "vxe-table": "4.5.22"
  },
  "devDependencies": {
    "@iconify/json": "2.2.201",
@@ -64,7 +55,6 @@
    "@types/js-cookie": "3.0.6",
    "@types/node": "18.18.2",
    "@types/nprogress": "0.2.3",
    "@types/path-browserify": "1.0.2",
    "@typescript-eslint/eslint-plugin": "7.3.1",
    "@typescript-eslint/parser": "7.3.1",
    "@unocss/preset-attributify": "0.58.6",
src/api/workflow/leave/index.ts
@@ -10,7 +10,7 @@
export const listLeave = (query?: LeaveQuery): AxiosPromise<LeaveVO[]> => {
  return request({
    url: '/demo/leave/list',
    url: '/workflow/leave/list',
    method: 'get',
    params: query
  });
@@ -22,7 +22,7 @@
 */
export const getLeave = (id: string | number): AxiosPromise<LeaveVO> => {
  return request({
    url: '/demo/leave/' + id,
    url: '/workflow/leave/' + id,
    method: 'get'
  });
};
@@ -33,7 +33,7 @@
 */
export const addLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
  return request({
    url: '/demo/leave',
    url: '/workflow/leave',
    method: 'post',
    data: data
  });
@@ -45,7 +45,7 @@
 */
export const updateLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
  return request({
    url: '/demo/leave',
    url: '/workflow/leave',
    method: 'put',
    data: data
  });
@@ -57,7 +57,7 @@
 */
export const delLeave = (id: string | number | Array<string | number>) => {
  return request({
    url: '/demo/leave/' + id,
    url: '/workflow/leave/' + id,
    method: 'delete'
  });
};
src/api/workflow/leave/types.ts
@@ -5,7 +5,7 @@
  endDate: string;
  leaveDays: number;
  remark: string;
  processInstanceVo: any;
  status?: string;
}
export interface LeaveForm extends BaseEntity {
@@ -15,7 +15,7 @@
  endDate?: string;
  leaveDays?: number;
  remark?: string;
  processInstanceVo?: any;
  status?: string;
}
export interface LeaveQuery extends PageQuery {
src/api/workflow/processInstance/index.ts
@@ -29,33 +29,33 @@
};
/**
 * é€šè¿‡æµç¨‹å®žä¾‹id获取历史流程图
 * é€šè¿‡ä¸šåŠ¡id获取历史流程图
 */
export const getHistoryImage = (processInstanceId: string) => {
export const getHistoryImage = (businessKey: string) => {
  return request({
    url: `/workflow/processInstance/getHistoryImage/${processInstanceId}` + '?t' + Math.random(),
    url: `/workflow/processInstance/getHistoryImage/${businessKey}` + '?t' + Math.random(),
    method: 'get'
  });
};
/**
 * é€šè¿‡æµç¨‹å®žä¾‹id获取历史流程图运行中,历史等节点
 * é€šè¿‡ä¸šåŠ¡id获取历史流程图运行中,历史等节点
 */
export const getHistoryList = (instanceId: string): AxiosPromise<Record<string, any>> => {
export const getHistoryList = (businessKey: string): AxiosPromise<Record<string, any>> => {
  return request({
    url: `/workflow/processInstance/getHistoryList/${instanceId}` + '?t' + Math.random(),
    url: `/workflow/processInstance/getHistoryList/${businessKey}` + '?t' + Math.random(),
    method: 'get'
  });
};
/**
 * èŽ·å–å®¡æ‰¹è®°å½•
 * @param processInstanceId æµç¨‹å®žä¾‹id
 * @param businessKey ä¸šåŠ¡id
 * @returns
 */
export const getHistoryRecord = (processInstanceId: string) => {
export const getHistoryRecord = (businessKey: string) => {
  return request({
    url: `/workflow/processInstance/getHistoryRecord/${processInstanceId}`,
    url: `/workflow/processInstance/getHistoryRecord/${businessKey}`,
    method: 'get'
  });
};
@@ -75,24 +75,24 @@
/**
 * è¿è¡Œä¸­çš„实例 åˆ é™¤ç¨‹å®žä¾‹ï¼Œåˆ é™¤åŽ†å²è®°å½•ï¼Œåˆ é™¤ä¸šåŠ¡ä¸Žæµç¨‹å…³è”ä¿¡æ¯
 * @param processInstanceId æµç¨‹å®žä¾‹id
 * @param businessKey ä¸šåŠ¡id
 * @returns
 */
export const deleteRunAndHisInstance = (processInstanceId: string | string[]) => {
export const deleteRunAndHisInstance = (businessKey: string | string[]) => {
  return request({
    url: `/workflow/processInstance/deleteRunAndHisInstance/${processInstanceId}`,
    url: `/workflow/processInstance/deleteRunAndHisInstance/${businessKey}`,
    method: 'delete'
  });
};
/**
 * å·²å®Œæˆçš„实例 åˆ é™¤ç¨‹å®žä¾‹ï¼Œåˆ é™¤åŽ†å²è®°å½•ï¼Œåˆ é™¤ä¸šåŠ¡ä¸Žæµç¨‹å…³è”ä¿¡æ¯
 * @param processInstanceId æµç¨‹å®žä¾‹id
 * @param businessKey ä¸šåŠ¡id
 * @returns
 */
export const deleteFinishAndHisInstance = (processInstanceId: string | string[]) => {
export const deleteFinishAndHisInstance = (businessKey: string | string[]) => {
  return request({
    url: `/workflow/processInstance/deleteFinishAndHisInstance/${processInstanceId}`,
    url: `/workflow/processInstance/deleteFinishAndHisInstance/${businessKey}`,
    method: 'delete'
  });
};
@@ -112,12 +112,12 @@
/**
 * æ’¤é”€æµç¨‹
 * @param processInstanceId æµç¨‹å®žä¾‹id
 * @param businessKey ä¸šåŠ¡id
 * @returns
 */
export const cancelProcessApply = (processInstanceId: string) => {
export const cancelProcessApply = (businessKey: string) => {
  return request({
    url: `/workflow/processInstance/cancelProcessApply/${processInstanceId}`,
    url: `/workflow/processInstance/cancelProcessApply/${businessKey}`,
    method: 'post'
  });
};
src/api/workflow/workflowCommon/index.ts
@@ -1,29 +1,29 @@
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('请到模型配置菜单!');
  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('请到模型配置菜单!');
    }
}
  }
};
src/bpmn/hooks/usePanel.ts
@@ -1,5 +1,5 @@
import showConfig from '../assets/showConfig';
import { ModdleElement } from 'bpmn';
import type { ModdleElement } from 'bpmn';
import useModelerStore from '@/store/modules/modeler';
import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums';
interface Options {
src/bpmn/hooks/useParseElement.ts
@@ -1,4 +1,4 @@
import { ModdleElement } from 'bpmn';
import type { ModdleElement } from 'bpmn';
interface Options {
  element: ModdleElement;
src/bpmn/index.vue
@@ -90,7 +90,7 @@
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 { Canvas, Modeler } from 'bpmn';
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';
src/bpmn/panel/GatewayPanel.vue
@@ -41,8 +41,8 @@
<script setup lang="ts">
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import { Modeler, ModdleElement } from 'bpmn';
import { GatewayPanel } from 'bpmnDesign';
import type { Modeler, ModdleElement } from 'bpmn';
import type { GatewayPanel } from 'bpmnDesign';
import ExecutionListener from './property/ExecutionListener.vue';
interface PropType {
src/bpmn/panel/ParticipantPanel.vue
@@ -42,8 +42,8 @@
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import ExecutionListener from './property/ExecutionListener.vue';
import { ModdleElement } from 'bpmn';
import { ParticipantPanel } from 'bpmnDesign';
import type { ModdleElement } from 'bpmn';
import type { ParticipantPanel } from 'bpmnDesign';
interface PropType {
  element: ModdleElement;
src/bpmn/panel/ProcessPanel.vue
@@ -43,8 +43,8 @@
import ExecutionListener from './property/ExecutionListener.vue';
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import { Modeler, ModdleElement } from 'bpmn';
import { ProcessPanel } from 'bpmnDesign';
import type { Modeler, ModdleElement } from 'bpmn';
import type { ProcessPanel } from 'bpmnDesign';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
src/bpmn/panel/SequenceFlowPanel.vue
@@ -49,8 +49,8 @@
import useModelerStore from '@/store/modules/modeler';
import usePanel from '../hooks/usePanel';
import ExecutionListener from './property/ExecutionListener.vue';
import { Modeler, ModdleElement } from 'bpmn';
import { SequenceFlowPanel } from 'bpmnDesign';
import type { Modeler, ModdleElement } from 'bpmn';
import type { SequenceFlowPanel } from 'bpmnDesign';
interface PropType {
  element: ModdleElement;
src/bpmn/panel/StartEndPanel.vue
@@ -42,8 +42,8 @@
import ExecutionListener from './property/ExecutionListener.vue';
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import { Modeler, ModdleElement } from 'bpmn';
import { StartEndPanel } from 'bpmnDesign';
import type { Modeler, ModdleElement } from 'bpmn';
import type { StartEndPanel } from 'bpmnDesign';
interface PropType {
  element: ModdleElement;
src/bpmn/panel/SubProcessPanel.vue
@@ -111,8 +111,8 @@
import ExecutionListener from './property/ExecutionListener.vue';
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import { ModdleElement } from 'bpmn';
import { SubProcessPanel } from 'bpmnDesign';
import type { ModdleElement } from 'bpmn';
import type { SubProcessPanel } from 'bpmnDesign';
import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums';
interface PropType {
src/bpmn/panel/TaskPanel.vue
@@ -243,8 +243,8 @@
import ExecutionListener from './property/ExecutionListener.vue';
import TaskListener from './property/TaskListener.vue';
import DueDate from './property/DueDate.vue';
import { ModdleElement } from 'bpmn';
import { TaskPanel } from 'bpmnDesign';
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';
src/bpmn/panel/index.vue
@@ -13,7 +13,7 @@
import SequenceFlowPanel from './SequenceFlowPanel.vue';
import ParticipantPanel from './ParticipantPanel.vue';
import SubProcessPanel from './SubProcessPanel.vue';
import { Modeler, ModdleElement } from 'bpmn';
import type { Modeler, ModdleElement } from 'bpmn';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
interface propsType {
  modeler: Modeler;
src/bpmn/panel/property/ExecutionListener.vue
@@ -90,8 +90,8 @@
<script setup lang="ts">
import ListenerParam from './ListenerParam.vue';
import { VxeTableEvents, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
import { ExecutionListenerVO } from 'bpmnDesign';
import { Moddle, Modeler, ModdleElement } from 'bpmn';
import type { ExecutionListenerVO } from 'bpmnDesign';
import type { Moddle, Modeler, ModdleElement } from 'bpmn';
import usePanel from '../../hooks/usePanel';
import useDialog from '@/hooks/useDialog';
src/bpmn/panel/property/ListenerParam.vue
@@ -47,7 +47,7 @@
<script setup lang="ts">
import { VXETable, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
import { ParamVO } from 'bpmnDesign';
import type { ParamVO } from 'bpmnDesign';
import useDialog from '@/hooks/useDialog';
interface PropType {
src/bpmn/panel/property/TaskListener.vue
@@ -91,8 +91,8 @@
<script setup lang="ts">
import ListenerParam from './ListenerParam.vue';
import { VxeTableEvents, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
import { TaskListenerVO } from 'bpmnDesign';
import { ModdleElement } from 'bpmn';
import type { TaskListenerVO } from 'bpmnDesign';
import type { ModdleElement } from 'bpmn';
import usePanel from '../../hooks/usePanel';
import useDialog from '@/hooks/useDialog';
src/components/BpmnView/index.vue
@@ -37,7 +37,7 @@
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
import { ModuleDeclaration } from 'didi';
import { Canvas, ModdleElement } from 'bpmn';
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';
@@ -51,7 +51,7 @@
const bpmnVisible = ref(true);
const historyList = ref([]);
const init = (instanceId) => {
const init = (businessKey) => {
  loading.value = true;
  bpmnVisible.value = true;
  nextTick(async () => {
@@ -67,7 +67,7 @@
        MoveCanvasModule
      ] as ModuleDeclaration[]
    });
    const resp = await processApi.getHistoryList(instanceId);
    const resp = await processApi.getHistoryList(businessKey);
    xml.value = resp.data.xml;
    taskList.value = resp.data.taskList;
    historyList.value = resp.data.historyList;
@@ -133,6 +133,7 @@
                    <p>开始时间:${data.startTime || ''}</p>
                    <p>结束时间:${data.endTime || ''}</p>
                    <p>审批耗时:${data.runDuration || ''}</p>
                    <p>流程版本:v${data.version || ''}</p>
                   </div>`
  });
};
src/components/Process/approvalRecord.vue
@@ -67,17 +67,17 @@
const bpmnViewRef = ref<BpmnView>();
//初始化查询审批记录
const init = async (instanceId: string) => {
const init = async (businessKey: string) => {
  visible.value = true;
  loading.value = true;
  tabActiveName.value = 'bpmn';
  historyList.value = [];
  processApi.getHistoryRecord(instanceId).then((resp) => {
  processApi.getHistoryRecord(businessKey).then((resp) => {
    historyList.value = resp.data;
    loading.value = false;
  });
  await nextTick(() => {
    bpmnViewRef.value.init(instanceId);
    bpmnViewRef.value.init(businessKey);
  });
};
src/components/Process/submitVerify.vue
@@ -8,29 +8,43 @@
          <el-checkbox label="3" name="type">短信</el-checkbox>
        </el-checkbox-group>
      </el-form-item>
      <el-form-item label="附件" v-if="task.businessStatus === 'waiting'">
        <fileUpload v-model="form.fileId" :fileType="['doc', 'xls', 'ppt', 'txt', 'pdf', 'xlsx', 'docx', 'zip']" :fileSize="'20'"/>
      <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>
      <el-form-item label="抄送">
        <el-button type="primary" @click="openUserSelectCopy" icon="Plus" circle />
          <el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
            {{ user.userName }}
          </el-tag>
        <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 }}
        </el-tag>
      </el-form-item>
      <el-form-item label="审批意见" v-if="task.businessStatus === 'waiting'">
      <el-form-item v-if="task.businessStatus === '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 v-loading="buttonLoading" type="primary" @click="handleCompleteTask"> æäº¤ </el-button>
        <el-button v-if="task.businessStatus === 'waiting'" v-loading="buttonLoading" type="primary" @click="openDelegateTask"> å§”托 </el-button>
        <el-button v-if="task.businessStatus === 'waiting'" v-loading="buttonLoading" type="primary" @click="openTransferTask"> è½¬åŠž </el-button>
        <el-button v-if="task.businessStatus === 'waiting' && task.multiInstance" v-loading="buttonLoading" type="primary" @click="addMultiInstanceUser"> åŠ ç­¾ </el-button>
        <el-button v-if="task.businessStatus === 'waiting' && task.multiInstance" v-loading="buttonLoading" type="primary" @click="deleteMultiInstanceUser"> å‡ç­¾ </el-button>
        <el-button v-if="task.businessStatus === 'waiting'" v-loading="buttonLoading" type="danger" @click="handleTerminationTask"> ç»ˆæ­¢ </el-button>
        <el-button v-if="task.businessStatus === 'waiting'" v-loading="buttonLoading" type="danger" @click="handleBackProcessOpen"> é€€å›ž </el-button>
        <el-button v-loading="buttonLoading" @click="cancel">取消</el-button>
        <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.businessStatus === 'waiting' && task.multiInstance"
          :disabled="buttonDisabled"
          type="primary"
          @click="addMultiInstanceUser"
        >
          åŠ ç­¾
        </el-button>
        <el-button
          v-if="task.businessStatus === 'waiting' && task.multiInstance"
          :disabled="buttonDisabled"
          type="primary"
          @click="deleteMultiInstanceUser"
        >
          å‡ç­¾
        </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 :disabled="buttonDisabled" @click="cancel">取消</el-button>
      </span>
    </template>
    <!-- æŠ„送 -->
@@ -40,19 +54,14 @@
    <!-- å§”托 -->
    <UserSelect ref="delegateTaskRef" :multiple="false" @confirm-call-back="handleDelegateTask"></UserSelect>
    <!-- åŠ ç­¾ç»„ä»¶ -->
    <multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback='closeDialog' />
    <multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback="closeDialog" />
    <!-- é©³å›žå¼€å§‹ -->
    <el-dialog v-model="backVisible" draggable title="驳回" width="40%" :close-on-click-modal="false">
      <el-form v-loading="backLoading" :model="backForm" label-width="120px" v-if="task.businessStatus === 'waiting'">
      <el-form v-if="task.businessStatus === 'waiting'" v-loading="backLoading" :model="backForm" label-width="120px">
        <el-form-item label="驳回节点">
          <el-select clearable placeholder="请选择" v-model="backForm.targetActivityId" style="width: 300px">
            <el-option
              v-for="item in taskNodeList"
              :key="item.nodeId"
              :label="item.nodeName"
              :value="item.nodeId"
            />
          <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>
        </el-form-item>
        <el-form-item label="消息提醒">
@@ -67,9 +76,9 @@
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer" style="float: right;padding-bottom: 20px;">
          <el-button type="primary" v-loading="backLoading" @click="handleBackProcess">确认</el-button>
          <el-button v-loading="backLoading" @click="backVisible = false">取消</el-button>
        <div class="dialog-footer" style="float: right; padding-bottom: 20px">
          <el-button :disabled="backButtonDisabled" type="primary" @click="handleBackProcess">确认</el-button>
          <el-button :disabled="backButtonDisabled" @click="backVisible = false">取消</el-button>
        </div>
      </template>
    </el-dialog>
@@ -81,7 +90,7 @@
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, getTaskById, transferTask, terminationTask, getTaskNodeList, delegateTask } from '@/api/workflow/task';
import UserSelect from '@/components/UserSelect';
import MultiInstanceUser from '@/components/Process/multiInstanceUser.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -91,7 +100,7 @@
const transferTaskRef = ref<InstanceType<typeof UserSelect>>();
const delegateTaskRef = ref<InstanceType<typeof UserSelect>>();
  //加签组件
//加签组件
const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>();
const props = defineProps({
@@ -103,7 +112,7 @@
//遮罩层
const loading = ref(true);
//按钮
const buttonLoading = ref(true);
const buttonDisabled = ref(true);
//任务id
const taskId = ref<string>('');
//抄送人
@@ -113,6 +122,7 @@
// é©³å›žæ˜¯å¦æ˜¾ç¤º
const backVisible = ref(false);
const backLoading = ref(true);
const backButtonDisabled = ref(true);
// å¯é©³å›žå¾—任务节点
const taskNodeList = ref([]);
//任务
@@ -166,23 +176,23 @@
  messageType: ['1']
});
const closeDialog = () => {
  dialog.visible = false
}
  dialog.visible = false;
};
//打开弹窗
const openDialog = (id?: string) => {
  selectCopyUserIds.value = undefined
  selectCopyUserList.value = []
  form.value.fileId = undefined
  selectCopyUserIds.value = undefined;
  selectCopyUserList.value = [];
  form.value.fileId = undefined;
  taskId.value = id;
  form.value.message = undefined;
  dialog.visible = true;
  loading.value = true;
  buttonLoading.value = true;
  buttonDisabled.value = true;
  nextTick(() => {
    getTaskById(taskId.value).then((response) => {
      task.value = response.data;
      loading.value = false;
      buttonLoading.value = false;
      buttonDisabled.value = false;
    });
  });
};
@@ -194,58 +204,62 @@
const handleCompleteTask = async () => {
  form.value.taskId = taskId.value;
  form.value.taskVariables = props.taskVariables;
  if(selectCopyUserList && selectCopyUserList.value.length > 0){
    let wfCopyList = []
    selectCopyUserList.value.forEach( e=> {
  if (selectCopyUserList.value && selectCopyUserList.value.length > 0) {
    let wfCopyList = [];
    selectCopyUserList.value.forEach((e) => {
      let copyUser = {
        userId: e.userId,
        userName: e.nickName
      }
      wfCopyList.push(copyUser)
    })
    form.value.wfCopyList = wfCopyList
      };
      wfCopyList.push(copyUser);
    });
    form.value.wfCopyList = wfCopyList;
  }
  await proxy?.$modal.confirm('是否确认提交?');
  loading.value = true;
  buttonLoading.value = true;
  buttonDisabled.value = true;
  try {
    await completeTask(form.value);
    dialog.visible = false;
    emits('submitCallback');
    proxy?.$modal.msgSuccess('操作成功');
  } finally {
    loading.value = false
    buttonLoading.value = false
    loading.value = false;
    buttonDisabled.value = false;
  }
};
/** é©³å›žå¼¹çª—打开 */
const handleBackProcessOpen = async () => {
  backForm.value = {}
  backForm.value.messageType = ['1']
  backVisible.value = true
  backLoading.value = true
  let data = await getTaskNodeList(task.value.processInstanceId)
  taskNodeList.value = data.data
  backLoading.value = false
  backForm.value.targetActivityId = taskNodeList.value[0].nodeId
}
  backForm.value = {};
  backForm.value.messageType = ['1'];
  backVisible.value = true;
  backLoading.value = true;
  backButtonDisabled.value = true;
  let data = await getTaskNodeList(task.value.processInstanceId);
  taskNodeList.value = data.data;
  backLoading.value = false;
  backButtonDisabled.value = false;
  backForm.value.targetActivityId = taskNodeList.value[0].nodeId;
};
/** é©³å›žæµç¨‹ */
const handleBackProcess = async () => {
  backForm.value.taskId = taskId.value;
  await proxy?.$modal.confirm('是否确认驳回到申请人?');
  loading.value = true;
  backLoading.value = true;
  backButtonDisabled.value = true;
  await backProcess(backForm.value).finally(() => (loading.value = false));
  dialog.visible = false;
  backLoading.value = false
  backLoading.value = false;
  backButtonDisabled.value = false;
  emits('submitCallback');
  proxy?.$modal.msgSuccess('操作成功');
};
//取消
const cancel = async () => {
  dialog.visible = false;
  buttonLoading.value = false;
  buttonDisabled.value = false;
  emits('cancelCallback');
};
//打开抄送人员
@@ -254,11 +268,11 @@
};
//确认抄送人员
const userSelectCopyCallBack = (data: UserVO[]) => {
  if(data && data.length > 0){
    selectCopyUserList.value = data
  if (data && data.length > 0) {
    selectCopyUserList.value = data;
    selectCopyUserIds.value = selectCopyUserList.value.map((item) => item.userId).join(',');
  }
}
};
//删除抄送人员
const handleCopyCloseTag = (user: UserVO) => {
  const userId = user.userId;
@@ -286,63 +300,62 @@
  transferTaskRef.value.open();
};
//转办
const handleTransferTask  = async (data) => {
  if(data && data.length > 0){
const handleTransferTask = async (data) => {
  if (data && data.length > 0) {
    let params = {
      taskId: taskId.value,
      userId: data[0].userId,
      comment: form.value.message
    }
    };
    await proxy?.$modal.confirm('是否确认提交?');
    loading.value = true;
    buttonLoading.value = true;
    buttonDisabled.value = true;
    await transferTask(params).finally(() => (loading.value = false));
    dialog.visible = false;
    emits('submitCallback');
    proxy?.$modal.msgSuccess('操作成功');
  }else{
  } else {
    proxy?.$modal.msgWarning('请选择用户!');
  }
}
};
//打开委托
const openDelegateTask = () => {
  delegateTaskRef.value.open();
};
//委托
const handleDelegateTask  = async (data) => {
  if(data && data.length > 0){
const handleDelegateTask = async (data) => {
  if (data && data.length > 0) {
    let params = {
      taskId: taskId.value,
      userId: data[0].userId,
      nickName: data[0].nickName
    }
    };
    await proxy?.$modal.confirm('是否确认提交?');
    loading.value = true;
    buttonLoading.value = true;
    buttonDisabled.value = true;
    await delegateTask(params).finally(() => (loading.value = false));
    dialog.visible = false;
    emits('submitCallback');
    proxy?.$modal.msgSuccess('操作成功');
  }else{
  } else {
    proxy?.$modal.msgWarning('请选择用户!');
  }
}
};
//终止任务
const handleTerminationTask  = async (data) => {
    let params = {
      taskId: taskId.value,
      comment: form.value.message
    }
    await proxy?.$modal.confirm('是否确认终止?');
    loading.value = true;
    buttonLoading.value = true;
    await terminationTask(params).finally(() => (loading.value = false));
    dialog.visible = false;
    emits('submitCallback');
    proxy?.$modal.msgSuccess('操作成功');
}
const handleTerminationTask = async (data) => {
  let params = {
    taskId: taskId.value,
    comment: form.value.message
  };
  await proxy?.$modal.confirm('是否确认终止?');
  loading.value = true;
  buttonDisabled.value = true;
  await terminationTask(params).finally(() => (loading.value = false));
  dialog.visible = false;
  emits('submitCallback');
  proxy?.$modal.msgSuccess('操作成功');
};
/**
 * å¯¹å¤–暴露子组件方法
src/router/index.ts
@@ -164,16 +164,16 @@
    ]
  },
  {
    path: '/demo/leaveEdit',
    path: '/workflow/leaveEdit',
    component: Layout,
    hidden: true,
    permissions: ['demo:leave:edit'],
    permissions: ['workflow:leave:edit'],
    children: [
      {
        path: 'index',
        component: () => import('@/views/workflow/leave/leaveEdit.vue'),
        name: 'leaveEdit',
        meta: { title: '请假申请', activeMenu: '/demo/leave', noCache: true }
        meta: { title: '请假申请', activeMenu: '/workflow/leave', noCache: true }
      }
    ]
  }
src/store/modules/modeler.ts
@@ -1,4 +1,4 @@
import { Modeler, Modeling, Canvas, ElementRegistry, Moddle, BpmnFactory } from 'bpmn';
import type { Modeler, Modeling, Canvas, ElementRegistry, Moddle, BpmnFactory } from 'bpmn';
type ModelerStore = {
  modeler: Modeler | undefined;
src/types/global.d.ts
@@ -4,8 +4,6 @@
declare global {
  /** vue Instance */
  declare type ComponentInternalInstance = ComponentInstance;
  /**vue */
  declare type PropType<T> = VuePropType<T>;
  /**
   * ç•Œé¢å­—段隐藏属性
src/views/index.vue
@@ -68,7 +68,6 @@
          * RPC远程调用 Apache Dubbo åŽŸç”Ÿæ€ä½¿ç”¨ä½“éªŒã€é«˜æ€§èƒ½<br />
          * åˆ†å¸ƒå¼é™æµç†”æ–­ Alibaba Sentinel æ— ä¾µå…¥ã€é«˜æ‰©å±•<br />
          * åˆ†å¸ƒå¼äº‹åŠ¡ Alibaba Seata æ— ä¾µå…¥ã€é«˜æ‰©å±• æ”¯æŒ å››ç§æ¨¡å¼<br />
          * åˆ†å¸ƒå¼æ¶ˆæ¯é˜Ÿåˆ— Spring Cloud Stream é—¨é¢æ¡†æž¶å…¼å®¹å„种MQ集成<br />
          * åˆ†å¸ƒå¼æ¶ˆæ¯é˜Ÿåˆ— Apache Kafka é«˜æ€§èƒ½é«˜é€Ÿåº¦<br />
          * åˆ†å¸ƒå¼æ¶ˆæ¯é˜Ÿåˆ— Apache RocketMQ é«˜å¯ç”¨åŠŸèƒ½å¤šæ ·<br />
          * åˆ†å¸ƒå¼æ¶ˆæ¯é˜Ÿåˆ— RabbitMQ æ”¯æŒå„种扩展插件功能多样性<br />
src/views/system/oss/index.vue
@@ -304,7 +304,7 @@
const handleDownload = (row: OssVO) => {
  proxy?.$download.oss(row.ossId);
};
/** ç”¨æˆ·çŠ¶æ€ä¿®æ”¹  */
/** é¢„览开关按钮  */
const handlePreviewListResource = async (preview: boolean) => {
  let text = preview ? '启用' : '停用';
  try {
src/views/tool/build/index.vue
ÎļþÒÑɾ³ý
src/views/workflow/leave/index.vue
@@ -22,10 +22,10 @@
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button v-hasPermi="['demo:leave:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
            <el-button v-hasPermi="['workflow:leave:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button v-hasPermi="['demo:leave:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
            <el-button v-hasPermi="['workflow:leave:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar>
        </el-row>
@@ -53,18 +53,14 @@
        <el-table-column label="请假原因" align="center" prop="remark" />
        <el-table-column align="center" label="流程状态" min-width="70">
          <template #default="scope">
            <dict-tag :options="wf_business_status" :value="scope.row.processInstanceVo.businessStatus"></dict-tag>
            <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">
          <template #default="scope">
            <el-button
              v-if="
                scope.row.processInstanceVo.businessStatus === 'draft' ||
                scope.row.processInstanceVo.businessStatus === 'cancel' ||
                scope.row.processInstanceVo.businessStatus === 'back'
              "
              v-hasPermi="['demo:leave:edit']"
              v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"
              v-hasPermi="['workflow:leave:edit']"
              size="small"
              link
              type="primary"
@@ -73,12 +69,8 @@
              >修改</el-button
            >
            <el-button
              v-if="
                scope.row.processInstanceVo.businessStatus === 'draft' ||
                scope.row.processInstanceVo.businessStatus === 'cancel' ||
                scope.row.processInstanceVo.businessStatus === 'back'
              "
              v-hasPermi="['demo:leave:remove']"
              v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"
              v-hasPermi="['workflow:leave:remove']"
              size="small"
              link
              type="primary"
@@ -88,12 +80,12 @@
            >
            <el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
            <el-button
              v-if="scope.row.processInstanceVo.businessStatus === 'waiting'"
              v-if="scope.row.status === 'waiting'"
              link
              size="small"
              type="primary"
              icon="Notification"
              @click="handleCancelProcessApply(scope.row.processInstanceVo.id)"
              @click="handleCancelProcessApply(scope.row.id)"
              >撤销</el-button
            >
          </template>
@@ -184,9 +176,9 @@
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  proxy.$tab.closePage(proxy.$route);
  proxy.$router.push(`/demo/leaveEdit/index/add/add`);
  proxy.$router.push(`/workflow/leaveEdit/index/add/add`);
  proxy.$router.push({
    path: `/demo/leaveEdit/index`,
    path: `/workflow/leaveEdit/index`,
    query: {
      type: 'add'
    }
@@ -197,7 +189,7 @@
const handleUpdate = (row?: LeaveVO) => {
  proxy.$tab.closePage(proxy.$route);
  proxy.$router.push({
    path: `/demo/leaveEdit/index`,
    path: `/workflow/leaveEdit/index`,
    query: {
      id: row.id,
      type: 'update'
@@ -209,7 +201,7 @@
const handleView = (row?: LeaveVO) => {
  proxy.$tab.closePage(proxy.$route);
  proxy.$router.push({
    path: `/demo/leaveEdit/index`,
    path: `/workflow/leaveEdit/index`,
    query: {
      id: row.id,
      type: 'view'
@@ -229,7 +221,7 @@
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download(
    'demo/leave/export',
    'workflow/leave/export',
    {
      ...queryParams.value
    },
src/views/workflow/leave/leaveEdit.vue
@@ -6,12 +6,7 @@
          <el-button
            v-if="
              routeParams.type === 'add' ||
              (routeParams.type === 'update' &&
                form.processInstanceVo &&
                form.processInstanceVo.businessStatus &&
                (form.processInstanceVo.businessStatus === 'draft' ||
                  form.processInstanceVo.businessStatus === 'cancel' ||
                  form.processInstanceVo.businessStatus === 'back'))
              (routeParams.type === 'update' && form.status && (form.status === 'draft' || form.status === 'cancel' || form.status === 'back'))
            "
            :loading="buttonLoading"
            type="info"
@@ -21,11 +16,7 @@
          <el-button
            v-if="
              routeParams.type === 'add' ||
              (routeParams.type === 'update' &&
                form.processInstanceVo &&
                (form.processInstanceVo.businessStatus === 'draft' ||
                  form.processInstanceVo.businessStatus === 'cancel' ||
                  form.processInstanceVo.businessStatus === 'back'))
              (routeParams.type === 'update' && form.status && (form.status === 'draft' || form.status === 'cancel' || form.status === 'back'))
            "
            :loading="buttonLoading"
            type="primary"
@@ -33,13 +24,13 @@
            >提 äº¤</el-button
          >
          <el-button
            v-if="routeParams.type === 'approval' && form.processInstanceVo && form.processInstanceVo.businessStatus === 'waiting'"
            v-if="routeParams.type === 'approval' && form.status && form.status === 'waiting'"
            :loading="buttonLoading"
            type="primary"
            @click="approvalVerifyOpen"
            >审批</el-button
          >
          <el-button v-if="processInstanceId" type="primary" @click="handleApprovalRecord">流程进度</el-button>
          <el-button v-if="form.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button>
        </div>
        <div>
          <el-button style="float: right" @click="goBack()">返回</el-button>
@@ -91,8 +82,6 @@
const buttonLoading = ref(false);
const loading = ref(true);
const leaveTime = ref<Array<string>>([]);
//流程实例id
const processInstanceId = ref('');
//路由参数
const routeParams = ref<Record<string, any>>({});
const options = [
@@ -134,7 +123,7 @@
  endDate: undefined,
  leaveDays: undefined,
  remark: undefined,
  processInstanceVo: {}
  status: undefined
};
const data = reactive<PageData<LeaveForm, LeaveQuery>>({
  form: { ...initFormData },
@@ -177,9 +166,6 @@
    leaveTime.value = [];
    leaveTime.value.push(form.value.startDate);
    leaveTime.value.push(form.value.endDate);
    if (form.value.processInstanceVo) {
      processInstanceId.value = form.value.processInstanceVo.id;
    }
    loading.value = false;
    buttonLoading.value = false;
  });
@@ -243,7 +229,7 @@
};
//审批记录
const handleApprovalRecord = () => {
  approvalRecordRef.value.init(processInstanceId.value);
  approvalRecordRef.value.init(form.value.id);
};
//提交回调
const submitCallback = async () => {
src/views/workflow/processInstance/index.vue
@@ -167,6 +167,8 @@
const loading = ref(true);
// é€‰ä¸­æ•°ç»„
const ids = ref<Array<any>>([]);
// é€‰ä¸­ä¸šåŠ¡id数组
const businessKeys = ref<Array<any>>([]);
// éžå•个禁用
const single = ref(true);
// éžå¤šä¸ªç¦ç”¨
@@ -257,6 +259,7 @@
// å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
const handleSelectionChange = (selection: ProcessInstanceVO[]) => {
  ids.value = selection.map((item: any) => item.id);
  businessKeys.value = selection.map((item: any) => item.businessKey);
  single.value = selection.length !== 1;
  multiple.value = !selection.length;
};
@@ -281,14 +284,14 @@
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row: any) => {
  const id = row.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除id为【' + id + '】的数据项?');
  const businessKey = row.businessKey || businessKeys.value;
  await proxy?.$modal.confirm('是否确认删除业务id为【' + businessKey + '】的数据项?');
  loading.value = true;
  if ('running' === tab.value) {
    await deleteRunAndHisInstance(id).finally(() => (loading.value = false));
    await deleteRunAndHisInstance(businessKey).finally(() => (loading.value = false));
    getProcessInstanceRunningList();
  } else {
    await deleteFinishAndHisInstance(id).finally(() => (loading.value = false));
    await deleteFinishAndHisInstance(businessKey).finally(() => (loading.value = false));
    getProcessInstanceFinishList();
  }
  proxy?.$modal.msgSuccess('删除成功');
@@ -308,7 +311,7 @@
  loading.value = true;
  if ('running' === tab.value) {
    let param = {
      processInstanceId: row.id,
      businessKey: row.businessKey,
      deleteReason: deleteReason.value
    };
    await deleteRunInstance(param).finally(() => (loading.value = false));
src/views/workflow/task/myDocument.vue
@@ -75,20 +75,20 @@
                  content="修改"
                  placement="top"
                >
                  <el-button v-hasPermi="['demo:leave:edit']" link type="primary" icon="Edit" @click="handleOpen(scope.row, 'update')"></el-button>
                  <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 v-hasPermi="['demo:leave:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
                  <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.id)"></el-button>
                  <el-button link type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.businessKey)"></el-button>
                </el-tooltip>
              </template>
            </el-table-column>
@@ -123,7 +123,7 @@
// é®ç½©å±‚
const loading = ref(true);
// é€‰ä¸­æ•°ç»„
const ids = ref<Array<any>>([]);
const businessKeys = ref<Array<any>>([]);
// éžå•个禁用
const single = ref(true);
// éžå¤šä¸ªç¦ç”¨
@@ -190,12 +190,6 @@
  categoryOptions.value.push(data);
};
//审批记录
const handleApprovalRecord = (processInstanceId: string) => {
  if (approvalRecordRef.value) {
    approvalRecordRef.value.init(processInstanceId);
  }
};
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  getList();
@@ -210,7 +204,7 @@
};
// å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
const handleSelectionChange = (selection: ProcessInstanceVO[]) => {
  ids.value = selection.map((item: any) => item.id);
  businessKeys.value = selection.map((item: any) => item.businessKey);
  single.value = selection.length !== 1;
  multiple.value = !selection.length;
};
@@ -226,22 +220,22 @@
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row: ProcessInstanceVO) => {
  const id = row.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除id为【' + id + '】的数据项?');
  const businessKey = row.businessKey || businessKeys.value;
  await proxy?.$modal.confirm('是否确认删除业务id为【' + businessKey + '】的数据项?');
  loading.value = true;
  if ('running' === tab.value) {
    await deleteRunAndHisInstance(id).finally(() => (loading.value = false));
    await deleteRunAndHisInstance(businessKey).finally(() => (loading.value = false));
    getList();
  }
  proxy?.$modal.msgSuccess('删除成功');
};
/** æ’¤é”€æŒ‰é’®æ“ä½œ */
const handleCancelProcessApply = async (processInstanceId: string) => {
const handleCancelProcessApply = async (businessKey: string) => {
  await proxy?.$modal.confirm('是否确认撤销当前单据?');
  loading.value = true;
  if ('running' === tab.value) {
    await cancelProcessApply(processInstanceId).finally(() => (loading.value = false));
    await cancelProcessApply(businessKey).finally(() => (loading.value = false));
    getList();
  }
  proxy?.$modal.msgSuccess('撤销成功');
vite.config.ts
@@ -61,7 +61,6 @@
        'pinia',
        'axios',
        '@vueuse/core',
        'path-to-regexp',
        'echarts',
        'vue-i18n',
        '@vueup/vue-quill',