<template>
  <div>
    <v-stage
      id="vstage"
      ref="stage"
      :config="wf.stageSize"
      @mousedown="handleStageMouseDown"
      @mousemove="handleStageMouseMove"
      @contextmenu="handleStageContextMenu"
      @contentContextmenu="contentContextmenu"
    >
      <v-layer ref="layer">
        <v-circle
          v-for="node in wf.WFNodes"
          :key="node.id"
          :config="node"
          @mousedown="nodeMouseDown"
          @dragmove="nodeDragMove"
          @dragend="nodeDragEnd"
          @mouseover="nodeMouseOver"
          @mouseleave="nodeMouseLeave"
        ></v-circle>
        <v-label v-for="nodeinfo in wf.nodeInfos" :key="nodeinfo.id" :config="nodeinfo">
          <v-tag :config="nodeinfo.tag"></v-tag>
          <v-text :config="nodeinfo.text"></v-text>
        </v-label>
        <v-arrow v-for="line in wf.lines" :key=" line.id" :config="line" @click="lineSelected"></v-arrow>
        <v-circle
          v-for="anchor in wf.AnchorPoints"
          :key="anchor.id"
          :config="anchor"
          @dragmove="anchorDragMove"
          @dragend="anchorDragEnd"
          @mouseup="anchorMouseUp"
        ></v-circle>

        <v-label v-for="toolTip in wf.toolTips" :key="toolTip.id" :config="toolTip" v-show="false">
          <v-tag :config="toolTip.tag" v-show="false"></v-tag>
          <v-text :config="toolTip.text" v-show="false"></v-text>
        </v-label>

        <v-transformer :config="wf.transformerConfig" ref="transformer" />
      </v-layer>
    </v-stage>
    <el-card
      class="box-card"
      :style="{left:wf.stageMenuContext.left,top:wf.stageMenuContext.top,width:wf.stageMenuContext.width}"
      v-show="wf.stageMenuContext.active"
      @contextmenu.native="preventContextMenu"
    >
      <el-row>
        <el-button type="primary" icon="iconfont icon-start" @click="addStartNode" circle></el-button>
        <el-button type="primary" icon="iconfont icon-wfnode" @click="addAuditNode" circle></el-button>
        <el-button type="primary" icon="iconfont icon-wfnode2" @click="addConditionNode" circle></el-button>
        <el-button type="primary" icon="iconfont icon-wfend" @click="addEndNode" circle></el-button>
        <el-button type="primary" icon="iconfont icon-wfexport" @click="wfExport" circle></el-button>
        <el-button type="primary" icon="iconfont icon-wfimport" @click="wfImport" circle></el-button>
      </el-row>
    </el-card>
    <el-card
      class="box-card"
      :style="{left:wf.nodeMenuContext.left,top:wf.nodeMenuContext.top,width:wf.nodeMenuContext.width}"
      v-show="wf.nodeMenuContext.active"
      @contextmenu.native="preventContextMenu"
    >
      <el-row>
        <el-button type="primary" icon="iconfont icon-wfline" @click="addLine" circle></el-button>
        <el-button type="primary" icon="el-icon-edit" @click="setNode" circle></el-button>
        <el-button type="danger" icon="el-icon-delete" @click="deleteNode" circle></el-button>
      </el-row>
    </el-card>
    <el-card
      class="box-card"
      :style="{left:wf.lineMenuContext.left,top:wf.lineMenuContext.top,width:wf.lineMenuContext.width}"
      v-show="wf.lineMenuContext.active"
      @contextmenu.native="preventContextMenu"
    >
      <el-row>
        <el-button type="primary" icon="el-icon-edit" @click="setLine" circle></el-button>
        <el-button type="danger" icon="el-icon-delete" @click="deleteLine" circle></el-button>
      </el-row>
    </el-card>
    <el-dialog title="导入流程配置" :visible.sync="dialogUploadVisible">
      <el-upload
        class="upload-wf"
        drag
        action
        ref="import"
        :auto-upload="false"
        :file-list="fileList"
        :on-change="handleChange"
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">
          将文件拖到此处，或
          <em>点击选择流程配置文件</em>
        </div>
        <div class="el-upload__tip" slot="tip">只能上传jpg/png文件，且不超过500kb</div>
      </el-upload>
    </el-dialog>
    <el-dialog title="编辑条件线" :visible.sync="dialogLineVisible">
      <el-row :gutter="20">
        <el-col :span="12">
          <div>编号</div>
        </el-col>
        <el-col :span="12">
          <div>{{wf.curEditLine.config.nodeCode}}</div>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <div>描述</div>
        </el-col>
        <el-col :span="12">
          <el-input v-model="wf.curEditLine.config.desc" placeholder="请输入内容"></el-input>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <div>条件脚本</div>
        </el-col>
        <el-col :span="12">
          <div class="ace-editor-wrap">
            <ace-editor ref="aceEditor" :config="aceConfig" @init="aceInit" @input="aceChange"></ace-editor>
          </div>
        </el-col>
      </el-row>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogLineVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveLineEdit">确 定</el-button>
      </div>
    </el-dialog>
    <el-dialog title="编辑审批节点" :visible.sync="dialogNodeVisible">
      <el-row :gutter="20">
        <el-col :span="12">
          <div>审核用户id</div>
        </el-col>
        <el-col :span="12">
          <el-input v-model="wf.curEditNode.config.userId" placeholder="请输入内容"></el-input>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <div>审核用户名称</div>
        </el-col>
        <el-col :span="12">
          <el-input v-model="wf.curEditNode.config.userName" placeholder="请输入内容"></el-input>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <div>节点描述</div>
        </el-col>
        <el-col :span="12">
          <el-input
            type="textarea"
            :rows="2"
            placeholder="请输入描述信息"
            v-model="wf.curEditNode.config.desc"
          ></el-input>
        </el-col>
      </el-row>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogNodeVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveNodeEdit">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { uuid } from "vue-uuid"; // Import uuid
import https from "../https";
import aceEditor from "../components/AceEditor/index.vue";

const width = window.innerWidth;
const height = window.innerHeight;
export default {
  components: {
    "ace-editor": aceEditor
  },
  data() {
    return {
      fileList: [],
      dialogUploadVisible: false,
      dialogLineVisible: false,
      dialogNodeVisible: false,
      aceConfig: {
        width: 450,
        height: 300,
        value: "",
        autoCompletion: true,
        fullScreen: false,
        theme: "monokai",
        lang: "javascript"
      },
      wf: {
        stageMenuContext: {
          left: "100px",
          top: "100px",
          width: "350px",
          active: false
        },
        nodeMenuContext: {
          left: "100px",
          top: "100px",
          width: "180px",
          active: false
        },
        lineMenuContext: {
          left: "100px",
          top: "100px",
          width: "120px",
          active: false
        },
        startNode: null,
        stageSize: {
          width: width,
          height: height,
          draggable: true
        },
        curSelectedNode: null,
        curEditLine: {
          points: [],
          stroke: "#B0E0E6",
          id: "",
          fill: "#B0E0E6",
          strokeEnabled: true,
          listening: true,
          draggable: false,
          sNodeId: "",
          eNodeId: "",
          strokeWidth: 5,
          type: "line",

          config: {
            nodeCode: 0,
            desc: "",
            conditionFuncStr: ""
          },

          tipId: ""
        },
        curEditNode: {
          x: 0,
          y: 0,
          radius: 60,
          fill: "	#7FFFD4",
          draggable: true,
          id: "",
          name: "cond",
          type: "wfn",

          scaleX: 1,
          scaleY: 1,
          wfNodeType: "cond",

          config: {
            userId: "",
            userName: "",
            desc: ""
          },

          tipId: ""
        },
        oldSelectedNode: null,
        selectedShapeId: "",
        transformerConfig: {
          rotateEnabled: false,
          enabledAnchors: ["bottom-right"],
          borderDash: [6, 1, 6]
        },
        lines: [],
        curLine: null,
        AnchorPoints: [],
        WFNodes: [],
        nodeInfos: [],
        toolTips: [
          {
            id: uuid.v4(),
            x: 170,
            y: 75,
            visible: false,
            opacity: 0.75,
            tag: {
              fill: "black",
              pointerDirection: "down",
              pointerWidth: 10,
              pointerHeight: 10,
              lineJoin: "round",
              shadowColor: "black",
              shadowBlur: 10,
              shadowOffsetX: 10,
              shadowOffsetY: 10,
              shadowOpacity: 0.5
            },
            text: {
              text: "Tooltip pointing down aadsdfasdfa",
              fontFamily: "Calibri",
              fontSize: 18,
              padding: 5,
              fill: "white"
            }
          }
        ],
        MousePoint: {
          x: 0,
          y: 0
        }
      }
    };
  },
  props: {
    workflow: Object
  },
  watch: {
    workflow: {
      handler(n, o) {
        this.wf.WFNodes = this.workflow.WFNodes;
        this.wf.lines = this.workflow.lines;
        this.wf.toolTips = this.workflow.toolTips;
        this.wf.id = this.workflow.id;
        this.wf.name = this.workflow.name;
        this.wf.desc = this.workflow.desc;
        this.wf.createUserId = this.workflow.createUserId;
        this.wf.createUserName = this.workflow.createUserName;
        this.wf.updateUserId = this.workflow.updateUserId;
        this.wf.updateUserName = this.workflow.updateUserName;
        this.wf.createTime = this.workflow.createTime;
        this.wf.updateTime = this.workflow.updateTime;
        this.wf.version = this.workflow.version;
        this.wf.nodeInfos = this.workflow.nodeInfos;
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    aceInit($ace) {
      console.log($ace);
    },
    aceChange(content, $ace, $fn) {
      console.log("content", content);
      this.wf.curEditLine.config.conditionFuncStr = content;
    },
    getWorkflow() {
      var lines = [];
      this.wf.lines.forEach(line => {
        lines.push({
          id: line.id,
          isDelete: false,
          wfId: this.wf.id,
          lineDef: "",
          linedefine: line
        });
      });
      var nodes = [];
      this.wf.WFNodes.forEach(node => {
        nodes.push({
          id: node.id,
          wfId: this.wf.id,
          nodeDef: "",
          inLines: [],
          outLines: [],
          nodeDefine: node
        });
      });
      var toolTips = [];
      this.wf.toolTips.forEach(tip => {
        toolTips.push({
          id: tip.id,
          wfId: this.wf.id,
          tipDef: JSON.stringify(tip)
        });
      });
      var curWF = {
        id: this.wf.id,
        name: this.wf.name,
        desc: this.wf.desc,
        createUserId: this.wf.createUserId,
        updateUserId: this.wf.updateUserId,
        createUserName: this.wf.createUserName,
        updateUserName: this.wf.updateUserName,
        createTime: this.wf.createTime,
        updateTime: this.wf.updateTime,
        version: this.wf.version,
        lines: lines,
        nodes: nodes,
        toolTips: toolTips
      };

      return curWF;
    },
    preventContextMenu(e) {
      e.preventDefault();
    },
    handleChange(file, fileList) {
      var that = this;
      var content = "";
      var reader = new FileReader();
      reader.onload = (function(theFile) {
        return function(e) {
          content = e.target.result;
        };
      })(file);

      reader.onloadend = function() {
        var wfjson = content;
        var wfObj = JSON.parse(wfjson);
        if (wfObj.constructor === Object) {
          that.wf = wfObj;
          that.wf.id = "00000000-0000-0000-0000-000000000000";
          that.wf.createUserId = "00000000-0000-0000-0000-000000000000";
          that.wf.updateUserId = "00000000-0000-0000-0000-000000000000";
          that.dialogUploadVisible = false;
        } else {
          console.log("导入工作流配置错误");
        }
      };
      reader.readAsText(file.raw);
    },
    wfExport(e) {
      this.download("wf.json", JSON.stringify(this.wf));
      this.wf.nodeMenuContext.active = false;
    },
    download(filename, text) {
      var element = document.createElement("a");
      element.setAttribute(
        "href",
        "data:text/plain;charset=utf-8," + encodeURIComponent(text)
      );
      element.setAttribute("download", filename);

      element.style.display = "none";
      document.body.appendChild(element);

      element.click();

      document.body.removeChild(element);
    },
    wfImport(e) {
      this.wf.nodeMenuContext.active = false;
      this.dialogUploadVisible = true;
    },
    saveLineEdit(e) {
      this.dialogLineVisible = false;
      var line = this.wf.lines.find(p => p.id === this.wf.curEditLine.id);
      if (line !== undefined) {
        line.config.desc = this.wf.curEditLine.config.desc;
        line.config.conditionFuncStr = this.wf.curEditLine.config.conditionFuncStr;

        var tipLine = this.wf.toolTips.find(p => p.id === line.tipId);
        if (tipLine !== undefined) {
          tipLine.text.text = line.config.desc;
        }
      }
    },
    saveNodeEdit(e) {
      this.dialogNodeVisible = false;
      var node = this.wf.WFNodes.find(p => p.id === this.wf.curSelectedNode.id);
      if (node !== undefined) {
        node.config.desc = this.wf.curEditNode.config.desc;
        node.config.userId = this.wf.curEditNode.config.userId;
        node.config.userName = this.wf.curEditNode.config.userName;

        var tipNode = this.wf.toolTips.find(p => p.id === node.tipId);
        if (tipNode !== undefined) {
          tipNode.text.text = node.config.desc;
        }

        var nodeinfo = this.wf.nodeInfos.find(p => p.nodeId === node.id);
        if (nodeinfo !== undefined) {
          nodeinfo.text.text = node.config.userName;
        } else {
          var nodeInfo = {
            id: uuid.v4(),
            x: this.wf.curSelectedNode.x,
            y: this.wf.curSelectedNode.y,
            visible: true,
            opacity: 0.75,
            tag: {
              fill: "green",
              pointerDirection: "down",
              pointerWidth: 0,
              pointerHeight: 0,
              lineJoin: "round",
              shadowColor: "green",
              shadowBlur: 10,
              shadowOffsetX: 10,
              shadowOffsetY: 10,
              shadowOpacity: 0.5
            },
            text: {
              text: "人员未定义",
              fontFamily: "Calibri",
              fontSize: 18,
              padding: 5,
              fill: "white"
            },
            nodeId: this.wf.curSelectedNode.id
          };
          nodeInfo.text.text = node.config.userName;
          this.wf.nodeInfos.push(nodeInfo);
        }
      }
    },
    addStartNode(e) {
      if (this.wf.WFNodes.every(p => p.wfNodeType !== "start")) {
        var nodeInfo = {
          id: uuid.v4(),
          x: this.wf.MousePoint.x,
          y: this.wf.MousePoint.y,
          visible: true,
          opacity: 0.75,
          tag: {
            fill: "green",
            pointerDirection: "down",
            pointerWidth: 0,
            pointerHeight: 0,
            lineJoin: "round",
            shadowColor: "green",
            shadowBlur: 10,
            shadowOffsetX: 10,
            shadowOffsetY: 10,
            shadowOpacity: 0.5
          },
          text: {
            text: "人员未定义",
            fontFamily: "Calibri",
            fontSize: 18,
            padding: 5,
            fill: "white"
          },
          nodeId: ""
        };
        var tooltip = {
          id: uuid.v4(),
          x: this.wf.MousePoint.x,
          y: this.wf.MousePoint.y - 50,
          visible: false,
          opacity: 0.75,
          tag: {
            fill: "black",
            pointerDirection: "down",
            pointerWidth: 10,
            pointerHeight: 10,
            lineJoin: "round",
            shadowColor: "black",
            shadowBlur: 10,
            shadowOffsetX: 10,
            shadowOffsetY: 10,
            shadowOpacity: 0.5
          },
          text: {
            text: "流程开始节点",
            fontFamily: "Calibri",
            fontSize: 18,
            padding: 5,
            fill: "white"
          }
        };
        var sNode = {
          x: this.wf.MousePoint.x,
          y: this.wf.MousePoint.y,
          radius: 50,
          fill: "#0f0",
          draggable: true,
          // strokeEnabled: false,

          id: uuid.v1(),
          name: "r2",
          type: "wfn",

          scaleX: 1,
          scaleY: 1,
          wfNodeType: "start",

          config: {
            userId: "",
            userName: "",
            desc: ""
          },

          tipId: tooltip.id
        };
        nodeInfo.nodeId = sNode.id;
        this.wf.WFNodes.push(sNode);
        this.wf.nodeInfos.push(nodeInfo);
        this.wf.toolTips.push(tooltip);
      }
      this.wf.nodeMenuContext.active = false;
    },
    addAuditNode(e) {
      var nodeInfo = {
        id: uuid.v4(),
        x: this.wf.MousePoint.x,
        y: this.wf.MousePoint.y,
        visible: true,
        opacity: 0.75,
        tag: {
          fill: "green",
          pointerDirection: "down",
          pointerWidth: 0,
          pointerHeight: 0,
          lineJoin: "round",
          shadowColor: "green",
          shadowBlur: 10,
          shadowOffsetX: 10,
          shadowOffsetY: 10,
          shadowOpacity: 0.5
        },
        text: {
          text: "人员未定义",
          fontFamily: "Calibri",
          fontSize: 18,
          padding: 5,
          fill: "white"
        },
        nodeId: ""
      };
      var tooltip = {
        id: uuid.v4(),
        x: this.wf.MousePoint.x,
        y: this.wf.MousePoint.y - 80,
        visible: false,
        opacity: 0.75,
        tag: {
          fill: "black",
          pointerDirection: "down",
          pointerWidth: 10,
          pointerHeight: 10,
          lineJoin: "round",
          shadowColor: "black",
          shadowBlur: 10,
          shadowOffsetX: 10,
          shadowOffsetY: 10,
          shadowOpacity: 0.5
        },
        text: {
          text: "审批节点",
          fontFamily: "Calibri",
          fontSize: 18,
          padding: 5,
          fill: "white"
        }
      };
      var anode = {
        x: this.wf.MousePoint.x,
        y: this.wf.MousePoint.y,
        radius: 80,
        fill: "#f4f4d2",
        draggable: true,
        // strokeEnabled: false,

        id: uuid.v1(),
        name: "r2",
        type: "wfn",

        scaleX: 1,
        scaleY: 1,
        wfNodeType: "audit",

        config: {
          userId: "",
          userName: "",
          desc: ""
        },

        tipId: tooltip.id
      };
      nodeInfo.nodeId = anode.id;
      this.wf.WFNodes.push(anode);
      this.wf.nodeInfos.push(nodeInfo);
      this.wf.toolTips.push(tooltip);
      this.wf.nodeMenuContext.active = false;
    },
    addConditionNode(e) {
      var nodeInfo = {
        id: uuid.v4(),
        x: this.wf.MousePoint.x,
        y: this.wf.MousePoint.y,
        visible: true,
        opacity: 0.75,
        tag: {
          fill: "green",
          pointerDirection: "down",
          pointerWidth: 0,
          pointerHeight: 0,
          lineJoin: "round",
          shadowColor: "green",
          shadowBlur: 10,
          shadowOffsetX: 10,
          shadowOffsetY: 10,
          shadowOpacity: 0.5
        },
        text: {
          text: "",
          fontFamily: "Calibri",
          fontSize: 18,
          padding: 5,
          fill: "white"
        },
        nodeId: ""
      };
      var tooltip = {
        id: uuid.v4(),
        x: this.wf.MousePoint.x,
        y: this.wf.MousePoint.y - 60,
        visible: false,
        opacity: 0.75,
        tag: {
          fill: "black",
          pointerDirection: "down",
          pointerWidth: 10,
          pointerHeight: 10,
          lineJoin: "round",
          shadowColor: "black",
          shadowBlur: 10,
          shadowOffsetX: 10,
          shadowOffsetY: 10,
          shadowOpacity: 0.5
        },
        text: {
          text: "条件自动流转节点",
          fontFamily: "Calibri",
          fontSize: 18,
          padding: 5,
          fill: "white"
        }
      };
      var cnode = {
        x: this.wf.MousePoint.x,
        y: this.wf.MousePoint.y,
        radius: 60,
        fill: "	#7FFFD4",
        draggable: true,
        // strokeEnabled: false,

        id: uuid.v1(),
        name: "cond",
        type: "wfn",

        scaleX: 1,
        scaleY: 1,
        wfNodeType: "cond",

        config: {
          userId: "",
          userName: "",
          desc: ""
        },

        tipId: tooltip.id
      };
      nodeInfo.nodeId = cnode.id;
      this.wf.WFNodes.push(cnode);
      this.wf.nodeInfos.push(nodeInfo);
      this.wf.toolTips.push(tooltip);
      this.wf.nodeMenuContext.active = false;
    },
    addEndNode(e) {
      if (this.wf.WFNodes.every(p => p.wfNodeType !== "end")) {
        var nodeInfo = {
          id: uuid.v4(),
          x: this.wf.MousePoint.x,
          y: this.wf.MousePoint.y,
          visible: true,
          opacity: 0.75,
          tag: {
            fill: "green",
            pointerDirection: "down",
            pointerWidth: 0,
            pointerHeight: 0,
            lineJoin: "round",
            shadowColor: "green",
            shadowBlur: 10,
            shadowOffsetX: 10,
            shadowOffsetY: 10,
            shadowOpacity: 0.5
          },
          text: {
            text: "人员未定义",
            fontFamily: "Calibri",
            fontSize: 18,
            padding: 5,
            fill: "white"
          },
          nodeId: ""
        };
        var tooltip = {
          id: uuid.v4(),
          x: this.wf.MousePoint.x,
          y: this.wf.MousePoint.y - 50,
          visible: false,
          opacity: 0.75,
          tag: {
            fill: "black",
            pointerDirection: "down",
            pointerWidth: 10,
            pointerHeight: 10,
            lineJoin: "round",
            shadowColor: "black",
            shadowBlur: 10,
            shadowOffsetX: 10,
            shadowOffsetY: 10,
            shadowOpacity: 0.5
          },
          text: {
            text: "流程结束节点",
            fontFamily: "Calibri",
            fontSize: 18,
            padding: 5,
            fill: "white"
          }
        };
        var enode = {
          x: this.wf.MousePoint.x,
          y: this.wf.MousePoint.y,
          radius: 50,
          fill: "#353535",
          draggable: true,
          // strokeEnabled: false,

          id: uuid.v1(),
          name: "end",
          type: "wfn",

          scaleX: 1,
          scaleY: 1,
          wfNodeType: "end",

          config: {
            userId: "",
            userName: "",
            desc: ""
          },

          tipId: tooltip.id
        };
        nodeInfo.nodeId = enode.id;
        this.wf.WFNodes.push(enode);
        this.wf.nodeInfos.push(nodeInfo);
        this.wf.toolTips.push(tooltip);
      }
      this.wf.nodeMenuContext.active = false;
    },
    deleteNode(e) {
      var that = this;

      for (var i = 0; i < this.wf.lines.length; i++) {
        if (this.wf.lines[i].sNodeId === that.wf.curSelectedNode.id) {
          var nodeId = uuid.v4();
          var anchorNode = {
            x: this.wf.lines[i].points[0],
            y: this.wf.lines[i].points[1],
            radius: 16,
            fill: "red",
            draggable: true,
            strokeEnabled: false,
            scaleX: 1,
            scaleY: 1,

            id: nodeId,
            wfNodeId: "",
            pairId: this.wf.lines[i].eNodeId,
            type: "astart"
          };
          this.wf.lines[i].sNodeId = anchorNode.id;
          that.wf.AnchorPoints.push(anchorNode);

          continue;
        }

        if (this.wf.lines[i].eNodeId === that.wf.curSelectedNode.id) {
          var nodeId = uuid.v4();
          var anchorNode = {
            x: this.wf.lines[i].points[2],
            y: this.wf.lines[i].points[3],
            radius: 16,
            fill: "red",
            draggable: true,
            strokeEnabled: false,
            scaleX: 1,
            scaleY: 1,

            id: nodeId,
            wfNodeId: "",
            pairId: this.wf.lines[i].sNodeId,
            type: "aend"
          };
          this.wf.lines[i].eNodeId = anchorNode.id;
          that.wf.AnchorPoints.push(anchorNode);

          continue;
        }
      }

      that.wf.WFNodes.splice(
        that.wf.WFNodes.findIndex(p => p.id === that.wf.curSelectedNode.id),
        1
      );
      that.wf.toolTips.splice(
        that.wf.toolTips.findIndex(p => p.id === that.wf.curSelectedNode.tipId),
        1
      );
      that.wf.nodeInfos.splice(
        that.wf.nodeInfos.findIndex(
          p => p.nodeId === that.wf.curSelectedNode.id
        ),
        1
      );
    },
    setLine(e) {
      this.dialogLineVisible = true;
      this.wf.curEditLine = this.wf.lines.find(
        p => p.id === this.wf.curLine.id
      );
      this.aceConfig.value = this.wf.curEditLine.config.conditionFuncStr;
      this.$refs.aceEditor.initAce(this.aceConfig);
    },
    setNode(e) {
      this.dialogNodeVisible = true;
      this.wf.curEditNode = this.wf.WFNodes.find(
        p => p.id === this.wf.curSelectedNode.id
      );
    },
    addLine(e) {
      if (this.wf.startNode.wfNodeType === "end") {
        this.$message({
          message: "结束节点不能作为连线起点",
          type: "warning"
        });
        return;
      }
      var eNodeId = uuid.v1();
      var lineId = uuid.v1();
      var startAnchorNode = {
        x: this.wf.startNode.x + this.wf.startNode.radius,
        y: this.wf.startNode.y + this.wf.startNode.radius,
        radius: this.wf.startNode.radius * this.wf.startNode.scaleX,
        id: this.wf.startNode.id,
        pairId: eNodeId
      };
      var endAnchorNode = {
        x: this.wf.MousePoint.x + 120,
        y: this.wf.MousePoint.y,
        radius: 16,
        fill: "red",
        draggable: true,
        strokeEnabled: false,
        scaleX: 1,
        scaleY: 1,

        id: eNodeId,
        wfNodeId: "",
        pairId: this.wf.startNode.id,
        type: "aend"
      };
      var points = this.getConnectorPoints(this.wf.startNode, endAnchorNode);

      var tooltip = {
        id: uuid.v4(),
        x: (points[0] + points[2]) / 2,
        y: (points[1] + points[3]) / 2,
        visible: false,
        opacity: 0.75,
        tag: {
          fill: "black",
          pointerDirection: "down",
          pointerWidth: 10,
          pointerHeight: 10,
          lineJoin: "round",
          shadowColor: "black",
          shadowBlur: 10,
          shadowOffsetX: 10,
          shadowOffsetY: 10,
          shadowOpacity: 0.5
        },
        text: {
          text: "未定义条件，自动流转到下一节点",
          fontFamily: "Calibri",
          fontSize: 18,
          padding: 5,
          fill: "white"
        }
      };

      var lineCodeNum = 1;
      if (
        this.wf.lines === undefined ||
        this.wf.lines == null ||
        this.wf.lines.length === 0
      ) {
        lineCodeNum = 1;
      } else {
        this.wf.lines.forEach(line => {
          if (line.config.nodeCode >= lineCodeNum) {
            lineCodeNum = line.config.nodeCode + 1;
          }
        });
      }

      var line = {
        points: points,
        stroke: "#B0E0E6",
        id: lineId,
        fill: "#B0E0E6",
        strokeEnabled: true,
        listening: true,
        draggable: false,
        sNodeId: this.wf.startNode.id,
        eNodeId: eNodeId,
        strokeWidth: 5,
        type: "line",

        config: {
          nodeCode: lineCodeNum,
          desc: "",
          conditionFuncStr: ""
        },

        tipId: tooltip.id
      };

      this.wf.toolTips.push(tooltip);

      this.wf.lines.push(line);

      this.wf.AnchorPoints.push(endAnchorNode);
      this.wf.nodeMenuContext.active = false;
    },
    deleteLine(e) {
      this.wf.lines.splice(
        this.wf.lines.findIndex(p => p.id === this.wf.curLine.id),
        1
      );
      this.wf.toolTips.splice(
        this.wf.toolTips.findIndex(p => p.id === this.wf.curLine.tipId),
        1
      );
      var enodeIndex = this.wf.AnchorPoints.findIndex(
        p => p.id === this.wf.curLine.eNodeId
      );
      if (enodeIndex >= 0) {
        this.wf.AnchorPoints.splice(enodeIndex, 1);
      }

      var snodeIndex = this.wf.AnchorPoints.findIndex(
        p => p.id === this.wf.curLine.sNodeId
      );
      if (snodeIndex >= 0) {
        this.wf.AnchorPoints.splice(snodeIndex, 1);
      }
    },
    contentContextmenu(e) {
      e.evt.preventDefault();
    },
    handleStageMouseEnter(e) {},
    handleStageContextMenu(e) {
      e.currentTarget.preventDefault(false);
    },
    handleStageMouseMove(e) {
      if (this.wf.selectedShapeId !== "") {
        //缩放后锚点是否还在原内
        if (this.wf.curSelectedNode !== null) {
          //获取anchor中的节点
          for (var i = 0; i < this.wf.AnchorPoints.length; i++) {
            if (
              this.wf.AnchorPoints[i].wfNodeId === this.wf.curSelectedNode.id
            ) {
              if (
                !this.judgeCircleContain(
                  {
                    x: this.wf.AnchorPoints[i].x,
                    y: this.wf.AnchorPoints[i].y,
                    radius: this.wf.AnchorPoints[i].radius
                  },
                  {
                    x: this.wf.curSelectedNode.x,
                    y: this.wf.curSelectedNode.y,
                    radius:
                      this.wf.curSelectedNode.radius *
                      this.wf.curSelectedNode.scaleX
                  }
                )
              ) {
                this.wf.AnchorPoints[i].wfNodeId = "";
                this.wf.AnchorPoints[i].fill = "red";
              }
            }
          }
        }
      }
    },
    handleStageMouseDown(e) {
      if (
        e.evt.bubbles === true &&
        e.evt.button === 2 &&
        e.evt.buttons === 2 &&
        e.evt.which === 3
      ) {
        e.evt.cancelBubble = false;

        if (e.target.constructor.name === "Arrow") {
          this.wf.curLine = this.wf.lines.find(p => p.id === e.target.attrs.id);
          this.wf.lineMenuContext.left = e.evt.clientX + "px";
          this.wf.lineMenuContext.top = e.evt.clientY + "px";
          this.wf.lineMenuContext.active = true;
          this.wf.nodeMenuContext.active = false;
          this.wf.stageMenuContext.active = false;
        } else if (e.target.attrs.id === "vstage") {
          this.wf.stageMenuContext.left = e.evt.clientX + "px";
          this.wf.stageMenuContext.top = e.evt.clientY + "px";
          this.wf.stageMenuContext.active = true;
          this.wf.lineMenuContext.active = false;
          this.wf.nodeMenuContext.active = false;
        } else if (e.target.attrs.type === "wfn") {
          this.wf.nodeMenuContext.left = e.evt.clientX + "px";
          this.wf.nodeMenuContext.top = e.evt.clientY + "px";
          this.wf.nodeMenuContext.active = true;
          this.wf.stageMenuContext.active = false;
          this.wf.lineMenuContext.active = false;

          this.wf.startNode = {
            x: e.target.attrs.x,
            y: e.target.attrs.y,
            id: e.target.attrs.id,
            radius: e.target.attrs.radius,
            wfNodeType: e.target.attrs.wfNodeType,
            scaleX: e.target.attrs.scaleX,
            scaleY: e.target.attrs.scaleY,
            fill: e.target.attrs.fill,
            draggable: e.target.attrs.draggable,
            name: e.target.attrs.name,
            type: e.target.attrs.type
          };
        }
        this.wf.MousePoint.x = e.evt.clientX;
        this.wf.MousePoint.y = e.evt.clientY;
      } else {
        this.wf.stageMenuContext.active = false;
        this.wf.nodeMenuContext.active = false;
        this.wf.lineMenuContext.active = false;
      }
      // clicked on stage - cler selection
      if (e.target === e.currentTarget) {
        this.wf.selectedShapeId = "";
        this.updateTransformer();
        return;
      }

      // clicked on transformer - do nothing
      const clickedOnTransformer =
        e.target.getParent().className === "Transformer";
      if (clickedOnTransformer) {
        return;
      }

      const circle = this.wf.WFNodes.find(r => r.id === e.target.attrs.id);
      if (circle) {
        this.wf.selectedShapeId = e.target.attrs.id;
      } else {
        this.wf.selectedShapeId = "";
      }
      this.updateTransformer();
    },
    updateTransformer() {
      // here we need to manually attach or detach Transformer node
      const transformerNode = this.$refs.transformer.getStage();
      const stage = transformerNode.getStage();
      stage.preventDefault(true);
      const { selectedShapeId } = this.wf;

      if (
        selectedShapeId === "" ||
        selectedShapeId === null ||
        selectedShapeId === undefined
      ) {
        transformerNode.detach();

        this.curSelectedNode = null;

        return;
      }

      const selectedNode = stage.findOne("#" + selectedShapeId);
      this.wf.curSelectedNode = {
        x: selectedNode.attrs.x,
        y: selectedNode.attrs.y,
        id: selectedNode.attrs.id,
        scaleX: selectedNode.attrs.scaleX,
        scaleY: selectedNode.attrs.scaleY,
        radius: selectedNode.attrs.attrs,
        fill: selectedNode.attrs.fill,
        draggable: selectedNode.attrs.draggable,
        id: selectedNode.attrs.id,
        name: selectedNode.attrs.name,
        type: selectedNode.attrs.type,
        wfNodeType: selectedNode.attrs.wfNodeType
      };
      // do nothing if selected node is already attached
      if (selectedNode === transformerNode.node()) {
        return;
      }

      if (selectedNode) {
        // attach to another node
        transformerNode.attachTo(selectedNode);
      } else {
        // remove transformer
        transformerNode.detach();
      }
      transformerNode.getLayer().batchDraw();
    },
    lineSelected(e) {
      console.log(e);
      var tip = this.wf.toolTips.find(p => p.id === e.target.attrs.tipId);
      tip.visible = !tip.visible;
      tip.text.text =
        e.target.attrs.config.nodeCode + ": " + e.target.attrs.config.desc;
    },
    anchorDragMove(e) {
      e.currentTarget.moveToTop();
      this.updateArrow(e.target.attrs);
    },
    anchorDragEnd(e) {
      e.currentTarget.moveToTop();
      this.updateArrow(e.target.attrs);
    },
    anchorMouseUp(e) {
      var that = this;
      if (
        this.wf.lines.some(
          p =>
            p.sNodeId === e.target.attrs.pairId &&
            p.eNodeId === e.target.attrs.wfNodeId
        )
      ) {
        return;
      }

      if (e.target.attrs.wfNodeId !== "" && e.target.attrs.fill == "green") {
        this.wf.lines.forEach(ele => {
          if (ele.eNodeId === e.target.attrs.id) {
            var sNode = that.wf.WFNodes.find(p => p.id === ele.sNodeId);
            if (sNode === undefined) {
              sNode = this.wf.AnchorPoints.find(p => p.id === ele.sNodeId);
            }
            ele.eNodeId = e.target.attrs.wfNodeId;
            var eNode = this.wf.WFNodes.find(p => p.id === ele.eNodeId);
            ele.points = that.getConnectorPoints(sNode, eNode);
          } else if (ele.sNodeId === e.target.attrs.id) {
            var eNode = this.wf.WFNodes.find(p => p.id === ele.eNodeId);
            if (eNode === undefined) {
              eNode = this.wf.AnchorPoints.find(p => p.id === ele.eNodeId);
            }
            ele.sNodeId = e.target.attrs.wfNodeId;
            var sNode = that.wf.WFNodes.find(p => p.id === ele.sNodeId);
            ele.points = that.getConnectorPoints(sNode, eNode);
          }
        });
        this.wf.AnchorPoints.splice(
          this.wf.AnchorPoints.findIndex(p => p.id === e.target.attrs.id),
          1
        );
        return;
      }
    },
    updateArrow(config) {
      //更新vue data 中的数据
      var that = this;

      this.wf.lines.forEach(ele => {
        if (ele.eNodeId === config.id) {
          var sNode = that.wf.WFNodes.find(p => p.id === ele.sNodeId);
          if (sNode !== undefined) {
            ele.points = that.getConnectorPoints(sNode, config);
          }
        }
        if (ele.sNodeId === config.id) {
          var eNode = that.wf.WFNodes.find(p => p.id === ele.eNodeId);
          if (eNode !== undefined) {
            ele.points = that.getConnectorPoints(config, eNode);
          }
        }

        var sNode = this.wf.AnchorPoints.find(p => p.id === ele.sNodeId);
        var eNode = this.wf.AnchorPoints.find(p => p.id === ele.eNodeId);
        if (sNode !== undefined) {
          if (sNode.pairId === config.id || sNode.id === config.pairId) {
            ele.points = that.getConnectorPoints(sNode, config);
            //校正关系
            if (sNode.pairId === config.id) {
              config.pairId = sNode.id;
            }
            if (sNode.id === config.pairId) {
              sNode.pairId = config.id;
            }
          }
        }
        if (eNode !== undefined) {
          if (eNode.pairId === config.id || eNode.id === config.pairId) {
            ele.points = that.getConnectorPoints(config, eNode);
            //校正关系
            if (eNode.pairId === config.id) {
              config.pairId = eNode.id;
            }
            if (eNode.id === config.pairId) {
              eNode.pairId = config.id;
            }
          }
        }

        var tipLine = this.wf.toolTips.find(p => p.id === ele.tipId);
        if (tipLine !== undefined) {
          tipLine.x = (ele.points[0] + ele.points[2]) / 2;
          tipLine.y = (ele.points[1] + ele.points[3]) / 2;
        }
      });

      var count = 0;
      var wfNodeId = "";
      var curNode = this.wf.AnchorPoints.find(p => p.id === config.id);
      curNode.x = config.x;
      curNode.y = config.y;

      curNode.radius = config.radius;
      for (var m = 0; m < this.wf.WFNodes.length; m++) {
        var curWFNode = this.$refs.layer
          .getNode()
          .findOne("#" + this.wf.WFNodes[m].id);
        if (
          this.judgeCircleContain(
            {
              x: config.x,
              y: config.y,
              radius: config.radius
            },
            {
              x: curWFNode.attrs.x,
              y: curWFNode.attrs.y,
              radius: curWFNode.attrs.radius * curWFNode.attrs.scaleX
            }
          )
        ) {
          count++;
          wfNodeId = this.wf.WFNodes[m].id;
        }
      }

      if (count == 1) {
        if (curNode.pairId !== wfNodeId) {
          if (
            this.wf.lines.some(
              p => p.sNodeId === config.pairId && p.eNodeId === wfNodeId
            )
          ) {
            return;
          }
          curNode.wfNodeId = wfNodeId;
          curNode.fill = "green";
        }
      } else {
        curNode.wfNodeId = "";
        curNode.fill = "red";
      }
    },

    nodeMouseDown(e) {
      e.currentTarget.moveToBottom();
      if (e.evt.button === 2) {
        this.wf.curSelectedNode = this.wf.WFNodes.find(
          p => p.id === e.target.attrs.id
        );
      }
    },
    nodeMouseOver(e) {
      this.wf.toolTips.find(p => p.id === e.target.attrs.tipId).visible = true;
    },
    nodeMouseLeave(e) {
      this.wf.toolTips.find(p => p.id === e.target.attrs.tipId).visible = false;
    },
    nodeDragMove(e) {
      this.updateWFNodeData(e);
    },
    nodeDragEnd(e) {
      this.updateWFNodeData(e);
    },

    updateWFNodeData(e) {
      //更新vue data 中的数据
      var curNode = this.wf.WFNodes.find(p => p.id === e.target.attrs.id);
      var tipNode = this.wf.toolTips.find(p => p.id === e.target.attrs.tipId);

      if (tipNode !== undefined) {
        if (e.target.attrs.type === "wfn") {
          tipNode.x = tipNode.x + (e.target.attrs.x - curNode.x);
          tipNode.y = tipNode.y + (e.target.attrs.y - curNode.y);
        }
      } else {
        console.log("没有tips");
      }

      var nodeInfo = this.wf.nodeInfos.find(
        p => p.nodeId === e.target.attrs.id
      );
      if (nodeInfo !== undefined) {
        nodeInfo.x = nodeInfo.x + (e.target.attrs.x - curNode.x);
        nodeInfo.y = nodeInfo.y + (e.target.attrs.y - curNode.y);
      }
      curNode.x = e.target.attrs.x;
      curNode.y = e.target.attrs.y;
      curNode.scaleX = e.target.attrs.scaleX;
      curNode.scaleY = e.target.attrs.scaleY;

      //更新相关锚点的位置信息
      for (var i = 0; i < this.wf.AnchorPoints.length; i++) {
        if (this.wf.AnchorPoints[i].wfNodeId === e.currentTarget.attrs.id) {
          this.wf.AnchorPoints[i].x =
            this.wf.AnchorPoints[i].x + e.evt.movementX;
          this.wf.AnchorPoints[i].y =
            this.wf.AnchorPoints[i].y + e.evt.movementY;

          this.updateArrow(this.wf.AnchorPoints[i]);
        }
      }

      this.wf.lines.forEach(ele => {
        var sNode = this.wf.WFNodes.find(p => p.id === ele.sNodeId);
        var eNode = this.wf.WFNodes.find(p => p.id === ele.eNodeId);
        if (eNode === undefined) {
          eNode = this.wf.AnchorPoints.find(p => p.id == ele.eNodeId);
        }
        if (sNode === undefined) {
          sNode = this.wf.AnchorPoints.find(p => p.id === ele.sNodeId);
        }

        if (sNode !== undefined && eNode !== undefined) {
          ele.points = this.getConnectorPoints(sNode, eNode);
        } else {
        }

        var tipLine = this.wf.toolTips.find(p => p.id === ele.tipId);
        if (tipLine !== undefined) {
          tipLine.x = (ele.points[0] + ele.points[2]) / 2;
          tipLine.y = (ele.points[1] + ele.points[3]) / 2;
        }
      });
    },
    getConnectorPoints(from, to) {
      //计算箭头线起始点位

      const dx = to.x - from.x;
      const dy = to.y - from.y;
      let angle = Math.atan2(-dy, dx);

      const radius = (from.radius + 10) * from.scaleX;
      const toradius = (to.radius + 10) * to.scaleX;

      return [
        from.x + -radius * Math.cos(angle + Math.PI),
        from.y + radius * Math.sin(angle + Math.PI),
        to.x + -toradius * Math.cos(angle),
        to.y + toradius * Math.sin(angle)
      ];
    },
    judgeCircleContain(cirle1, circle2) {
      var distance = Math.sqrt(
        Math.pow(cirle1.x - circle2.x, 2) + Math.pow(cirle1.y - circle2.y, 2)
      );

      var rDis = cirle1.radius + circle2.radius;
      if (distance < rDis) {
        return true;
      }
      return false;
    },
    updateObjects() {
      var that = this;
      this.wf.targets.forEach(target => {
        var node = that.$refs.layer.getNode().findOne("#" + target.id);
        if (!!node) {
          node.x(target.x);
          node.y(target.y);
        }
      });
      this.wf.connectors.forEach(connect => {
        var line = that.$refs.layer.getNode().findOne("#" + connect.id);
        var fromNode = that.$refs.layer.getNode().findOne("#" + connect.from);
        var toNode = that.$refs.layer.getNode().findOne("#" + connect.to);

        if (!!fromNode && !!toNode) {
          const points = that.getConnectorPoints(
            fromNode.position(),
            toNode.position()
          );
          line.points(points);
        }
      });
      this.$refs.layer.getNode().batchDraw();
    }
  },
  created() {
    this.wf.WFNodes = this.workflow.wFNodes;
    this.wf.lines = this.workflow.lines;
    this.wf.toolTips = this.workflow.toolTips;
    this.wf.id = this.workflow.id;
    this.wf.name = this.workflow.name;
    this.wf.desc = this.workflow.desc;
    this.wf.createUserId = this.workflow.createUserId;
    this.wf.createUserName = this.workflow.createUserName;
    this.wf.updateUserId = this.workflow.updateUserId;
    this.wf.updateUserName = this.workflow.updateUserName;
    this.wf.createTime = this.workflow.createTime;
    this.wf.updateTime = this.workflow.updateTime;
    this.wf.version = this.workflow.version;
    this.wf.nodeInfos = this.workflow.nodeInfos;
  },
  beforeMount() {
    // console.log("aaa");
  },
  mounted() {
    var that = this;
    this.wf.AnchorPoints.forEach(ele => {
      that.updateArrow(ele);
    });
  }
};
</script>

<style lang="css">
@import url("../components/AceEditor/style.css");
.box-card {
  width: 180px;
  position: absolute;
  opacity: 0.8;
  background: #fff;
}
.el-card__body {
  padding: 5px;
}
.ace-editor-wrap {
  width: 100%;
  height: 100%;
}
</style>