xiangpei
2025-05-06 5c929cfb5286a31a4e067cbc61e8774f4e7d42ae
src/views/flowable/task/myProcess/send/index.vue
@@ -3,58 +3,72 @@
    <el-card class="box-card" >
      <div slot="header" class="clearfix" style="display: flex">
        <div style="flex: 1" class="el-icon-document">{{`任务办理:` + processName}}</div>
        <div style="flex: 2">{{projectName + '——' + flowName}}</div>
        <div style="flex: 2; color: #303133">{{projectName + '——' + flowName}}</div>
        <el-button style="float: right;" size="mini" type="danger" @click="goBack">关闭</el-button>
      </div>
      <el-tabs  tab-position="top" v-model="activeName"  @tab-click="handleClick">
        <!--表单信息-->
        <el-tab-pane label="表单信息" name="1">
          <!--初始化流程加载表单信息-->
          <el-col :span="16" :offset="4">
          <el-col :span="24" v-loading="formLoading"  class="tab-min-height">
            <div v-if="formDataList && formDataList.length > 0">
              <div v-for="(formDataObj, index) in formDataList" :key="index" class="form-warp" style="position: relative">
                <div v-if="formDataObj.current">
                  <!--     当前节点可协同、转办等操作         -->
                  <div style="position: absolute; top: 4px; right: 4px; display: flex;justify-content: center; align-items: center;">
                    <el-button size="small" type="primary" @click="submitForm">确认并提交</el-button>
                    <el-button size="small" type="primary" disabled @click="submitForm">协同办理(功能开发中)</el-button>
                    <el-button size="small" type="primary" @click="openDelegation(formDataList[0].beforeNodeName)">转办</el-button>
                  </div>
                  <div style="margin-bottom: 15px;color: #E6A23C">当前阶段:<span style="color: #409EFF">{{formDataObj.beforeNodeName}}</span></div>
                </div>
                <div v-else-if="formDataList.length > 1">
                  <!--     前置节点可驳回         -->
                  <div style="position: absolute; top: 4px; right: 4px">
                    <el-button type="danger" size="small" @click="openRejectTask(formDataObj.beforeNodeDefId)">驳 回</el-button>
                  </div>
                  <div style="margin-bottom: 15px;color: #E6A23C">前置阶段:<span style="color: #F56C6C">{{formDataObj.beforeNodeName}}</span></div>
                </div>
                <div v-if="formDataObj.formJson !== null && formDataObj.formJson !== ''">
                  <v-form-render  :form-data="formDataObj.formJson" :ref="'form' + index"/>
                </div>
                <div v-else>
                  <el-alert
                    title="节点未绑定表单"
                    type="warning"
                    :closable="false"
                  >
                  </el-alert>
                </div>
                <div v-if="formDataList.length <= 1">
                  <el-alert
                    title="不存在前置节点"
                    type="warning"
                    :closable="false"
                  >
                  </el-alert>
                </div>
              <div v-for="(formDataObj, index) in formDataList" :key="index" class="form-warp">
                <el-row>
                  <el-col :span="18" style="position: relative">
                    <div v-if="formDataObj.current">
                      <!--     当前节点可协同、转办等操作         -->
                      <div class="op-list">
                        <el-button size="small" type="primary" :disabled="formDataObj.taskStatus === '挂起' || submitLoading" v-loading="submitLoading" @click="submitForm">确认并提交</el-button>
                        <!--                    <el-button size="small" type="primary" disabled @click="submitForm">协同办理(功能开发中)</el-button>-->
                        <el-button size="small" type="primary" v-if="!isWait" :disabled="formDataObj.taskStatus === '挂起'" @click="openDelegation(formDataList[0].beforeNodeName)">转办</el-button>
                        <el-button v-if="formDataObj.canJump && !isWait" :disabled="formDataObj.taskStatus === '挂起'" size="small" type="primary" @click="jumpTask()">跳过</el-button>
                        <el-button v-if="formDataObj.canWait && !isWait" :disabled="formDataObj.taskStatus === '挂起'" size="small" type="primary" @click="waitTask()">容缺</el-button>
                        <el-button v-if="formDataObj.canHangup && formDataObj.taskStatus !== '挂起' && !isWait" size="small" type="primary" @click="hangup">挂起</el-button>
                        <el-button v-if="formDataObj.canHangup && formDataObj.taskStatus === '挂起' && !isWait" size="small" type="primary" @click="cancelHangup">结束挂起</el-button>
                      </div>
                      <div class="current">当前阶段:<span>{{formDataObj.beforeNodeName}}</span><span v-if="formDataObj.taskStatus === 'HANGUP'">(挂起中)</span></div>
                    </div>
                    <div v-else-if="formDataList.length > 1">
                      <!--     前置节点可驳回         -->
                      <div class="reject-but">
                        <el-button type="danger" size="small" @click="openRejectTask(formDataObj.beforeNodeName)">驳 回</el-button>
                      </div>
                      <div class="before">前置阶段:<span>{{formDataObj.beforeNodeName}}</span></div>
                    </div>
                    <div v-if="formDataObj != null && formDataObj.formJsonObj != null">
                      <v-form-render  :form-data="formDataObj.formJsonObj.formJson" :ref="'form' + index"/>
                    </div>
                    <div v-else>
                      <el-alert
                        title="未绑定表单"
                        type="warning"
                        :closable="false"
                      >
                      </el-alert>
                    </div>
                    <div v-if="formDataList.length <= 1">
                      <div class="before_none">前置阶段:<span>不存在前置阶段</span></div>
                      <el-alert
                        title="不存在前置阶段"
                        type="warning"
                        :closable="false"
                      >
                      </el-alert>
                    </div>
                  </el-col>
                  <el-col :span="6">
                    <log-time-line v-if="formDataObj.events.length > 0" :log-list="formDataObj.events"/>
                  </el-col>
                </el-row>
              </div>
            </div>
          </el-col>
        </el-tab-pane>
        <!--流程图-->
        <el-tab-pane label="流程图" name="2">
          <bpmn-viewer :flowData="flowData" :procInsId="procInsId"/>
          <div v-loading="imgLoading" class="tab-min-height">
            <bpmn-viewer :flowData="flowData" :procInsId="procInsId"/>
          </div>
        </el-tab-pane>
      </el-tabs>
      <!--选择流程接收人-->
@@ -70,7 +84,7 @@
    <el-dialog
      :title="`驳回:` + rejectForm.projectName"
      :title="`驳回:` + rejectForm.taskName"
      :visible.sync="rejectShow"
      width="950px"
      :destroy-on-close="true"
@@ -85,7 +99,7 @@
        </el-input>
      </div>
      <div class="opBut">
        <el-button type="danger" size="small" @click="rejectTask">驳回</el-button>
        <el-button type="danger" size="small" :disabled="rejectLoading" v-loading="rejectLoading" @click="rejectTask">驳回</el-button>
      </div>
    </el-dialog>
@@ -152,7 +166,7 @@
        </el-form>
      </div>
      <div class="opBut">
        <el-button type="danger" size="small" @click="delegation">转 办</el-button>
        <el-button type="danger" size="small" :disabled="delegationButLoading" v-loading="delegationButLoading" @click="delegation">转 办</el-button>
      </div>
    </el-dialog>
@@ -166,11 +180,13 @@
import SingleUser from '@/components/flow/User/SingleUser'
import MultUser from '@/components/flow/User/MultUser'
import MyRole from '@/components/flow/Role/MyRole'
import {completeSubmitFormTask} from "@/api/flowable/process";
import {completeSubmitFormTask, waitCompleteSubmitFormTask} from "@/api/flowable/process";
import { flowTaskForm } from "@/api/flowable/todo";
import {getNextFlowNodeByStart} from "@/api/flowable/todo";
import LogView from "@/views/projectProcess/components/LogView";
import LogTimeLine from "@/views/projectProcess/components/LogTimeLine";
import {rejectTask} from "@/api/flowable/process";
import {taskDelegation} from "@/api/projectProcess/projectProcess";
import {cancelTaskHangup, taskDelegation, taskHangup, taskJump, taskWait} from "@/api/projectProcess/projectProcess";
export default {
  name: "Record",
@@ -180,10 +196,19 @@
    MyDept,
    SingleUser,
    MultUser,
    LogView,
    LogTimeLine
  },
  props: {},
  data() {
    return {
      isWait: false,
      jumpDesc: '', // 跳过说明
      rejectLoading: false, // 驳回按钮加载
      submitLoading: false, // 提交按钮加载
      delegationButLoading: false, // 转办按钮加载
      formLoading: false,  // 加载当前喝前置节点数据
      imgLoading: false,  // 加载流程图
      roleKey: 'role',
      deptKey: 'dept',
      multUserKey: 0,
@@ -209,7 +234,9 @@
        taskId: '',
        peopleType: '',
        targetId: '',
        taskName: ''
        taskName: '',
        processInsId: '',
        projectId: '',
      },
      delegationShow: false, // 转办显示
      rejectShow: false, // 驳回显示
@@ -244,7 +271,7 @@
      rejectForm: {
        comment: '', // 审核意见
        taskId: '',
        // rejectedTaskDefKey: ''  // 被驳回的任务key
        taskName: ''  // 被驳回的任务k
      }
    };
  },
@@ -253,15 +280,123 @@
    this.deployId = this.$route.query && this.$route.query.deployId;
    this.taskId = this.$route.query && this.$route.query.taskId;
    this.projectName = this.$route.query && this.$route.query.projectName;
    this.projectId = this.$route.query && this.$route.query.projectId;
    this.flowName = this.$route.query && this.$route.query.flowName;
    // 初始化表单
    this.procDefId  = this.$route.query && this.$route.query.procDefId;
    this.procInsId  = this.$route.query && this.$route.query.procInsId;
    this.goBackParams  = this.$route.query && this.$route.query.goBackParams;
    this.isWait = this.$route.query && this.$route.query.isWait === 'true' ? true : false;
    // this.getNextFlowNodeByStart(this.deployId);
    this.getFlowFormData(this.taskId);
  },
  methods: {
    // 挂起任务
    hangup() {
      this.$prompt('备注说明', '确定要挂起此任务吗', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputType: 'textarea'
        // inputPattern: /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
        // inputErrorMessage: '邮箱格式不正确'
      }).then(({ value }) => {
        let hangupForm = {
          taskId: this.taskId,
          projectId: this.projectId,
          processInsId: this.procInsId,
          reason: value
        }
        taskHangup(hangupForm).then(res => {
          this.$message.success("操作成功")
          this.goBack()
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消挂起操作'
        });
      });
    },
    // 挂起任务
    cancelHangup() {
      this.$confirm('确定要取消挂起吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        let cancelHangupForm = {
          taskId: this.taskId,
          projectId: this.projectId,
          processInsId: this.procInsId
        }
        cancelTaskHangup(cancelHangupForm).then(res => {
          this.$message.success("操作成功")
          this.goBack()
        })
      })
    },
    // 容缺任务
    waitTask() {
      this.$prompt('备注说明', '确定要容缺此任务吗', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputType: 'textarea',
        inputValidator: (value) => {
          if (!value || value.trim() === '') {
            return "请填写备注说明"
          }
          return true
        },
        inputErrorMessage: '请填写备注说明'
      }).then(({ value }) => {
        let waitForm = {
          taskId: this.taskId,
          projectId: this.projectId,
          processInsId: this.procInsId,
          desc: value
        }
        taskWait(waitForm).then(res => {
          this.$message.success("操作成功")
          this.goBack()
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消容缺操作'
        });
      });
    },
    // 跳过任务
    jumpTask() {
      this.$prompt('备注说明', '确定要跳过此任务吗', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputType: 'textarea',
        inputValidator: (value) => {
          if (!value || value.trim() === '') {
            return "请填写备注说明"
          }
          return true
        },
        inputErrorMessage: '请填写备注说明'
      }).then(({ value }) => {
        let jumpForm = {
          taskId: this.taskId,
          projectId: this.projectId,
          processInsId: this.procInsId,
          desc: value
        }
        taskJump(jumpForm).then(res => {
          this.$message.success("操作成功")
          this.goBack()
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消跳过操作'
        });
      });
    },
    removeDept(dept) {
      let index = this.delegationDeptSelect.indexOf(dept);
      if (index !== -1) {
@@ -305,8 +440,13 @@
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            this.delegationForm.projectId = this.projectId
            this.delegationForm.processInsId = this.procInsId
            this.delegationButLoading = true
            taskDelegation(this.delegationForm).then(res => {
              this.$message.success("已发起转办申请")
              this.delegationButLoading = false
              this.delegationShow = false
              this.goBack()
            })
          }).catch(() => {
@@ -434,19 +574,36 @@
      this.delegationShow = true
    },
    rejectTask() {
      rejectTask(this.rejectForm).then(res => {
        this.rejectShow = false
        this.$message.success("驳回成功")
      })
      this.$confirm(`确定要驳回任务【${this.rejectForm.taskName}】吗?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.rejectLoading = true
        rejectTask(this.rejectForm).then(res => {
          this.rejectShow = false
          this.$message.success("驳回成功")
          this.goBack()
        })
      }).catch((err) => {
        console.log(err)
        this.$message({
          type: 'info',
          message: '已取驳回交操作'
        });
      });
    },
    openRejectTask(rejectedTaskDefKey) {
      // this.rejectForm.rejectedTaskDefKey = rejectedTaskDefKey;
    openRejectTask(taskName) {
      this.rejectForm.taskName = taskName;
      this.rejectForm.taskId = this.taskId;
      this.rejectShow = true
    },
    handleClick(tab, event) {
      if (tab.name === '2'){
        flowXmlAndNode({procInsId:this.procInsId,deployId:this.deployId}).then(res => {
        this.imgLoading = true
        flowXmlAndNode({processInsId:this.procInsId,deployId:this.deployId}).then(res => {
          this.imgLoading = false
          this.flowData = res.data;
        })
      }
@@ -454,13 +611,13 @@
    /** 流程表单数据 */
    getFlowFormData(taskId) {
      const params = {taskId: taskId}
      this.formLoading = true
      flowTaskForm(params).then(res => {
        this.formDataList = res.data
        if (this.formDataList && this.formDataList.length > 0) {
          this.$nextTick(() => {
            this.formDataList.forEach((formDataObj, index) => {
              let that = this
              console.log(eval("that.$refs.form" +index))
              if (eval("that.$refs.form" +index) && formDataObj.formJsonObj) {
                eval("that.$refs.form" +index)[0].setFormJson(formDataObj.formJsonObj.formJson);
                eval("that.$refs.form" +index)[0].setFormData(formDataObj.formJsonObj);
@@ -470,8 +627,8 @@
              this.formJson = this.formDataList[0].formJsonObj.formJson
            }
          })
        }
        this.formLoading = false
        // if (res.data.formJson) {
        //   // 回显表单
        //   this.$refs.vFormRef.setFormJson(res.data.formJson);
@@ -503,7 +660,7 @@
      this.$router.push({
        path: '/projectFlow/detail',
        query: {
          projectId: this.goBackParams.projectId,
          projectId: this.projectId,
          processDefId: this.goBackParams.processDefId,
          processName: this.goBackParams.processName
        }
@@ -511,54 +668,60 @@
    },
    /** 申请流程表单数据提交 */
    submitForm() {
      let that = this
      eval("that.$refs.form" +0)[0].getFormData().then(formData => {
        // 根据当前任务或者流程设计配置的下一步节点 todo 暂时未涉及到考虑网关、表达式和多节点情况
        getNextFlowNodeByStart({deploymentId: this.deployId, variables: formData}).then(res => {
          const data = res.data;
          if (data) {
            this.formData = formData;
            if (data.dataType === 'dynamic') {
              if (data.type === 'assignee') { // 指定人员
                this.checkSendUser = true;
                this.checkType = "single";
              } else if (data.type === 'candidateUsers') {  // 候选人员(多个)
                this.checkSendUser = true;
                this.checkType = "multiple";
              } else if (data.type === 'candidateGroups') { // 指定组(所属角色接收任务)
                this.checkSendRole = true;
              } else { // 会签
                // 流程设计指定的 elementVariable 作为会签人员列表
                this.multiInstanceVars = data.vars;
                this.checkSendUser = true;
                this.checkType = "multiple";
              }
              this.taskOpen = true;
              this.taskTitle = "选择任务接收";
            } else {
              if (this.procDefId) {
                const param = {
                  formJson:  this.formJson,
                }
                // 复制对象的属性值给新的对象
                Object.assign(param, formData);
                // 完成任务
                completeSubmitFormTask(this.taskId, param).then(res => {
                  this.$modal.msgSuccess(res.msg);
                  this.goBack();
                })
                // // 启动流程并将表单数据加入流程变量
                // definitionStart(this.procDefId, param).then(res => {
                //   this.$modal.msgSuccess(res.msg);
                //   this.goBack();
                // })
              }
      this.$confirm(`确定要提交任务【${this.processName}】吗?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        let that = this
        if (eval("that.$refs.form" +0)) {
          eval("that.$refs.form" +0)[0].getFormData().then(formData => {
            this.submitLoading = true
            this.formData = formData
            const param = {
              formJson:  this.formJson,
            }
            // 复制对象的属性值给新的对象
            Object.assign(param, formData);
            // 完成任务
            if (this.isWait) {
              waitCompleteSubmitFormTask(this.taskId, param).then(res => {
                this.$modal.msgSuccess(res.msg);
                this.submitLoading = false
                this.goBack();
              })
            } else {
              completeSubmitFormTask(this.taskId, param).then(res => {
                this.$modal.msgSuccess(res.msg);
                this.submitLoading = false
                this.goBack();
              })
            }
          })
        } else {
          // 没关联表单直接传空
          if (this.isWait) {
              waitCompleteSubmitFormTask(this.taskId, {}).then(res => {
              this.$modal.msgSuccess(res.msg);
              this.submitLoading = false
              this.goBack();
            })
          } else {
            completeSubmitFormTask(this.taskId, {}).then(res => {
              this.$modal.msgSuccess(res.msg);
              this.submitLoading = false
              this.goBack();
            })
          }
        })
      }).catch(error => {
        // this.$modal.msgError(error)
      })
        }
      }).catch((err) => {
        console.log(err)
        this.$message({
          type: 'info',
          message: '已取消提交操作'
        });
      });
    },
    /** 重置表单 */
    resetForm() {
@@ -635,7 +798,6 @@
  width: 800px;
  padding: 15px;
}
.clearfix:before,
.clearfix:after {
  display: table;
@@ -644,25 +806,61 @@
.clearfix:after {
  clear: both
}
.box-card {
  width: 100%;
  margin-bottom: 20px;
}
.el-tag + .el-tag {
  margin-left: 10px;
}
.my-label {
  background: #E1F3D8;
}
.form-warp {
  min-width: 700px;
  padding: 20px;
  margin-top: 5px;
  margin-bottom: 20px;
  margin-left: 3px;
  margin-right: 3px;
  box-shadow: rgba(67, 71, 85, 0.27) 0px 0px 0.25em, rgba(90, 125, 188, 0.05) 0px 0.25em 1em;
}
.before {
  span {
    color: #F56C6C
  }
  margin-bottom: 15px;
  color: #E6A23C
}
.before_none {
  span {
    color: #F56C6C
  }
  margin-bottom: 15px;
  margin-top: 15px;
  color: #E6A23C
}
.reject-but {
  position: absolute;
  top: -4px;
  right: 4px
}
.current {
  span {
    color: #409EFF
  }
  margin-bottom: 15px;
  color: #E6A23C
}
.op-list {
  position: absolute;
  top: -4px;
  right: 4px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.tab-min-height {
  min-height: 500px;
}
</style>