Browse Source

Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm

# Conflicts:
#	src/views/bpm/processInstance/detail/index_new.vue
YunaiV 10 months ago
parent
commit
6b06f320b9

+ 1 - 1
src/api/bpm/processInstance/index.ts

@@ -46,7 +46,7 @@ export type ApprovalNodeInfo = {
   status: number
   status: number
   startTime?: Date
   startTime?: Date
   endTime?: Date
   endTime?: Date
-  candidateUserList?: User[]
+  candidateUsers?: User[]
   tasks: ApprovalTaskInfo[]
   tasks: ApprovalTaskInfo[]
 }
 }
 
 

+ 5 - 0
src/api/bpm/task/index.ts

@@ -106,6 +106,11 @@ export const signDeleteTask = async (data: any) => {
   return await request.delete({ url: '/bpm/task/delete-sign', data })
   return await request.delete({ url: '/bpm/task/delete-sign', data })
 }
 }
 
 
+// 抄送
+export const copyTask = async (data: any) => {
+  return await request.put({ url: '/bpm/task/copy', data })
+}
+
 // 获取减签任务列表
 // 获取减签任务列表
 export const getChildrenTaskList = async (id: string) => {
 export const getChildrenTaskList = async (id: string) => {
   return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id })
   return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id })

+ 6 - 1
src/components/SimpleProcessDesignerV2/src/consts.ts

@@ -362,7 +362,11 @@ export enum OperationButtonType {
   /**
   /**
    * 回退
    * 回退
    */
    */
-  RETURN = 6
+  RETURN = 6,
+  /**
+   * 抄送
+   */
+  COPY = 7
 }
 }
 
 
 /**
 /**
@@ -504,6 +508,7 @@ OPERATION_BUTTON_NAME.set(OperationButtonType.TRANSFER, '转办')
 OPERATION_BUTTON_NAME.set(OperationButtonType.DELEGATE, '委派')
 OPERATION_BUTTON_NAME.set(OperationButtonType.DELEGATE, '委派')
 OPERATION_BUTTON_NAME.set(OperationButtonType.ADD_SIGN, '加签')
 OPERATION_BUTTON_NAME.set(OperationButtonType.ADD_SIGN, '加签')
 OPERATION_BUTTON_NAME.set(OperationButtonType.RETURN, '回退')
 OPERATION_BUTTON_NAME.set(OperationButtonType.RETURN, '回退')
+OPERATION_BUTTON_NAME.set(OperationButtonType.COPY, '抄送')
 
 
 // 默认的按钮权限设置
 // 默认的按钮权限设置
 export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [
 export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [

+ 2 - 34
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue

@@ -139,7 +139,6 @@
                 clearable
                 clearable
                 multiple
                 multiple
                 style="width: 100%"
                 style="width: 100%"
-                @change="changedCandidateUsers"
               >
               >
                 <el-option
                 <el-option
                   v-for="item in userOptions"
                   v-for="item in userOptions"
@@ -187,10 +186,6 @@
                     <el-radio
                     <el-radio
                       :value="item.value"
                       :value="item.value"
                       :label="item.value"
                       :label="item.value"
-                      :disabled="
-                        item.value !== ApproveMethodType.RANDOM_SELECT_ONE_APPROVE &&
-                        notAllowedMultiApprovers
-                      "
                     >
                     >
                       {{ item.label }}
                       {{ item.label }}
                     </el-radio>
                     </el-radio>
@@ -537,8 +532,7 @@ const {
   getShowText
   getShowText
 } = useNodeForm(NodeType.USER_TASK_NODE)
 } = useNodeForm(NodeType.USER_TASK_NODE)
 const configForm = tempConfigForm as Ref<UserTaskFormType>
 const configForm = tempConfigForm as Ref<UserTaskFormType>
-// 不允许多人审批
-const notAllowedMultiApprovers = ref(false)
+
 // 改变审批人设置策略
 // 改变审批人设置策略
 const changeCandidateStrategy = () => {
 const changeCandidateStrategy = () => {
   configForm.value.userIds = []
   configForm.value.userIds = []
@@ -548,29 +542,8 @@ const changeCandidateStrategy = () => {
   configForm.value.userGroups = []
   configForm.value.userGroups = []
   configForm.value.deptLevel = 1
   configForm.value.deptLevel = 1
   configForm.value.approveMethod = ApproveMethodType.SEQUENTIAL_APPROVE
   configForm.value.approveMethod = ApproveMethodType.SEQUENTIAL_APPROVE
-  if (
-    configForm.value.candidateStrategy === CandidateStrategy.START_USER ||
-    configForm.value.candidateStrategy === CandidateStrategy.USER
-  ) {
-    notAllowedMultiApprovers.value = true
-  } else {
-    notAllowedMultiApprovers.value = false
-  }
-}
-// 改变审批候选人
-const changedCandidateUsers = () => {
-  if (
-    configForm.value.userIds &&
-    configForm.value.userIds?.length <= 1 &&
-    configForm.value.candidateStrategy === CandidateStrategy.USER
-  ) {
-    configForm.value.approveMethod = ApproveMethodType.RANDOM_SELECT_ONE_APPROVE
-    configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
-    notAllowedMultiApprovers.value = true
-  } else {
-    notAllowedMultiApprovers.value = false
-  }
 }
 }
+
 // 审批方式改变
 // 审批方式改变
 const approveMethodChanged = () => {
 const approveMethodChanged = () => {
   configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
   configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
@@ -666,11 +639,6 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
   configForm.value.candidateStrategy = node.candidateStrategy!
   configForm.value.candidateStrategy = node.candidateStrategy!
   // 解析候选人参数
   // 解析候选人参数
   parseCandidateParam(node.candidateStrategy!, node?.candidateParam)
   parseCandidateParam(node.candidateStrategy!, node?.candidateParam)
-  if (configForm.value.userIds && configForm.value.userIds.length > 1) {
-    notAllowedMultiApprovers.value = true
-  } else {
-    notAllowedMultiApprovers.value = false
-  }
   // 2.2 设置审批方式
   // 2.2 设置审批方式
   configForm.value.approveMethod = node.approveMethod!
   configForm.value.approveMethod = node.approveMethod!
   if (node.approveMethod == ApproveMethodType.APPROVE_BY_RATIO) {
   if (node.approveMethod == ApproveMethodType.APPROVE_BY_RATIO) {

+ 425 - 118
src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue

@@ -5,14 +5,14 @@
   >
   >
     <!-- 【通过】按钮 -->
     <!-- 【通过】按钮 -->
     <el-popover
     <el-popover
-      :visible="passVisible"
+      :visible="popOverVisible.approve"
       placement="top-end"
       placement="top-end"
-      :width="500"
+      :width="420"
       trigger="click"
       trigger="click"
       v-if="isShowButton(OperationButtonType.APPROVE)"
       v-if="isShowButton(OperationButtonType.APPROVE)"
     >
     >
       <template #reference>
       <template #reference>
-        <el-button plain type="success" @click="openPopover('1')">
+        <el-button plain type="success" @click="openPopover('approve')">
           <Icon icon="ep:select" />&nbsp; {{ getButtonDisplayName(OperationButtonType.APPROVE) }}
           <Icon icon="ep:select" />&nbsp; {{ getButtonDisplayName(OperationButtonType.APPROVE) }}
         </el-button>
         </el-button>
       </template>
       </template>
@@ -22,16 +22,10 @@
           label-position="top"
           label-position="top"
           class="mb-auto"
           class="mb-auto"
           ref="formRef"
           ref="formRef"
-          :model="auditForm"
-          :rules="auditRule"
+          :model="genericForm"
+          :rules="genericRule"
           label-width="100px"
           label-width="100px"
         >
         >
-          <el-form-item v-if="processInstance && processInstance.startUser" label="流程发起人">
-            {{ processInstance?.startUser.nickname }}
-            <el-tag size="small" type="info" class="ml-8px">
-              {{ processInstance?.startUser.deptName }}
-            </el-tag>
-          </el-form-item>
           <el-card v-if="runningTask.formId > 0" class="mb-15px !-mt-10px">
           <el-card v-if="runningTask.formId > 0" class="mb-15px !-mt-10px">
             <template #header>
             <template #header>
               <span class="el-icon-picture-outline"> 填写表单【{{ runningTask?.formName }}】 </span>
               <span class="el-icon-picture-outline"> 填写表单【{{ runningTask?.formName }}】 </span>
@@ -43,25 +37,14 @@
               :rule="approveForm.rule"
               :rule="approveForm.rule"
             />
             />
           </el-card>
           </el-card>
-          <el-form-item label="审批建议" prop="reason">
-            <el-input v-model="auditForm.reason" placeholder="请输入审批建议" type="textarea" />
-          </el-form-item>
-          <el-form-item label="抄送人" prop="copyUserIds">
-            <el-select v-model="auditForm.copyUserIds" multiple placeholder="请选择抄送人">
-              <el-option
-                v-for="itemx in userOptions"
-                :key="itemx.id"
-                :label="itemx.nickname"
-                :value="itemx.id"
-              />
-            </el-select>
+          <el-form-item label="审批意见" prop="reason">
+            <el-input v-model="genericForm.reason" placeholder="请输入审批意见" type="textarea" :rows="4" />
           </el-form-item>
           </el-form-item>
-
           <el-form-item>
           <el-form-item>
             <el-button :disabled="formLoading" type="success" @click="handleAudit(true)">
             <el-button :disabled="formLoading" type="success" @click="handleAudit(true)">
               {{ getButtonDisplayName(OperationButtonType.APPROVE) }}
               {{ getButtonDisplayName(OperationButtonType.APPROVE) }}
             </el-button>
             </el-button>
-            <el-button @click="passVisible = false"> 取消 </el-button>
+            <el-button @click="popOverVisible.approve = false"> 取消 </el-button>
           </el-form-item>
           </el-form-item>
         </el-form>
         </el-form>
       </div>
       </div>
@@ -69,14 +52,14 @@
 
 
     <!-- 【拒绝】按钮 -->
     <!-- 【拒绝】按钮 -->
     <el-popover
     <el-popover
-      :visible="rejectVisible"
+      :visible="popOverVisible.reject"
       placement="top-end"
       placement="top-end"
-      :width="500"
+      :width="420"
       trigger="click"
       trigger="click"
       v-if="isShowButton(OperationButtonType.REJECT)"
       v-if="isShowButton(OperationButtonType.REJECT)"
     >
     >
       <template #reference>
       <template #reference>
-        <el-button class="mr-20px" plain type="danger" @click="openPopover('2')">
+        <el-button class="mr-20px" plain type="danger" @click="openPopover('reject')">
           <Icon icon="ep:close" />&nbsp; {{ getButtonDisplayName(OperationButtonType.REJECT) }}
           <Icon icon="ep:close" />&nbsp; {{ getButtonDisplayName(OperationButtonType.REJECT) }}
         </el-button>
         </el-button>
       </template>
       </template>
@@ -86,16 +69,10 @@
           label-position="top"
           label-position="top"
           class="mb-auto"
           class="mb-auto"
           ref="formRef"
           ref="formRef"
-          :model="auditForm"
-          :rules="auditRule"
+          :model="genericForm"
+          :rules="genericRule"
           label-width="100px"
           label-width="100px"
         >
         >
-          <el-form-item v-if="processInstance && processInstance.startUser" label="流程发起人">
-            {{ processInstance?.startUser.nickname }}
-            <el-tag size="small" type="info" class="ml-8px">
-              {{ processInstance?.startUser.deptName }}
-            </el-tag>
-          </el-form-item>
           <el-card v-if="runningTask.formId > 0" class="mb-15px !-mt-10px">
           <el-card v-if="runningTask.formId > 0" class="mb-15px !-mt-10px">
             <template #header>
             <template #header>
               <span class="el-icon-picture-outline"> 填写表单【{{ runningTask?.formName }}】 </span>
               <span class="el-icon-picture-outline"> 填写表单【{{ runningTask?.formName }}】 </span>
@@ -107,80 +84,273 @@
               :rule="approveForm.rule"
               :rule="approveForm.rule"
             />
             />
           </el-card>
           </el-card>
-          <el-form-item label="审批建议" prop="reason">
-            <el-input v-model="auditForm.reason" placeholder="请输入审批建议" type="textarea" />
+          <el-form-item label="审批意见" prop="reason">
+            <el-input v-model="genericForm.reason" placeholder="请输入审批意见" type="textarea" :rows="4" />
+          </el-form-item>
+          <el-form-item>
+            <el-button :disabled="formLoading" type="danger" @click="handleAudit(false)">
+              {{ getButtonDisplayName(OperationButtonType.REJECT) }}
+            </el-button>
+            <el-button @click="popOverVisible.reject = false"> 取消 </el-button>
           </el-form-item>
           </el-form-item>
+        </el-form>
+      </div>
+    </el-popover>
+
+    <!-- 【抄送】按钮 -->
+    <el-popover
+      :visible="popOverVisible.copy"
+      placement="top-start"
+      :width="420"
+      trigger="click"
+      v-if="isShowButton(OperationButtonType.COPY)"
+    >
+      <template #reference>
+        <div @click="openPopover('copy')" class="hover-bg-gray-100 rounded-xl p-6px" >
+          <Icon :size="14" icon="svg-icon:send" />&nbsp;
+          {{ getButtonDisplayName(OperationButtonType.COPY) }}
+        </div>
+      </template>
+      <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
+        <el-form
+          label-position="top"
+          class="mb-auto"
+          ref="formRef"
+          :model="genericForm"
+          :rules="genericRule"
+          label-width="100px"
+        >
+                
           <el-form-item label="抄送人" prop="copyUserIds">
           <el-form-item label="抄送人" prop="copyUserIds">
-            <el-select v-model="auditForm.copyUserIds" multiple placeholder="请选择抄送人">
+            <el-select v-model="genericForm.copyUserIds" clearable style="width: 100%" multiple placeholder="请选择抄送人">
               <el-option
               <el-option
-                v-for="itemx in userOptions"
-                :key="itemx.id"
-                :label="itemx.nickname"
-                :value="itemx.id"
+                v-for="item in userOptions"
+                :key="item.id"
+                :label="item.nickname"
+                :value="item.id"
               />
               />
             </el-select>
             </el-select>
           </el-form-item>
           </el-form-item>
+          <el-form-item label="抄送意见" prop="copyReason">
+            <el-input v-model="genericForm.copyReason" clearable placeholder="请输入抄送意见" type="textarea"  :rows="3" />
+          </el-form-item>
 
 
           <el-form-item>
           <el-form-item>
-            <el-button :disabled="formLoading" type="danger" @click="handleAudit(false)">
-              {{ getButtonDisplayName(OperationButtonType.REJECT) }}
+            <el-button :disabled="formLoading" type="primary" @click="handleCopy">
+              {{ getButtonDisplayName(OperationButtonType.COPY) }}
             </el-button>
             </el-button>
-            <el-button @click="rejectVisible = false"> 取消 </el-button>
+            <el-button @click="popOverVisible.copy = false"> 取消 </el-button>
           </el-form-item>
           </el-form-item>
         </el-form>
         </el-form>
       </div>
       </div>
     </el-popover>
     </el-popover>
 
 
-    <!-- 【抄送】按钮 -->
-    <div @click="handleSend"> <Icon :size="14" icon="svg-icon:send" />&nbsp;抄送 </div>
-
     <!-- 【转交】按钮 -->
     <!-- 【转交】按钮 -->
-    <div @click="openTaskUpdateAssigneeForm" v-if="isShowButton(OperationButtonType.TRANSFER)">
-      <Icon :size="14" icon="fa:share-square-o" />&nbsp;
-      {{ getButtonDisplayName(OperationButtonType.TRANSFER) }}
-    </div>
+    <el-popover
+      :visible="popOverVisible.transfer"
+      placement="top-start"
+      :width="420"
+      trigger="click"
+      v-if="isShowButton(OperationButtonType.TRANSFER)"
+    >
+      <template #reference>
+        <div @click="openPopover('transfer')" class="hover-bg-gray-100 rounded-xl p-6px" >
+          <Icon :size="14" icon="fa:share-square-o" />&nbsp;
+          {{ getButtonDisplayName(OperationButtonType.TRANSFER) }}
+        </div>
+      </template>
+      <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
+        <el-form
+          label-position="top"
+          class="mb-auto"
+          ref="formRef"
+          :model="genericForm"
+          :rules="genericRule"
+          label-width="100px"
+        >
+                
+          <el-form-item label="新审批人" prop="assigneeUserId">
+            <el-select v-model="genericForm.assigneeUserId" clearable style="width: 100%">
+              <el-option
+                v-for="item in userOptions"
+                :key="item.id"
+                :label="item.nickname"
+                :value="item.id"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="审批意见" prop="reason">
+            <el-input v-model="genericForm.reason" clearable placeholder="请输入审批意见" type="textarea"  :rows="3" />
+          </el-form-item>
 
 
-    <!-- 【委托】按钮 -->
-    <div @click="handleDelegate" v-if="isShowButton(OperationButtonType.DELEGATE)">
-      <Icon :size="14" icon="ep:position" />&nbsp;
-      {{ getButtonDisplayName(OperationButtonType.DELEGATE) }}
-    </div>
 
 
-    <!-- 【加签】 -->
-    <div @click="handleSign" v-if="isShowButton(OperationButtonType.ADD_SIGN)">
-      <Icon :size="14" icon="ep:plus" />&nbsp;
-      {{ getButtonDisplayName(OperationButtonType.ADD_SIGN) }}
-    </div>
-    <!-- TODO @jason:减签 -->
+          <el-form-item>
+            <el-button :disabled="formLoading" type="primary"  @click="handleTransfer()">
+              {{ getButtonDisplayName(OperationButtonType.TRANSFER) }}
+            </el-button>
+            <el-button @click="popOverVisible.transfer = false"> 取消 </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-popover>
+    
+    <!-- 【委派】按钮 -->
+    <el-popover
+      :visible="popOverVisible.delegate"
+      placement="top-start"
+      :width="420"
+      trigger="click"
+      v-if="isShowButton(OperationButtonType.DELEGATE)"
+    >
+      <template #reference>
+        <div @click="openPopover('delegate')" class="hover-bg-gray-100 rounded-xl p-6px" >
+          <Icon :size="14" icon="ep:position" />&nbsp;
+          {{ getButtonDisplayName(OperationButtonType.DELEGATE) }}
+        </div>
+      </template>
+      
+      <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
+        <el-form
+          label-position="top"
+          class="mb-auto"
+          ref="formRef"
+          :model="genericForm"
+          :rules="genericRule"
+          label-width="100px"
+        >
+          <el-form-item label="接收人" prop="delegateUserId">
+            <el-select v-model="genericForm.delegateUserId" clearable style="width: 100%">
+              <el-option
+                v-for="item in userOptions"
+                :key="item.id"
+                :label="item.nickname"
+                :value="item.id"
+              />
+            </el-select>
+          </el-form-item>
+     
+          <el-form-item label="审批意见" prop="reason">
+            <el-input v-model="genericForm.reason" clearable placeholder="请输入审批意见" type="textarea"  :rows="3" />
+          </el-form-item>
 
 
-    <!-- 【退回】按钮 -->
-    <div @click="handleBack" v-if="isShowButton(OperationButtonType.RETURN)">
-      <Icon :size="14" icon="fa:mail-reply" />&nbsp;
-      {{ getButtonDisplayName(OperationButtonType.RETURN) }}
-    </div>
+          <el-form-item>
+            <el-button :disabled="formLoading" type="primary" @click="handleDelegate()">
+              {{ getButtonDisplayName(OperationButtonType.DELEGATE) }}
+            </el-button>
+            <el-button @click="popOverVisible.delegate = false"> 取消 </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+    </el-popover>
 
 
+    <!-- 【加签】按钮 当前任务审批人为A,向前加签选了一个C,则需要C先审批,然后再是A审批,向后加签B,A审批完,需要B再审批完,才算完成这个任务节点 -->
+    <el-popover
+      :visible="popOverVisible.addSign"
+      placement="top-start"
+      :width="420"
+      trigger="click"
+      v-if="isShowButton(OperationButtonType.ADD_SIGN)"
+    >
+      <template #reference>
+        <div @click="openPopover('addSign')" class="hover-bg-gray-100 rounded-xl p-6px" >
+          <Icon :size="14" icon="ep:plus" />&nbsp;
+          {{ getButtonDisplayName(OperationButtonType.ADD_SIGN) }}
+        </div>
+      </template>
+
+      <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
+        <el-form
+          label-position="top"
+          class="mb-auto"
+          ref="formRef"
+          :model="genericForm"
+          :rules="genericRule"
+          label-width="100px"
+        >
+          <el-form-item label="加签处理人" prop="addSignUserIds">
+            <el-select v-model="genericForm.addSignUserIds" multiple clearable style="width: 100%">
+              <el-option
+                v-for="item in userOptions"
+                :key="item.id"
+                :label="item.nickname"
+                :value="item.id"
+              />
+            </el-select>
+          </el-form-item>
+      
+          <el-form-item label="审批意见" prop="reason">
+            <el-input v-model="genericForm.reason" clearable placeholder="请输入审批意见" type="textarea"  :rows="3" />
+          </el-form-item>
+          <el-form-item>
+            <el-button :disabled="formLoading" type="primary" @click="handlerAddSign('before')">
+              向前{{ getButtonDisplayName(OperationButtonType.ADD_SIGN) }}
+            </el-button>
+            <el-button :disabled="formLoading" type="primary" @click="handlerAddSign('after')">
+              向后{{ getButtonDisplayName(OperationButtonType.ADD_SIGN) }}
+            </el-button>
+            <el-button @click="popOverVisible.addSign = false"> 取消 </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-popover>
+
+    <!-- TODO @jason:减签 -->
+    <!-- 【退回】按钮 -->
+    <el-popover
+      :visible="popOverVisible.return"
+      placement="top-start"
+      :width="420"
+      trigger="click"
+      v-if="isShowButton(OperationButtonType.RETURN)"
+    >
+      <template #reference>
+        <div @click="openReturnPopover" class="hover-bg-gray-100 rounded-xl p-6px" >
+          <Icon :size="14" icon="fa:mail-reply" />&nbsp;
+          {{ getButtonDisplayName(OperationButtonType.RETURN) }}
+        </div>
+      </template>
+      <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
+        <el-form
+          label-position="top"
+          class="mb-auto"
+          ref="formRef"
+          :model="genericForm"
+          :rules="genericRule"
+          label-width="100px"
+        >
+          <el-form-item label="退回节点" prop="targetTaskDefinitionKey">
+              <el-select v-model="genericForm.targetTaskDefinitionKey" clearable style="width: 100%">
+                <el-option
+                  v-for="item in returnList"
+                  :key="item.taskDefinitionKey"
+                  :label="item.name"
+                  :value="item.taskDefinitionKey"
+                />
+              </el-select>
+          </el-form-item>
+          <el-form-item label="退回理由" prop="returnReason">
+            <el-input v-model="genericForm.returnReason" clearable placeholder="请输入退回理由" type="textarea"  :rows="3" />
+          </el-form-item>
+          <el-form-item>
+            <el-button :disabled="formLoading" type="primary"  @click="handleReturn()">
+              {{ getButtonDisplayName(OperationButtonType.RETURN) }}
+            </el-button>
+            <el-button @click="popOverVisible.return = false"> 取消 </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-popover>
+   
     <!--TODO @jason:撤回 -->
     <!--TODO @jason:撤回 -->
     <!--TODO @jason:再次发起 -->
     <!--TODO @jason:再次发起 -->
   </div>
   </div>
-
-  <!-- 弹窗:转派审批人 -->
-  <TaskTransferForm ref="taskTransferFormRef" @success="getDetail" />
-  <!-- 弹窗:回退节点 -->
-  <TaskReturnForm ref="taskReturnFormRef" @success="getDetail" />
-  <!-- 弹窗:委派,将任务委派给别人处理,处理完成后,会重新回到原审批人手中-->
-  <TaskDelegateForm ref="taskDelegateForm" @success="getDetail" />
-  <!-- 弹窗:加签,当前任务审批人为A,向前加签选了一个C,则需要C先审批,然后再是A审批,向后加签B,A审批完,需要B再审批完,才算完成这个任务节点 -->
-  <TaskSignCreateForm ref="taskSignCreateFormRef" @success="getDetail" />
 </template>
 </template>
 <script lang="ts" setup>
 <script lang="ts" setup>
 import { setConfAndFields2 } from '@/utils/formCreate'
 import { setConfAndFields2 } from '@/utils/formCreate'
 import { useUserStore } from '@/store/modules/user'
 import { useUserStore } from '@/store/modules/user'
 import * as TaskApi from '@/api/bpm/task'
 import * as TaskApi from '@/api/bpm/task'
 import { propTypes } from '@/utils/propTypes'
 import { propTypes } from '@/utils/propTypes'
-import TaskReturnForm from './dialog/TaskReturnForm.vue'
-import TaskDelegateForm from './dialog/TaskDelegateForm.vue'
-import TaskTransferForm from './dialog/TaskTransferForm.vue'
-import TaskSignCreateForm from './dialog/TaskSignCreateForm.vue'
 import { isEmpty } from '@/utils/is'
 import { isEmpty } from '@/utils/is'
 import {
 import {
   OperationButtonType,
   OperationButtonType,
@@ -197,16 +367,32 @@ defineProps({
   userOptions: propTypes.any
   userOptions: propTypes.any
 })
 })
 const formLoading = ref(false) // 表单加载中
 const formLoading = ref(false) // 表单加载中
-const passVisible = ref(false) // 是否显示
-const rejectVisible = ref(false) // 是否显示
+/** 气泡卡是否展示 */
+const popOverVisible = ref({
+  approve: false,
+  reject: false,
+  transfer: false,
+  delegate: false,
+  addSign: false,
+  return : false,
+  copy: false
+})
+/** 退回节点 */
+const returnList = ref([] as any)
 // ========== 审批信息 ==========
 // ========== 审批信息 ==========
 const runningTask = ref<any>({}) // 运行中的任务
 const runningTask = ref<any>({}) // 运行中的任务
-const auditForm = ref<any>({}) // 审批任务的表单
+const genericForm = ref<any>({}) // 通用表单
 const approveForm = ref<any>({}) // 审批通过时,额外的补充信息
 const approveForm = ref<any>({}) // 审批通过时,额外的补充信息
 const approveFormFApi = ref<any>({}) // approveForms 的 fAPi
 const approveFormFApi = ref<any>({}) // approveForms 的 fAPi
 const formRef = ref()
 const formRef = ref()
-const auditRule = reactive({
-  reason: [{ required: true, message: '审批建议不能为空', trigger: 'blur' }]
+/** 表单校验规则 */
+const genericRule = reactive({
+  reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
+  returnReason: [{ required: true, message: '退回理由不能为空', trigger: 'blur' }],
+  copyUserIds: [{ required: true, message: '抄送人不能为空', trigger: 'change' }],
+  assigneeUserId:[{ required: true, message: '新审批人不能为空', trigger: 'change' }],
+  delegateUserId: [{ required: true, message: '接收人不能为空', trigger: 'change' }],
+  addSignUserIds: [{ required: true, message: '加签处理人不能为空', trigger: 'change' }]
 })
 })
 
 
 /** 监听 approveFormFApis,实现它对应的 form-create 初始化后,隐藏掉对应的表单提交按钮 */
 /** 监听 approveFormFApis,实现它对应的 form-create 初始化后,隐藏掉对应的表单提交按钮 */
@@ -227,7 +413,7 @@ watch(
  */
  */
 const loadRunningTask = (tasks: any[]) => {
 const loadRunningTask = (tasks: any[]) => {
   runningTask.value = {}
   runningTask.value = {}
-  auditForm.value = {}
+  genericForm.value = {}
   approveForm.value = {}
   approveForm.value = {}
   approveFormFApi.value = {}
   approveFormFApi.value = {}
   tasks.forEach((task: any) => {
   tasks.forEach((task: any) => {
@@ -244,7 +430,7 @@ const loadRunningTask = (tasks: any[]) => {
     }
     }
     // 2.3 添加到处理任务
     // 2.3 添加到处理任务
     runningTask.value = { ...task }
     runningTask.value = { ...task }
-    auditForm.value = {
+    genericForm.value = {
       reason: '',
       reason: '',
       copyUserIds: []
       copyUserIds: []
     }
     }
@@ -261,12 +447,12 @@ const loadRunningTask = (tasks: any[]) => {
 }
 }
 
 
 /** 处理审批通过和不通过的操作 */
 /** 处理审批通过和不通过的操作 */
-const handleAudit = async (pass: any) => {
+const handleAudit = async (pass: boolean) => {
   formLoading.value = true
   formLoading.value = true
   try {
   try {
-    const auditFormRef = proxy.$refs['formRef']
+    const genericFormRef = proxy.$refs['formRef']
     // 1.2 校验表单
     // 1.2 校验表单
-    const elForm = unref(auditFormRef)
+    const elForm = unref(genericFormRef)
     if (!elForm) return
     if (!elForm) return
     const valid = await elForm.validate()
     const valid = await elForm.validate()
     if (!valid) return
     if (!valid) return
@@ -274,8 +460,7 @@ const handleAudit = async (pass: any) => {
     // 2.1 提交审批
     // 2.1 提交审批
     const data = {
     const data = {
       id: runningTask.value.id,
       id: runningTask.value.id,
-      reason: auditForm.value.reason,
-      copyUserIds: auditForm.value.copyUserIds
+      reason: genericForm.value.reason
     }
     }
     if (pass) {
     if (pass) {
       // 审批通过,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
       // 审批通过,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
@@ -286,9 +471,11 @@ const handleAudit = async (pass: any) => {
         data.variables = approveForm.value.value
         data.variables = approveForm.value.value
       }
       }
       await TaskApi.approveTask(data)
       await TaskApi.approveTask(data)
+      popOverVisible.value.approve = false
       message.success('审批通过成功')
       message.success('审批通过成功')
     } else {
     } else {
       await TaskApi.rejectTask(data)
       await TaskApi.rejectTask(data)
+      popOverVisible.value.reject = false
       message.success('审批不通过成功')
       message.success('审批不通过成功')
     }
     }
     // 2.2 加载最新数据
     // 2.2 加载最新数据
@@ -298,40 +485,160 @@ const handleAudit = async (pass: any) => {
   }
   }
 }
 }
 
 
-/* 抄送 TODO */
-const handleSend = () => {}
-
-// TODO 代码优化:这里 flag 改成 approve: boolean 。因为 flag 目前就只有 1 和 2
-const openPopover = (flag) => {
-  passVisible.value = false
-  rejectVisible.value = false
-  formRef.value.resetFields()
-  flag === '1' ? (passVisible.value = true) : (rejectVisible.value = true)
+/* 处理抄送 */
+const handleCopy = async () => {
+  formLoading.value = true
+  try {
+    const copyFormRef = proxy.$refs['formRef']
+    // 1. 校验表单
+    const elForm = unref(copyFormRef)
+    if (!elForm) return
+    const valid = await elForm.validate()
+    if (!valid) return
+    // 2. 提交抄送
+    const data = {
+      id: runningTask.value.id,
+      reason: genericForm.value.copyReason,
+      copyUserIds: genericForm.value.copyUserIds
+    }
+    await TaskApi.copyTask(data)
+    popOverVisible.value.copy = false
+    message.success('操作成功')
+  } finally {
+    formLoading.value = false
+  }
 }
 }
 
 
-/** 转派审批人 */
-const taskTransferFormRef = ref()
-const openTaskUpdateAssigneeForm = () => {
-  taskTransferFormRef.value.open(runningTask.value.id)
+/** 处理转交 */
+const handleTransfer = async () => {
+   
+  formLoading.value = true
+  try {
+    const transferFormRef = proxy.$refs['formRef']
+    // 1.1 校验表单
+    const elForm = unref(transferFormRef)
+    if (!elForm) return
+    const valid = await elForm.validate()
+    if (!valid) return
+    // 1.2 提交转交
+    const data = {
+      id: runningTask.value.id,
+      reason: genericForm.value.reason,
+      assigneeUserId: genericForm.value.assigneeUserId
+    }
+  
+    await TaskApi.transferTask(data)
+    popOverVisible.value.transfer = false
+    message.success('操作成功')
+    // 2. 加载最新数据
+    getDetail()
+  } finally {
+    formLoading.value = false
+  }
 }
 }
 
 
-/** 处理审批退回的操作 */
-const taskDelegateForm = ref()
+/** 处理委派 */
 const handleDelegate = async () => {
 const handleDelegate = async () => {
-  taskDelegateForm.value.open(runningTask.value.id)
+   formLoading.value = true
+   try {
+     const deletegateFormRef = proxy.$refs['formRef']
+     // 1.1 校验表单
+     const elForm = unref(deletegateFormRef)
+     if (!elForm) return
+     const valid = await elForm.validate()
+     if (!valid) return
+     // 1.2 处理委派
+     const data = {
+       id: runningTask.value.id,
+       reason: genericForm.value.reason,
+       delegateUserId: genericForm.value.delegateUserId
+     }
+   
+     await TaskApi.delegateTask(data)
+     popOverVisible.value.delegate = false
+     message.success('操作成功')
+     // 2. 加载最新数据
+     getDetail()
+   } finally {
+     formLoading.value = false
+   }
+ }
+
+/** 处理加签 */
+const handlerAddSign = async (type: string) => {
+  formLoading.value = true
+  try {
+    const transferFormRef = proxy.$refs['formRef']
+    // 1.1 校验表单
+    const elForm = unref(transferFormRef)
+    if (!elForm) return
+    const valid = await elForm.validate()
+    if (!valid) return
+    // 1.2 提交加签
+    const data = {
+      id: runningTask.value.id,
+      type,
+      reason: genericForm.value.reason,
+      userIds: genericForm.value.addSignUserIds
+    }
+    await TaskApi.signCreateTask(data)
+    message.success('操作成功')
+    popOverVisible.value.addSign = false
+    // 2 加载最新数据
+    getDetail()
+  } finally {
+    formLoading.value = false
+  }
 }
 }
 
 
-/** 处理审批退回的操作 */
-const taskReturnFormRef = ref()
-const handleBack = async () => {
-  taskReturnFormRef.value.open(runningTask.value.id)
+/** 处理退回 */
+const handleReturn = async () => {
+  formLoading.value = true
+  try {
+    const returnFormRef = proxy.$refs['formRef']
+    // 1.1 校验表单
+    const elForm = unref(returnFormRef)
+    if (!elForm) return
+    const valid = await elForm.validate()
+    if (!valid) return
+    // 1.2 提交退回
+    const data = {
+      id: runningTask.value.id,
+      reason: genericForm.value.returnReason,
+      targetTaskDefinitionKey: genericForm.value.targetTaskDefinitionKey
+    }
+  
+    await TaskApi.returnTask(data)
+    popOverVisible.value.return = false
+    message.success('操作成功')
+    // 2 加载最新数据
+    getDetail()
+  } finally {
+    formLoading.value = false
+  }
 }
 }
 
 
-/** 处理审批加签的操作 */
-const taskSignCreateFormRef = ref()
-const handleSign = async () => {
-  taskSignCreateFormRef.value.open(runningTask.value.id)
+/** 弹出退回气泡卡 */
+const openReturnPopover = async  () => {
+  returnList.value = await TaskApi.getTaskListByReturn(runningTask.value.id)
+  if (returnList.value.length === 0) {
+    message.warning('当前没有可退回的节点')
+    return
+  }
+  openPopover('return')
 }
 }
+/** 弹出气泡卡 */
+const openPopover = (type: string ) => {
+  Object.keys(popOverVisible.value).forEach( item => {
+    if( item === type) {
+      popOverVisible.value[item] = true
+    } else {
+      popOverVisible.value[item] = false
+    }
+  })
+  formRef.value.resetFields()
+}
+
 /** 获得详情 */
 /** 获得详情 */
 const getDetail = () => {
 const getDetail = () => {
   emit('success')
   emit('success')

+ 11 - 6
src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue

@@ -14,7 +14,7 @@
         <div class="flex items-center mt-1">
         <div class="flex items-center mt-1">
           <!-- 情况一:遍历每个审批节点下的【进行中】task 任务 -->
           <!-- 情况一:遍历每个审批节点下的【进行中】task 任务 -->
           <div v-for="(task, idx) in activity.tasks" :key="idx" class="flex items-center">
           <div v-for="(task, idx) in activity.tasks" :key="idx" class="flex items-center">
-            <div class="flex items-center flex-col pr-2">
+            <div class="flex flex-col pr-2">
               <div class="position-relative" v-if="task.assigneeUser || task.ownerUser">
               <div class="position-relative" v-if="task.assigneeUser || task.ownerUser">
                 <!-- 信息:头像 -->
                 <!-- 信息:头像 -->
                 <el-avatar
                 <el-avatar
@@ -47,7 +47,7 @@
                 <!-- 信息:昵称 -->
                 <!-- 信息:昵称 -->
                 <div
                 <div
                   v-if="task.assigneeUser && task.assigneeUser.nickname"
                   v-if="task.assigneeUser && task.assigneeUser.nickname"
-                  class="text-10px text-align-center"
+                  class="text-12px text-align-center"
                 >
                 >
                   {{ task.assigneeUser.nickname }}
                   {{ task.assigneeUser.nickname }}
                 </div>
                 </div>
@@ -57,14 +57,20 @@
                 >
                 >
                   {{ task.ownerUser.nickname }}
                   {{ task.ownerUser.nickname }}
                 </div>
                 </div>
-                <!-- TODO @jason:审批意见,要展示哈。 -->
-                <!-- <div v-if="task.reason" :title="task.reason" class="text-13px text-truncate w-150px mt-1"> 审批意见: {{ task.reason }}</div> -->
+                <div v-if="task.reason" class="text-#a5a5a5 my-4px text-12px flex items-center w-100%">
+                  <div
+                    :title="task.reason"
+                    class="text-truncate w-200px border-1px border-#a5a5a5 border-dashed rounded py-5px px-15px text-#2d2d2d"
+                  >
+                    {{ task.reason }}
+                  </div>
+                </div>
               </div>
               </div>
             </div>
             </div>
           </div>
           </div>
           <!-- 情况二:遍历每个审批节点下的【候选的】task 任务。例如说,1)依次审批,2)未来的审批任务等 -->
           <!-- 情况二:遍历每个审批节点下的【候选的】task 任务。例如说,1)依次审批,2)未来的审批任务等 -->
           <div
           <div
-            v-for="(user, idx1) in activity.candidateUserList"
+            v-for="(user, idx1) in activity.candidateUsers"
             :key="idx1"
             :key="idx1"
             class="flex items-center"
             class="flex items-center"
           >
           >
@@ -91,7 +97,6 @@
                 <div v-if="user.nickname" class="text-10px text-align-center">
                 <div v-if="user.nickname" class="text-10px text-align-center">
                   {{ user.nickname }}
                   {{ user.nickname }}
                 </div>
                 </div>
-                <!-- <div v-if="task.reason" :title="task.reason" class="text-13px text-truncate w-150px mt-1"> 审批意见: {{ task.reason }}</div> -->
               </div>
               </div>
             </div>
             </div>
           </div>
           </div>

+ 62 - 31
src/views/bpm/processInstance/detail/index_new.vue

@@ -12,25 +12,37 @@
         <el-divider class="!my-8px" />
         <el-divider class="!my-8px" />
         <div class="flex items-center gap-5 mb-10px h-40px">
         <div class="flex items-center gap-5 mb-10px h-40px">
           <div class="text-26px font-bold mb-5px">{{ processInstance.name }}</div>
           <div class="text-26px font-bold mb-5px">{{ processInstance.name }}</div>
-          <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="processInstance.status" />
+          <dict-tag
+            v-if="processInstance.status"
+            :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
+            :value="processInstance.status"
+          />
         </div>
         </div>
 
 
         <div class="flex items-center gap-5 mb-10px text-13px h-35px">
         <div class="flex items-center gap-5 mb-10px text-13px h-35px">
           <div
           <div
             class="bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600"
             class="bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600"
           >
           >
-            <img class="rounded-full h-28px" src="@/assets/imgs/avatar.jpg" alt="" />
+            <!-- <img class="rounded-full h-28px" src="@/assets/imgs/avatar.jpg" alt="" /> -->
+            <el-avatar
+              :size="28"
+              v-if="processInstance?.startUser?.avatar"
+              :src="processInstance?.startUser?.avatar"
+            />
+            <el-avatar :size="28" v-else-if="processInstance?.startUser?.nickname">
+              {{ processInstance?.startUser?.nickname.substring(0, 1) }}
+            </el-avatar>
             {{ processInstance?.startUser?.nickname }}
             {{ processInstance?.startUser?.nickname }}
           </div>
           </div>
           <div class="text-#878c93"> {{ formatDate(processInstance.startTime) }} 提交 </div>
           <div class="text-#878c93"> {{ formatDate(processInstance.startTime) }} 提交 </div>
         </div>
         </div>
 
 
-        <el-tabs v-model="activeTab">
+        <el-tabs v-model="activeTab" @tab-change="onTabChange">
           <!-- 表单信息 -->
           <!-- 表单信息 -->
           <el-tab-pane label="审批详情" name="form">
           <el-tab-pane label="审批详情" name="form">
             <div class="form-scroll-area">
             <div class="form-scroll-area">
               <el-scrollbar>
               <el-scrollbar>
-                <el-row :gutter="10">
+                <el-row>
                   <el-col :span="18" class="!flex !flex-col formCol">
                   <el-col :span="18" class="!flex !flex-col formCol">
                     <!-- 表单信息 -->
                     <!-- 表单信息 -->
                     <div
                     <div
@@ -38,11 +50,7 @@
                       class="form-box flex flex-col mb-30px flex-1"
                       class="form-box flex flex-col mb-30px flex-1"
                     >
                     >
                       <!-- 情况一:流程表单 -->
                       <!-- 情况一:流程表单 -->
-                      <el-col
-                        v-if="processInstance?.processDefinition?.formType === 10"
-                        :offset="6"
-                        :span="16"
-                      >
+                      <el-col v-if="processInstance?.processDefinition?.formType === 10">
                         <form-create
                         <form-create
                           v-model="detailForm.value"
                           v-model="detailForm.value"
                           v-model:api="fApi"
                           v-model:api="fApi"
@@ -64,27 +72,36 @@
               </el-scrollbar>
               </el-scrollbar>
             </div>
             </div>
           </el-tab-pane>
           </el-tab-pane>
+
           <!-- 流程图 -->
           <!-- 流程图 -->
           <el-tab-pane label="流程图" name="diagram">
           <el-tab-pane label="流程图" name="diagram">
-            <ProcessInstanceBpmnViewer :id="`${id}`" :loading="processInstanceLoading" />
+            <div class="form-scroll-area">
+              <ProcessInstanceBpmnViewer :id="`${id}`" :loading="processInstanceLoading" />
+            </div>
           </el-tab-pane>
           </el-tab-pane>
+
           <!-- 流转记录 -->
           <!-- 流转记录 -->
           <el-tab-pane label="流转记录" name="record">
           <el-tab-pane label="流转记录" name="record">
-            <ProcessInstanceTaskList
-              :loading="tasksLoad"
-              :process-instance="processInstance"
-              :tasks="tasks"
-              @refresh="getTaskList"
-            />
+            <div class="form-scroll-area">
+              <el-scrollbar>
+                <ProcessInstanceTaskList
+                  :loading="tasksLoad"
+                  :process-instance="processInstance"
+                  :tasks="tasks"
+                />
+              </el-scrollbar>
+            </div>
           </el-tab-pane>
           </el-tab-pane>
+
           <!-- 流转评论 TODO 待开发 -->
           <!-- 流转评论 TODO 待开发 -->
-          <el-tab-pane label="流转评论" name="comment"> 流转评论 </el-tab-pane>
+          <el-tab-pane label="流转评论" name="comment">
+            <div class="form-scroll-area">
+              <el-scrollbar> 流转评论 </el-scrollbar>
+            </div>
+          </el-tab-pane>
         </el-tabs>
         </el-tabs>
 
 
-        <div
-          class="b-t-solid border-t-1px border-[var(--el-border-color)]"
-          v-if="activeTab === 'form'"
-        >
+        <div class="b-t-solid border-t-1px border-[var(--el-border-color)]">
           <!-- 操作栏按钮 -->
           <!-- 操作栏按钮 -->
           <ProcessInstanceOperationButton
           <ProcessInstanceOperationButton
             ref="operationButtonRef"
             ref="operationButtonRef"
@@ -125,6 +142,7 @@ const props = defineProps<{
 const message = useMessage() // 消息弹窗
 const message = useMessage() // 消息弹窗
 const processInstanceLoading = ref(false) // 流程实例的加载中
 const processInstanceLoading = ref(false) // 流程实例的加载中
 const processInstance = ref<any>({}) // 流程实例
 const processInstance = ref<any>({}) // 流程实例
+let processDefinitionId = undefined // 流程定义 Id
 const operationButtonRef = ref()
 const operationButtonRef = ref()
 const timelineRef = ref()
 const timelineRef = ref()
 const bpmnXml = ref('') // BPMN XML
 const bpmnXml = ref('') // BPMN XML
@@ -145,10 +163,10 @@ const detailForm = ref({
 }) // 流程实例的表单详情
 }) // 流程实例的表单详情
 
 
 /** 获得详情 */
 /** 获得详情 */
-const getDetail = () => {
+const getDetail = async () => {
   // 1. 获得流程实例相关
   // 1. 获得流程实例相关
   getProcessInstance()
   getProcessInstance()
-  // 2. 获得流程任务列表(审批记录)
+  // 2. 获得流程任务列表
   getTaskList()
   getTaskList()
 }
 }
 
 
@@ -176,12 +194,18 @@ const getProcessInstance = async () => {
           activityId: props.activityId
           activityId: props.activityId
         })
         })
       }
       }
-      setConfAndFields2(
-        detailForm,
-        processDefinition.formConf,
-        processDefinition.formFields,
-        data.formVariables
-      )
+
+      if (detailForm.value.rule.length > 0) {  // 避免刷新 form-create 表单不显示
+        detailForm.value.value = data.formVariables
+      } else {
+        setConfAndFields2(
+          detailForm,
+          processDefinition.formConf,
+          processDefinition.formFields,
+          data.formVariables
+        )
+      }
+
       nextTick().then(() => {
       nextTick().then(() => {
         fApi.value?.btn.show(false)
         fApi.value?.btn.show(false)
         fApi.value?.resetBtn.show(false)
         fApi.value?.resetBtn.show(false)
@@ -196,9 +220,9 @@ const getProcessInstance = async () => {
       // 注意:data.processDefinition.formCustomViewPath 是组件的全路径,例如说:/crm/contract/detail/index.vue
       // 注意:data.processDefinition.formCustomViewPath 是组件的全路径,例如说:/crm/contract/detail/index.vue
       BusinessFormComponent.value = registerComponent(data.processDefinition.formCustomViewPath)
       BusinessFormComponent.value = registerComponent(data.processDefinition.formCustomViewPath)
     }
     }
-
+    processDefinitionId = processDefinition.id
     // 加载流程图
     // 加载流程图
-    bpmnXml.value = (await DefinitionApi.getProcessDefinition(processDefinition.id))?.bpmnXml
+    // bpmnXml.value = (await DefinitionApi.getProcessDefinition(processDefinition.id))?.bpmnXml
   } finally {
   } finally {
     processInstanceLoading.value = false
     processInstanceLoading.value = false
   }
   }
@@ -267,6 +291,13 @@ const refresh = () => {
 /** 当前的Tab */
 /** 当前的Tab */
 const activeTab = ref('form')
 const activeTab = ref('form')
 
 
+/** Tab 切换 加载流程图,直接加载显示不出来,不知道啥原因,所以切换以后在加载 */
+const onTabChange = async (tabName: string) => {
+  if (tabName === 'diagram' && processDefinitionId && !bpmnXml.value) {
+    //加载流程图
+    bpmnXml.value = (await DefinitionApi.getProcessDefinition(processDefinitionId))?.bpmnXml
+  }
+}
 /** 初始化 */
 /** 初始化 */
 const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
 const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
 onMounted(async () => {
 onMounted(async () => {

+ 1 - 0
src/views/bpm/task/copy/index.vue

@@ -55,6 +55,7 @@
       />
       />
       <el-table-column align="center" label="抄送任务" prop="taskName" min-width="180" />
       <el-table-column align="center" label="抄送任务" prop="taskName" min-width="180" />
       <el-table-column align="center" label="抄送人" prop="creatorName" min-width="100" />
       <el-table-column align="center" label="抄送人" prop="creatorName" min-width="100" />
+      <el-table-column align="center" label="抄送意见" prop="reason" width="150" />
       <el-table-column
       <el-table-column
         align="center"
         align="center"
         label="抄送时间"
         label="抄送时间"