From 8aa269ba98dca3084ad25edbd0bc97fe0de2efb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E4=BA=9A=E5=B3=B0=20=7C=20battcn?= <1837307557@qq.com> Date: Tue, 23 Jun 2026 09:19:14 +0800 Subject: [PATCH 01/13] =?UTF-8?q?update:=20=E6=96=B0=E5=A2=9E=20AI=20codin?= =?UTF-8?q?g=20agent=20=E6=8F=90=E7=A4=BA=E8=AF=8D=E8=A7=84=E5=88=99(AGENT?= =?UTF-8?q?S/CLAUDE/.cursor)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 根 AGENTS.md(规则唯一来源) 与 CLAUDE.md(红线摘要) - core/orm/plugin/ui 模块级 AGENTS.md(仅写模块差异) - .cursor/rules/warm-flow.mdc(Cursor 规则, 指向 AGENTS.md) Co-authored-by: Cursor --- .cursor/rules/warm-flow.mdc | 48 ++++++++ AGENTS.md | 238 ++++++++++++++++++++++++++++++++++++ CLAUDE.md | 53 ++++++++ warm-flow-core/AGENTS.md | 45 +++++++ warm-flow-orm/AGENTS.md | 39 ++++++ warm-flow-plugin/AGENTS.md | 34 ++++++ warm-flow-ui/AGENTS.md | 43 +++++++ 7 files changed, 500 insertions(+) create mode 100644 .cursor/rules/warm-flow.mdc create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 warm-flow-core/AGENTS.md create mode 100644 warm-flow-orm/AGENTS.md create mode 100644 warm-flow-plugin/AGENTS.md create mode 100644 warm-flow-ui/AGENTS.md diff --git a/.cursor/rules/warm-flow.mdc b/.cursor/rules/warm-flow.mdc new file mode 100644 index 00000000..93a495ea --- /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/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..894956ad --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,238 @@ +# AGENTS.md + +本文件是 Codex 以及其他 coding agent 在本仓库工作的项目级操作指南,也是本仓库 **AI 规则的唯一主来源**。 + +它综合了: + +- 当前 `warm-flow` 仓库的真实模块结构、技术基线与扩展机制。 +- dromara 开源协作约定与 Apache 2.0 开源协议要求。 +- 工作流引擎作为「公共依赖库(SDK)」对外契约稳定与多生态兼容的长期规则。 +- `.qoder/repowiki` 中已沉淀的引擎架构、实体模型、服务层与权限文档。 +- 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` 是更细的引擎架构与领域参考(本地文档,不要无故改动,也不要当作必读入口长期新增依赖)。 +- 新增、删除或调整长期项目规则时,先更新根 `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 00000000..210cabe5 --- /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 00000000..c2fd4d67 --- /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 00000000..b28c6cd3 --- /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 00000000..def4f721 --- /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/AGENTS.md b/warm-flow-ui/AGENTS.md new file mode 100644 index 00000000..2eaf6a14 --- /dev/null +++ b/warm-flow-ui/AGENTS.md @@ -0,0 +1,43 @@ +# 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 -- Gitee From ccc0d91f2df1d566a68360df6946f4c8454fbce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E4=BA=9A=E5=B3=B0=20=7C=20battcn?= <1837307557@qq.com> Date: Tue, 23 Jun 2026 14:24:50 +0800 Subject: [PATCH 06/13] =?UTF-8?q?style:=20=E6=B5=81=E7=A8=8B=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E5=99=A8=E7=94=BB=E5=B8=83=E4=B8=BB=E9=A2=98=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E4=B8=8E=E8=AE=BE=E8=AE=A1=E6=80=81=E8=AF=AD=E4=B9=89?= =?UTF-8?q?=E8=89=B2=E6=A0=87=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- warm-flow-ui/src/views/flow-design/index.vue | 71 +++++++++++--------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/warm-flow-ui/src/views/flow-design/index.vue b/warm-flow-ui/src/views/flow-design/index.vue index 697a5967..87d90651 100644 --- a/warm-flow-ui/src/views/flow-design/index.vue +++ b/warm-flow-ui/src/views/flow-design/index.vue @@ -8,7 +8,7 @@
- {{ logicJson.flowName }} + {{ logicJson.flowName || '未命名流程' }}
@@ -244,6 +244,8 @@ async function handleStepClick(index) { onMounted(() => { // 隐藏滚动条 document.body.style.overflow = 'hidden'; + // 标记当前处于设计器页面:供经典节点设计态语义色判断(业务侧实例进度图不受影响) + window.__WF_FLOW_DESIGN_MODE__ = true; if (!appParams.value) appStore.fetchTokenName(); if (appParams.value.id) { definitionId.value = appParams.value.id; @@ -347,6 +349,15 @@ function initLogicFlow() { fill: themeColors.value.edgeTextBg, }, }, + // 选中/悬浮的包围框:默认是黑色虚线,改成柔和蓝实线(贴近基础信息页 chroma 与 Mac 风格) + outline: { + stroke: 'rgba(64, 158, 255, 0.7)', + strokeWidth: 1, + strokeDasharray: '', + hover: { + stroke: 'rgba(64, 158, 255, 0.35)', + }, + }, }); register(); @@ -427,6 +438,8 @@ watch(isDark, (v) => { onUnmounted(() => { cleanupMessageListener(); window.removeEventListener('resize', handleMobileResize); + // 离开设计器页面,复位设计态标记 + window.__WF_FLOW_DESIGN_MODE__ = false; }); // 监听窗口变化,真机旋转屏幕时重绘(带防抖 + 标志位屏蔽抽屉操作干扰) @@ -1223,8 +1236,8 @@ html.dark .steps-tabs { } .step-tab:hover { - color: #3b82f6; - background: rgba(59, 130, 246, 0.06); + color: var(--wf-primary, #409eff); + background: var(--wf-primary-light, #ecf5ff); } .step-tab .tab-icon { @@ -1240,8 +1253,8 @@ html.dark .steps-tabs { .step-tab.active { color: #fff; - background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); - box-shadow: 0 4px 12px rgba(59, 130, 246, 0.35); + background: var(--wf-primary, #409eff); + box-shadow: 0 2px 8px rgba(64, 158, 255, 0.28); } .step-tab.active .tab-icon { @@ -1249,9 +1262,7 @@ html.dark .steps-tabs { } .step-tab.active:hover { - background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%); - transform: translateY(-1px); - box-shadow: 0 6px 16px rgba(59, 130, 246, 0.4); + background: var(--wf-primary-dark, #2b7de9); } /* ========== 保存按钮 ========== */ @@ -1259,25 +1270,28 @@ html.dark .steps-tabs { display: flex; align-items: center; gap: 6px; - background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important; + background: var(--wf-primary, #409eff) !important; border: none !important; color: #fff !important; font-weight: 500; font-size: 14px; - padding: 10px 24px !important; + padding: 9px 22px !important; border-radius: 10px !important; - box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); - transition: all 0.25s ease !important; + box-shadow: 0 2px 8px rgba(64, 158, 255, 0.28); + transition: all 0.2s ease !important; } .save-btn:hover { - background: linear-gradient(135deg, #059669 0%, #047857 100%) !important; - box-shadow: 0 6px 16px rgba(16, 185, 129, 0.4) !important; - transform: translateY(-1px); + background: var(--wf-primary-dark, #2b7de9) !important; } -.save-btn:active { - transform: translateY(0); +/* Element Plus 会把按钮默认插槽内容包进一层 span, + 导致 .save-btn 上的 gap 作用不到「图标 + 文字」之间。 + 这里让该包裹层成为 flex 容器,恢复图标与文字的间距与垂直居中。 */ +.save-btn > span { + display: inline-flex; + align-items: center; + gap: 6px; } .save-btn .save-icon { @@ -1291,16 +1305,15 @@ html.dark .design-header { border-bottom-color: var(--wf-border-color); } -/* 暗黑模式:保存按钮降低饱和度,避免刺眼 */ +/* 暗黑模式:保存按钮统一主色,扁平 */ html.dark .save-btn, html.dark .toolbar-save-btn { - background: linear-gradient(135deg, var(--wf-save-dark, #0d9488) 0%, var(--wf-save-dark-end, #0f766e) 100%) !important; - box-shadow: 0 2px 8px rgba(13, 148, 136, 0.25) !important; + background: var(--wf-primary, #409eff) !important; + box-shadow: none !important; } html.dark .save-btn:hover, html.dark .toolbar-save-btn:hover { - background: linear-gradient(135deg, var(--wf-save-dark-end, #0f766e) 0%, var(--wf-save-darker, #115e59) 100%) !important; - box-shadow: 0 4px 12px rgba(13, 148, 136, 0.35) !important; + background: var(--wf-primary-dark, #2b7de9) !important; } /* 工具栏区域(el-header 第二行)暗黑模式 */ @@ -1374,23 +1387,17 @@ html.dark .logo-text { /* ========== 工具栏内保存按钮 ========== */ .toolbar-save-btn { - background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important; + background: var(--wf-primary, #409eff) !important; border: none !important; color: #fff !important; font-weight: 500; border-radius: 8px !important; - box-shadow: 0 2px 8px rgba(16, 185, 129, 0.25); - transition: all 0.25s ease !important; + box-shadow: none; + transition: background-color 0.2s ease !important; } .toolbar-save-btn:hover { - background: linear-gradient(135deg, #059669 0%, #047857 100%) !important; - box-shadow: 0 4px 12px rgba(16, 185, 129, 0.35) !important; - transform: translateY(-1px); -} - -.toolbar-save-btn:active { - transform: translateY(0); + background: var(--wf-primary-dark, #2b7de9) !important; } /* ========== 响应式适配:平板端 (<= 1024px) ========== */ -- Gitee From e755c09ab774894c0e1cbd4cbb0349d60336e88f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E4=BA=9A=E5=B3=B0=20=7C=20battcn?= <1837307557@qq.com> Date: Tue, 23 Jun 2026 14:24:50 +0800 Subject: [PATCH 07/13] =?UTF-8?q?update:=20=E6=9B=B4=E6=96=B0=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E5=99=A8=E5=9B=BE=E6=A0=87=E8=B5=84=E4=BA=A7=EF=BC=88?= =?UTF-8?q?=E8=8A=82=E7=82=B9/=E5=B7=A5=E5=85=B7=E6=A0=8F/=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=20svg=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .../src/assets/icons/svg/baseInfo.svg | 11 +++++------ warm-flow-ui/src/assets/icons/svg/between.svg | 10 +++++----- warm-flow-ui/src/assets/icons/svg/classic.svg | 7 +++++++ .../src/assets/icons/svg/flowDesign.svg | 19 +++++++------------ .../src/assets/icons/svg/flowName.svg | 9 +++++---- .../src/assets/icons/svg/inclusive.svg | 2 +- warm-flow-ui/src/assets/icons/svg/mimic.svg | 7 +++++++ .../src/assets/icons/svg/parallel.svg | 6 +++--- warm-flow-ui/src/assets/icons/svg/save.svg | 14 ++++---------- warm-flow-ui/src/assets/icons/svg/serial.svg | 6 +++--- 10 files changed, 47 insertions(+), 44 deletions(-) create mode 100644 warm-flow-ui/src/assets/icons/svg/classic.svg create mode 100644 warm-flow-ui/src/assets/icons/svg/mimic.svg diff --git a/warm-flow-ui/src/assets/icons/svg/baseInfo.svg b/warm-flow-ui/src/assets/icons/svg/baseInfo.svg index 26b36b7d..ebdac396 100644 --- a/warm-flow-ui/src/assets/icons/svg/baseInfo.svg +++ b/warm-flow-ui/src/assets/icons/svg/baseInfo.svg @@ -1,7 +1,6 @@ - - - + + + + + diff --git a/warm-flow-ui/src/assets/icons/svg/between.svg b/warm-flow-ui/src/assets/icons/svg/between.svg index 7d64c6fc..9b50c2f7 100644 --- a/warm-flow-ui/src/assets/icons/svg/between.svg +++ b/warm-flow-ui/src/assets/icons/svg/between.svg @@ -3,13 +3,13 @@ + fill="#ecf5ff" p-id="1718"> + fill="#2b7de9" p-id="1719"> + fill="#409eff" p-id="1720"> + fill="#66b1ff" p-id="1721"> + fill="#a0cfff" p-id="1722"> diff --git a/warm-flow-ui/src/assets/icons/svg/classic.svg b/warm-flow-ui/src/assets/icons/svg/classic.svg new file mode 100644 index 00000000..3203698d --- /dev/null +++ b/warm-flow-ui/src/assets/icons/svg/classic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/warm-flow-ui/src/assets/icons/svg/flowDesign.svg b/warm-flow-ui/src/assets/icons/svg/flowDesign.svg index bfbbcde0..53380a23 100644 --- a/warm-flow-ui/src/assets/icons/svg/flowDesign.svg +++ b/warm-flow-ui/src/assets/icons/svg/flowDesign.svg @@ -1,13 +1,8 @@ - - - - - - + + + + + + + diff --git a/warm-flow-ui/src/assets/icons/svg/flowName.svg b/warm-flow-ui/src/assets/icons/svg/flowName.svg index 234b6772..81f91d6f 100644 --- a/warm-flow-ui/src/assets/icons/svg/flowName.svg +++ b/warm-flow-ui/src/assets/icons/svg/flowName.svg @@ -1,5 +1,6 @@ - - + + + + + diff --git a/warm-flow-ui/src/assets/icons/svg/inclusive.svg b/warm-flow-ui/src/assets/icons/svg/inclusive.svg index 71fb0b1b..a4f9a63b 100644 --- a/warm-flow-ui/src/assets/icons/svg/inclusive.svg +++ b/warm-flow-ui/src/assets/icons/svg/inclusive.svg @@ -4,5 +4,5 @@ xmlns="http://www.w3.org/2000/svg" p-id="9632" width="32" height="200"> + fill="#409eff"> diff --git a/warm-flow-ui/src/assets/icons/svg/mimic.svg b/warm-flow-ui/src/assets/icons/svg/mimic.svg new file mode 100644 index 00000000..1a449897 --- /dev/null +++ b/warm-flow-ui/src/assets/icons/svg/mimic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/warm-flow-ui/src/assets/icons/svg/parallel.svg b/warm-flow-ui/src/assets/icons/svg/parallel.svg index 63b2715d..6975d8b5 100644 --- a/warm-flow-ui/src/assets/icons/svg/parallel.svg +++ b/warm-flow-ui/src/assets/icons/svg/parallel.svg @@ -2,9 +2,9 @@ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> - + + fill="#409eff" p-id="3252"> + fill="#409eff" p-id="3253"> diff --git a/warm-flow-ui/src/assets/icons/svg/save.svg b/warm-flow-ui/src/assets/icons/svg/save.svg index 4f69098b..b13c3d0a 100644 --- a/warm-flow-ui/src/assets/icons/svg/save.svg +++ b/warm-flow-ui/src/assets/icons/svg/save.svg @@ -1,11 +1,5 @@ - - - - - + + + + diff --git a/warm-flow-ui/src/assets/icons/svg/serial.svg b/warm-flow-ui/src/assets/icons/svg/serial.svg index ffe85903..5188b6a9 100644 --- a/warm-flow-ui/src/assets/icons/svg/serial.svg +++ b/warm-flow-ui/src/assets/icons/svg/serial.svg @@ -2,9 +2,9 @@ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> - + + fill="#409eff" p-id="4081"> + fill="#409eff" p-id="4082"> -- Gitee From ea15c02119f1ecfa7385e108d801b39fac22670a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E4=BA=9A=E5=B3=B0=20=7C=20battcn?= <1837307557@qq.com> Date: Tue, 23 Jun 2026 14:24:50 +0800 Subject: [PATCH 08/13] =?UTF-8?q?update:=20=E8=A1=A5=E5=85=85=E5=B9=B6?= =?UTF-8?q?=E6=A0=A1=E6=AD=A3=20warm-flow-ui=20UI=20=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E8=A7=84=E8=8C=83=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- warm-flow-ui/AGENTS.md | 88 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/warm-flow-ui/AGENTS.md b/warm-flow-ui/AGENTS.md index 2eaf6a14..39bd4a3d 100644 --- a/warm-flow-ui/AGENTS.md +++ b/warm-flow-ui/AGENTS.md @@ -41,3 +41,91 @@ yarn preview # 预览构建产物 - 改动后至少 `yarn dev` 跑通本地、`yarn build:prod` 能成功构建;涉及流程图 / 表单交互时手动验证关键路径。 - 无法验证时如实报告命令、现象与风险,不要声称构建通过。 + +## UI 设计规范(Design System) + +> 设计器整体风格:**扁平 + iOS / macOS 质感**,主色调(chroma)为蓝色 `#409eff`。**基准页面是 `基础信息`(`components/design/common/vue/baseInfo.vue`)**,所有节点属性面板、弹窗、表单都要向它对齐。新增任何表单 / 面板 / 控件前,先看 `baseInfo.vue` 和本节,复用既有 token 与 mixin,**不要另起一套风格**。 + +### 1. 设计 Token(颜色 / 圆角 / 阴影 / 字体) + +- 颜色来源唯一:`src/config/themeConfig.js`(JS 常量)→ 运行时同步为 `--wf-*` CSS 变量;**禁止在组件里写死十六进制色**,用变量并带回退值,如 `var(--wf-primary, #409eff)`。 +- 主色族:`--wf-primary #409eff`、`--wf-primary-dark #2b7de9`、`--wf-primary-light #ecf5ff`、`--wf-primary-lighter #f0f7ff`。 +- 语义色:危险 `--wf-danger #f56c6c`、成功 `#67c23a`、监听器紫 `#8960dc`。 +- 圆角:`--wf-radius 8px`、`--wf-radius-lg 12px`、`--wf-radius-sm 4px`。 +- 字体栈(必加,保证 iOS 质感):`-apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif` + `-webkit-font-smoothing: antialiased`。 +- 共享 SCSS mixin 在 `src/assets/styles/_common.scss`:`modern-tabs` / `base-settings-card` / `section-card` / `table-form-align` / `responsive-adaption`,改风格优先改 mixin,全局生效。 + +### 2. 输入控件(白底描边式) + +统一为「白底 + 浅边框」,独立的 `el-input / el-select / el-textarea`(基础信息页 / 属性抽屉 / 弹窗): + +- 默认:`background: var(--wf-bg-white, #fff)`;`border: 1px solid var(--wf-border-light, #dcdfe6)`;`border-radius: 10px`;`box-shadow: none`。**未填写也保持白底**。 +- hover:`border-color: var(--wf-primary)`。 +- focus:白底 + `border-color: var(--wf-primary)` + 柔光环 `box-shadow: 0 0 0 4px rgba(64,158,255,0.12)`。 +- 校验失败(`.is-error`):红边 + 红光环 `0 0 0 4px rgba(245,108,108,0.12)`,**优先级要压过 focus 蓝色**,禁止红蓝混色。 +- 暗黑:深底(`rgba(255,255,255,0.06)` 或 `--wf-bg-color`)+ 描边,focus 蓝环。 +- **控件尺寸用默认(高 ~32px),禁止 `size="small"`**(与基础信息页一致)。 +- **禁止**默认态用发灰的填充底(曾用的 `rgba(118,128,150,0.07)` iOS 灰填充已废弃——一进页面没填写就发灰、易被误读为禁用态)。 +- **例外**:表格内的输入 / 下拉控件默认 `transparent`(白表格上即白底),hover 轻填充、focus 才显白底 + 蓝环(见第 5 节),避免整行被填充底染灰。 + +### 3. 表单标签与分区 + +- 标签:**右对齐**(EP 默认 `label-position`,勿设 `left`)、`label-width="110px"`、`font-weight:600`、色 `--wf-text-primary`。 +- 分区:**扁平**——分区标题 15px 加粗 + 底部 1px 分隔线(`--wf-border-lighter`),下方内容直接平铺。**禁止**给分区套「边框卡片 + 灰渐变头底 + 阴影」(`base-settings-card` / `section-card` mixin 已扁平化,勿改回卡片)。 +- 行间距:参考基础信息页 `el-form-item margin-bottom: 24px` 的呼吸感。 + +### 4. 页签(Tab) + +- 用 `modern-tabs` mixin:**扁平下划线**风格——底部一条分隔线;tab 项 = `图标 + 文字`,默认灰字,激活态主色字 + 底部 2px 主色下划线指示条(带滑入动画)。**禁止**蓝色实心胶囊 / 外层白盒 / 上浮阴影。 +- tab 图标:16px 单路径 SVG,`fill="currentColor"`(跟随 tab 文字色),放在 tab 上而非内容区;图标语义示例:基础设置=齿轮、办理人=人群、监听器=铃铛、扩展=拼图。 +- **避免「两个标题」**:抽屉本身已有标题(如「设置边属性」),面板内容区不要再放与之重复的分区标题——有 tab 的面板 tab 名即标题;单分区无 tab 的面板(边 / 网关 / 结束)也直接平铺表单、**去掉 `.base-settings-header` 二级标题**(如「跳转条件配置 / 网关配置 / 基础配置」),保持单一标题。 + +### 5. 表格 + +`el-table` 统一:圆角 `12px` + 1px 边框 + `overflow:hidden`;**表头白底 `var(--wf-bg-white, #fff)`**、`font-weight:600`(全站表头统一为白——办理人 / 监听器 / 扩展属性表一致;勿用发灰的 `rgba(118,128,150,0.06)`,也需用 `!important` 压过 ruoyi 全局 `.el-table th { #f8f8f9 }`);行 hover = 浅蓝底 `--wf-primary-light` + 左侧 3px 主色指示条;删除按钮 `el-button--danger` hover 红渐变 + 阴影。暗黑:表头 `rgba(255,255,255,0.04)`、hover `rgba(64,158,255,0.12)`。 + +**表格内的输入 / 下拉控件默认透明底**(`background: transparent`),hover 轻填充、focus 才显白底 + 蓝环——让整行读作干净白底,避免「整行都是控件」的行被填充底染灰、与「含纯文本列」的行深浅不一致。 + +### 6. 单选(radio-card) + +统一为「卡片式单选」一套设计语言:`1.5px` 边框 + 圆角,选中 = 主色边框 + **实色浅蓝底 `--wf-primary-light`**(勿用渐变)+ 实心蓝圆点。两种尺寸变体: + +- 大卡片(图标 + 标题 + 描述):用于「设计器模型」等需要解释的重要选择。 +- 紧凑 pill(圆点 + 文字 + 可选 tooltip):用于「协作方式 / 自定义表单」等简单多选项。 +- 布尔类(是 / 否)可直接用 `el-switch`(如基础信息页「自定义表单」)。 + +### 7. 按钮 + +- 「增加行 / 添加行」:虚线主色边框 + 透明底 + 居中,hover 实线边框 + 浅蓝底 `--wf-primary-light` + 主色阴影。 +- 主操作(保存等):主色实心,圆角 ~10px,图标与文字间距用包裹 `span` 的 `inline-flex + gap`(EP 会把图标+文字包进一层 span,`gap` 要落在该 span 上)。 + +### 8. 属性面板抽屉(append-to-body) + +- `el-drawer` teleport 到 body,scoped 样式命不中,**面板内样式必须写全局 `
- +
@@ -217,7 +217,8 @@ const isMobileDevice = () => { const zoomViewport = async (mode) => { if (!lf.value) return; if (mode === 'fit') { - lf.value.fitView(40, 20); + // 自适应:显示全部节点并居中,最大缩放 100% + fitViewIfMobile(); } else if (mode === 1) { lf.value.zoom(1); lf.value.translateCenter(); @@ -246,6 +247,12 @@ function fitViewIfMobile() { } lf.value.fitView(40, 20); + // 限制最大缩放 100%:节点少时不放大撑屏,保持原始大小并居中 + const scale = lf.value.getTransform ? lf.value.getTransform().SCALE_X : 1; + if (scale && scale > 1) { + lf.value.resetZoom ? lf.value.resetZoom() : lf.value.zoom(1); + if (lf.value.translateCenter) lf.value.translateCenter(); + } } /** diff --git a/warm-flow-ui/src/views/flow-design/index.vue b/warm-flow-ui/src/views/flow-design/index.vue index 87d90651..a70054a0 100644 --- a/warm-flow-ui/src/views/flow-design/index.vue +++ b/warm-flow-ui/src/views/flow-design/index.vue @@ -44,8 +44,8 @@
- - + + @@ -166,13 +166,27 @@ const isMobileDevice = () => { return window.innerWidth <= 1024 || ('ontouchstart' in window && window.innerWidth <= 1280); }; -/** 仅在移动端/平板执行 fitView,PC 端不干预 */ +/** 仅在移动端/平板执行 fitView(用于新增节点等增量操作,避免 PC 编辑时被打断) */ function fitViewIfMobile() { if (isMobileDevice() && lf.value?.fitView) { lf.value.fitView(40, 20); } } +/** 自适应显示全部节点(所有端):打开 / 进入流程设计 / 点击「自适应」按钮时使用 */ +function fitViewAll() { + const lfInst = lf.value; + if (!lfInst?.fitView) return; + lfInst.fitView(40, 20); + // fitView 会把节点较少的流程放大到撑满画布,这里限制最大缩放 100%: + // 流程大 -> 缩小铺满;流程小 -> 保持原始大小并居中,避免进来就糊脸 + const scale = lfInst.getTransform ? lfInst.getTransform().SCALE_X : 1; + if (scale && scale > 1) { + lfInst.resetZoom ? lfInst.resetZoom() : lfInst.zoom(1); + if (lfInst.translateCenter) lfInst.translateCenter(); + } +} + const activeStep = ref(0); const onlyDesignShow = ref(false); @@ -368,8 +382,8 @@ function initLogicFlow() { initTouchEventBridge(); if (logicJson.value) { lf.value.render(logicJson.value); - // 移动端/平板端:自适应显示全部节点;PC 端保持默认行为不干预 - fitViewIfMobile(); + // 打开即自适应显示全部节点(所有端) + fitViewAll(); } // 初始化完成后,如果当前是暗黑模式,显式应用一次主题(解决 URL 参数初始化时序问题) if (isDark.value && lf.value) { @@ -387,15 +401,15 @@ function initLogicFlow() { } /** - * 真机兼容:延迟触发 LogicFlow resize + fitView(仅移动端/平板端生效) - * PC 端不执行自动 fitView,保持用户手动缩放行为 + * 延迟触发 LogicFlow resize + fitView(所有端) + * 覆盖移动端真机 / v-show 切换 / iframe 嵌入等容器尺寸延迟场景 */ function scheduleMobileResize() { const doFit = () => { if (lf.value && lf.value.resize) { lf.value.resize(); - // 仅在移动设备上才执行自动 fitView - requestAnimationFrame(fitViewIfMobile); + // resize 后自适应显示全部节点(所有端,覆盖布局/iframe 时序) + requestAnimationFrame(fitViewAll); } }; // 多重延迟策略覆盖各种场景:移动端/v-show切换/iframe嵌入 @@ -408,15 +422,14 @@ function scheduleMobileResize() { } /** - * 监听步骤切换:从"基础信息"切到"流程设计"时(仅移动端/平板端生效) - * PC 端不执行自动 fitView,保持用户手动缩放行为 + * 监听步骤切换:从"基础信息"切到"流程设计"时,自适应显示全部节点(所有端) */ watch(activeStep, (newVal) => { if (newVal === 1 && lf.value) { const doFit = () => { if (lf.value?.resize) { lf.value.resize(); - requestAnimationFrame(fitViewIfMobile); + requestAnimationFrame(fitViewAll); } }; // 多次延迟确保在各种时序下移动端能正确适配 @@ -998,9 +1011,9 @@ const zoomViewport = async (zoom) => { lf.value.translateCenter(); } } else if (zoom === 'fit') { - // 移动端/平板端自适应:fitView 将所有节点缩放并居中到画布可视区域 + // 自适应:显示全部节点并居中,最大缩放 100%(节点少不放大撑屏) if (lf.value.fitView) { - lf.value.fitView(40, 20); + fitViewAll(); } else { // fallback if (lf.value.translateCenter) lf.value.translateCenter(); -- Gitee From 0cf08d53615b6e9586a7ebddc82f9112ba0dcc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E4=BA=9A=E5=B3=B0=20=7C=20battcn?= <1837307557@qq.com> Date: Thu, 25 Jun 2026 16:19:55 +0800 Subject: [PATCH 10/13] =?UTF-8?q?fix:=20=E8=AE=BE=E8=AE=A1=E5=99=A8?= =?UTF-8?q?=E8=AF=AD=E4=B9=89=E8=89=B2=E4=BB=85=E5=9C=A8=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E5=99=A8=E5=86=85=E7=94=9F=E6=95=88=E5=B9=B6=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E7=8A=B6=E6=80=81=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit applyClassicDesignColor 去掉 status===1/2 判断,设计器内一律使用新版语义色; 业务侧流程实例进度图(非设计器)沿用后端 chartStatusColor 状态色,行为不变。(PR#396 评审③) Co-authored-by: Cursor --- warm-flow-ui/src/components/design/common/js/tool.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/warm-flow-ui/src/components/design/common/js/tool.js b/warm-flow-ui/src/components/design/common/js/tool.js index fe1dcadc..6237f2f4 100644 --- a/warm-flow-ui/src/components/design/common/js/tool.js +++ b/warm-flow-ui/src/components/design/common/js/tool.js @@ -310,8 +310,8 @@ export const setCommonStyle = (style, properties, nodeType, type) => { * 让各类节点一眼可辨,同时把发灰的投影替换成同色系柔和阴影。 * * 安全边界(不破坏既有契约): - * - 仅在设计器页面生效(window.__WF_FLOW_DESIGN_MODE__),业务侧渲染的流程实例进度图不受影响; - * - status 为「在办(1) / 已办(2)」时直接返回,继续沿用后端 chartStatusColor 的状态语义; + * - 仅在设计器页面生效(window.__WF_FLOW_DESIGN_MODE__):设计器内一律用新版语义色,不再判断节点运行状态; + * - 业务侧渲染的流程实例进度图(非设计器)不受影响,继续沿用后端 chartStatusColor 的状态语义; * - 仅经典模式节点调用本函数,仿钉钉模式不调用、行为完全不变。 * * @param {Object} style setCommonStyle 处理后的样式对象 @@ -321,8 +321,8 @@ export const setCommonStyle = (style, properties, nodeType, type) => { */ export const applyClassicDesignColor = (style, properties, rgb) => { const inDesigner = typeof window !== 'undefined' && window.__WF_FLOW_DESIGN_MODE__; - // 非设计器页面,或节点已有运行状态:保持 setCommonStyle 的状态语义色不变 - if (!inDesigner || properties.status === 1 || properties.status === 2) { + // 仅设计器页面用新版语义色;非设计器保持 setCommonStyle 的状态语义色不变 + if (!inDesigner) { return style; } style.stroke = `rgb(${rgb})`; -- Gitee From 621262562b5dcd8ea5f0ff1bb59f6412cdb7babd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E4=BA=9A=E5=B3=B0=20=7C=20battcn?= <1837307557@qq.com> Date: Thu, 25 Jun 2026 16:20:02 +0800 Subject: [PATCH 11/13] =?UTF-8?q?style:=20=E4=BB=BF=E9=92=89=E9=92=89?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E9=80=82=E9=85=8D=E6=9A=97=E9=BB=91=E5=B9=B6?= =?UTF-8?q?=E6=8C=89=E8=8A=82=E7=82=B9=E7=B1=BB=E5=9E=8B=E5=8C=BA=E5=88=86?= =?UTF-8?q?=E9=85=8D=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 节点卡片背景/文字改用主题变量 --wf-bg-white/--wf-text-primary 适配暗黑模式; 节点头部与网关按类型着色——开始绿/审批蓝/结束红、串行橙/并行青/包容紫,与经典模式语义色统一; 修复网关标签文字写死 #000 在暗黑模式下不可见的问题。(PR#396 评审②④) Co-authored-by: Cursor --- .../components/design/mimic/js/inclusive.ts | 16 ++++++++++++++-- .../src/components/design/mimic/js/parallel.ts | 16 ++++++++++++++-- .../src/components/design/mimic/js/serial.ts | 16 ++++++++++++++-- .../components/design/mimic/vue/baseNode.vue | 18 ++++++++++++------ 4 files changed, 54 insertions(+), 12 deletions(-) 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 3dc8f4ad..2a46dadf 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 { @@ -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 c2d9aa90..cc8dc6b7 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 { @@ -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 8a4a993c..4b3372ce 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 { @@ -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/vue/baseNode.vue b/warm-flow-ui/src/components/design/mimic/vue/baseNode.vue index e4ebb57b..b9d14092 100644 --- a/warm-flow-ui/src/components/design/mimic/vue/baseNode.vue +++ b/warm-flow-ui/src/components/design/mimic/vue/baseNode.vue @@ -85,18 +85,24 @@ const baseNodeColor = computed(() => { border: (props.status === 1 ? "2px dashed " : "1px solid ") + (props.stroke || "rgb(166,178,189)"), }; } - // 设计态:无边框纯白卡片,仅靠柔和阴影区分层次(更现代、更干净) + // 设计态:无边框卡片,仅靠柔和阴影区分层次;背景跟随主题变量(暗黑模式自动变深) return { - background: "#fff", + background: "var(--wf-bg-white, #fff)", }; }); +// 设计态头部按节点类型区分(开始=绿 / 结束=红 / 其余审批=蓝),不再全蓝 +const DESIGN_HEADER_GRADIENT = { + start: "linear-gradient(135deg, #67c23a 0%, #5daf34 100%)", + end: "linear-gradient(135deg, #f56c6c 0%, #e85c5c 100%)", +}; + const topSectionColor = computed(() => { if (isRuntime.value) { return { backgroundColor: props.stroke || "rgb(166,178,189)" }; } - // 设计态:钉钉蓝渐变头部 - return { background: "linear-gradient(135deg, #409eff 0%, #2b7de9 100%)" }; + // 设计态:按节点类型着色头部,默认审批蓝 + return { background: DESIGN_HEADER_GRADIENT[props.type] || "linear-gradient(135deg, #409eff 0%, #2b7de9 100%)" }; }); const deleteNode = () => { @@ -164,7 +170,7 @@ function handleLeave() { height: 80px; box-sizing: border-box; border-radius: 10px; - background: #fff; + background: var(--wf-bg-white, #fff); /* 去边框,仅用多层柔和阴影区分层次(现代卡片质感) */ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.10), 0 1px 4px rgba(0, 0, 0, 0.05); overflow: hidden; /* 让头部跟随卡片圆角 */ @@ -198,7 +204,7 @@ function handleLeave() { padding: 10px; height: calc(100%); font-size: 14px; - color: #303133; + color: var(--wf-text-primary, #303133); } .edit-icon { -- Gitee From 257286d6441a24c39415949e66703902faa018e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E4=BA=9A=E5=B3=B0=20=7C=20battcn?= <1837307557@qq.com> Date: Thu, 25 Jun 2026 16:20:09 +0800 Subject: [PATCH 12/13] =?UTF-8?q?docs:=20=E4=BF=AE=E6=AD=A3=20AGENTS.md=20?= =?UTF-8?q?=E5=AF=B9=20qoder/repowiki=20=E7=9A=84=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 .qoder/repowiki 标注为本地、已 gitignore、未纳入仓库的可选参考资源, 避免文档引用与仓库实际内容不一致。(PR#396 评审⑤) Co-authored-by: Cursor --- AGENTS.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 894956ad..a91856c0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,6 @@ - 当前 `warm-flow` 仓库的真实模块结构、技术基线与扩展机制。 - dromara 开源协作约定与 Apache 2.0 开源协议要求。 - 工作流引擎作为「公共依赖库(SDK)」对外契约稳定与多生态兼容的长期规则。 -- `.qoder/repowiki` 中已沉淀的引擎架构、实体模型、服务层与权限文档。 - Karpathy 风格 coding-agent 规则:澄清不确定性、保持简单、避免顺手改无关代码、用可验证结果证明行为。 ## 项目概览 @@ -71,7 +70,7 @@ ## 规则源维护 - `AGENTS.md` 是本仓库 agent 规则主来源。 -- `.qoder/repowiki` 是更细的引擎架构与领域参考(本地文档,不要无故改动,也不要当作必读入口长期新增依赖)。 +- `.qoder/repowiki` 是更细的引擎架构与领域参考(**本地文档,已 gitignore、未纳入仓库**;作者本地可选参考,团队成员默认没有,不要当作必读入口或长期依赖)。 - 新增、删除或调整长期项目规则时,先更新根 `AGENTS.md`,再按需要同步模块级 `AGENTS.md`、根 `CLAUDE.md` 与 `.cursor/rules`。 - 如果本文件、其他 agent 规则与用户当前指令冲突,优先遵循用户当前指令,同时说明冲突点、取舍原因与影响。 - 不要把一次性任务背景写成永久规则。只有能长期约束本仓库开发质量的约定才加入本文件。 @@ -84,7 +83,7 @@ 2. 模块级 `AGENTS.md`(所在顶层模块下若存在)。 3. 仓库根 `AGENTS.md`(本文件)。 4. 根 `CLAUDE.md` 与 `.cursor/rules/*`(与 `AGENTS.md` 冲突一律以 `AGENTS.md` 为准)。 -5. `.qoder/repowiki` 等领域 / 架构参考文档。 +5. (可选)本地 `.qoder/repowiki` 等领域 / 架构参考(未纳入仓库,可能不存在)。 ## 模块级 AGENTS.md 与 CLAUDE.md @@ -185,7 +184,7 @@ mvn -f warm-flow-orm/warm-flow-mybatis/warm-flow-mybatis-core/pom.xml -DskipTest ## 文档与 AI 产物归档 -- 面向用户的正式文档以 README 与官网(warm-flow.com)为准;引擎细节参考 `.qoder/repowiki`。 +- 面向用户的正式文档以 README 与官网(warm-flow.com)为准;引擎细节可参考本地 `.qoder/repowiki`(未纳入仓库,仅本地可选)。 - AI / agent 的一次性调研、决策记录、临时计划放 `.codex/` 或 `docs/`,不要塞进源码包,也不要当作长期必读入口。 - 临时 / 备份代码、注释掉的旧实现、压测入口不留在源码树,确认无引用后删除(git 历史可追溯)。 -- Gitee From 0d04e655a231d2b88f2c9323ec6cdf07f8cdc1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E4=BA=9A=E5=B3=B0=20=7C=20battcn?= <1837307557@qq.com> Date: Thu, 25 Jun 2026 16:20:09 +0800 Subject: [PATCH 13/13] =?UTF-8?q?chore:=20=E8=A1=A5=E5=85=85=E5=BF=BD?= =?UTF-8?q?=E7=95=A5=20demo=20=E4=B8=8E=20vue-designer=20=E7=9A=84?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E4=BE=9D=E8=B5=96=E4=B8=8E=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E4=BA=A7=E7=89=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 忽略各 demo / vue-designer 子目录的 node_modules、dist、.playwright-cli、.codex 等本地产物。 Co-authored-by: Cursor --- .gitignore | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.gitignore b/.gitignore index b9c4713c..79b20bfe 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,16 @@ build/ /.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/ -- Gitee