diff --git a/docs/superpowers/plans/2026-04-21-next-steps-after-platform-context.md b/docs/superpowers/plans/2026-04-21-next-steps-after-platform-context.md new file mode 100644 index 0000000..564fa36 --- /dev/null +++ b/docs/superpowers/plans/2026-04-21-next-steps-after-platform-context.md @@ -0,0 +1,195 @@ +# 拆分后续改进计划 + +日期:2026-04-21 + +## 背景 + +截至本文档编写时,双应用拆分已完成以下里程碑: + +| 里程碑 | 状态 | 关键 commit | +|--------|------|-------------| +| Workspace 结构(三个 crate) | 已完成 | — | +| 平台模块迁入 plc_platform_core | 已完成 | config/db/model/connection/telemetry/event/websocket/service/util/control | +| Web 目录拆分(core/feeder/ops + ServeDir fallback) | 已完成 | — | +| 三面板 UI(运维/应用配置/平台配置) | 已完成 | — | +| Log/Doc handler 迁入 core | 已完成 | — | +| PlatformContext 填充(pool/connection_manager/ws_manager) | 已完成 | 429c2d0 | +| WebSocket 类型去重(feeder 改为从 core 重导出) | 已完成 | 429c2d0 | +| PlatformBuilder 模式(消除 unsafe 初始化) | 已完成 | 429c2d0 | +| 旧 root src/ 删除 | 已完成 | — | +| Ops 应用拥有真实 PlatformContext(含数据库连接) | 已完成 | 429c2d0 | + +以下四项改进是 spec(`docs/superpowers/specs/2026-04-14-dual-app-shared-core-design.md`)中明确要求但尚未完成的工作。 + +--- + +## 改进 1:平台 Handler 迁入 Core(中优先级) + +### 目标 + +将不依赖业务状态的 handler 从 `app_feeder_distributor` 迁入 `plc_platform_core::handler`,使 ops 也能注册同一套平台 API。 + +### 前置条件 + +- PlatformContext 已包含 pool/connection_manager/ws_manager(**已满足**) +- Handler 函数签名需改为从 `PlatformContext` 提取状态,而非 feeder 的 `AppState` + +### 待迁移 Handler + +| 文件 | 行数 | 依赖分析 | 迁移难度 | +|------|------|----------|----------| +| `handler/source.rs` | 626 | pool, connection_manager, event_manager | 中 — event_manager 是 feeder 特有的,需拆分或抽象 | +| `handler/point.rs` | 693 | pool, connection_manager, event_manager | 中 — 同上 | +| `handler/equipment.rs` | 335 | pool, event_manager | 中 — 同上 | +| `handler/tag.rs` | 126 | pool | 低 — 纯数据库操作,可直接迁移 | +| `handler/page.rs` | 169 | pool | 低 — 纯数据库操作,可直接迁移 | + +### 不迁移的 Handler + +| 文件 | 行数 | 原因 | +|------|------|------| +| `handler/control.rs` | 750 | 完全是投煤器/布料机业务逻辑(unit CRUD、自动控制启停、故障确认) | + +### 建议实施步骤 + +1. **先迁 tag.rs 和 page.rs**:只依赖 pool,无 event_manager 依赖,最简单 + - Core 的 handler 签名使用 `State` 或提取 pool 的 extractor + - Feeder 和 ops 的 router 都注册这些路由 +2. **定义平台事件发送 trait**:在 core 中定义 `PlatformEventSink` trait,feeder 的 `EventManager` 实现它 + - 这样 source/point/equipment handler 可以依赖 trait 而非具体的 `EventManager` +3. **迁移 source.rs、equipment.rs、point.rs**:改为依赖 `PlatformContext` + `PlatformEventSink` +4. **Ops 注册平台路由**:ops router 中注册 source/point/equipment/tag/page 路由 + +### 关键设计决策 + +Handler 迁移后,两个 app 的 router 有两种注册方式: + +- **方案 A**:Core 提供 `pub fn platform_routes() -> Router`,每个 app merge 进来 +- **方案 B**:Core 只导出 handler 函数,每个 app 自己 `.route()` 注册 + +推荐方案 B:更灵活,允许 app 按需选择注册哪些路由。 + +--- + +## 改进 2:事件命名空间(中优先级) + +### 目标 + +给所有事件类型加上命名空间前缀(spec §6 要求),使不同业务的事件在同一张 event 表中可按前缀区分。 + +### 当前状态 + +Feeder 的 `event.rs` 中的事件类型已使用了点分隔命名(如 `source.created`、`unit.auto_control_started`),但缺少顶层业务前缀。 + +### 目标命名规范 + +| 前缀 | 含义 | 示例 | +|------|------|------| +| `platform.*` | 平台级通用事件 | `platform.source.created`, `platform.point.batch_created` | +| `feeder.*` | 投煤器布料机业务事件 | `feeder.unit.auto_control_started`, `feeder.unit.fault_locked` | +| `ops.*` | 运转系统业务事件 | `ops.unit.started`, `ops.interlock.triggered` | + +### 建议实施步骤 + +1. 梳理 `app_feeder_distributor/src/event.rs` 中 `persist_event_if_needed` 的所有 event_type 字符串 +2. 将平台通用事件(source.*, point.batch_*)改为 `platform.` 前缀 +3. 将业务事件(unit.*, equipment.start/stop_command_sent)改为 `feeder.` 前缀 +4. 前端 JS 中若有事件类型过滤逻辑,同步更新 +5. 数据库中已有的历史事件不做回填(向前兼容) + +--- + +## 改进 3:Ops 注册平台 Handler(中优先级) + +### 目标 + +让 ops 应用能提供与 feeder 相同的平台配置能力(数据源、点位、设备、标签、页面管理)。 + +### 前置条件 + +- 改进 1(平台 handler 迁入 core)完成 +- PlatformContext 已包含 pool(**已满足**) + +### 当前 Ops Router + +``` +/api/health — health check +/api/logs — 日志查询(已从 core 注册) +/api/logs/stream — 日志 SSE 推送(已从 core 注册) +/api/docs/api-md — API 文档 +/api/docs/readme-md — README +/ui — 静态页面(web/ops fallback web/core) +``` + +### 目标 Ops Router(改进 1 完成后) + +``` +/api/health +/api/logs, /api/logs/stream +/api/docs/api-md, /api/docs/readme-md +/api/source, /api/source/{source_id}, ... — 新增 +/api/point, /api/point/{point_id}, ... — 新增 +/api/equipment, /api/equipment/{id}, ... — 新增 +/api/tag, /api/tag/{tag_id}, ... — 新增 +/api/page, /api/page/{page_id}, ... — 新增 +/ws/public — 新增(WebSocket 推送) +/ui +``` + +### 注意事项 + +- Ops 不注册 `/api/unit` 和 `/api/control` 路由(那是 feeder 业务) +- Ops 的 event_manager 需要独立实现(或先不实现事件广播,只做 CRUD) +- Ops 的 WebSocket handler 可以复用 core 的 WsMessage 类型 + +--- + +## 改进 4:Ops 业务逻辑(低优先级) + +### 目标 + +为运转系统应用添加独立的业务能力。 + +### 前置条件 + +- 运转系统业务需求明确 +- 改进 1-3 完成 + +### 待实现模块 + +根据 spec §5.2,`app_operation_system` 需要: + +- 运转系统控制逻辑(`control/engine.rs`) +- 运转系统业务接口(`handler/control.rs`) +- 运转系统业务页面(`web/ops/` 扩充) +- 业务事件定义(`event.rs`,使用 `ops.*` 前缀) +- 业务运行时状态(`OperationRuntimeStore`) + +### Ops 业务事件示例(来自 spec §6.3) + +- `ops.unit.started` +- `ops.unit.stopped` +- `ops.phase.changed` +- `ops.interlock.triggered` +- `ops.interlock.released` + +### 当前不做的事 + +- 不把两套业务的控制引擎抽象为通用状态机(spec §12.2 明确约束) +- 不做业务插件化(spec §3 方案 C 已排除) + +--- + +## 建议执行顺序 + +``` +改进 1(handler 迁移) + ├── 1a: 迁移 tag.rs + page.rs(纯 pool 依赖) + ├── 1b: 定义 PlatformEventSink trait + └── 1c: 迁移 source.rs + equipment.rs + point.rs +改进 2(事件命名空间)── 可与改进 1 并行 +改进 3(ops 注册平台路由)── 依赖改进 1 完成 +改进 4(ops 业务逻辑)── 依赖改进 3 + 业务需求 +``` + +改进 1a 和改进 2 可以并行推进,是当前最优先的两个切入点。