G6流程引擎技术文档
目录
简介
G6流程引擎是一个基于AntV G6构建的工艺流程图设计系统,专为MES(制造执行系统)工艺建模而设计。该引擎提供了完整的图形化流程设计能力,支持复杂的节点类型、自定义行为、交互菜单和工具栏功能。
系统使用 Vue 3 Composition API 和 TypeScript,按组件划分职责,并通过事件传递状态变化。
项目结构
G6流程引擎采用清晰的分层架构,主要组织结构如下:
图表来源
src/components/G6Flow/G6Flow.tsxsrc/components/G6Flow/core/Core.ts
章节来源
src/components/G6Flow/G6Flow.tsx
核心架构
系统架构概览
G6流程引擎采用了现代化的前端架构模式,结合Vue 3的新特性实现了高效的数据流管理和组件通信。
图表来源
src/components/G6Flow/G6Flow.tsxsrc/components/G6Flow/core/Core.tssrc/components/G6Flow/core/store.tssrc/components/G6Flow/core/GraphEvent.ts
模块依赖关系
系统各模块之间存在清晰的依赖关系,通过依赖注入和事件总线实现松耦合设计:
图表来源
src/components/G6Flow/G6Flow.tsxsrc/components/G6Flow/core/store.ts
章节来源
src/components/G6Flow/G6Flow.tsxsrc/components/G6Flow/core/Core.ts
图实例管理
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',
},
},
}
}
图实例生命周期管理
图表来源
src/components/G6Flow/core/Core.tssrc/components/G6Flow/core/store.ts
章节来源
src/components/G6Flow/core/Core.ts
节点与边线系统
基础节点组件化封装
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
},
},
}
节点状态样式系统
图表来源
src/components/G6Flow/core/Core.ts
边线配置与样式
系统支持多种类型的边线配置,包括默认边线样式和状态样式:
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,
},
},
},
章节来源
src/components/G6Flow/components/Nodes/StartNode.tsxsrc/components/G6Flow/components/Nodes/OrdinaryNode.tsxsrc/components/G6Flow/core/Core.ts
事件总线与状态管理
GraphEvent类的设计原理
GraphEvent类实现了完整的事件总线系统,负责管理所有用户交互事件和状态变化。
图表来源
src/components/G6Flow/core/GraphEvent.tssrc/components/G6Flow/core/store.ts
事件监听器注册机制
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)
}
状态存储系统
图表来源
src/components/G6Flow/core/store.ts
章节来源
src/components/G6Flow/core/GraphEvent.tssrc/components/G6Flow/core/store.ts
交互组件设计
自定义菜单系统
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
})
工具栏交互设计
工具栏提供了标准化的操作界面,支持撤销、重做、缩放、布局等功能:
图表来源
src/components/G6Flow/components/ToolBar/ToolBar.tsx
扩展接口设计
系统提供了丰富的扩展接口,允许开发者添加自定义行为和布局变换:
// 行为映射接口
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' }
})
}
}
}
章节来源
src/components/G6Flow/G6Flow.tsxsrc/components/G6Flow/components/ToolBar/ToolBar.tsxsrc/components/G6Flow/components/Menu/Menu.tsxsrc/components/G6Flow/core/behavior.ts
数据转换与序列化
JSON Schema序列化规范
G6流程引擎实现了完整的XML到JSON的数据转换机制,支持复杂的流程图结构序列化。
图表来源
src/components/G6Flow/core/transformHelp.ts
数据转换核心算法
// 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)
}
高并发场景下的数据持久化策略
图表来源
src/components/G6Flow/core/transformHelp.ts
章节来源
src/components/G6Flow/core/transformHelp.tssrc/api/logic-flow.ts
性能优化策略
图数据缓存机制
系统实现了多层缓存机制来提升性能:
- 节点映射缓存:使用Map结构缓存节点ID到节点对象的映射
- 边线映射缓存:缓存边线关系以便快速查找
- 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)
章节来源
src/components/G6Flow/G6Flow.tsxsrc/components/G6Flow/core/GraphEvent.ts
总结
G6 流程引擎的组件和设计方式如下:
技术优势
- 模块化设计:清晰的分层架构使得系统易于维护和扩展
- 事件驱动:完善的事件总线系统确保了组件间的松耦合
- 类型安全:TypeScript的强类型支持提高了代码质量和开发效率
- 性能优化:多层缓存和批量操作机制保证了良好的用户体验
架构亮点
- Core类统一管理:提供一致的API接口和配置管理
- GraphEvent事件总线:完整的用户交互事件处理机制
- Store状态管理:基于Vue 3的响应式状态管理
- 组件化节点系统:灵活的节点类型扩展能力
扩展建议
- 插件化架构:可以进一步抽象出插件接口,支持更多自定义功能
- 主题系统:实现可配置的主题系统,支持不同风格的视觉呈现
- 协作功能:添加实时协作功能,支持多人同时编辑
- 移动端优化:针对移动设备进行专门的交互优化