<!--
流程图展示组件
@Author: linqian
@Date: 2020/06/22
-->
<template>
  <div>
    <div class="legend-group">
      <div class="legend-group__item" v-for="(item, index) in chartLegend" :key="index">
        <span class="retange" :style="{ background: item.color }"></span>
        <span>{{ item.text }}</span>
      </div>
    </div>
    <div id="myDiagramDiv" ref="myDiagramDiv" style="width: 100%; height: 600px; overflow: auto"></div>
    <!-- 详情弹出框 -->
    <div class="shallow-box" v-if="isShow" :style="modalStyle" ref="shallowBox">
      <span class="close" @click="closeModal"><i class="el-icon-close"></i></span>
      <div class="header">
        <span class="title">{{ detailBindData.name }}</span>
        <span id="time" class="time" v-if="detailBindData.showCountDown">{{ detailBindData.countTime }}</span>
      </div>
      <div class="form">
        <div class="form-item" v-if="detailBindData.actStartTime">
          <span class="label">转入时间</span>
          <span class="text">{{ detailBindData.actStartTime }}</span>
        </div>
        <div class="form-item" v-if="detailBindData.actEndTime">
          <span class="label">转出时间</span>
          <span class="text">{{ detailBindData.actEndTime }}</span>
        </div>
        <div class="form-item" v-if="detailBindData.assigneeList.length > 0">
          <span class="label">处理人</span>
          <span class="text">{{ detailBindData.assigneeList.join(' ') }}</span>
        </div>
        <div class="form-item" v-if="detailBindData.statusStr">
          <span class="label">状态</span>
          <span class="text">{{ detailBindData.statusStr }}</span>
        </div>
        <div class="form-item" v-if="detailBindData.dueDateNum">
          <span class="label">办理期限</span>
          <span class="text">{{ detailBindData.dueDateNum }}H</span>
        </div>
        <div class="form-item" v-if="detailBindData.beforeDueLimit">
          <span class="label">催办期限</span>
          <span class="text">{{ detailBindData.beforeDueLimit }}H</span>
        </div>
        <div class="form-item" v-if="detailBindData.description">
          <span class="label">任务描述</span>
          <span class="text">{{ detailBindData.description }}</span>
        </div>
        <div class="form-item" style="color: red" v-if="detailBindData.tipMsgStr">
          <span id="tipMsgSpan">{{ detailBindData.tipMsgStr }}</span>
        </div>
        <div class="form-item" v-if="detailBindData.approveMessage">
          <span class="label">审批信息</span>
          <span class="text">{{ detailBindData.approveMessage }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import go from 'ui-gojs';
import icons from './icon.js';
import { processConfig, getFlowChartDetail } from '@/api/permission-selfhelp-manage';
import moment from 'moment';
// 颜色变量
const lightGray = 'rgb(233,233,233)';
const lightBlue = 'rgb(227,239,255)';
const lightGreen = 'rgb(201,226,206)';
const blue = 'rgb(64,144,255)';
const green = 'rgb(52,159,29)';
const $ = window.go.GraphObject.make;

// 预定义图形
const GeneratorEllipseSpot1 = new go.Spot(0.156, 0.156);
const GeneratorEllipseSpot2 = new go.Spot(0.844, 0.844);

go.Shape.defineFigureGenerator('CircleLine', function (shape, w, h) {
  const rad = w / 2;
  const geo = new go.Geometry().add(
    new go.PathFigure(w, w / 2, false) // clockwise
      .add(new go.PathSegment(go.PathSegment.Arc, 0, 360, rad, rad, rad, rad).close())
  );
  geo.spot1 = GeneratorEllipseSpot1;
  geo.spot2 = GeneratorEllipseSpot2;
  geo.defaultStretch = go.GraphObject.Uniform;
  return geo;
});

go.Shape.defineFigureGenerator('DataStorage', function (shape, w, h) {
  var geo = new go.Geometry();
  var fig = new go.PathFigure(0, 0, true);
  geo.add(fig);
  fig.add(new go.PathSegment(go.PathSegment.Line, 200, 0));
  fig.add(new go.PathSegment(go.PathSegment.Bezier, 200, h, 220, 0.05 * h, 226, 0.85 * h));
  fig.add(new go.PathSegment(go.PathSegment.Line, 0, h));
  fig.add(new go.PathSegment(go.PathSegment.Bezier, 0, 0, 26, 0.7 * h, 8, (0.5).h).close());

  geo.spot1 = new go.Spot(0.226, 0);
  geo.spot2 = new go.Spot(0.81, 1);
  return geo;
});

function geoFunc(geoname) {
  var geo = icons[geoname];
  if (geo === undefined) geo = icons['home']; // use this for an unknown icon name
  if (typeof geo === 'string') {
    geo = icons[geoname] = go.Geometry.parse(geo, true); // fill each geometry
  }
  return geo;
}

export default {
  components: {},
  props: {
    applyOrdNo: [String, Number]
  },
  data() {
    return {
      modelData: {},
      isEmpty: false,
      taskDetail: {},
      isShow: false,
      textColor: {
        ready: 'gray',
        complete: blue,
        ing: 'white'
      },
      borderColor: {
        ready: 'gray',
        complete: blue,
        ing: green
      },
      bgColor: {
        ready: 'white',
        complete: lightBlue,
        ing: green
      },
      myDiagram: null,
      modalStyle: {},
      timer: null,
      // 详情框绑定的数据
      detailBindData: {},
      chartLegend: [
        {
          color: 'rgb(64,144,255)',
          text: '已经过的节点'
        },
        {
          color: 'gray',
          text: '未经过的节点'
        },
        {
          color: 'rgb(52,159,29)',
          text: '当前节点'
        }
      ]
    };
  },
  computed: {
    // 已生成的任务
    taskList() {
      return this.modelData.data;
    },
    // 所有节点数据
    allNodeList() {
      return JSON.parse(this.modelData.json).dataModel;
    }
  },
  methods: {
    // 关闭弹框
    closeModal() {
      this.isShow = false;
      clearTimeout(this.timer);
    },

    getSubContainerDrawData(id) {
      for (const key in this.allNodeList) {
        const element = this.allNodeList[key];
        if (key === id) {
          return element;
        }
      }
    },

    // 返回当前节点(非子容器)的状态
    // 三种状态: 未开始、进行中、 已完成
    getTaskStatus(id) {
      const item = this.taskList.find((el) => el.id === id);
      if (item === undefined) {
        return 'ready';
      } else {
        return item.activity === false ? 'complete' : 'ing';
      }
    },

    getTaskColor() {},

    // 返回子容器状态，根据子容器里面的节点状态判断,所有节点都完成 - 完成， 部分节点进行中 - 进行中 ， 节点都没有开始 - 未开始
    getSubContainerStatus(id) {
      const node = this.getSubContainerDrawData(id);
      if (!node) {
        return 'ready';
      }
      const { nodeDataArray } = node.diagramModel;
      const groupItems = nodeDataArray.filter((el) => el.category !== 'event');
      // 交集
      let attr = [...groupItems].filter((x) => [...this.taskList].some((y) => y.id === x.id));
      if (groupItems.length === 0 || attr.length === 0) {
        return 'ready';
      } else if (attr.length < groupItems.length) {
        return 'ing';
      } else {
        return 'complete';
      }
    },
    // 添加子容器里面的节点数据
    addGroupItems(data, myDiagram) {
      myDiagram.startTransaction('addGroupContents');
      const subKey = data.key;
      const id = data.id;
      const { nodeDataArray } = JSON.parse(this.modelData.json); // 主图的绘图数据
      const node = this.getSubContainerDrawData(id);
      // 子容器的绘图数据
      let subNodeDataArray = node.diagramModel.nodeDataArray;
      let subLinkDataArray = node.diagramModel.linkDataArray;
      // const isEnd =
      //   subNodeDataArray.find(
      //     el => el.category === "event" && el.type === "end"
      //   ) === undefined
      //     ? false
      //     : true;
      const isEnd =
        subNodeDataArray.find((el) => el.category === 'event' && el.text === '终止') === undefined ? false : true;

      // 数据模型中需要添加子节点集合， 去除开始、结束/终止节点
      let nodeAttr = subNodeDataArray.filter((el) => el.category !== 'event');

      // 注意:  子容器里的节点key不唯一，所以给key添加一个时间戳 格式为${key}_ ${time}
      let time = new Date().getTime();
      nodeAttr.map((item) => {
        item.group = subKey; // 组成员标识
        item.key = item.key + '_' + time;
      });

      // 修改连线集合中对应的节点key
      subLinkDataArray.map((item) => {
        item.to = item.to + '_' + time;
        item.from = item.from + '_' + time;
      });

      // 将节点添加到数据模型中
      for (let i = 0; i < nodeAttr.length; i++) {
        let nodeItem = nodeAttr[i];
        myDiagram.model.addNodeData(nodeItem);
      }

      // 获取当前子容器节点
      let subNode = myDiagram.findNodeForKey(subKey);

      // 进入子容器线集合
      let linkIntoAttr = [];

      // 从子容器出来线集合
      let linkOutOfAttr = [];

      // 获取进入节点的线
      subNode.findLinksInto().each((item) => {
        linkIntoAttr.push(item.data);
      });
      // 获取从节点出来的线
      subNode.findLinksOutOf().each((item) => {
        linkOutOfAttr.push(item.data);
      });

      // 删除子组件本身的连线
      let removeLinks = [];
      subNode.findLinksConnected().each(function (link) {
        removeLinks.push(link.data);
      });
      myDiagram.model.removeLinkDataCollection(removeLinks);

      const subStartLink = subLinkDataArray.find((el) => el.sourceRef === 'pre');

      for (let i = 0; i < linkIntoAttr.length; i++) {
        let linkItem = linkIntoAttr[i];
        linkItem.to = subStartLink.to;
      }

      // 新增流入的连线
      subLinkDataArray = [...subLinkDataArray, ...linkIntoAttr];

      const subEndLink = subLinkDataArray.find((el) => el.targetRef === 'next' || el.targetRef === 'end');

      const subEndIndex = subLinkDataArray.findIndex((el) => el.targetRef === 'next' || el.targetRef === 'end');

      // 判断该流程是否是终止状态，如果是，则最终指向主流程的结束， 如果不是，则最终指向子容器的下一节点
      if (isEnd) {
        subLinkDataArray[subEndIndex].to = nodeDataArray.filter((el) => el.type === 'end').key;
      } else {
        for (let i = 0; i < linkOutOfAttr.length; i++) {
          let linkItem = linkOutOfAttr[i];
          linkItem.from = subEndLink.from;
        }
        subLinkDataArray = [...subLinkDataArray, ...linkOutOfAttr];
      }

      subLinkDataArray = subLinkDataArray.filter(
        (item) => item.sourceRef !== 'pre' && item.targetRef !== 'next' && item.targetRef !== 'end'
      );

      console.log('subNodeDataArray', subNodeDataArray);
      console.log('subLinkDataArray', subLinkDataArray);

      for (let i = 0; i < subLinkDataArray.length; i++) {
        const linkItem = subLinkDataArray[i];
        myDiagram.model.addLinkData(linkItem);
      }

      myDiagram.commitTransaction('addGroupContents');

      // 当前画布中的绘图数据
      const aa = JSON.parse(myDiagram.model.toJson());
      console.log(aa.nodeDataArray.length, aa.linkDataArray.length);
    },

    // 获取连线颜色 -
    // 普通节点： 根据sourceRef和targetRef分为去匹配已经生成的任务，如果有两个id中有任意一个不存在于taskList中，则说明是未走过流程
    // 子容器节点：
    getLinkColor(data) {
      const { sourceRef, targetRef } = data;
      let fromNodeStatus = false;
      let toNodeStatus = false;
      // 判断节点是普通节点还是子容器节点
      const isSubNodeFrom = sourceRef.startsWith('subContainer');
      const isSubNodeTo = targetRef.startsWith('subContainer');

      if (isSubNodeFrom) {
        fromNodeStatus = this.getSubContainerStatus(sourceRef);
      } else {
        fromNodeStatus = this.taskList.find((el) => el.id === sourceRef);
      }

      if (isSubNodeTo) {
        toNodeStatus = this.getSubContainerStatus(targetRef);
      } else {
        toNodeStatus = this.taskList.find((el) => el.id === targetRef);
      }
      if (
        fromNodeStatus !== 'ready' &&
        fromNodeStatus !== undefined &&
        toNodeStatus !== 'ready' &&
        toNodeStatus !== undefined
      ) {
        return blue;
      } else {
        return 'gray';
      }
    },

    // 返回节点背景图模板
    getTaskPictureTemplate() {
      const { getSubContainerStatus, getTaskStatus, textColor, bgColor } = this;
      return $(
        go.Panel,
        { name: 'pictureTemplate' },
        $(
          go.Shape,
          'RoundedRectangle',
          this.nodeText(),
          new go.Binding('stroke', function (e) {
            const status = e.category === 'subprocess' ? getSubContainerStatus(e.id) : getTaskStatus(e.id);
            return textColor[status];
          }),
          new go.Binding('fill', function (e) {
            const status = e.category === 'subprocess' ? getSubContainerStatus(e.id) : getTaskStatus(e.id);
            return bgColor[status];
          })
        ),
        // $(
        //   go.Shape,
        //   {
        //     desiredSize: new go.Size(14, 14),
        //     margin: new go.Margin(5, 0, 0, 5),
        //     strokeWidth: 0
        //   },
        //   new go.Binding('fill', function (e) {
        //     const status = e.category === 'subprocess' ? getSubContainerStatus(e.id) : getTaskStatus(e.id);
        //     return textColor[status];
        //   }),
        //   new go.Binding('geometry', function (e) {
        //     return geoFunc('' + e.type);
        //   })
        // )
      );
    },

    // 获取详情框数据
    getlDetail(e, o) {
      const status = this.getTaskStatus(o.data.id);
      const params = {
        applyOrdNo: this.applyOrdNo,
        nodeKey: o.data.id,
        nodeStatus: status == 'complete' ? 'finish' : status == 'ing' ? 'unfinish' : 'unstart'
      };

      getFlowChartDetail(params).then((res) => {
        // 模拟接口返回的详情数据
        let result = res.data.content;
        result.actStartTime = result.actStartTime ? moment(result.actStartTime).format('YYYY-MM-DD HH:mm') : '';
        result.actEndTime = result.actEndTime ? moment(result.actEndTime).format('YYYY-MM-DD HH:mm') : '';
        const obj = result;
        this.renderModal(obj);
        this.isShow = true;

        this.$nextTick(() => {
          // 弹框展示
          let left = e.Dr.offsetX;
          let top = e.Dr.offsetY + 50;

          const diagramDom = this.$refs['myDiagramDiv'];
          const dom = this.$refs['shallowBox'];

          // 防止弹框超出画布范围
          if (left + dom.clientWidth > diagramDom.clientWidth) {
            left = left - dom.clientWidth;
          }
          if (top + dom.clientHeight > diagramDom.clientHeight) {
            top = top - 50 - dom.clientHeight;
          }
          // 设置弹出框的位置
          this.modalStyle = {
            left: left + 'px',
            top: top + 'px'
          };
        });
      });
    },
    // 渲染弹出框信息
    renderModal(obj) {
      this.detailBindData = obj;
      const { actStartTime, dueDate, beforeDueLimit } = obj;
      let tipMsg = [];
      let currentTime = new Date().getTime();

      // 倒计时计算 - 前提：流入时间/办理期限不为空
      if (actStartTime) {
        if (dueDate) {
          // 任务截止时间 - 当前时间 ---> > 0 计算倒计时 ， <= 0 提示节点超时
          let differTime = new Date(dueDate).getTime() - currentTime; // 任务截止与流入时间差值
          if (differTime > 0) {
            // 倒计时
            let h = Math.floor(differTime / 1000 / 60 / 60);
            let m = Math.floor((differTime / 1000 / 60) % 60);
            let s = Math.floor((differTime / 1000) % 60);
            h = h < 10 ? '0' + h : h;
            m = m < 10 ? '0' + m : m;
            s = s < 10 ? '0' + s : s;
            this.detailBindData = {
              ...this.detailBindData,
              showCountDown: true,
              countTime: h + ':' + m + ':' + s
            };
            this.timer = setTimeout(() => {
              this.renderModal(obj);
            }, 1000);
          } else {
            // 系统超时
            tipMsg.push('节点超时');
          }
        }

        // 系统催办时间 - 当前时间 ---> > 0 不催办， <= 0 提示系统催办
        if (beforeDueLimit) {
          let differPress = new Date(actStartTime).getTime() + Number(beforeDueLimit) * 60 * 60 * 1000 - currentTime; // 催办时间与流入时间差值
          if (differPress <= 0) {
            tipMsg.push('系统催办');
          }
        }
      }

      this.detailBindData = {
        ...this.detailBindData,
        tipMsgStr: tipMsg.length > 0 ? tipMsg.join('/') : ''
      };

      console.log('详情数据', this.detailBindData);
    },
    nodeStyle() {
      return [
        new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
        {
          locationSpot: go.Spot.Center
        }
      ];
    },
    nodeText(defaultSize = ['90', '50']) {
      return [
        new go.Binding('desiredSize', function (e) {
          let size;
          if (e.size) {
            size = e.size.split(' ');
          } else {
            size = defaultSize;
          }
          return new go.Size(Number(size[0]), Number(size[1]));
        })
      ];
    },
    initDiagram() {
      const {
        getTaskStatus,
        getSubContainerStatus,
        textColor,
        borderColor,
        bgColor,
        getLinkColor,
        addGroupItems,
        getTaskPictureTemplate,
        getlDetail,
        closeModal,
        getSubContainerDrawData,
        nodeStyle,
        nodeText
      } = this;

      let { myDiagram } = this;

      myDiagram = $(go.Diagram, 'myDiagramDiv', {
        // initialContentAlignment: go.Spot.Left,
        allowCopy: false,
        allowDelete: false
      });

      // 返回文字节点模板
      function getTextTemplate() {
        return $(
          go.TextBlock,
          {
            font: '10pt Lato, Helvetica, Arial, sans-serif',
            name: 'textTemplate',
            wrap: go.TextBlock.WrapDesiredSize,
            verticalAlignment: go.Spot.Center,
            textAlign: 'center'
          },
          nodeText(),
          new go.Binding('stroke', function (e) {
            const status = e.category === 'subprocess' ? getSubContainerStatus(e.id) : getTaskStatus(e.id);
            return textColor[status];
          }),
          new go.Binding('text', 'text', function (text) {
            // 只截取7个字符长度，超过部分用'...'表示
            if (text.length > 10) {
              return text.substr(0, 10) + '...';
            } else {
              return text;
            }
          })
        );
      }

      // 返回悬浮提示框节点模板
      function getToolTipTemplate() {
        return $('ToolTip', $(go.TextBlock, { margin: 3 }, new go.Binding('text')));
      }

      // 定义事件-开始/结束模板
      // 结束节点 -> 只有“未开始/已完成” 状态, 开始节点 -> 只有“已完成”状态
      const eventNodeTemplate = $(
        go.Node,
        'Table',
        nodeStyle(),
        $(
          go.Panel,
          'Spot',
          { desiredSize: new go.Size(45, 45) },
          $(
            go.Shape,
            'Circle',
            {
              stroke: null
            },
            new go.Binding('fill', function (e) {
              return e.type == 'start' ? lightBlue : lightGray;
            })
          ),
          $(
            go.Shape,
            'Circle',
            {
              desiredSize: new go.Size(35, 35),
              strokeWidth: 2,
              stroke: null
            },
            new go.Binding('fill', function (e) {
              if (e.type == 'start') {
                return blue;
              } else {
                return getTaskStatus(e.id) === 'ready' ? 'white' : blue;
              }
            })
          ),
          $(
            go.TextBlock,
            {
              font: 'bold 9pt helvetica, bold arial, sans-serif'
            },
            new go.Binding('stroke', function (e) {
              if (e.type == 'start') {
                return 'white';
              } else {
                return getTaskStatus(e.id) === 'ready' ? 'gray' : 'white';
              }
            }),
            new go.Binding('text')
          )
        )
      );

      // 定义节点默认模板
      const defaultNodeTemplate = $(go.Node, 'Auto', nodeStyle(), getTaskPictureTemplate(), getTextTemplate(), {
        toolTip: getToolTipTemplate(),
        click: function (e, o) {
          return getlDetail(e, o);
        },
        selectionChanged: function (e) {
          if (!e.isSelected) {
            closeModal();
          }
        }
      });

      // 定义网关节点模板
      // const gatewayNodeTemplate = $(go.Node, "Auto", getTaskPictureTemplate());
      const gatewayNodeTemplate = $(
        go.Node,
        'Table',
        nodeStyle(),
        $(
          go.Panel,
          'Spot',
          { desiredSize: new go.Size(40, 40) },
          // 最外层
          $(
            go.Shape,
            'Diamond',
            {
              stroke: null
            },
            new go.Binding('fill', function (e) {
              const status = getTaskStatus(e.id);
              return status === 'ready' ? lightGray : status === 'complete' ? lightBlue : lightGreen;
            })
          ),
          // 中间层
          $(
            go.Shape,
            'Diamond',
            {
              desiredSize: new go.Size(25, 25),
              strokeWidth: 2
            },
            new go.Binding('stroke', function (e) {
              const status = getTaskStatus(e.id);
              return status === 'ready' ? 'gray' : null;
            }),
            new go.Binding('fill', function (e) {
              const status = getTaskStatus(e.id);
              return status === 'ready' ? 'white' : status === 'complete' ? blue : green;
            })
          ),
          // 里层
          $(
            go.Shape,
            {
              desiredSize: new go.Size(10, 10),
              strokeWidth: 2
            },
            new go.Binding('stroke', function (e) {
              const status = getTaskStatus(e.id);
              return status === 'ready' ? 'gray' : 'white';
            }),
            new go.Binding('figure', function (obj) {
              const { type } = obj;
              return type == 'exclusiveGateway' ? 'XLine' : type == 'inclusiveGateway' ? 'CircleLine' : 'PlusLine';
            })
          )
        )
      );

      // 定义子容器分组
      const defaultGroupTemplate = $(
        go.Group,
        'Auto',
        nodeStyle(),
        {
          layout: $(go.TreeLayout, {
            angle: 90,
            arrangement: go.TreeLayout.ArrangementHorizontal,
            isRealtime: false
          }),
          isSubGraphExpanded: false,
          subGraphExpandedChanged: function (group) {
            // 动态修改节点属性值
            let box = group.findObject('box');
            let pictureTemplate = group.findObject('pictureTemplate');
            let textTemplate = group.findObject('textTemplate');
            box.visible = group.isSubGraphExpanded;
            pictureTemplate.visible = !box.visible;
            textTemplate.visible = !box.visible;
            if (group.memberParts.count === 0) {
              addGroupItems(group.data, myDiagram);
            }
          }
        },
        $(
          go.Shape,
          'Rectangle',
          {
            name: 'box',
            fill: null,
            visible: false,
            strokeDashArray: [10, 10] // 设置虚线
          },
          new go.Binding('stroke', 'id', function (id) {
            let status = getSubContainerStatus(id);
            return borderColor[status];
          })
        ),
        $(
          go.Panel,
          'Table',
          { margin: new go.Margin(0, 0, 0, 0) },
          getTaskPictureTemplate(),
          getTextTemplate(),
          $(
            'SubGraphExpanderButton',
            {
              alignment: go.Spot.Right,
              margin: new go.Margin(0, 15, 0, 0),
              width: 18,
              height: 18
            },
            new go.Binding('visible', 'id', function (id) {
              let node = getSubContainerDrawData(id);
              if (node) {
                // 子容器的绘图数据
                let subNodeDataArray = node.diagramModel.nodeDataArray;
                let subLinkDataArray = node.diagramModel.linkDataArray;

                // 节点或者连线，两者有一个没有数据，则默认不绘图
                if (
                  subNodeDataArray.length === 0 ||
                  subLinkDataArray.length === 0 ||
                  subNodeDataArray.length === 2 ||
                  subLinkDataArray.length < subNodeDataArray.length - 1
                ) {
                  return false;
                } else {
                  return true;
                }
              } else {
                return false;
              }
            })
          ),
          $(go.Placeholder, {
            row: 1,
            columnSpan: 2,
            padding: 10,
            alignment: go.Spot.TopLeft
          })
        ),

        {
          toolTip: getToolTipTemplate()
        }
      );

      /*******************  节点模板引用    ***************************/
      myDiagram.nodeTemplateMap.add('', defaultNodeTemplate);
      myDiagram.nodeTemplateMap.add('event', eventNodeTemplate);
      myDiagram.nodeTemplateMap.add('gateway', gatewayNodeTemplate);

      /*******************  分组模板引用    ***************************/
      myDiagram.groupTemplateMap.add('subprocess', defaultGroupTemplate);

      /*******************  连线模板    ***************************/

      myDiagram.linkTemplate = $(
        go.Link, // the whole link panel
        {
          routing: go.Link.AvoidsNodes,
          // curve: go.Link.JumpOver,
          corner: 5
        },
        new go.Binding('points').makeTwoWay(),
        $(
          go.Shape, // the link path shape
          { isPanelMain: true, strokeWidth: 1 },
          new go.Binding('stroke', function (e) {
            let color = getLinkColor(e);
            return color;
          })
          // new go.Binding("stroke", "isSelected", function (sel) {
          //   return sel ? "dodgerblue" : "gray";
          // }).ofObject()
        ),
        // 箭头
        $(
          go.Shape,
          { toArrow: 'standard', strokeWidth: 0 },
          new go.Binding('fill', function (e) {
            return getLinkColor(e);
          })
        ),
        $(
          go.Panel,
          'Auto',
          $(
            go.TextBlock,
            {
              textAlign: 'center',
              font: '9pt helvetica, arial, sans-serif',
              margin: 4
            },
            new go.Binding('text')
          )
        )
      );

      // 鼠标滚轮滚动，隐藏弹框
      const tool = myDiagram.toolManager;
      tool.standardMouseWheel = () => {
        if (this.isShow) {
          this.isShow = false;
        }
        go.ToolManager.prototype.standardMouseWheel.call(tool);
      };

      // 加载数据
      myDiagram.model = go.Model.fromJson(this.modelData.json);
      this.isEmpty = Object.keys(this.modelData).length == 0;
    }
  },
  mounted() {
    processConfig(this.applyOrdNo).then((res) => {
      if (res.data.content) {
        this.modelData = res.data.content;
        this.$nextTick(() => {
          this.initDiagram();
        });
      }
    });
  },
  created() {}
};
</script>

<style lang="scss">
/* -- 流程图状态说明 ---------*/
.legend-group {
  display: flex;
  align-items: center;
  &__item {
    display: flex;
    align-items: center;
    margin-left: 20px;
    .retange {
      display: inline-block;
      width: 16px;
      height: 16px;
      border: 1px;
      background: red;
      margin-right: 5px;
    }
  }
}
.shallow-box {
  position: absolute;
  top: 300px;
  left: 100px;
  padding: 12px;
  width: 400px;
  border: 1px solid lightgray;
  background: white;
  z-index: 10000;
  color: rgba(0, 0, 0, 0.85);
  .close {
    position: absolute;
    right: 10px;
    top: 5px;
    cursor: pointer;
  }
  .header {
    display: flex;
    align-items: center;
    border-bottom: 1px solid lightgray;
    padding-bottom: 12px;
    .title {
      width: 270px;
      display: inline-block;
      // white-space: nowrap;
      // overflow: hidden;
      // text-overflow: ellipsis;
    }
    .time {
      margin-left: 30px;
      background: rgb(227, 239, 255);
      height: 24px;
      padding: 0 5px;
    }
  }
  .form-item {
    display: flex;
    margin: 10px 0;
    .label {
      width: 80px;
      color: gray;
      display: inline-block;
    }
    .text {
      width: calc(100% - 80px);
    }
  }
}
</style>

