清理无用菜单
This commit is contained in:
@@ -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>
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user