4 Commits e6e5587ecf ... d23787d31c

Auteur SHA1 Message Date
  twzydn20000928 d23787d31c Merge remote-tracking branch 'origin/dev_xlk' into dev_xlk il y a 2 ans
  twzydn20000928 4743f46f48 二叉树画图 il y a 2 ans
  twzydn20000928 9673027b87 二叉树画图 il y a 2 ans
  twzydn20000928 5608c6a64e 新增画图功能 il y a 2 ans

+ 372 - 0
src/views/knowledge/search/binaryTree.vue

@@ -0,0 +1,372 @@
+<template>
+  <div>
+    <div id="chart" style="width: 1000px; height: 700px"></div>
+    <button v-show="selectedNode" @click="addLeftNode">添加左节点</button>
+    <button v-show="selectedNode" @click="addRightNode">添加右节点</button>
+    <button v-show="selectedNode" @click="deleteNode">删除该节点</button>
+    <button v-show="selectedNode" @click="updateNode">修改该节点</button>
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="检查点" prop="startId">
+          <el-select
+            v-model="form.id"
+            placeholder="请选择检查点"
+            filterable
+          >
+            <el-option
+              v-for="item in pointList"
+              :key="item.code"
+              :label="item.check_piont"
+              :value="item.code"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+
+
+<script>
+import echarts from "echarts";
+import { getPointOption } from "@/api/suport/piont";
+
+export default {
+  props: {
+    codes: {
+      type: String,
+    },
+  },
+  data() {
+    return {
+      chartInstance: null,
+      selectedNode: null,
+      treeData: [
+        // 初始节点
+        {
+          name: "Root",
+          value: null,
+          children: [],
+          itemStyle: { borderColor: "#ccc" },
+        },
+      ],
+      title: "",
+      open: false,
+      form: {},
+      rules: {},
+      pointList: [],
+      idMap: new Map(),
+      codeMap: new Map(),
+    };
+  },
+
+  created() {},
+
+  mounted() {
+    this.chartInstance = echarts.init(document.getElementById("chart"));
+    this.chartInstance.on("click", this.selectNode); // 监听点击事件
+    this.getPointOption();
+  },
+  beforeDestroy() {
+    this.chartInstance.off("click", this.selectNode); // 移除监听事件
+  },
+  methods: {
+    renderChart() {
+      const option = {
+        // ECharts配置项
+        tooltip: {
+          trigger: "item",
+          triggerOn: "mousemove",
+        },
+        series: [
+          {
+            type: "tree",
+            data: this.treeData,
+            left: "2%",
+            right: "2%",
+            top: "8%",
+            bottom: "20%",
+            symbol: "emptyCircle",
+            orient: "vertical",
+            symbolSize: 30,
+            itemStyle: {
+              color: null,
+            },
+            expandAndCollapse: false,
+            label: {
+              position: "bottom",
+              rotate: 0,
+              verticalAlign: "middle",
+              align: "center",
+              fontSize: 15,
+              distance: 15,
+              color: "#ccc",
+            },
+            animationDurationUpdate: 750,
+            initialTreeDepth: 10,
+            lineStyle: {
+              color: "rgba(16, 228, 232, 1)",
+            },
+          },
+        ],
+      };
+
+      this.chartInstance.setOption(option);
+    },
+
+    reset() {
+      this.form = {
+        id: null,
+        code: null,
+        checkPiont: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null,
+      };
+      this.resetForm("form");
+    },
+
+    selectNode(params) {
+      if (params.data && params.data.name) {
+        this.selectedNode = params.data;
+      }
+    },
+
+    addLeftNode() {
+      const newNode = {
+        name: "Left Node",
+        value: null,
+        children: [],
+        itemStyle: { borderColor: "#FF0000" },
+      };
+      let n = this.selectedNode.children.length;
+      if (n === 2) {
+        this.$message({
+          message: "左节点已存在",
+          type: "warning",
+        });
+        return;
+      }
+      if (
+        n === 1 &&
+        this.selectedNode.children[0].itemStyle.borderColor == "#FF0000"
+      ) {
+        this.$message({
+          message: "左节点已存在",
+          type: "warning",
+        });
+        return;
+      }
+      this.selectedNode.children.unshift(newNode);
+      this.treeData = this.chartInstance.getOption().series[0].data;
+      this.chartInstance.clear();
+      this.renderChart();
+      this.levelOrder();
+    },
+    addRightNode() {
+      const newNode = {
+        name: "Right Node",
+        value: null,
+        children: [],
+        itemStyle: { borderColor: "#0000FF" },
+      };
+      let n = this.selectedNode.children.length;
+      if (n === 2) {
+        this.$message({
+          message: "右节点已存在",
+          type: "warning",
+        });
+        return;
+      }
+      if (
+        n === 1 &&
+        this.selectedNode.children[0].itemStyle.borderColor == "#0000FF"
+      ) {
+        this.$message({
+          message: "右节点已存在",
+          type: "warning",
+        });
+        return;
+      }
+      this.selectedNode.children.push(newNode);
+      this.treeData = this.chartInstance.getOption().series[0].data;
+      this.chartInstance.clear();
+      debugger
+      this.renderChart();
+      this.levelOrder();
+    },
+    deleteNode() {
+      this.treeData = this.chartInstance.getOption().series[0].data;
+      const parentNode = this.findParentNode(this.treeData, this.selectedNode);
+      if (parentNode) {
+        const index = parentNode.children.indexOf(this.selectedNode);
+        parentNode.children.splice(index, 1);
+        this.chartInstance.clear();
+        this.renderChart();
+        this.levelOrder();
+        this.selectedNode = null;
+      }
+    },
+    findParentNode(tree, targetNode) {
+      for (const node of tree) {
+        for (const child of node.children) {
+          if (child.name === targetNode.name) {
+            return node;
+          }
+        }
+        if (node.children.length > 0) {
+          const parentNode = this.findParentNode(node.children, targetNode);
+          if (parentNode) {
+            return parentNode;
+          }
+        }
+      }
+      return null;
+    },
+
+    updateNode() {
+      this.reset();
+      this.form.id = this.selectedNode.value;
+      this.open = true;
+      this.title = "修改检查点";
+    },
+
+    /** 提交按钮 */
+    submitForm() {
+      this.selectedNode.value = this.form.id;
+      for (const point of this.pointList) {
+        if (point.id === this.form.id) {
+          this.selectedNode.name = point.check_piont;
+          break;
+        }
+      }
+      this.open = false;
+      this.treeData = this.chartInstance.getOption().series[0].data;
+      this.chartInstance.clear();
+      this.renderChart();
+      this.levelOrder();
+    },
+
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+
+    getPointOption() {
+      getPointOption().then((resp) => {
+        this.pointList = resp.data;
+        console.info(resp);
+        this.creatIdMap();
+        this.createCodeMap();
+        this.createTree();
+        this.renderChart();
+        console.info(this);
+      });
+    },
+
+    //根据treeData生成flowEncode并返回父组件
+    levelOrder() {
+      const ret = [];
+      if (!this.treeData) {
+        return ret;
+      }
+      const q = [];
+      q.push(this.treeData[0]);
+      while (q.length !== 0) {
+        const currentLevelSize = q.length;
+        const nullNode = { name: "", value: 0, children: [] };
+        for (let i = 1; i <= currentLevelSize; ++i) {
+          const node = q.shift();
+          ret.push(node.value);
+          let n = node.children.length;
+          if (n == 0 && node.value != 0) {
+            q.push(nullNode);
+            q.push(nullNode);
+          } else if (n == 1) {
+            if (node.children[0].itemStyle.borderColor == "#FF0000") {
+              q.push(node.children[0]);
+              q.push(nullNode);
+            } else {
+              q.push(nullNode);
+              q.push(node.children[0]);
+            }
+          } else if (n == 2) {
+            q.push(node.children[0]);
+            q.push(node.children[1]);
+          }
+        }
+      }
+      let n = ret.length;
+      while (ret[n - 1] === 0) {
+        ret.pop();
+        n--;
+      }
+      this.$emit("handleEncode", ret.join(","));
+    },
+
+    //根据父页面传来的codes给treeData赋值
+    createTree() {
+      let v = this.codes.split(",");
+      let n = v.length;
+      if (n === 0) {
+        return;
+      }
+      const q = [];
+      let j = 0;
+      this.treeData[0].name = this.codeMap.get(v[j]);
+      this.treeData[0].value = v[j];
+      q.push(this.treeData[0]);
+      j++;
+      while (q.length !== 0 && j < n) {
+        const node = q.shift();
+        if (v[j] !== "0") {
+          const l = {
+            name: this.codeMap.get(v[j]),
+            value: v[j],
+            children: [],
+            itemStyle: { borderColor: "#FF0000" },
+          };
+          node.children.unshift(l);
+          q.push(l);
+        }
+        j++;
+        if (j === n) {
+          break;
+        }
+        if (v[j] !== "0") {
+          const r = {
+            name: this.codeMap.get(v[j]),
+            value: v[j],
+            children: [],
+            itemStyle: { borderColor: "#0000FF" },
+          };
+          node.children.push(r);
+          q.push(r);
+        }
+        j++;
+      }
+    },
+
+    creatIdMap() {
+      for (const point of this.pointList) {
+        this.idMap.set(point.id, point.check_piont);
+      }
+    },
+
+    createCodeMap() {
+      for (const point of this.pointList) {
+        this.codeMap.set(point.code, point.check_piont);
+      }
+    },
+  },
+};
+</script>

+ 87 - 249
src/views/knowledge/search/chartByD3.vue

@@ -1,263 +1,101 @@
 <template>
-  <div>
-    <div id="chart" style="width: 1000px; height: 700px"></div>
-    <button v-show="selectedNode" @click="addLeftNode">添加左节点</button>
-    <button v-show="selectedNode" @click="addRightNode">添加右节点</button>
-    <button v-show="selectedNode" @click="deleteNode">删除该节点</button>
-    <button v-show="selectedNode" @click="updateNode">修改该节点</button>
-
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="检查点" prop="startId">
-          <el-select
-            v-model="form.id"
-            placeholder="请选择检查点"
-            value-key="id"
-            filterable
-          >
-            <el-option
-              v-for="item in pointList"
-              :key="item.id"
-              :label="item.check_piont"
-              :value="item.id"
-            >
-            </el-option>
-          </el-select>
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitForm">确 定</el-button>
-        <el-button @click="cancel">取 消</el-button>
-      </div>
-    </el-dialog>
-  </div>
+  <div class="app-container" ref="svgContainer"></div>
 </template>
 
-
-
 <script>
-import echarts from "echarts";
-import { getPointOption } from "@/api/suport/piont";
+import * as d3 from 'd3';
 
 export default {
-  data() {
-    return {
-      chartInstance: null,
-      selectedNode: null,
-      treeData: [
-        // 初始节点
-        {
-          name: "Root",
-          value: null,
-          children: [],
-          borderColor: {
-            color: "#ccc"
-          }
-        },
-      ],
-      title: "",
-      open: false,
-      form: {},
-      rules: {},
-      pointList: [],
-      ecode:'',
-    };
-  },
-
-  created() {
-    this.getPointOption();
-  },
-
   mounted() {
-    this.chartInstance = echarts.init(document.getElementById("chart"));
-    this.chartInstance.on("click", this.selectNode); // 监听点击事件
-    this.renderChart();
-    this.levelOrder();
-  },
-  beforeDestroy() {
-    this.chartInstance.off("click", this.selectNode); // 移除监听事件
-  },
-  methods: {
-    renderChart() {
-      const option = {
-        // ECharts配置项
-        tooltip: {
-          trigger: "item",
-          triggerOn: "mousemove",
-        },
-        series: [
-          {
-            type: "tree",
-            data: this.treeData,
-            left: "2%",
-            right: "2%",
-            top: "8%",
-            bottom: "20%",
-            symbol: "emptyCircle",
-            orient: "vertical",
-            symbolSize: 30,
-            itemStyle: {
-              color: null,
-            },
-            expandAndCollapse: false,
-            label: {
-              position: "bottom",
-              rotate: 0,
-              verticalAlign: "middle",
-              align: "center",
-              fontSize: 15,
-              distance: 10,
-            },
-            animationDurationUpdate: 750,
-            initialTreeDepth: 10,
-          },
-        ],
-      };
-
-      this.chartInstance.setOption(option);
-    },
-
-    reset() {
-      this.form = {
-        id: null,
-        code: null,
-        checkPiont: null,
-        createBy: null,
-        createTime: null,
-        updateBy: null,
-        updateTime: null,
-      };
-      this.resetForm("form");
-    },
-
-    selectNode(params) {
-      if (params.data && params.data.name) {
-        this.selectedNode = params.data;
+    const svgContainer = this.$refs.svgContainer;
+    const width = svgContainer.clientWidth;
+    const height = svgContainer.clientHeight;
+
+    const links = [
+      { source: "A", target: "B", value: 1 },
+      { source: "A", target: "C", value: 2 },
+      { source: "B", target: "C", value: 3 },
+      { source: "B", target: "D", value: 4 },
+      { source: "C", target: "D", value: 5 },
+    ];
+
+    const nodes = [
+      { id: "A", x: 100, y: 100 },
+      { id: "B", x: 200, y: 100 },
+      { id: "C", x: 150, y: 200 },
+      { id: "D", x: 250, y: 200 },
+    ];
+
+    const svg = d3.select(svgContainer).append("svg")
+      .attr("width", width)
+      .attr("height", height);
+
+    const link = svg.selectAll("line")
+      .data(links)
+      .join("line")
+      .attr("stroke", "black")
+      .attr("stroke-width", d => d.value);
+
+    const node = svg.selectAll("circle")
+      .data(nodes)
+      .join("circle")
+      .attr("r", 20)
+      .attr("fill", "red")
+      .call(drag(simulation));
+
+    const label = svg.selectAll("text")
+      .data(nodes)
+      .join("text")
+      .text(d => d.id)
+      .attr("x", d => d.x)
+      .attr("y", d => d.y);
+
+    const simulation = d3.forceSimulation(nodes)
+      .force("link", d3.forceLink(links).id(d => d.id))
+      .force("charge", d3.forceManyBody())
+      .force("center", d3.forceCenter(width / 2, height / 2));
+
+    simulation.on("tick", () => {
+      link
+        .attr("x1", d => d.source.x)
+        .attr("y1", d => d.source.y)
+        .attr("x2", d => d.target.x)
+        .attr("y2", d => d.target.y);
+
+      node
+        .attr("cx", d => d.x)
+        .attr("cy", d => d.y);
+
+      label
+        .attr("x", d => d.x)
+        .attr("y", d => d.y - 25);
+    });
+
+    function drag(simulation) {
+
+      function dragstarted(event) {
+        if (!event.active) simulation.alphaTarget(0.3).restart();
+        event.subject.fx = event.subject.x;
+        event.subject.fy = event.subject.y;
       }
-    },
 
-    addLeftNode() {
-      const newNode = { name: "Left Node", value: null, children: [], itemStyle: {borderColor: "#FF0000"} };
-      this.selectedNode.children.unshift(newNode);
-      this.treeData = this.chartInstance.getOption().series[0].data;
-      this.chartInstance.clear();
-      this.renderChart();
-      this.levelOrder();
-    },
-    addRightNode() {
-      const newNode = { name: "Right Node", value: null, children: [],itemStyle: {borderColor: "#0000FF"} };
-      this.selectedNode.children.push(newNode);
-      this.treeData = this.chartInstance.getOption().series[0].data;
-      this.chartInstance.clear();
-      this.renderChart();
-      this.levelOrder();
-    },
-    deleteNode() {
-      this.treeData = this.chartInstance.getOption().series[0].data;
-      const parentNode = this.findParentNode(this.treeData, this.selectedNode);
-      if (parentNode) {
-        const index = parentNode.children.indexOf(this.selectedNode);
-        parentNode.children.splice(index, 1);
-        this.chartInstance.clear();
-        this.renderChart();
-        this.levelOrder();
-        this.selectedNode = null;
-      }
-    },
-    findParentNode(tree, targetNode) {
-      for (const node of tree) {
-        for (const child of node.children) {
-          if (child.name === targetNode.name) {
-            return node;
-          }
-        }
-        if (node.children.length > 0) {
-          const parentNode = this.findParentNode(node.children, targetNode);
-          if (parentNode) {
-            return parentNode;
-          }
-        }
+      function dragged(event) {
+        event.subject.fx = event.x;
+        event.subject.fy = event.y;
       }
-      return null;
-    },
 
-    updateNode() {
-      this.reset();
-      this.form.id = this.selectedNode.value;
-      this.open = true;
-      this.title = "修改检查点";
-    },
-
-    /** 提交按钮 */
-    submitForm() {
-      this.selectedNode.value = this.form.id;
-      for (const point of this.pointList) {
-        if (point.id === this.form.id) {
-          this.selectedNode.name = point.check_piont;
-          break;
-        }
+      function dragended(event) {
+        if (!event.active) simulation.alphaTarget(0);
+        event.subject.fx = null;
+        event.subject.fy = null;
       }
-      this.open = false;
-      this.treeData = this.chartInstance.getOption().series[0].data;
-      this.chartInstance.clear();
-      this.renderChart();
-      this.levelOrder();
-    },
-
-    // 取消按钮
-    cancel() {
-      this.open = false;
-      this.reset();
-    },
-
-    getPointOption() {
-      getPointOption().then((resp) => {
-        this.pointList = resp.data;
-        console.info(resp);
-      });
-    },
 
-    levelOrder() {
-        const ret = [];
-        if (!this.treeData) {
-            return ret;
-        }
-        const q = [];
-        q.push(this.treeData[0]);
-        while (q.length !== 0) {
-            const currentLevelSize = q.length;
-            const nullNode = { name: "", value: 0, children: [],itemStyle: {} };
-            for (let i = 1; i <= currentLevelSize; ++i) {
-                const node = q.shift();
-                ret.push(node.value);
-                let n = node.children.length;
-                if (n == 0 && node.value != 0) {
-                  q.push(nullNode);
-                  q.push(nullNode);
-                }
-                else if (n == 1) {
-                  if (node.children[0].itemStyle.borderColor == "#FF0000"){
-                    q.push(node.children[0]);
-                    q.push(nullNode);
-                  }
-                  else {
-                    q.push(nullNode);
-                    q.push(node.children[0]);
-                  }
-                }
-                else if (n == 2) {
-                  q.push(node.children[0]);
-                  q.push(node.children[1]);
-                }
-            }
-        }
-        let n = ret.length;
-        while (ret[n-1] === 0) {
-          ret.pop();
-          n--;
-        }
-        this.$emit('flowEncode', ret.join(','));
-    },
-  },
-};
+      return d3.drag()
+        .on("start", dragstarted)
+        .on("drag",
+          dragged)
+        .on("end", dragended);
+    }
+  }
+}
 </script>

+ 3 - 3
src/views/suport/flow/index.vue

@@ -158,7 +158,7 @@
           <el-input v-model="form.flowEncode" type="textarea" placeholder="请输入内容" />
         </el-form-item>
         <div>
-          <chartByD3 @handleEncode="handleFlowEncode" :codes="form.flowEncode" />
+          <binaryTree @handleEncode="handleFlowEncode" :codes="form.flowEncode" />
         </div>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -215,11 +215,11 @@
 <script>
 import { listFlow, getInfo, delFlow, addFlow, updateFlow } from "@/api/suport/flow";
 import { getToken } from "@/utils/auth";
-import chartByD3 from "@/views/knowledge/search/chartByD3.vue";
+import binaryTree from "@/views/knowledge/search/binaryTree.vue";
 
 export default {
   name: "Flow",
-  components: { chartByD3 },
+  components: { binaryTree },
   data() {
     return {
       // 遮罩层