feat: add flowChart components
25
package-lock.json
generated
@ -390,9 +390,18 @@
|
||||
}
|
||||
},
|
||||
"@logicflow/core": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npm.taobao.org/@logicflow/core/download/@logicflow/core-0.2.9.tgz",
|
||||
"integrity": "sha1-wTU8PV0P58QNm7jPq+PMbVmF5PE="
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@logicflow/core/-/core-0.3.0.tgz",
|
||||
"integrity": "sha512-FPRTuj0y6Yny+YDZ+faTzA8pZyouEWX1Vr6rH91wJR0J3NOHgb7pV/TJoHSosavFuyyw87nLw9UsyUUgHKVV+A=="
|
||||
},
|
||||
"@logicflow/extension": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@logicflow/extension/-/extension-0.3.0.tgz",
|
||||
"integrity": "sha512-vMmYT8H53oFhOpNftCYQMbNYbTiXqQUxOOKlPcrKkZb0FsXSiEZ/MUKBF3mAarvFlzdMaB5xJjakMfy07/bdvw==",
|
||||
"requires": {
|
||||
"@logicflow/core": "^0.3.0",
|
||||
"ids": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.4",
|
||||
@ -1235,6 +1244,11 @@
|
||||
"integrity": "sha1-xr5oWKvQE9do6YNmrkfiXViHsa4=",
|
||||
"dev": true
|
||||
},
|
||||
"ids": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ids/-/ids-1.0.0.tgz",
|
||||
"integrity": "sha512-Zvtq1xUto4LttpstyOlFum8lKx+i1OmRfg+6A9drFS9iSZsDPMHG4Sof/qwNR4kCU7jBeWFPrY2ocHxiz7cCRw=="
|
||||
},
|
||||
"indexes-of": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/indexes-of/download/indexes-of-1.0.1.tgz",
|
||||
@ -1958,6 +1972,11 @@
|
||||
"@vue/devtools-api": "^6.0.0-beta.7"
|
||||
}
|
||||
},
|
||||
"vue-json-pretty": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-2.0.2.tgz",
|
||||
"integrity": "sha512-Vn7SX3XR9cfvGRNoTDNID89GmvVUMb7/fLUX3C3n0Qptga0N7hp7Zwspui1I1XN5pE+PeoVghCSYty+bi8KnjA=="
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-4.0.6.tgz",
|
||||
|
@ -8,7 +8,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||
"@logicflow/core": "^0.2.9",
|
||||
"@logicflow/core": "^0.3.0",
|
||||
"@logicflow/extension": "^0.3.0",
|
||||
"@vueuse/core": "^4.8.1",
|
||||
"await-to-js": "^2.1.1",
|
||||
"axios": "^0.21.1",
|
||||
@ -27,6 +28,7 @@
|
||||
"v-contextmenu": "^3.0.0-alpha.4",
|
||||
"vue": "^3.0.11",
|
||||
"vue-i18n": "^9.1.2",
|
||||
"vue-json-pretty": "^2.0.2",
|
||||
"vue-router": "^4.0.6",
|
||||
"vue-types": "^3.0.2",
|
||||
"vuedraggable": "^4.0.1",
|
||||
|
0
src/components/FlowChart/index.ts
Normal file
115
src/components/FlowChart/src/AddPanel.vue
Normal file
@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<el-tabs tab-position="left">
|
||||
<el-tab-pane label="添加动作">
|
||||
<div v-for="item in nodeList" :key="item.type">
|
||||
<el-button
|
||||
class="add-node-btn"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="$_addNode(item)"
|
||||
>{{item.label}}</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="添加组">
|
||||
<el-button class="add-node-btn" type="primary" size="mini" @click="$_addTempalte">模板</el-button>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AddPanel',
|
||||
props: {
|
||||
nodeData: Object,
|
||||
lf: Object || String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nodeList: [
|
||||
{
|
||||
type: 'user',
|
||||
label: '用户'
|
||||
},
|
||||
{
|
||||
type: 'push',
|
||||
label: '推送'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
$_addNode(item) {
|
||||
const { lf, nodeData } = this.$props
|
||||
const { id, x, y } = nodeData
|
||||
const nextNode = lf.addNode({
|
||||
type: item.type,
|
||||
x: x + 150,
|
||||
y: y + 150
|
||||
})
|
||||
const nextId = nextNode.id
|
||||
lf.createEdge({ sourceNodeId: id, targetNodeId: nextId })
|
||||
this.$emit('addNodeFinish')
|
||||
},
|
||||
$_addTempalte() {
|
||||
const { lf, nodeData } = this.$props
|
||||
const { id, x, y } = nodeData
|
||||
const timeNode = lf.addNode({
|
||||
type: 'download',
|
||||
x,
|
||||
y: y + 150
|
||||
})
|
||||
const userNode = lf.addNode({
|
||||
type: 'user',
|
||||
x: x + 150,
|
||||
y: y + 150
|
||||
})
|
||||
const pushNode = lf.addNode({
|
||||
type: 'push',
|
||||
x: x + 150,
|
||||
y: y + 300,
|
||||
properties: {}
|
||||
})
|
||||
const endNode = lf.addNode({
|
||||
type: 'end',
|
||||
x: x + 300,
|
||||
y: y + 150
|
||||
})
|
||||
const endNode2 = lf.addNode({
|
||||
type: 'end',
|
||||
x: x + 300,
|
||||
y: y + 300
|
||||
})
|
||||
lf.createEdge({ sourceNodeId: id, targetNodeId: timeNode.id })
|
||||
lf.createEdge({ sourceNodeId: timeNode.id, targetNodeId: userNode.id })
|
||||
lf.createEdge({
|
||||
sourceNodeId: userNode.id,
|
||||
targetNodeId: endNode.id,
|
||||
endPoint: { x: x + 280, y: y + 150 },
|
||||
text: {
|
||||
value: 'Y',
|
||||
x: x + 230,
|
||||
y: y + 140
|
||||
}
|
||||
})
|
||||
lf.createEdge({
|
||||
sourceNodeId: userNode.id,
|
||||
targetNodeId: pushNode.id,
|
||||
text: {
|
||||
value: 'N',
|
||||
x: x + 160,
|
||||
y: y + 230
|
||||
}
|
||||
})
|
||||
lf.createEdge({ sourceNodeId: pushNode.id, targetNodeId: endNode2.id, endPoint: { x: x + 280, y: y + 300 } })
|
||||
this.$emit('addNodeFinish')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.add-node-btn {
|
||||
margin-bottom: 10px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
</style>
|
0
src/components/FlowChart/src/Bpmn.vue
Normal file
74
src/components/FlowChart/src/Control.vue
Normal file
@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button-group>
|
||||
<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>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Control',
|
||||
props: {
|
||||
lf: Object || String,
|
||||
catTurboData: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
undoDisable: true,
|
||||
redoDisable: true,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$props.lf.on('history:change', ({ data: { undoAble, redoAble } }) => {
|
||||
this.$data.undoDisable = !undoAble
|
||||
this.$data.redoDisable = !redoAble
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
$_zoomIn() {
|
||||
this.$props.lf.zoom(true)
|
||||
},
|
||||
$_zoomOut() {
|
||||
this.$props.lf.zoom(false)
|
||||
},
|
||||
$_zoomReset() {
|
||||
this.$props.lf.resetZoom()
|
||||
},
|
||||
$_translateRest() {
|
||||
this.$props.lf.resetTranslate()
|
||||
},
|
||||
$_reset() {
|
||||
this.$props.lf.resetZoom()
|
||||
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>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
22
src/components/FlowChart/src/DataDialog.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
<vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="graphData"></vue-json-pretty>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueJsonPretty from 'vue-json-pretty'
|
||||
import 'vue-json-pretty/lib/styles.css'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
graphData: Object
|
||||
},
|
||||
components: {
|
||||
VueJsonPretty,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
124
src/components/FlowChart/src/NodePanel.vue
Normal file
@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<div class="node-panel">
|
||||
<div class="node-item" v-for="item in nodeList" :key="item.text" @mousedown="$_dragNode(item)">
|
||||
<div class="node-item-icon" :class="item.class">
|
||||
<div v-if="item.type === 'user' || item.type === 'time'" class="shape"></div>
|
||||
</div>
|
||||
<span class="node-label">{{item.text}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'NodePanel',
|
||||
props: {
|
||||
lf: Object,
|
||||
nodeList: Array,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
node: {
|
||||
type: 'rect',
|
||||
property: {
|
||||
a: 'efrwe',
|
||||
b: 'wewe'
|
||||
}
|
||||
},
|
||||
properties: {
|
||||
a: 'efrwe',
|
||||
b: 'wewe'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
$_dragNode(item) {
|
||||
this.$props.lf.dnd.startDrag({
|
||||
type: item.type,
|
||||
properties: this.$data.properties
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.node-panel {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 50px;
|
||||
width: 70px;
|
||||
padding: 20px 10px;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px 1px rgb(228, 224, 219);
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
z-index: 101;
|
||||
}
|
||||
.node-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.node-item-icon {
|
||||
height: 30px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
background-size: cover;
|
||||
}
|
||||
.node-label {
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
user-select: none;
|
||||
}
|
||||
.node-start {
|
||||
background: url("./background/start.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.node-rect {
|
||||
border: 1px solid black;
|
||||
}
|
||||
.node-user {
|
||||
background: url("./background/user.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.node-time {
|
||||
background: url("./background/time.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.node-push {
|
||||
background: url("./background/push.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.node-download {
|
||||
background: url("./background/download.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.node-click {
|
||||
background: url("./background/click.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.node-end {
|
||||
background: url("./background/end.png") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.bpmn-start {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAAH6ji2bAAAABGdBTUEAALGPC/xhBQAAAnBJREFUOBGdVL1rU1EcPfdGBddmaZLiEhdx1MHZQXApraCzQ7GKLgoRBxMfcRELuihWKcXFRcEWF8HBf0DdDCKYRZpnl7p0svLe9Zzbd29eQhTbC8nv+9zf130AT63jvooOGS8Vf9Nt5zxba7sXQwODfkWpkbjTQfCGUd9gIp3uuPP8bZ946g56dYQvnBg+b1HB8VIQmMFrazKcKSvFW2dQTxJnJdQ77urmXWOMBCmXM2Rke4S7UAW+/8ywwFoewmBps2tu7mbTdp8VMOkIRAkKfrVawalJTtIliclFbaOBqa0M2xImHeVIfd/nKAfVq/LGnPss5Kh00VEdSzfwnBXPUpmykNss4lUI9C1ga+8PNrBD5YeqRY2Zz8PhjooIbfJXjowvQJBqkmEkVnktWhwu2SM7SMx7Cj0N9IC0oQXRo8xwAGzQms+xrB/nNSUWVveI48ayrFGyC2+E2C+aWrZHXvOuz+CiV6iycWe1Rd1Q6+QUG07nb5SbPrL4426d+9E1axKjY3AoRrlEeSQo2Eu0T6BWAAr6COhTcWjRaYfKG5csnvytvUr/WY4rrPMB53Uo7jZRjXaG6/CFfNMaXEu75nG47X+oepU7PKJvvzGDY1YLSKHJrK7vFUwXKkaxwhCW3u+sDFMVrIju54RYYbFKpALZAo7sB6wcKyyrd+aBMryMT2gPyD6GsQoRFkGHr14TthZni9ck0z+Pnmee460mHXbRAypKNy3nuMdrWgVKj8YVV8E7PSzp1BZ9SJnJAsXdryw/h5ctboUVi4AFiCd+lQaYMw5z3LGTBKjLQOeUF35k89f58Vv/tGh+l+PE/wG0rgfIUbZK5AAAAABJRU5ErkJggg==)
|
||||
center center no-repeat;
|
||||
cursor: grab;
|
||||
}
|
||||
.bpmn-end {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAAH6ji2bAAAABGdBTUEAALGPC/xhBQAAA1BJREFUOBFtVE1IVUEYPXOf+tq40Y3vPcmFIdSjIorWoRG0ERWUgnb5FwVhYQSl72oUoZAboxKNFtWiwKRN0M+jpfSzqJAQclHo001tKkjl3emc8V69igP3znzfnO/M9zcDcKT67azmjYWTwl9Vn7Vumeqzj1DVb6cleQY4oAVnIOPb+mKAGxQmKI5CWNJ2aLPatxWa3aB9K7/fB+/Z0jUF6TmMlFLQqrkECWQzOZxYGjTlOl8eeKaIY5yHnFn486xBustDjWT6dG7pmjHOJd+33t0iitTPkK6tEvjxq4h2MozQ6WFSX/LkDUGfFwfhEZj1Auz/U4pyAi5Sznd7uKzznXeVHlI/Aywmk6j7fsUsEuCGADrWARXXwjxWQsUbIupDHJI7kF5dRktg0eN81IbiZXiTESic50iwS+t1oJgL83jAiBupLDCQqwziaWSoAFSeIR3P5Xv5az00wyIn35QRYTwdSYbz8pH8fxUUAtxnFvYmEmgI0wYXUXcCCSpeEVpXlsRhBnCEATxWylL9+EKCAYhe1NGstUa6356kS9NVvt3DU2fd+Wtbm/+lSbylJqsqkSm9CRhvoJVlvKPvF1RKY/FcPn5j4UfIMLn8D4UYb54BNsilTDXKnF4CfTobA0FpoW/LSp306wkXM+XaOJhZaFkcNM82ASNAWMrhrUbRfmyeI1FvRBTpN06WKxa9BK0o2E4Pd3zfBBEwPsv9sQBnmLVbLEIZ/Xe9LYwJu/Er17W6HYVBc7vmuk0xUQ+pqxdom5Fnp55SiytXLPYoMXNM4u4SNSCFWnrVIzKG3EGyMXo6n/BQOe+bX3FClY4PwydVhthOZ9NnS+ntiLh0fxtlUJHAuGaFoVmttpVMeum0p3WEXbcll94l1wM/gZ0Ccczop77VvN2I7TlsZCsuXf1WHvWEhjO8DPtyOVg2/mvK9QqboEth+7pD6NUQC1HN/TwvydGBARi9MZSzLE4b8Ru3XhX2PBxf8E1er2A6516o0w4sIA+lwURhAON82Kwe2iDAC1Watq4XHaGQ7skLcFOtI5lDxuM2gZe6WFIotPAhbaeYlU4to5cuarF1QrcZ/lwrLaCJl66JBocYZnrNlvm2+MBCTmUymPrYZVbjdlr/BxlMjmNmNI3SAAAAAElFTkSuQmCC)
|
||||
center center no-repeat;
|
||||
cursor: grab;
|
||||
}
|
||||
.bpmn-user {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAEFVwZaAAAABGdBTUEAALGPC/xhBQAAAqlJREFUOBF9VM9rE0EUfrMJNUKLihGbpLGtaCOIR8VjQMGDePCgCCIiCNqzCAp2MyYUCXhUtF5E0D+g1t48qAd7CCLqQUQKEWkStcEfVGlLdp/fm3aW2QQdyLzf33zz5m2IsAZ9XhDpyaaIZkTS4ASzK41TFao88GuJ3hsr2pAbipHxuSYyKRugagICGANkfFnNh3HeE2N0b3nN2cgnpcictw5veJIzxmDamSlxxQZicq/mflxhbaH8BLRbuRwNtZp0JAhoplVRUdzmCe/vO27wFuuA3S5qXruGdboy5/PRGFsbFGKo/haRtQHIrM83bVeTrOgNhZReWaYGnE4aUQgTJNvijJFF4jQ8BxJE5xfKatZWmZcTQ+BVgh7s8SgPlCkcec4mGTmieTP4xd7PcpIEg1TX6gdeLW8rTVMVLVvb7ctXoH0Cydl2QOPJBG21STE5OsnbweVYzAnD3A7PVILuY0yiiyDwSm2g441r6rMSgp6iK42yqroI2QoXeJVeA+YeZSa47gZdXaZWQKTrG93rukk/l2Al6Kzh5AZEl7dDQy+JjgFahQjRopSxPbrbvK7GRe9ePWBo1wcU7sYrFZtavXALwGw/7Dnc50urrHJuTPSoO2IMV3gUQGNg87IbSOIY9BpiT9HV7FCZ94nPXb3MSnwHn/FFFE1vG6DTby+r31KAkUktB3Qf6ikUPWxW1BkXSPQeMHHiW0+HAd2GelJsZz1OJegCxqzl+CLVHa/IibuHeJ1HAKzhuDR+ymNaRFM+4jU6UWKXorRmbyqkq/D76FffevwdCp+jN3UAN/C9JRVTDuOxC/oh+EdMnqIOrlYteKSfadVRGLJFJPSB/ti/6K8f0CNymg/iH2gO/f0DwE0yjAFO6l8JaR5j0VPwPwfaYHqOqrCI319WzwhwzNW/aQAAAABJRU5ErkJggg==)
|
||||
center center no-repeat;
|
||||
cursor: grab;
|
||||
}
|
||||
.bpmn-exclusiveGateway {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAYAAAHeEJUAAAAABGdBTUEAALGPC/xhBQAAAvVJREFUOBGNVEFrE0EU/mY3bQoiFlOkaUJrQUQoWMGePLX24EH0IIoHKQiCV0G8iE1covgLiqA/QTzVm1JPogc9tIJYFaQtlhQxqYjSpunu+L7JvmUTU3AgmTfvffPNN++9WSA1DO182f6xwILzD5btfAoQmwL5KJEwiQyVbSVZ0IgRyV6PTpIJ81E5ZvqfHQR0HUOBHW4L5Et2kQ6Zf7iAOhTFAA8s0pEP7AXO1uAA52SbqGk6h/6J45LaLhO64ByfcUzM39V7ZiAdS2yCePPEIQYvTUHqM/n7dgQNfBKWPjpF4ISk8q3J4nB11qw6X8l+FsF3EhlkEMfrjIer3wJTLwS2aCNcj4DbGxXTw00JmAuO+Ni6bBxVUCvS5d9aa04+so4pHW5jLTywuXAL7jJ+D06sl82Sgl2JuVBQn498zkc2bGKxULHjCnSMadBKYDYYHAtsby1EQ5lNGrQd4Y3v4Zo0XdGEmDno46yCM9Tk+RiJmUYHS/aXHPNTcjxcbTFna000PFJHIVZ5lFRqRpJWk9/+QtlOUYJj9HG5pVFEU7zqIYDVsw2s+AJaD8wTd2umgSCCyUxgGsS1Y6TBwXQQTFuZaHcd8gAGioE90hlsY+wMcs30RduYtxanjMGal8H5dMW67dmT1JFtYUEe8LiQLRsPZ6IIc7A4J5tqco3T0pnv/4u0kyzrYUq7gASuEyI8VXKvB9Odytv6jS/PNaZBln0nioJG/AVQRZvApOdhjj3Jt8QC8Im09SafwdBdvIpztpxWxpeKCC+EsFdS8DCyuCn2munFpL7ctHKp+Xc5cMybeIyMAN33SPL3ZR9QV1XVwLyzHm6Iv0/yeUuUb7PPlZC4D4HZkeu6dpF4v9j9MreGtMbxMMRLIcjJic9yHi7WQ3yVKzZVWUr5UrViJvn1FfUlwe/KYVfYyWRLSGNu16hR01U9IacajXPei0wx/5BqgInvJN+MMNtNme7ReU9SBbgntovn0kKHpFg7UogZvaZiOue/q1SBo9ktHzQAAAAASUVORK5CYII=)
|
||||
center center no-repeat;
|
||||
cursor: grab;
|
||||
}
|
||||
</style>
|
166
src/components/FlowChart/src/adpterForTurbo.ts
Normal file
@ -0,0 +1,166 @@
|
||||
|
||||
const TurboType = {
|
||||
SEQUENCE_FLOW: 1,
|
||||
START_EVENT: 2,
|
||||
END_EVENT: 3,
|
||||
USER_TASK: 4,
|
||||
SERVICE_TASK: 5,
|
||||
EXCLUSIVE_GATEWAY: 6,
|
||||
}
|
||||
|
||||
function getTurboType(type) {
|
||||
switch (type) {
|
||||
case 'bpmn:sequenceFlow':
|
||||
return TurboType.SEQUENCE_FLOW
|
||||
case 'bpmn:startEvent':
|
||||
return TurboType.START_EVENT
|
||||
case 'bpmn:endEvent':
|
||||
return TurboType.END_EVENT
|
||||
case 'bpmn:userTask':
|
||||
return TurboType.USER_TASK
|
||||
case 'bpmn:serviceTask':
|
||||
return TurboType.SERVICE_TASK
|
||||
case 'bpmn:exclusiveGateway':
|
||||
return TurboType.EXCLUSIVE_GATEWAY
|
||||
default:
|
||||
return type
|
||||
}
|
||||
}
|
||||
|
||||
function convertNodeToTurboElement(node) {
|
||||
const { id, type, x, y, text = '', properties } = node
|
||||
return {
|
||||
incoming: [],
|
||||
outgoing: [],
|
||||
dockers: [],
|
||||
type: getTurboType(node.type),
|
||||
properties: {
|
||||
...properties,
|
||||
name: text && text.value || '',
|
||||
x: x,
|
||||
y: y,
|
||||
text,
|
||||
logicFlowType: type,
|
||||
},
|
||||
key: id,
|
||||
}
|
||||
}
|
||||
|
||||
function convertEdgeToTurboElement(edge) {
|
||||
const {
|
||||
id,
|
||||
type,
|
||||
sourceNodeId,
|
||||
targetNodeId,
|
||||
startPoint,
|
||||
endPoint,
|
||||
pointsList,
|
||||
text = '',
|
||||
properties } = edge
|
||||
return {
|
||||
incoming: [sourceNodeId],
|
||||
outgoing: [targetNodeId],
|
||||
type: getTurboType(type),
|
||||
dockers: [],
|
||||
properties: {
|
||||
...properties,
|
||||
name: text && text.value || '',
|
||||
text,
|
||||
startPoint,
|
||||
endPoint,
|
||||
pointsList,
|
||||
logicFlowType: type,
|
||||
},
|
||||
key: id,
|
||||
}
|
||||
}
|
||||
|
||||
export function toTurboData(data) {
|
||||
const nodeMap = new Map()
|
||||
const turboData = {
|
||||
flowElementList: [],
|
||||
}
|
||||
data.nodes.forEach((node) => {
|
||||
const flowElement = convertNodeToTurboElement(node)
|
||||
turboData.flowElementList.push(flowElement)
|
||||
nodeMap.set(node.id, flowElement)
|
||||
})
|
||||
data.edges.forEach((edge) => {
|
||||
const flowElement = convertEdgeToTurboElement(edge)
|
||||
const sourceElement = nodeMap.get(edge.sourceNodeId)
|
||||
sourceElement.outgoing.push(flowElement.key)
|
||||
const targetElement = nodeMap.get(edge.targetNodeId)
|
||||
targetElement.incoming.push(flowElement.key)
|
||||
turboData.flowElementList.push(flowElement)
|
||||
})
|
||||
return turboData
|
||||
}
|
||||
|
||||
|
||||
function convertFlowElementToEdge(element) {
|
||||
const { incoming, outgoing, properties, key } = element
|
||||
const {
|
||||
text,
|
||||
startPoint,
|
||||
endPoint,
|
||||
pointsList,
|
||||
logicFlowType
|
||||
} = properties
|
||||
const edge = {
|
||||
id: key,
|
||||
type: logicFlowType,
|
||||
sourceNodeId: incoming[0],
|
||||
targetNodeId: outgoing[0],
|
||||
text,
|
||||
startPoint,
|
||||
endPoint,
|
||||
pointsList,
|
||||
properties: {}
|
||||
}
|
||||
const excludeProperties = ['startPoint', 'endPoint', 'pointsList', 'text', 'logicFlowType']
|
||||
Object.keys(element.properties).forEach(property => {
|
||||
if (excludeProperties.indexOf(property) === -1) {
|
||||
edge.properties[property] = element.properties[property]
|
||||
}
|
||||
})
|
||||
return edge
|
||||
}
|
||||
|
||||
function convertFlowElementToNode(element) {
|
||||
const { properties, key } = element
|
||||
const { x, y, text, logicFlowType } = properties
|
||||
const node = {
|
||||
id: key,
|
||||
type: logicFlowType,
|
||||
x,
|
||||
y,
|
||||
text,
|
||||
properties: {}
|
||||
}
|
||||
const excludeProperties = ['x', 'y', 'text', 'logicFlowType']
|
||||
Object.keys(element.properties).forEach(property => {
|
||||
if (excludeProperties.indexOf(property) === -1) {
|
||||
node.properties[property] = element.properties[property]
|
||||
}
|
||||
})
|
||||
return node
|
||||
|
||||
}
|
||||
|
||||
export function toLogicflowData(data) {
|
||||
const lfData = {
|
||||
nodes: [],
|
||||
edges: [],
|
||||
}
|
||||
const list = data.flowElementList
|
||||
list && list.length > 0 && list.forEach(element => {
|
||||
if (element.type === TurboType.SEQUENCE_FLOW) {
|
||||
const edge = convertFlowElementToEdge(element)
|
||||
lfData.edges.push(edge)
|
||||
} else {
|
||||
const node = convertFlowElementToNode(element)
|
||||
lfData.nodes.push(node)
|
||||
}
|
||||
})
|
||||
return lfData
|
||||
}
|
BIN
src/components/FlowChart/src/background/click.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
src/components/FlowChart/src/background/download.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
src/components/FlowChart/src/background/end.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
src/components/FlowChart/src/background/push.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
src/components/FlowChart/src/background/start.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
src/components/FlowChart/src/background/time.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
src/components/FlowChart/src/background/user.png
Normal file
After Width: | Height: | Size: 40 KiB |
55
src/components/FlowChart/src/config.ts
Normal file
@ -0,0 +1,55 @@
|
||||
export const nodeList = [
|
||||
{
|
||||
text: '开始',
|
||||
type: 'start',
|
||||
class: 'node-start'
|
||||
},
|
||||
{
|
||||
text: '矩形',
|
||||
type: 'rect',
|
||||
class: 'node-rect'
|
||||
},
|
||||
{
|
||||
type: 'user',
|
||||
text: '用户',
|
||||
class: 'node-user'
|
||||
},
|
||||
{
|
||||
type: 'push',
|
||||
text: '推送',
|
||||
class: 'node-push'
|
||||
},
|
||||
{
|
||||
type: 'download',
|
||||
text: '位置',
|
||||
class: 'node-download'
|
||||
},
|
||||
{
|
||||
type: 'end',
|
||||
text: '结束',
|
||||
class: 'node-end'
|
||||
},
|
||||
]
|
||||
|
||||
export const BpmnNode = [
|
||||
{
|
||||
type: 'bpmn:startEvent',
|
||||
text: '开始',
|
||||
class: 'bpmn-start'
|
||||
},
|
||||
{
|
||||
type: 'bpmn:endEvent',
|
||||
text: '结束',
|
||||
class: 'bpmn-end'
|
||||
},
|
||||
{
|
||||
type: 'bpmn:exclusiveGateway',
|
||||
text: '网关',
|
||||
class: 'bpmn-exclusiveGateway'
|
||||
},
|
||||
{
|
||||
type: 'bpmn:userTask',
|
||||
text: '用户',
|
||||
class: 'bpmn-user'
|
||||
},
|
||||
]
|
@ -131,25 +131,24 @@ const routes: Array<RouteRecordRaw> = [
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/user',
|
||||
name: 'user',
|
||||
path: '/flowChart',
|
||||
name: 'flowChart',
|
||||
component: Layout,
|
||||
redirect: '/user/base',
|
||||
redirect: '/flowChart/index',
|
||||
children: [
|
||||
{
|
||||
path: '/user/base',
|
||||
component: () => import(/* webpackChunkName: "user" */ '../views/user.vue'),
|
||||
path: '/flowChart/index',
|
||||
component: () => import(/* webpackChunkName: "user" */ '../views/flow-chart/index.vue'),
|
||||
meta: {
|
||||
// icon: 'el-icon-user',
|
||||
title: 'baseinfo',
|
||||
title: 'flowChart',
|
||||
showLink: false,
|
||||
savedPosition: true
|
||||
}
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
icon: 'el-icon-user',
|
||||
title: 'usermanagement',
|
||||
icon: 'el-icon-set-up',
|
||||
title: 'flowChart',
|
||||
showLink: true,
|
||||
savedPosition: true
|
||||
}
|
||||
@ -178,6 +177,30 @@ const routes: Array<RouteRecordRaw> = [
|
||||
savedPosition: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/user',
|
||||
name: 'user',
|
||||
component: Layout,
|
||||
redirect: '/user/base',
|
||||
children: [
|
||||
{
|
||||
path: '/user/base',
|
||||
component: () => import(/* webpackChunkName: "user" */ '../views/user.vue'),
|
||||
meta: {
|
||||
// icon: 'el-icon-user',
|
||||
title: 'baseinfo',
|
||||
showLink: false,
|
||||
savedPosition: true
|
||||
}
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
icon: 'el-icon-user',
|
||||
title: 'usermanagement',
|
||||
showLink: true,
|
||||
savedPosition: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/error',
|
||||
name: 'error',
|
||||
|
@ -4,10 +4,18 @@
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>无缝滚动示例</span>
|
||||
<el-button class="button" type="text" @click="changeDirection('top')">向上滚动</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('bottom')">向下滚动</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('left')">向左滚动</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('right')">向右滚动</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('top')">
|
||||
<span :style="{color: classOption.direction === 'top' ? 'red' : ''}">向上滚动</span>
|
||||
</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('bottom')">
|
||||
<span :style="{color: classOption.direction === 'bottom' ? 'red' : ''}">向下滚动</span>
|
||||
</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('left')">
|
||||
<span :style="{color: classOption.direction === 'left' ? 'red' : ''}">向左滚动</span>
|
||||
</el-button>
|
||||
<el-button class="button" type="text" @click="changeDirection('right')">
|
||||
<span :style="{color: classOption.direction === 'right' ? 'red' : ''}">向右滚动</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<SeamlessScroll ref="scroll" :data="listData" :class-option="classOption" class="warp">
|
||||
|
272
src/views/flow-chart/dataTurbo.json
Normal file
@ -0,0 +1,272 @@
|
||||
{
|
||||
"flowElementList": [
|
||||
{
|
||||
"incoming": [],
|
||||
"outgoing": [
|
||||
"Flow_33inf2k"
|
||||
],
|
||||
"dockers": [],
|
||||
"type": 2,
|
||||
"properties": {
|
||||
"a": "efrwe",
|
||||
"b": "wewe",
|
||||
"name": "开始",
|
||||
"x": 280,
|
||||
"y": 200,
|
||||
"text": {
|
||||
"x": 280,
|
||||
"y": 200,
|
||||
"value": "开始"
|
||||
},
|
||||
"logicFlowType": "bpmn:startEvent"
|
||||
},
|
||||
"key": "Event_1d42u4p"
|
||||
},
|
||||
{
|
||||
"incoming": [
|
||||
"Flow_379e0o9"
|
||||
],
|
||||
"outgoing": [],
|
||||
"dockers": [],
|
||||
"type": 3,
|
||||
"properties": {
|
||||
"a": "efrwe",
|
||||
"b": "wewe",
|
||||
"name": "结束",
|
||||
"x": 920,
|
||||
"y": 200,
|
||||
"text": {
|
||||
"x": 920,
|
||||
"y": 200,
|
||||
"value": "结束"
|
||||
},
|
||||
"logicFlowType": "bpmn:endEvent"
|
||||
},
|
||||
"key": "Event_08p8i6q"
|
||||
},
|
||||
{
|
||||
"incoming": [
|
||||
"Flow_0pfouf0"
|
||||
],
|
||||
"outgoing": [
|
||||
"Flow_3918lhh"
|
||||
],
|
||||
"dockers": [],
|
||||
"type": 6,
|
||||
"properties": {
|
||||
"a": "efrwe",
|
||||
"b": "wewe",
|
||||
"name": "网关",
|
||||
"x": 580,
|
||||
"y": 200,
|
||||
"text": {
|
||||
"x": 580,
|
||||
"y": 200,
|
||||
"value": "网关"
|
||||
},
|
||||
"logicFlowType": "bpmn:exclusiveGateway"
|
||||
},
|
||||
"key": "Gateway_1fngqgj"
|
||||
},
|
||||
{
|
||||
"incoming": [
|
||||
"Flow_33inf2k"
|
||||
],
|
||||
"outgoing": [
|
||||
"Flow_0pfouf0"
|
||||
],
|
||||
"dockers": [],
|
||||
"type": 4,
|
||||
"properties": {
|
||||
"a": "efrwe",
|
||||
"b": "wewe",
|
||||
"name": "用户",
|
||||
"x": 420,
|
||||
"y": 200,
|
||||
"text": {
|
||||
"x": 420,
|
||||
"y": 200,
|
||||
"value": "用户"
|
||||
},
|
||||
"logicFlowType": "bpmn:userTask"
|
||||
},
|
||||
"key": "Activity_2mgtaia"
|
||||
},
|
||||
{
|
||||
"incoming": [
|
||||
"Flow_3918lhh"
|
||||
],
|
||||
"outgoing": [
|
||||
"Flow_379e0o9"
|
||||
],
|
||||
"dockers": [],
|
||||
"type": 5,
|
||||
"properties": {
|
||||
"a": "efrwe",
|
||||
"b": "wewe",
|
||||
"name": "服务",
|
||||
"x": 760,
|
||||
"y": 200,
|
||||
"text": {
|
||||
"x": 760,
|
||||
"y": 200,
|
||||
"value": "服务"
|
||||
},
|
||||
"logicFlowType": "bpmn:serviceTask"
|
||||
},
|
||||
"key": "Activity_1sp8qc8"
|
||||
},
|
||||
{
|
||||
"incoming": [
|
||||
"Event_1d42u4p"
|
||||
],
|
||||
"outgoing": [
|
||||
"Activity_2mgtaia"
|
||||
],
|
||||
"type": 1,
|
||||
"dockers": [],
|
||||
"properties": {
|
||||
"name": "边",
|
||||
"text": {
|
||||
"x": 331,
|
||||
"y": 200,
|
||||
"value": "边"
|
||||
},
|
||||
"startPoint": {
|
||||
"x": 298,
|
||||
"y": 200
|
||||
},
|
||||
"endPoint": {
|
||||
"x": 370,
|
||||
"y": 200
|
||||
},
|
||||
"pointsList": [
|
||||
{
|
||||
"x": 298,
|
||||
"y": 200
|
||||
},
|
||||
{
|
||||
"x": 370,
|
||||
"y": 200
|
||||
}
|
||||
],
|
||||
"logicFlowType": "bpmn:sequenceFlow"
|
||||
},
|
||||
"key": "Flow_33inf2k"
|
||||
},
|
||||
{
|
||||
"incoming": [
|
||||
"Activity_2mgtaia"
|
||||
],
|
||||
"outgoing": [
|
||||
"Gateway_1fngqgj"
|
||||
],
|
||||
"type": 1,
|
||||
"dockers": [],
|
||||
"properties": {
|
||||
"name": "边2",
|
||||
"text": {
|
||||
"x": 507,
|
||||
"y": 200,
|
||||
"value": "边2"
|
||||
},
|
||||
"startPoint": {
|
||||
"x": 470,
|
||||
"y": 200
|
||||
},
|
||||
"endPoint": {
|
||||
"x": 555,
|
||||
"y": 200
|
||||
},
|
||||
"pointsList": [
|
||||
{
|
||||
"x": 470,
|
||||
"y": 200
|
||||
},
|
||||
{
|
||||
"x": 555,
|
||||
"y": 200
|
||||
}
|
||||
],
|
||||
"logicFlowType": "bpmn:sequenceFlow"
|
||||
},
|
||||
"key": "Flow_0pfouf0"
|
||||
},
|
||||
{
|
||||
"incoming": [
|
||||
"Gateway_1fngqgj"
|
||||
],
|
||||
"outgoing": [
|
||||
"Activity_1sp8qc8"
|
||||
],
|
||||
"type": 1,
|
||||
"dockers": [],
|
||||
"properties": {
|
||||
"name": "边3",
|
||||
"text": {
|
||||
"x": 664,
|
||||
"y": 200,
|
||||
"value": "边3"
|
||||
},
|
||||
"startPoint": {
|
||||
"x": 605,
|
||||
"y": 200
|
||||
},
|
||||
"endPoint": {
|
||||
"x": 710,
|
||||
"y": 200
|
||||
},
|
||||
"pointsList": [
|
||||
{
|
||||
"x": 605,
|
||||
"y": 200
|
||||
},
|
||||
{
|
||||
"x": 710,
|
||||
"y": 200
|
||||
}
|
||||
],
|
||||
"logicFlowType": "bpmn:sequenceFlow"
|
||||
},
|
||||
"key": "Flow_3918lhh"
|
||||
},
|
||||
{
|
||||
"incoming": [
|
||||
"Activity_1sp8qc8"
|
||||
],
|
||||
"outgoing": [
|
||||
"Event_08p8i6q"
|
||||
],
|
||||
"type": 1,
|
||||
"dockers": [],
|
||||
"properties": {
|
||||
"name": "边4",
|
||||
"text": {
|
||||
"x": 871,
|
||||
"y": 200,
|
||||
"value": "边4"
|
||||
},
|
||||
"startPoint": {
|
||||
"x": 810,
|
||||
"y": 200
|
||||
},
|
||||
"endPoint": {
|
||||
"x": 902,
|
||||
"y": 200
|
||||
},
|
||||
"pointsList": [
|
||||
{
|
||||
"x": 810,
|
||||
"y": 200
|
||||
},
|
||||
{
|
||||
"x": 902,
|
||||
"y": 200
|
||||
}
|
||||
],
|
||||
"logicFlowType": "bpmn:sequenceFlow"
|
||||
},
|
||||
"key": "Flow_379e0o9"
|
||||
}
|
||||
]
|
||||
}
|
132
src/views/flow-chart/index.vue
Normal file
@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div class="logic-flow-view">
|
||||
<!-- 辅助工具栏 -->
|
||||
<Control
|
||||
class="demo-control"
|
||||
v-if="lf"
|
||||
:lf="lf"
|
||||
:catTurboData="false"
|
||||
@catData="$_catData"
|
||||
@catTurboData="$_catTurboData"
|
||||
></Control>
|
||||
<!-- 节点面板 -->
|
||||
<NodePanel :lf="lf" :nodeList="nodeList"></NodePanel>
|
||||
<!-- 画布 -->
|
||||
<div id="LF-Turbo"></div>
|
||||
<!-- 数据查看面板 -->
|
||||
<el-dialog title="数据" v-model="dataVisible" width="50%">
|
||||
<DataDialog :graphData="graphData"></DataDialog>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import LogicFlow from '@logicflow/core'
|
||||
import { Snapshot, BpmnElement } from '@logicflow/extension'
|
||||
import '@logicflow/core/dist/style/index.css'
|
||||
import '@logicflow/extension/lib/style/index.css'
|
||||
import NodePanel from '/@/components/FlowChart/src/NodePanel.vue'
|
||||
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'
|
||||
|
||||
export default {
|
||||
name: 'LF',
|
||||
components: { NodePanel, Control, DataDialog },
|
||||
data() {
|
||||
return {
|
||||
lf: null,
|
||||
dialogVisible: false,
|
||||
graphData: null,
|
||||
dataVisible: false,
|
||||
config: {
|
||||
grid: true,
|
||||
background: {
|
||||
color: '#f7f9ff'
|
||||
},
|
||||
keyboard: {
|
||||
enabled: true
|
||||
},
|
||||
},
|
||||
nodeList: BpmnNode,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$_initLf()
|
||||
},
|
||||
methods: {
|
||||
$_initLf() {
|
||||
// 画布配置
|
||||
LogicFlow.use(Snapshot)
|
||||
// 使用bpmn插件,引入bpmn元素,这些元素可以在turbo中转换后使用
|
||||
LogicFlow.use(BpmnElement)
|
||||
const lf = new LogicFlow({ ...this.config, container: document.querySelector('#LF-Turbo') })
|
||||
this.lf = lf
|
||||
// 设置边类型bpmn:sequenceFlow为默认类型
|
||||
lf.setDefaultEdgeType('bpmn:sequenceFlow')
|
||||
this.$_render()
|
||||
},
|
||||
$_render() {
|
||||
// Turbo数据转换为LogicFlow内部识别的数据结构
|
||||
const lFData = toLogicflowData(demoData)
|
||||
this.lf.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('/')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.logic-flow-view {
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
.demo-title {
|
||||
text-align: center;
|
||||
margin: 20px;
|
||||
}
|
||||
.demo-control {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 100px;
|
||||
z-index: 2;
|
||||
}
|
||||
#LF-Turbo {
|
||||
width: 100vw;
|
||||
height: 85%;
|
||||
outline: none;
|
||||
margin: 10px 0 0 10px;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
|