docs: add refactor overview documents

This commit is contained in:
Misaka
2026-03-21 09:07:13 +08:00
parent 7b57545127
commit 08bd2cb7d5
2 changed files with 465 additions and 0 deletions

View File

@@ -0,0 +1,247 @@
# useCleaner 重构说明
本文档记录 `src/renderer/src/hooks/useCleaner.ts` 的第一阶段重构工作。目标不是一次性把整个 Cleaner 页面完全组件化,而是优先拆出共享类型、纯函数和 IPC 编排逻辑,让 `useCleaner` 从“大而全逻辑容器”逐步收敛为“组合层”。
## 1. 重构背景
重构前,`useCleaner.ts` 同时负责:
- 页面初始化
- 权限判断
- sessionStorage 持久化
- 校验请求
- 结果筛选
- 勾选状态处理
- 删除计划构建
- 保存物料变更
- Cleaner 执行编排
- 导出编排
- 弹窗确认
- 报告状态维护
这导致它虽然名义上是一个 hook但实际上已经接近一个“前端页面服务总线”。
## 2. 重构目标
本次重构目标是:
- 提取共享类型,消除重复定义
- 提取纯函数,隔离无副作用逻辑
- 提取 IPC / 异步编排,隔离对 `window.electron` 的直接调用
- 保持 `useCleaner()` 返回值和 `CleanerPage.tsx` 使用方式不变
## 3. 重构后结构
```mermaid
graph TD
Page[CleanerPage.tsx]
Hook[useCleaner.ts]
subgraph CleanerHookModules[Cleaner Hook Modules]
Types[hooks/cleaner/types.ts]
Helpers[hooks/cleaner/helpers.ts]
Api[hooks/cleaner/api.ts]
end
subgraph ExternalDeps[External Dependencies]
Electron[window.electron]
Store[useAppStore / Toast]
Dialog[ConfirmDialog]
end
Page --> Hook
Hook --> Types
Hook --> Helpers
Hook --> Api
Hook --> Store
Hook --> Dialog
Api --> Electron
```
## 4. 本次拆分内容
### 4.1 共享类型
新增:
- `src/renderer/src/hooks/cleaner/types.ts`
统一收敛了以下类型:
- `ValidationRequest`
- `ValidationResult`
- `ValidationStats`
- `ValidationResponsePayload`
- `CleanerProgress`
- `CleanerReportData`
- `CleanerInitializationResult`
- `CleanerConfigResult`
这一步解决了原来多个文件重复定义同类类型的问题,比如:
- `useCleaner.ts`
- `useValidation.ts`
- `ExecutionReportDialog.tsx`
### 4.2 纯函数与数据构造
新增:
- `src/renderer/src/hooks/cleaner/helpers.ts`
提取出的纯函数包括:
- `getStoredBoolean()`
- `getStoredValidationMode()`
- `filterValidationResults()`
- `buildDeletionPlan()`
- `buildExportItems()`
这些逻辑之前都散落在 `useCleaner.ts``useMemo` 或事件处理函数里,现在可以单独测试。
### 4.3 IPC 与异步编排
新增:
- `src/renderer/src/hooks/cleaner/api.ts`
提取出的异步编排包括:
- `initializeCleanerPage()`
- `loadCleanerConfig()`
- `runValidationRequest()`
- `saveDeletionPlan()`
- `reloadManagers()`
- `runCleanerExecution()`
- `exportCleanerResults()`
这样做之后,`useCleaner.ts` 不再需要在每个 handler 里直接拼接 `window.electron.xxx` 调用细节。
## 5. useCleaner 的角色变化
```mermaid
flowchart LR
subgraph Before[重构前]
A[useCleaner.ts]
A --> A1[本地状态]
A --> A2[筛选逻辑]
A --> A3[删除计划构建]
A --> A4[执行清理请求]
A --> A5[导出请求]
A --> A6[初始化请求]
A --> A7[共享类型定义]
end
subgraph After[重构后]
B[useCleaner.ts]
B --> B1[组合状态]
B --> B2[调用 helpers]
B --> B3[调用 api]
C[helpers.ts]
D[api.ts]
E[types.ts]
B --> C
B --> D
B --> E
end
```
重构后,`useCleaner.ts` 更接近“组合层”:
- 管理 React state
- 串联用户交互流程
- 调用 helpers 和 api
- 将最终能力暴露给页面
## 6. 受影响的文件
### 6.1 主体修改
- `src/renderer/src/hooks/useCleaner.ts`
- `src/renderer/src/hooks/useValidation.ts`
- `src/renderer/src/components/ExecutionReportDialog.tsx`
### 6.2 新增模块
- `src/renderer/src/hooks/cleaner/types.ts`
- `src/renderer/src/hooks/cleaner/helpers.ts`
- `src/renderer/src/hooks/cleaner/api.ts`
### 6.3 新增测试
- `tests/unit/cleaner-helpers.test.ts`
## 7. 具体收益
### 7.1 类型一致性提升
之前 `ValidationResult``CleanerProgress` 在多个文件重复定义,修改字段时容易遗漏。
现在统一从 `hooks/cleaner/types.ts` 引用,降低了类型漂移风险。
### 7.2 可测试性提升
原先删除计划构建、筛选和导出映射逻辑只能通过 hook 间接覆盖。
现在这些逻辑已经被抽成纯函数,可以直接做单测。
### 7.3 Hook 复杂度下降
虽然 `useCleaner.ts` 还没有变成一个很小的文件,但其中的“细节密度”已经明显下降:
- 数据变换逻辑外提
- API 编排逻辑外提
- 重复类型移除
### 7.4 为下一步组件拆分做准备
后续如果要拆 `CleanerPage.tsx`
- 左侧筛选区
- 表格工具栏
- 底部执行区
这些组件就可以直接消费已经整理好的 hook 能力,而不是继续把逻辑往页面里塞。
## 8. 验证方式
本次重构后执行了以下验证:
- `npm run typecheck:node`
- `tests/unit/cleaner-helpers.test.ts`
- `tests/unit/cleaner.test.ts`
## 9. 新增测试覆盖点
`tests/unit/cleaner-helpers.test.ts` 覆盖了:
- 非管理员筛选逻辑
- 删除计划构建逻辑
- 导出数据构建逻辑
## 10. 仍然保留在 useCleaner 中的内容
为了控制改动风险,这次没有继续下沉以下能力:
- `ConfirmDialog` 的 Promise 封装
- 编辑状态 `editingCell / editValue`
- `isRunning / isExecuting / isReportDialogOpen` 等 UI 状态
- 页面层直接依赖的完整返回对象
这些能力仍然保留在 `useCleaner.ts`,因为它们和当前页面交互绑定较深。
## 11. 下一步建议
基于目前的结构,建议下一阶段继续做:
1.`CleanerPage.tsx` 为“左侧筛选区”和“右侧结果与执行区”两个子组件。
2.`showConfirmDialog()` 封装为独立 hook例如 `useConfirmDialogController()`
3. 将 inline edit 相关逻辑提取到更专门的 manager-assignment controller。
4. 视情况把 Cleaner 相关状态进一步收敛到专门 store 或 domain hook 中。
## 12. 总结
这次 `useCleaner` 重构的核心价值,不是“让文件立刻变得很小”,而是先把最容易复用、最适合测试、最不应继续堆在 hook 里的部分拆出来。
它为接下来的页面组件拆分提供了一个更稳的基础,也让 Cleaner 模块开始从“页面驱动逻辑”向“模块化前端能力”转变。

View File

@@ -0,0 +1,218 @@
# validation-handler 重构说明
本文档记录 `src/main/ipc/validation-handler.ts` 的第一阶段重构工作,目标是把“超大 IPC Handler”拆回到更清晰的职责边界中同时保持对外 IPC 协议和业务行为不变。
## 1. 重构背景
重构前,`validation-handler.ts` 同时承担了以下职责:
- IPC 通道注册
- 跨页面共享 `Production ID` 状态
- 数据库连接创建与释放
- MySQL / SQL Server 方言分支
- 输入识别与订单号解析
- 物料校验结果组装
- Cleaner 执行前数据准备
- 物料查询与富化
这种结构的主要问题是:
- 文件过大,理解成本高
- 数据库和业务规则直接堆叠在 IPC 层
- 复用困难,后续其他模块无法直接复用这些逻辑
- 单元测试难以细粒度编写
## 2. 重构目标
本次重构聚焦在“职责下沉、行为不变”:
- 保留原有 IPC channel 和返回结构
- 将共享状态、数据库工厂、输入解析、验证业务流程拆出
-`validation-handler.ts` 回归为薄 IPC 壳层
- 为后续继续拆 `cleaner-handler`、前端校验流程提供复用基础
## 3. 重构后结构
```mermaid
graph TD
Renderer[Renderer / Preload]
Handler[validation-handler.ts]
subgraph ValidationServices[Validation Services]
Store[shared-production-ids-store.ts]
DbFactory[validation-database.ts]
InputSvc[production-input-service.ts]
AppSvc[validation-application-service.ts]
end
subgraph ExistingServices[Existing Services]
MaterialsDAO[MaterialsToBeDeletedDAO]
PlanDAO[DiscreteMaterialPlanDAO]
Session[SessionManager]
end
Renderer --> Handler
Handler --> Session
Handler --> Store
Handler --> AppSvc
Handler --> MaterialsDAO
AppSvc --> Store
AppSvc --> DbFactory
AppSvc --> InputSvc
AppSvc --> MaterialsDAO
AppSvc --> PlanDAO
```
## 4. 新增与调整的文件
### 4.1 IPC 薄壳
- `src/main/ipc/validation-handler.ts`
职责收敛为:
- 注册 IPC handler
-`SessionManager` 读取当前用户
- 调用应用服务
- 对简单 DAO 操作做最轻量转发
### 4.2 共享状态模块
- `src/main/services/validation/shared-production-ids-store.ts`
职责:
- 管理按 `senderId` 隔离的共享 `Production IDs`
- 提供 `set/get/clear`
价值:
- 将原本散落在 handler 文件顶部的状态提升为独立服务
- 后续如果要迁移到更持久的 session store只需替换这一层
### 4.3 数据库创建与表名适配
- `src/main/services/validation/validation-database.ts`
职责:
- 创建用于 validation 相关流程的数据库服务
- 提供 `getValidationTableName()` 做表名方言转换
价值:
- 收敛 MySQL / SQL Server 的连接逻辑
- 避免 IPC 文件里反复出现数据库构造代码
### 4.4 输入解析服务
- `src/main/services/validation/production-input-service.ts`
职责:
- 读取 Production ID 文件
- 识别输入是 `production_id``order_number` 还是 `unknown`
- 从输入解析出订单号列表
价值:
- 把“输入解析规则”变成可复用、可测试的纯业务模块
### 4.5 应用服务
- `src/main/services/validation/validation-application-service.ts`
职责:
- 校验流程编排
- Cleaner 数据准备
- 物料按负责人查询 / 全量查询的富化逻辑
- 统一管理数据库生命周期
价值:
- 形成明确的 application service 层
- 让后续业务扩展不再从 IPC 文件开刀
## 5. 重构前后职责对比
```mermaid
flowchart LR
subgraph Before[重构前]
A1[validation-handler.ts]
A1 --> A2[IPC 注册]
A1 --> A3[共享状态]
A1 --> A4[数据库连接]
A1 --> A5[输入解析]
A1 --> A6[校验编排]
A1 --> A7[物料富化]
A1 --> A8[Cleaner 数据准备]
end
subgraph After[重构后]
B1[validation-handler.ts]
B2[shared-production-ids-store.ts]
B3[validation-database.ts]
B4[production-input-service.ts]
B5[validation-application-service.ts]
B1 --> B5
B1 --> B2
B5 --> B3
B5 --> B4
end
```
## 6. 本次保留不变的部分
为了控制风险,这次没有修改以下内容:
- IPC channel 名称
- Preload / Renderer 调用方式
- 物料匹配规则
- Cleaner 数据准备规则
- DAO 层的既有 SQL 结构
也就是说,这次更像是一次“结构性搬迁”,不是业务规则改造。
## 7. 验证方式
本次重构完成后,做了以下验证:
- `npm run typecheck:node`
- `tests/unit/shared-production-ids-store.test.ts`
- `tests/unit/production-input-service.test.ts`
- 既有 `tests/unit/ipc-index.test.ts`
## 8. 新增测试
新增测试文件:
- `tests/unit/shared-production-ids-store.test.ts`
- `tests/unit/production-input-service.test.ts`
覆盖内容:
- sender 隔离存储
- 去重行为
- 清空逻辑
- 输入类型识别
## 9. 收益总结
这次重构带来的直接收益:
- `validation-handler.ts` 不再承担过多业务职责
- validation 相关逻辑形成了可复用服务层
- 输入解析与共享状态有了独立测试入口
- 后续继续拆 `cleaner-handler` 时,可以直接复用订单号解析和 cleaner 数据准备逻辑
## 10. 后续建议
建议在这个基础上继续推进:
1.`validation-application-service.ts` 中的 SQL Server / MySQL 分支继续下沉到 repository 或 dialect adapter。
2. 逐步给 `getCleanerData()``getMaterialsByManager()` 这类编排逻辑补更多单测。
3. 把和 validation 强耦合的 renderer 逻辑改成显式依赖 application contract而不是隐式依赖 payload shape。