From 29932c6f54f57340ef5588803e2c7cc82faa784e Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Mon, 27 Jul 2026 00:43:26 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor(product-library):=20=E6=B7=B1?= =?UTF-8?q?=E5=8C=96=20ProductLibrary=20=E6=8B=86=E5=88=86=EF=BC=8C?= =?UTF-8?q?=E6=8A=BD=E7=A6=BB=E7=AD=9B=E9=80=89=E6=A0=8F/=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=93=8D=E4=BD=9C=E6=A0=8F/=E7=A9=BA=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 抽 ProductFilterBar 组件: 6 个筛选器 + 结果计数 - 抽 ProductBatchBar 组件: 批量操作栏(全选/下载/发布/删除) - 抽 ProductEmptyState 组件: 加载/404/错误/空状态四种展示 - 主文件 329→176 行 (-47%),仅保留 Hook 组装与整体布局 --- .../web/src/pages/products/ProductLibrary.tsx | 241 ++++-------------- .../products/components/ProductBatchBar.tsx | 85 ++++++ .../products/components/ProductEmptyState.tsx | 92 +++++++ .../products/components/ProductFilterBar.tsx | 119 +++++++++ 4 files changed, 340 insertions(+), 197 deletions(-) mode change 100755 => 100644 apps/web/src/pages/products/ProductLibrary.tsx create mode 100644 apps/web/src/pages/products/components/ProductBatchBar.tsx create mode 100644 apps/web/src/pages/products/components/ProductEmptyState.tsx create mode 100644 apps/web/src/pages/products/components/ProductFilterBar.tsx diff --git a/apps/web/src/pages/products/ProductLibrary.tsx b/apps/web/src/pages/products/ProductLibrary.tsx old mode 100755 new mode 100644 index af70965eb..d2c4ca906 --- a/apps/web/src/pages/products/ProductLibrary.tsx +++ b/apps/web/src/pages/products/ProductLibrary.tsx @@ -1,38 +1,29 @@ /** * 成片库页面 — V21 设计系统 * 卡片网格布局,支持视频播放/下载/分享、批量操作、筛选 - * 使用 useQuery 对接后端真实 API(api/products.ts) * - * 代码结构(三阶段重构后): - * - types.ts: 类型定义 - * - constants.ts: 常量配置 - * - utils/index.ts: 工具函数 - * - components/ProductCard.tsx: 产品卡片组件 - * - components/VideoPlayer.tsx: 视频播放器组件 - * - hooks/useProductList.ts: 列表查询与筛选 - * - hooks/useProductActions.ts: 单个/批量操作 + * 主组件仅保留 Hook 组装与整体布局 + * 列表查询 → hooks/useProductList + * 操作逻辑 → hooks/useProductActions + * 筛选栏 → components/ProductFilterBar + * 批量操作栏 → components/ProductBatchBar + * 空状态 → components/ProductEmptyState + * 产品卡片 → components/ProductCard + * 视频播放 → components/VideoPlayer */ import React, { useState } from "react" -import { Popconfirm, message } from "antd" -import { - SearchOutlined, - VideoCameraOutlined, - DownloadOutlined, - DeleteOutlined, - CheckOutlined, - CloudUploadOutlined, -} from "@ant-design/icons" -import { Button, Input, Select } from "@/components/ui" +import { VideoCameraOutlined, DownloadOutlined } from "@ant-design/icons" +import { Button } from "@/components/ui" import type { ProductItem } from "./types" import { ProductCard } from "./components/ProductCard" import { VideoPlayer } from "./components/VideoPlayer" +import { ProductFilterBar } from "./components/ProductFilterBar" +import { ProductBatchBar } from "./components/ProductBatchBar" +import { ProductEmptyState } from "./components/ProductEmptyState" import { useProductList } from "./hooks/useProductList" import { useProductActions } from "./hooks/useProductActions" import "./products.css" -/* ============================================================ - * 主组件 - * ============================================================ */ const ProductLibrary: React.FC = () => { const { products, @@ -83,58 +74,20 @@ const ProductLibrary: React.FC = () => { setPlayingProduct, }) + // ── Loading 状态 ── if (isLoading) { - return ( -
-
-
-

加载中...

-
-
- ) + return } // ── Error 状态 ── if (isError) { console.error("[ProductLibrary] 加载失败:", error) const errorMsg = error?.message || "加载失败" - // 404 视为空数据(API 尚未就绪或无数据) const is404 = errorMsg.includes("404") || errorMsg.includes("Not Found") if (is404) { - return ( -
-
-

- 成片库 -

-
-
-
🎬
-

暂无成片数据

-

- 完成视频生成后,成片将自动保存到这里 -

-
-
- ) + return } - return ( -
-
-
-

{errorMsg || "加载失败,请稍后重试"}

- -
-
- ) + return } return ( @@ -153,129 +106,35 @@ const ProductLibrary: React.FC = () => { {/* 批量操作栏 */} {batchMode && ( -
-
-
- {allSelected && } -
- - {allSelected ? "取消全选" : "全选"} - - 已选择 {selectedIds.size} 项 -
-
- - - - - - -
-
+ )} {/* 筛选栏 */} -
-
- } - value={searchText} - onChange={(e) => setSearchText(e.target.value)} - allowClear - style={{ width: 220 }} - /> - - - } + value={searchText} + onChange={(e) => onSearchChange(e.target.value)} + allowClear + style={{ width: 220 }} + /> + + +