清理无用菜单

This commit is contained in:
2023-05-10 14:51:32 +08:00
parent 82f596f7eb
commit 8a11e20306
154 changed files with 84 additions and 32006 deletions

View File

@@ -1,314 +0,0 @@
<template>
<div class="graph-main">
<div class="legend-box" v-show="!legendHide">
<div class="item-row" v-for="(value, key) in legendList" :key="key">
<div class="point" :style="'background-color:' + value.color"></div>
<div class="label">{{ value.label }}</div>
</div>
</div>
<div :id="id" style="width: 100%; height: 100%"></div>
</div>
</template>
<script>
import request from '@/utils/request';
import G6 from '@antv/g6';
var graphObj = {};
export default {
data() {
return {
ontologyId: '',
id: Math.round(Math.random() * 10000000).toString(),
graph: null,
graphData: null,
legendHide: false,
legendList: {
"armyType": {label: '军种', color: 'rgb(76,142,218)'},
"control": {label: '控制系统', color: 'rgb(236,181,201)'},
"engine": {label: '发动机', color: 'rgb(241,102,103)'},
"fault": {label: '故障信息', color: 'rgb(141,204,147)'},
"faultCase": {label: '故障案例', color: 'rgb(156,33,234)'},
"oriPlane": {label: '原飞机', color: 'rgb(255,196,84)'},
"part": {label: '部件', color: 'rgb(86,148,128)'},
"place": {label: '发生地', color: 'rgb(217,200,174)'},
"plane": {label: '飞机', color: 'rgb(87,199,227)'}
}
}
},
created() {
this.ontologyId = this.$route.query.id;
},
mounted() {
},
methods: {
initGraph: function (cmd, flag, clickNodeFun, legendHide) { // 是否隐藏图例
if(legendHide) {
this.legendHide = true;
}
let graph = graphObj[this.id];
this.$nextTick(() => {
this.destroyGraph();
let _width = document.getElementById(this.id).clientWidth;
let _height = document.getElementById(this.id).clientHeight;
// 创建 G6 图实例
if (graph == undefined || graph == null) {
graph = new G6.Graph({
container: this.id, // 指定图画布的容器 id与第 9 行的容器对应
// 画布宽高
width: _width,
height: _height,
layout: {
type: 'force',
nodeStrength: -0,
nodeSize: 80,
preventOverlap: true,
edgeStrength: 0.1
},
modes: {
// Defualt mode
default: ['drag-node',
{
type: 'drag-canvas',
enableOptimize: true, // enable the optimize to hide the shapes beside nodes' keyShape
},
{
type: 'zoom-canvas',
enableOptimize: true, // enable the optimize to hide the shapes beside nodes' keyShape
},
{
type: 'tooltip',
formatText: function formatText(model) {
let name = '';
let argumentsStr = '';
if (model.label) name = model.label + '<br/>';
if (model.arguments && model.arguments.length > 0) {
model.arguments.forEach(arg => {
argumentsStr += arg.role + "" + arg.argument + '<br/>';
});
}
const text = `${name} ${argumentsStr}`;
return text;
},
shouldUpdate: function shouldUpdate() {
return true;
},
},
],
},
defaultNode: {
size: 20,
color: '#4b4b4b',
label: 'name',
style: {
lineWidth: 2,
fill: '#68BDF6'
},
labelCfg: {
position: 'bottom',
style: {
fontSize: 14,
fill: '#454545'
}
}
},
defaultEdge: {
style: {
stroke: '#b3b3b3',
lineAppendWidth: 10, // Enlarge the range the edge to be hitted
},
labelCfg: {
autoRotate: false,
style: {
fontSize: 14,
fill: '#848484'
}
},
},
nodeStateStyles: {
yourStateName: {
stroke: '#f00',
lineWidth: 3,
},
},
edgeStateStyles: {
yourStateName: {
stroke: '#f00',
lineWidth: 3,
},
},
});
/*拖动节点-start*/
const forceLayout = graph.get('layoutController').layoutMethod;
graph.on('node:dragstart', function (e) {
graph.layout();
refreshDragedNodePosition(e);
});
graph.on('node:drag', function (e) {
if (forceLayout) {
forceLayout.execute();
}
refreshDragedNodePosition(e);
});
graph.on('node:dragend', function (e) {
e.item.get('model').fx = null;
e.item.get('model').fy = null;
});
/*拖动节点-end*/
graph.on('node:click', (e) => {
let node = e.item._cfg.model;
if (clickNodeFun) {
clickNodeFun(node);
}
this.clearStates();
graph.setItemState(e.item, 'yourStateName', true);
});
graph.on('canvas:click', (e) => {
this.clearStates();
});
graphObj[this.id] = graph;
}
if (flag) {
this.importData(cmd);
} else {
this.queryData(cmd);
}
});
},
importData({nodes, edges}) { // 查询图空间内节点关系
let graph = graphObj[this.id];
// 更新颜色数据
nodes.forEach(node => {
node.style = {
lineWidth: 2,
fill: this.legendList[node._label].color || "#68BDF6"
};
});
this.graphData = {
nodes: nodes,
edges: edges
};
// 读取数据
graph.data(this.graphData);
// 渲染图
graph.render();
},
queryData({path, qo}) { // 查询图空间内节点关系
let graph = graphObj[this.id];
request({
url: path,
method: 'post',
data: qo
}).then(res => {
res.data.nodes.forEach(node => {
node.label = node.properties.name;
node.id = node.id.toString();
});
res.data.relations.forEach(edge => {
delete edge.id;
edge.source = edge.source.toString();
edge.target = edge.target.toString();
if (edge.source === edge.target) {
edge.type = 'loop';
} else {
delete edge.type;
}
});
this.importData({
nodes: res.data.nodes,
edges: res.data.relations
});
// this.graphData = {
// nodes: res.data.nodes,
// edges: res.data.relations
// };
// // 读取数据
// graph.data(this.graphData);
// // 渲染图
// graph.render();
});
},
clearStates() { // 清空选中状态
let graph = graphObj[this.id];
graph.getNodes().forEach((node) => {
graph.clearItemStates(node);
});
graph.getEdges().forEach((edge) => {
graph.clearItemStates(edge);
});
},
destroyGraph() {
let graph = graphObj[this.id];
try {
if (graph != undefined && graph != null) {
graph.clear();
graph = null;
document.getElementById("mountNode").innerHTML = "";
}
} catch (err) {
console.log(err);
}
},
}
}
function refreshDragedNodePosition(e) {
const model = e.item.get('model');
model.fx = e.x;
model.fy = e.y;
}
</script>
<style>
.g6-tooltip {
border: 1px solid #e2e2e2;
border-radius: 4px;
font-size: 12px;
color: #545454;
background-color: rgba(255, 255, 255, 0.9);
padding: 10px 8px;
box-shadow: rgb(174 174 174) 0px 0px 10px;
}
.graph-main {
position: relative;
width: 100%;
height: 100%;
}
.legend-box {
position: absolute;
top: 10px;
left: 10px;
}
.item-row {
float: left;
margin-right: 15px;
}
.item-row .point {
width: 20px;
height: 20px;
border-radius: 40px;
border: 2px solid #4b4b4b;
display: inline-block;
}
.item-row .label {
line-height: 20px;
height: 20px;
float: right;
margin-left: 5px;
}
</style>

View File

@@ -250,7 +250,6 @@ import {config} from '@/components/graph/config';
import G6 from '@antv/g6';
import {listToTree} from "@/utils/common";
import noumenonInfo from '@/components/dialog/NoumenonInfo';
import tagModify from "@/components/dialog/TagModify";
var vm;
var graph;

View File

@@ -1,782 +0,0 @@
<template>
<div class="node-box" style="position: relative">
<transition name="el-zoom-in-center">
<div v-show="infoVisible" class="graph-info-box">
<div class="graph-info-child">
<div v-show="selectObj.type == 'edge'">
<noumenon-edge-modify ref="noumenonEdgeModify"></noumenon-edge-modify>
</div>
<div v-show="selectObj.type == 'node'">
<noumenon-modify ref="noumenonModify"></noumenon-modify>
</div>
<i class="el-icon-d-arrow-left" @click="infoVisible = false"></i>
</div>
</div>
</transition>
<transition name="el-zoom-in-center">
<div v-show="treeInfoVisible" class="tree-graph-info">
<div class="graph-info-child">
<tree-graph-info ref="treeGraphInfo"></tree-graph-info>
<i class="el-icon-d-arrow-right" @click="treeInfoVisible = false"></i>
</div>
</div>
</transition>
<!-- 为图谱准备一个具备大小宽高的Dom -->
<div class="tree-container">
<div class="graph-name-box">
<label>本体名称 {{ graphName }}</label>
<label>节点数量{{ nodeCount }}</label>
<label>关系属性数量{{ edgeCount }}</label>
<label>值属性数量{{ valueCount }}</label>
</div>
<!-- <div class="tips-box">-->
<!-- <label></label>-->
<!-- </div>-->
<div class="icon-box">
<div class="icon icon-tree" @click="showTreeCom">
<i title="树形图谱"></i>
</div>
<div class="icon icon-add" @click="showAddNodeDialog">
<i title="新增概念"></i>
</div>
<div title="按住shift点选两节点可新增关系" :class="['icon icon-arrow', createEdgeModelFlag ? 'active' : '']" @click="changeCreateEdgeModel">
<i title="按住shift点选两节点可新增关系"></i>
</div>
<div class="icon icon-remove" @click="removeNode">
<i title="删除"></i>
</div>
<div class="icon icon-save" @click="backGraph">
<i title="返回"></i>
</div>
</div>
<div id="mountNode" style="width: 100%; height: 1000px"></div>
</div>
<el-dialog
title="新增概念"
:visible.sync="addNodeDialogVisible"
width="40%">
<el-form ref="addNodeForm" label-width="80px" :rules="addNodeRules" :model="addNodeCmd">
<el-form-item label="概念名" prop="tagName">
<el-input v-model="addNodeCmd.tagName"></el-input>
</el-form-item>
<el-form-item label="概念描述">
<el-input v-model="addNodeCmd.label"></el-input>
</el-form-item>
</el-form>
<el-button @click="addNodeDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitAddNode"> </el-button>
</el-dialog>
<el-dialog
title="新增关系"
:visible.sync="addEdgeDialogVisible"
@close="handleAddEdgeDialogClose"
width="40%">
<el-form ref="addEdgeForm" :model="addEdgeCmd" label-width="100px" :rules="addEdgeRules">
<el-form-item label="关系名称" prop="edgeName">
<el-input v-model="addEdgeCmd.edgeName"></el-input>
</el-form-item>
<el-form-item label="关系描述">
<el-input v-model="addEdgeCmd.label"></el-input>
</el-form-item>
<el-form-item label="是否显示箭头">
<el-radio v-model="addEdgeCmd.arrow" :label="true"></el-radio>
<el-radio v-model="addEdgeCmd.arrow" :label="false"></el-radio>
</el-form-item>
</el-form>
<el-button @click="addEdgeDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitAddEdge"> </el-button>
</el-dialog>
</div>
</template>
<script>
import request from '@/utils/request';
import {config} from '@/components/graph/config';
import G6 from '@antv/g6';
import noumenonModify from '@/components/dialog/NoumenonModify';
import noumenonEdgeModify from '@/components/dialog/NoumenonEdgeModify';
import treeGraphInfo from '@/components/dialog/TreeGraphInfo';
G6.registerBehavior('click-add-edge', {
// Set the events and the corresponding responsing function for this behavior
getEvents() {
return {
'node:click': 'onClick', // The event is canvas:click, the responsing function is onClick
mousemove: 'onMousemove', // The event is mousemove, the responsing function is onMousemove
'edge:click': 'onEdgeClick',
};
},
// The responsing function for node:click defined in getEvents
onClick(ev) {
const self = this;
const node = ev.item;
const graph = self.graph;
// The position where the mouse clicks
const point = {x: ev.x, y: ev.y};
const model = node.getModel();
if (self.addingEdge && self.edge) {
graph.updateItem(self.edge, {
target: model.id,
});
// 打开编辑新建关系的信息弹窗
vm.showAddEdge(self.edge._cfg.model);
self.edge = null;
self.addingEdge = false;
} else {
// Add anew edge, the end node is the current node user clicks
self.edge = graph.addItem('edge', {
source: model.id,
target: model.id,
});
self.addingEdge = true;
}
},
// The responsing function for mousemove defined in getEvents
onMousemove(ev) {
const self = this;
// The current position the mouse clicks
const point = {x: ev.x, y: ev.y};
if (self.addingEdge && self.edge) {
// Update the end node to the current node the mouse clicks
self.graph.updateItem(self.edge, {
target: point,
});
}
},
// The responsing function for edge:click defined in getEvents
onEdgeClick(ev) {
const self = this;
const currentEdge = ev.item;
if (self.addingEdge && self.edge === currentEdge) {
self.graph.removeItem(self.edge);
self.edge = null;
self.addingEdge = false;
}
},
});
var vm;
var graph;
var graphData;
var _ = require('lodash');
var nodeProps = {
id: 'vid',
label: 'properties.label',
name: 'properties.tagName',
labelName: 'properties.label'
};
var edgeProps = {
source: 'srcId',
target: 'dstId',
name: 'properties.edgeName',
label: 'properties.label',
arrow: 'properties.arrow',
labelName: 'properties.label'
}
// const subjectColors = ['#5F95FF', '#61DDAA', '#65789B', '#F6BD16', '#7262FD', '#78D3F8', '#9661BC', '#F6903D', '#008685', '#F08BB4'];
// const colorSets = G6.Util.getColorSetsBySubjectColors(subjectColors, '#fff', 'default', '#777');
export default {
components: {
'noumenon-modify': noumenonModify,
'noumenon-edge-modify': noumenonEdgeModify,
'tree-graph-info': treeGraphInfo
},
data() {
return {
qo: '',
graphName: '',
nodeCount: 0,
edgeCount: 0,
valueCount: 0,
ontologyId: '',
infoVisible: false, // 左侧信息栏显隐
treeInfoVisible: false, // 右侧树形图谱
clickNode: {id: '', name: ''},
addNodeDialogVisible: false,
addNodeCmd: {
ontologyId: '',
tagName: '',
label: ''
},
arrowVisible: false, // 是否展示箭头方向
createEdgeModelFlag: false, // 创建关系模式开关
addEdgeDialogVisible: false,
addEdgeCmd: {
ontologyId: '',
edgeName: '',
label: '',
source: '',
target: '',
arrow: false
},
selectObj: {
type: '',
value: {}
},
addNodeRules: {
tagName: [
{required: true, message: '请输入类名称', trigger: 'blur'},
],
},
addEdgeRules: {
edgeName: [
{required: true, message: '请输入类名称', trigger: 'blur'},
],
},
}
},
created() {
vm = this;
vm.ontologyId = this.$route.query.id;
vm.qo = {
pageNo: this.$route.query.pageNo,
name: this.$route.query.name
};
vm.graphName = this.$route.query.graphName;
},
mounted() {
vm.initGraph();
},
methods: {
queryCount() {
request({
url: `/nebula_model/countallbyontologyid/${vm.ontologyId}`,
method: 'get',
data: {}
}).then(res => {
vm.nodeCount = res.data.gns;
vm.edgeCount = res.data.gxs;
vm.valueCount = res.data.zsxs;
});
},
queryTagData() { // 查询图空间内节点关系
vm.queryCount(); // 更新统计信息
request({
url: `/nebula_model/findrelationbyontologyid/${vm.ontologyId}`,
method: 'post',
data: {
// ontologyId: vm.ontologyId
}
}).then(res => {
res.data.nodes.forEach(node => {
Reflect.ownKeys(nodeProps).forEach(key => {
node[key] = _.get(node, nodeProps[key], '');
});
});
res.data.relations.forEach(edge => {
Reflect.ownKeys(edgeProps).forEach(key => {
edge[key] = _.get(edge, edgeProps[key], '');
});
// 是否指向自己
edge.type = edge.srcId === edge.dstId ? 'loop' : '';
// 是否显示箭头
edge.style = {endArrow: edge.arrow};
});
graphData = {
nodes: res.data.nodes,
edges: res.data.relations
};
// 读取数据
graph.data(graphData);
// 渲染图
graph.render();
});
},
initGraph: function () {
this.destroyGraph();
let mountNodeDom = document.getElementById("mountNode");
let _width = mountNodeDom.clientWidth, _height = mountNodeDom.clientHeight;
// 创建 G6 图实例
if (graph == undefined || graph == null) {
graph = new G6.Graph(config({width: _width, height: _height, id: 'mountNode'}));
graph.on('aftercreateedge', (e) => {
vm.showAddEdge(e.edge._cfg.model);
});
graph.on('canvas:click', (e) => {
vm.selectObj = {
type: '',
value: {}
};
vm.clearStates();
vm.infoVisible = false;
});
/*拖动节点-start*/
// const forceLayout = graph.get('layoutController').layoutMethod;
// graph.on('node:dragstart', function (e) {
// graph.layout();
// refreshDragedNodePosition(e);
// });
// graph.on('node:drag', function (e) {
// if (forceLayout) {
// forceLayout.execute();
// }
// refreshDragedNodePosition(e);
// });
// graph.on('node:dragend', function (e) {
// e.item.get('model').fx = null;
// e.item.get('model').fy = null;
// });
/*拖动节点-end*/
graph.on('edge:click', function (e) { // 点击边事件
let edge = e.item._cfg.model;
if (!edge.name) {
return;
}
let fields = [];
if (edge.properties && edge.properties.nebulafieldsnapshot) {
fields = edge.properties.nebulafieldsnapshot;
}
vm.showEdgeModifyCom({
edgeName: edge.name,
label: edge.labelName,
arrow: edge.arrow,
source: edge.srcId,
target: edge.dstId
}, fields);
graph.getEdges().forEach((edge) => {
graph.clearItemStates(edge);
});
graph.getNodes().forEach((node) => {
graph.clearItemStates(node);
});
graph.setItemState(e.item, 'yourStateName', true);
});
graph.on('node:click', (e) => {
if (!event.shiftKey && !vm.createEdgeModelFlag) { // 按住shift属于新增关系不需要触发点击节点事件
let node = e.item._cfg.model;
vm.showNodeModifyCom({
id: node.id,
tagName: node.name,
label: node.labelName
}, _.get(node, 'properties.nebulafieldsnapshot', []));
vm.clearStates();
graph.setItemState(e.item, 'yourStateName', true);
}
});
}
vm.queryTagData();
},
destroyGraph() {
try {
if (graph != undefined && graph != null) {
graph.clear();
graph = null;
document.getElementById("mountNode").innerHTML = "";
}
} catch (err) {
console.log(err);
}
},
clearStates() { // 清空选中状态
graph.getNodes().forEach((node) => {
graph.clearItemStates(node);
});
graph.getEdges().forEach((edge) => {
graph.clearItemStates(edge);
});
},
changeCreateEdgeModel() { // 切换模式,默认和添加关系模式之间切换
vm.createEdgeModelFlag = !vm.createEdgeModelFlag;
if (vm.createEdgeModelFlag) {
graph.setMode("addEdge");
} else {
graph.setMode("default");
}
},
showAddNodeDialog() {
vm.addNodeCmd = {
ontologyId: vm.ontologyId,
tagName: '',
label: ''
};
vm.addNodeDialogVisible = true;
},
submitAddNode() {
request({
url: `/nebula_model/insertmodelvertex`,
method: 'post',
data: {
ontologyId: vm.ontologyId,
tagName: vm.addNodeCmd.tagName,
label: vm.addNodeCmd.label
}
}).then(res => {
graph.addItem('node', {
id: res.data.vid,
name: vm.addNodeCmd.tagName,
label: vm.addNodeCmd.tagName,
labelName: vm.addNodeCmd.label
});
graphData.nodes = graph.save().nodes;
graph.layout();
vm.$message.success("新增类成功");
vm.addNodeDialogVisible = false;
vm.showNodeModifyCom(res.data.ob, []);
});
},
showAddEdge(edge) {
vm.addEdgeCmd = {
ontologyId: vm.ontologyId,
edgeName: '',
label: '',
arrow: false,
source: edge.source,
target: edge.target
};
vm.addEdgeDialogVisible = true;
},
handleAddEdgeDialogClose() {
vm.queryTagData();
},
submitAddEdge() {
vm.$refs['addEdgeForm'].validate((valid) => {
if (!valid) {
return;
}
let edge = {
srcId: vm.addEdgeCmd.source,
ontologyId: vm.ontologyId,
dstId: vm.addEdgeCmd.target,
edgeName: vm.addEdgeCmd.edgeName,
arrow: vm.addEdgeCmd.arrow,
label: vm.addEdgeCmd.label
};
request({
url: `/nebula_model/insertmodeledge`,
method: 'post',
data: edge
}).then(res => {
vm.queryTagData();
vm.$message.success("新增关系成功");
vm.addEdgeDialogVisible = false;
vm.showEdgeModifyCom(edge, []);
});
});
},
showTreeCom() { // 显示树形图谱窗口
vm.treeInfoVisible = true;
vm.$nextTick(() => {
vm.$refs['treeGraphInfo'].queryTreeData(vm.ontologyId);
});
},
showNodeModifyCom(node, fields) { // 显示节点编辑组件
vm.infoVisible = true;
vm.$nextTick(() => {
vm.selectObj = {
type: 'node',
value: node
};
vm.$refs['noumenonModify'].updateValue(node.tagName, node.label, fields);
});
},
showEdgeModifyCom(edge, fields) { // 显示关系编辑组件
vm.infoVisible = true;
vm.selectObj = {
type: 'edge',
value: edge
};
vm.$nextTick(() => {
vm.$refs['noumenonEdgeModify'].updateValue(edge.edgeName, edge.label, edge.arrow, fields, vm.selectObj.value.source, vm.selectObj.value.target);
});
},
backGraph() { // 返回
if(vm.$refs['treeGraphInfo']) {
vm.$refs['treeGraphInfo'].destroyTree();
}
vm.$router.push({path: "/graphModel", query: {pageNo: vm.qo.pageNo, name: vm.qo.name}})
vm.$message.success("保存成功");
},
changeArrowVisible() { // 显隐箭头
vm.arrowVisible = !vm.arrowVisible;
vm.queryTagData();
},
removeNode() { // 删除节点
if (vm.selectObj.type.length === 0) {
vm.$message.warning("请先选中节点或关系");
return;
}
this.$confirm('此操作将永久删除选中节点和关系, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if (vm.selectObj.type === "node") {
request({
url: `/nebula_model/deletemodelvertex/${vm.selectObj.value.id}`,
method: 'get',
data: {
// vid: vm.selectObj.value.id
}
}).then(res => {
vm.$message.success("删除成功");
vm.queryTagData();
vm.infoVisible = false;
});
} else if (vm.selectObj.type === "edge") {
request({
url: `/nebula_model/deletemodeledge`,
method: 'post',
data: {
srcId: vm.selectObj.value.source,
dstId: vm.selectObj.value.target,
}
}).then(res => {
vm.$message.success("删除成功");
vm.queryTagData();
vm.infoVisible = false;
});
}
}).catch(() => {
});
},
submitUpdateNode(modifyCmd) { // 更新
request({
url: `/nebula_model/insertmodelvertex`,
method: 'post',
data: {
vid: vm.selectObj.value.id,
tagName: modifyCmd.tagName,
label: modifyCmd.label,
fields: modifyCmd.fields
}
}).then(res => {
vm.queryTagData();
vm.$message.success("保存成功");
});
},
submitUpdateEdge(modifyCmd) {
request({
url: `/nebula_model/insertmodeledge`,
method: 'post',
data: {
edgeName: modifyCmd.edgeName,
label: modifyCmd.label,
fields: modifyCmd.fields,
arrow: modifyCmd.arrow,
srcId: vm.selectObj.value.source,
dstId: vm.selectObj.value.target,
}
}).then(res => {
vm.queryTagData();
vm.$message.success("保存成功");
});
},
}
}
function refreshDragedNodePosition(e) {
const model = e.item.get('model');
model.fx = e.x;
model.fy = e.y;
}
</script>
<style scoped>
.graph-name-box {
position: absolute;
top: 25px;
left: 65px;
width: 700px;
font-size: 18px;
font-weight: bold;
}
.form-title {
font-size: 16px;
margin: 15px 0;
}
.add-attribute-box {
margin-top: 10px;
color: #409EFF;
cursor: pointer;
text-align: right;
}
.graph-info-box, .tree-graph-info {
position: absolute;
width: 500px;
top: 0px;
overflow: hidden;
bottom: 0;
background-color: #fff;
padding: 15px;
z-index: 999;
border-right: 1px solid rgba(52, 100, 224, 0.15);
box-shadow: 0px 2px 21px 0px rgba(52, 100, 224, 0.15);
}
.graph-info-box {
left: 0px;
}
.tree-graph-info {
right: 0;
}
.graph-info-child {
width: 100%;
height: 100%;
position: relative;
}
.el-icon-d-arrow-left, .el-icon-d-arrow-right {
position: absolute;
top: 50%;
margin-top: -10px;
font-size: 20px;
cursor: pointer;
z-index: 1000;
}
.el-icon-d-arrow-left {
right: 0px;
}
.el-icon-d-arrow-right {
left: 0px;
}
.info-line-item {
margin-bottom: 35px;
}
.info-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 12px;
}
.info-content > div {
margin-bottom: 5px;
line-height: 20px;
}
ol, ul {
list-style: none;
margin: 0;
padding: 0;
}
.menu {
/*这个样式不写,右键弹框会一直显示在画布的左下角*/
position: absolute;
background: white;
border-radius: 5px;
border: 1px solid #f2f4f7;
left: -99999px;
top: -999999px;
}
.menu div {
list-style: none;
padding: 5px 10px;
color: black;
border-bottom: 1px dashed #ffffff;
font-size: 14px;
cursor: pointer;
}
.menu div:hover {
color: #659bc5;
background: #f3f6fa;
}
.menu div:last-child {
border-bottom: none;
}
ul#menuBox li {
cursor: pointer;
margin: 5px 0;
}
ul#menuBox li:hover {
color: #1c63e0;
}
.tree-container {
position: relative;
}
.tips-box {
position: absolute;
top: 25px;
left: 50%;
width: 300px;
margin-left: -150px;
font-size: 16px;
}
div.icon-box {
position: absolute;
top: 25px;
right: 75px;
}
div.icon {
display: inline-block;
cursor: pointer;
padding: 15px;
background-color: #fff;
border-radius: 40px;
margin-left: 15px;
}
div.icon i {
width: 25px;
height: 25px;
margin: auto;
display: inline-block;
}
div.icon-add i {
background: url("../../assets/image/icon/bg-add.png") no-repeat center/contain;
}
div.icon-remove i {
background: url("../../assets/image/icon/changyonggoupiaorenshanchu.png") no-repeat center/contain;
}
div.icon-save i {
background: url("../../assets/image/icon/fanhui.png") no-repeat center/contain;
}
div.icon-arrow i {
background: url("../../assets/image/icon/arrowTop-fill.png") no-repeat center/contain;
}
div.icon-tree i {
background: url("../../assets/image/icon/shuxingicon.png") no-repeat center/contain;
}
div.icon-arrow.active i {
background: url("../../assets/image/icon/arrowTop-fill-active.png") no-repeat center/contain;
}
div.icon-arrow.active {
box-shadow: 0px 0px 6px #979797;
}
.node-box {
height: 100%;
}
</style>

View File

@@ -1,327 +0,0 @@
<template>
<div class="node-box">
<transition name="el-zoom-in-center">
<div v-show="infoVisible" class="graph-info-box">
<div class="form-title"></div>
<el-form ref="relationForm" label-width="80px">
<el-form-item label="*关系名称">
<el-input v-model="relationCmd.name"></el-input>
</el-form-item>
</el-form>
</div>
</transition>
<i :class="infoVisible ? 'el-icon-d-arrow-left' : 'el-icon-d-arrow-right'"
@click="infoVisible = !infoVisible"></i>
<!-- 为图谱准备一个具备大小宽高的Dom -->
<div class="tree-container">
<div class="icon icon-add" @click="showAddNodeDialog">
<i title="新增节点"></i>
</div>
<div class="icon icon-remove">
<i title="删除"></i>
</div>
<div class="icon icon-save">
<i title="保存"></i>
</div>
<div id="mountNode" style="width: 100%; height: 1000px"></div>
</div>
<el-dialog
title="新增节点"
:visible.sync="addNodeDialogVisible"
width="40%">
<el-form ref="addNodeForm" label-width="80px">
<el-form-item label="节点名称">
<el-input v-model="addNodeCmd.name"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addNodeDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitAddNode"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import request from '@/utils/request';
import { Graph } from '@antv/x6';
var vm;
var graph;
export default {
data() {
return {
nodeNum: 0,
linkNum: 0,
infoVisible: false,
clickNode: {id: '', name: ''},
addNodeDialogVisible: false,
addNodeCmd: {
name: ''
},
relationCmd: {
name: '',
table: '',
sourceId: '',
targetId: '',
edgeId: ''
},
nodeAttributes: [] // 节点属性
}
},
created() {
vm = this;
},
mounted() {
const data = {
// 节点
nodes: [
{
id: 'node1', // String可选节点的唯一标识
x: 40, // Number必选节点位置的 x 值
y: 40, // Number必选节点位置的 y 值
width: 80, // Number可选节点大小的 width 值
height: 40, // Number可选节点大小的 height 值
label: 'hello', // String节点标签
},
{
id: 'node2', // String节点的唯一标识
x: 160, // Number必选节点位置的 x 值
y: 180, // Number必选节点位置的 y 值
width: 80, // Number可选节点大小的 width 值
height: 40, // Number可选节点大小的 height 值
label: 'world', // String节点标签
},
],
// 边
edges: [
{
source: 'node1', // String必须起始节点 id
target: 'node2', // String必须目标节点 id
},
],
};
vm.initGraph(data);
},
methods: {
initGraph: function (_data) {
this.destroyGraph();
let _width = document.getElementById("mountNode").clientWidth;
let _height = document.getElementById("mountNode").clientHeight;
graph = new Graph({
container: document.getElementById('mountNode'),
width: _width,
height: _height,
scroller: {
enabled: true,
pannable: true,
pageVisible: false,
pageBreak: false,
},
// mousewheel: {
// enabled: true,
// modifiers: ['ctrl', 'meta'],
// },
modes: {
// Defualt mode
default: ['drag-node',
{
type: 'drag-canvas',
enableOptimize: true, // enable the optimize to hide the shapes beside nodes' keyShape
},
{
type: 'zoom-canvas',
enableOptimize: true, // enable the optimize to hide the shapes beside nodes' keyShape
},
{
type: 'create-edge',
key: 'shift', // undefined by default, options: 'shift', 'control', 'ctrl', 'meta', 'alt'
},
]
},
});
graph.fromJSON(_data);
},
destroyGraph() {
try {
if(graph != undefined && graph != null) {
graph.clear();
graph = null;
document.getElementById("mountNode").innerHTML = "";
}
} catch (err) {
console.log(err);
}
},
clearStates() { // 清空选中状态
graph.getNodes().forEach((node) => {
graph.clearItemStates(node);
});
graph.getEdges().forEach((edge) => {
graph.clearItemStates(edge);
});
},
showAddNodeDialog() {
vm.addNodeCmd = {
name: ''
};
vm.addNodeDialogVisible = true;
},
submitAddNode() {
graph.addNode({
id: Math.ceil(Math.random()*10000).toString(),
label: vm.addNodeCmd.name
});
vm.$message.success("新增节点成功");
vm.addNodeDialogVisible = false;
},
}
}
function refreshDragedNodePosition(e) {
const model = e.item.get('model');
model.fx = e.x;
model.fy = e.y;
}
</script>
<style>
.graph-info-box {
position: absolute;
left: 290px;
width: 500px;
top: 60px;
bottom: 0;
background-color: #fff;
padding: 15px 15px;
z-index: 999;
border-right: 1px solid rgba(52, 100, 224, 0.15);
box-shadow: 0px 2px 21px 0px rgba(52, 100, 224, 0.15);
}
.el-icon-d-arrow-left, .el-icon-d-arrow-right {
position: absolute;
top: 50%;
margin-top: -10px;
font-size: 20px;
cursor: pointer;
z-index: 1000;
}
.el-icon-d-arrow-left {
left: 780px;
}
.el-icon-d-arrow-right {
left: 300px;
}
.info-line-item {
margin-bottom: 35px;
}
.info-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 12px;
}
.info-content > div {
margin-bottom: 5px;
line-height: 20px;
}
ol, ul {
list-style: none;
margin: 0;
padding: 0;
}
.menu {
/*这个样式不写,右键弹框会一直显示在画布的左下角*/
position: absolute;
background: white;
border-radius: 5px;
border: 1px solid #f2f4f7;
left: -99999px;
top: -999999px;
}
.menu div {
list-style: none;
padding: 5px 10px;
color: black;
border-bottom: 1px dashed #ffffff;
font-size: 14px;
cursor: pointer;
}
.menu div:hover {
color: #659bc5;
background: #f3f6fa;
}
.menu div:last-child {
border-bottom: none;
}
ul#menuBox li {
cursor: pointer;
margin: 5px 0;
}
ul#menuBox li:hover {
color: #1c63e0;
}
.tree-container {
position: relative;
}
div.icon {
display: inline-block;
cursor: pointer;
padding: 15px;
background-color: #fff;
border-radius: 40px;
position: absolute;
top: 25px;
z-index: 9999;
}
div.icon i {
width: 25px;
height: 25px;
margin: auto;
display: inline-block;
}
div.icon-add {
right: 75px;
}
div.icon-add i {
background: url("../../assets/image/icon/bg-add.png") no-repeat center/contain;
}
div.icon-remove {
right: 145px;
}
div.icon-remove i {
background: url("../../assets/image/icon/changyonggoupiaorenshanchu.png") no-repeat center/contain;
}
div.icon-save {
right: 215px;
}
div.icon-save i {
background: url("../../assets/image/icon/baocun.png") no-repeat center/contain;
}
</style>