<template>
  <div class="dashboard-container">
    <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-button @click="save()">提交</el-button>


    <!--    添加任务详情设计-->
    <el-dialog title="添加表" :visible.sync="taskInputForm" width="70%">
        <formData v-if="formData" :group="graph" :node-id="nodeId" :taskInputForm="taskInputForm"
                  :nodeName="nodeName" :tableInfo="tableInfo" @taskInputForm="findFormValue"></formData>
    </el-dialog>

    <!--    联查弹窗-->
    <el-dialog title="联查" :visible.sync="taskInputJoin" width="70%">
      <formJoin v-if="formJoin" :group="graph" :node-id="nodeId"
                :nodeName="nodeName" :neighbors="neighbors"
                :taskId="taskId" :taskInputJoin="taskInputJoin" @saveTaskJoin="findFormValue"></formJoin>
    </el-dialog>

    <!--    数据输出弹窗-->
    <el-dialog title="数据输出" :visible.sync="taskDataOutPut" width="70%">
      <dataOutInput v-if="formOut" taskDataOutPut:taskDataOutPut></dataOutInput>
    </el-dialog>


  </div>
</template>

<script>

import { Graph } from "@antv/x6";
import { findByNodeId } from '@/api/task/task'
import  formData from '/src/views/components/task/formData.vue'
import  formJoin from '/src/views/components/task/formJoin.vue'
import  dataOutInput from '/src/views/components/task/formDataOut.vue'

export default {
  name: "antvX6",
  components:{
    formData,
    formJoin,
    dataOutInput,
  },
  data() {
    return {
      //数据输出弹窗界面
      taskDataOutPut:false,
      //任务设计添加表弹窗
      taskInputAdd:false,
      //联查界面
      taskInputJoin:false,
      //选择字段弹窗
      taskInputFieldAdd:false,
      //连再联查的节点id
      neighbors:[],
      //记录表信息
      tableInfo:{},
      //画布节点选项
      moduleList: [
        {
          id: 1,
          name: "开始",
          image: require("@/assets/img/1.png"),
          data:{}
        },
        {
          id: 2,
          name: "表",
          image: require("@/assets/img/2.png"),
          data:{
            databaseId:null,
            tableName:null,
            zd:null,
          }
        },
        {
          id: 3,
          name: "联查",
          image: require("@/assets/img/3.png"),
          data:{}
        },
        {
          id: 4,
          name: "数据输出",
          image: require("@/assets/img/4.png"),
          data:{}
        },
      ],
      //画布
      graph:null,
      //节点id
      nodeId:null,
      nodeName:null,

      //添加表弹窗
      taskInputForm:false,
      formData:false,
      formJoin:false,
      formOut:false,
      taskId:this.$route.params.id,
    };
  },
  //初始化
  mounted() {
    this.initGraph();
  },
  methods: {
    findFormValue(){
      this.formData=false;
      this.taskInputForm=false;
      this.taskInputJoin=false;
    },

    //保存画布，并提交
    save() {
      console.log(this.graph.toJSON(), "graph");
      console.log(this.graph.getNodes(), "node");
    },


    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:click",(evt)=>{
        const data = evt.node.store.data;
        const thisData = data.attrs.label.textWrap.text;
        this.nodeId = data.id;
        this.nodeName = thisData;
        if(thisData == "表"){
          findByNodeId(this.nodeId).then(res=>{
            this.tableInfo={};
            this.tableInfo.taskId = this.taskId;
            if(res.code == 200 && res.data!=null){
              this.tableInfo = res.data;
            }
          })
          //TODO man
          this.taskInputForm = true;
          this.formData = true;
        }

        if(thisData == "联查"){
            // 获取与当前节点相连的所有边
            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); // 或者你可以推送整个节点对象，而不是仅ID
              }
            });
            // 现在neighbors数组包含了所有与当前节点相连的节点的ID
            console.log('相连节点的ID:', neighbors);
            this.neighbors = neighbors;
            this.taskInputJoin = true;
            this.formJoin = true;
        }

        if(thisData == "数据输出"){
          this.taskDataOutPut = true;
          this.formOut = true;
        }
      });


      this.graph.on("node:mouseenter", () => {
        changePortsVisible(true);
      });
      this.graph.on("node:mouseleave", () => {
        changePortsVisible(false);
      });

      // 节点绑定右键点击事件
      this.graph.on("node:contextmenu", ({ e, x, y, node, view }) => {
        console.log("点击！！！", node);
        // 判断是否有选中过节点
        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,
                },
              },
            },
          ]);
        }
      });

      //双击事件
      this.graph.on('node:dblclick', (evt) => {
        const data = evt.node.store.data;
        console.log(data);
        // this.showNodeForm(data);
      });

      // 连线绑定悬浮事件
      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; // 保证未悬停的线在下层，不会遮挡悬停的线
        }
      });
    },


    // 拖动后松开鼠标触发事件
    handleDragEnd(e, item) {
      // console.log(e); // 可以获取到最后拖动后松开鼠标时的坐标和拖动的节点相关信息
      this.addHandleNode(
        e.pageX - 500,
        e.pageY - 200,
        new Date().getTime(),
        item.image,
        item.name,
        item.data
      );
    },

    //添加节点到画布
    addHandleNode(x, y, id, image, name ,data) {
      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,
        data:data,
      });
    },

    //初始化
    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();
    },
  },

};
</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>
