ER图测试,域账号登录测试,修改数据查询的展示问题

This commit is contained in:
暮光:城中城
2021-08-02 21:18:58 +08:00
parent 83ca189598
commit 51f74f60c3
34 changed files with 1795 additions and 89 deletions

View File

@@ -0,0 +1,26 @@
.er-editor-demo-container {
width: 100%;
height: 100%;
background-color: #fafafa;
.minimap-container {
position: absolute;
top: 10px;
right: 10px;
/** X6推荐覆写样式 */
.x6-widget-minimap {
.x6-graph {
box-shadow: 0 0 0 0 #ffffff;
}
.x6-widget-minimap-viewport {
border: 1px solid rgba(0, 0, 0, 0.1);
.x6-widget-minimap-viewport-zoom {
border: 1px solid rgba(0, 0, 0, 0.1);
}
}
}
}
}

View File

@@ -0,0 +1,88 @@
<template>
<div class="er-editor-demo-container">
<div
id="refContainer"
ref="refContainer"
style="width: 100%; height: 100%"/>
<div id="refMinimapContainer" ref="refMinimapContainer" class="minimap-container" />
</div>
</template>
<script lang="js">
import './index.less'
import { BaseGraph } from '../xflow/index' // GraphData, GraphOptions
export default {
name: 'index',
components: {
},
props: {
graphOptions: {
type: Object,
default: null,
required: false
},
graphData: {
type: Object,
default: null,
required: false
}
},
data () {
return {
// graphContainer: document.getElementById('refContainer'),
// minimapContainer: document.getElementById('refMinimapContainer'),
baseGraph: null
}
},
mounted () {
const that = this
setTimeout(() => {
/** 初始化画布 */
this.baseGraph = new BaseGraph({
...this.graphOptions,
container: document.getElementById('refContainer'),
grid: {
visible: false
},
minimap: {
enabled: true,
container: document.getElementById('refMinimapContainer'),
minScale: 0.5,
maxScale: 2
}
})
/** 渲染画布内容 */
this.baseGraph.updateGraph(that.graphData)
}, 100)
},
methods: {
onHandleToolbar (action) {
switch (action) {
case 'in':
console.log('in')
this.baseGraph.zoomGraph(0.1)
break
case 'out':
console.log('out')
this.baseGraph.zoomGraph(-0.1)
break
case 'fit':
console.log('fit')
this.baseGraph.zoomGraph('fit')
break
case 'real':
console.log('real')
this.baseGraph.zoomGraph('real')
break
default:
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,113 @@
.entity-container {
width: calc(100% - 2px);
height: calc(100% - 2px);
border-radius: 2px;
background-color: white;
&.fact {
border: 1px solid #ced4de;
&:hover {
border: 1px solid #1890ff;
}
}
&.dim {
border: 1px solid #cdddfd;
&:hover {
border: 1px solid #1890ff;
}
}
&.other {
border: 1px solid #decfea;
&:hover {
border: 1px solid #1890ff;
}
}
.content {
margin: 1px 1px;
width: calc(100% - 2px);
height: calc(100% - 2px);
display:block;
&.fact {
background-color: #ced4de;
}
&.dim {
background-color: #cdddfd;
}
&.other {
background-color: #decfea;
}
.head {
width: calc(100% - 12px);
height: 38px;
margin-left: 6px;
font-size: 12px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.type {
padding-right: 8px;
}
.more {
cursor: pointer;
}
}
.body {
width: calc(100% - 12px);
height: calc(100% - 36px - 6px);
margin-left: 6px;
margin-bottom: 6px;
background-color: white;
overflow: auto;
cursor: pointer;
//float:clear;
.body-item {
width: 100%;
height: 28px;
font-size: 12px;
color: #595959;
border-bottom: 1px solid rgba(206, 212, 222, 0.2);
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.name {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-left: 6px;
.pk,
.fk {
width: 12px;
font-family: HelveticaNeue-CondensedBold;
color: #ffd666;
margin-right: 6px;
}
}
.type {
color: #bfbfbf;
font-size: 8px;
margin-right: 8px;
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
<template>
<div class="entity-container fact">
<div class="content other">
<div class="head">
<div>
<a-icon type="bars" class="type"/>
<span>{{ entity.name }}</span>
</div>
<a-icon type="ellipsis" class="more" />
</div>
<div class="body">
<div class="body-item" v-for="(item,index) in entity.properties" :key="index">
<div class="name">
<!-- {{ value.isPK }} && <span class="pk">PK</span>-->
<!-- {{value.isFK }} && <span class="fk">FK</span>-->
{{ item.name }}
</div>
<div class="type">{{ item.propertyType }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
import './Entity.less'
export default {
name: 'Entity',
props: {
entity: {
type: Object,
default: null,
required: true
}
},
mounted () {
console.log(this.entity, 'this.entity')
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,75 @@
<template>
<div style="width: 100%; height: 650px">
<ERGraph :graphData="graphData"/>
</div>
</template>
<script lang="js">
import ERGraph from '../ERGraph'
import { mockEntityData, mockRelationData } from './mock'
import Entity from './Entity'
export default {
name: 'index',
components: {
ERGraph
},
data () {
return {
graphData: {
nodes: '',
edges: ''
}
}
},
mounted () {
this.calRenderData()
},
methods: {
calRenderData () {
this.graphData.nodes = mockEntityData.map((entity) => {
const { entityId, x, y, width, height } = entity
return {
x,
y,
width,
height,
id: entityId,
component: {
template: '<Entity :entity="entity"/>',
data () {
return {
entity: entity
}
},
components: {
Entity
}
}
// data: entity
}
}
)
this.graphData.edges = mockRelationData.map((relation) => {
const { relationId, sourceEntityId, targetEntityId } = relation
return {
id: relationId,
source: sourceEntityId,
target: targetEntityId,
label: '1:N',
// render: (data: RelationCanvasModel) => {
// return null;
// },
data: relation
}
}
)
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,193 @@
// import {
// EntityProperty,
// EntityCanvasModel,
// RelationCanvasModel
// } from './interface'
// : EntityProperty[]
export const mockProperties = [
{
propertyId: 'propertyId1',
name: '业务日期',
propertyType: 'string',
isPK: true
},
{
propertyId: 'propertyId2',
name: '交易号1',
propertyType: 'bigint',
isFK: true
},
{
propertyId: 'propertyId3',
name: '最长显示的表单名最长显示的表单名',
propertyType: 'string'
},
{
propertyId: 'propertyId4',
name: '交易支付外键',
propertyType: 'string'
},
{
propertyId: 'propertyId5',
name: '卖家支付日期',
propertyType: 'string'
},
{
propertyId: 'propertyId6',
name: '网商银行',
propertyType: 'string'
},
{
propertyId: 'propertyId7',
name: '业务日期',
propertyType: 'string'
},
{
propertyId: 'propertyId8',
name: '业务日期111',
propertyType: 'string'
},
{
propertyId: 'propertyId9',
name: '业务日期222',
propertyType: 'string'
},
{
propertyId: 'propertyId10',
name: '业务日期333',
propertyType: 'string'
}
]
// : EntityCanvasModel[]
export const mockEntityData = [
{
entityId: 'fact_1',
name: '事实表',
entityType: 'FACT',
properties: mockProperties,
x: 550,
y: 400,
width: 214,
height: 248
},
{
entityId: 'fact_up',
name: '事实表',
entityType: 'FACT',
properties: mockProperties,
x: 100,
y: 100,
width: 214,
height: 248
},
{
entityId: 'dim_up',
name: '维度表',
entityType: 'DIM',
properties: mockProperties,
x: 100,
y: 400,
width: 214,
height: 248
},
{
entityId: 'other_up',
name: '其他表',
entityType: 'OTHER',
properties: mockProperties,
x: 100,
y: 700,
width: 214,
height: 248
},
{
entityId: 'other_down',
name: '其他表',
entityType: 'OTHER',
properties: mockProperties,
x: 900,
y: 0,
width: 214,
height: 248
},
{
entityId: 'fact_down1',
name: '事实表',
entityType: 'FACT',
properties: mockProperties,
x: 900,
y: 280,
width: 214,
height: 248
},
{
entityId: 'dim_down',
name: '维度表',
entityType: 'DIM',
properties: mockProperties,
x: 900,
y: 580,
width: 214,
height: 248
},
{
entityId: 'fact_down2',
name: '事实表',
entityType: 'FACT',
properties: mockProperties,
x: 900,
y: 860,
width: 214,
height: 248
}
]
// : RelationCanvasModel[]
export const mockRelationData = [
{
relationId: 'relationId_1',
sourceEntityId: 'fact_up',
targetEntityId: 'fact_1'
},
{
relationId: 'relationId_2',
sourceEntityId: 'fact_1',
targetEntityId: 'fact_up'
},
{
relationId: 'relationId_1_loop',
sourceEntityId: 'fact_1',
targetEntityId: 'fact_1'
},
{
relationId: 'relationId_2',
sourceEntityId: 'dim_up',
targetEntityId: 'fact_1'
},
{
relationId: 'relationId_3',
sourceEntityId: 'other_up',
targetEntityId: 'fact_1'
},
{
relationId: 'relationId_4',
sourceEntityId: 'fact_1',
targetEntityId: 'other_down'
},
{
relationId: 'relationId_5',
sourceEntityId: 'fact_1',
targetEntityId: 'fact_down1'
},
{
relationId: 'relationId_6',
sourceEntityId: 'fact_1',
targetEntityId: 'dim_down'
},
{
relationId: 'relationId_7',
sourceEntityId: 'fact_1',
targetEntityId: 'fact_down2'
}
]

View File

@@ -0,0 +1,5 @@
.erGraphDemo {
width: 100%;
height: 100vh;
overflow: hidden;
}

View File

@@ -0,0 +1,46 @@
<template>
<div class="styles.erGraphDemo">
<ERGraphDemo />
</div>
</template>
<script lang="js">
import styles from './index.less'
import ERGraphDemo from './ERGraphDemo'
export default {
name: 'index',
components: {
ERGraphDemo
},
data () {
return {
visible: false,
graph: '',
styles: styles
}
},
mounted () {
},
methods: {
showDrawer () {
// setTimeout(() => {
// this.initGraph()
// }, 100)
this.visible = true
},
onClose () {
// this.graph.dispose()
this.visible = false
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,87 @@
<template>
<div style="padding: 10px;">
<div ref="graphContainer"></div>
</div>
</template>
<script>
import {Graph} from '@antv/x6';
export default {
data() {
return {
graphData: {
// 节点
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
},
],
},
graph: {},
};
},
mounted () {
this.graph = new Graph({
container: this.$refs.graphContainer,
height: 600,
scroller: {
enabled: true,
pannable: true,
pageBreak: false,
},
grid: {
size: 10,
visible: true
}
});
this.graph.fromJSON(this.graphData);
this.graph.centerContent();
},
methods: {
addNode(){
this.graph.createNode({
shape: 'org-node',
attrs: {
'.card': { fill: background },
'.image': { xlinkHref: image },
'.rank': {
fill: textColor,
text: Dom.breakText(rank, { width: 160, height: 45 }),
},
'.name': {
fill: textColor,
text: Dom.breakText(name, { width: 160, height: 45 }),
},
'.btn > circle': { stroke: textColor },
'.btn > text': { fill: textColor, stroke: textColor },
},
})
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,220 @@
// import { Graph } from '@antv/x6'
import { Edge } from '@antv/x6'
//
// import '@antv/x6-react-shape'
// import X6BaseGraph from '../graph/baseGraph'
// import Node from '../graph/node'
// import Edge from '../graph/edge'
// import { NodeConfig, EdgeConfig } from '../interface/graph-core'
import _ from 'lodash'
import '@antv/x6-vue-shape'
const x6VueShape = 'vue-shape'
export default class CellController {
// private graph: Graph;
//
// /** 记录画布中的节点 */
// public nodes: Node[] = [];
// /** 记录画布中的连线 */
// public edges: Edge[] = [];
constructor (x6BaseGraph) {
this.graph = x6BaseGraph.graph
/** 记录画布中的节点 */
this.nodes = []
/** 记录画布中的连线 */
this.edges = []
}
/**
* 批量添加节点
* @template T
* @param {T[]} nodesData 节点数据集合
* @memberof CellController
*/
addNodes (nodesData) {
nodesData.forEach((nodeData) => {
this.addNode(nodeData)
})
}
/**
* 添加单个节点
* @template T
* @param {T} nodeData 节点数据
* @memberof CellController
*/
addNode (nodeData) {
console.log(nodeData, 'nodeData')
const { id, x, y, width, height, component, data, ...rest } = nodeData
const newNode = this.graph.addNode({
id,
x: x || 0,
y: y || 0,
width: width || 100,
height: height || 60,
// data: data || undefined,
shape: x6VueShape,
component: component,
...rest
})
this.nodes.push(newNode)
}
/**
* 更新节点
* @param {Node} node 节点实例
* @param {NodeConfig} newNodeData 节点最新数据
* @memberof CellController
*/
updateNode (node, newNodeData) {
// !!! 现在仅支持data数据不一致才认为更新
if (!_.isEqual(node.data, newNodeData.data)) {
// 重设节点数据, 触发x6更新节点逻辑
node.setData(newNodeData.data)
// node.setPosition(newNodeData.x, newNodeData.y)
// node.setSize(newNodeData.width, newNodeData.height)
}
}
/**
* 批量删除节点
* @param {Node[]} removeNodes
* @memberof CellController
*/
removeNodes (removeNodes) {
if (_.size(removeNodes) > 0) {
this.graph.removeCells(removeNodes)
this.nodes = _.pullAll(this.nodes, removeNodes)
}
}
/**
* 单个删除节点
* @param {(Node | string)} node
* @memberof CellController
*/
removeNode (removeNode) {
if (!removeNode) {
return
}
if (removeNode instanceof Node) {
this.removeNodes([removeNode])
} else {
const findNode = this.findNodeById(removeNode)
if (findNode) {
this.removeNodes([findNode])
}
}
// !!! 待补充: 删除节点时是否需要将与之关联的连线都删除, 这里可以加一个标记
}
/**
* 批量添加连线
* @template T
* @param {T[]} edgesData 边数据集合
* @memberof CellController
*/
addEdges (edgesData) {
edgesData.forEach((edgeData) => {
this.addEdge(edgeData)
})
}
/**
* 添加单个连线
* @template T
* @param {T} edgeData 边数据
* @memberof CellController
*/
addEdge (edgeData) {
const { id, source, target, render, data, ...rest } = edgeData
const sourceNode = _.find(this.nodes, (node) => node.id === source)
const targetNode = _.find(this.nodes, (node) => node.id === target)
if (!source || !target) {
throw new Error('edge must has source and target!')
}
const newEdge = this.graph.addEdge({
id: id || `${source}-${target}`,
data: data || undefined,
source: sourceNode,
target: targetNode,
// label: (edge: Edge) => {
// return render && render(edge && edge.data)
// },
attrs: {
line: {
stroke: '#B4BDCF',
strokeWidth: 1
}
},
...rest
})
this.edges.push(newEdge)
}
/**
* 更新边
* @param {Edge} edge 边实例
* @param {EdgeConfig} newEdgeData 边最新数据
* @memberof CellController
*/
updateEdge (edge, newEdgeData) {
// !!! 现在仅支持data数据不一致才认为更新, 需要扩展
if (!_.isEqual(edge.data, newEdgeData.data)) {
edge.setData(newEdgeData.data)
}
}
/**
* 批量删除边
* @param {Edge[]} removeEdges
* @memberof CellController
*/
removeEdges (removeEdges) {
this.graph.removeCells(removeEdges)
this.edges = _.pullAll(this.edges, removeEdges)
}
/**
* 单个删除边
* @param {(Edge | string)} removeEdge
* @memberof CellController
*/
removeEdge (removeEdge) {
if (!removeEdge) {
return
}
if (removeEdge instanceof Edge) {
this.graph.removeCells([removeEdge])
this.removeEdges([removeEdge])
} else {
const findEdge = this.findEdgeById(removeEdge)
if (findEdge) {
this.removeEdges([findEdge])
}
}
}
/**
* 根据节点id获取节点
* @param {string} id 节点id
* @returns {(Node | undefined)}
* @memberof CellController
*/
findNodeById (id) {
return this.nodes.find((node) => node.id === id)
}
/**
* 根据连线id获取连线
* @param {string} id 边id
* @returns {(Edge | undefined)}
* @memberof CellController
*/
findEdgeById (id) {
return this.edges.find((edge) => edge.id === id)
}
}

View File

@@ -0,0 +1,149 @@
// import { Graph } from '@antv/x6'
// import X6BaseGraph from '../graph/baseGraph'
// import { EventArg } from '../interface/graph-core'
export default class EventController {
// private x6BaseGraph: X6BaseGraph;
// private graph: Graph;
//
// // 是否删除X6自动生成的无实际业务含义的连线(用户在画布上拖拽生成连线, 这条连线是没有业务含义的)
// private isDeleteX6DefaultEdge!: boolean;
constructor (x6BaseGraph) {
this.x6BaseGraph = x6BaseGraph
this.graph = x6BaseGraph.graph
}
registerEvent = (events) => {
events &&
events.forEach((event) => {
switch (event.eventName) {
case 'scale': {
this.graph.on('scale', ({ sx, sy, ox, oy }) => {
const scale = sx
event.handler && event.handler({ scale })
})
break
}
case 'graph:mouseenter': {
this.graph.on('graph:mouseenter', ({ e }) => {
event.handler && event.handler()
})
break
}
case 'graph:mouseleave': {
this.graph.on('graph:mouseleave', ({ e }) => {
event.handler && event.handler()
})
break
}
case 'blank:mouseDown': {
this.graph.on('blank:mousedown', ({ e, x, y }) => {
event.handler && event.handler({ x, y })
})
break
}
case 'blank:mouseUp': {
this.graph.on('blank:mouseup', ({ e, x, y }) => {
event.handler && event.handler({ x, y })
})
break
}
case 'node:added': {
this.graph.on('node:added', ({ node }) => {
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
// event.handler && event.handler({ node });
// }
this.x6BaseGraph.bringNodesToFront([node])
})
break
}
case 'node:removed': {
this.graph.on('node:removed', ({ node }) => {
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
// event.handler && event.handler({ node })
// }
})
break
}
case 'edge:added': {
this.graph.on('edge:added', ({ edge }) => {
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
// event.handler && event.handler({ edge })
// }
// this.x6BaseGraph.bringCellsToBack([edge])
})
break
}
case 'edge:removed': {
this.graph.on('edge:removed', ({ edge }) => {
if (this.isDeleteX6DefaultEdge) {
}
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
// event.handler && event.handler({ edge })
// }
})
break
}
case 'node:mousedown': {
this.graph.on('node:mousedown', ({ e, view, x, y }) => {
event.handler && event.handler({ node: view.cell, x, y })
})
break
}
case 'node:mousemove': {
this.graph.on('node:mousemove', ({ e, view, x, y }) => {
event.handler && event.handler({ node: view.cell, x, y })
})
break
}
case 'node:mouseup': {
this.graph.on('node:mouseup', ({ e, view, x, y }) => {
event.handler && event.handler({ node: view.cell, x, y })
})
break
}
case 'node:click': {
this.graph.on('node:click', ({ view }) => {
event.handler && event.handler({ node: view.cell })
})
break
}
case 'node:dbclick': {
this.graph.on('node:dblclick', ({ view }) => {
event.handler && event.handler({ node: view.cell })
})
break
}
case 'edge:connected': {
this.graph.on('edge:connected', ({ edge }) => {
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
// // 拖拽连线过程中画布会出现一条连线, 该连线无实际业务含义, 需要删除
// if (!edge.data && edge.id.toString().startsWith('cell-', 0)) {
// this.isDeleteX6DefaultEdge = true;
// this.graph.removeCells([edge]);
// this.isDeleteX6DefaultEdge = false;
// }
// event.handler && event.handler({ edge });
// }
})
break
}
case 'selection:changed': {
this.graph.on(
'selection:changed',
({ selected, removed, added }) => {
event.handler && event.handler({ selected, removed, added })
this.x6BaseGraph.bringCellsToFront(selected)
}
)
break
}
default: {
break
}
}
})
};
}

View File

@@ -0,0 +1,4 @@
export { default as CellController } from './cellController'
export { default as EventController } from './eventController'
/** 更多独立功能控制器, 比如快捷方式、布局等 */

View File

@@ -0,0 +1,267 @@
import { Graph } from '@antv/x6'
// import Node from '../graph/node'
// import Edge from '../graph/edge'
import { CellController, EventController } from '../controller/index'
import _ from 'lodash'
export default class X6BaseGraph {
// public graph!: Graph;
// public cellController!: CellController;
// public eventController!: EventController;
constructor (graphOptions) {
/** 创建X6画布实例 */
const defaultCfg = this.getDefaultCfg()
this.graph = new Graph({
...defaultCfg,
...graphOptions
})
this.init()
}
init () {
this.cellController = new CellController(this)
this.eventController = new EventController(this)
}
/**
* 获取画布默认配置项
* @returns {Partial<GraphOptions>}
* @memberof X6BaseGraph
*/
getDefaultCfg () {
const defaultCfg = {
/** 无限画布设置 */
scroller: {
enabled: true,
pageVisible: false,
pageBreak: false,
pannable: true
},
/** 画布网格 */
grid: {
visible: true,
size: 20,
type: 'doubleMesh',
args: [
{
color: '#888',
thickness: 1
}
// {
// color: '#ddd',
// thickness: 1,
// factor: 4,
// },
]
},
/** 全局连线配置 */
// connecting: {
// anchor: 'midSide',
// router: {
// name: 'er',
// },
// // connector: {
// // name: 'smooth',
// // },
// },
connecting: {
connector: {
name: 'rounded'
},
router: {
name: 'er',
args: {
direction: 'H'
}
}
},
/** 对齐线 */
snapline: {
enabled: true
},
/** 滚轮缩放 */
// mousewheel: {
// enabled: true,
// zoomAtMousePosition: false,
// factor: 1.1,
// },
keyboard: {
enabled: true
},
clipboard: {
enabled: true
}
}
return defaultCfg
}
/**
* 更新画布内容
* @param {GraphData} graphData 画布元素数据
* @memberof X6BaseGraph
*/
updateGraph (graphData) {
if (!graphData) {
throw new Error('graphData must be defined first!')
}
const { addNodesData, addEdgesData } = this.graphContentDiff(graphData)
this.graph.batchUpdate('updateGraph', () => {
if (addNodesData && addNodesData.length > 0) {
this.cellController.addNodes(addNodesData)
}
if (addEdgesData && addEdgesData.length > 0) {
this.cellController.addEdges(addEdgesData)
}
})
}
/**
* 画布缩放
* @param {number} factor 缩放比例尺
* @memberof X6BaseGraph
*/
zoomGraph (factor) {
if (typeof factor === 'number') {
this.graph.zoom(factor)
} else if (factor === 'fit') {
this.graph.zoomToFit({ padding: 12 })
} else if (factor) {
this.graph.scale(1)
this.graph.centerContent()
}
}
/**
* 移动节点到画布中央
* @param {(Node | string)} node
* @memberof X6BaseGraph
*/
focusNodeToGraphCenter (node) {
if (node instanceof Node) {
this.graph.centerCell(node)
} else {
const temp = this.cellController.findNodeById(node)
if (temp) {
this.graph.centerCell(temp)
}
}
}
/**
* 将Nodes置于画布最前方
* @param {Node[]} nodes
* @memberof X6BaseGraph
*/
bringNodesToFront (nodes) {
nodes.forEach((node) => {
node.toBack()
})
}
/**
* 将Nodes置于画布最后方
* @param {Node[]} nodess
* @memberof X6BaseGraph
*/
bringNodesToBack (nodes) {
nodes.forEach((node) => {
node.toBack()
})
}
/**
* 清空画布内容
* @memberof X6BaseGraph
*/
clearGraph () {
// todo
}
/**
* 注册监听事件
* @param {EventArg[]} events
* @memberof X6BaseGraph
*/
registerEvent (events) {
this.eventController.registerEvent(events)
}
/** 画布内容Diff */
graphContentDiff (graphData) {
const { nodes: nodesData, edges: edgesData } = graphData
// 新增节点数据
const addNodesData = []
nodesData.forEach((nodeData) => {
const findNode = this.cellController.findNodeById(nodeData.id)
if (!findNode) {
addNodesData.push(nodeData)
}
})
// 保持、更新、移除的节点
const retainNodes = []
const updateNodes = []
const removeNodes = []
this.cellController.nodes.forEach((node) => {
const findNodeData = nodesData.find(
(nodeData) => nodeData.id === node.id
)
if (!findNodeData) {
removeNodes.push(node)
} else {
// !!! 目前仅支持节点data数据变化, 才认为更新
if (_.isEqual(node.data, findNodeData.data)) {
retainNodes.push(node)
} else {
updateNodes.push(node)
this.cellController.updateNode(node, findNodeData)
}
}
})
// 新增连线数据
const addEdgesData = []
edgesData.forEach((edgeData) => {
if (!edgeData.id) {
return
}
const findEdge = this.cellController.findEdgeById(edgeData.id)
if (!findEdge) {
addEdgesData.push(edgeData)
}
})
// 保持、更新、移除的连线
const retainEdges = []
const updateEdges = []
const removeEdges = []
this.cellController.edges.forEach((edge) => {
const findEdgeData = edgesData.find(
(edgeData) => edgeData.id === edge.id
)
if (!findEdgeData) {
removeEdges.push(edge)
} else {
// !!! 目前仅支持连线data数据变化, 才认为更新
if (_.isEqual(edge.data, findEdgeData.data)) {
retainEdges.push(edge)
} else {
updateEdges.push(edge)
this.cellController.updateEdge(edge, findEdgeData)
}
}
})
this.cellController.removeNodes(removeNodes)
this.cellController.removeEdges(removeEdges)
return {
addNodesData,
addEdgesData
}
}
}

View File

@@ -0,0 +1,7 @@
/** 类型定义 */
// export * from './interface/graph-core'
/** BaseGraph、Node、Edge */
export { default as BaseGraph } from './graph/baseGraph'
// export { default as Node } from './graph/node'
// export { default as Edge } from './graph/edge'