fix: Improve the flowChart component

This commit is contained in:
xiaoxian521 2021-04-17 00:35:12 +08:00
parent 5ec1f62f8d
commit ba41753d77
7 changed files with 195 additions and 235 deletions

View File

@ -0,0 +1,22 @@
import { App } from "vue"
import control from "./src/Control.vue"
import nodePanel from "./src/NodePanel.vue"
import dataDialog from "./src/DataDialog.vue"
export const Control = Object.assign(control, {
install(app: App) {
app.component(control.name, control)
}
})
export const NodePanel = Object.assign(nodePanel, {
install(app: App) {
app.component(nodePanel.name, nodePanel)
}
})
export const DataDialog = Object.assign(dataDialog, {
install(app: App) {
app.component(dataDialog.name, dataDialog)
}
})

View File

@ -1,5 +1,6 @@
<template> <template>
<div class="control-container"> <div class="control-container">
<!-- 功能按钮 -->
<ul> <ul>
<li <li
v-for="(item,key) in titleLists" v-for="(item,key) in titleLists"
@ -9,117 +10,111 @@
@mouseenter.prevent="onEnter(key)" @mouseenter.prevent="onEnter(key)"
@mouseleave.prevent="focusIndex = -1" @mouseleave.prevent="focusIndex = -1"
> >
<button ref="controlButton" @click="onControl(item,key)"> <button
:ref="'controlButton' + key"
:disabled="item.disabled"
:style="{cursor: item.disabled === false ? 'pointer' : 'not-allowed'}"
@click="onControl(item,key)"
>
<span :class="'iconfont ' + item.icon"></span> <span :class="'iconfont ' + item.icon"></span>
<p>{{ item.text }}</p> <p>{{ item.text }}</p>
</button> </button>
</li> </li>
</ul> </ul>
<!-- <el-button size="small" @click="$_zoomIn">放大</el-button>
<el-button size="small" @click="$_zoomOut">缩小</el-button>
<el-button size="small" @click="$_zoomReset">大小适应</el-button>
<el-button size="small" @click="$_translateRest">定位还原</el-button>
<el-button size="small" @click="$_reset">还原(大小&定位)</el-button>
<el-button size="small" @click="$_undo" :disabled="undoDisable">上一步(ctrl+z)</el-button>
<el-button size="small" @click="$_redo" :disabled="redoDisable">下一步(ctrl+y)</el-button>
<el-button size="small" @click="$_download">下载图片</el-button>
<el-button size="small" @click="$_catData">查看数据</el-button>
<el-button v-if="catTurboData" size="small" @click="$_catTurboData">查看turbo数据</el-button>-->
</div> </div>
</template> </template>
<script> <script lang='ts'>
export default { import { defineComponent ,ref, unref, onMounted } from "vue";
import { templateRef } from '@vueuse/core'
export default defineComponent({
name: "Control", name: "Control",
props: { props: {
lf: Object || String, lf: Object || String,
catTurboData: Boolean, catTurboData: Boolean,
}, },
data() { emits: ["catData"],
return { setup(props,{emit}) {
undoDisable: true, const controlButton3 = templateRef<HTMLElement | null>('controlButton3', null)
redoDisable: true, const controlButton4 = templateRef<HTMLElement | null>('controlButton4', null)
focusIndex: -1,
titleLists: [ let focusIndex = ref(-1)
let titleLists = ref([
{ {
icon: "icon-zoom-out-hs", icon: "icon-zoom-out-hs",
text: "缩小", text: "缩小",
disabled: false
}, },
{ {
icon: "icon-enlarge-hs", icon: "icon-enlarge-hs",
text: "放大", text: "放大",
disabled: false
}, },
{ {
icon: "icon-full-screen-hs", icon: "icon-full-screen-hs",
text: "适应", text: "适应",
disabled: false
}, },
{ {
icon: "icon-previous-hs", icon: "icon-previous-hs",
text: "上一步", text: "上一步",
disabled: true
}, },
{ {
icon: "icon-next-step-hs", icon: "icon-next-step-hs",
text: "下一步", text: "下一步",
disabled: true
}, },
], {
}; icon: "icon-download-hs",
}, text: "下载图片",
mounted() { disabled: false
this.$props.lf.on("history:change", ({ data: { undoAble, redoAble } }) => { },
this.$data.undoDisable = !undoAble; {
this.$data.redoDisable = !redoAble; icon: "icon-watch-hs",
}); text: "查看数据",
}, disabled: false
methods: { },
onControl(item, key) { ])
["zoom", "zoom", "resetZoom", "undo", "redo"].forEach((v, i) => {
let domControl = this.$props.lf; const onControl = (item, key) => {
["zoom", "zoom", "resetZoom", "undo", "redo", "getSnapshot"].forEach((v, i) => {
let domControl = props.lf
if (key === 1) { if (key === 1) {
domControl.zoom(true); domControl.zoom(true)
}
if (key === 6) {
emit("catData")
} }
if (key === i) { if (key === i) {
domControl[v](); domControl[v]()
} }
}); })
}, }
onEnter(key) {
this.focusIndex = key; const onEnter = (key) => {
}, focusIndex.value = key
$_zoomIn() { }
this.$props.lf.zoom(true);
}, onMounted(()=>{
$_zoomOut() { props.lf.on("history:change", ({ data: { undoAble, redoAble } }) => {
this.$props.lf.zoom(false); unref(titleLists)[3].disabled = unref(controlButton3).disabled = !undoAble
}, unref(titleLists)[4].disabled = unref(controlButton4).disabled = !redoAble
$_zoomReset() { })
this.$props.lf.resetZoom(); })
},
$_translateRest() { return {
this.$props.lf.resetTranslate(); focusIndex,
}, titleLists,
$_reset() { onControl,
this.$props.lf.resetZoom(); onEnter
this.$props.lf.resetTranslate(); };
},
$_undo() {
this.$props.lf.undo();
},
$_redo() {
this.$props.lf.redo();
},
$_download() {
this.$props.lf.getSnapshot();
},
$_catData() {
this.$emit("catData");
},
$_catTurboData() {
this.$emit("catTurboData");
},
}, },
}; });
</script> </script>
<style scoped> <style scoped>
@import "./assets/iconfont/iconfont.css"; @import "./assets/iconfont/iconfont.css";
.control-container { .control-container {
@ -127,7 +122,6 @@ export default {
right: 20px; right: 20px;
background: hsla(0, 0%, 100%, 0.8); background: hsla(0, 0%, 100%, 0.8);
box-shadow: 0 1px 4px rgb(0 0 0 / 30%); box-shadow: 0 1px 4px rgb(0 0 0 / 30%);
border-radius: 5px;
} }
.iconfont { .iconfont {
font-size: 25px; font-size: 25px;
@ -145,7 +139,10 @@ export default {
.control-container ul li { .control-container ul li {
width: 60px; width: 60px;
text-align: center; text-align: center;
cursor: pointer; }
/* pointer-events: none; */ .control-container ul li button {
border: none;
background-color: transparent;
outline: none;
} }
</style> </style>

View File

@ -1,22 +1,18 @@
<template> <template>
<div> <vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="graphData"></vue-json-pretty>
<vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="graphData"></vue-json-pretty>
</div>
</template> </template>
<script> <script lang='ts'>
import VueJsonPretty from 'vue-json-pretty' import VueJsonPretty from "vue-json-pretty";
import 'vue-json-pretty/lib/styles.css' import "vue-json-pretty/lib/styles.css";
import { defineComponent } from "vue";
export default { export default defineComponent({
name: "DataDialog",
props: { props: {
graphData: Object graphData: Object
}, },
components: { components: {
VueJsonPretty, VueJsonPretty
}, }
}; });
</script> </script>
<style scoped>
</style>

View File

@ -1,6 +1,12 @@
<template> <template>
<!-- 左侧bpmn元素选择器 -->
<div class="node-panel"> <div class="node-panel">
<div class="node-item" v-for="item in nodeList" :key="item.text" @mousedown="$_dragNode(item)"> <div
class="node-item"
v-for="item in nodeList"
:key="item.text"
@mousedown="nodeDragNode(item)"
>
<div class="node-item-icon" :class="item.class"> <div class="node-item-icon" :class="item.class">
<div v-if="item.type === 'user' || item.type === 'time'" class="shape"></div> <div v-if="item.type === 'user' || item.type === 'time'" class="shape"></div>
</div> </div>
@ -9,40 +15,45 @@
</div> </div>
</template> </template>
<script> <script lang='ts'>
export default { import { defineComponent, ref, unref } from "vue";
name: 'NodePanel', export default defineComponent({
name: "NodePanel",
props: { props: {
lf: Object, lf: Object,
nodeList: Array, nodeList: Array
}, },
data() { setup(props) {
return { let node = ref({
node: { type: "rect",
type: 'rect', property: {
property: { a: "efrwe",
a: 'efrwe', b: "wewe"
b: 'wewe'
}
},
properties: {
a: 'efrwe',
b: 'wewe'
} }
} });
}, let properties = ref({
methods: { a: "efrwe",
$_dragNode(item) { b: "wewe"
this.$props.lf.dnd.startDrag({ });
const nodeDragNode = item => {
props.lf.dnd.startDrag({
type: item.type, type: item.type,
properties: this.$data.properties properties: unref(properties)
}) });
} };
return {
node,
properties,
nodeDragNode
};
} }
} });
</script> </script>
<style>
<style scoped>
.node-panel { .node-panel {
position: absolute; position: absolute;
top: 100px; top: 100px;

View File

@ -1,60 +0,0 @@
<template>
<div id="container"></div>
</template>
<script lang='ts'>
import LogicFlow from "@logicflow/core";
import "@logicflow/core/dist/style/index.css";
import { onMounted } from "vue";
const data = {
//
nodes: [
{
id: 50,
type: "rect",
x: 100,
y: 150,
text: "你好",
},
{
id: 21,
type: "circle",
x: 300,
y: 150,
},
],
//
edges: [
{
type: "polyline",
sourceNodeId: 50,
targetNodeId: 21,
},
],
};
export default {
setup() {
onMounted(() => {
const lf = new LogicFlow({
container: document.querySelector("#container"),
stopScrollGraph: true,
stopZoomGraph: true,
width: 500,
height: 500,
grid: {
type: "dot",
size: 20,
},
});
lf.render(data);
});
return {};
},
};
</script>
<style scoped>
</style>

View File

@ -6,8 +6,7 @@
v-if="lf" v-if="lf"
:lf="lf" :lf="lf"
:catTurboData="false" :catTurboData="false"
@catData="$_catData" @catData="catData"
@catTurboData="$_catTurboData"
></Control> ></Control>
<!-- 节点面板 --> <!-- 节点面板 -->
<NodePanel :lf="lf" :nodeList="nodeList"></NodePanel> <NodePanel :lf="lf" :nodeList="nodeList"></NodePanel>
@ -19,28 +18,25 @@
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script>
<script lang='ts'>
import { ref, unref, onMounted, nextTick } from "vue"
import LogicFlow from '@logicflow/core' import LogicFlow from '@logicflow/core'
import { Snapshot, BpmnElement } from '@logicflow/extension' import { Snapshot, BpmnElement } from '@logicflow/extension'
import '@logicflow/core/dist/style/index.css' import '@logicflow/core/dist/style/index.css'
import '@logicflow/extension/lib/style/index.css' import '@logicflow/extension/lib/style/index.css'
import NodePanel from '/@/components/FlowChart/src/NodePanel.vue' import { Control, NodePanel, DataDialog } from '/@/components/FlowChart'
import Control from '/@/components/FlowChart/src/Control.vue'
import DataDialog from '/@/components/FlowChart/src/DataDialog.vue'
import { toTurboData, toLogicflowData } from '/@/components/FlowChart/src/adpterForTurbo.ts'
import { BpmnNode } from '/@/components/FlowChart/src/config.ts'
import demoData from './dataTurbo.json'
import { toTurboData, toLogicflowData } from '/@/components/FlowChart/src/adpterForTurbo'
import { BpmnNode } from '/@/components/FlowChart/src/config'
import demoData from './dataTurbo.json'
export default { export default {
name: 'LF',
components: { NodePanel, Control, DataDialog }, components: { NodePanel, Control, DataDialog },
data() { setup() {
return { let lf = ref(null)
lf: null, let graphData =ref(null)
dialogVisible: false, let dataVisible = ref(false)
graphData: null, let config = ref({
dataVisible: false,
config: {
grid: true, grid: true,
background: { background: {
color: '#f7f9ff' color: '#f7f9ff'
@ -48,51 +44,54 @@ export default {
keyboard: { keyboard: {
enabled: true enabled: true
}, },
}, })
nodeList: BpmnNode, let nodeList= BpmnNode
}
}, function initLf() {
mounted() {
this.$_initLf()
},
methods: {
$_initLf() {
// //
LogicFlow.use(Snapshot) LogicFlow.use(Snapshot)
// 使bpmnbpmnturbo使 // 使bpmnbpmnturbo使
LogicFlow.use(BpmnElement) LogicFlow.use(BpmnElement)
const lf = new LogicFlow({ ...this.config, container: document.querySelector('#LF-Turbo') }) const domLf = new LogicFlow({ ...unref(config), container: document.querySelector('#LF-Turbo') })
this.lf = lf lf.value = domLf
// bpmn:sequenceFlow // bpmn:sequenceFlow
lf.setDefaultEdgeType('bpmn:sequenceFlow') unref(lf).setDefaultEdgeType('bpmn:sequenceFlow')
this.$_render() onRender()
}, }
$_render() {
function onRender() {
// TurboLogicFlow // TurboLogicFlow
const lFData = toLogicflowData(demoData) const lFData = toLogicflowData(demoData)
this.lf.render(lFData) lf.value.render(lFData)
},
closeDialog() {
this.$data.dialogVisible = false
},
$_catData() {
this.$data.graphData = this.$data.lf.getGraphData()
this.$data.dataVisible = true
},
$_catTurboData() {
debugger
const graphData = this.$data.lf.getGraphData()
// Turbo
this.$data.graphData = toTurboData(graphData)
this.$data.dataVisible = true
},
goto() {
this.$router.push('/')
} }
}
} function catData() {
graphData.value = unref(lf).getGraphData()
dataVisible.value = true
}
onMounted(()=>{
initLf()
})
return {
lf,
graphData,
dataVisible,
config,
nodeList,
catData
};
},
};
</script> </script>
<style>
<style scoped>
#LF-Turbo {
width: 100vw;
height: 85%;
outline: none;
}
.logic-flow-view { .logic-flow-view {
height: 100%; height: 100%;
position: relative; position: relative;
@ -107,11 +106,6 @@ export default {
right: 20px; right: 20px;
z-index: 2; z-index: 2;
} }
#LF-Turbo {
width: 100vw;
height: 85%;
outline: none;
}
.time-plus { .time-plus {
cursor: pointer; cursor: pointer;
} }