
<template>
  <div class="super-flow-demo1">
    <div class="scale_block">
      <div class="scale_control">
        <div class="less">
          <i class="el-icon-minus"></i>
        </div>
        <div class="num">{{ scale_num }}%</div>
        <div class="add">
          <i class="el-icon-plus"></i>
        </div>
      </div>
      <div class="node-container">
        <p class="label_head">节点类型</p>
        <p class="label_explanation">请拖拽添加到流程中</p>
        <div
          class="node-item"
          :class="{'node-item-begin': item.value.meta.type == 0, 'node-item-end': item.value.meta.type == 1, 'node-item-default': item.value.meta.type == 2}"
          v-for="(item, index) in nodeItemList"
          :key="index"
          @mousedown="evt => nodeItemMouseDown(evt, item.value)"
        >
          <span>{{item.label}}</span>
        </div>
      </div>
    </div>
    <div class="flow-container" ref="flowContainer">
      <super-flow
        ref="superFlow"
        :node-list="nodeList"
        :link-list="linkList"
        :link-menu="linkMenu"
        line-color="#c4d8f8"
        onLineColor="#94a8c8"
        :origin="origin"
      >
        <template v-slot:node="{meta}">
          <div
            :class="{'flow-node-begin': nodeParams(meta.id).type == 0, 'flow-node-end': nodeParams(meta.id).type == 1, 'flow-node-default': nodeParams(meta.id).type == 2 && meta.id != nodeItem.id, 'flow-node-default-active': nodeParams(meta.id).type == 2 && meta.id == nodeItem.id }"
            :id="meta.id"
          >
            <div
              class="node_span"
              @click="clickItem(meta.id)"
              @blur="blurItem"
            >{{nodeParams(meta.id).name}}</div>
          </div>
        </template>
      </super-flow>
    </div>
    <div class="flow_options">
      <p class="options_head">操作</p>
      <div class="options_item" @click="generalSettings">
        <img :src="require('@/assets/imgs/lcsj_ic_set.png')" class="options_img" />
        <p class="options_text">常规设置</p>
      </div>
      <div class="options_item_1">
        <img :src="require('@/assets/imgs/lcsj_ic_chajian.png')" class="options_img" />
        <p class="options_text">插件设置</p>
        <div class="options_pop">
          <div class="options_pop_item">
            <img :src="require('@/assets/imgs/lcsj_ic_jiekou.png')" class="options_item_img" />
            <p class="options_item_text">接口插件</p>
          </div>
          <div class="options_pop_item">
            <img :src="require('@/assets/imgs/lcsj_ic_liucheng.png')" class="options_item_img" />
            <p class="options_item_text">流程服务</p>
          </div>
          <div class="options_pop_item">
            <img :src="require('@/assets/imgs/lcsj_ic_chaoshi.png')" class="options_item_img" />
            <p class="options_item_text">超时管理</p>
          </div>
        </div>
      </div>
    </div>
    <el-dialog
      :visible.sync="dialog_general"
      top="25vh"
      width="420px"
      :modal-append-to-body="false"
      title="常规设置"
      :close-on-click-modal="false"
    >
      <div class="general_settings">
        <p class="general_title">节点编号：</p>
        <p class="general_val">WF0000000101</p>
        <p class="general_title">节点名称：</p>
        <p class="general_input">
          <el-input v-model="node_name" placeholder="请输入节点名称"></el-input>
        </p>
        <div class="dia_footer">
          <el-button class="cancel" @click="generalCancel">取消</el-button>
          <el-button class="submit" @click="generalSubmit">确定</el-button>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
const drawerType = {
  node: 0,
  link: 1,
};
export default {
  data() {
    return {
      scale_num: 100,
      origin: [0, 0],
      nodeList: [],
      linkList: [],
      drawerType,
      drawerConf: {
        title: "",
        visible: false,
        type: null,
        info: null,
        open: (type, info) => {
          const conf = this.drawerConf;
          conf.visible = true;
          conf.type = type;
          conf.info = info;
          if (conf.type === drawerType.node) {
            conf.title = "节点";
            if (this.$refs.nodeSetting) this.$refs.nodeSetting.resetFields();
            this.$set(this.nodeSetting, "name", info.meta.name);
            this.$set(this.nodeSetting, "desc", info.meta.desc);
          } else {
            conf.title = "连线";
            if (this.$refs.linkSetting) this.$refs.linkSetting.resetFields();
            this.$set(
              this.linkSetting,
              "desc",
              info.meta ? info.meta.desc : ""
            );
          }
        },
        cancel: () => {
          this.drawerConf.visible = false;
          if (this.drawerConf.type === drawerType.node) {
            this.$refs.nodeSetting.clearValidate();
          } else {
            this.$refs.linkSetting.clearValidate();
          }
        },
      },
      linkSetting: {
        desc: "",
      },
      nodeSetting: {
        name: "",
        desc: "",
      },
      dragConf: {
        isDown: false,
        isMove: false,
        offsetTop: 0,
        offsetLeft: 0,
        clientX: 0,
        clientY: 0,
        ele: null,
        info: null,
      },
      nodeItemList: [
        {
          label: "普通节点",
          value: {
            width: 120,
            height: 48,
            meta: {
              label: "普通节点",
              name: "普通节点",
              type: 2,
            },
          },
        },
        {
          label: "开始",
          value: {
            width: 120,
            height: 48,
            meta: {
              label: "开始",
              name: "开始",
              type: 0,
            },
          },
        },
        {
          label: "结束",
          value: {
            width: 120,
            height: 48,
            meta: {
              label: "结束",
              name: "结束",
              type: 1,
            },
          },
        },
      ],
      nodeParamsList: [],
      linkMenu: [
        [
          {
            label: "删除",
            selected: (link) => {
              console.log(link);
              link.remove();
            },
          },
        ],
      ],
      dialog_general: false,
      nodeItem: {
        id: "",
        name: "",
      },
      node_name: "",
      show_options_pop: false,
    };
  },
  mounted() {
    document.addEventListener("mousemove", this.docMousemove);
    document.addEventListener("mouseup", this.docMouseup);
    this.$once("hook:beforeDestroy", () => {
      document.removeEventListener("mousemove", this.docMousemove);
      document.removeEventListener("mouseup", this.docMouseup);
    });
  },
  methods: {
    linkStyle(link) {
      return {};
    },
    docMousemove({ clientX, clientY }) {
      const conf = this.dragConf;
      if (conf.isMove) {
        conf.ele.style.top = clientY - conf.offsetTop + "px";
        conf.ele.style.left = clientX - conf.offsetLeft + "px";
      } else if (conf.isDown) {
        // 鼠标移动量大于 5 时 移动状态生效
        conf.isMove =
          Math.abs(clientX - conf.clientX) > 5 ||
          Math.abs(clientY - conf.clientY) > 5;
      }
    },
    docMouseup({ clientX, clientY }) {
      const conf = this.dragConf;
      conf.isDown = false;
      if (conf.isMove) {
        const {
          top,
          right,
          bottom,
          left,
        } = this.$refs.flowContainer.getBoundingClientRect();
        // 判断鼠标是否进入 flow container
        if (
          clientX > left &&
          clientX < right &&
          clientY > top &&
          clientY < bottom
        ) {
        } else if (clientX <= left) {
          clientX = left;
        } else if (clientX >= right) {
          clientX = right;
        } else if (clientY <= top) {
          clientY = top;
        } else if (clientY >= bottom) {
          clientY = bottom;
        }
        // 获取拖动元素左上角相对 super flow 区域原点坐标
        const coordinate = this.$refs.superFlow.getMouseCoordinate(
          clientX - conf.offsetLeft,
          clientY - conf.offsetTop
        );
        // 添加节点
        let query = { width: 120, height: 48, meta: {} };
        if (conf.info.meta.type == 0) {
          query.meta.type == 0;
        } else if (conf.info.meta.type == 1) {
          query.meta.type == 1;
        } else if (conf.info.meta.type == 2) {
          query.meta.type == 2;
        }
        if (!conf.info.meta.id) {
          query.meta.id = parseInt(Math.random() * 1000 * 1000);
        }
        console.log(query);
        this.$refs.superFlow.addNode({
          coordinate,
          ...query,
        });
        if (
          this.nodeParamsList.findIndex((item) => {
            return item.id == query.meta.id;
          }) == -1
        ) {
          let obj = {};
          if (conf.info.meta.type == 0) {
            obj = {
              label: "开始",
              name: "开始",
              type: 0,
              id: query.meta.id,
            };
          } else if (conf.info.meta.type == 1) {
            obj = {
              label: "结束",
              name: "结束",
              type: 1,
              id: query.meta.id,
            };
          } else if (conf.info.meta.type == 2) {
            obj = {
              label: "普通节点",
              name: "普通节点",
              type: 2,
              id: query.meta.id,
            };
          }
          this.nodeParamsList.push(obj);
          console.log(this.nodeParamsList);
        }
        conf.isMove = false;
      }
      if (conf.ele) {
        conf.ele.remove();
        conf.ele = null;
      }
    },
    nodeItemMouseDown(evt, info) {
      const { clientX, clientY, currentTarget } = evt;
      const { top, left } = evt.currentTarget.getBoundingClientRect();
      const conf = this.dragConf;
      const ele = currentTarget.cloneNode(true);
      Object.assign(this.dragConf, {
        offsetLeft: clientX - left,
        offsetTop: clientY - top,
        clientX: clientX,
        clientY: clientY,
        info,
        ele,
        isDown: true,
      });
      ele.style.position = "fixed";
      ele.style.margin = "0";
      ele.style.top = clientY - conf.offsetTop + "px";
      ele.style.left = clientX - conf.offsetLeft + "px";
      this.$el.appendChild(this.dragConf.ele);
    },
    clickItem(index) {
      let item = this.nodeParams(index);
      this.nodeItem = item;
      console.log(item);
    },
    blurItem() {
      this.nodeItem = {
        id: "",
      };
      console.log(this.nodeItem);
    },
    getData() {
      return {
        obj: this.$refs.superFlow.toJSON(),
        params: this.nodeParamsList,
      };
    },
    handleChange() {},
    generalSettings() {
      let self = this;
      if (self.nodeItem.id && self.nodeItem.id != "") {
        if (self.nodeItem.type == 2) {
          self.node_name = self.nodeParamsList.find((item) => {
            return item.id == self.nodeItem.id;
          }).name;
          self.dialog_general = true;
        } else {
          self.$message({
            message: "开始和结束节点不可被编辑",
            type: "warning",
          });
        }
      } else {
        self.$message({
          message: "请选择节点",
          type: "warning",
        });
      }
    },
    nodeParams(id) {
      let index = this.nodeParamsList.findIndex((item) => {
        return item.id == id;
      });
      if (index != -1) {
        return this.nodeParamsList[index];
      } else {
        return {};
      }
    },
    generalCancel() {
      this.dialog_general = false;
    },
    generalSubmit() {
      let self = this;
      if (self.nodeItem.type == 2) {
        let index = self.nodeParamsList.findIndex((item) => {
          return item.id == self.nodeItem.id;
        });
        if (index != -1) {
          self.nodeParamsList[index].name = self.node_name;
        } else {
          self.$message({
            message: "修改失败",
            type: "error",
          });
        }
      }

      self.dialog_general = false;
    },
  },
};
</script>

<style lang="less" scoped>
.link-base-style-form {
  .el-form-item {
    margin-bottom: 12px;
  }
  padding-bottom: 20px;
  border-bottom: 1px solid #dcdcdc;
}
.super-flow-demo1 {
  margin-top: 20px;
  width: 100%;
  height: 100%;
  background-color: #fff;
  @list-width: 160px;
  position: relative;
  > .flow-container {
    width: 100%;
    float: left;
    height: 100%;
    overflow: hidden;
  }
  .flow_options {
    width: 84px;
    height: 244px;
    background-color: #f8f9fd;
    border-radius: 42px;
    position: absolute;
    top: 10px;
    right: 0;
    text-align: center;
    .options_head {
      color: #242c43;
      font-size: 12px;
      font-weight: bold;
      margin-top: 30px;
    }
    .options_item {
      margin-top: 20px;
      cursor: pointer;
      color: #242c43;
      &:hover {
        color: #515fe7;
      }
      .options_img {
        width: 40px;
        height: 40px;
      }
    }
    .options_item_1 {
      margin-top: 20px;
      cursor: pointer;
      color: #242c43;
      position: relative;
      .options_img {
        width: 40px;
        height: 40px;
      }
      .options_pop {
        display: none;
      }
      &:hover .options_pop {
        position: absolute;
        width: 250px;
        height: 82px;
        background-color: #0d1847;
        border-radius: 10px;
        z-index: 2;
        top: 0;
        right: 0;
        animation: myfirst 1s;
        display: flex;
        overflow: hidden;
        justify-content: space-around;
        color: #ffffff;
        font-size: 12px;
        .options_pop_item {
          padding-top: 10px;
          .options_item_img {
            width: 40px;
            height: 40px;
          }
          .options_item_text {
            white-space: nowrap;
          }
        }
      }
      @keyframes myfirst {
        from {
          width: 0;
        }
        to {
          width: 250px;
        }
      }
    }
  }
}
.node-item {
  @node-item-height: 42px;
  font-size: 16px;
  display: inline-block;
  height: @node-item-height + 6;
  width: 120px;
  margin-top: 18px;
  background-color: #ffffff;
  border-radius: 10px;
  line-height: @node-item-height;
  box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.3);
  cursor: pointer;
  user-select: none;
  text-align: center;
  z-index: 6;
  &:hover {
    box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.4);
  }
  &.node-item-begin {
    border: solid 3px #25bdb1;
  }
  &.node-item-end {
    border: solid 3px #f78181;
  }
  &.node-item-default {
    border: solid 3px #b4c6f5;
  }
}
.scale_block {
  position: absolute;
  left: 0;
  z-index: 2;
  top: 5px;
  width: 160px;
  .scale_control {
    width: 130px;
    display: flex;
    justify-content: space-around;
    border-radius: 8px;
    border: solid 2px #e3e5ef;
    height: 40px;
    font-size: 16px;
    line-height: 36px;
    margin: 0 auto;
    color: #8390ee;
    .less {
      padding: 0 10px;
      border-right: solid 2px #e3e5ef;
    }
    .add {
      padding: 0 10px;
      border-left: solid 2px #e3e5ef;
    }
    .num {
      color: #58617a;
    }
  }
  .node-container {
    width: 160px;
    height: 300px;
    text-align: center;
    background-color: #f8f9fd;
    border-radius: 8px;
    margin-top: 20px;
    .label_head {
      font-weight: bold;
      font-size: 14px;
      text-align: center;
      padding: 20px 0 15px;
      color: #242c43;
    }
    .label_explanation {
      font-size: 14px;
      text-align: center;
      color: #8890a7;
    }
  }
}
</style>
<style lang="less">
.super-flow {
  .super-flow__node {
    border: none;
    background-color: transparent;
    border-radius: 8px;
    font-size: 16px;
    /deep/ .node_span {
      text-align: center;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .flow-node-begin {
      width: 100%;
      height: 100%;
      line-height: 42px;
      padding: 0 6px;
      border-radius: 8px;
      border: solid 3px #109e93;
      background-color: #25bdb1;
      color: #ffffff;
    }
    .flow-node-end {
      width: 100%;
      height: 100%;
      line-height: 42px;
      padding: 0 6px;
      border-radius: 8px;
      background-color: #f78181;
      border: solid 3px #e86262;
      color: #ffffff;
    }
    .flow-node-default {
      width: 100%;
      height: 100%;
      line-height: 42px;
      padding: 0 6px;
      border-radius: 8px;
      background-color: #fff;
      border: solid 3px #b4c6f5;
    }
    .flow-node-default-active {
      width: 100%;
      height: 100%;
      line-height: 42px;
      padding: 0 6px;
      border-radius: 8px;
      border: solid 3px #b4c6f5;
      box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.8);
      background-color: #515fe7;
      color: #fff;
    }
  }
}
.super-flow__menu-container .super-flow__menu {
  width: 120px;
}
.super-flow-demo1 .el-dialog__wrapper {
  padding-left: 180px;
}
.super-flow-demo1 .el-dialog__body {
  padding: 20px;
}
.super-flow-demo1 >  .v-modal {
  position: absolute;
  border-radius: 8px;
  width: calc(100% + 40px);
  height: calc(100% + 230px);
  top: -160px;
  left: -20px;
}
.general_settings {
  font-size: 14px;
  text-align: left;
  .general_title {
    margin-bottom: 20px;
    padding-left: 10px;
  }
  .general_val {
    margin-bottom: 30px;
    padding-left: 10px;
  }
  .general_input {
    margin-bottom: 50px;
  }
}
.dia_footer {
  font-size: 14px;
  text-align: center;
  display: flex;
  justify-content: flex-end;
  .cancel {
    background-color: #c3caf8;
    color: #0f2683;
    width: 90px;
    height: 34px;
    padding: 0 20px;
  }
  .submit {
    background-color: #0f2683;
    color: #f8f9fd;
    width: 90px;
    height: 34px;
    padding: 0 20px;
  }
}
</style>