<template>
  <div>
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/visi-design' }">可视化设计</el-breadcrumb-item>
      <el-breadcrumb-item>实验设置</el-breadcrumb-item>
    </el-breadcrumb>
    <el-divider class="divi"></el-divider>
    <el-container>
      <el-aside>
        <el-tree
          :data="treeData"
          :default-checked-keys="[]"
          :default-expanded-keys="['0-0']"
          :check-strictly="true"
          @check="handleCheck"
          show-checkbox
          node-key="key"
          ref="tree"
        >
          <span slot-scope="{ node, data }">
            <span v-if="data.children">
              <i class="el-icon-folder"></i>
            </span>
            <span v-else>
              <i class="el-icon-document"></i>
            </span>
            {{ node.label }}
          </span>
        </el-tree>
      </el-aside>
      <el-main class="app-content">
        <div class="main">
          <div class="header">
            <el-tooltip content="提交" placement="bottom-end" effect="dark">
              <i
                @click="onRun"
                style="
                          height: 50px;
                          width: 50px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="iconfont icon-yunXang"
              ></i>
            </el-tooltip>
            <el-tooltip content="保存" placement="bottom-end" effect="dark">
              <i
                @click="onPrimary"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="el-icon-document-checked"
              ></i>
            </el-tooltip>
            <el-tooltip content="取消" effect="dark">
              <i
                @click="onCancel"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="el-icon-error"
              ></i>
            </el-tooltip>
            <el-tooltip content="Undo" effect="dark">
              <i
                @click="onUndo"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="el-icon-arrow-left"
              ></i>
            </el-tooltip>
            <el-tooltip content="Redo" effect="dark">
              <i
                @click="onRedo"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="el-icon-arrow-right"
              ></i>
            </el-tooltip>
            <el-tooltip content="示例" effect="dark">
              <i
                @click="onGetExample"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="el-icon-notebook-2"
              ></i>
            </el-tooltip>
            <el-tooltip content="清空" effect="dark">
              <i
                @click="onCleargraph"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="el-icon-delete"
              ></i>
            </el-tooltip>
            <el-tooltip content="获取代码模板" effect="dark">
              <i
                @click="getParaTemp"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="el-icon-tickets"
              ></i>
            </el-tooltip>
            <el-tooltip content="日志" effect="dark">
              <i
                @click="getworkflowContent"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="el-icon-document"
              ></i>
            </el-tooltip>
            <el-tooltip content="节点居中" effect="dark">
              <i
                @click="getgraphContentcenter"
                style="
                          height: 25px;
                          width: 25px;
                          margin: 10px 5px 10px 10px;
                          font-size: 23px;
                        "
                class="iconfont icon-tishi"
              ></i>
            </el-tooltip>
            <el-tag :key="workflowstatustag.name" :type="workflowstatustag.type">
              {{ workflowstatustag.name }}
            </el-tag>
          </div>
          <div class="container" id="container"></div>
        </div>
        <!-- 右边部分 -->
        <div class="right">
          <design-experconfig v-show="isShow.designExperconfig" :data.sync="experimentName"></design-experconfig>
          <design-node-config
            v-show="isShow.designNodeConfig"
            :isShow="isShow.designNodeConfig"
            ref="designNodeConfig"
          ></design-node-config>
          <design-connode-config v-show="isShow.conNodeConfigVisi" ref="newConNodeConfig"></design-connode-config>
          <design-csvselect-config
            v-show="isShow.csvselectNodeConVisible"
            ref="csvselectNodeConfig"
          ></design-csvselect-config>
        </div>
      </el-main>
    </el-container>
    <design-para-temp ref="paraTemp"></design-para-temp>
    <design-workflowlog ref="getworkflowlog"></design-workflowlog>
    <design-inputnode-config ref="inputNodeConfig"></design-inputnode-config>
    <design-outputnode-config ref="outputNodeConfig"></design-outputnode-config>
  </div>
</template>

<script>
import { Graph, Shape } from "@antv/x6";
import { Message, MessageBox } from "element-ui";
import DesignExperconfig from "./design-experconfig.vue";
import DesignNodeConfig from "./design-node-config.vue";
import exampleCode from "./exampleCode";
import DesignParaTemp from "./design-para-temp.vue";
import DesignWorkflowlog from "./design-workflowlog.vue";
import DesignInputnodeConfig from "./design-inputnode-config.vue";
import DesignOutputnodeConfig from "./design-outputnode-config.vue";
import DesignConnodeConfig from "./design-connode-config.vue";
import DesignCsvselectConfig from "./design-csvselect-config.vue";
export default {
  name: "design-graph",
  components: {
    DesignExperconfig,
    DesignNodeConfig,
    DesignParaTemp,
    DesignWorkflowlog,
    DesignInputnodeConfig,
    DesignOutputnodeConfig,
    DesignConnodeConfig,
    DesignCsvselectConfig
  },
  beforeRouteLeave(to, from, next) {
    // 清除定时任务
    if (this.interval) {
      window.clearInterval(this.interval);
    }
    // 清空画布
    if (this.graph) {
      this.graph.dispose();
    }
    next();
  },
  data() {
    return {
      // 树形组件
      treeData: [],
      workflowstatustag: {
        name: "未提交",
        type: "info"
      },
      graph: undefined,
      history: undefined,
      // 节点数据
      nodedata: [],
      // 组件是否展示
      isShow: {
        designExperconfig: true,
        designNodeConfig: false,
        conNodeConfigVisi: false,
        csvselectNodeConVisible: false
      },
      // 实验名称
      experimentName: undefined,
      // true表示update,新增  false表示add
      addorupdate: true,
      // 当前工作流id
      workflowId: null,
      // 当前画布工作流名称
      workflowName: "",
      // 提交后的状态
      workflowStatus: "uncommitted",
      // 是否保存
      isSave: false,
      // id与templatename
      idTemplateNameMap: null,
      // 定时任务
      interval: null,
      // 工作流模板名称
      workflowtempName: ""
    };
  },
  activated() {
    // 清空数据
    this.initData();
    // 创建图
    this.createGraph();
    // 注册tools
    this.addGraphEvent();
    // 初始化node节点
    this.createNode();
    // 初始化数据
    this.getAlgorithmDataList();
    // 清除画布数据
    this.onCleargraph();
    // 初始化画布信息
    if (this.$route.query.update === true) {
      const graphInfo = this.$route.query.winfo;
      this.experimentName = graphInfo.experimentName;
      this.workflowName = graphInfo.workflowName;
      this.workflowId = graphInfo.workflowId;
      this.workflowtempName = graphInfo.workflowtempName;
      this.graph.fromJSON(JSON.parse(graphInfo.graphJson).cells);
    }
  },
  mounted() {
    // 注册第三方节点和边
    this.register();
  },
  methods: {
    /**
     * 钩子函数，处理tree的回调
     *
     * @param data 该节点所对应的对象
     * @param checkedKeys 树目前的选中状态对象
     */
    handleCheck(data, { checkedKeys }) {
      if (checkedKeys.length > 1) {
        Message.error("只允许选择一个节点");
        this.$refs.tree.setCheckedKeys([]);
        return;
      }
      if (this.$refs.tree.getCheckedKeys().length === 1) {
        const node = this.nodedata.find(
          (item) => item.attrs.label.text === this.$refs.tree.getCheckedKeys()[0].split("-")[0]
        );
        if (node) {
          const cloneNode = node.clone();
          const randomNum = Math.floor(Math.random() * 1000);
          cloneNode.setData({
            nodeName: cloneNode.getData().nodeName || "" + randomNum
          });
          cloneNode.setData({
            templateName: cloneNode.getData().templateName || "" + randomNum
          });
          const { offsetWidth, offsetHeight } = this.graph.container;
          cloneNode.position(offsetWidth / 2, offsetHeight / 2);
          this.graph.addNode(cloneNode);
          this.$refs.tree.setCheckedKeys([]);
        }
      }
    },
    /**
     * 初始化数据
     */
    initData() {
      this.nodedata = [];
      this.treeData = [];
      this.graph = undefined;
      this.history = undefined;
    },
    /**
     * 创建graph
     */
    createGraph() {
      const { offsetWidth, offsetHeight } = document.getElementById("container");
      const graph = new Graph({
        grid: true,
        container: document.getElementById("container"),
        width: offsetWidth,
        height: offsetHeight,
        panning: {
          enabled: true
        },
        // 调节节点大小
        resizing: {
          enabled: true,
          minWidth: 1,
          maxWidth: 200,
          minHeight: 1,
          maxHeight: 150,
          orthogonal: false,
          restricted: false,
          preserveAspectRatio: false
        },
        history: true,
        highlighting: {
          // nodeAvailable: {
          //   // 连线过程中，节点可以被链接时被使用。
          //   name: "stroke",
          //   args: {
          //     attrs: {
          //       fill: "#5F95FF",
          //       stroke: "#5F95FF"
          //     }
          //   }
          // },
          magnetAvailable: {
            // 连线过程中，链接桩可以被链接时被使用。
            name: "stroke",
            args: {
              attrs: {
                fill: "#fff",
                stroke: "#31d0c6"
              }
            }
          },
          magnetAdsorbed: {
            // 连线过程中，自动吸附到链接桩时被使用。
            name: "stroke",
            args: {
              attrs: {
                fill: "#5F95FF",
                stroke: "#5F95FF"
              }
            }
          }
        },
        scroller: {
          enabled: true,
          pannable: true,
          minVisibleHeight: offsetHeight,
          minVisibleWidth: offsetWidth,
          pageBreak: true,
          pageVisible: true,
          autoResize: true
        },
        mousewheel: {
          enabled: true,
          modifiers: ["ctrl", "meta"]
        },
        clipboard: {
          enabled: true,
          useLocalStorage: true
        },
        keyboard: {
          enabled: true,
          global: true
        },
        selecting: {
          enabled: true,
          showNodeSelectionBox: true
        },
        // 节点与边交互
        translating: {
          // 限制节点不能移动超出画布区域
          // restrict: true
        },
        connecting: {
          // 连线距离节点或者连接桩 50px 时会触发自动吸附
          snap: true,
          allowBlank: false,
          allowLoop: false,
          highlight: true,
          sourceAnchor: {
            //指定源节点的锚点
            name: "bottom"
          },
          targetAnchor: {
            //指定目标节点的锚点
            name: "center"
          },
          connectionPoint: "anchor",
          createEdge() {
            return graph.createEdge({
              // 更新连接边edge样式
              router: {
                name: "er",
                args: {
                  offset: "center"
                }
              },
              attrs: {
                line: {
                  stroke: "#808080",
                  strokeWidth: 1,
                  targetMarker: {
                    name: "block",
                    args: {
                      size: "6"
                    }
                  }
                }
              }
            });
          },
          validateMagnet({ magnet }) {
            return magnet.getAttribute("port-group") !== "in";
          },
          validateConnection({ sourceView, targetView, sourceMagnet, targetMagnet }) {
            // 只能从输出链接桩创建连接
            if (!sourceMagnet || sourceMagnet.getAttribute("port-group").includes("in")) {
              return false;
            }

            // 只能连接到输入链接桩
            if (!targetMagnet || !targetMagnet.getAttribute("port-group").includes("in")) {
              return false;
            }

            // 判断目标链接桩是否可连接
            const portId = targetMagnet.getAttribute("port");
            const node = targetView.cell;
            const port = node.getPort(portId);
            if (port && port.connected) {
              return false;
            }
            return true;
          }
        }
      });
      this.graph = graph;
      this.history = graph.history;
    },
    /**
     * 初始化节点
     */
    createNode() {
      const conditionnode = new Shape.Polygon({
        width: 90,
        height: 90,
        attrs: {
          text: { text: "条件节点", fill: "condition" },
          body: {
            stroke: "#b6e3e7",
            refPoints: "0,10 10,0 20,10 10,20"
          },
          label: {
            text: "条件节点",
            fontSize: 8,
            fill: "#333",
            fontWeight: 800
          }
        },
        data: {
          truetargetid: "",
          falsetargetid: "",
          inputcondition: "true",
          sourcedatalist: [],
          sourceartilist: []
        },
        ports: {
          groups: {
            in: {
              position: "top",
              attrs: {
                circle: {
                  r: 2,
                  magnet: true,
                  stroke: "#5F95FF",
                  strokeWidth: 2,
                  fill: "#fff"
                }
              }
            },
            out: {
              position: "right",
              label: {
                position: "top"
              },
              attrs: {
                circle: {
                  r: 2,
                  magnet: true,
                  stroke: "#5F95FF",
                  strokeWidth: 2,
                  fill: "#fff"
                }
              }
            },
            out1: {
              position: "bottom",
              label: {
                position: "right"
              },
              attrs: {
                circle: {
                  r: 2,
                  magnet: true,
                  stroke: "#5F95FF",
                  strokeWidth: 2,
                  fill: "#fff"
                }
              }
            },
            in1: {
              position: "left",
              attrs: {
                circle: {
                  r: 2,
                  magnet: true,
                  stroke: "#5F95FF",
                  strokeWidth: 2,
                  fill: "#fff"
                }
              }
            }
          },
          items: [
            {
              id: "top",
              group: "in"
            },
            {
              id: "righttrue",
              group: "out",
              attrs: {
                text: { text: "是" }
              }
            },
            {
              id: "bottomfalse",
              group: "out1",
              attrs: {
                text: { text: "否" }
              }
            },
            {
              id: "left",
              group: "in1"
            }
          ]
        }
      });
      const consume_artifact = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "consume_artifact"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/circle.svg")
          }
        },
        data: {
          nodeName: "zhang_consume_artifac",
          templateName: "print-message",
          templateImage: "alpine:latest",
          templateCommand: {
            1: "sh",
            2: "-c"
          },
          templateArgs: {
            1: "cat /tmp/message"
          },
          inputsparameters: [],
          inputsartifacts: [
            {
              name: "message",
              path: "/tmp/message"
            }
          ],
          argumentsparameters: [],
          argumentsartifacts: [
            {
              name: "message",
              valuefrom: "{{tasks.whalesay.outputs.artifacts.hello-art}}"
            }
          ],
          outputsparameters: [],
          outputsartifacts: [],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const generate_artifact = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "generate_artifact"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/circle.svg")
          }
        },
        data: {
          nodeName: "zhang_generate_artifact",
          templateName: "whalesay",
          templateImage: "docker/whalesay:latest",
          templateCommand: {
            1: "sh",
            2: "-c"
          },
          templateArgs: {
            1: "sleep 1; cowsay hello world | tee /tmp/hello_world.txt"
          },
          inputsparameters: [],
          inputsartifacts: [],
          argumentsparameters: [],
          argumentsartifacts: [],
          outputsparameters: [],
          outputsartifacts: [
            {
              name: "hello-art",
              path: "/tmp/hello_world.txt"
            }
          ],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const zdocker_test = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "zdockertest"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/circle.svg")
          }
        },
        data: {
          nodeName: "zdockertest",
          templateName: "print-message",
          templateImage: "zvinjodocker/zdockertest1:20211011",
          templateCommand: {},
          templateArgs: {},
          inputsparameters: [],
          inputsartifacts: [],
          argumentsparameters: [],
          argumentsartifacts: [],
          outputsparameters: [],
          outputsartifacts: [],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的   文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const contourTask1 = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "contourTask1"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/circle.svg")
          }
        },
        data: {
          nodeName: "contourTask1",
          templateName: "contourTask1",
          templateImage: "zvinjodocker/contous_task1:20211014",
          templateCommand: {},
          templateArgs: {},
          inputsparameters: [],
          inputsartifacts: [],
          argumentsparameters: [],
          argumentsartifacts: [],
          outputsparameters: [],
          outputsartifacts: [
            {
              paraname: "thresh",
              paradesc: "",
              paratype: "",
              valuefrom: "/myapps/thresh1.png"
            },
            {
              paraname: "contours",
              paradesc: "",
              paratype: "",
              valuefrom: "/myapps/contours.png"
            }
          ],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const contourTask2 = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "contourTask2"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/circle.svg")
          }
        },
        data: {
          nodeName: "contourTask2",
          templateName: "contourTask2",
          templateImage: "zvinjodocker/contours_task2:20211014",
          templateCommand: {},
          templateArgs: {},
          inputsparameters: [],
          inputsartifacts: [
            {
              paraname: "thresh",
              parapath: "/myapps/thresh1.png",
              paradesc: ""
            },
            {
              paraname: "contours",
              parapath: "/myapps/contours.png",
              paradesc: ""
            }
          ],
          argumentsparameters: [],
          argumentsartifacts: [
            {
              paraname: "thresh",
              valuefrom: "{{tasks.contourTask1.outputs.artifacts.thresh}}",
              fileurls: []
            },
            {
              paraname: "contours",
              valuefrom: "{{tasks.contourTask1.outputs.artifacts.contours}}",
              fileurls: []
            }
          ],
          outputsparameters: [],
          outputsartifacts: [
            {
              paraname: "contours0",
              valuefrom: "/myapps/contours[0].npy",
              paradesc: "",
              paratype: ""
            },
            {
              paraname: "res",
              valuefrom: "/myapps/res1.png",
              paradesc: "",
              paratype: ""
            }
          ],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const contourTask3 = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "contourTask3"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/circle.svg")
          }
        },
        data: {
          nodeName: "contourTask3",
          templateName: "contourTask3",
          templateImage: "zvinjodocker/contours_task3:20211015",
          templateCommand: {},
          templateArgs: {},
          inputsparameters: [],
          inputsartifacts: [
            {
              paraname: "contours0",
              parapath: "/myapps/contours[0].npy",
              paradesc: ""
            }
          ],
          argumentsparameters: [],
          argumentsartifacts: [
            {
              paraname: "contours0",
              valuefrom: "{{tasks.contourTask2.outputs.artifacts.contours0}}",
              fileurls: []
            }
          ],
          outputsparameters: [],
          outputsartifacts: [],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const contourApproximate1 = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "contourApproximate1"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/cloud.svg")
          }
        },
        data: {
          nodeName: "contourApproximate1",
          templateName: "contourApproximate1",
          templateImage: "zvinjodocker/contour_approximate1:20211015",
          templateCommand: {},
          templateArgs: {},
          inputsparameters: [],
          inputsartifacts: [],
          argumentsparameters: [],
          argumentsartifacts: [],
          outputsparameters: [],
          outputsartifacts: [
            {
              paraname: "approxCnt",
              valuefrom: "/myapps/approx_cnt.npy",
              paradesc: "",
              paratype: ""
            },
            {
              paraname: "approxRes",
              valuefrom: "/myapps/approx_res.png",
              paradesc: "",
              paratype: ""
            }
          ],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const contourApproximate2 = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "contourApproximate2"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/cloud.svg")
          }
        },
        data: {
          nodeName: "contourApproximate2",
          templateName: "contourApproximate2",
          templateImage: "zvinjodocker/contour_approximate2:20211015",
          templateCommand: {},
          templateArgs: {},
          inputsparameters: [],
          inputsartifacts: [
            {
              paraname: "approxCnt",
              parapath: "/myapps/approx_cnt.npy",
              paradesc: ""
            }
          ],
          argumentsparameters: [],
          argumentsartifacts: [
            {
              paraname: "approxCnt",
              valuefrom: "{{tasks.contourApproximate1.outputs.artifacts.approxCnt}}",
              fileurls: []
            }
          ],
          outputsparameters: [],
          outputsartifacts: [
            {
              paraname: "approxRes2",
              valuefrom: "/myapps/approx_res2.png",
              paradesc: "",
              paratype: ""
            }
          ],
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const contourRect1 = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "contourRect1"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/computer.svg")
          }
        },
        data: {
          nodeName: "contourRect1",
          templateName: "contourRect1",
          templateImage: "zvinjodocker/contours_rect1:20211015",
          templateCommand: {},
          templateArgs: {},
          inputsparameters: [],
          inputsartifacts: [],
          argumentsparameters: [],
          argumentsartifacts: [],
          outputsparameters: [],
          outputsartifacts: [
            {
              paraname: "cnt",
              valuefrom: "/myapps/contour_rect_cnt.npy",
              paradesc: "",
              paratype: ""
            },
            {
              paraname: "contourRect",
              valuefrom: "/myapps/contour_rect.png",
              paradesc: "",
              paratype: ""
            }
          ],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const contourCircle2 = this.graph.createNode({
        shape: "template-node",
        attrs: {
          label: {
            text: "contourCircle2"
          },
          body: {
            fill: "#d3ebf3"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/computer.svg")
          }
        },
        data: {
          nodeName: "contourCircle2",
          templateName: "contourCircle2",
          templateImage: "zvinjodocker/contours_circle2:20211015",
          templateCommand: {},
          templateArgs: {},
          inputsparameters: [],
          inputsartifacts: [
            {
              paraname: "contourRect",
              parapath: "/myapps/contour_rect.png",
              paradesc: ""
            },
            {
              paraname: "cnt",
              parapath: "/myapps/contour_rect_cnt.npy",
              paradesc: ""
            }
          ],
          argumentsparameters: [],
          argumentsartifacts: [
            {
              paraname: "contourRect",
              valuefrom: "{{tasks.contourRect1.outputs.artifacts.contourRect}}",
              fileurls: []
            },
            {
              paraname: "cnt",
              valuefrom: "{{tasks.contourRect1.outputs.artifacts.cnt}}",
              fileurls: []
            }
          ],
          outputsparameters: [],
          outputsartifacts: [
            {
              paraname: "contourCircle",
              valuefrom: "contour_circle.png",
              paradesc: "",
              paratype: ""
            }
          ],
          // 获取到的连接线源的数据连接线的源的输出数据
          sourcedatalist: [],
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
        }
      });
      const dataInputnode = this.graph.createNode({
        shape: "template-input",
        attrs: {
          label: {
            text: "dataInputnode"
          },
          body: {
            fill: "#e2c3a0"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/computer.svg")
          }
        },
        data: {
          nodeName: "dataInputnode",
          templateName: "dataInputnode",
          st_dataListvalue: [], // 静态数据集选中 文件对应value
          dy_dataListvalue: [], // 动态数据集选中  文件对应value
          fileList: [], // 外部上传文件
          allfilemap: null // 选中的文件对应的名称及url
        }
      });
      const dataOutputnode = this.graph.createNode({
        shape: "template-output",
        attrs: {
          label: {
            text: "dataOutputnode"
          },
          body: {
            fill: "#e2c3a0"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/computer.svg")
          }
        },
        data: {
          nodeName: "dataOutputnode",
          templateName: "dataOutputnode",
          sourcealgocell: null // 输出节点的前一个节点的结果
        }
      });
      const CSVConversionnode = this.graph.createNode({
        shape: "template-csvselect",
        attrs: {
          label: {
            text: "CSVConversionnode"
          },
          body: {
            fill: "#e2c3a0"
          },
          image: {
            "xlink:href": require("@/assets/img/visisvg/computer.svg")
          }
        },
        data: {
          nodeName: "CSVConversionnode",
          templateName: "CSVConversionnode",
          inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
          inputnodefilevalue: [], // 用户选择的输入节点的文件，存储文件url,后端调用
          allfilemap: null // 选中的文件对应的名称及url
        }
      });
      this.nodedata.push(conditionnode);
      this.nodedata.push(consume_artifact);
      this.nodedata.push(generate_artifact);
      this.nodedata.push(zdocker_test);
      this.nodedata.push(contourTask1);
      this.nodedata.push(contourTask2);
      this.nodedata.push(contourTask3);
      this.nodedata.push(contourApproximate1);
      this.nodedata.push(contourApproximate2);
      this.nodedata.push(contourRect1);
      this.nodedata.push(contourCircle2);
      this.nodedata.push(dataInputnode);
      this.nodedata.push(dataOutputnode);
      this.nodedata.push(CSVConversionnode);
    },
    /**
     * 注册自定义节点和边
     */
    register() {
      try {
        // 定义节点
        Graph.registerNode("template-node", {
          inherit: "rect",
          width: 90,
          height: 90,
          attrs: {
            body: {
              strokeWidth: 1,
              stroke: "#d3e3ee",
              fill: "#1891ec",
              rx: 8,
              ry: 8
            },
            // 设置内部添加图片
            image: {
              width: 36,
              height: 36,
              refX: 27,
              refY: 27,
              "xlink:href": require("@/assets/img/visisvg/api.svg")
            },
            label: {
              refX: 0.5,
              refY: 0.85,
              fill: "#333",
              fontSize: 11,
              fontVariant: "small-caps"
            }
          },
          ports: {
            groups: {
              // 输入链接桩群组定义
              in: {
                position: "left",
                attrs: {
                  circle: {
                    r: 2.5,
                    magnet: true,
                    stroke: "black",
                    strokeWidth: 1,
                    fill: "#fff"
                  }
                }
              },
              // 输出链接桩群组定义
              out: {
                position: "right",
                attrs: {
                  circle: {
                    r: 2.5,
                    magnet: true,
                    stroke: "black",
                    strokeWidth: 1,
                    fill: "#fff"
                  }
                }
              }
            },
            items: [
              {
                id: "inport1",
                group: "in"
              },
              {
                id: "inport2",
                group: "in"
              },
              {
                id: "outport1",
                group: "out"
              },
              {
                id: "outport2",
                group: "out"
              }
            ]
          },

          markup: [
            {
              tagName: "rect",
              selector: "body",
              attrs: {
                fill: "#fff",
                stroke: "#000",
                strokeWidth: 2
              }
            },
            {
              tagName: "image",
              selector: "image"
            },
            {
              tagName: "text",
              selector: "label",
              attrs: {
                fill: "#333",
                textAnchor: "middle",
                textVerticalAnchor: "middle"
              }
            }
          ],
          data: {
            nodeName: undefined,
            algonodeId: undefined,
            templateName: undefined,
            templateImage: undefined,
            templateCommand: {},
            templateArgs: {},
            // 新增根据输入输出模板获取到的输入输出参数名称，类型，描述等
            algoparaInput: {
              userInput: [],
              getInput: []
            },
            // 包括userInput[]和getInput[]
            algoparaOutput: [],
            // 保存输入
            algoparaInputargu: {
              userInput: [],
              getInput: []
            },
            algonodeSource: [],
            inputsparameters: [],
            inputsartifacts: [],
            argumentsparameters: [],
            argumentsartifacts: [],
            outputsparameters: [],
            outputsartifacts: [],
            sourcedatalist: [], // 获取到的连接线源的数据，连接线的源的输出数据
            sourceartilist: [],
            inputnodefilemap: [], // 引用输入节点的文件列表，包含文件名和url
            inputnodefilevalue: [] // 用户选择的输入节点的文件，存储文件url,后端调用
          }
        });
        // 定义输入节点
        Graph.registerNode("template-input", {
          inherit: "rect",
          width: 90,
          height: 90,
          attrs: {
            body: {
              strokeWidth: 1,
              stroke: "#d3e3ee",
              fill: "#e2c3a0",
              rx: 8,
              ry: 8
            },
            //设置内部添加图片
            image: {
              width: 36,
              height: 36,
              refX: 27,
              refY: 27,
              "xlink:href": require("@/assets/img/visisvg/api.svg")
            },
            label: {
              refX: 0.5,
              refY: 0.85,
              fill: "#333",
              fontSize: 11,
              fontVariant: "small-caps"
            }
          },
          ports: {
            groups: {
              // 输入链接桩群组定义
              in: {
                position: "left",
                attrs: {
                  circle: {
                    r: 2.5,
                    magnet: true,
                    stroke: "black",
                    strokeWidth: 1,
                    fill: "#fff"
                  }
                }
              },
              // 输出链接桩群组定义
              out: {
                position: "right",
                attrs: {
                  circle: {
                    r: 2.5,
                    magnet: true,
                    stroke: "black",
                    strokeWidth: 1,
                    fill: "#fff"
                  }
                }
              }
            },
            items: [
              {
                id: "inport1",
                group: "in"
              },
              {
                id: "inport2",
                group: "in"
              },
              {
                id: "outport1",
                group: "out"
              },
              {
                id: "outport2",
                group: "out"
              }
            ]
          },

          markup: [
            {
              tagName: "rect",
              selector: "body",
              attrs: {
                fill: "#fff",
                stroke: "#000",
                strokeWidth: 2
              }
            },
            {
              tagName: "image",
              selector: "image"
            },
            {
              tagName: "text",
              selector: "label",
              attrs: {
                fill: "#333",
                textAnchor: "middle",
                textVerticalAnchor: "middle"
              }
            }
          ],
          data: {
            nodeName: undefined,
            algonodeId: undefined,
            st_dataListvalue: [], // 静态数据集选中文件对应value
            dy_dataListvalue: [], // 动态数据集选中文件对应value
            fileList: [], // 外部上传的文件
            allfilemap: [] // 选中的文件对应的名称及url
          }
        });
        // 定义输出节点
        Graph.registerNode("template-output", {
          inherit: "rect",
          width: 90,
          height: 90,
          attrs: {
            body: {
              strokeWidth: 1,
              stroke: "#d3e3ee",
              fill: "#e2c3a0",
              rx: 8,
              ry: 8
            },
            // 设置内部添加图片
            image: {
              width: 36,
              height: 36,
              refX: 27,
              refY: 27,
              "xlink:href": require("@/assets/img/visisvg/api.svg")
            },
            label: {
              refX: 0.5,
              refY: 0.85,
              fill: "#333",
              fontSize: 11,
              fontVariant: "small-caps"
            }
          },
          ports: {
            groups: {
              // 输入链接桩群组定义
              in: {
                position: "left",
                attrs: {
                  circle: {
                    r: 2.5,
                    magnet: true,
                    stroke: "black",
                    strokeWidth: 1,
                    fill: "#fff"
                  }
                }
              },
              // 输出链接桩群组定义
              out: {
                position: "right",
                attrs: {
                  circle: {
                    r: 2.5,
                    magnet: true,
                    stroke: "black",
                    strokeWidth: 1,
                    fill: "#fff"
                  }
                }
              }
            },
            items: [
              {
                id: "inport1",
                group: "in"
              },
              {
                id: "inport2",
                group: "in"
              },
              {
                id: "outport1",
                group: "out"
              },
              {
                id: "outport2",
                group: "out"
              }
            ]
          },
          markup: [
            {
              tagName: "rect",
              selector: "body",
              attrs: {
                fill: "#fff",
                stroke: "#000",
                strokeWidth: 2
              }
            },
            {
              tagName: "image",
              selector: "image"
            },
            {
              tagName: "text",
              selector: "label",
              attrs: {
                fill: "#333",
                textAnchor: "middle",
                textVerticalAnchor: "middle"
              }
            }
          ],
          data: {
            nodeName: "",
            algonodeId: null,
            sourcealgocell: null
          }
        });
        // 定义输出节点
        Graph.registerNode("template-csvselect", {
          inherit: "rect",
          width: 90,
          height: 90,
          attrs: {
            body: {
              strokeWidth: 1,
              stroke: "#d3e3ee",
              fill: "#e2c3a0",
              rx: 8,
              ry: 8
            },
            // 设置内部添加图片
            image: {
              width: 36,
              height: 36,
              refX: 27,
              refY: 27,
              "xlink:href": require("@/assets/img/visisvg/api.svg")
            },
            label: {
              refX: 0.5,
              refY: 0.85,
              fill: "#333",
              fontSize: 11,
              fontVariant: "small-caps"
            }
          },
          ports: {
            groups: {
              // 输入链接桩群组定义
              in: {
                position: "left",
                attrs: {
                  circle: {
                    r: 2.5,
                    magnet: true,
                    stroke: "black",
                    strokeWidth: 1,
                    fill: "#fff"
                  }
                }
              },
              // 输出链接桩群组定义
              out: {
                position: "right",
                attrs: {
                  circle: {
                    r: 2.5,
                    magnet: true,
                    stroke: "black",
                    strokeWidth: 1,
                    fill: "#fff"
                  }
                }
              }
            },
            items: [
              {
                id: "inport1",
                group: "in"
              },
              {
                id: "inport2",
                group: "in"
              },
              {
                id: "outport1",
                group: "out"
              },
              {
                id: "outport2",
                group: "out"
              }
            ]
          },
          markup: [
            {
              tagName: "rect",
              selector: "body",
              attrs: {
                fill: "#fff",
                stroke: "#000",
                strokeWidth: 2
              }
            },
            {
              tagName: "image",
              selector: "image"
            },
            {
              tagName: "text",
              selector: "label",
              attrs: {
                fill: "#333",
                textAnchor: "middle",
                textVerticalAnchor: "middle"
              }
            }
          ],
          data: {
            nodeName: undefined,
            algonodeId: undefined,
            st_dataListvalue: [], // 静态数据集选中 文件对应value
            dy_dataListvalue: [], // 动态数据集选中  文件对应value
            fileList: [], // 外部上传  文件
            inputnodefilemap: [], // 引用输入节点的   文件列表，包含文件名和url
            inputnodefilevalue: [], // 用户选择的输入节点的文件，存储文件url,后端调用    ---与算法节点的不同，存储文件名，桶名称，url
            allfilemap: [], // 选中的文件对应的名称及url
            isMakenewfile: false
          }
        });
      } catch (e) {}
    },
    /**
     * 添加graph事件
     */
    addGraphEvent() {
      // 鼠标 Hover 时添加删除按钮
      this.graph.on("node:mouseenter", ({ node }) => {
        if (node.label === "条件节点") {
          node.addTools({
            name: "button-remove",
            args: {
              x: 0,
              y: 0,
              offset: { x: 30, y: 30 }
            }
          });
        } else {
          node.addTools({
            name: "button-remove",
            args: {
              x: 0,
              y: 0,
              offset: { x: 10, y: 10 }
            }
          });
        }
      });

      // 鼠标移开时删除删除按钮
      this.graph.on("node:mouseleave", ({ node }) => {
        node.removeTools();
      });

      // 鼠标点击元素的回调
      this.graph.on("cell:click", ({ cell }) => {
        if (["", undefined, null].includes(this.experimentName)) {
          Message.error("请先输入实验名称");
          for (let key of Object.keys(this.isShow)) {
            this.isShow[key] = false;
          }
          this.isShow["designExperconfig"] = true;
          return;
        }
        if (cell.shape === "polygon") {
          for (let key of Object.keys(this.isShow)) {
            this.isShow[key] = false;
          }
          this.isShow["conNodeConfigVisi"] = true;
          this.$refs.newConNodeConfig.init(cell);
        } else if (cell.shape === "template-node") {
          for (let key of Object.keys(this.isShow)) {
            this.isShow[key] = false;
          }
          this.isShow["designNodeConfig"] = true;
          this.$refs.designNodeConfig.init(cell, this.workflowName, this.workflowStatus, this.idTemplateNameMap);
        } else if (cell.shape === "template-csvselect") {
          for (let key of Object.keys(this.isShow)) {
            this.isShow[key] = false;
          }
          this.isShow["csvselectNodeConVisible"] = true;
          this.$refs.csvselectNodeConfig.init(cell);
        } else if (cell.shape === "template-input") {
          this.$refs.inputNodeConfig.init(cell);
        } else if (cell.shape === "template-output") {
          this.$refs.outputNodeConfig.init(cell, this.workflowName, this.workflowStatus);
        }
      });

      // 点击空白区域
      this.graph.on("blank:click", () => {
        for (let key of Object.keys(this.isShow)) {
          this.isShow[key] = false;
        }
        this.isShow["designExperconfig"] = true;
      });

      // 添加边的事件
      /**
       * @param isNew 是否新建
       * @param edge 边
       * @param currentCell 目标节点
       */
      this.graph.on("edge:connected", ({ isNew, edge, currentCell }) => {
        // 只有新建边才会进行赋值操作
        if (isNew === false) return;
        const source = edge.getSourceCell();
        const target = currentCell;

        // 源节点为 polygon
        if (source.shape === "polygon") {
          if (edge.source.port == "righttrue") {
            source.setData({ truetargetid: target.id });
          } else if (edge.source.port == "bottomfalse") {
            source.setData({ falsetargetid: target.id });
          }
        }

        if (source.shape === "template-node" && target.shape === "template-node") {
          const index = target.getData().algonodeSource.findIndex((item) => item.id === source.id);
          if (index === -1) {
            target.setData({
              algonodeSource: target.getData().algonodeSource.concat(source)
            });
          }
        } else if (source.shape === "template-node" && target.shape === "polygon") {
          const { outputsparameters, outputsartifacts } = source.getData();
          const { nodeName } = source.getData();
          for (const item of outputsparameters) {
            item.from = `{{tasks.${nodeName}.outputs.parameters.${item.paraname}}}`;
          }
          for (const item of outputsartifacts) {
            item.from = `{{tasks.${nodeName}.outputs.partifacts.${item.paraname}}}`;
          }
          target.setData({
            sourcedatalist: target.getData().sourcedatalist.concat(outputsparameters),
            sourceartilist: target.getData().sourceartilist.concat(outputsartifacts)
          });
        } else if (source.shape === "template-input" && target.shape === "template-node") {
          target.setData({
            inputnodefilemap: source.getData().allfilemap || []
          });
        } else if (source.shape === "template-node" && target.shape == "template-output") {
          target.setData({
            sourcealgocell: source
          });
        } else if (source.shape === "template-input" && target.shape === "template-csvselect") {
          target.setData({
            inputnodefilemap: source.getData().allfilemap
          });
        } else if (source.shape === "template-csvselect" && target.shape === "template-node") {
          target.setData({
            inputnodefilemap: source.getData().allfilemap
          });
        }
      });
      // 移动边
      this.graph.on("edge:mouseenter", ({ cell }) => {
        cell.addTools([
          {
            name: "target-arrowhead",
            args: {
              attrs: {
                fill: "red"
              }
            }
          },
          // 在指定的位置处，渲染一个删除按钮，点击时删除对应的边。
          {
            name: "button-remove",
            args: { distance: -100 }
          }
        ]);
      });

      this.graph.on("edge:mouseleave", ({ cell }) => {
        cell.removeTools();
      });
    },
    /*
     * 获取数据列表
     */
    async getAlgorithmDataList() {
      const { data } = await this.$http({
        url: this.$http.adornUrl("/sys/visialgorithmnode/list"),
        method: "get"
      });
      if (data.code != 0) {
        return;
      }
      this.createAlgorithmNode(data.list);
    },
    createAlgorithmNode(list) {
      this.treeData = [
        {
          label: "操作节点",
          key: "0-0",
          disabled: true,
          children: [
            {
              label: "条件节点",
              key: "条件节点"
            },
            {
              label: "输入节点",
              key: "dataInputnode"
            },
            {
              label: "输出节点",
              key: "dataOutputnode"
            },
            {
              label: "CSV文件转换节点",
              key: "CSVConversionnode"
            }
          ]
        },
        {
          label: "轮廓识别",
          key: "0-1",
          disabled: true,
          children: [
            {
              label: "contourTask1",
              key: "contourTask1"
            },
            {
              label: "contourTask2",
              key: "contourTask2"
            },
            {
              label: "contourTask3",
              key: "contourTask3"
            },
            {
              label: "contourApproximate1",
              key: "contourApproximate1"
            },
            {
              label: "contourApproximate2",
              key: "contourApproximate2"
            },
            {
              label: "contourRect1",
              key: "contourRect1"
            },
            {
              label: "contourCircle2",
              key: "contourCircle2"
            }
          ]
        }
      ];
      this.treeData = list.reduce((acc, cur) => {
        let index = acc.findIndex((item) => item.label === cur.algotreetype);
        const randomNum = Math.floor(Math.random() * 1000);
        if (index === -1) {
          acc.push({
            label: cur.algotreetype,
            key: cur.algotreetype,
            disabled: true,
            children: []
          });
          acc[acc.length - 1].children.push({
            label: cur.algonodeName,
            key: cur.algonodeName + "-" + randomNum
          });
        } else {
          acc[index].children.push({
            label: cur.algonodeName,
            key: cur.algonodeName + "-" + randomNum
          });
        }
        // 接下来处理graph
        if (cur.algotreetype != "传统算法" && cur.algotreetype != "智能应用") {
          this.imageurl = require("@/assets/img/visisvg/" + cur.algonodeName + ".svg");
        }
        let newalgonode = this.graph.createNode({
          shape: "template-node",
          attrs: {
            label: {
              text: cur.algonodeName
            },
            body: {
              fill: "#d3ebf3"
            },
            image: {
              "xlink:href": this.imageurl
            }
          },
          data: {
            algonodeId: cur.algonodeId,
            nodeName: cur.algonodeName,
            templateName: cur.algonodeName,
            templateImage: cur.algonodeImage,
            templateCommand: {},
            templateArgs: {},
            algoparaInput: JSON.parse(cur.algoparatempJson).Input,
            algoparaOutput: JSON.parse(cur.algoparatempJson).Output,
            algoparaOutAddress: cur.algoparaoutputAddress,
            algonodeSource: [],
            inputsparameters: JSON.parse(cur.algoparatempJson).Input.ParameterInput,
            inputsartifacts: JSON.parse(cur.algoparatempJson).Input.FileInput,
            argumentsparameters: JSON.parse(cur.algoparatempJson).Input.ParameterInput,
            argumentsartifacts: JSON.parse(cur.algoparatempJson).Input.FileInput,
            outputsparameters: JSON.parse(cur.algoparatempJson).Output.ParameterOutput,
            outputsartifacts: JSON.parse(cur.algoparatempJson).Output.FileOutput,
            sourcedatalist: [],
            inputnodefilemap: [],
            inputnodefilevalue: [],
            wftempname: ""
          }
        });
        this.nodedata.push(newalgonode);
        return acc;
      }, this.treeData);
    },
    /**
     * 运行该流程
     */
    onRun() {
      if (!this.isSave) {
        Message.error("运行之前请先进行保存");
        return;
      }
      MessageBox.confirm(`确定进行[提交]操作?`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        this.$http({
          url: this.$http.adornUrl("/visi/visiworkflow/submit"),
          method: "post",
          data: this.$http.adornData({
            graphJson: JSON.stringify(this.graph.toJSON()),
            workflowId: this.workflowId,
            experimentName: this.experimentName,
            addorupdate: this.addorupdate
          })
        }).then(({ data }) => {
          this.isSave = false;
          if (data && data.code === 0) {
            console.log(data);
            Message.success("提交成功");
            this.workflowName = data.workflowName;
            // 节点id与 DAG中task和Template 的对应关系
            this.idTemplateNameMap = data.idTemplateNameMap;
            // 若为新增，返回新增的主键ID  workflowId
            this.workflowId = data.workflowId;
            // 迭代属性名称:
            for (let nodeid of Object.keys(this.idTemplateNameMap)) {
              let tempName = this.idTemplateNameMap[nodeid];
              // temp后端已向末尾添加随机数
              this.graph.getCellById(nodeid).setData({ wftempname: tempName });
            }
            this.workflowstatustag.name = "Running";
            this.workflowstatustag.type = "";
            this.interval = window.setInterval(() => {
              this.getWorkflowStatus();
            }, 5000);
          } else {
            Message.error("提交失败");
          }
        });
      });
    },
    /**
     * 保存流程图到数据库
     */
    async onPrimary() {
      console.log(this.workflowId);
      if (["", null, undefined].includes(this.experimentName)) {
        Message.error("实验名称不能为空");
        return;
      }
      try {
        await MessageBox.confirm(`确定进行[保存]操作?`, "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        });
        const { data } = await this.$http({
          url: this.$http.adornUrl("/visi/visiworkflow/save"),
          method: "post",
          data: this.$http.adornData({
            userId: this.$store.state.user.id,
            workflowId: this.workflowId,
            experimentName: this.experimentName,
            workflowtempName: this.workflowtempName,
            workflowName: this.workflowName,
            graphJson: JSON.stringify(this.graph.toJSON())
          })
        });
        if (data && data.code === 0) {
          this.isSave = true;
          Message.success("操作成功");
        } else {
          this.isSave = false;
          Message.error(data.msg);
        }
      } catch (e) {}
    },
    /**
     * 查询状态
     */
    async getWorkflowStatus() {
      const { data } = await this.$http({
        url: this.$http.adornUrl("/visi/visiworkflow/getworkflowstatus"),
        method: "get",
        params: this.$http.adornParams({
          workflowName: this.workflowName
        })
      });
      if (data && data.code === 0) {
        this.workflowStatus = data.statusPhase;
        if (this.workflowStatus == "Succeeded") {
          this.workflowstatustag.name = "Succeeded";
          this.workflowstatustag.type = "success";
        } else if (this.workflowStatus == "Error" || this.workflowStatus == "Failed") {
          this.workflowstatustag.name = "Failed";
          this.workflowstatustag.type = "danger";
        } else {
          this.workflowstatustag.name = "Running";
          this.workflowstatustag.type = "";
        }
        // 取消该定时设置
        if (["Failed", "Error", "Succeeded"].includes(this.workflowStatus)) {
          window.clearInterval(this.interval);
        }
      }
    },
    /**
     * 退出操作
     */
    async onCancel() {
      if (!this.isSave && !["", null, undefined].includes(this.experimentName)) {
        MessageBox.confirm(`模板还未保存，是否保存？`, "提示", {
          confirmButtonText: "保存退出",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            // 清除定时任务
            if (this.interval) {
              window.clearInterval(this.interval);
            }
            if (this.workflowstatustag.name == "Running" && this.workflowName != "") {
              this.$http({
                url: this.$http.adornUrl("/visi/visiworkflow/stopworkflow"),
                method: "post",
                data: this.$http.adornData({ workflowName: this.workflowName })
              }).then(({ data }) => {
                this.$router.push({ path: "visi-design" });
              });
            }
          })
          .catch((e) => {
            MessageBox.confirm(`确定进行退出操作?`, "提示", {
              confirmButtonText: "确定",
              cancelButtonText: "取消",
              type: "warning"
            })
              .then(() => {
                this.$router.push({ path: "visi-design" });
              })
              .catch((e) => {});
          });
      } else {
        MessageBox.confirm(`确定进行退出操作?`, "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            this.$router.push({ path: "visi-design" });
          })
          .catch((e) => {});
      }
    },
    /**
     * 撤掉
     */
    onUndo() {
      this.history.undo();
    },
    /**
     * 返回
     */
    onRedo() {
      this.history.redo();
    },
    /**
     * 获取代码示例
     */
    onGetExample() {
      this.onCleargraph();
      this.graph.fromJSON(exampleCode);
    },
    /**
     * 获取代码模板
     */
    getParaTemp() {
      this.$refs.paraTemp.init();
    },
    /**
     * 获取日志
     */
    getworkflowContent() {
      if (["", null, undefined].includes(this.workflowName)) {
        Message.error("请先提交！");
        return;
      }
      this.$refs.getworkflowlog.init(this.workflowName);
    },
    /**
     * 画布居中
     */
    getgraphContentcenter() {
      this.graph.centerContent();
    },
    /**
     * 清空画布
     */
    onCleargraph() {
      this.graph.clearCells();
    }
  }
};
</script>

<style scoped lang="scss">
/deep/ .el-tree > .el-tree-node > .el-tree-node__content .el-checkbox {
  display: none;
}
.divi {
  display: block;
  height: 1px;
  width: 100%;
  margin: 24px 0;
  background-color: #dcdfe6;
  position: relative;
}
.app-content {
  height: 80vh;
  width: 100vw;
  margin: 0 8px;
  box-shadow: 0 0 10px 1px #e9e9e9;
  display: flex;
  .main {
    display: flex;
    flex-direction: column;
    flex: 1;
    .header {
      height: 10%;
    }
    .container {
      flex: 1;
    }
  }
  .right {
    width: 300px;
  }
}
</style>
