xiangpei
2025-03-24 1e3fb9fed595a95d7efc763eb043d0a3f358dbc3
src/views/projectProcess/detail/index.vue
@@ -18,18 +18,18 @@
      </div>
      <div class="search-warp">
        <div @click="changeTab(1, 'all')" :class="{'item-warm': true, 'all-color': true, 'active': 1 === selectTabId}">全部事项<span v-if="detailData && detailData.statistics">({{detailData.statistics.totalTaskNum}})</span></div>
        <div @click="changeTab(2, 'todo')" :class="{'item-warm': true, 'all-color': true, 'active': 2 === selectTabId}">待办事项<span v-if="detailData && detailData.statistics">({{detailData.statistics.todoTaskNum}})</span></div>
        <div @click="changeTab(3, 'todo')" :class="{'item-warm': true, 'current-color': true, 'active': 3 === selectTabId}">当前环节</div>
        <div @click="changeTab(2, 'todo')" :class="{'item-warm': true, 'todo-color': true, 'active': 2 === selectTabId}">待办事项<span v-if="detailData && detailData.statistics">({{detailData.statistics.todoTaskNum}})</span></div>
        <div @click="changeTab(4, 'remaining')" :class="{'item-warm': true, 'remaining-color': true, 'active': 4 === selectTabId}">剩余事项<span v-if="detailData && detailData.statistics">({{detailData.statistics.remainingTaskNum}})</span></div>
        <div @click="changeTab(5, 'timely')" :class="{'item-warm': true, 'timely-color': true, 'active': 5 === selectTabId}">按时完成(0)</div>
        <div @click="changeTab(5, 'timely')" :class="{'item-warm': true, 'timely-color': true, 'active': 5 === selectTabId}">按时完成<span v-if="detailData && detailData.statistics">({{detailData.statistics.timelyFinishedTaskNum}})</span></div>
        <div @click="changeTab(6, 'overtime')" :class="{'item-warm': true, 'overtime-color': true, 'active': 6 === selectTabId}">超时事项(0)</div>
        <div @click="changeTab(7, 'willOvertime')" :class="{'item-warm': true, 'willOvertime-color': true, 'active': 7 === selectTabId}">临期事项(0)</div>
        <div @click="changeTab(3, 'wait')" :class="{'item-warm': true, 'wait-color': true, 'active': 3 === selectTabId}">容缺事项<span v-if="detailData && detailData.statistics">({{detailData.statistics.waitTaskNum}})</span></div>
        <div @click="changeTab(7, 'jump')" :class="{'item-warm': true, 'willOvertime-color': true, 'active': 7 === selectTabId}">跳过事项<span v-if="detailData && detailData.statistics">({{detailData.statistics.jumpTaskNum}})</span></div>
        <div @click="changeTab(8, 'urge')" :class="{'item-warm': true, 'urge-color': true, 'active': 8 === selectTabId}">督办事项(0)</div>
      </div>
      <div style="display: flex;justify-content: center;align-items: center;margin-top: 20px; position: relative">
        <el-form :inline="true" :model="queryParams" class="demo-form-inline">
          <el-form-item label="任务名称">
            <el-input v-model="queryParams.taskName" placeholder="任务名称"></el-input>
            <el-input v-model="queryParams.taskName" clearable @clear="search" placeholder="任务名称"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="search">查询</el-button>
@@ -37,7 +37,7 @@
        </el-form>
        <div style="position: absolute; right: 0; top: 0">
          <el-button @click="openProcessImg" v-loading="imgLoading" type="primary">流程图</el-button>
          <el-button @click="openRecord" type="info" v-loading="recordLoading">流转记录</el-button>
          <el-button @click="openRecord" type="info" v-loading="recordLoading">流程日志</el-button>
        </div>
      </div>
      <div class="table">
@@ -53,24 +53,13 @@
          </el-table-column>
          <el-table-column
            prop="promoterUnitName"
            label="发起单位"
            label="责任单位"
          >
          </el-table-column>
          <el-table-column
            prop="promoterName"
            label="发起人"
            label="责任人及联系电话"
          >
          </el-table-column>
          <el-table-column
            align="center"
            prop="handlerType"
            label="处理方类型"
          >
            <template slot-scope="scope">
              <el-tag v-if="scope.row.handlerType === 'USER'">人员账号</el-tag>
              <el-tag type="success" v-else-if="scope.row.handlerType === 'DEPT'">单位</el-tag>
              <el-tag type="info" v-else-if="scope.row.handlerType === 'ROLE'">角色</el-tag>
            </template>
          </el-table-column>
          <el-table-column
            prop="handlerUnitName"
@@ -80,14 +69,8 @@
          </el-table-column>
          <el-table-column
            prop="handlerName"
            label="候选处理人"
            label="处理人及联系电话"
            :formatter="candidateFormatter"
          >
          </el-table-column>
          <el-table-column
            prop="handlerName"
            label="实际处理人"
            :formatter="finalFinishedFormatter"
          >
          </el-table-column>
          <el-table-column
@@ -99,10 +82,12 @@
          <el-table-column
            fixed="right"
            label="操作"
            width="100">
            align="center"
            width="140">
            <template slot-scope="scope">
              <el-button v-if="scope.row.taskStatus !== '未开始'" @click="goToProcessDetail(scope.row)" type="text" size="small">查看</el-button>
              <el-button v-if="showHandle(scope.row)" @click="goToDo(scope.row)" type="text" size="small">办理</el-button>
              <el-button v-if = "scope.row.taskStatus === '待办'" @click="openSupervise(scope.row)" type="text" size="small">督办</el-button>
            </template>
          </el-table-column>
        </el-table>
@@ -132,62 +117,83 @@
      </div>
    </el-dialog>
    <el-dialog
      :title="`${this.queryParams.processName}:流转记录`"
    <el-drawer
      :title="`${this.queryParams.processName}:流程日志`"
      :visible.sync="processRecordShow"
      :fullscreen="true"
      :close-on-click-modal="false"
      :destroy-on-close="true"
    >
      <div>
        <div class="block">
          <el-timeline>
            <el-timeline-item
              v-for="(item,index ) in flowRecordList"
              :key="index"
              :icon="setIcon(item.finishTime)"
              :color="setColor(item.finishTime)"
            >
              <p style="font-weight: 700">{{item.taskName}}
                <span v-if="item.comment && item.comment.type === '3'" style="color: red">(执行了驳回)</span>
                <span v-if="item.overtime && item.overtime==='red'" style="color: red">(已超时)</span>
                <span v-if="item.overtime && item.overtime==='yellow'" style="color: orange">(即将超时)</span>
              </p>
              <el-card :body-style="{ padding: '10px' }">
                <el-descriptions class="margin-top" :column="1" size="small" border>
                  <el-descriptions-item v-if="item.assigneeName" label-class-name="my-label">
                    <template slot="label"><i class="el-icon-user"></i>办理人</template>
                    {{item.assigneeName}}
                    <el-tag type="info" size="mini">{{item.deptName}}</el-tag>
                  </el-descriptions-item>
                  <el-descriptions-item v-if="item.candidate" label-class-name="my-label">
                    <template slot="label"><i class="el-icon-user"></i>候选办理</template>
                    {{item.candidate}}
                  </el-descriptions-item>
                  <el-descriptions-item label-class-name="my-label">
                    <template slot="label"><i class="el-icon-date"></i>接收时间</template>
                    {{item.createTime}}
                  </el-descriptions-item>
                  <el-descriptions-item v-if="item.finishTime" label-class-name="my-label">
                    <template slot="label"><i class="el-icon-date"></i>处理时间</template>
                    {{item.finishTime}}
                  </el-descriptions-item>
                  <el-descriptions-item v-if="item.duration"  label-class-name="my-label">
                    <template slot="label"><i class="el-icon-time"></i>耗时</template>
                    {{item.duration}}
                  </el-descriptions-item>
                  <el-descriptions-item v-if="item.comment" label-class-name="my-label">
                    <template slot="label"><i class="el-icon-tickets"></i>处理意见</template>
                    {{item.comment.comment}}
                  </el-descriptions-item>
                </el-descriptions>
              </el-card>
            </el-timeline-item>
          </el-timeline>
        </div>
      direction="ltr"
      :modal="false"
      size="800px"
      >
      <log-view style="padding: 10px 20px" :log-list="logList"/>
    </el-drawer>
<!--    <el-dialog-->
<!--      :title="`${this.queryParams.processName}:流转记录`"-->
<!--      :visible.sync="processRecordShow"-->
<!--      :fullscreen="true"-->
<!--      :close-on-click-modal="false"-->
<!--      :destroy-on-close="true"-->
<!--    >-->
<!--      <div>-->
<!--        <log-view :log-list="logList"/>-->
<!--&lt;!&ndash;        <div class="block">&ndash;&gt;-->
<!--&lt;!&ndash;          <el-timeline>&ndash;&gt;-->
<!--&lt;!&ndash;            <el-timeline-item&ndash;&gt;-->
<!--&lt;!&ndash;              v-for="(item,index ) in flowRecordList"&ndash;&gt;-->
<!--&lt;!&ndash;              :key="index"&ndash;&gt;-->
<!--&lt;!&ndash;              :icon="setIcon(item.finishTime)"&ndash;&gt;-->
<!--&lt;!&ndash;              :color="setColor(item.finishTime)"&ndash;&gt;-->
<!--&lt;!&ndash;            >&ndash;&gt;-->
<!--&lt;!&ndash;              <p style="font-weight: 700">{{item.taskName}}&ndash;&gt;-->
<!--&lt;!&ndash;                <span v-if="item.comment && item.comment.type === '3'" style="color: red">(执行了驳回)</span>&ndash;&gt;-->
<!--&lt;!&ndash;                <span v-if="item.overtime && item.overtime==='red'" style="color: red">(已超时)</span>&ndash;&gt;-->
<!--&lt;!&ndash;                <span v-if="item.overtime && item.overtime==='yellow'" style="color: orange">(即将超时)</span>&ndash;&gt;-->
<!--&lt;!&ndash;              </p>&ndash;&gt;-->
<!--&lt;!&ndash;              <el-card :body-style="{ padding: '10px' }">&ndash;&gt;-->
<!--&lt;!&ndash;                <el-descriptions class="margin-top" :column="1" size="small" border>&ndash;&gt;-->
<!--&lt;!&ndash;                  <el-descriptions-item v-if="item.assigneeName" label-class-name="my-label">&ndash;&gt;-->
<!--&lt;!&ndash;                    <template slot="label"><i class="el-icon-user"></i>办理人</template>&ndash;&gt;-->
<!--&lt;!&ndash;                    {{item.assigneeName}}&ndash;&gt;-->
<!--&lt;!&ndash;                    <el-tag type="info" size="mini">{{item.deptName}}</el-tag>&ndash;&gt;-->
<!--&lt;!&ndash;                  </el-descriptions-item>&ndash;&gt;-->
<!--&lt;!&ndash;                  <el-descriptions-item v-if="item.candidate" label-class-name="my-label">&ndash;&gt;-->
<!--&lt;!&ndash;                    <template slot="label"><i class="el-icon-user"></i>候选办理</template>&ndash;&gt;-->
<!--&lt;!&ndash;                    {{item.candidate}}&ndash;&gt;-->
<!--&lt;!&ndash;                  </el-descriptions-item>&ndash;&gt;-->
<!--&lt;!&ndash;                  <el-descriptions-item label-class-name="my-label">&ndash;&gt;-->
<!--&lt;!&ndash;                    <template slot="label"><i class="el-icon-date"></i>接收时间</template>&ndash;&gt;-->
<!--&lt;!&ndash;                    {{item.createTime}}&ndash;&gt;-->
<!--&lt;!&ndash;                  </el-descriptions-item>&ndash;&gt;-->
<!--&lt;!&ndash;                  <el-descriptions-item v-if="item.finishTime" label-class-name="my-label">&ndash;&gt;-->
<!--&lt;!&ndash;                    <template slot="label"><i class="el-icon-date"></i>处理时间</template>&ndash;&gt;-->
<!--&lt;!&ndash;                    {{item.finishTime}}&ndash;&gt;-->
<!--&lt;!&ndash;                  </el-descriptions-item>&ndash;&gt;-->
<!--&lt;!&ndash;                  <el-descriptions-item v-if="item.duration"  label-class-name="my-label">&ndash;&gt;-->
<!--&lt;!&ndash;                    <template slot="label"><i class="el-icon-time"></i>耗时</template>&ndash;&gt;-->
<!--&lt;!&ndash;                    {{item.duration}}&ndash;&gt;-->
<!--&lt;!&ndash;                  </el-descriptions-item>&ndash;&gt;-->
<!--&lt;!&ndash;                  <el-descriptions-item v-if="item.comment" label-class-name="my-label">&ndash;&gt;-->
<!--&lt;!&ndash;                    <template slot="label"><i class="el-icon-tickets"></i>处理意见</template>&ndash;&gt;-->
<!--&lt;!&ndash;                    {{item.comment.comment}}&ndash;&gt;-->
<!--&lt;!&ndash;                  </el-descriptions-item>&ndash;&gt;-->
<!--&lt;!&ndash;                </el-descriptions>&ndash;&gt;-->
<!--&lt;!&ndash;              </el-card>&ndash;&gt;-->
<!--&lt;!&ndash;            </el-timeline-item>&ndash;&gt;-->
<!--&lt;!&ndash;          </el-timeline>&ndash;&gt;-->
<!--&lt;!&ndash;        </div>&ndash;&gt;-->
<!--      </div>-->
<!--    </el-dialog>-->
    <el-dialog :visible.sync="superviseShow" width="1000px"  title="督办" append-to-body>
      <el-form ref="superviseForm" :model="superviseForm" :rules="superviseRules" label-width="80px">
        <el-form-item label="督办内容" prop="content">
          <el-input type="textarea" v-model="superviseForm.content"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="superviseShow = false">取 消</el-button>
        <el-button type="primary" @click="submitSupervise">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
@@ -195,19 +201,24 @@
import {
  getProjectProcessDetail,
  getProjectProcessDetailTaskList,
  getTaskIsAuditing
  getTaskIsAuditing, taskSupervise
} from "@/api/projectProcess/projectProcess";
import {flowXmlAndNode} from "@/api/flowable/definition";
import BpmnViewer from '@/components/Process/viewer';
import LogView from "@/views/projectProcess/components/LogView";
import {flowRecord} from "@/api/flowable/finished";
import {editProject} from "@/api/projectEngineering/projectInfo";
import {getProjectProcessLog} from "@/api/flowLog/flowLog";
export default {
  name: "Detail",
  components: {
    BpmnViewer
    BpmnViewer,
    LogView
  },
  data() {
    return {
      logList: [], // 流程日志
      processRecordShow: false, // 流转记录显示
      flowRecordList: [], // 流程流转数据
      recordLoading: false, // 流转记录加载
@@ -216,11 +227,21 @@
      processImgShow: false, // 流程图显示
      imgLoading: false, // 流程图加载
      loading: false,
      superviseShow: false,
      tableLoading: false,
      detailData: {},
      taskList: [],
      total: 0,
      selectTabId: 2,
      superviseForm: {
        taskId: null,
        projectId: null,
        processInsId: null,
        receiverIds: null,
        receiverType: null,
        superviseType: null,
        content: '',
      },
      queryParams: {
        taskName: '',
        taskType: 'todo',
@@ -231,6 +252,9 @@
        processInsId: null,
        deployId: null,
        processName: '' // 流程名称
      },
      superviseRules: {
        content: [{required: true, message: '督办内容不能为空', trigger: 'blur'}]
      }
    }
  },
@@ -244,14 +268,63 @@
      this.queryParams.processInsId = this.$route.query.processInsId
      this.queryParams.deployId = this.$route.query.deployId
      this.queryParams.processName = this.$route.query.processName
      if (this.$route.query.selectTabId) {
        this.selectTabId = parseInt(this.$route.query.selectTabId)
      }
      sessionStorage.setItem("projectProDetail", JSON.stringify(this.queryParams))
    } else {
      this.queryParams = params
    }
    this.loading = true
    this.changeTab(this.selectTabId, this.transEventType(this.selectTabId))
    this.getProjectProcessInfo()
  },
  methods: {
    transEventType(selectTabId) {
      if (selectTabId == 1) {
        return "all"
      } else if (selectTabId == 2) {
        return "todo"
      } else if (selectTabId == 3) {
        return "wait"
      } else if (selectTabId == 4) {
        return "remaining"
      } else if (selectTabId == 5) {
        return "timely"
      } else if (selectTabId == 6) {
        return "overtime"
      } else if (selectTabId == 7) {
        return "jump"
      } else if (selectTabId == 8) {
        return "urge"
      }
    },
    submitSupervise() {
      this.$refs["superviseForm"].validate(valid => {
        if (valid) {
          taskSupervise(this.superviseForm).then((res) => {
            this.superviseShow = false;
            this.$message.success("操作成功");
          })
        }
      });
    },
    openSupervise(row){
      this.superviseForm.content ='';
      this.superviseForm.taskId = row.taskId;
      this.superviseForm.projectId = this.$route.query.projectId;
      this.superviseForm.processInsId = row.processInsId;
      this.superviseForm.superviseType = "SUPERVISE";
      this.superviseForm.receiverType = row.handlerType;
      if (row.handlerType === 'USER') {
        this.superviseForm.receiverIds = row.handlerId;
      } else if (row.handlerType === 'DEPT') {
        this.superviseForm.receiverIds = row.handlerUnitId;
      } else if (row.handlerType === 'ROLE') {
        this.superviseForm.receiverIds = row.handlerUnitId;
      }
      this.superviseShow = true
    },
    setIcon(val) {
      if (val) {
        return "el-icon-check";
@@ -267,7 +340,7 @@
      }
    },
    openRecord() {
      this.getFlowRecordList(this.queryParams.processInsId);
      this.getFlowLogList(this.queryParams.processInsId);
    },
    openProcessImg() {
      this.imgLoading = true
@@ -289,23 +362,33 @@
        this.processRecordShow = true
      })
    },
    getFlowLogList(procInsId) {
      const params = {processInsId: procInsId, projectId: this.queryParams.projectId}
      this.recordLoading = true
      getProjectProcessLog(params).then(res => {
        this.logList = res.data;
        this.recordLoading = false
        this.processRecordShow = true
      })
    },
    unitFormatter(row) {
      if (row.handlerType === 'USER') {
        return null;
      } else if (row.handlerType === 'DEPT') {
        return row.handlerUnitName.join("、")
      } else if (row.handlerType === 'ROLE') {
        return row.handlerUnitName.join('、')
      if (row.taskStatus != '已完成' && row.taskStatus != '跳过') {
        return null
      }
      return row.handlerUnitName.join("、")
    },
    candidateFormatter(row) {
      if (row.handlerType === 'USER') {
        return row.handlerName.join('、')
      } else if (row.handlerType === 'DEPT') {
        return row.handlerUnitName.join('、')
      } else if (row.handlerType === 'ROLE') {
        return row.handlerUnitName.join('、')
      if (row.taskStatus != '已完成' && row.taskStatus != '跳过') {
        return null
      }
      return row.handlerName.join("、")
      // if (row.handlerType === 'USER') {
      //   return row.handlerName.join('、')
      // } else if (row.handlerType === 'DEPT') {
      //   return row.handlerUnitName.join('、')
      // } else if (row.handlerType === 'ROLE') {
      //   return row.handlerUnitName.join('、')
      // }
    },
    finalFinishedFormatter(row) {
      // 不是已完成的状态没有实际处理人,已完成的状态只有一个人
@@ -316,14 +399,11 @@
      }
    },
    showHandle(row) {
      if (row.taskStatus === '待办') {
      if (row.taskStatus === '待办' || row.taskStatus === '挂起' || row.taskStatus === '容缺') {
        if (row.handlerType === "USER") {
          console.log(row.handlerId.indexOf(this.$store.state.user.id) !== -1, "我是不是")
          return row.handlerId.indexOf(this.$store.state.user.id) !== -1
        } else if (row.handlerType === "DEPT") {
          console.log(this.$store.state.user.deptId, "部门id", row.handlerUnitId)
          return row.handlerUnitId.indexOf(this.$store.state.user.deptId) !== -1
          // return this.$store.state.user.name === '市发展改革委' || this.$store.state.user.name === '市住建局'
          return row.handlerUnitId.indexOf(this.$store.state.user.deptId) !== -1 || row.handlerUnitId.some(id => this.$store.state.user.childDeptIds.indexOf(id) !== -1)
        } else if (row.handlerType === "ROLE") {
          return row.handlerUnitId.some(roleId => this.$store.state.user.roleIds.indexOf(roleId) !== -1)
        }
@@ -332,13 +412,7 @@
      }
    },
    goToDo(row) {
      // 查询该任务是否配置了需要审批
      let params = {
        processDefId: row.processDefId,
        taskId: row.taskId
      }
      getTaskIsAuditing(params).then(res => {
        console.log("row",row)
      if (row.taskStatus === '容缺') {
        this.$router.push({
          path: '/flowable/task/myProcess/send/index',
          query: {
@@ -349,11 +423,38 @@
            flowName: this.queryParams.processName,
            projectName: this.detailData.projectName,
            taskId: row.taskId,
            showAuditing: res.data,
            showAuditing: false,
            projectId: this.queryParams.projectId,
            isWait: true,
            goBackParams: this.queryParams
          }
        })
      })
      } else {
        // 查询该任务是否配置了需要审批
        let params = {
          processDefId: row.processDefId,
          taskId: row.taskId
        }
        getTaskIsAuditing(params).then(res => {
          console.log("row",row)
          this.$router.push({
            path: '/flowable/task/myProcess/send/index',
            query: {
              deployId: row.deployId,
              procDefId: row.processDefId,
              procInsId: row.processInsId,
              processName: row.taskName,
              flowName: this.queryParams.processName,
              projectName: this.detailData.projectName,
              taskId: row.taskId,
              showAuditing: res.data,
              projectId: this.queryParams.projectId,
              isWait: false,
              goBackParams: this.queryParams
            }
          })
        })
      }
    },
    goToProcessDetail(row) {
      this.$router.push({ path: '/flowable/task/myProcess/detail/index',
@@ -363,6 +464,7 @@
          procInsId: row.processInsId,
          deployId: row.deployId,
          taskId: row.taskId,
          projectId: this.queryParams.projectId,
          goBackParams: this.queryParams
        }})
    },
@@ -390,22 +492,28 @@
        this.total = res.total
      })
    },
    isProject(id) {
      const numericPattern = /^\d+(\.\d+)?$/;
      return numericPattern.test(id)
    },
    // 查询详情
    getProjectProcessInfo() {
      getProjectProcessDetail(this.queryParams.projectId, this.queryParams.processDefId).then(res => {
      const projectType = this.isProject(this.queryParams.projectId) ? "PROJECT" : "ENGINEERING"
      const param = {
        projectId: this.queryParams.projectId,
        processDefId: this.queryParams.processDefId,
        projectType: projectType
      }
      getProjectProcessDetail(param).then(res => {
        this.detailData = res.data
        this.taskList = res.taskList
        this.total = res.total
        this.loading = false
      })
    },
    changeTab(id, event) {
      let beforeId = this.selectTabId
      this.selectTabId = id
      this.queryParams.taskType = event
      if (beforeId !== id) {
        this.getList()
      }
      this.queryParams.currentPage = 1;
      this.getList()
    }
  }
}
@@ -455,6 +563,9 @@
.all-color {
  background-color: rgb(180, 253, 255);
}
.todo-color {
  background-color: rgb(66, 174, 243);
}
.current-color {
  background-color: rgb(127, 131, 247);
@@ -465,17 +576,21 @@
  color: white;
}
.timely-color {
  background-color: rgb(204, 247, 131);
  background-color: rgb(85, 248, 106);
}
.overtime-color {
  background-color: rgb(129, 179, 55);
  color: white;
  background-color: #e8e866;
}
.wait-color {
  background-color: orange;
}
.willOvertime-color {
  background-color: rgb(255, 248, 29);
  background-color: rgb(204, 247, 131);
}
.urge-color {
  background-color: rgb(0, 0, 0);
  background-color: red;
  color: white;
}
.active {