366 lines
8.9 KiB
Vue
366 lines
8.9 KiB
Vue
<template>
|
|
<div class="node-item" ref="node"
|
|
:class="[(isActive || isSelected) ? 'active' : '']"
|
|
:style="flowNodeContainer"
|
|
v-click-outside="setNotActive"
|
|
@click="setActive"
|
|
@mouseenter="showAnchor"
|
|
@mouseleave="hideAnchor"
|
|
@dblclick.prevent="findDisposition()"
|
|
@contextmenu.prevent="onContextmenu">
|
|
<div class="log-wrap">
|
|
<img :src="node.logImg" alt="">
|
|
</div>
|
|
<div class="nodeName">{{node.nodeName}}</div>
|
|
<!--连线用--//触发连线的区域-->
|
|
<div class="node-anchor anchor-top" v-show="mouseEnter"></div>
|
|
<div class="node-anchor anchor-right" v-show="mouseEnter"></div>
|
|
<div class="node-anchor anchor-bottom" v-show="mouseEnter"></div>
|
|
<div class="node-anchor anchor-left" v-show="mouseEnter"></div>
|
|
<div align="center">
|
|
<DispFind :data="data" :node="node" :disp="disp" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import ClickOutside from 'vue-click-outside'
|
|
import Home from '../Home.vue'
|
|
import {listDbTableAll, selDbNameAll, selectDbTableColumnsByName} from "@/api/tool/gen";
|
|
import {listDisposition} from "@/api/quest/disposition";
|
|
import DispFind from "./node/dispFind.vue";
|
|
|
|
|
|
export default {
|
|
name: "nodeItem",
|
|
components: {
|
|
DispFind,
|
|
},
|
|
props: {
|
|
data: {},
|
|
node: Object
|
|
},
|
|
directives: {
|
|
ClickOutside
|
|
},
|
|
computed: {
|
|
// 节点容器样式
|
|
flowNodeContainer: {
|
|
get() {
|
|
return {
|
|
top: this.node.top,
|
|
left: this.node.left
|
|
};
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
mouseEnter: false,
|
|
isActive: false,
|
|
isSelected: false,
|
|
disp: {
|
|
nodeCode: undefined,
|
|
nodeType: undefined,
|
|
findFlag: false,
|
|
updFlag: false,
|
|
formData: {
|
|
db: {},
|
|
fields: []
|
|
}
|
|
}
|
|
};
|
|
},
|
|
methods: {
|
|
showAnchor() {
|
|
this.mouseEnter = true
|
|
},
|
|
hideAnchor() {
|
|
this.mouseEnter = false
|
|
},
|
|
// 右击菜单
|
|
onContextmenu() {
|
|
this.$contextmenu({
|
|
items: [
|
|
{
|
|
label: '修改名称',
|
|
disabled: false,
|
|
icon: "",
|
|
onClick: () => {
|
|
this.toUpdName();
|
|
}
|
|
},{
|
|
label: '删除节点',
|
|
disabled: false,
|
|
icon: "",
|
|
onClick: () => {
|
|
this.deleteNode()
|
|
}
|
|
}
|
|
],
|
|
event,
|
|
customClass: 'custom-class',
|
|
zIndex: 9999,
|
|
minWidth: 180
|
|
})
|
|
},
|
|
setActive() {
|
|
if (window.event.ctrlKey) {
|
|
this.isSelected = !this.isSelected
|
|
return false
|
|
}
|
|
this.isActive = true
|
|
this.isSelected = false
|
|
setTimeout(() => {
|
|
this.$emit("changeLineState", this.node.id, true)
|
|
}, 0)
|
|
},
|
|
setNotActive() {
|
|
if (!window.event.ctrlKey) {
|
|
this.isSelected = false
|
|
}
|
|
if (!this.isActive) {
|
|
return
|
|
}
|
|
this.$emit("changeLineState", this.node.id, false)
|
|
this.isActive = false
|
|
},
|
|
// 修改名称
|
|
toUpdName() {
|
|
this.$prompt('请输入新名称', '更改名称', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消'
|
|
}).then(({ value }) => {
|
|
this.$emit('setNodeName', this.node.id, value)
|
|
this.$message({
|
|
type: 'success',
|
|
message: '修改成功'
|
|
});
|
|
this.$emit("checkFlag")
|
|
}).catch(() => {
|
|
this.$message({
|
|
type: 'info',
|
|
message: '操作取消'
|
|
});
|
|
});
|
|
},
|
|
// 选择删除节点
|
|
deleteNode() {
|
|
this.$confirm('确认删除该节点吗?', '删除提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
this.$emit("deleteNode", this.node)
|
|
this.$message({
|
|
type: 'success',
|
|
message: '删除成功'
|
|
});
|
|
}).catch(() => {
|
|
this.$message({
|
|
type: 'info',
|
|
message: '操作取消'
|
|
});
|
|
});
|
|
},
|
|
// 双击触发-查看配置
|
|
findDisposition() {
|
|
let type = this.node.type
|
|
if (type === 'start' || type === 'end'){
|
|
this.toUpdName()
|
|
return
|
|
}
|
|
// 查询节点配置信息
|
|
this.disp.nodeCode = this.node.id
|
|
this.disp.findFlag = true
|
|
listDisposition({nodeCode: this.node.id}).then(res => {
|
|
this.disp.formData = this.getVueDisp(res.data.rows)
|
|
})
|
|
},
|
|
/** jsPlumb节点类型 --> 数据库节点类型 */
|
|
toMysqlNode(node,preLine,nextLine,taskCode){
|
|
return {
|
|
nodeType: node.type,
|
|
taskCode: taskCode,
|
|
nodeCode: node.id,
|
|
nodeName: node.nodeName,
|
|
nodePositionTop: node.top,
|
|
nodePositionLeft: node.left,
|
|
nodePreCode: preLine,
|
|
nodeNextCode: nextLine,
|
|
state: 'Y'
|
|
}
|
|
},
|
|
/** 数据库节点类型 --> jsPlumb节点类型 */
|
|
toJsPlumbNode(nodeInfo){
|
|
const node = {
|
|
id: nodeInfo.nodeCode,
|
|
type: nodeInfo.nodeType,
|
|
nodeName: nodeInfo.nodeName,
|
|
top: nodeInfo.nodePositionTop,
|
|
left: nodeInfo.nodePositionLeft
|
|
}
|
|
const line = []
|
|
// 节点有后继节点
|
|
if (nodeInfo.nodeNextCode){
|
|
const nextLine = {
|
|
from: nodeInfo.nodeCode,
|
|
to: nodeInfo.nodeNextCode
|
|
}
|
|
line.push(nextLine)
|
|
}
|
|
// 节点有前驱节点
|
|
if (nodeInfo.nodePreCode){
|
|
const perLine = {
|
|
from: nodeInfo.nodePreCode,
|
|
to: nodeInfo.nodeCode
|
|
}
|
|
line.push(perLine)
|
|
}
|
|
return {
|
|
node: node,
|
|
line: line
|
|
}
|
|
},
|
|
/** 类型转换 mysql -> vue */
|
|
getVueDisp(dispList) {
|
|
let type = this.node.type
|
|
const db = {}
|
|
const fields = []
|
|
if (type === 'table'){
|
|
dispList.forEach(disp => {
|
|
if (disp.dispKey === 'db'){
|
|
db.dbName = disp.dispValue
|
|
}
|
|
if (disp.dispKey === 'table'){
|
|
db.tableName = disp.dispValue
|
|
db.tableComment = disp.dispLabel
|
|
}
|
|
if (disp.dispKey === 'fields'){
|
|
fields.push({
|
|
fieldName: disp.dispValue,
|
|
fieldType: disp.dispType,
|
|
fieldComment: disp.dispLabel
|
|
})
|
|
}
|
|
})
|
|
}
|
|
if (type === 'exportation') {
|
|
let i = 0
|
|
let j = 0
|
|
dispList.forEach(disp => {
|
|
if (disp.dispKey === 'formDb'){
|
|
db.formDb = disp.dispValue
|
|
}
|
|
if (disp.dispKey === 'formTable'){
|
|
db.formTable = disp.dispValue
|
|
db.formTableComment = disp.dispLabel
|
|
}
|
|
if (disp.dispKey === 'toDb'){
|
|
db.toDb = disp.dispValue
|
|
}
|
|
if (disp.dispKey === 'toTable'){
|
|
db.toTable = disp.dispValue
|
|
db.toTableComment = disp.dispLabel
|
|
}
|
|
if (disp.dispKey === 'formFields'){
|
|
fields.push({
|
|
id: i++,
|
|
fieldName: disp.dispValue,
|
|
fieldType: disp.dispType,
|
|
fieldComment: disp.dispLabel
|
|
})
|
|
}
|
|
if (disp.dispKey === 'toFields'){
|
|
fields.push({
|
|
id: j++,
|
|
fieldName: disp.dispValue,
|
|
fieldType: disp.dispType,
|
|
fieldComment: disp.dispLabel
|
|
})
|
|
}
|
|
})
|
|
}
|
|
return {db, fields}
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
@labelColor: #409eff;
|
|
@nodeSize: 20px;
|
|
@viewSize: 10px;
|
|
.v-modal {
|
|
width: 50%;
|
|
display: none !important;
|
|
}
|
|
.node-item {
|
|
position: absolute;
|
|
display: flex;
|
|
height: 40px;
|
|
width: 120px;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border: 1px solid #b7b6b6;
|
|
border-radius: 4px;
|
|
cursor: move;
|
|
box-sizing: content-box;
|
|
z-index: 996;
|
|
&:hover {
|
|
z-index: 997;
|
|
.delete-btn{
|
|
display: block;
|
|
}
|
|
}
|
|
.log-wrap{
|
|
width: 40px;
|
|
height: 40px;
|
|
border-right: 1px solid #b7b6b6;
|
|
}
|
|
.nodeName {
|
|
flex-grow: 1;
|
|
width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.node-anchor {
|
|
display: flex;
|
|
position: absolute;
|
|
width: @nodeSize;
|
|
height: @nodeSize;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 10px;
|
|
cursor: crosshair;
|
|
z-index: 998;
|
|
background: -webkit-radial-gradient(sandybrown 10%, white 30%, #9a54ff 60%);
|
|
}
|
|
.anchor-top{
|
|
top: calc((@nodeSize / 2)*-1);
|
|
left: 50%;
|
|
margin-left: calc((@nodeSize/2)*-1);
|
|
}
|
|
.anchor-right{
|
|
top: 50%;
|
|
right: calc((@nodeSize / 2)*-1);
|
|
margin-top: calc((@nodeSize / 2)*-1);
|
|
}
|
|
.anchor-bottom{
|
|
bottom: calc((@nodeSize / 2)*-1);
|
|
left: 50%;
|
|
margin-left: calc((@nodeSize / 2)*-1);
|
|
}
|
|
.anchor-left{
|
|
top: 50%;
|
|
left: calc((@nodeSize / 2)*-1);
|
|
margin-top: calc((@nodeSize / 2)*-1);
|
|
}
|
|
}
|
|
.active{
|
|
border: 1px dashed @labelColor;
|
|
box-shadow: 0px 5px 9px 0px rgba(0,0,0,0.5);
|
|
}
|
|
</style>
|