<template>
  <div class="diagramContainer">
    <div class="diagram-wrap left-diagram">
      <p style="margin-left: 10px; margin-bottom: 6px;">主流程字段</p>
      <!-- <plumb-tree :list="leftList" /> -->
      <div class="leftdata box" v-for="(item, index) in leftData" :key="index">
        <p
          class="con"
          :id="'left' + item.fieldName + '&' + item.path + '&' + item.fieldType"
        >
          {{ item.fieldShowName }}
        </p>
      </div>
    </div>
    <div class="diagram-wrap right-diagram">
      <p style="margin-left: 10px; margin-bottom: 6px;">子流程字段</p>
      <div
        class="rightList box"
        v-for="(item, index) in rightData"
        :key="index + 1"
      >
        <p
          class="con"
          :id="
            'right' + item.fieldName + '&' + item.path + '&' + item.fieldType
          "
        >
          {{ item.fieldShowName }}
        </p>
      </div>
      <!-- <plumb-tree :list="rightList" /> -->
    </div>
  </div>
</template>

<script>
import jsPlumb from 'jsplumb' // 可拉伸指示箭头,可用于映射图标
import draggable from 'vuedraggable' //导入draggable组件

export default {
  name: 'plumb',
  components: {
    draggable
  },
  data() {
    return {
      testList2: [],
      common: null,
      plumbIns: null,
      leftData: [],
      rightData: [],
      pointList: [
        // { sourceId: 4, targetId: 2 }
      ],
      drag: false // 上下拖拽列表顺序
    }
  },
  props: {
    type: {
      type: String,
      default() {
        return ''
      }
    },
    leftList: {
      type: Array,
      default() {
        return []
      }
    },
    rightList: {
      type: Array,
      default() {
        return []
      }
    },
    connectData: {
      type: Array,
      default() {
        return []
      }
    }
  },
  watch: {
    leftData(nVal, oVal) {
      // 设置连接点
      this.setLinkPoint()
      // 设置默认连线
      this.setDefaultLine()
      // 连线前的判断
      this.beforeDrop()
    }
  },
  created() {
    // this.format(this.rightList)
    let that = this
    this.pointList = this.connectData
    this.plumbIns = jsPlumb.jsPlumb.getInstance({
      ConnectionsDetachable: true, //连线是否可用鼠标分离
      ReattachConnections: true, //是否重新连接使用鼠标分离的线
      //父级元素id；假如页面元素所在上层不同，最外层父级一定要设置
      Container: 'module',
      // DragOptions : { cursor: "pointer", zIndex:2000 },//拖动的时候
      PaintStyle: {
        stroke: '#BCBCBC'
      }, // 默认悬停样式  默认为null
      HoverPaintStyle: {
        stroke: '#1E90FF'
      }, // 默认悬停样式  默认为null
      EndpointStyle: {
        fill: '#BCBCBC',
        radius: 5
      },
      EndpointHoverStyle: {
        fill: '#1E90FF',
        radius: 5
      }, // 端点悬停样式
      Rectangle: {}
    })
    this.common = {
      isSource: true,
      isTarget: true,
      endpoint: [
        'Dot',
        {
          radius: 5,
          fill: '#ff5722'
        }
      ], // 端点的形状
      maxConnections: -1,
      connector: [
        'Straight',
        {
          gap: 2,
          cornerRadius: 5,
          alwaysRespectStubs: true
        }
      ], // 连接线的样式种类有[Bezier],[Flowchart],[StateMachine ],[Straight ]
      connectorOverlays: [
        [
          'Arrow',
          {
            width: 10,
            length: 10,
            location: 1
          }
        ],
        [
          'Label',
          {
            location: 0.3,
            label: '',
            visible: true,
            id: 'label',
            labelStyle: {
              color: '#FFF'
            },
            cssClass: 'aLabel',
            events: {
              click(labelOverlay, originalEvent) {
                // console.log('删除当前映射线 :', that.pointList, labelOverlay.component.sourceId, labelOverlay.component.targetId);
                let sourceId = labelOverlay.component.sourceId // 起点
                let targetId = labelOverlay.component.targetId // 目标点
                // 删除列表中的连线关系
                console.log(sourceId, 'sourceId')
                console.log(targetId, 'targetId')
                for (let i = 0; i < that.pointList.length; i++) {
                  let item = that.pointList[i]
                  console.log(that.pointList[i], 'left')
                  if (
                    'left' + item.LeftName === sourceId &&
                    'right' + item.RightName === targetId
                  ) {
                    that.pointList.splice(i, 1)
                    that.$emit('confirm', that.pointList)
                  }
                }

                that.plumbIns.deleteConnection(labelOverlay.component) // 删除当前映射线
              }
            }
          }
        ]
      ]
    }
  },
  mounted() {
    this.formatData(this.leftList)
    this.formatData2(this.rightList)
    let that = this
    that.plumbIns.ready(() => {
      that.plumbIns.setContainer('module')

      // 设置连接点
      this.setLinkPoint()
      // 设置默认连线
      this.setDefaultLine()
      // 连线前的判断
      this.beforeDrop()
      // 断开连接线触发
      that.plumbIns.bind('connectionDetached', info => {})
      //点击删除连接线
      that.plumbIns.bind('click', function(labelOverlay, originalEvent) {
        // console.log('删除当前映射线 :', that.pointList, labelOverlay.component.sourceId, labelOverlay.component.targetId);
        let sourceId = labelOverlay.sourceId // 起点
        let targetId = labelOverlay.targetId // 目标点
        // 删除列表中的连线关系
        for (let i = 0; i < that.pointList.length; i++) {
          let item = that.pointList[i]
          if (
            'left' + item.fieldName === sourceId &&
            'right' + item.fieldName === targetId
          ) {
            that.pointList.splice(i, 1)
          }
        }
        that.plumbIns.deleteConnection(labelOverlay) // 删除当前映射线
        console.log(this.pointList)
        this.$emit('confirm', this.pointList)
      })
    })
  },
  methods: {
    testParse(data, path, parseList) {
      let that = this
      data.forEach(function(item, index) {
        path = '0'
        const parseData = {
          fieldName: item.fieldName,
          fieldShowName: item.fieldShowName,
          fieldType: item.fieldType,
          id: item.id,
          sourceId: item.id,
          type: item.fieldType,
          path: path + '.' + item.fieldName,
          child: []
        }

        if (item.fieldType && item.fieldType == 'Array' && item.child) {
          path = path + '.' + item.fieldName
          let parseList = []
          that.testParseArray(item.child, path, parseList)
          parseData.child = parseList
        }

        that.testList2.push(parseData)
      })
    },
    testParseArray(data, path, parseList) {
      let that = this
      data.forEach(function(item, index) {
        const parseData = {
          fieldName: item.fieldName,
          fieldShowName: item.fieldShowName,
          fieldType: item.fieldType,
          id: item.id,
          sourceId: item.id,
          type: item.fieldType,
          path: path + '.' + item.fieldName,
          child: []
        }

        if (item.fieldType && item.fieldType == 'Array' && item.child) {
          path = path + '.' + item.fieldName
          let parseList = []
          that.testParseArray(item.child, path, parseList)
          parseData.child = parseList
        }

        parseList.push(parseData)
      })
      return parseList
    },
    format(val, pname) {
      val.forEach((item, index) => {
        if (item.children && item.children.length > 0) {
          this.rightList.push(...item.children)
        }
      })
    },
    formatData2(val, pname) {
      var pname = pname
      val.forEach((ele, index) => {
        let newname = ''
        if (pname == undefined) {
          newname = ele.fieldName
        } else {
          newname = pname + '.' + ele.fieldName
        }
        if (ele.nodeTableLists) {
          this.formatData(ele.nodeTableLists, newname)
        }
        this.rightData.push({
          fieldName: ele.fieldName,
          fieldShowName: ele.fieldShowName,
          fieldType: ele.fieldType,
          id: ele.id,
          sourceId: ele.id,
          type: 'source',
          path: newname
        })
      })
    },
    formatData(val, pname) {
      var pname = pname
      val.forEach((ele, index) => {
        let newname = ''
        if (pname == undefined) {
          newname = ele.fieldName
        } else {
          newname = pname + '.' + ele.fieldName
        }
        if (ele.nodeTableLists) {
          this.formatData(ele.nodeTableLists, newname)
        }
        this.leftData.push({
          fieldName: ele.fieldName,
          fieldShowName: ele.fieldShowName,
          fieldType: ele.fieldType,
          id: ele.id,
          sourceId: ele.id,
          type: 'source',
          path: newname
        })
      })
    },
    // 设置连接点
    setLinkPoint() {
      this.plumbIns.reset() // 清除后再跟进后台传过来的值画线
      this.$nextTick(() => {
        this.leftData.forEach(item => {
          this.plumbIns.addEndpoint(
            'left' + item.fieldName + '&' + item.path + '&' + item.fieldType,
            {
              anchors: ['Right'],
              uuid:
                'left' +
                item.fieldName +
                '&' +
                item.path +
                '&' +
                item.fieldType,
              fieldType: item.fieldType
            },
            this.common
          )
        })
        this.rightData.forEach(item => {
          this.plumbIns.addEndpoint(
            'right' + item.fieldName + '&' + item.path + '&' + item.fieldType,
            {
              anchors: ['Left'],
              uuid:
                'right' +
                item.fieldName +
                '&' +
                item.path +
                '&' +
                item.fieldType,
              esbFieldType: item.esbFieldType
            },
            this.common
          )
        })
      })
    },
    // 连线前的判断
    beforeDrop() {
      // 连线前规则,返回true符合规则,不返回或者返回false,不符合规则
      this.plumbIns.bind('beforeDrop', info => {
        // info是该线段的基本信息  sourceId是线头节点id，targetId是线尾节点id
        if (info.sourceId == info.targetId) {
          // 判断是否是同一节点
          return false
        }
        // 必须是右边连接左边
        if (info.targetId.indexOf('right') === -1) {
          return false
        }
        // 左边不可以连接右边
        if (info.sourceId.indexOf('left') === -1) {
          return false
        }
        let sourceId = info.sourceId // 起点
        let targetId = info.targetId // 目标点
        let sourceKey = info.connection['endpoints'][0].anchor.type // 连接的位置获取
        let targetKey = info.dropEndpoint.anchor.type // 连接的位置获取
        let pointList = JSON.parse(JSON.stringify(this.pointList))
        for (let i = 0; i < pointList.length; i++) {
          let item = pointList[i]
          if (
            'right' + item.sourceId === sourceId &&
            'left' + item.targetId === targetId
          ) {
            return false
          }
        }

        pointList.push({
          LeftName: sourceId.replace(/left/, ''),
          RightName: targetId.replace(/right/, '')
        })
        this.pointList = pointList
        this.$emit('confirm', this.pointList)
        return true
      })
    },
    // 设置默认连线
    setDefaultLine() {
      this.plumbIns.reset() // 清除后再跟进后台传过来的值画线
      console.log(this.pointList, 'pointList')
      this.$nextTick(() => {
        this.pointList.forEach((item, index) => {
          this.plumbIns.connect(
            { uuids: ['left' + item.LeftName, 'right' + item.RightName] },
            this.common
          )
        })
      })
    },
    checkMove(evt) {
      return true
    }
  }
}
</script>

<style scoped>
#wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  padding: 15px;
  width: 100%;
  height: 100vh;
  box-sizing: border-box;
}
/* 头部 */
.head {
  display: inline-flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}
.head .title {
  position: relative;
  margin: 10px 0;
  color: #999;
}
.head .title::before {
  float: left;
  display: inline-block;
  content: ' ';
  margin: 3px 10px 0 0;
  width: 5px;
  height: 16px;
  background-color: #1abc9c;
}

/* 内容 */
.content {
  flex-grow: 1;
  position: relative;
  margin: 15px 0 0;
  padding: 20px 20px 100px 20px;
  box-sizing: border-box;
  background-color: #fff;
}
.content .row {
  display: flex;
  flex-wrap: nowrap;
  margin-bottom: 10px;
  color: #333;
  font-size: 14px;
}

.content .thead {
  align-items: center;
}
.thead .formLabel {
  display: inline-block;
  margin-right: 10px;
  color: #333;
  font-weight: bold;
}
.thead .input {
  display: inline-block;
  margin-right: 62px;
  width: 300px;
}
.thead .select {
  display: inline-block;
  width: 150px;
}

.content .dataCont {
  position: relative;
  margin-top: 30px;
  justify-content: space-between;
}
.dataCont .data {
}
.data .dataTitle {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  justify-content: space-between;
  width: 100%;
}
.data .dataTitle .title {
  font-weight: bold;
  font-size: 16px;
}
.data .tab {
}
.data .addItemBtn {
  margin-top: 15px;
}
.data .tab .tabHead {
}
.data .tab table {
  border-collapse: collapse;
}
.tab table th {
  height: 40px;
  line-height: 40px;
  text-align: center;
  border: 1px solid #aaa;
  background-color: #f2f2f2;
}
.tab table td {
  position: relative;
  height: 40px;
  line-height: 40px;
  border: 1px solid #aaa;
  vertical-align: middle;
}
::v-deep .tab .tInput .el-input__inner {
  border: none;
}
::v-deep .tab .tSelect .el-input__inner {
  border: none;
}
.tab .btn {
  display: inline-block;
  padding: 0 10px;
  height: 30px;
  line-height: 30px;
  cursor: pointer;
  opacity: 1;
}
.tab .btn:hover {
  opacity: 0.9;
}
.tab .btn .fixedMsg {
  margin-left: 10px;
  color: #ccc;
}
.tab .delBtn {
  margin-left: 15px;
  color: #fff;
  background-color: #ff5722;
}
.tab .dragBtn {
  position: absolute;
  top: 6px;
  right: 20px;
  padding: 0;
  width: 24px;
  height: 28px;
  cursor: move;

  background-size: 100% 100%;
}
.dataCont .dataModelBox {
}
/* 数据源列表 */
.dataCont .dataStart {
  width: 400px;
}
.dataStart .dataTitle .dSelect {
  width: 180px;
}
::v-deep .dataStart .dataTitle .dSelect .el-input__inner {
  border: none;
}
.dataStart table {
  width: 100%;
}
.dataStart table th,
.dataStart table td {
  padding: 0 15px;
  text-align: left;
}

.content .groupBtn {
  position: absolute;
  bottom: 20px;
}

::v-deep .aLabel {
  display: inline-block;
  width: 8px;
  height: 8px;
  line-height: 8px;
  cursor: pointer;
  font-size: 12px;
  border-radius: 50%;
  border: 1px solid #bcbcbc;
  background: #bcbcbc;
  background-size: 100% 100%;
}
::v-deep .aLabel:hover {
  width: 16px;
  height: 16px;
  line-height: 16px;
  font-size: 14px;
  border: 1px solid #dc143c;

  background-size: 100% 100%;
}
.diagramContainer {
  width: 100%;
  overflow: hidden;
  position: relative;
}
.diagram-wrap {
  float: left;
  width: 50%;
  font-size: 12px;
}
.box .con {
  width: 200px;
  margin: 5px 0;
  padding: 5px 0;
  display: inline-block;
  text-indent: 8px;
  border: 1px solid #eee;
  border-radius: 4px;
  /* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
}
.box .required {
  border: 1px solid #fb1c1c;
}
</style>
