refactor: split useProductActions into product-actions sub-hooks #1095

Merged
xiaoxia merged 1 commits from refactor/use-product-actions into develop 2026-07-28 16:18:44 +08:00
Owner

变更说明

将 useProductActions 拆分为多个子 Hook,主文件从 187 行精简到 96 行(-49%)。

拆分结构

products/hooks/
├── useProductActions.ts          (96行, 主入口)
└── product-actions/
    ├── useBatchDownload.ts       (批量下载 + 轮询)
    ├── useBatchDelete.ts         (批量删除 + query 失效)
    └── useProductMutations.ts    (单个删除 + 复核状态变更 mutation)

三阶段拆分

  • Phase 1: 类型常量(已在 products/types/ 中,无需改动)
  • Phase 2: 抽离业务 Hook — useBatchDownload / useBatchDelete / useProductMutations
  • Phase 3: 主文件瘦身,保留单文件操作逻辑

兼容性

  • 主入口 useProductActions.ts 路径不变,导出接口完全兼容
  • 所有子 Hook 均在 product-actions/ 目录内,外部无需感知
## 变更说明 将 useProductActions 拆分为多个子 Hook,主文件从 187 行精简到 96 行(-49%)。 ## 拆分结构 ``` products/hooks/ ├── useProductActions.ts (96行, 主入口) └── product-actions/ ├── useBatchDownload.ts (批量下载 + 轮询) ├── useBatchDelete.ts (批量删除 + query 失效) └── useProductMutations.ts (单个删除 + 复核状态变更 mutation) ``` ## 三阶段拆分 - Phase 1: 类型常量(已在 products/types/ 中,无需改动) - Phase 2: 抽离业务 Hook — useBatchDownload / useBatchDelete / useProductMutations - Phase 3: 主文件瘦身,保留单文件操作逻辑 ## 兼容性 - 主入口 useProductActions.ts 路径不变,导出接口完全兼容 - 所有子 Hook 均在 product-actions/ 目录内,外部无需感知
xiaoxia added 1 commit 2026-07-28 16:06:11 +08:00
refactor: split useProductActions into product-actions sub-hooks
CI/CD Pipeline / Staging E2E Tests (pull_request) Blocked by required conditions
CI/CD Pipeline / Staging API Integration Tests (pull_request) Blocked by required conditions
CI/CD Pipeline / Deploy Production (pull_request) Blocked by required conditions
CI/CD Pipeline / Production Browser E2E (pull_request) Blocked by required conditions
CI/CD Pipeline / ACR Image Cleanup (pull_request) Blocked by required conditions
CI/CD Pipeline / Canary Release to Production (pull_request) Blocked by required conditions
Preview Cleanup / Cleanup Preview Environment (pull_request) Waiting to run
ACR Cleanup / ACR Image Cleanup (pull_request_target) Has been cancelled
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Unit Tests (pull_request) Waiting to run
CI/CD Pipeline / Frontend Unit Tests (pull_request) Waiting to run
CI/CD Pipeline / Build Production API Image (pull_request) Waiting to run
CI/CD Pipeline / Build Production Web Image (pull_request) Waiting to run
CI/CD Pipeline / Build Production Worker Image (pull_request) Waiting to run
CI/CD Pipeline / CI Gate (pull_request) Blocked by required conditions
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m37s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m35s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 35s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 3m2s
CI/CD Pipeline / Integration Tests (pull_request) Waiting to run
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Waiting to run
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m50s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m35s
PR Automation / Auto Approve on CI Green (pull_request) Failing after 37s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 53s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m42s
AI Code Review / AI Code Review (pull_request) Failing after 2m18s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 46m4s
976c5b7215
Extract batch download, batch delete, and mutation logic into separate
hooks under product-actions/ directory. Main file reduces from 187 to 96 lines (-49%).

- useBatchDownload: bulk download with polling
- useBatchDelete: sequential batch delete with query invalidation
- useProductMutations: delete and review status mutations
xiaoxia force-pushed refactor/use-product-actions from fc8ffc94f1 to 976c5b7215 2026-07-28 16:06:11 +08:00 Compare
xiaoxia merged commit 3eb541ca39 into develop 2026-07-28 16:18:44 +08:00
auto-approve-bot reviewed 2026-07-28 16:50:12 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。

🚀 预览环境已部署

项目 详情
PR号 #1095
预览链接 https://pr-1095.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1095 | | 预览链接 | [https://pr-1095.preview.xiaoxiajianji.com](https://pr-1095.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:是
  • 阻塞级问题数量:2 个

📊 审查概览

  • 整体评价:需修改
  • 建议级问题数量:2 个

🔥 阻塞级问题(必须修复)

  1. [useBatchDownload.ts: 24-47] 组件卸载后状态更新导致内存泄漏

    • 问题类型:逻辑bug
    • 问题描述:poll 函数是一个递归异步调用,如果用户在轮询过程中离开当前页面(组件卸载),递归仍会继续执行。当最终调用 setBatchDownloading(false) 时,React 会抛出 "Can't perform a React state update on an unmounted component" 警告,且网络请求仍在浪费资源。
    • 修改建议:使用 useRef 跟踪组件的挂载状态,或在 useEffect 中进行清理。例如:
    const isMounted = useRef(true);
    useEffect(() => {
      return () => { isMounted.current = false; };
    }, []);
    // 在 poll 函数中调用 setState 前检查 if (!isMounted.current) return;
    
  2. [useBatchDelete.ts: 18-22] 串行执行导致严重的性能问题

    • 问题类型:性能问题
    • 问题描述:在 for 循环中使用 await 逐个等待删除请求完成。如果用户选中了较多项目(例如 50 个或更多),操作总耗时将是单个请求耗时的累加,导致界面长时间无响应,严重违背“批量操作”的高效初衷。
    • 修改建议:应使用 Promise.allPromise.allSettled 进行并发请求处理,以大幅提升操作速度。若担心并发过高,可使用分块并发(如 p-limit 库)。

💡 改进建议(不阻塞合并)

  1. [useBatchDelete.ts: 20-22] 错误处理过于静默

    • 具体内容:catch 块中完全忽略错误(// 忽略单个失败)。如果删除是因为权限不足或网络错误导致的,用户将无法得知具体原因。建议至少在控制台记录错误,或者在最终提示中明确告知用户有部分失败。
  2. [useBatchDelete.ts: 27] 部分成功时的提示不准确

    • 具体内容:无论是否全部成功,都显示 success 类型的 message。如果 successCount < ids.length,应该使用 warningerror 级别的提示,告知用户仅部分删除成功,避免误导。

良好实践

  • 代码重构结构清晰,将批量操作逻辑拆分到独立的 Hook 中,提高了可维护性。
  • useBatchDownload 中实现了轮询超时机制(maxAttempts),避免了无限轮询。
  • useBatchDownload 使用了 useCallback 并正确依赖了 selectedIdsclearSelection,保证了回调函数引用的稳定性(注意:selectedIds 是引用类型,需确保父组件传递时引用稳定,否则会导致频繁重渲染)。

🤖 由 AI 代码审查机器人自动生成 | 2026-07-28 08:51:29 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:2 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:2 个 ### 🔥 阻塞级问题(必须修复) 1. **[useBatchDownload.ts: 24-47] 组件卸载后状态更新导致内存泄漏** - 问题类型:逻辑bug - 问题描述:`poll` 函数是一个递归异步调用,如果用户在轮询过程中离开当前页面(组件卸载),递归仍会继续执行。当最终调用 `setBatchDownloading(false)` 时,React 会抛出 "Can't perform a React state update on an unmounted component" 警告,且网络请求仍在浪费资源。 - 修改建议:使用 `useRef` 跟踪组件的挂载状态,或在 `useEffect` 中进行清理。例如: ```typescript const isMounted = useRef(true); useEffect(() => { return () => { isMounted.current = false; }; }, []); // 在 poll 函数中调用 setState 前检查 if (!isMounted.current) return; ``` 2. **[useBatchDelete.ts: 18-22] 串行执行导致严重的性能问题** - 问题类型:性能问题 - 问题描述:在 `for` 循环中使用 `await` 逐个等待删除请求完成。如果用户选中了较多项目(例如 50 个或更多),操作总耗时将是单个请求耗时的累加,导致界面长时间无响应,严重违背“批量操作”的高效初衷。 - 修改建议:应使用 `Promise.all` 或 `Promise.allSettled` 进行并发请求处理,以大幅提升操作速度。若担心并发过高,可使用分块并发(如 `p-limit` 库)。 ### 💡 改进建议(不阻塞合并) 1. **[useBatchDelete.ts: 20-22] 错误处理过于静默** - 具体内容:`catch` 块中完全忽略错误(`// 忽略单个失败`)。如果删除是因为权限不足或网络错误导致的,用户将无法得知具体原因。建议至少在控制台记录错误,或者在最终提示中明确告知用户有部分失败。 2. **[useBatchDelete.ts: 27] 部分成功时的提示不准确** - 具体内容:无论是否全部成功,都显示 `success` 类型的 message。如果 `successCount < ids.length`,应该使用 `warning` 或 `error` 级别的提示,告知用户仅部分删除成功,避免误导。 ### ✅ 良好实践 - 代码重构结构清晰,将批量操作逻辑拆分到独立的 Hook 中,提高了可维护性。 - `useBatchDownload` 中实现了轮询超时机制(`maxAttempts`),避免了无限轮询。 - `useBatchDownload` 使用了 `useCallback` 并正确依赖了 `selectedIds` 和 `clearSelection`,保证了回调函数引用的稳定性(注意:`selectedIds` 是引用类型,需确保父组件传递时引用稳定,否则会导致频繁重渲染)。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-28 08:51:29 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
Sign in to join this conversation.