<template>
  <div class="dashboard-container">
    <el-button @click="saveActive" icon="el-icon-position" style="margin-right: 20px;float :right">保存</el-button>
    <p>选择节点</p>
    <div class="antvBox">
      <div class="menu-list">
        <div v-for="item in moduleList" :key="item.id"
             draggable="true"
             @dragend="handleDragEnd($event, item)">
          <img :src="item.image" alt="" />
          <p>{{ item.name }}</p>
        </div>
      </div>
      <div class="canvas-card">
        <div id="container" />
      </div>
    </div>
    <el-dialog title="提示" :visible.sync="dialogVisible" width="30%">
      <task v-if="taskOpen" @taskInputForm="findFormValue" :nodes-ids="nodesIds"/>
    </el-dialog>

    <el-dialog title="提示" :visible.sync="dialogVisible1" width="30%">
      <el-table :data="nodeList" style="width: 100%">
        <el-table-column prop="databaseId" label="数据库" width="180"></el-table-column>
        <el-table-column prop="tableAsName" label="表别名" width="180"></el-table-column>
      </el-table>
      <div style="margin: 20px;"></div>
      <el-form label-width="80px" :model="joinCheck">
        <el-form-item label="联查方式">
          <el-select v-model="joinCheck.joinId" placeholder="联查方式">
            <el-option label="左联查" value="1"></el-option>
            <el-option label="右联查" value="2"></el-option>
            <el-option label="内联查" value="3"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
            <el-select v-model="joinCheck.firstCloumn" placeholder="请选择关联字段">
              <el-option
                v-for="item in options1"
                :key="item.nodeMsg"
                :label="item.nodeMsg"
                :value="item.nodeMsg">
              </el-option>
            </el-select>
        </el-form-item>
        <el-form-item>
          <el-select v-model="joinCheck.secondCloumn" placeholder="请选择关联字段">
            <el-option
              v-for="item in options2"
              :key="item.nodeMsg"
              :label="item.nodeMsg"
              :value="item.nodeMsg">
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible1 = false">取 消</el-button>
    <el-button type="primary" @click="todoSelect">确 定</el-button>
  </span>
    </el-dialog>

    <el-dialog
      title="提示"
      :visible.sync="dialogVisible2"
      width="40%"
      >
      <el-table ref="multipleTable" :data="fields" tooltip-effect="dark" style="width: 100%"
        @selection-change="SelectionChange">
        <el-table-column type="selection" width="55"/>
        <el-table-column label="字段" width="120"><template slot-scope="scope">{{ scope.row.field }}</template></el-table-column>
        <el-table-column label="别名" width="120"><template slot-scope="scope">{{ scope.row.asField }}</template></el-table-column>
        <el-table-column label="非空" width="120"><template slot-scope="scope">{{ scope.row.isNull }}</template></el-table-column>
        <el-table-column label="注释" width="120"><template slot-scope="scope">{{ scope.row.comment }}</template></el-table-column>
      </el-table>
      <br>
      <el-cascader
        v-model="toTable"
        :options="tt"
        :props="{ expandTrigger: 'hover',value:'name',label:'name',children:'tableNames' }"
        @change="handleChange"></el-cascader>
      <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible2 = false">取 消</el-button>
    <el-button type="primary" @click="showTableFields">确 定</el-button>
  </span>
    </el-dialog>

    <el-dialog title="提示" :visible.sync="finalVisible" width="30%">
      <el-table ref="multipleTable" :data="sqlList" tooltip-effect="dark" style="width: 100%"
                @selection-change="SelectionChange">
        <el-table-column label="输入字段" width="120">
          <template slot-scope="scope">
            {{ scope.row.asField }}
          </template>
        </el-table-column>
        <el-table-column label="输出字段" width="120">
          <el-select v-model="cloumns" placeholder="请选择">
            <el-option
              v-for="item in options"
              :key="item.id"
              :label="item.field"
              :value="item.field">
            </el-option>
          </el-select>
        </el-table-column>
      </el-table>
      <span slot="footer" class="dialog-footer">
          <el-button @click="finalVisible = false">取 消</el-button>
          <el-button type="primary" @click="addSql">确 定</el-button>
        </span>
    </el-dialog>
  </div>
</template>

<script>
import { Graph } from "@antv/x6";
import {
  addOutPut,
  addSelect,
  extractDataName, findBySelectId,
  seeTableField, selectByAsField,
  selectByNodeId,
  selectByOne, selectByTableName,
} from "../../../api/etl/etl";
import task from "/src/views/components/task/index.vue"
export default {
  name: "antvX6",
  components:{
    task
  },
  data() {
    return {
      sourceField:[],
      outPuter:{
        nodeId:"",
        taskId:"",
        tableFields:"",
        tableAsFields:"",
        targetDatabase:"",
        targetTableName:""
      },
      options:{},
      sqlList:[],
      toTable:"",
      tt:{},
      fields:[],
      finalVisible:false,
      dialogVisible2:false,
      options1:{},
      options2:{},
      nodeList:[],
      neighbors:[],
      nodesIds:"",
      taskOpen:false,
      joinCheck:{
         nodeId:"",
         joinId:"",
         leftNodeId:"",
         rightNodeId:"",
         firstCloumn:"",
         secondCloumn:""
      },
      asFields:[],
      tableData:[],
      dialogVisible1: false,
      tables:{},
      tableMsg:{
        tableName:"",
        tableAsField:""
      },
      cloumns:'',
      labelPosition: 'right',
      dialogVisible:false,
      curSelectNode: "",
      tableFields:[],
      tableDataNodeId:[],
      moduleList: [
        {
          id: 1,
          name: "开始",
          image: require("@/assets/img/1.png"),
        },
        {
          id: 8,
          name: "表",
          image: require("@/assets/img/2.png"),
        },
        {
          id: 2,
          name: "联查",
          image: require("@/assets/img/3.png"),
        },
        {
          id: 3,
          name: "导出",
          image: require("@/assets/img/4.png"),
        },
      ],
      graph: null
    };
  },
  created() {
    this.getDatabaseMessage()
  },
  methods: {
    showTableFields(){
      this.finalVisible = true
      let fieldsList = [...new Set(this.tableFields)]
      selectByAsField(fieldsList).then(res => {
          this.sqlList = res.data
      })

      selectByTableName(this.toTable).then(res => {
        this.options = res.data
      })

    },
    addSql(){
      this.outPuter.taskId = this.$route.query.id
      let fieldsList = [...new Set(this.tableFields)]
      let tableAsFieldList = [...new Set(this.sourceField)]
      this.outPuter.tableFields = fieldsList.toString()
      this.outPuter.tableAsFields = tableAsFieldList.toString()
      this.outPuter.targetTableName = this.toTable
      addOutPut(this.outPuter).then(res => {
        if (res.code == 200){
          this.$message.success("输出节点放置成功")
        }else {
          this.$message.error("发生异常请联系管理员")
        }
      })
      this.dialogVisible2 = false
      this.finalVisible = false
    },
    handleChange(value){
        this.outPuter.targetDatabase = value[0]
        this.toTable = value[1]
    },
    getDatabaseMessage(){
      extractDataName().then(res => {
        this.tt = res.data
      })
    },
    SelectionChange(val){
      val.forEach(res => {
         this.tableFields.push(res.asField)
         this.sourceField.push(res.field)
      })
    },
    todoSelect(){
      addSelect(this.joinCheck).then(res => {
          if (res.code == 200){
            this.$message.success("操作成功")
          }else {
            this.$message.error(res.msg)
          }
      })
      this.dialogVisible1 = false
    },
    findFormValue(){
      this.dialogVisible = false
      this.taskOpen = false
    },
    openForm(data){
      let textWrap = data.attrs.label.textWrap;
      if (textWrap.text == "表"){
        console.log("表节点ID=>"+data.id);
        this.tableDataNodeId.push(data.id)
        this.dialogVisible = true;
        this.taskOpen=true;
      }
      if (textWrap.text == "联查"){
        this.dialogVisible1 = true;
        this.joinCheck.nodeId = data.id
        console.log("联查节点ID=>"+data.id);
        const edges = this.graph.getEdges().filter(edge => {
          return edge.getSourceNode().id === data.id || edge.getTargetNode().id === data.id;
        });

        const neighbors = [];
        edges.forEach(edge => {
          const otherNodeId = edge.getSourceNode().id === data.id ? edge.getTargetNode().id : edge.getSourceNode().id;
          if (!neighbors.includes(otherNodeId)) {
            neighbors.push(otherNodeId);
          }
        });
        this.neighbors = neighbors;
        this.joinCheck.leftNodeId = neighbors[0]
        this.joinCheck.rightNodeId = neighbors[1]
        selectByOne(neighbors[0]).then(res =>{
          this.options1 = res.data
        })
        selectByOne(neighbors[1]).then(res =>{
          this.options2 = res.data
        })
        selectByNodeId(JSON.stringify(this.neighbors)).then(res => {
            this.nodeList = res.data
        })
      }

      if (textWrap.text == "导出"){
        this.outPuter.nodeId = data.id
        console.log("导出节点ID=>"+data.id);
        this.dialogVisible2 = true
        findBySelectId(this.neighbors[0]).then(res => {
          if (res.data == null){
             seeTableField(this.tableDataNodeId).then(res => {
               this.fields = res.data
             })
          }else{
            seeTableField(this.neighbors).then(res => {
              this.fields = res.data
            })
          }
        })
      }

    },
    //todo 鼠标划过节点在显示连接桩
    nodeAddEvent() {
      const { graph } = this;
      const container = document.getElementById("container");
      const changePortsVisible = (visible) => {
        const ports = container.querySelectorAll(".x6-port-body");
        for (let i = 0, len = ports.length; i < len; i = i + 1) {
          ports[i].style.visibility = visible ? "visible" : "hidden";
        }
      };
      this.graph.on("node:mouseenter", () => {
        changePortsVisible(true);
      });
      this.graph.on("node:mouseleave", () => {
        changePortsVisible(false);
      });
      this.graph.on("node:dblclick",(evt) =>{
          let data = evt.node.store.data;
          this.nodesIds = data.id;
          this.openForm(data)
      })
      //todo 节点绑定点击事件
      this.graph.on("node:click", ({ e, x, y, node, view }) => {

        // 判断是否有选中过节点
        if (this.curSelectNode) {
          // 移除选中状态
          this.curSelectNode.removeTools();
          // 判断两次选中节点是否相同
          if (this.curSelectNode !== node) {
            node.addTools([
              {
                name: "boundary",
                args: {
                  attrs: {
                    fill: "#16B8AA",
                    stroke: "#2F80EB",
                    strokeWidth: 1,
                    fillOpacity: 0.1,
                  },
                },
              },
              {
                name: "button-remove",
                args: {
                  x: "100%",
                  y: 0,
                  offset: {
                    x: 0,
                    y: 0,
                  },
                },
              },
            ]);
            this.curSelectNode = node;
          } else {
            this.curSelectNode = null;
          }
        } else {
          this.curSelectNode = node;
          node.addTools([
            {
              name: "boundary",
              args: {
                attrs: {
                  fill: "#16B8AA",
                  stroke: "#2F80EB",
                  strokeWidth: 1,
                  fillOpacity: 0.1,
                },
              },
            },
            {
              name: "button-remove",
              args: {
                x: "100%",
                y: 0,
                offset: {
                  x: 0,
                  y: 0,
                },
              },
            },
          ]);
        }
      });

      //todo 连线绑定悬浮事件
      this.graph.on("cell:mouseenter", ({ cell }) => {
        if (cell.shape == "edge") {
          cell.addTools([
            {
              name: "button-remove",
              args: {
                x: "100%",
                y: 0,
                offset: {
                  x: 0,
                  y: 0,
                },
              },
            },
          ]);
          cell.setAttrs({
            line: {
              stroke: "#409EFF",
            },
          });
          cell.zIndex = 99; // 保证当前悬停的线在最上层，不会被遮挡
        }
      });
      this.graph.on("cell:mouseleave", ({ cell }) => {
        if (cell.shape === "edge") {
          cell.removeTools();
          cell.setAttrs({
            line: {
              stroke: "black",
            },
          });
          cell.zIndex = 1; // 保证未悬停的线在下层，不会遮挡悬停的线
        }
      });
    },
    // todo 拖动后松开鼠标触发事件
    handleDragEnd(e, item) {
      // 可以获取到最后拖动后松开鼠标时的坐标和拖动的节点相关信息
      this.addHandleNode(
        e.pageX - 500,
        e.pageY - 200,
        new Date().getTime(),
        item.image,
        item.name
      );
    },
    initGraph() {
      const container = document.getElementById("container");
      this.graph = new Graph({
        container: container, // 画布容器
        width: container.offsetWidth, // 画布宽
        height: container.offsetHeight, // 画布高
        background: false, // 背景（透明）
        snapline: true, // 对齐线
        // 配置连线规则
        connecting: {
          snap: true, // 自动吸附
          allowBlank: false, // 是否允许连接到画布空白位置的点
          allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边
          allowLoop: true, // 是否允许创建循环连线，即边的起始节点和终止节点为同一节点
          highlight: true, // 拖动边时，是否高亮显示所有可用的节点
          highlighting: {
            magnetAdsorbed: {
              name: "stroke",
              args: {
                attrs: {
                  fill: "#5F95FF",
                  stroke: "#5F95FF",
                },
              },
            },
          },
          router: {
            // 对路径添加额外的点
            name: "orth",
          },
          connector: {
            // 边渲染到画布后的样式
            name: "rounded",
            args: {
              radius: 8,
            },
          },
        },
        panning: {
          enabled: false,
        },
        mousewheel: {
          enabled: true, // 支持滚动放大缩小
          zoomAtMousePosition: true,
          modifiers: "ctrl",
          minScale: 0.5,
          maxScale: 3,
        },
        grid: {
          type: "dot",
          size: 20, // 网格大小 10px
          visible: true, // 渲染网格背景
          args: {
            color: "#a0a0a0", // 网格线/点颜色
            thickness: 2, // 网格线宽度/网格点大小
          },
        },
      });
      this.nodeAddEvent()
    },
    //添加节点到画布
    addHandleNode(x, y, id, image, name) {
      this.graph.addNode({
        id: id,
        shape: "image", // 指定使用何种图形，默认值为 'rect'
        x: x,
        y: y,
        width: 60,
        height: 60,
        imageUrl: image,
        attrs: {
          body: {
            stroke: "#ffa940",
            fill: "#ffd591",
          },
          label: {
            textWrap: {
              width: 90,
              text: name,
            },
            fill: "black",
            fontSize: 12,
            refX: 0.5,
            refY: "100%",
            refY2: 4,
            textAnchor: "middle",
            textVerticalAnchor: "top",
          },
        },
        ports: {
          groups: {
            group1: {
              position: [30, 30],
            },
          },
          items: [
            {
              group: "group1",
              id: "port1",
              attrs: {
                circle: {
                  r: 6,
                  magnet: true,
                  stroke: "#ffffff",
                  strokeWidth: 2,
                  fill: "#5F95FF",
                },
              },
            },
          ],
        },
        zIndex: 10,
      });
    },
    //todo 保存画布，并提交
    saveActive() {
      console.log(this.graph.toJSON(), "graph");
      console.log(this.graph.getNodes(), "node");
    },
  },
  //生命周期 - 挂载完成（可以访问DOM元素）",
  mounted() {
    this.initGraph()
  },
};
</script>
<style lang="scss" scoped>
.dashboard-container {
  .antvBox {
    display: flex;
    width: 100%;
    height: 100%;
    color: black;
    padding-top: 20px;
    .menu-list {
      height: 100%;
      width: 300px;
      padding: 0 10px;
      box-sizing: border-box;
      display: flex;
      justify-content: space-between;
      align-content: flex-start;
      flex-wrap: wrap;
      > div {
        margin-bottom: 10px;
        border-radius: 5px;
        padding: 0 10px;
        box-sizing: border-box;
        cursor: pointer;
        color: black;
        width: 105px;
        display: flex;
        flex-wrap: wrap;

        justify-content: center;
        img {
          height: 50px;
          width: 50px;
        }
        P {
          width: 90px;
          text-align: center;
        }
      }
    }
    .canvas-card {
      width: 1700px;
      height: 750px;
      box-sizing: border-box;
      > div {
        width: 1400px;
        height: 750px;
        border: 2px dashed #2149ce;
      }
    }
  }
}
</style>


