Files
BIPMaterialManager/docs/use-cleaner-refactor-overview.md
2026-03-21 09:34:44 +08:00

247 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 模块开始从“页面驱动逻辑”向“模块化前端能力”转变。