
<template>
  <div>
    <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': meta.type == 0, 'flow-node-end': meta.type == 1, 'flow-node-default': meta.type == 2}"
              :id="meta.id"
            >
              <div class="node_span" @click="clickItem(meta)">{{meta.name}}</div>
            </div>
          </template>
        </super-flow>
      </div>
    </div>
  </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,
            },
          },
        },
      ],
      linkMenu: [
        [
          {
            label: "删除",
            selected: (link) => {
              console.log(link);
              link.remove();
            },
          },
        ],
      ],
    };
  },
  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
        );
        // 添加节点
        this.$refs.superFlow.addNode({
          coordinate,
          ...conf.info,
        });
        conf.isMove = false;
      }
      if (conf.ele) {
        conf.ele.remove();
        conf.ele = null;
      }
    },
    nodeItemMouseDown(evt, info) {
      info.meta.id = parseInt(Math.random() * 1000 * 1000);
      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(item) {
      console.log(item);
    },
    getData() {
      return this.$refs.superFlow.toJSON();
    },
    handleChange() {},
  },
};
</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;
  }
}
.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;
    &:focus {
      box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.8);
      background-color: #515fe7;
      color: #fff;
    }
    /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;
      border: solid 3px #b4c6f5;
    }
  }
}
.super-flow__menu-container .super-flow__menu {
  width: 120px;
}
</style>