From d088628a4b421e7e0a8363b8b75529d8b2ecfe89 Mon Sep 17 00:00:00 2001
From: lyh <liuyuanheng@xalxzn.com>
Date: 星期一, 24 二月 2025 10:07:14 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 src/views/flowable/components/HistoricDetail.vue |  343 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 343 insertions(+), 0 deletions(-)

diff --git a/src/views/flowable/components/HistoricDetail.vue b/src/views/flowable/components/HistoricDetail.vue
new file mode 100644
index 0000000..be707cc
--- /dev/null
+++ b/src/views/flowable/components/HistoricDetail.vue
@@ -0,0 +1,343 @@
+<style lang="less">
+</style>
+<template>
+  <div class="search">
+    <a-card>
+      <p slot="title">
+        <span>娴佺▼鍥�</span>
+      </p>
+      <div :style="{height: svgHeight}" v-if="svgShow">
+        <bpmnModeler class="svg" ref="bpm" :xml="xmlData" :is-view="true"></bpmnModeler>
+      </div>
+    </a-card>
+    <a-card style="margin-top:10px;">
+      <p slot="title">
+        <span>娴佺▼瀹℃壒杩涘害鍘嗗彶</span>
+      </p>
+      <a-row style="position:relative">
+        <div class="block">
+          <a-timeline>
+            <a-timeline-item
+              v-for="(item,index ) in flowRecordList"
+              :key="index"
+              :color="setColor(item.finishTime)"
+            >
+              <p style="font-weight: 700;">{{item.taskName}}
+                <i v-if="!item.finishTime" style="color: orange">(寰呭姙涓�傘�傘��)</i>
+              </p>
+
+              <a-card :body-style="{ padding: '10px' }">
+                <label v-if="item.assigneeName&&item.finishTime" style="font-weight: normal;margin-right: 30px;">瀹為檯鍔炵悊浜猴細 {{item.assigneeName}} <a-tag type="info" size="mini">{{item.deptName}}</a-tag></label>
+                <label v-if="item.candidate" style="font-weight: normal;margin-right: 30px;">鍊欓�夊姙鐞嗕汉锛� {{item.candidate}}</label>
+                <label style="font-weight: normal">鎺ユ敹鏃堕棿锛� </label><label style="color:#8a909c;font-weight: normal">{{item.createTime}}</label>
+                <label v-if="item.finishTime" style="margin-left: 30px;font-weight: normal">鍔炵粨鏃堕棿锛� </label><label style="color:#8a909c;font-weight: normal">{{item.finishTime}}</label>
+                <label v-if="item.duration" style="margin-left: 30px;font-weight: normal">鑰楁椂锛� </label><label style="color:#8a909c;font-weight: normal">{{item.duration}}</label>
+
+                <p  v-if="item.comment">
+<!--  1 姝e父鎰忚  2 閫�鍥炴剰瑙� 3 椹冲洖鎰忚                -->
+                  <a-tag color="green" v-if="item.comment.type === '1'">
+                    <span v-if="item.comment.comment!='閲嶆柊鎻愪氦'">閫氳繃锛�</span>
+                    {{item.comment.comment}}
+                  </a-tag>
+                  <a-tag color="orange" v-if="item.comment.type === '2'">閫�鍥烇細  {{item.comment.comment}}</a-tag>
+                  <a-tag color="red" v-if="item.comment.type === '3'">椹冲洖锛�  {{item.comment.comment}}</a-tag>
+                </p>
+              </a-card>
+            </a-timeline-item>
+          </a-timeline>
+        </div>
+      </a-row>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import {flowRecord} from "@views/flowable/api/finished";
+import {getFlowViewerByDataId, readXmlByDataId} from "@views/flowable/api/definition";
+import bpmnModeler from "workflow-bpmn-modeler";
+
+export default {
+    name: 'HistoricDetail',
+  components: {
+    bpmnModeler,
+  },
+    props: {
+    /**/
+        dataId: {
+            type: String,
+            default: '',
+            required: true
+        },
+
+    },
+    data() {
+        return {
+            taskList:[],
+            flowRecordList: [], // 娴佺▼娴佽浆鏁版嵁
+            formData:{},
+            xmlData:'',
+            type: 0,
+            loading: false, // 琛ㄥ崟鍔犺浇鐘舵��
+            loadingImg: false,
+            data: [],
+            id: '',
+            imgUrl: '',
+            backRoute: '',
+          svgHeight:'',
+          svgShow: true
+        };
+    },
+    created() {
+        this.init();
+    },
+    watch: {
+      dataId: function(newval, oldName) {
+            this.init();
+        }
+    },
+
+    methods: {
+        init() {
+          this.getFlowRecordList()
+          this.getModelDetail()
+        },
+      /** xml 鏂囦欢 */
+      getModelDetail() {
+        // 鍙戦�佽姹傦紝鑾峰彇xml
+        readXmlByDataId(this.dataId).then(res => {
+          this.xmlData = res.result
+          this.getFlowViewer()
+          setTimeout(()=>{
+            this.fitViewport()
+          })
+        })
+      },
+      // 娴佺▼杩涜鎯呭喌
+      getFlowViewer() {
+        getFlowViewerByDataId(this.dataId).then(res => {
+          this.taskList = res.result || []
+          this.fillColor();
+        })
+      },
+      /** 娴佺▼娴佽浆璁板綍 */
+      getFlowRecordList() {
+        const params = {dataId: this.dataId}
+        flowRecord(params).then(res => {
+          // console.log(res)
+          this.flowRecordList = res.result.flowList;
+          this.finishOrder()
+          // 娴佺▼杩囩▼涓笉瀛樺湪鍒濆鍖栬〃鍗� 鐩存帴璇诲彇鐨勬祦绋嬪彉閲忎腑瀛樺偍鐨勮〃鍗曞��
+          if (res.result.formData) {
+            this.formData = res.result.formData;
+          }
+        }).catch(res => {
+          console.log(res)
+        })
+      },
+        //鏁寸悊椤哄簭锛屾妸寰呭姙鏀炬渶涓婇潰锛屽苟涓斿彧鐣欎竴涓紙涓嶇劧浼氱鏃朵細涔憋級
+      finishOrder(){
+        const list = []
+        let noFinish = null
+        for (const flow of this.flowRecordList) {
+          if (flow.finishTime){
+            // 鍔炵粨鐨勮妭鐐瑰悓鏃跺彇鏈夊疄闄呭姙鐞嗕汉鐨勶紝鍥犱负浼氱浼氬皢鎵�鏈夌殑澶氬疄渚嬮兘杩斿洖锛岄渶瑕佽繃婊�
+            if (flow.assigneeId){
+              list.push(flow)
+            }
+          } else {
+            noFinish = flow
+          }
+        }
+        if (noFinish){
+          const find = list.find(obj=>obj.taskDefKey == noFinish.taskDefKey);
+          if (find){
+            noFinish.taskName = '銆愪細绛句腑銆�'+noFinish.taskName
+          }
+          this.flowRecordList = [noFinish,...list];
+        } else {
+          this.flowRecordList = list;
+        }
+
+      },
+        setColor(val) {
+          if (val) {
+            return "#2bc418";
+          } else {
+            return "#b3bdbb";
+          }
+        },
+      fillColor() {
+        const modeler = this.$refs.bpm.modeler;
+        const canvas = modeler.get('canvas')
+        modeler._definitions.rootElements[0].flowElements.forEach(n => {
+          const completeTask = this.taskList.find(m => m.key === n.id)
+          const todoTask = this.taskList.find(m => !m.completed)
+          const endTask = this.taskList[this.taskList.length - 1]
+          //鐢ㄦ埛浠诲姟
+          if (n.$type === 'bpmn:UserTask') {
+            if (completeTask) {
+              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
+              canvas.addMarker(n.id, completeTask.back ? 'highlight-back' : 'highlight-noback')
+              n.outgoing.forEach(nn => {
+                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
+                if (targetTask) {
+                  if (todoTask && completeTask.key === todoTask.key && !todoTask.completed){
+                    canvas.addMarker(nn.id, todoTask.completed ? 'highlight' : 'highlight-todo')
+                    canvas.addMarker(nn.targetRef.id, todoTask.completed ? 'highlight' : 'highlight-todo')
+                  }else {
+                    canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                    canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                  }
+                }
+              })
+            }
+          }
+          // 鎺掍粬缃戝叧
+          else if (n.$type === 'bpmn:ExclusiveGateway') {
+            if (completeTask) {
+              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
+              n.outgoing.forEach(nn => {
+                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
+                if (targetTask) {
+
+                  canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                  canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                }
+
+              })
+            }
+
+          }
+          // 骞惰缃戝叧
+          else if (n.$type === 'bpmn:ParallelGateway') {
+            if (completeTask) {
+              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
+              n.outgoing.forEach(nn => {
+                debugger
+                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
+                if (targetTask) {
+                  canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                  canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                }
+              })
+            }
+          }
+          else if (n.$type === 'bpmn:StartEvent') {
+            n.outgoing.forEach(nn => {
+              const completeTask = this.taskList.find(m => m.key === nn.targetRef.id)
+              if (completeTask) {
+                canvas.addMarker(nn.id, 'highlight')
+                canvas.addMarker(n.id, 'highlight')
+                return
+              }
+            })
+          }
+          else if (n.$type === 'bpmn:EndEvent') {
+            if (endTask.key === n.id && endTask.completed) {
+              canvas.addMarker(n.id, 'highlight')
+              return
+            }
+          }
+        })
+      },
+      // 璁╁浘鑳借嚜閫傚簲灞忓箷
+      fitViewport() {
+        const modeler = this.$refs.bpm.modeler;
+        const canvas = modeler.get('canvas')
+        // this.zoom = this.modeler.get('canvas').zoom('fit-viewport')
+        if (this.svgHeight){
+          document.querySelector('.canvas').style.height = this.svgHeight;
+        }
+        const bbox = document.querySelector('.flow-containers .viewport').getBBox()
+        const currentViewbox = modeler.get('canvas').viewbox()
+        if (!this.svgHeight){
+          this.svgHeight = currentViewbox.inner.height + 'px'
+          this.svgShow = false
+          this.$nextTick(()=>{
+            this.svgShow = true
+          })
+          // this.fitViewport()
+          setTimeout(()=>{
+            this.fitViewport()
+          })
+        }
+
+        const elementMid = {
+          x: bbox.x + bbox.width / 2 - 65,
+          y: bbox.y + bbox.height / 2
+        }
+        // 璋冭妭浣嶇疆
+        modeler.get('canvas').viewbox({
+          x: elementMid.x - currentViewbox.width / 2 + 70,
+          y: elementMid.y - currentViewbox.height/2,
+          width: currentViewbox.width,
+          height: currentViewbox.height
+        })
+        // 璋冭妭澶у皬缂╂斁
+        const zoom = currentViewbox.outer.width /(currentViewbox.inner.width+200)
+        console.log('********',zoom,elementMid,currentViewbox.inner,currentViewbox.outer)
+        // modeler.get('canvas').zoom(zoom)
+
+
+      },
+    }
+
+};
+</script>
+<style lang="less">
+   .highlight.djs-shape .djs-visual > :nth-child(1) {
+     fill: green !important;
+     stroke: green !important;
+     fill-opacity: 0.2 !important;
+   }
+   .highlight.djs-shape .djs-visual > :nth-child(2) {
+     fill: green !important;
+   }
+   .highlight.djs-shape .djs-visual > path {
+     fill: green !important;
+     fill-opacity: 0.2 !important;
+     stroke: green !important;
+   }
+   .highlight.djs-connection > .djs-visual > path {
+     stroke: green !important;
+   }
+   // .djs-connection > .djs-visual > path {
+   //   stroke: orange !important;
+   //   stroke-dasharray: 4px !important;
+   //   fill-opacity: 0.2 !important;
+   // }
+   // .djs-shape .djs-visual > :nth-child(1) {
+   //   fill: orange !important;
+   //   stroke: orange !important;
+   //   stroke-dasharray: 4px !important;
+   //   fill-opacity: 0.2 !important;
+   // }
+   .highlight-todo.djs-connection > .djs-visual > path {
+     stroke: orange !important;
+     stroke-dasharray: 4px !important;
+     fill-opacity: 0.2 !important;
+   }
+   .highlight-todo.djs-shape .djs-visual > :nth-child(1) {
+     fill: orange !important;
+     stroke: orange !important;
+     stroke-dasharray: 4px !important;
+     fill-opacity: 0.2 !important;
+   }
+   .highlight-back.djs-connection > .djs-visual > path {
+     stroke: red !important;
+     stroke-dasharray: 4px !important;
+     fill-opacity: 0.2 !important;
+   }
+   .highlight-back.djs-shape .djs-visual > :nth-child(1) {
+     fill: red !important;
+     stroke: red !important;
+     stroke-dasharray: 4px !important;
+     fill-opacity: 0.2 !important;
+   }
+   .overlays-div {
+     font-size: 10px;
+     color: red;
+     width: 100px;
+     top: -20px !important;
+   }
+</style>
\ No newline at end of file

--
Gitblit v1.9.3