logic-flow创建html节点

有很多功能没有完善,开发了30%记录一下,但是大概自己改改能用

创建自定义组件(未完成)

// registerUser.js
import Vue from 'vue';
import Vnode from './Vnode.vue';
export default function registerUser(lf) {
  // 其中user是自定义的type
  lf.register('user', ({ HtmlNodeModel, HtmlNode }) => {
    class UmlNode extends HtmlNode {
      constructor(props) {
        super(props);
      }
      setHtml(rootEl) {
        const { properties } = this.props.model;
        const that = this;
        const el = document.createElement('div');
        rootEl.innerHTML = '';
        rootEl.appendChild(el);
        const Profile = Vue.extend({
          render: function(h) {
            // Vnode是引入的vue组件
            return h(Vnode, {
              props: {
                name: properties.name,
                properties: properties,
              },
              on: {
                'select-button': (type) => {
                  that.props.graphModel.eventCenter.emit('custom:onBtnClick', {
                    type,
                    props: that.props,
                  });
                },
              },
            });
          },
        });
        new Profile().$mount(el);
      }
    }
    class UmlModel extends HtmlNodeModel {
      setAttributes() {
        this.text.editable = false; // 禁止节点文本编辑
        // 设置节点宽高和锚点
        const width = 300;
        const height = 150;
        this.width = width;
        this.height = height;
        this.anchorsOffset = [
          [width / 2, 0],
          [0, height / 2],
          [-width / 2, 0],
          [0, -height / 2],
        ];
      }
    }

    return {
      view: UmlNode,
      model: UmlModel,
    };
  });
}

自定义组件中引入的vue组件(未完成)

// Vnode.vue
<template>
  <div class="connect">
    <p>{{ name }}</p>
    <p>您好,请问需要买保险吗?</p>
    <div @click.stop="done(1)">123</div>
    <div @click.stop="done(2)">{{ properties.type }}</div>
    <div v-if="isLastNode">456</div>
  </div>
</template>

<script>
export default {
  props: {
    name: String,
    properties: {
      type: Object,
      default: () => null,
    },
  },
  data() {
    return {
      isLastNode: false,
    };
  },
  watch: {
    "properties.isLastNode": {
      handler(val) {
        this.isLastNode = val;
      },
      immediate: true,
    },
  },
  methods: {
    done(type) {
      console.log(this.properties);
      this.$emit("select-button", type);
    },
  },
};
</script>

<style scoped>
.connect {
  width: 100%;
  height: 100%;
  background: #fff;
  border: 1px solid #9a9a9b;
  box-sizing: border-box;
  padding: 10px;
}
.connect p {
  margin: 0;
}
.button-list {
  position: absolute;
  bottom: 10px;
}
</style>

引入logic-flow,创建实例

// LF.vue 最主要的组件
<template>
  <div class="logic-flow-view">
    <!-- 辅助工具栏 -->
    <Control
      class="demo-control"
      v-if="lf"
      :lf="lf"
      @catData="$_catData"
    ></Control>
    <!-- 节点面板 -->
    <NodePanel v-if="lf" :lf="lf" :nodeList="nodeList"></NodePanel>
    <!-- 画布 -->
    <div id="LF-view" ref="container"></div>
    <!-- 属性面板 -->
    <el-drawer
      title="设置节点属性"
      :visible.sync="dialogVisible"
      direction="rtl"
      size="500px"
      :before-close="closeDialog"
    >
      <PropertyDialog
        v-if="dialogVisible"
        :nodeData="clickNode"
        :lf="lf"
        @setPropertiesFinish="closeDialog"
      ></PropertyDialog>
    </el-drawer>
    <!-- 数据查看面板 -->
    <el-dialog title="数据" :visible.sync="dataVisible" width="50%">
      <DataDialog :graphData="graphData"></DataDialog>
    </el-dialog>
  </div>
</template>
<script>
import LogicFlow from "@logicflow/core";
// const LogicFlow = window.LogicFlow
import { Menu, Snapshot, MiniMap } from "@logicflow/extension";
import "@logicflow/core/dist/style/index.css";
import "@logicflow/extension/lib/style/index.css";
import NodePanel from "./LFComponents/NodePanel";
import Control from "./LFComponents/Control";
import PropertyDialog from "./PropertySetting/PropertyDialog";
import DataDialog from "./LFComponents/DataDialog";
import { nodeList } from "./config";
import Dagre from "../Util/dagre.js";

import {
  registerStart,
  registerUser,
  registerEnd,
  registerPush,
  registerDownload,
  registerPolyline,
  registerTask,
  registerConnect,
} from "./registerNode";
const demoData = require("./data.json");

export default {
  name: "LF",
  components: { NodePanel, Control, PropertyDialog, DataDialog },
  data() {
    return {
      lf: null,
      showAddPanel: false,
      addPanelStyle: {
        top: 0,
        left: 0,
      },
      nodeData: null,
      addClickNode: null,
      clickNode: null,
      dialogVisible: false,
      graphData: null,
      dataVisible: false,
      config: {
        background: {
          backgroundColor: "#f7f9ff",
        },
        grid: {
          size: 10,
          visible: false,
        },
        keyboard: {
          enabled: true,
        },
        edgeTextDraggable: true,
        hoverOutline: false,
      },
      moveData: {},
      nodeList,
    };
  },
  mounted() {
    this.$_initLf();
  },
  methods: {
    $_initLf() {
      // 画布配置
      const lf = new LogicFlow({
        ...this.config,
        plugins: [Menu, MiniMap, Snapshot, Dagre],
        container: this.$refs.container,
        disabledTools: ["multipleSelect", "textEdit"],
        textEdit: false,
        nodeTextEdit: false,
        edgeTextEdit: false,
      });
      this.lf = lf;
      // 设置主题
      lf.setTheme({
        circle: {
          stroke: "#000000",
          strokeWidth: 1,
          outlineColor: "#88f",
        },
        rect: {
          outlineColor: "#88f",
          strokeWidth: 1,
        },
        polygon: {
          strokeWidth: 1,
        },
        polyline: {
          stroke: "#000000",
          hoverStroke: "#000000",
          selectedStroke: "#000000",
          outlineColor: "#88f",
          strokeWidth: 1,
        },
        nodeText: {
          color: "#000000",
        },
        edgeText: {
          color: "#000000",
          background: {
            fill: "#f7f9ff",
          },
        },
      });
      this.lf.extension.menu.setMenuConfig({
        nodeMenu: [
          {
            text: "保存",
            callback: () => {
              this.lf.graphModel.eventCenter.emit("custom:save", true);
            },
          },
          {
            text: "清空",
            callback: () => {
              this.lf.graphModel.clearData();
              this.lf.render({
                nodes: [
                  {
                    id: this.rootId,
                    x: 200,
                    y: 200,
                    type: "center-node",
                    text: "会计事件",
                  },
                ],
              });
            },
          },
          {
            text: "回到中心",
            callback: () => {},
          },
        ],
        graphMenu: [
          {
            text: "保存",
            callback: () => {
              this.lf.graphModel.eventCenter.emit("custom:save", true);
            },
          },
          {
            text: "清空",
            callback: () => {
              this.lf.graphModel.clearData();
              this.lf.render({
                nodes: [
                  {
                    id: this.rootId,
                    x: 200,
                    y: 200,
                    type: "center-node",
                    text: "会计事件",
                  },
                ],
              });
            },
          },
          {
            text: "回到中心",
            callback: () => {},
          },
        ],
      });
      this.$_registerNode();
    },
    // 自定义
    $_registerNode() {
      registerStart(this.lf);
      // 将自定义的节点挂载lf上
      registerUser(this.lf);
      registerEnd(this.lf);
      registerPush(this.lf, this.clickPlus, this.mouseDownPlus);
      registerDownload(this.lf);
      registerPolyline(this.lf);
      registerTask(this.lf);
      registerConnect(this.lf);
      this.$_render();
    },
    $_render() {
      this.lf.render(demoData);
      this.$_LfEvent();
    },
    $_getData() {
      const data = this.lf.getGraphData();
      console.log(JSON.stringify(data));
    },
    $_LfEvent() {
      this.lf.on("node:click", ({ data }) => {
        console.log("node:click", data);
        this.$data.clickNode = data;
        console.log(data);
        // this.$data.dialogVisible = true;
      });
      this.lf.on("node:dbclick", ({ data }) => {
        console.log("node:dbclick", data);
        this.$data.clickNode = data;
        // this.$data.dialogVisible = true;
      });
      this.lf.on("edge:click", ({ data }) => {
        console.log("edge:click", data);
        this.$data.clickNode = data;
        this.$data.dialogVisible = true;
      });
      this.lf.on("element:click", () => {
        this.hideAddPanel();
      });
      this.lf.on("node:onBtnClick", (value) => {
        console.log(value);
      });
      // this.lf.on("edge:add", ({ data }) => {
      //   console.log("edge:add", data);
      // });
      this.lf.on("node:mousemove", ({ data }) => {
        console.log("node:mousemove");
        this.moveData = data;
      });
      this.lf.on("blank:click", () => {
        this.hideAddPanel();
      });
      this.lf.on("connection:not-allowed", (data) => {
        this.$message({
          type: "error",
          message: data.msg,
        });
      });
      this.lf.on("node:mousemove", () => {
        console.log("on mousemove");
      });

      this.lf.on("node:drop,edge:exchange-node,edge:add", ({ data }) => {
        console.log("node:drop", data);
        // this.lf.updateText("49106603-2b88-4b2c-b1e8-723c1f2210bd", "ddddd");
      });
      this.lf.on("custom:onBtnClick", ({ type, props }) => {
        console.log(props);
        this.lf.setProperties(props.model.id, {
          isLastNode: true,
          type,
        });
        // 一键美化功能
        this.lf.extension.dagre &&
          this.lf.extension.dagre.layout({
            nodesep: 20,
            ranksep: 20,
          });
      });

      this.lf.graphModel.eventCenter.on("custom:save", () => {
        const { nodes, edges } = this.lf.getGraphData();
        console.log(nodes, edges);
        const res = this.convertResult(this.convertToTree(nodes, edges)).flat();
        console.log(res);
      });
    },
    clickPlus(e, attributes) {
      e.stopPropagation();
      console.log("clickPlus", e, attributes);
      const { clientX, clientY } = e;
      console.log(clientX, clientY);
      this.$data.addPanelStyle.top = clientY - 40 + "px";
      this.$data.addPanelStyle.left = clientX + "px";
      this.$data.showAddPanel = true;
      this.$data.addClickNode = attributes;
    },
    mouseDownPlus(e, attributes) {
      e.stopPropagation();
      console.log("mouseDownPlus", e, attributes);
    },
    hideAddPanel() {
      this.$data.showAddPanel = false;
      this.$data.addPanelStyle.top = 0;
      this.$data.addPanelStyle.left = 0;
      this.$data.addClickNode = null;
    },
    closeDialog() {
      this.$data.dialogVisible = false;
    },
    $_catData() {
      this.$data.graphData = this.$data.lf.getGraphData();
      this.$data.dataVisible = true;
    },
    goto() {
      this.$router.push("/TurboAdpter");
    },
    convertResult(data) {
      console.log(data);
      let result = [];
      const that = this;
      function transformNode(node) {
        const currRes = [];
        let baseKey = {};
        if (node.type) {
          baseKey = {
            data: node.data,
            type: node.type,
            id: node.id,
          };
        }

        if (node.id && node.type) {
          node.children.map((item) => {
            const curr = {
              ...baseKey,
              value: item.id,
            };
            if (item.children && item.children.length) {
              curr.children = [...that.convertResult(item)].flat();
            }
            currRes.push(curr);
          });
        }

        return currRes;
      }

      result = transformNode(data);
      return result;
    },

    convertToTree(nodes, edges) {
      // 创建一个空的树形结构
      const tree = {};

      // 遍历所有节点,将节点添加到树中
      nodes.forEach((node) => {
        tree[node.id] = {
          type: node.type,
          data: node?.text?.value || "",
          id: node.id,
          children: [],
        };
      });

      // 遍历所有边,将边连接的节点添加为子节点
      edges.forEach((edge) => {
        const sourceNode = tree[edge.sourceNodeId];
        const targetNode = tree[edge.targetNodeId];
        sourceNode.children.push(targetNode);
      });

      // 找到根节点并返回
      const root = Object.values(tree).find(
        (node) => !edges.some((edge) => edge.targetNodeId === node.id)
      );
      console.log(root);
      return root;
    },
  },
};
</script>
<style scoped>
.logic-flow-view {
  width: 100%;
  height: 80vh;
  display: flex;
  position: relative;
}
#LF-view {
  width: 100%;
  height: 100%;
  outline: none;
}
.demo-title {
  text-align: center;
  margin: 20px;
}
.demo-control {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 2;
}
.time-plus {
  cursor: pointer;
}
.add-panel {
  position: absolute;
  z-index: 11;
  background-color: white;
  padding: 10px 5px;
}
.el-drawer__body {
  height: 80%;
  overflow: auto;
  margin-top: -30px;
  z-index: 3;
}

@keyframes lf_animate_dash {
  to {
    stroke-dashoffset: 0;
  }
}
</style>


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值