MappingPanel.vue 6.18 KB
<template>
  <div class="mapping-panel__container">
    <div class="mapping-tool__bar">
      <el-button type="text" icon="el-icon-refresh-left" @click="reset"
        >重置</el-button
      >
      <el-divider direction="vertical"></el-divider>
      <el-button type="text" icon="el-icon-delete" @click="clear"
        >清空</el-button
      >
      <el-divider direction="vertical"></el-divider>
      <el-button
        :disabled="!currentConnect"
        type="text"
        icon="el-icon-close"
        @click="handleDeleteKeyUp"
        >删除</el-button
      >
      <el-divider
        v-if="triggerType == 'multiDiffData'"
        direction="vertical"
      ></el-divider>
      <el-button
        v-if="triggerType == 'multiDiffData'"
        :disabled="!currentNode || !currentColumn"
        type="text"
        icon="el-icon-user-solid"
        v-tooltip.after="{
          content:
            '在子流程业务对象中选中一个字段,将所选字段作为子流程发起人字段(注意:只能选择用户账号字段)。'
        }"
        @click="setCreatorFollowData"
        >设置为发起人</el-button
      >
    </div>
    <div
      id="flowWrap"
      ref="flowWrap"
      class="flowWrap"
      @keyup.delete="handleDeleteKeyUp"
    >
      <div id="flow" v-if="json !== null">
        <mapping-node-item
          v-for="item in json.nodes"
          :key="item.id"
          :id="item.id"
          :node="item"
          :current-node="currentNode"
          :current-column="currentColumn"
          :creator-follow-column="creatorFollowData[item.id]"
          @column-click="handleColumnClick"
        />
      </div>
    </div>
  </div>
</template>

<script>
import {jsPlumb} from 'jsplumb'
import jsPlumbSetting from './jsplumbConfig.js'
import core from './coreMethods.js'
import MappingNodeItem from './MappingNodeItem.vue'
import {tbType} from './tbType.js'

export default {
  name: 'MappingPanel',
  components: {
    MappingNodeItem
  },
  props: {
    triggerType: {
      type: String,
      required: true
    },
    creatorFollowDataKey: String
  },
  data() {
    return {
      jsPlumb: null,
      json: null,
      jsPlumbSetting: jsPlumbSetting,
      commonGrid: [5, 5], //节点移动最小距离
      minus: '-', //表名和列名的分割符号
      currentConnect: null, //当前选中的连线
      creatorFollowData: {}, //用作发起人的字段(以node中id为key,所选列为value)
      currentNode: null, //当前选中列所在node
      currentColumn: null //当前选中列
    }
  },
  mounted() {
    this.jsPlumb = jsPlumb.getInstance()
  },
  watch: {
    currentConnect: function(newVal, oldVal) {
      if (newVal !== oldVal) {
        if (newVal && newVal.target) {
          newVal.setPaintStyle({
            stroke: tbType['RS'].color
          })
        }
        if (oldVal && oldVal.target) {
          oldVal.setPaintStyle({
            stroke: tbType['Union'].color
          })
        }
      }
    }
  },
  methods: {
    ...core,
    handleDeleteKeyUp() {
      if (this.currentConnect) {
        this.jsPlumb.deleteConnection(this.currentConnect)
      }
    },
    renderWithJson(json) {
      if (json) {
        this.json = json
        if (!this.json.edges) {
          this.$set(this.json, 'edges', [])
        }
        this.parseCreatorFollowDataKey(this.json.nodes)
        this.fixNodesPosition()
        this.$nextTick(() => this.init())
      }
    },
    // 从发起人字段中解析为 creatorFollowData 对象
    parseCreatorFollowDataKey(nodes) {
      if (this.triggerType == 'multiDiffData' && this.creatorFollowDataKey) {
        const keyAry = this.creatorFollowDataKey.split('.')
        if (!keyAry || keyAry.length != 2) {
          this.$message.warn('子流程发起人字段格式错误,需要重新设置.')
          return
        }
        const [nodeName, columnName] = keyAry
        const node = nodes.find(n => n.name == nodeName)
        if (node && node.columns && node.columns.length > 0) {
          const column = node.columns.find(c => c.name == columnName)
          if (column) {
            this.$set(this.creatorFollowData, node.id, column)
          }
        }
      }
    },
    // 将 creatorFollowData 对象构建为
    buildCreatorFollowDataKey() {
      let result = null
      if (this.triggerType == 'multiDiffData' && this.creatorFollowData) {
        const keys = Object.keys(this.creatorFollowData)
        if (keys && keys.length > 0) {
          const key = keys[0]
          const node = this.json.nodes.find(n => n.id == key)
          const column = this.creatorFollowData[key]
          result = `${node.name}.${column.name}`
        }
      }
      return result
    },
    reset() {
      this.clear()
      this.renderWithJson(this.json)
    },
    clear() {
      this.jsPlumb.deleteEveryConnection()
    },
    setCreatorFollowData() {
      if (this.currentNode && this.currentColumn) {
        this.$set(
          this.creatorFollowData,
          this.currentNode.id,
          this.currentColumn
        )
      }
    },
    handleColumnClick(node, column) {
      if (this.currentNode == node && this.currentColumn == column) {
        this.$set(this, 'currentNode', null)
        this.$set(this, 'currentColumn', null)
      } else {
        this.$set(this, 'currentNode', node)
        this.$set(this, 'currentColumn', column)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.mapping-panel__container {
  .mapping-tool__bar {
    background-color: #f8f8f8;
    border-radius: 5px;
    height: 40px;
    margin-bottom: 10px;
    padding: 0 20px;
    display: flex;
    align-items: center;

    ::v-deep {
      svg.el-tooltip.fa-icon {
        vertical-align: -3px;
      }
    }
  }

  .flowWrap {
    border: 1px solid #ccc;
    height: 500px;
    position: relative;
    overflow: hidden;
    outline: none !important;
    flex-grow: 1;
    background-image: url('../../assets/img/point.png');
    #flow {
      position: relative;
      width: 100%;
      height: 100%;
    }
  }
}
</style>

<style lang="scss">
.jtk-connector.jtk-hover {
  z-index: 10001;
  path {
    cursor: pointer !important;
  }
}
.jtk-endpoint.endpoint-rect {
  z-index: 10000;
  cursor: crosshair;
  svg {
    visibility: hidden;
  }
}
</style>