cloud-ui/src/views/quest/node/components/node-item.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>