cloud-ui/src/views/quest/node/components/node-item.vue

481 lines
14 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">
<el-dialog :modal="false" title="配置" :visible.sync="disposition.findFlag" width="50%">
<span>数据库:&nbsp;&nbsp;{{ disposition.formData.dbName }}</span>
<span>数据表:&nbsp;&nbsp;{{ disposition.formData.table }}</span>
<span>
<el-table ref="table" :data="disposition.formData.fields" height="300px">
<el-table-column :show-overflow-tooltip="true" label="字段名称" prop="columnName" />
<el-table-column :show-overflow-tooltip="true" label="字段描述" prop="columnComment" />
<el-table-column :show-overflow-tooltip="true" label="字段类型" prop="columnType" />
</el-table>
</span>
<el-button @click="disposition.findFlag = false">确认</el-button>
<el-button type="primary" @click="editDisposition"></el-button>
</el-dialog>
<!-- 自定义表单对话框 -->
<el-drawer
style="padding-left: 20px; padding-right: 20px;"
:modal="false"
:visible.sync="disposition.updFlag"
direction="rtl"
title="节点配置"
append-to-body
size="60%">
<el-form ref="queryForm" :inline="true" :model="queryParams" size="small">
<el-form-item label="数据库名称" prop="dbName">
<el-select v-model="queryParams.dbName" placeholder="请选择数据库" clearable>
<el-option v-for="item in dbNameOptions" :key="item" :label="item" :value="item"/>
</el-select>
</el-form-item>
<el-form-item label="表名称" prop="tableName">
<el-input
v-model="queryParams.tableName"
clearable
placeholder="请输入表名称" />
</el-form-item>
<el-form-item label="表描述" prop="tableComment">
<el-input
v-model="queryParams.tableComment"
clearable
placeholder="请输入表描述" />
</el-form-item>
<el-form-item>
<el-button icon="el-icon-search" size="mini" type="primary" @click="handleQuery">查找</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table ref="table" :data="tableOptions" height="300px">
<el-table-column :show-overflow-tooltip="true" label="表名称" prop="tableName" />
<el-table-column :show-overflow-tooltip="true" label="表描述" prop="tableComment" />
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="text" @click="selectTable(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
<el-divider />
<el-table ref="table" v-show="fieldsOptions" :data="fieldsOptions" height="300px"
@row-click="clickRow" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column :show-overflow-tooltip="true" label="字段名称" prop="columnName" />
<el-table-column :show-overflow-tooltip="true" label="字段描述" prop="columnComment" />
<el-table-column :show-overflow-tooltip="true" label="字段类型" prop="columnType" />
</el-table>
<el-divider />
<div align="center">
<el-button type="primary" @click="saveDisposition">确 定</el-button>
<el-button @click="disposition.updFlag = false"> </el-button>
</div>
</el-drawer>
</div>
</div>
</template>
<script>
import ClickOutside from 'vue-click-outside'
import {listDbTableAll, selDbNameAll, selectDbTableColumnsByName} from "../../../../api/tool/gen";
export default {
name: "nodeItem",
props: {
node: Object
},
directives: {
ClickOutside
},
computed: {
// 节点容器样式
flowNodeContainer: {
get() {
return {
top: this.node.top,
left: this.node.left
};
}
}
},
data() {
return {
mouseEnter: false,
isActive: false,
isSelected: false,
disposition: {
findFlag: false,
updFlag: false,
formData: {
nodeId: undefined,
dbName: undefined,
table: {},
fields: []
}
},
total: 0,
queryParams: {
pageNum: 1,
pageSize: 10,
dbName: undefined,
tableName: undefined,
tableComment: undefined
},
// 数据库列表
dbNameOptions: [],
// 展示数据表列表
tableOptions: [],
// 所有数据库列表
tableList: [],
// 字段列表
fieldsOptions: []
};
},
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.disposition.updFlag = true;
}
},{
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: '修改成功'
});
}).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: '操作取消'
});
});
},
/** jsPlumb节点类型 --> 数据库节点类型 */
toMysqlNode(node,preLine,nextLine){
return {
id: node.authId,
nodeType: node.type,
nodeCode: node.id,
nodeName: node.nodeName,
nodePositionTop: node.top,
nodePositionLeft: node.left,
nodePreCode: preLine,
nodeNextCode: nextLine,
state: 'Y'
}
},
/** 数据库节点类型 --> jsPlumb节点类型 */
toJsPlumbNode(nodeInfo){
const node = {
authId: nodeInfo.id,
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
}
},
// 双击触发-查看配置
findDisposition() {
// 查询节点配置信息
this.disposition.formData.nodeId = this.node.id
this.disposition.findFlag = true
},
// 编辑配置
editDisposition() {
this.selDbNameList()
this.getListAll()
this.disposition.updFlag = true
},
// 查询所有数据库名称
selDbNameList() {
selDbNameAll().then(res => {
this.dbNameOptions = res.data
})
},
// 查询表字段
getFields(dbName, tableName) {
selectDbTableColumnsByName(dbName, tableName).then(res => {
this.fieldsOptions = res.data
})
},
// 保存配置按钮
saveDisposition() {
console.log(this.disposition.formData)
const dispositionData = this.disposition.formData
const addData = []
/**
* {
* node_info_code: '',
* node_type: '',
* node_value: ''
* }
*/
// 处理数据库信息
addData.push({
nodeInfoCode: dispositionData.nodeId,
nodeType: 'dbName',
nodeValue: dispositionData.dbName
})
// 处理数据表信息
addData.push({
nodeInfoCode: dispositionData.nodeId,
nodeType: 'table',
nodeValue: dispositionData.table
})
// 处理数据字段信息
addData.push({
nodeInfoCode: dispositionData.nodeId,
nodeType: 'fields',
nodeValue: dispositionData.fields.toString()
})
console.log(addData)
this.disposition.updFlag = false
this.disposition.findFlag = false
},
// 重置配置信息
resetDisposition() {
this.disposition.formData = {
dbName: undefined,
table: {},
fields: []
}
},
getListAll() {
listDbTableAll().then(res => {
this.tableList = res.data;
this.tableOptions = res.data;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.tableOptions = []
this.tableList.forEach(table => {
const params = this.queryParams
if ((table.dbName === params.dbName || !params.dbName) &&
(table.tableName.includes(params.tableName) || !params.tableName) &&
(table.tableComment.includes(params.tableComment) || !params.tableComment)){
this.tableOptions.push(table)
}
})
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.resetDisposition()
this.handleQuery();
},
/** 选择表信息*/
selectTable(row) {
this.disposition.formData.table = row.tableName
this.disposition.formData.dbName = row.dbName
this.getFields(row.dbName, row.tableName)
},
clickRow(row) {
this.$refs.table.toggleRowSelection(row);
},
// 多选框选中数据
handleSelectionChange(selection) {
this.disposition.formData.fields = selection.map(item => {
return {
fieldName: item.columnName,
fieldType: item.columnType,
fieldComment: item.columnComment
};
});
},
}
};
</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: 1006;
&:hover {
z-index: 1007;
.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: 1008;
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>