diff --git a/.cursor/rules/warm-flow.mdc b/.cursor/rules/warm-flow.mdc new file mode 100644 index 0000000000000000000000000000000000000000..93a495eae529beba7303cc31690b2816e1112146 --- /dev/null +++ b/.cursor/rules/warm-flow.mdc @@ -0,0 +1,48 @@ +--- +description: warm-flow 工程编码与协作规则;以根 AGENTS.md 为唯一来源,约束 JDK1.8 兼容、框架解耦、对外契约与多生态/多ORM/多DB +globs: * +alwaysApply: true +--- + +# warm-flow 工程规则(Cursor) + +本规则是 `warm-flow`(Dromara 开源轻量级工作流引擎 / SDK)的编码与协作约束摘要,**以根 [AGENTS.md](mdc:AGENTS.md) 为唯一来源**。开始任务前先读根 `AGENTS.md`;改动所在顶层模块下若有模块级 `AGENTS.md`(`warm-flow-core`/`warm-flow-orm`/`warm-flow-plugin`/`warm-flow-ui`),再读模块级。本文件与 `AGENTS.md` 冲突时以 `AGENTS.md` 为准。 + +## 规则优先级 + +1. 用户当前明确指令。 +2. 模块级 `AGENTS.md`(若存在)。 +3. 根 `AGENTS.md`。 +4. 本规则与根 `CLAUDE.md`(与 `AGENTS.md` 冲突以 `AGENTS.md` 为准)。 +5. `.qoder/repowiki` 等领域 / 架构参考。 + +## 项目性质 + +被他人依赖的**开源类库 / SDK**(Maven 中央仓库,`groupId=org.dromara.warm`),不是业务应用。三大最高约束:**JDK 1.8 源码级兼容**、**对外契约向后兼容**、**核心与框架 / ORM / JSON 解耦**。 + +## 模块速览 + +- `warm-flow-core`:框架 / ORM / JSON 无关的引擎核心(实体、服务、抽象 `WarmDao`、`FlowEngine`、`FrameInvoker`、SPI、表达式 / 监听器策略)。 +- `warm-flow-orm`:ORM 适配,按「ORM(mybatis / mybatis-plus / easy-query) × (sb/sb3/sb4/solon)」矩阵实现 `WarmDao`。 +- `warm-flow-plugin`:可插拔扩展(`modes` 表达式、`json` 序列化、`ui` 设计器后端)。 +- `warm-flow-ui`:Vue3 + Vite 前端设计器,独立于 Maven 反应堆,许可证 MIT。 +- `sql/`:mysql / oracle / postgresql / sqlserver 四套脚本 + MySQL `v1-upgrade/`。 + +## 核心红线(详见 AGENTS.md) + +1. **JDK 8 语法**:主代码禁止 `var`/`record`/switch 表达式/文本块/`List.of`/`Optional.isEmpty`/`Stream.toList`/`String.isBlank` 等 Java 9+ API;优先用 core 的 `utils.*`。 +2. **解耦**:`warm-flow-core` 禁止 import `org.springframework.*` / `org.noear.solon.*` / `com.baomidou.*`;框架差异走 `FrameInvoker` + SPI + 各 starter,ORM 差异走 `WarmDao` 实现。 +3. **门面**:统一通过 `FlowEngine.xxxService()` / `FlowEngine.newXxx()` 取服务和建实体,不绕过门面直接 new 实现类。 +4. **向后兼容**:公共方法签名、`WarmDao` 接口、实体字段、枚举常量(code / 顺序)、`WarmFlow` 配置项是已发布契约,不随意删 / 改签名 / 重排;废弃用 `@Deprecated` 留过渡期。 +5. **多生态对齐**:改某 starter 能力时,确认 `sb`/`sb3`/`sb4`/`solon` 与对应 ORM 模块是否需同步;自动装配按 SB2 `spring.factories`、SB3/4 `AutoConfiguration.imports`、Solon `META-INF/solon/*.properties` 注册。 +6. **SQL 四套同步**:表结构改动同步四库全量脚本 + 新增 `v1-upgrade/warm-flow_x.x.x.sql`,写明各库方言兼容与回滚。 +7. **扩展机制**:新增 JSON 走 `JsonConvert` + `META-INF/services`;新增 ORM / 框架走五件套矩阵 + 对应自动装配。 +8. **状态机**:通过 / 退回 / 跳转 / 转办 / 加减签 / 终止 / 撤回 / 票签 / 网关有副作用,改动前读对应 `service.impl` / `strategy` / `listener` 与状态枚举。 +9. **品牌与协议**:保留每个 Java 文件 Apache 2.0 license header、`@author warm`、`org.dromara.warm` 包名、banner、README 链接与 `LICENSE`,不弱化「永久开源免费」声明。 + +## 验证与安全边界 + +- 本仓库无 `src/test`(测试在独立仓库 `warm-flow-test`),用**分模块编译**验证:`mvn -pl -am -DskipTests compile` 或 `mvn clean install -DskipTests`;core 改动至少编译一个下游 orm/plugin 模块。前端用 `yarn dev` / `yarn build:prod`。无法验证时如实报告命令、现象、风险与下一步。 +- 未经用户明确批准:不 `git commit` / `git push`、不 `mvn deploy` / 改版本推送、不改写历史、不执行 `DROP` / 批量 `DELETE`、不降 JDK 基线 / 删编译插件、不输出真实发布凭证。 + +完整规则见根 [AGENTS.md](mdc:AGENTS.md)。 diff --git a/.gitignore b/.gitignore index 109ec935ff0f16efac5f7805110f7e47b1eb07a7..79b20bfe324901f3ee6184a0d389fc135e80ff11 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,20 @@ build/ .soloncode/ /.qoder/ +/.cursor/rules/qingtian-mcp.mdc +/.cursor/mcp.json +/.playwright-cli/ +/output/ +/warm-flow-designer-demo/warm-flow-antdv4-designer-demo/.playwright-cli/ +/warm-flow-designer-demo/warm-flow-antdv4-designer-demo/node_modules/ +/warm-flow-designer-demo/warm-flow-antdv4-designer-demo/dist/ +/warm-flow-designer-demo/warm-flow-ep-designer-demo/.playwright-cli/ +/warm-flow-designer-demo/warm-flow-ep-designer-demo/dist/ +/warm-flow-designer-demo/warm-flow-ep-designer-demo/node_modules/ +/warm-flow-vue-designer/node_modules/ +/warm-flow-vue-designer/output/ +/warm-flow-vue-designer/dist/ +/node_modules/ +/.codex/ +/warm-flow-vue-designer/.playwright-cli/ +/warm-flow-vue-designer/dist-lib/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000000000000000000000000000000000..a91856c05c9d51ec4f10c408601dc0c88b818ba6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,237 @@ +# AGENTS.md + +本文件是 Codex 以及其他 coding agent 在本仓库工作的项目级操作指南,也是本仓库 **AI 规则的唯一主来源**。 + +它综合了: + +- 当前 `warm-flow` 仓库的真实模块结构、技术基线与扩展机制。 +- dromara 开源协作约定与 Apache 2.0 开源协议要求。 +- 工作流引擎作为「公共依赖库(SDK)」对外契约稳定与多生态兼容的长期规则。 +- Karpathy 风格 coding-agent 规则:澄清不确定性、保持简单、避免顺手改无关代码、用可验证结果证明行为。 + +## 项目概览 + +`warm-flow` 是 [Dromara](https://dromara.org/) 社区的国产轻量级工作流引擎,`groupId=org.dromara.warm`,发布到 Maven 中央仓库供他人依赖。它**是一个被集成的类库 / SDK,不是业务应用**:简洁轻量(核心仅 7 张表)、五脏俱全、扩展性强,可通过 jar 包快速集成流程设计器,原生支持经典与仿钉钉双模式。 + +核心定位决定了最高优先约束:**对外公共 API、实体字段、数据库表结构、配置项都是契约,向后兼容是红线**;**核心引擎与具体框架 / ORM / JSON 库解耦**;**JDK 1.8 源码级兼容**。 + +顶层结构(Maven 反应堆模块 + 前端 + 脚本): + +- `warm-flow-core`:流程引擎核心,**框架无关、ORM 无关、JSON 库无关**。流程定义 / 节点 / 跳转 / 实例 / 任务 / 历史任务 / 用户 / 表单的实体、服务、抽象 DAO、处理器、监听器、条件与办理人表达式策略、ID 生成、SPI 入口。 +- `warm-flow-orm`:ORM 适配层,实现 core 的 `WarmDao` 与实体。按「ORM × 框架」矩阵展开: + - `warm-flow-mybatis`:`*-core` + `*-sb-starter`(SpringBoot2) + `*-sb3-starter`(SpringBoot3) + `*-sb4-starter`(SpringBoot4) + `*-solon-plugin`(Solon)。 + - `warm-flow-mybatis-plus`:同上五件套。 + - `warm-flow-easy-query`:同上五件套。 +- `warm-flow-plugin`:可插拔扩展。 + - `warm-flow-plugin-modes`:框架模式与表达式实现(`*-sb` SpEL、`*-solon` SnEL)。 + - `warm-flow-plugin-json`:JSON 序列化实现(`*-json-v1`:snack/snack4/jackson/fastjson2/gson;`*-json-jackson3`)。 + - `warm-flow-plugin-ui`:设计器 / 流程图后端(`*-ui-core`、`*-ui-sb-web`、`*-ui-solon-web`、`*-vue3-ui`)。 +- `warm-flow-ui`:流程设计器**前端工程(Vue3 + yarn)**,独立于 Maven 反应堆,不被父 `pom.xml` 的 `` 纳入。 +- `sql/`:建表与升级脚本,按数据库分目录:`mysql/`、`oracle/`、`postgresql/`、`sqlserver/`;每库一份全量 `*-all.sql`,MySQL 另有 `v1-upgrade/` 版本升级脚本。 +- 测试不在本仓库:官方测试在独立仓库 `warm-flow-test`(gitee),本仓库无 `src/test`。 + +## 技术基线 + +- **JDK 1.8 源码级**:父 `pom.xml` 锁定 `maven.compiler.source/target = 8`,需同时兼容 Java 8 / 17 / 21。主代码**禁止使用 Java 9+ 的语法与 API**(详见「兼容性红线」)。 +- **多框架生态**:Spring Boot 2.7.18 / 3.0.1 / 4.0.2 与 Solon 3.10.0 并行支持,对应 `sb` / `sb3` / `sb4` / `solon` 后缀的 starter。 +- **多 ORM**:MyBatis 3.5.15(mybatis-spring-boot 2.3.2)、MyBatis-Plus 3.5.12、Easy-Query 3.1.79;README 另提到 JPA / BeetlSql 等生态由社区扩展。 +- **多 JSON**:snack3 3.2.139、snack4 4.0.8、jackson 2.13.5、jackson3 3.0.4、fastjson2 2.0.43、gson 2.9.0。 +- **多数据库**:MySQL、Oracle、PostgreSQL、SQL Server(其它库转换表结构即可)。 +- **基础依赖**:Lombok、`slf4j-api`(仅 API,不绑定日志实现)、JUnit 4(测试在独立仓库)。 +- **依赖版本统一在父 `pom.xml` 的 `dependencyManagement` 与 `properties` 管理**,子模块不私自写死或改版本号;版本属性 `${warm-flow}` 跟随 `${project.version}`。 + +## 架构与扩展机制(warm-flow 的灵魂,改动前必须理解) + +引擎通过几个解耦点做到「核心与框架无关、可多生态适配」,**这是本仓库最重要的设计约束,破坏它等于破坏整个工程**: + +- `FlowEngine`:静态门面,持有各 `XxxService`、实体 `Supplier`、`handler` / `listener`、`jsonConvert`。业务方与内部统一通过 `FlowEngine.xxxService()` / `FlowEngine.newXxx()` 取服务和新建实体,不要绕过它直接 new 实现类。 +- `FrameInvoker`:框架桥接点,通过 `setBeanFunction` / `setCfgFunction` 注入「取 Bean」「取配置」的能力。**core 因此不依赖任何容器**;Spring / Solon 适配模块在启动时注入这两个 Function。 +- `WarmFlow`(config):引擎配置载体(`enabled`、`framework`、`banner`、`keyType`、`logicDelete`、租户 / 数据填充 / 权限 / 全局监听器的类路径、`dataSourceType`、`ui`、`tokenName`、流程图三原色等),`init()` 负责装配 handler、打印 banner、SPI 加载。 +- **Java SPI**:`ServiceLoaderUtil.loadFirst(...)` + `META-INF/services/`(如 `org.dromara.warm.flow.core.json.JsonConvert`)用于可替换实现(典型:JSON 转换策略)。 +- **自动装配注册**随框架不同而不同: + - Spring Boot 2:`META-INF/spring.factories`。 + - Spring Boot 3 / 4:`META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`。 + - Solon:`META-INF/solon/*.properties`。 +- **ORM 抽象**:core 定义 `WarmDao`、`WarmQuery`、`WarmServiceImpl` 与各实体接口;每个 ORM 模块提供实体实现(如 `FlowDefinition`)、Mapper / Dao 实现(如 `WarmDaoImpl`)、ID 生成器适配,并通过 starter 把实现接入 `FlowEngine`。 + +新增能力时**必须沿用上述矩阵与扩展点**,不要在 core 里直接耦合某个框架 / ORM / JSON 实现。 + +## 核心工作规则 + +- 先思考,再编辑。非平凡任务开始前,先识别目标文件、期望行为、验证方式与风险。 +- 保持简单。优先选择与现有模式一致的最小正确改动。 +- 外科手术式改动。不要格式化、重命名、重排或重构无关代码。 +- 保护用户已有工作。较大改动前先看 `git status --short`,除非用户明确要求,绝不回退不是你做的改动。 +- 管理不确定性。如果流程语义、状态流转、跨生态行为不清晰且无法从代码安全推断,先问一个简洁问题,或明确写出假设。 +- 用证据验证。没有新鲜命令输出或直接检查结果时,不要声称构建、测试、修复已经成功。 +- 暴露真实失败。不要用假默认值、吞异常、模拟成功数据或静默降级掩盖真实问题。 +- 凡涉及**公共 API / 实体字段 / 表结构 / 配置项 / SPI 契约 / 跨生态行为 / 多数据库 SQL** 的改动,一律按高风险处理。 + +## 规则源维护 + +- `AGENTS.md` 是本仓库 agent 规则主来源。 +- `.qoder/repowiki` 是更细的引擎架构与领域参考(**本地文档,已 gitignore、未纳入仓库**;作者本地可选参考,团队成员默认没有,不要当作必读入口或长期依赖)。 +- 新增、删除或调整长期项目规则时,先更新根 `AGENTS.md`,再按需要同步模块级 `AGENTS.md`、根 `CLAUDE.md` 与 `.cursor/rules`。 +- 如果本文件、其他 agent 规则与用户当前指令冲突,优先遵循用户当前指令,同时说明冲突点、取舍原因与影响。 +- 不要把一次性任务背景写成永久规则。只有能长期约束本仓库开发质量的约定才加入本文件。 + +## 规则优先级 + +冲突时从高到低: + +1. 用户当前明确指令。 +2. 模块级 `AGENTS.md`(所在顶层模块下若存在)。 +3. 仓库根 `AGENTS.md`(本文件)。 +4. 根 `CLAUDE.md` 与 `.cursor/rules/*`(与 `AGENTS.md` 冲突一律以 `AGENTS.md` 为准)。 +5. (可选)本地 `.qoder/repowiki` 等领域 / 架构参考(未纳入仓库,可能不存在)。 + +## 模块级 AGENTS.md 与 CLAUDE.md + +- 每个顶层模块(`warm-flow-core`、`warm-flow-orm`、`warm-flow-plugin`、`warm-flow-ui`)下都有一份模块级 `AGENTS.md`,**只写本模块差异**(职责、改动前必读、高风险点、聚焦验证),通用规范一律指向根 `AGENTS.md`。 +- 根 `CLAUDE.md` 是「以 `AGENTS.md` 为唯一来源」的红线摘要,不承载独有规则。 +- 同一条规则只维护一处:通用规则进根 `AGENTS.md`,模块差异进模块级 `AGENTS.md`,避免多处漂移。开始任务前先读根 `AGENTS.md`,再读所在模块级 `AGENTS.md`。 + +## 品牌与版权保护 + +- 不要移除、替换或弱化 `warm-flow`、`Warm-Flow`、`dromara`、`org.dromara.warm` 包名 / groupId、模块名、启动 banner、作者信息(`warm` / `290631660@qq.com` 等 `developers`)、README 中的 Star/赞助商/文档/演示链接,除非用户明确要求。 +- **每个 Java 文件保留 Apache 2.0 license header**(`Copyright 2024-2025, Warm-Flow (290631660@qq.com).` 开头的注释块)。新增 Java 文件必须照抄现有 header、`package`、Lombok 与注释风格。 +- 保留现有中文 README、中文注释、类注释中的 `@author warm` 与 `@since`,不要批量改成英文或通用模板。 +- 不改动 `LICENSE`,不弱化「永久开源免费、无商业版」的项目声明。 + +## 任务分级 + +使用与风险匹配的最轻流程。 + +- **L0**:单文件小修、注释、文档、单库 SQL 注释类改动。读相关代码,改,跑聚焦编译。 +- **L1**:模块内多文件改动、服务逻辑、工具类、单个 starter 适配、单库 SQL 增改。收集上下文,简短规划,小步编辑,编译受影响模块。 +- **L2**:core 公共 API / 实体 / 抽象 DAO 改动、扩展机制(`FlowEngine` / `FrameInvoker` / SPI / 自动装配)改动、跨生态(SB2/3/4/Solon)行为、跨 ORM 行为、多数据库表结构 / 升级脚本、版本发布、流程状态机语义。必要时在 `.codex/` 或 `docs/` 记录关键决策与验证细节。 + +## 兼容性红线(warm-flow 最关键的约束) + +### 1. JDK 1.8 源码级兼容 + +主代码(`src/main`)只能用 Java 8 语法与 API。**禁止**: + +- `var` 局部变量类型推断、`record`、`sealed`、switch 表达式 / `yield`、文本块 `"""`、增强 `instanceof` 模式匹配。 +- Java 9+ 集合工厂 `List.of` / `Map.of` / `Set.of`(用 `Arrays.asList` / `Collections` / 手动构造)。 +- `Optional.isEmpty()`(用 `!opt.isPresent()`)、`Stream.toList()`(用 `collect(Collectors.toList())`)、`String.isBlank()` / `String.strip()`、`Files.readString` 等 Java 9+ 新方法。 +- 任何只在高版本 JDK 存在的 API。优先复用项目已有的 `org.dromara.warm.flow.core.utils.*`(`StringUtils`、`ObjectUtil`、`CollUtil`、`MapUtil`、`StreamUtils`、`ArrayUtil`、`AssertUtil` 等),引擎已自带 JDK8 下的流式 / 集合 / 字符串替代工具。 + +### 2. 对外契约向后兼容 + +- 公共类、方法签名、`FlowEngine` 门面、`WarmDao` 接口、实体字段、枚举常量(code / 顺序 / 名称)、`WarmFlow` 配置项都是已发布契约,**改动前评估对下游依赖方的破坏**;不要随意删除 / 重命名 / 改签名 / 重排枚举。 +- 确需废弃时用 `@Deprecated` 并保留过渡期,新增能力优先「加法」而非「改签名」。 + +### 3. 框架与 ORM 解耦 + +- `warm-flow-core` **禁止**出现 `org.springframework.*`、`org.noear.solon.*`、`com.baomidou.*` 等具体框架 / ORM 依赖与 import(当前 core 已做到零此类依赖,必须保持)。 +- 框架差异通过 `FrameInvoker`、SPI、各 starter 解决;ORM 差异通过 `WarmDao` 实现与各 orm 模块解决。 + +### 4. 多生态对齐 + +- 改某个 starter 的能力时,确认是否需要在 `sb` / `sb3` / `sb4` / `solon` 以及对应 ORM 模块同步;不要只改一处导致生态不一致。 + +## Java 与编码风格 + +- **格式基线以 `.editorconfig` 为准**:4 空格缩进、UTF-8、LF 换行、去行尾空格、文件末尾留空行(`json`/`yml`/`js` 为 2 空格)。仓库**未启用 checkstyle / spotless**,没有自动格式化兜底,提交前自觉对齐既有风格。 +- 遵循引擎现有「实体 / 服务接口 + `service.impl` / 抽象 DAO + orm 实现」分层,不引入新的架构风格或 DDD 分层。 +- Lombok:实体 / DTO 用 `@Getter`/`@Setter`/`@Data`,组件用构造器注入;**不要手写可由注解生成的 getter/setter**。 +- 日志使用 `slf4j` + 占位符;不要 `printStackTrace()` / `System.out.println`;不打印敏感信息。 +- 工具优先复用 `org.dromara.warm.flow.core.utils.*`,不为一次性需求新增通用工具类、不重复造轮子、不在 core 引入重型三方工具库。 +- 注释解释意图、流程语义、边界与非显然取舍,不复述下一行代码;新增类保持标准类注释与 `@author`。 +- 表达式(条件 / 办理人 / 票签)与监听器是引擎对外扩展点,新增策略沿用 `condition` / `strategy` / `listener` 既有接口与 `plugin-modes` 的 SpEL/SnEL 实现模式。 + +## 实体、DAO、服务与状态机 + +- 实体(`Definition`/`Node`/`Skip`/`Instance`/`Task`/`HisTask`/`User`/`Form`)通过 `FlowEngine.newXxx()` 创建;新增实体字段要同时考虑各 ORM 实体实现、JSON 序列化、SQL 表结构与升级脚本。 +- 单表 CRUD 走 `WarmDao` 抽象与各 ORM 实现,不在 core 写死某 ORM 的查询 API。 +- 流程状态、跳转、转办、加签 / 减签、终止、撤回、票签 / 会签、互斥 / 并行网关都有业务副作用与状态机约束,改动前先读对应 `service.impl`、`strategy`、`handler`、`listener` 与状态枚举,确认现有流转后再改,不要凭文件名猜行为。 + +## SQL 与数据库 + +- 表结构改动必须**同步四套脚本**:`sql/mysql`、`sql/oracle`、`sql/postgresql`、`sql/sqlserver` 的全量脚本,并在 `sql/mysql/v1-upgrade/` 新增对应版本升级脚本(命名沿用 `warm-flow_x.x.x.sql`)。 +- 注意各库方言差异(类型、自增 / 序列、分页、大小写、关键字);破坏性或迁移脚本必须写明用途、影响范围、回滚方式与各库兼容性,执行需用户明确批准。 +- 引擎自身维护**多租户与逻辑删除**(见 `WarmFlow.logicDelete` 等);改动相关字段 / 行为要兼顾「引擎自带实现」与「复用 ORM 框架实现」两条路径。 + +## 扩展开发指引(新增生态 / ORM / JSON / DB) + +- **新增 JSON 实现**:实现 core 的 `JsonConvert`,放到 `warm-flow-plugin-json`,并加 `META-INF/services/org.dromara.warm.flow.core.json.JsonConvert`。 +- **新增 ORM 支持**:在 `warm-flow-orm` 下按现有五件套(`core` + `sb`/`sb3`/`sb4` starter + `solon-plugin`)建模块,实现 `WarmDao`、实体与 ID 生成适配。 +- **新增框架适配**:提供注入 `FrameInvoker` 的启动逻辑与对应自动装配文件(`spring.factories` / `AutoConfiguration.imports` / Solon properties)。 +- **新增数据库**:补四套之外的脚本目录与全量脚本,并验证 `dataSourceType` / 分页 / 方言。 +- 以上均为 L2,先评估必要性与对现有矩阵的影响,再实施。 + +## 验证规则 + +本仓库**无 `src/test`**(测试在独立仓库 `warm-flow-test`),验证以**分模块编译**为主,按风险选择范围: + +```bash +# 全量安装到本地仓库(最稳,先装核心再装下游) +mvn clean install -DskipTests + +# 聚焦编译单个模块(按改动模块替换 -pl 路径或 -f 指定 pom) +mvn -pl warm-flow-core -am -DskipTests compile +mvn -f warm-flow-orm/warm-flow-mybatis/warm-flow-mybatis-core/pom.xml -DskipTests compile +``` + +- 文档 / 注释改动:`git diff --check` 即可。 +- core 改动:编译 core,并至少编译一个依赖它的 orm / plugin 模块。 +- 某 starter / 适配改动:编译该模块,必要时编译同一 ORM 的其它 starter 确认生态一致。 +- SPI / 自动装配改动:确认注册文件与实现类一致,编译相关模块。 +- SQL / 表结构改动:核对四套脚本与升级脚本一致性,说明各库兼容性。 + +无法完成验证时必须报告:尝试的命令、失败现象、可能原因、对当前改动的风险、建议下一步。**不要为了让构建“通过”而删插件、降基线或改 JDK 版本。** + +## 文档与 AI 产物归档 + +- 面向用户的正式文档以 README 与官网(warm-flow.com)为准;引擎细节可参考本地 `.qoder/repowiki`(未纳入仓库,仅本地可选)。 +- AI / agent 的一次性调研、决策记录、临时计划放 `.codex/` 或 `docs/`,不要塞进源码包,也不要当作长期必读入口。 +- 临时 / 备份代码、注释掉的旧实现、压测入口不留在源码树,确认无引用后删除(git 历史可追溯)。 + +## git 提交规范 + +提交信息前缀沿用 README 约定(中文项目): + +``` +init: 初始化 +feat: 增加新功能 +fix: 修复问题/BUG +perf: 优化/性能提升 +refactor: 重构 +revert: 撤销修改 +style: 代码风格相关无影响运行结果的 +update: 其他修改 +upgrade: 升级版本 +``` + +## 构建与发布命令 + +```bash +mvn clean package -DskipTests # 打包 +mvn clean install -DskipTests # 安装到本地仓库 +mvn clean deploy -P release # 发布中央仓库(需 release profile 与凭证) +mvn versions:set -DnewVersion=1.8.9 # 统一修改版本号 +mvn versions:commit # 确认版本修改(versions:revert 回滚) +``` + +- 发布到中央仓库依赖 `release` profile(javadoc、gpg 签名、central-publishing),需本地 `settings.xml` 配置 `ossrh` 凭证与 GPG。 +- `.github/workflows/release.yml` 当前是**全注释的模板(CI 未启用)**,发布是**手动**执行,不要假设 CI 会自动发版。`.gitee/` 下有中文 issue / PR 模板,提 PR 时遵循。 + +## 安全边界 + +没有用户明确批准,不要执行: + +- `git commit`、`git push`、删除分支、强推或改写历史。 +- `mvn deploy` / 发布到中央仓库、改版本号后推送、轮换发布凭证。 +- 任务范围外的破坏性文件系统操作。 +- `DROP`、批量 `DELETE`、表结构重写等破坏性数据库脚本的执行。 +- 降低 JDK 基线、删除编译 / 打包插件、放宽开源协议或弱化品牌信息。 + +默认允许在相关任务中执行:读取文件、搜索代码、运行本地构建 / 编译、编辑项目文件、使用 `git status` / `git diff`。 + +## Agent 回复风格 + +- 简洁但具体,优先说明改了什么、验证了什么。 +- 有帮助时带上文件路径。 +- 如实说明不确定性、跨生态 / 兼容性残余风险。 +- 不要掩盖构建或编译失败。 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000000000000000000000000000000000..210cabe5f57b58b981370cef34a46cecc147dc00 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,53 @@ +# CLAUDE.md + +本仓库(`warm-flow`,Dromara 开源轻量级工作流引擎 / SDK)的编码与协作规则,**以 [AGENTS.md](./AGENTS.md) 为唯一来源**。开始任何任务前先读根 `AGENTS.md`;若改动所在顶层模块下还有模块级 `AGENTS.md`,再读模块级。本文件只是核心红线摘要,**与 `AGENTS.md` 冲突时以 `AGENTS.md` 为准**。 + +## 规则优先级 + +1. 用户当前明确指令。 +2. 模块级 `AGENTS.md`(若存在)。 +3. 根 `AGENTS.md`。 +4. 本 `CLAUDE.md` 与 `.cursor/rules`(与 `AGENTS.md` 冲突以 `AGENTS.md` 为准)。 +5. `.qoder/repowiki` 等领域 / 架构参考。 + +## 项目性质(决定一切约束) + +- 这是**被他人依赖的开源类库 / SDK**(发布到 Maven 中央仓库,`groupId=org.dromara.warm`),不是业务应用。 +- 三大最高约束:**JDK 1.8 源码级兼容**、**对外契约向后兼容**、**核心与框架 / ORM / JSON 解耦**。 + +## 技术基线 + +- JDK 1.8 源码级(兼容 Java 8/17/21);多框架 Spring Boot 2.7/3.0/4.0 + Solon 3.10;多 ORM MyBatis / MyBatis-Plus / Easy-Query;多 JSON snack3/snack4/jackson/jackson3/fastjson2/gson;多数据库 MySQL/Oracle/PostgreSQL/SQL Server。 +- Lombok + `slf4j-api`;依赖版本统一在父 `pom.xml`,子模块不私改。 + +## 模块速览 + +- `warm-flow-core`:框架 / ORM / JSON 无关的引擎核心(实体、服务、抽象 `WarmDao`、`FlowEngine`、`FrameInvoker`、SPI、表达式 / 监听器策略)。 +- `warm-flow-orm`:ORM 适配,按「ORM × (sb/sb3/sb4/solon)」矩阵实现 `WarmDao`。 +- `warm-flow-plugin`:可插拔扩展(`modes` 表达式、`json` 序列化、`ui` 设计器后端)。 +- `warm-flow-ui`:Vue3 前端设计器,独立于 Maven 反应堆。 +- `sql/`:mysql/oracle/postgresql/sqlserver 四套脚本 + MySQL `v1-upgrade/`。 + +## 核心红线(详见 AGENTS.md) + +1. **JDK 8 语法**:主代码禁止 `var`/`record`/switch 表达式/文本块/`List.of`/`Optional.isEmpty`/`Stream.toList`/`String.isBlank` 等 Java 9+ API;优先用 core 的 `utils.*`。 +2. **解耦**:`warm-flow-core` 禁止 import `org.springframework.*` / `org.noear.solon.*` / `com.baomidou.*`;框架差异走 `FrameInvoker` + SPI + 各 starter,ORM 差异走 `WarmDao` 实现。 +3. **门面**:统一通过 `FlowEngine.xxxService()` / `FlowEngine.newXxx()` 取服务和建实体,不绕过门面直接 new 实现类。 +4. **向后兼容**:公共方法签名、`WarmDao` 接口、实体字段、枚举常量(code/顺序)、`WarmFlow` 配置项是已发布契约,不随意删 / 改签名 / 重排;废弃用 `@Deprecated` 留过渡期。 +5. **多生态对齐**:改某 starter 能力时,确认 `sb`/`sb3`/`sb4`/`solon` 与对应 ORM 模块是否需同步。 +6. **SQL 四套同步**:表结构改动同步 mysql/oracle/postgresql/sqlserver 全量脚本 + 新增 `v1-upgrade/warm-flow_x.x.x.sql`,写明各库方言兼容与回滚。 +7. **多租户 / 逻辑删除**:引擎自带实现,相关字段 / 行为改动兼顾「引擎自带」与「ORM 框架」两条路径。 +8. **扩展机制**:新增 JSON 走 `JsonConvert` + `META-INF/services`;新增 ORM / 框架走五件套矩阵 + 对应自动装配(`spring.factories` / `AutoConfiguration.imports` / Solon properties)。 +9. **状态机**:通过 / 退回 / 跳转 / 转办 / 加减签 / 终止 / 撤回 / 票签 / 网关有副作用,改动前读对应 `service.impl` / `strategy` / `listener` 与状态枚举。 +10. **品牌与协议**:保留每个 Java 文件 Apache 2.0 license header、`@author warm`、`org.dromara.warm` 包名、banner、README 链接与 `LICENSE`,不弱化「永久开源免费」声明。 + +## 高风险(按 L2 处理,先读调用链) + +core 公共 API / 实体 / 抽象 DAO、扩展机制(`FlowEngine` / `FrameInvoker` / SPI / 自动装配)、跨生态行为、跨 ORM 行为、多数据库表结构 / 升级脚本、版本发布、流程状态机语义。 + +## 验证与安全边界 + +- 本仓库无 `src/test`(测试在独立仓库 `warm-flow-test`),用**分模块编译**验证:`mvn -pl -am -DskipTests compile` 或 `mvn clean install -DskipTests`;core 改动至少编译一个下游 orm/plugin 模块。无法验证时如实报告命令、现象、风险与下一步。 +- 未经用户明确批准:不 `git commit` / `git push`、不 `mvn deploy` / 改版本推送、不改写历史、不执行 `DROP` / 批量 `DELETE`、不降 JDK 基线 / 删编译插件、不输出真实发布凭证。 + +完整规则见 **[AGENTS.md](./AGENTS.md)**。 diff --git a/warm-flow-core/AGENTS.md b/warm-flow-core/AGENTS.md new file mode 100644 index 0000000000000000000000000000000000000000..c2fd4d6781095bacfd7aa940458b7d08d7611236 --- /dev/null +++ b/warm-flow-core/AGENTS.md @@ -0,0 +1,45 @@ +# AGENTS.md — warm-flow-core 模块规则 + +> 本文件只写 `warm-flow-core` 的差异化规则。通用工程与编码规范以仓库根 [`../AGENTS.md`](../AGENTS.md) 为准;规则优先级见根 `AGENTS.md`「规则优先级」。 +> +> 最高约束:core 是整个引擎的地基,被所有 orm / plugin 模块与下游使用方依赖。**任何公共行为改动按 L2 高风险处理**。 + +## 模块职责 + +框架无关、ORM 无关、JSON 库无关的流程引擎核心,包根 `org.dromara.warm.flow.core`: + +- `FlowEngine`:静态门面,持有各 `XxxService`、实体 `Supplier`、handler / listener / `jsonConvert`。 +- `config`:`WarmFlow` 引擎配置与 `init()` 装配。 +- `invoker/FrameInvoker`:框架桥接(`setBeanFunction` / `setCfgFunction`),core 不依赖容器的关键。 +- `entity`:`Definition`/`Node`/`Skip`/`Instance`/`Task`/`HisTask`/`User`/`Form` 等接口。 +- `service` + `service.impl`:`DefService`/`NodeService`/`SkipService`/`InsService`/`TaskService`/`HisTaskService`/`UserService`/`FormService`/`ChartService`。 +- `orm`:抽象 `dao/WarmDao`、`agent/WarmQuery`、`service/WarmServiceImpl`(ORM 接缝,不含具体实现)。 +- `handler`:`DataFillHandler`/`TenantHandler`/`PermissionHandler`。 +- `listener`:`Listener`/`GlobalListener`/`ListenerVariable`。 +- `strategy`:策略接口——`ConditionStrategy`(条件)、`HandlerStrategy`(办理人)、`ListenerStrategy`(监听器)、`VoteSignStrategy`(票签)、`ExpressionStrategy`(表达式基类);具体 SpEL/SnEL 实现在 `plugin-modes`。 +- `condition`:条件比较运算的具体实现(`AbstractConditionStrategy` + `Eq`/`Ne`/`Gt`/`Ge`/`Lt`/`Le`/`Like`/`NotLike`)。 +- `keygen`:`SnowFlakeId14/15` 等 ID 生成。 +- `json`:`JsonConvert` SPI 接口(实现在 plugin-json)。 +- `utils`:引擎自带工具(`StringUtils`/`ObjectUtil`/`CollUtil`/`MapUtil`/`AssertUtil` 等)。 + +## 改动前必读 + +- 根 [`../AGENTS.md`](../AGENTS.md)「架构与扩展机制」「兼容性红线」。 +- 改服务 / 状态机前,先读对应 `service.impl` + 相关 `strategy` / `handler` / `listener` + 状态枚举(`FlowStatus`/`NodeType`/`SkipType`/`CooperateType` 等)。 +- `../.qoder/repowiki/zh/content/核心引擎架构/` 有服务层、实体模型、数据流的详细文档(本地参考)。 + +## 高风险点(一律 L2) + +- **零框架依赖红线**:core **禁止**出现 `org.springframework.*`、`org.noear.solon.*`、`com.baomidou.*` 等具体框架 / ORM import(当前已是零依赖,必须保持)。需要容器能力时走 `FrameInvoker`,需要可替换实现走 SPI。 +- **JDK 1.8 语法**:禁止 Java 9+ 语法 / API(`var`、`record`、switch 表达式、文本块、`List.of`、`Optional.isEmpty`、`Stream.toList`、`String.isBlank` 等);用 `utils.*` 替代。 +- **门面与契约**:`FlowEngine` 方法、`WarmDao` 抽象、实体接口、`WarmFlow` 配置项、枚举常量(code / 顺序 / 名称)都是对外契约,改动评估下游破坏,优先「加法」,废弃用 `@Deprecated` 留过渡期。 +- **状态机语义**:通过 / 退回 / 跳转 / 转办 / 加减签 / 终止 / 撤回 / 票签 / 网关有副作用,先确认现有流转再改,不要凭文件名猜。 +- **实体字段**:新增 / 改字段要同步各 ORM 实体实现、JSON 序列化与 `sql/` 四套表结构。 + +## 聚焦验证 + +```bash +mvn -pl warm-flow-core -am -DskipTests compile +``` + +core 改动后至少再编译一个下游模块(如某 orm-core 或 plugin),确认接缝未破。 diff --git a/warm-flow-orm/AGENTS.md b/warm-flow-orm/AGENTS.md new file mode 100644 index 0000000000000000000000000000000000000000..b28c6cd332b7d1a88b947e56f9e387a8f13e3591 --- /dev/null +++ b/warm-flow-orm/AGENTS.md @@ -0,0 +1,39 @@ +# AGENTS.md — warm-flow-orm 模块规则 + +> 本文件只写 `warm-flow-orm` 的差异化规则。通用工程与编码规范以仓库根 [`../AGENTS.md`](../AGENTS.md) 为准;规则优先级见根 `AGENTS.md`「规则优先级」。 + +## 模块职责 + +ORM 适配层,实现 `warm-flow-core` 的 `WarmDao` 抽象与各实体。按「**ORM × 框架**」矩阵组织,每种 ORM 一套五件套: + +- `warm-flow-mybatis`:`*-core`(实体 / Mapper / `WarmDaoImpl`)+ `*-sb-starter`(SB2) + `*-sb3-starter`(SB3) + `*-sb4-starter`(SB4) + `*-solon-plugin`(Solon)。 +- `warm-flow-mybatis-plus`:同上五件套(含 `MybatisPlusIdGen` 等适配)。 +- `warm-flow-easy-query`:同上五件套。 + +包根:ORM 实现 `org.dromara.warm.flow.orm`(`entity`/`mapper`/`dao`/`keygen`/`utils`);Spring 适配 `org.dromara.warm.flow.spring.boot`;Solon 适配 `org.dromara.warm.flow.solon`。 + +## 改动前必读 + +- 根 [`../AGENTS.md`](../AGENTS.md)「架构与扩展机制」「兼容性红线」「扩展开发指引」。 +- core 的 `WarmDao` / `WarmQuery` / `WarmServiceImpl` 与对应实体接口;改某 ORM 的 `WarmDaoImpl` 前,先看同 ORM 的 `*-core` 实现与 starter 装配。 + +## 高风险点(按 L2) + +- **多生态对齐**:一个能力改动通常要在同 ORM 的 `sb` / `sb3` / `sb4` / `solon` 同步;不要只改一套 starter 导致生态不一致。 +- **自动装配注册一致**:SB2 用 `META-INF/spring.factories`,SB3/4 用 `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`,Solon 用 `META-INF/solon/*.properties`。新增 / 改 `FlowAutoConfig` 时同步对应注册文件,并确保把实现接入 `FlowEngine` / 注入 `FrameInvoker`。 +- **WarmDao 契约**:各 ORM 实现要满足 core `WarmDao` 的语义(分页、批量、软删除、租户),不要让不同 ORM 行为漂移。 +- **ID 生成 / 分页 / 方言**:`keyType`、`dataSourceType` 影响 ID 与分页 SQL;跨数据库时确认方言差异。 +- **多租户与逻辑删除**:区分「引擎自带实现」与「复用 ORM 框架实现」两条路径,改动时两者都要自洽。 + +## SQL 同步 + +表结构相关改动按根 `AGENTS.md`「SQL 与数据库」同步 `sql/` 下 mysql / oracle / postgresql / sqlserver 四套脚本与升级脚本。 + +## 聚焦验证 + +```bash +# 编译被改的某个 ORM 模块(按实际路径替换) +mvn -f warm-flow-orm/warm-flow-mybatis-plus/warm-flow-mybatis-plus-core/pom.xml -DskipTests compile +``` + +改 core 接缝相关内容时,至少各编译一种受影响 ORM 的 `*-core` 与一个 starter。 diff --git a/warm-flow-plugin/AGENTS.md b/warm-flow-plugin/AGENTS.md new file mode 100644 index 0000000000000000000000000000000000000000..def4f721a1f65479dfd8b798b652b3006778b9ec --- /dev/null +++ b/warm-flow-plugin/AGENTS.md @@ -0,0 +1,34 @@ +# AGENTS.md — warm-flow-plugin 模块规则 + +> 本文件只写 `warm-flow-plugin` 的差异化规则。通用工程与编码规范以仓库根 [`../AGENTS.md`](../AGENTS.md) 为准;规则优先级见根 `AGENTS.md`「规则优先级」。 + +## 模块职责 + +引擎的可插拔扩展实现,按扩展点分三类: + +- `warm-flow-plugin-modes`:框架模式与表达式实现。`*-sb`(Spring,SpEL:`ConditionStrategySpel`、`VoteSignStrategySpel`、`HandlerStrategySpel` 等,含 `SpelHelper` / 安全方法解析);`*-solon`(Solon,SnEL:`*SnEl`)。包根 `org.dromara.warm.plugin.modes.sb` / `.solon`。 +- `warm-flow-plugin-json`:`JsonConvert` 的 SPI 实现。`*-json-v1`(`JsonConvertSnack`/`Snack4`/`Jackson`/`FastJson`/`Gson`);`*-json-jackson3`。包根 `org.dromara.warm.plugin.json`。 +- `warm-flow-plugin-ui`:设计器 / 流程图后端。`*-ui-core`(`service` / `dto` / `vo`)、`*-ui-sb-web`(Spring controller)、`*-ui-solon-web`(Solon controller)、`*-vue3-ui`(打包前端资源)。包根 `org.dromara.warm.flow.ui`。 + +## 改动前必读 + +- 根 [`../AGENTS.md`](../AGENTS.md)「架构与扩展机制」「兼容性红线」「扩展开发指引」。 +- core 的 `condition` / `strategy` / `listener` / `json.JsonConvert` 接口;改表达式策略前先读 core 默认实现与同类 sb/solon 实现。 + +## 高风险点(按 L2) + +- **SPI 注册一致**:新增 / 改 JSON 实现必须同步 `META-INF/services/org.dromara.warm.flow.core.json.JsonConvert`;`FlowEngine` 通过 `ServiceLoaderUtil.loadFirst` 取首个实现,注意实现优先级与 classpath 唯一性。 +- **表达式安全**:SpEL / SnEL 涉及脚本执行,沿用现有 `SafeMethodResolver` / `SafeTypeLocator` 等安全约束,**不要放开任意方法 / 类型调用**,避免表达式注入风险。 +- **双模式 UI**:经典模式与仿钉钉模式都要兼顾;controller 在 sb-web 与 solon-web 行为对齐,前端资源放 `*-vue3-ui`。 +- **多生态对齐**:modes / ui 的 sb 与 solon 实现保持能力一致,不要只改一侧。 +- **JSON 兼容**:不同 JSON 库对日期 / null / 泛型 / 多态序列化差异要与引擎实体约定一致,避免下游切换 JSON 库后行为变化。 + +## 聚焦验证 + +```bash +# 按被改子模块替换路径 +mvn -f warm-flow-plugin/warm-flow-plugin-json/warm-flow-plugin-json-v1/pom.xml -DskipTests compile +mvn -f warm-flow-plugin/warm-flow-plugin-modes/warm-flow-plugin-modes-sb/pom.xml -DskipTests compile +``` + +涉及 SPI / 表达式 / UI 契约时,确认注册文件与对应 sb/solon 实现同步。 diff --git a/warm-flow-ui/.gitignore b/warm-flow-ui/.gitignore index 78a752d87e8427f84570300f62bdfb5b183a9931..a43175e7d27ee8bc869f9844194e2bf02179b775 100644 --- a/warm-flow-ui/.gitignore +++ b/warm-flow-ui/.gitignore @@ -21,3 +21,5 @@ selenium-debug.log package-lock.json yarn.lock +/.playwright-cli/ +/output/ diff --git a/warm-flow-ui/AGENTS.md b/warm-flow-ui/AGENTS.md new file mode 100644 index 0000000000000000000000000000000000000000..39bd4a3df48394ad5d2c0d547a55afd611d049da --- /dev/null +++ b/warm-flow-ui/AGENTS.md @@ -0,0 +1,131 @@ +# AGENTS.md — warm-flow-ui 模块规则 + +> 本文件只写 `warm-flow-ui` 的差异化规则。通用协作原则(先思考、最小改动、外科手术式、用证据验证、品牌保护、安全边界)以仓库根 [`../AGENTS.md`](../AGENTS.md) 为准。 +> +> 注意:本模块是**前端工程,不属于 Maven 反应堆**,不受根 `AGENTS.md` 中 Java / JDK / ORM / SQL 规则约束;后端编译命令与本模块无关。 + +## 模块职责 + +Warm-Flow 流程设计器前端(经典 + 仿钉钉双模式),构建产物供 `warm-flow-plugin-ui` 集成为 jar 内置设计器。 + +技术栈(以 `package.json` 为准): + +- Vue 3.3.9 + Vite 5 + ` \ No newline at end of file diff --git a/warm-flow-ui/src/components/design/mimic/js/gatewayView.ts b/warm-flow-ui/src/components/design/mimic/js/gatewayView.ts index e8d539ef97e9f662195c9d74f371b1a9bc33bc68..6a3aab8595f5410866d4922a2c18832da06c12b7 100644 --- a/warm-flow-ui/src/components/design/mimic/js/gatewayView.ts +++ b/warm-flow-ui/src/components/design/mimic/js/gatewayView.ts @@ -24,15 +24,15 @@ export abstract class GatewayView extends RectNode { [ // 多个输入边时的图标 h('path', { - fill: style.stroke ? style.stroke : '#FF8B00', + fill: style.stroke ? style.stroke : '#409eff', d: 'M171.52 280.064H51.2c-28.672 0-51.2-22.528-51.2-51.2V108.544c0-28.672 22.528-51.2 51.2-51.2h120.32c28.672 0 51.2 22.528 51.2 51.2v120.32c0 28.672-22.528 51.2-51.2 51.2zM51.2 108.544v120.32h120.32V108.544H51.2zM572.416 280.064H451.584c-28.672 0-51.2-22.528-51.2-51.2V108.544c0-28.672 22.528-51.2 51.2-51.2h120.32c28.672 0 51.2 22.528 51.2 51.2v119.808c0.512 13.312-4.608 26.112-13.824 35.84-9.728 10.24-23.04 15.872-36.864 15.872z m-0.512-50.176zM451.584 108.544v120.32h120.32V108.544H451.584zM972.8 280.064h-120.32c-28.672 0-51.2-22.528-51.2-51.2V108.544c0-28.672 22.528-51.2 51.2-51.2H972.8c28.672 0 51.2 22.528 51.2 51.2v120.32c0 28.672-22.528 51.2-51.2 51.2z m-120.32-171.52v120.32H972.8V108.544h-120.32zM572.416 966.656H451.584c-28.672 0-51.2-22.528-51.2-51.2v-120.32c0-28.672 22.528-51.2 51.2-51.2h120.32c28.672 0 51.2 22.528 51.2 51.2v119.808c0.512 13.312-4.608 26.112-13.824 35.84-9.728 10.24-23.04 15.872-36.864 15.872z m-0.512-50.176z m-120.32-121.344v120.32h120.32v-120.32H451.584z', }), h('path', { - fill: style.stroke ? style.stroke : '#FF8B00', + fill: style.stroke ? style.stroke : '#409eff', d: 'M861.696 566.272H162.816c-42.496 0-76.8-34.304-76.8-76.8V254.464c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v235.008c0 14.336 11.264 25.6 25.6 25.6h698.88c14.336 0 25.6-11.264 25.6-25.6V254.464c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v235.008c0 42.496-34.304 76.8-76.8 76.8z', }), h('path', { - fill: style.stroke ? style.stroke : '#FF8B00', + fill: style.stroke ? style.stroke : '#409eff', d: 'M512 766.464c-14.336 0-25.6-11.264-25.6-25.6V283.136c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v457.728c0 14.336-11.264 25.6-25.6 25.6z', }), ], diff --git a/warm-flow-ui/src/components/design/mimic/js/inclusive.ts b/warm-flow-ui/src/components/design/mimic/js/inclusive.ts index b06caca3a01f4fffc01bfad4a892e4976f3e4628..2a46dadf65ab708397d5ee9f9ac4b081474269f3 100644 --- a/warm-flow-ui/src/components/design/mimic/js/inclusive.ts +++ b/warm-flow-ui/src/components/design/mimic/js/inclusive.ts @@ -1,7 +1,19 @@ import {GatewayModel} from "./gatewayModel"; import {GatewayView} from "./gatewayView"; import {h} from "@logicflow/core"; -class InclusiveModel extends GatewayModel {} +import {applyClassicDesignColor} from "../../common/js/tool"; +class InclusiveModel extends GatewayModel { + // 设计态:包容网关用紫色语义色,与经典模式一致;运行态进度图沿用状态色不受影响 + getNodeStyle() { + const style: any = super.getNodeStyle(); + applyClassicDesignColor(style, this.properties, '146,84,222'); + const inDesigner = typeof window !== 'undefined' && (window as any).__WF_FLOW_DESIGN_MODE__; + if (inDesigner && typeof style._statusRgba === 'function') { + style.fill = style._statusRgba(0.12); + } + return style; + } +} class InclusiveView extends GatewayView { @@ -17,11 +29,11 @@ class InclusiveView extends GatewayView { }, [ // 单个输入边时的图标 h('path', { - fill: style.fill ? style.fill : '#FFFCEB', + fill: style.fill ? style.fill : '#ecf5ff', d: 'M85.418667 512L512.021333 85.397333 938.624 512 512.021333 938.602667z', }), h('path', { - fill: style.stroke ? style.stroke : '#FF8B00', + fill: style.stroke ? style.stroke : '#409eff', d: 'M512 970.24a66.346667 66.346667 0 0 1-47.146667-19.413333L72.96 558.72a66.346667 66.346667 0 0 1 0-94.08L464.853333 72.533333a68.266667 68.266667 0 0 1 94.293334 0l392.106666 392.106667a66.773333 66.773333 0 0 1 0 94.08L559.146667 950.826667a66.346667 66.346667 0 0 1-47.146667 19.413333z m0-853.333333a2.986667 2.986667 0 0 0-1.92 0L118.186667 509.866667a2.56 2.56 0 0 0 0 3.626666l391.893333 392.106667a3.2 3.2 0 0 0 3.84 0l391.893333-392.106667a2.56 2.56 0 0 0 0-3.626666L513.92 117.76a2.986667 2.986667 0 0 0-1.92-0.64z', }), h('circle', { @@ -29,7 +41,7 @@ class InclusiveView extends GatewayView { cy: 512, r: 200, fill: 'none', - stroke: style.stroke ? style.stroke : '#FF8B00', + stroke: style.stroke ? style.stroke : '#409eff', strokeWidth: 60, }), ]), @@ -38,9 +50,9 @@ class InclusiveView extends GatewayView { x: x - width / 2 + 27, y: y - height / 2 + 20, fontSize: 13, - fill: "#000", style: { userSelect: 'none', + fill: 'var(--wf-text-primary, #303133)', } }, textValue) : null ]); diff --git a/warm-flow-ui/src/components/design/mimic/js/parallel.ts b/warm-flow-ui/src/components/design/mimic/js/parallel.ts index c45e99c86d124e09b4a6e62b5ea9a9fdd7343e8d..cc8dc6b7142da8c14266400dd880bdd9697bc374 100644 --- a/warm-flow-ui/src/components/design/mimic/js/parallel.ts +++ b/warm-flow-ui/src/components/design/mimic/js/parallel.ts @@ -1,8 +1,20 @@ import {GatewayModel} from "./gatewayModel"; import {GatewayView} from "./gatewayView"; import {h} from "@logicflow/core"; +import {applyClassicDesignColor} from "../../common/js/tool"; -class ParallelModel extends GatewayModel {} +class ParallelModel extends GatewayModel { + // 设计态:并行网关用青色语义色,与经典模式一致;运行态进度图沿用状态色不受影响 + getNodeStyle() { + const style: any = super.getNodeStyle(); + applyClassicDesignColor(style, this.properties, '19,194,194'); + const inDesigner = typeof window !== 'undefined' && (window as any).__WF_FLOW_DESIGN_MODE__; + if (inDesigner && typeof style._statusRgba === 'function') { + style.fill = style._statusRgba(0.12); + } + return style; + } +} class ParallelView extends GatewayView { @@ -18,15 +30,15 @@ class ParallelView extends GatewayView { viewBox: '0 0 1024 1024', }, [ h('path', { - fill: style.fill ? style.fill : '#FFFCEB', + fill: style.fill ? style.fill : '#ecf5ff', d: 'M85.418667 512L512.021333 85.397333 938.624 512 512.021333 938.602667z', }), h('path', { - fill: style.stroke ? style.stroke : '#FF8B00', + fill: style.stroke ? style.stroke : '#409eff', d: 'M512 714.453333A32 32 0 0 1 480 682.666667v-138.666667H341.333333a32 32 0 1 1 0-64h138.666667V341.333333a32 32 0 0 1 64 0v138.666667H682.666667a32 32 0 0 1 0 64h-138.666667V682.666667a32 32 0 0 1-32 31.786666z', }), h('path', { - fill: style.stroke ? style.stroke : '#FF8B00', + fill: style.stroke ? style.stroke : '#409eff', d: 'M512 970.453333a66.56 66.56 0 0 1-47.146667-19.626666L72.96 558.933333a66.346667 66.346667 0 0 1 0-94.293333L464.853333 72.533333a68.266667 68.266667 0 0 1 94.293334 0l391.893333 392.106667a66.346667 66.346667 0 0 1 0 94.293333L559.146667 950.826667a66.56 66.56 0 0 1-47.146667 19.626666z m0-853.333333a2.986667 2.986667 0 0 0-1.92 0L118.186667 509.866667a2.56 2.56 0 0 0 0 3.626666l391.893333 392.106667a3.2 3.2 0 0 0 3.84 0l391.893333-392.106667a2.986667 2.986667 0 0 0 0-3.626666L513.92 117.76a2.986667 2.986667 0 0 0-1.92-0.64z', }), ]), @@ -35,9 +47,9 @@ class ParallelView extends GatewayView { x: x - width / 2 + 27, y: y - height / 2 + 20, fontSize: 13, - fill: "#000", style: { userSelect: 'none', + fill: 'var(--wf-text-primary, #303133)', } }, textValue) : null ]); diff --git a/warm-flow-ui/src/components/design/mimic/js/serial.ts b/warm-flow-ui/src/components/design/mimic/js/serial.ts index 028fc297d4ff50861e728ca59f5a381c2adddc1e..4b3372ce739fe3339f78013c37e0ef01e9b2cce4 100644 --- a/warm-flow-ui/src/components/design/mimic/js/serial.ts +++ b/warm-flow-ui/src/components/design/mimic/js/serial.ts @@ -1,7 +1,19 @@ import {GatewayModel} from "./gatewayModel"; import {GatewayView} from "./gatewayView"; import {h} from "@logicflow/core"; -class SerialModel extends GatewayModel {} +import {applyClassicDesignColor} from "../../common/js/tool"; +class SerialModel extends GatewayModel { + // 设计态:串行(互斥)网关用橙色语义色,与经典模式一致;运行态进度图沿用状态色不受影响 + getNodeStyle() { + const style: any = super.getNodeStyle(); + applyClassicDesignColor(style, this.properties, '245,158,11'); + const inDesigner = typeof window !== 'undefined' && (window as any).__WF_FLOW_DESIGN_MODE__; + if (inDesigner && typeof style._statusRgba === 'function') { + style.fill = style._statusRgba(0.12); + } + return style; + } +} class SerialView extends GatewayView { @@ -17,15 +29,15 @@ class SerialView extends GatewayView { }, [ // 单个输入边时的图标 h('path', { - fill: style.fill ? style.fill : '#FFFCEB', + fill: style.fill ? style.fill : '#ecf5ff', d: 'M85.418667 512L512.021333 85.397333 938.624 512 512.021333 938.602667z', }), h('path', { - fill: style.stroke ? style.stroke : '#FF8B00', + fill: style.stroke ? style.stroke : '#409eff', d: 'M512 970.24a66.346667 66.346667 0 0 1-47.146667-19.413333L72.96 558.72a66.346667 66.346667 0 0 1 0-94.08L464.853333 72.533333a68.266667 68.266667 0 0 1 94.293334 0l392.106666 392.106667a66.773333 66.773333 0 0 1 0 94.08L559.146667 950.826667a66.346667 66.346667 0 0 1-47.146667 19.413333z m0-853.333333a2.986667 2.986667 0 0 0-1.92 0L118.186667 509.866667a2.56 2.56 0 0 0 0 3.626666l391.893333 392.106667a3.2 3.2 0 0 0 3.84 0l391.893333-392.106667a2.56 2.56 0 0 0 0-3.626666L513.92 117.76a2.986667 2.986667 0 0 0-1.92-0.64z', }), h('path', { - fill: style.stroke ? style.stroke : '#FF8B00', + fill: style.stroke ? style.stroke : '#409eff', d: 'M554.666667 516.266667l107.946666-107.946667a30.506667 30.506667 0 0 0-42.666666-42.666667L512 473.173333l-107.946667-107.946666a30.506667 30.506667 0 0 0-42.666666 42.666666L469.333333 516.266667l-108.8 107.946666a30.506667 30.506667 0 1 0 42.666667 42.666667l108.8-107.306667 106.666667 107.733334a30.506667 30.506667 0 0 0 42.666666-42.666667z', }), ]), @@ -34,9 +46,9 @@ class SerialView extends GatewayView { x: x - width / 2 + 27, y: y - height / 2 + 20, fontSize: 13, - fill: "#000", style: { userSelect: 'none', + fill: 'var(--wf-text-primary, #303133)', } }, textValue) : null ]); diff --git a/warm-flow-ui/src/components/design/mimic/js/skip.ts b/warm-flow-ui/src/components/design/mimic/js/skip.ts index d254ed687d326a4d28b87d3cc1dfca68c9fcce38..cd3eaa0da5919690435e5257487c4b8bfef93a4c 100644 --- a/warm-flow-ui/src/components/design/mimic/js/skip.ts +++ b/warm-flow-ui/src/components/design/mimic/js/skip.ts @@ -55,6 +55,8 @@ class SkipView extends CurvedEdge { const { points: pointsStr, isAnimation, arrowConfig, radius = 0 } = model; const style = model.getEdgeStyle(); const animationStyle = model.getEdgeAnimationStyle(); + // 跳转条件图标底色:设计态用主蓝 chroma,运行态保留状态语义色(chartStatusColor) + const condColor = model.properties.chartStatusColor ? style.stroke : '#409eff'; let points = this.pointFilter(pointsStr.split(' ').map((p) => p.split(',').map((a) => +a))); // 主路径 @@ -69,7 +71,7 @@ class SkipView extends CurvedEdge { // 如果上一个节点是互斥网关,并且网关后节点大于1个,也就是说是互斥网关结束节点时 if (['serial', 'inclusive'].includes(model.sourceNode.type as string) && nextEdge.length > 1) { const midPoint = [points[0][0], points[0][1] + offsetY - 10]; - plusElements = this.getForeignObject(midPoint, style.stroke, model.text.value); + plusElements = this.getForeignObject(midPoint, condColor, model.text.value); } else if (!model.properties.chartStatusColor) { const midPoint = [points[0][0], points[0][1] + offsetY]; plusElements = this.getPlusElements(midPoint); @@ -88,7 +90,7 @@ class SkipView extends CurvedEdge { // 判断是否由横线变为竖线,并且是互斥网关 if (model.sourceNode && ['serial', 'inclusive'].includes(model.sourceNode.type as string) && p0[1] === p1[1] && p0[0] !== p1[0]) { const midPoint = [p2[0], p1[1] + offsetY]; - plusElements = this.getForeignObject(midPoint, style.stroke, model.text.value); + plusElements = this.getForeignObject(midPoint, condColor, model.text.value); } } @@ -190,7 +192,7 @@ class SkipView extends CurvedEdge { cx: x, cy: y, r: 13, - fill: 'blue', + fill: '#409eff', }), h('line', { x1: x - 8, diff --git a/warm-flow-ui/src/components/design/mimic/vue/EdgeTooltip.vue b/warm-flow-ui/src/components/design/mimic/vue/EdgeTooltip.vue index 35d362cccdcf8a43ee38262bba65f8a6a8da0e35..6859b3ed82ab908efcc4be741373d83667fc9f0c 100644 --- a/warm-flow-ui/src/components/design/mimic/vue/EdgeTooltip.vue +++ b/warm-flow-ui/src/components/design/mimic/vue/EdgeTooltip.vue @@ -37,14 +37,14 @@ const tooltipStyle = computed(() => ({ pointerEvents: 'auto', backgroundColor: themeColors.value.tooltipBg, border: `1px solid ${themeColors.value.tooltipBorder}`, - borderRadius: '4px', + borderRadius: '12px', boxShadow: themeColors.value.tooltipShadow, - padding: '4px 5px', - fontSize: '15px', + padding: '6px', + fontSize: '13px', zIndex: 1000, color: themeColors.value.tooltipColor, display: 'flex', - width: '350px' + width: 'max-content' })); function handleTooltipEnter() { @@ -66,82 +66,75 @@ const handleClick = (item) => {