有很多功能没有完善,开发了30%记录一下,但是大概自己改改能用
创建自定义组件(未完成)
import Vue from 'vue';
import Vnode from './Vnode.vue';
export default function registerUser(lf) {
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) {
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组件(未完成)
<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,创建实例
<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";
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);
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.lf.on("node:dbclick", ({ data }) => {
console.log("node:dbclick", data);
this.$data.clickNode = data;
});
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("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.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>