跳到主要内容
版本:Next

G6流程引擎技术文档

目录

  1. 简介
  2. 项目结构
  3. 核心架构
  4. 图实例管理
  5. 节点与边线系统
  6. 事件总线与状态管理
  7. 交互组件设计
  8. 数据转换与序列化
  9. 性能优化策略
  10. 故障排除指南
  11. 总结

简介

G6流程引擎是一个基于AntV G6构建的工艺流程图设计系统,专为MES(制造执行系统)工艺建模而设计。该引擎提供了完整的图形化流程设计能力,支持复杂的节点类型、自定义行为、交互菜单和工具栏功能。

系统采用Vue 3 Composition API架构,结合TypeScript提供强类型支持,实现了高度模块化的组件设计。通过事件驱动的状态管理模式,确保了系统的可扩展性和维护性。

项目结构

G6流程引擎采用清晰的分层架构,主要组织结构如下:

图表来源

章节来源

核心架构

系统架构概览

G6流程引擎采用了现代化的前端架构模式,结合Vue 3的新特性实现了高效的数据流管理和组件通信。

图表来源

模块依赖关系

系统各模块之间存在清晰的依赖关系,通过依赖注入和事件总线实现松耦合设计:

图表来源

章节来源

图实例管理

Core类的核心功能

Core类是整个G6流程引擎的核心,负责图实例的创建、配置和初始化。它提供了统一的接口来管理不同类型的节点和边线。

// 核心节点创建方法
createNode({ label, type }: NodeItem, { x, y, properties }: PointType) {
const id = uuidv4()
return new Create({
id,
type,
label,
x,
y,
properties,
Name: label,
name: label,
})
}

// 默认图配置
setDefaultProps() {
return {
fitCenter: true,
animate: true,
minZoom: 0.2,
maxZoom: 1.4,
defaultNode: {
type: NODES.ACTIVITIES,
labelCfg: {
style: {
fill: '#333',
fontSize: nodeFontSize,
textAlign: 'center',
textBaseline: 'middle',
fontWeight: 'bold',
},
},
},
defaultEdge: {
type: 'polyline',
labelCfg: {
style: {
fill: '#333',
stroke: '#aaa',
fontSize: fontSize - 2,
},
},
style: {
radius: 20,
offset: 45,
endArrow: true,
lineWidth: 3,
stroke: '#aaa',
},
},
}
}

图实例生命周期管理

图表来源

章节来源

节点与边线系统

基础节点组件化封装

G6流程引擎实现了完整的节点组件化体系,包括开始节点、结束节点和普通节点三种基础类型。

开始节点(StartNode)

const StartNode: {
type: string
options: Record<string, any>
} = {
type: NODES.ACTIVITY,
options: {
drawShape(cfg: Record<string, any>, group: any) {
const rect = group.addShape('rect', {
attrs: {
x: -75 - x,
y: -25 - y,
width,
height,
radius: 10,
stroke: '#5B8FF9',
fill: '#C6E5FF',
lineWidth: 3,
},
name: 'rect-shape',
})
return rect
},
},
}

普通节点(OrdinaryNode)

普通节点支持动态图标加载和状态样式配置:

const OrdinaryNode: {
type: string
options: Record<string, any>
} = {
type: NODES.ACTIVITIES,
options: {
drawShape(cfg: Record<string, any>, group: any) {
const type = cfg?.properties?.type
const isRoot = cfg?.isRoot
const rect = group.addShape('rect', {
zIndex: 1,
attrs: {
x: -width / 2,
y: -height / 2,
width,
height,
radius: 1,
stroke: '#5B8FF9',
fill: '#C6E5FF',
lineWidth: 2,
},
name: 'rect-shape',
})
group.addShape('image', {
zIndex: 100,
draggable: false,
attrs: {
x: -width / 2 + 1,
y: -height / 2 + 1,
radius: 1,
width: 20,
height: 20,
img: `/resources/assets/images/${isRoot ? NODES.ACTIVITY : type}.png`,
},
name: 'node-icon',
})
return rect
},
},
}

节点状态样式系统

图表来源

边线配置与样式

系统支持多种类型的边线配置,包括默认边线样式和状态样式:

defaultEdge: {
type: 'polyline',
labelCfg: {
style: {
fill: '#333',
stroke: '#aaa',
fontSize: fontSize - 2,
},
},
style: {
radius: 20,
offset: 45,
endArrow: true,
lineWidth: 3,
stroke: '#aaa',
},
},
edgeStateStyles: {
active: {
stroke: '#5a84ff',
lineWidth: 6,
'text-shape': {
fontSize: fontSize,
},
},
hover: {
stroke: '#5a84ff',
lineWidth: 6,
'text-shape': {
fontSize: fontSize,
},
},
},

章节来源

事件总线与状态管理

GraphEvent类的设计原理

GraphEvent类实现了完整的事件总线系统,负责管理所有用户交互事件和状态变化。

图表来源

事件监听器注册机制

GraphEvent类在初始化时会注册各种事件监听器:

init(graph: Graph, layout: Record<string, any>) {
this.graph = graph
this.layout = layout

// 画布事件
this.graph.on('canvas:contextmenu', this.onCanvasContextMenu)

// 触摸事件
this.graph.on('canvas:touchmove', this.onNodeTouchmove)
this.graph.on('node:touchstart', this.onNodeTouchStart)
this.graph.on('edge:touchstart', this.onNodeTouchStart)
this.graph.on('touchend', this.onNodeTouchEnd)

// 鼠标事件
this.graph.on('node:contextmenu', this.nodeContextMenu)
this.graph.on('edge:contextmenu', this.edgeContextMenu)
this.graph.on('node:mouseenter', (...arg) => this.nodeMouseOver(...arg, true))
this.graph.on('node:mouseleave', (...arg) => this.nodeMouseOver(...arg, false))
this.graph.on('edge:mouseenter', (...arg) => this.edgeMouseOver(...arg, true))
this.graph.on('edge:mouseleave', (...arg) => this.edgeMouseOver(...arg, false))
this.graph.on('edge:click', (...arg) => this.edgeClick(...arg))

// 特殊事件
this.graph.on('aftercreateedge', this.onAfterCreateEdge)
}

状态存储系统

图表来源

章节来源

交互组件设计

自定义菜单系统

G6流程引擎实现了完整的右键菜单系统,支持节点和边线的不同上下文菜单。

// 菜单项配置
const contextMenu = computed<any[]>(() => {
if (graphEvent.isShowPassNode.value && graphEvent.type.value === 'canvas') {
return [{
type: 'view',
label: _t('粘贴'),
fn: onPassNode,
divided: true,
disabled: false,
icon: 'files/pass',
}]
}

const menu: any[] = [{
type: 'view',
label: _t('查看属性'),
fn: onViewDialog,
divided: true,
disabled: false,
icon: 'viewProps',
}]

if (isEdit.value) {
if (graphEvent.type.value === 'node') {
menu.push({
label: _t('复制'),
fn: onCopyNode,
divided: true,
icon: 'copy',
type: 'copy',
})
}
menu.push({
label: _t('删除'),
fn: onDelete,
type: 'del',
divided: true,
disabled: false,
icon: 'delete-menu',
})
}
return menu
})

工具栏交互设计

工具栏提供了标准化的操作界面,支持撤销、重做、缩放、布局等功能:

图表来源

扩展接口设计

系统提供了丰富的扩展接口,允许开发者添加自定义行为和布局变换:

// 行为映射接口
export const behaviorMap: {
[key: string]: string
} = {
dragCanvas: 'drag-canvas',
dragNode: 'drag-node',
zoomCanvas: 'zoom-canvas',
clickSelect: 'click-select',
createEdge: 'create-edge',
}

// 自定义行为示例
const customBehavior = {
type: 'custom-behavior',
trigger: 'click',
callback: (graph, e) => {
// 自定义点击处理逻辑
const node = graph.find('node', { id: e.item.get('id') })
if (node) {
// 执行自定义操作
node.update({
style: { fill: '#ff0000' }
})
}
}
}

章节来源

数据转换与序列化

JSON Schema序列化规范

G6流程引擎实现了完整的XML到JSON的数据转换机制,支持复杂的流程图结构序列化。

图表来源

数据转换核心算法

// XML转JSON转换
export const getJsonByXml = (xml: string, name?: string) => {
const options = {
ignoreAttributes: false,
attributeNamePrefix: '@_',
}
const parser = new XMLParser(options)

try {
const json = parser.parse(xml)
xmlData.value = json
return json
} catch (error) {
const newXml = Core.createBaseXml(name)
const json = parser.parse(newXml)
xmlData.value = json
return json
}
}

// 流程图数据转XML
export const getFlowDataToXml = ({ nodes, edges }: FlowType) => {
const Activity: any[] = []
const Transition: any[] = []
const nodeMap: Record<string, any> = {}

nodes.forEach((item) => {
const obj: Record<string, any> = {}
Object.keys(item.properties || {}).forEach((key) => {
if (isFirstLetterUpperCase(key)) {
obj[key] = item.properties[key]
}
})
const oldId = item?.properties?.oldId
const flow = flowMap.get(oldId)
obj.Name = flow?.properties?.Name || item.properties.Name || ''
nodeMap[obj.Name] = {
x: item.x,
y: item.y,
}
Activity.push(obj)
})

edges.forEach((item) => {
const obj: Record<string, any> = {}
Object.keys(item?.properties || {}).forEach((key) => {
if (isFirstLetterUpperCase(key)) {
obj[key] = item.properties[key]
}
})
// 处理条件数据
const condition = item.properties?.Condition || {}
obj.Condition = handleConditionChildren(obj.Condition)

// 处理源节点和目标节点
const oldSourceId = item.properties?.oldSourceId
const oldTargetId = item.properties?.oldTargetId
const flowSource = flowMap.get(oldSourceId)
const flowTarget = flowMap.get(oldTargetId)

obj.Source = flowSource?.properties?.Name || ''
obj.Sink = flowTarget?.properties?.Name || ''

Transition.push(obj)
})

return getXmlByJson(Activity, Transition, nodeMap)
}

高并发场景下的数据持久化策略

图表来源

章节来源

性能优化策略

图数据缓存机制

系统实现了多层缓存机制来提升性能:

  1. 节点映射缓存:使用Map结构缓存节点ID到节点对象的映射
  2. 边线映射缓存:缓存边线关系以便快速查找
  3. XML数据缓存:避免重复解析XML数据
// 缓存优化示例
const flowMap: Map<string, any> = new Map()
const flowNodeMap: Map<string, any> = new Map()
const edgeMap = new Map()
const nodeMap = new Map()

// 使用缓存进行快速查找
const findNodeById = (id: string) => {
return flowNodeMap.get(id)
}

const findEdgeBySourceTarget = (source: string, target: string) => {
return edgeMap.get(`${source}-${target}`)
}

内存管理策略

批量操作优化

对于大量节点和边线的操作,系统提供了批量处理机制:

// 批量节点添加
const batchAddNodes = (nodes: any[]) => {
const batchData = nodes.map(node => ({
id: node.id,
type: node.type,
x: node.x,
y: node.y,
properties: node.properties
}))

graph.batchAddItems('node', batchData)
}

// 批量边线添加
const batchAddEdges = (edges: any[]) => {
const batchData = edges.map(edge => ({
id: edge.id,
source: edge.source,
target: edge.target,
type: edge.type,
properties: edge.properties
}))

graph.batchAddItems('edge', batchData)
}

故障排除指南

常见问题诊断

1. 图实例初始化失败

症状:页面显示空白或报错 原因:G6实例创建失败或配置错误 解决方案

// 检查G6版本兼容性
console.log(G6.version)

// 验证容器元素是否存在
const container = document.getElementById('g6-container')
if (!container) {
throw new Error('G6容器元素不存在')
}

// 检查配置参数
const config = {
container: 'g6-container',
width: 800,
height: 600,
...Core.prototype.setDefaultProps()
}

2. 节点拖拽失效

症状:无法拖拽节点到画布 原因:事件监听器未正确注册或权限不足 解决方案

// 检查编辑模式
if (!isEdit.value) {
console.warn('当前处于只读模式,无法拖拽节点')
return
}

// 验证事件监听器
const graph = g6RenderRef.value?.getGraph()
if (!graph) {
console.error('G6实例未初始化')
return
}

// 重新绑定事件
graph.on('node:dragstart', onDragstart)
graph.on('node:dragend', onDragend)

3. 数据保存失败

症状:保存操作无响应或报错 原因:网络问题或数据格式错误 解决方案

// 添加错误处理
const graphSave = async (isTemp: boolean = false) => {
try {
const graph = g6RenderRef.value.getGraph()
const xml = generateFlowXml(graph)

if (!xml) {
throw new Error('生成XML数据失败')
}

const data = {
...flowConfig,
content: xml,
version: flowConfig.version || 1,
}

await saveFlowData(data, isTemp)
ElMessage.success(_t('保存成功'))
} catch (error) {
console.error('保存失败:', error)
ElMessage.error(`保存失败: ${error.message}`)
}
}

性能问题排查

1. 大量节点渲染缓慢

诊断方法

// 监控渲染性能
const startTime = performance.now()
graph.render()
const endTime = performance.now()
console.log(`渲染耗时: ${endTime - startTime}ms`)

// 检查节点数量
const nodeCount = graph.getNodes().length
console.log(`节点数量: ${nodeCount}`)

优化方案

  • 使用虚拟滚动减少DOM节点
  • 实现节点懒加载机制
  • 优化节点绘制算法

2. 内存泄漏检测

// 内存使用监控
const monitorMemory = () => {
if ('memory' in performance) {
const memoryInfo = (performance as any).memory
console.log('内存使用情况:', {
usedJSHeapSize: memoryInfo.usedJSHeapSize,
totalJSHeapSize: memoryInfo.totalJSHeapSize,
jsHeapSizeLimit: memoryInfo.jsHeapSizeLimit
})
}
}

// 定期检查
setInterval(monitorMemory, 5000)

章节来源

总结

G6流程引擎是一个功能完整、架构清晰的工艺流程图设计系统。通过深入分析其核心组件和设计模式,我们可以看到以下关键特点:

技术优势

  1. 模块化设计:清晰的分层架构使得系统易于维护和扩展
  2. 事件驱动:完善的事件总线系统确保了组件间的松耦合
  3. 类型安全:TypeScript的强类型支持提高了代码质量和开发效率
  4. 性能优化:多层缓存和批量操作机制保证了良好的用户体验

架构亮点

  • Core类统一管理:提供一致的API接口和配置管理
  • GraphEvent事件总线:完整的用户交互事件处理机制
  • Store状态管理:基于Vue 3的响应式状态管理
  • 组件化节点系统:灵活的节点类型扩展能力

扩展建议

  1. 插件化架构:可以进一步抽象出插件接口,支持更多自定义功能
  2. 主题系统:实现可配置的主题系统,支持不同风格的视觉呈现
  3. 协作功能:添加实时协作功能,支持多人同时编辑
  4. 移动端优化:针对移动设备进行专门的交互优化

G6流程引擎为MES系统提供了强大的工艺流程建模能力,其设计理念和实现方式值得在类似项目中借鉴和应用。通过持续的优化和扩展,该系统能够满足更复杂的业务需求和技术挑战。