BPMN编辑器技术实现总结AI时代的工作流编辑器

项目概述

基于 diagram.js 的 BPMN 流程设计器,通过依赖注入(DI)实现模块化扩展,自定义模块扩展与SVG图形渲染。后端工作流引擎自定义统一任务调度函数,实现异构模型统一调用。
在这里插入图片描述

核心技术架构

1. diagram.js 架构基础

核心模块组成
  • Canvas: 画布管理,负责SVG容器的创建和管理
  • ElementRegistry: 元素注册表,管理所有图形元素的生命周期
  • GraphicsFactory: 图形工厂,负责创建和渲染图形元素
  • EventBus: 事件总线,实现模块间的解耦通信
  • Renderer: 渲染器,负责具体的图形绘制逻辑
渲染流程
用户操作 → EventBus → ElementRegistry → GraphicsFactory → Renderer → SVG渲染

2. 依赖注入(DI)机制实现

模块注册机制
// ProcessDesigner.vue 中的依赖注入配置
const additionalModules = [CustomModule,           // 自定义模块TranslateModule,        // 翻译模块tokenSimulation,        // 流程模拟模块flowableModdleExtension // Flowable扩展
];// CustomModeler 初始化
this.bpmnModeler = new CustomModeler({container: this.$refs["bpmn-canvas"],additionalModules: this.additionalModules,moddleExtensions: this.moddleExtensions
});
自定义模块结构
// customModule/index.js - 模块定义
export default {__init__: ['customPalette', 'customRenderer', 'customContextPad'],customPalette: ['type', CustomPalette],customRenderer: ['type', CustomRenderer],customContextPad: ['type', CustomContextPad]
}

3. 模块化扩展实现

3.1 自定义调色板(CustomPalette)

功能: 扩展工具面板,添加灾害模型节点

// 依赖注入声明
CustomPalette.$inject = ['bpmnFactory', 'create', 'elementFactory', 'palette', 'translate'
];// 创建自定义节点
function createAction(type, group, className, title, options) {const shape = elementFactory.createShape(assign({ type: type }))shape.businessObject.customType = options.customType;shape.businessObject.name = options.name;create.start(event, shape);
}// 注册灾害模型节点
return {"create.flood-task": createAction("bpmn:CallActivity", "activity", "custom-icon-flood-task", "Create Flood Task", {customType:"flood", name:"调用内涝模型"}),// ... 其他灾害模型
}
3.2 自定义上下文菜单(CustomContextPad)

功能: 右键菜单扩展,快速创建相关节点

// 动态生成上下文菜单项
const taskTypes = [{ customType: 'flood', icon: 'custom-icon-flood-task', title: '创建内涝节点' },{ customType: 'fire', icon: 'custom-icon-fire-task', title: '创建火灾节点' },// ...
];taskTypes.forEach(({ customType, icon, title }) => {entries[`append.${icon}`] = {group: 'activity',className: `icon-custom ${icon}`,title: translate(title),action: {click: (event) => createListener(event, customType)}};
});

4. SVG自定义图形渲染

4.1 自定义渲染器(CustomRenderer)

核心: 继承BaseRenderer,实现自定义图形绘制

export default class CustomRenderer extends BaseRenderer {constructor(eventBus, bpmnRenderer) {super(eventBus, HIGH_PRIORITY) // 设置高优先级this.bpmnRenderer = bpmnRenderer}canRender(element) {return !element.labelTarget // 忽略标签元素}drawShape(parentNode, element) {const type = element.typeif (customElements.includes(type)) {// 解析自定义类型const regex = /调用(.*?)模型/;const res = element.businessObject.name.match(regex);const name = res && res[1];// 映射到图标类型let customType = this.mapNameToType(name);if (customType) {const { url, attr } = customConfig[customType];// 创建SVG图像元素const customIcon = svgCreate('image', {...attr,href: url});// 设置元素尺寸element['width'] = attr.width;element['height'] = attr.height;// 渲染到父节点svgAppend(parentNode, customIcon);// 渲染文本标签this.renderLabel(parentNode, element, attr);return customIcon;}}// 回退到默认渲染return this.bpmnRenderer.drawShape(parentNode, element);}
}
4.2 图标资源管理

动态加载: 使用webpack的require.context动态导入图标

// 动态导入所有PNG图标
const iconContext = require.context('../icons', false, /\.png$/);const customConfig = {};
iconContext.keys().forEach((key) => {const iconName = key.replace(/^\.\/(.*)\.png$/, '$1');customConfig[iconName] = {url: iconContext(key),attr: { x: 0, y: 0, width: 68, height: 68 }};
});

5. 技术特点与优势

5.1 模块化设计
  • 松耦合: 通过依赖注入实现模块间解耦
  • 可扩展: 新增功能只需添加新模块,无需修改核心代码
  • 可维护: 每个模块职责单一,便于维护和测试
5.2 高优先级渲染
const HIGH_PRIORITY = 1500; // 确保自定义渲染器优先执行
5.3 事件驱动架构
// 监听元素变化事件
EventBus.on("commandStack.changed", async event => {// 实时更新XMLlet { xml } = await this.bpmnModeler.saveXML({ format: true });this.$emit("input", xml);
});

6. 后端工作流引擎集成

统一任务调度函数
  • 异构模型统一调用: 通过customType字段区分不同灾害模型
  • 标准化接口: 所有模型节点统一使用CallActivity类型
  • 参数传递: 通过businessObject传递模型特定参数
// 节点创建时设置自定义属性
shape.businessObject.customType = options.customType;
shape.businessObject.name = options.name;

7. 面试要点总结

技术深度
  1. diagram.js架构理解: 掌握Canvas、ElementRegistry、GraphicsFactory等核心模块
  2. 依赖注入机制: 理解DI容器的工作原理和模块注册机制
  3. SVG渲染原理: 掌握tiny-svg库的使用和自定义图形绘制
  4. 事件驱动模式: 理解EventBus的作用和事件监听机制
实现难点
  1. 渲染优先级控制: 通过HIGH_PRIORITY确保自定义渲染器优先执行
  2. 元素类型映射: 通过正则表达式解析节点名称,映射到对应图标
  3. 动态资源加载: 使用webpack的require.context实现图标的动态导入
  4. 模块间通信: 通过依赖注入和事件总线实现模块解耦
项目价值
  1. 业务适配: 针对灾害应急场景定制化的流程设计器
  2. 技术创新: 基于开源框架的深度定制和扩展
  3. 架构设计: 良好的模块化设计,便于后续功能扩展
  4. 用户体验: 直观的图形化界面,降低流程设计门槛

8. 技术栈总结

  • 前端框架: Vue.js + Element UI
  • 流程引擎: bpmn-js + diagram.js
  • 图形渲染: SVG + tiny-svg
  • 模块管理: 依赖注入 + ES6模块
  • 构建工具: Webpack (require.context)
  • 后端集成: Flowable工作流引擎

这个项目展示了对前端架构设计、模块化开发、图形渲染等多个技术领域的深入理解和实践能力。


BPMN.js 自定义扩展模块与SVG自定义图形渲染实现原理

1. BPMN.js 架构概述

1.1 核心架构

bpmn-js
├── Viewer (查看器)
├── Modeler (建模器)
├── NavigatedViewer (带导航的查看器)
└── 核心模块系统├── diagram-js (图形引擎)├── bpmn-moddle (BPMN元模型)└── 各种扩展模块

1.2 依赖注入系统

  • 基于 didi 依赖注入框架
  • 模块化设计,每个功能都是独立的模块
  • 通过模块注册和依赖解析实现松耦合

2. 自定义扩展模块实现

2.1 模块结构

// 自定义模块示例
export default {__init__: ['customRenderer', 'customPaletteProvider'],customRenderer: ['type', CustomRenderer],customPaletteProvider: ['type', CustomPaletteProvider]
};

2.2 模块注册机制

// 在 Modeler 中注册自定义模块
import BpmnModeler from 'bpmn-js/lib/Modeler';
import customModule from './custom-module';const modeler = new BpmnModeler({container: '#canvas',additionalModules: [customModule]
});

2.3 核心扩展点

A. Renderer (渲染器)
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';export default class CustomRenderer extends BaseRenderer {constructor(eventBus, styles) {super(eventBus, 1500); // 优先级this.styles = styles;}canRender(element) {// 判断是否可以渲染该元素return element.type === 'custom:Task';}drawShape(parentNode, element) {// 绘制自定义形状const shape = this.drawCustomShape(parentNode, element);return shape;}drawConnection(parentNode, element) {// 绘制自定义连接线return this.drawCustomConnection(parentNode, element);}
}
B. PaletteProvider (工具面板提供者)
export default class CustomPaletteProvider {constructor(palette, create, elementFactory, spaceTool, lassoTool) {this.palette = palette;this.create = create;this.elementFactory = elementFactory;}getPaletteEntries() {return {'custom-task': {group: 'custom',className: 'custom-task-icon',title: '自定义任务',action: {dragstart: this.createCustomTask.bind(this),click: this.createCustomTask.bind(this)}}};}createCustomTask(event) {const shape = this.elementFactory.createShape({type: 'custom:Task'});this.create.start(event, shape);}
}
C. ContextPadProvider (上下文菜单提供者)
export default class CustomContextPadProvider {constructor(contextPad, modeling, elementFactory) {this.contextPad = contextPad;this.modeling = modeling;this.elementFactory = elementFactory;}getContextPadEntries(element) {if (element.type !== 'custom:Task') {return {};}return {'custom-action': {group: 'edit',className: 'custom-action-icon',title: '自定义操作',action: {click: this.performCustomAction.bind(this, element)}}};}
}

3. SVG自定义图形渲染实现

3.1 SVG渲染原理

// 自定义形状渲染
drawCustomShape(parentNode, element) {const { width, height } = element;// 创建SVG组const group = this.svgCreate('g');// 绘制主体形状const rect = this.svgCreate('rect', {x: 0,y: 0,width: width,height: height,rx: 10,ry: 10,fill: '#e1f5fe',stroke: '#01579b','stroke-width': 2});// 添加图标const icon = this.svgCreate('path', {d: 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z',fill: '#01579b',transform: `translate(${width/2 - 12}, ${height/2 - 12})`});// 添加文本const text = this.svgCreate('text', {x: width / 2,y: height - 10,'text-anchor': 'middle','font-size': '12px',fill: '#01579b'});text.textContent = element.businessObject.name || 'Custom Task';// 组装元素group.appendChild(rect);group.appendChild(icon);group.appendChild(text);// 添加到父节点parentNode.appendChild(group);return group;
}

3.2 SVG工具方法

// SVG创建工具方法
svgCreate(tagName, attrs = {}) {const element = document.createElementNS('http://www.w3.org/2000/svg', tagName);Object.keys(attrs).forEach(key => {element.setAttribute(key, attrs[key]);});return element;
}// 路径绘制工具
createPathData(points) {return points.map((point, index) => {const command = index === 0 ? 'M' : 'L';return `${command} ${point.x} ${point.y}`;}).join(' ');
}

3.3 连接线自定义渲染

drawCustomConnection(parentNode, element) {const waypoints = element.waypoints;// 创建路径数据const pathData = this.createPathData(waypoints);// 创建路径元素const path = this.svgCreate('path', {d: pathData,fill: 'none',stroke: '#ff5722','stroke-width': 3,'stroke-dasharray': '5,5','marker-end': 'url(#custom-arrow)'});parentNode.appendChild(path);return path;
}

4. 元模型扩展

4.1 自定义元素定义

// moddle扩展定义
const customModdleExtension = {name: 'custom',uri: 'http://custom.example.com/schema/bpmn',prefix: 'custom',xml: {tagAlias: 'lowerCase'},types: [{name: 'CustomTask',extends: ['bpmn:Task'],properties: [{name: 'customProperty',type: 'String'},{name: 'priority',type: 'Integer'}]}]
};// 在Modeler中使用
const modeler = new BpmnModeler({moddleExtensions: {custom: customModdleExtension}
});

4.2 属性面板扩展

// 自定义属性提供者
export default class CustomPropertiesProvider {constructor(propertiesPanel, injector) {this.propertiesPanel = propertiesPanel;this.injector = injector;}getGroups(element) {if (element.type !== 'custom:Task') {return [];}return [{id: 'custom-properties',label: '自定义属性',entries: [{id: 'custom-property',label: '自定义属性',modelProperty: 'customProperty',widget: 'textField'},{id: 'priority',label: '优先级',modelProperty: 'priority',widget: 'textField'}]}];}
}

5. 事件系统与交互

5.1 事件监听

// 自定义行为处理器
export default class CustomBehavior {constructor(eventBus, modeling) {this.eventBus = eventBus;this.modeling = modeling;// 监听元素创建事件eventBus.on('shape.added', (event) => {const { element } = event;if (element.type === 'custom:Task') {this.handleCustomTaskAdded(element);}});// 监听元素选择事件eventBus.on('selection.changed', (event) => {this.handleSelectionChanged(event.newSelection);});}handleCustomTaskAdded(element) {// 自定义任务添加后的处理逻辑console.log('Custom task added:', element);}
}

5.2 命令扩展

// 自定义命令处理器
export default class CustomCommandHandler {constructor(modeling) {this.modeling = modeling;}preExecute(context) {// 命令执行前的处理}execute(context) {// 执行自定义命令const { element, newProperties } = context;return this.modeling.updateProperties(element, newProperties);}revert(context) {// 撤销命令const { element, oldProperties } = context;return this.modeling.updateProperties(element, oldProperties);}
}

6. 完整示例:自定义审批节点

// 自定义审批节点模块
import CustomRenderer from './CustomRenderer';
import CustomPaletteProvider from './CustomPaletteProvider';
import CustomContextPadProvider from './CustomContextPadProvider';
import CustomBehavior from './CustomBehavior';export default {__init__: ['customRenderer','customPaletteProvider', 'customContextPadProvider','customBehavior'],customRenderer: ['type', CustomRenderer],customPaletteProvider: ['type', CustomPaletteProvider],customContextPadProvider: ['type', CustomContextPadProvider],customBehavior: ['type', CustomBehavior]
};// 审批节点渲染器
class ApprovalRenderer extends BaseRenderer {drawShape(parentNode, element) {if (element.type !== 'custom:ApprovalTask') {return;}const { width, height } = element;// 创建审批节点的特殊形状const group = this.svgCreate('g');// 主体矩形const rect = this.svgCreate('rect', {x: 0,y: 0,width: width,height: height,rx: 15,fill: '#fff3e0',stroke: '#f57c00','stroke-width': 2});// 审批图标const icon = this.svgCreate('path', {d: 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z',fill: '#f57c00',transform: `translate(${width/2 - 12}, ${height/2 - 12})`});// 状态指示器const statusCircle = this.svgCreate('circle', {cx: width - 10,cy: 10,r: 5,fill: this.getStatusColor(element)});group.appendChild(rect);group.appendChild(icon);group.appendChild(statusCircle);parentNode.appendChild(group);return group;}getStatusColor(element) {const status = element.businessObject.approvalStatus;switch(status) {case 'pending': return '#ffc107';case 'approved': return '#4caf50';case 'rejected': return '#f44336';default: return '#9e9e9e';}}
}

7. 面试要点总结

7.1 核心概念

  • 模块化架构:基于依赖注入的松耦合设计
  • 渲染器机制:通过优先级控制自定义渲染逻辑
  • 事件驱动:完整的事件系统支持交互扩展
  • 元模型扩展:支持BPMN标准的自定义扩展

7.2 技术难点

  • SVG操作:熟练掌握SVG DOM操作和路径绘制
  • 依赖注入:理解didi框架的工作原理
  • 事件传播:掌握事件的冒泡和捕获机制
  • 模块注册:理解模块的生命周期和初始化顺序

7.3 最佳实践

  • 性能优化:合理使用渲染优先级,避免重复渲染
  • 代码组织:模块化拆分,职责单一
  • 扩展性设计:预留扩展点,支持插件化开发
  • 错误处理:完善的错误边界和降级策略

7.4 常见问题

  1. 如何实现自定义形状?

    • 继承BaseRenderer,实现canRender和drawShape方法
    • 使用SVG API创建自定义图形
  2. 如何添加工具面板按钮?

    • 实现PaletteProvider接口
    • 返回工具项配置对象
  3. 如何处理自定义属性?

    • 扩展moddle元模型
    • 实现PropertiesProvider
  4. 如何实现拖拽创建?

    • 在PaletteProvider中配置dragstart事件
    • 使用create服务启动拖拽

这套扩展机制使得bpmn.js具有极强的可定制性,能够满足各种复杂的业务流程建模需求。


AI时代(更智能)

节点类型、数据类型(多模态)、

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 动态路径选择 :基于AI推理结果动态选择执行分支

在这里插入图片描述


关键词汇

  • 技术栈演进:Diagram.js → FlowGram
  • 架构模式:事件驱动 → 数据流驱动
  • 核心挑战:类型系统、异步调度、性能优化
  • 发展趋势:多模态、Agent编排、自然语言编程

面试表达:AI时代流程编辑器技术总结

开场介绍(第一段)

“关于AI时代的流程编辑器,我认为这是一个非常有意思的技术演进话题。传统的BPMN流程编辑器主要解决的是业务流程标准化问题,比如我们项目中使用的基于diagram.js的流程设计器,通过依赖注入实现模块化扩展。但AI工作流编辑器解决的是完全不同的问题域——它是为AI模型编排和数据处理管道而设计的。从技术架构上看,传统编辑器是事件驱动的流程引擎,而AI工作流编辑器是数据流驱动的DAG调度器。”

主流产品分析(第二段)

“目前主流的AI工作流编辑器中,字节跳动的Coze工作流是比较典型的代表。它的核心特点是低代码设计,用户可以通过拖拽LLM节点、工具节点、逻辑节点来构建复杂的AI应用。技术栈上,前端使用React + Canvas渲染,后端是自研的执行引擎,支持实时调试和版本管理。除了Coze,还有开源的LangFlow基于LangChain + ReactFlow,Dify支持多模态和RAG集成,ComfyUI专注于图像生成工作流。这些产品都体现了从传统流程图向智能化编排平台的转变。”

技术实现深度(第三段)

“从技术实现角度,AI工作流编辑器的核心挑战在于节点系统设计和数据流管理。节点需要支持强类型的输入输出,比如text、image、audio、embedding等数据类型,还要处理异步执行、错误重试、并行调度等复杂场景。前端通常基于React Flow或类似的图形库,需要实现自定义节点组件、连线验证、实时预览等功能。执行引擎则需要构建DAG,进行拓扑排序,管理执行上下文。相比传统的BPMN编辑器,这里的技术复杂度主要体现在数据类型系统和异步执行调度上。”

发展趋势展望(第四段)

“我认为AI工作流编辑器的发展趋势有几个方向:首先是多模态融合,未来会支持文本、图像、音频、视频的统一处理;其次是Agent编排,从单一模型调用发展到多智能体协作;第三是自然语言编程,用户可以用自然语言描述需求,AI自动生成工作流;最后是边缘计算集成,支持在边缘设备上部署轻量化的AI工作流。这个领域还在快速发展中,技术栈也在不断演进,对前端开发者来说是一个很有挑战性的方向。”

个人技术见解(第五段)

“基于我在BPMN流程设计器上的开发经验,我觉得AI工作流编辑器和传统流程编辑器在架构设计上有很多相通之处,比如模块化设计、依赖注入、事件系统等。但也有本质差异,AI工作流更注重数据流的类型安全和执行性能。如果让我来设计一个AI工作流编辑器,我会重点关注几个方面:一是建立完善的类型系统,确保节点间数据流的类型安全;二是实现高效的虚拟化渲染,支持大规模节点的流畅操作;三是设计灵活的插件系统,支持第三方节点扩展;四是提供完善的调试和监控能力,帮助用户快速定位问题。”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/93142.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

两阶段最小二乘法(2SLS)与 工具变量(IV)模型

以下是关于两阶段最小二乘法(2SLS)与工具变量(IV)模型关系的系统解析,结合计量经济学理论与论文上下文进行说明:一、核心关系:2SLS是IV模型的实现方法 1. IV模型:解决内生性的理论框…

熬夜面膜赛道跑出的新物种

在快节奏的现代生活中,熬夜已成为都市人群的常态,深夜11点后的朋友圈总是一片“失眠”哀嚎。随之而来的是“熬夜肌”问题的激增——暗沉、干燥、屏障受损等诉求催生了庞大的熬夜面膜市场。2025年,中国面膜线上规模已达484亿元,其中…

20250813测试开发岗(凉)面

1. 自我介绍2. 你如何理解测开,你认为测开的工作有哪些3. 测试的时候包括哪些部分4. 就功能层面,你认为需要从那些部分考虑,形成一个完整并可执行的trace(是这个词吧)5. 你了解数据库吗(我说只会比较基础的…

面向Python/C#开发者入门Java与Bukkit API

本教程将以"手持发射器箭矢机枪"功能为例,带你掌握Java语言基础和Bukkit API的核心概念,最终实现自主开发插件。 我们将通过剖析一个实际Java代码文件,逐步解析其运作机制,帮助你顺利将现有编程知识迁移到Java和Bukkit…

从100到0.3美元:GPT-5用价格战血洗大模型赛道

————————— 一、从 100 美元到 0.3 美元:史无前例的效率革命 ————————— 互联网女王 Mary Meeker 在《AI 趋势报告 2025》里写下这组数字: • 训练成本 8 年飙升 2400 倍; • 推理成本 2 年暴跌 99.7%。OpenAI 把“暴跌”推到…

第三十二天(文件操作安全)

文件遍历上传下载删除编辑包含等 $_FILES:PHP中一个预定义的超全局变量,用于在上传文件时从客户端接收文件,并将其保存到服务器上。它是一个包含上传文件信息的数组,包括文件名、类型、大小、临时文件名等信息。 $_FILES"表…

系统集成项目管理工程师【第十一章 规划过程组】规划风险应对、规划采购管理篇

系统集成项目管理工程师【第十一章 规划过程组】规划风险应对、规划采购管理篇 一、规划风险应对:为项目穿上"防护衣" 1. 什么是规划风险应对? 规划风险应对是基于风险量化分析结果,制定可选方案、选择应对策略并商定具体行动的过程…

20250813比赛总结

题目T1.volumeT2.storyT3.treeT4.game预计分数6060030实际分数306000T1.volume 确实是暴力,但我是用数组统计每个可能出现的数,于是3AC 3WA 4TLE。拿到全部分应该直接按照题目模拟。 T2.story 暴力dfs,由于忘记优化所以60pts,而且…

适合物流/应急/工业的对讲机,AORO M6 Pro构建高效指挥调度方案

在物流调度、应急救援与工业协同等对通信可靠性要求极高的领域中,专业对讲设备的技术迭代直接关系到任务执行效率与安全保障。AORO M6 Pro对讲机作为新一代融合通信终端,正以多模融合技术与国产化自主创新,为复杂场景下的高效调度提供坚实的技…

类和对象----中

这里写目录标题<font color"#FF00FF">1. 类和对象(中)<font color"#FF00FF">2. 构造函数<font color"#FF00FF">3. 析构函数<font color"#FF00FF">4. 拷⻉构造函数1. 类和对象(中) 类的默认成员函数&#xff1…

CAD 的 C# 开发中,对多段线(封闭多边形)内部的点进行 “一笔连线且不交叉、不出界

本质上是约束条件下的路径规划问题&#xff0c;核心是找到一条连续路径遍历所有点&#xff0c;同时满足&#xff1a; 路径不与自身交叉&#xff1b; 路径全程在多段线&#xff08;多边形&#xff09;内部&#xff1b; 路径连续&#xff08;一笔画&#xff09;。核心思路与算法步…

ZED 2i相机调试

1. 测试 ZED SDK /usr/local/zed/tools/ZED_Diagnostic/usr/local/zed/tools/ZED_Explorer2. 安装SDK How to Install ZED SDK on Linux - Stereolabs 安装命令&#xff1a; sudo apt install zstd./ZED_SDK_Ubuntu20_cuda12.1_tensorrt8.6_v5.0.5.zstd.run

Go语言select并发编程实战指南

一、select作用Go 语言中的 select 语句是处理多通道&#xff08;Channel&#xff09;操作的核心控制结构&#xff0c;专为高效并发通信而设计。通过巧妙运用 select 语句&#xff0c;开发者能够高效实现并发控制、超时处理和非阻塞通信等功能&#xff0c;使其成为 Go 语言并发…

OpenCV常见问题汇总

1、深度拷贝的问题我对整张图像通过裁剪分别进行识别&#xff0c;出现识别结果与期望不同的问题&#xff0c;经过大量排查是OpenCV深度拷贝问题&#xff0c;我原来有问题的写法cv::Mat matCrop matZoom(roi); cv::Mat matCrop1 matCrop(roi1); cv::Mat matCrop2 matCrop(roi2)…

【Unity开发】Unity核心学习(一)

一、2D相关1、图片导入相关设置 &#xff08;1&#xff09;Unity支持的图片格式 支持BMP、TIF、JPG、PNG、TGA、PSD 常用格式具体介绍&#xff1a; JPG&#xff1a;指JPGE格式&#xff0c;属于有损压缩格式&#xff0c;无透明通道 PNG&#xff1a;无损压缩格式&#xff0c;有透…

Python自定义异常类的写法与使用场景

在软件开发的生命周期中&#xff0c;异常处理是保障程序健壮性与可维护性的关键环节。Python作为一门高级编程语言&#xff0c;内置了丰富的异常机制&#xff0c;能够高效、优雅地应对运行时的各种错误。然而&#xff0c;面对复杂业务场景和多层架构时&#xff0c;内置异常往往…

为 Promethus 配置https访问

一、序言 本篇将介绍如何使用数字证书为Promethus 访问提供加密功能&#xff0c;由于是实验环境证书由openssl生成&#xff0c;操作指南来自官网手册&#xff1a;https://prometheus.io/docs/guides/tls-encryption/在生产环境中prometheus可能会放在后端&#xff0c;证书一般配…

摆脱例行 SQL 报表的隐性成本:用 n8n 构建四节点自动化报告流程

例行 SQL 报表的隐藏成本 各类组织的数据团队都面临同样的反复难题:利益相关方需要定期报告,但手工 SQL 报表占用了本可用于分析的宝贵时间。无论公司规模如何,流程几乎一致——连接数据库、执行查询、格式化结果,并将结论分发给决策者。 数据从业者经常要处理并不需要高…

HCIP——OSPF综合实验

一、实验拓扑二、实验要求1、R4为ISP&#xff0c;其上只配置IP地址&#xff1b;R4与其他所直连设备间均使用公有IP&#xff1b; 2、R3-R5、R6、R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;除了R12有两个环回&#x…

GitHub 趋势日报 (2025年08月12日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图1397gpt4all442system-prompts-and-models-of-ai-tools331umami307full-stack-fast…