AI开发图书管理系统,组件化到底该怎么拆

OK,OK,大家好,欢迎大家来到大鹏 AI 教育,我是张大鹏。

这篇继续做 RuyiLibraryAdmin 图书管理系统。

前面我们已经做了模块化、主题系统和 CSS Modules。代码不再全部堆在 App.tsx,样式也不再全部堆在 styles.css

但做到这里,还有一个问题必须继续解决:页面内部还是会越来越大。

比如仪表盘里有顶部概览、统计卡片、借阅趋势图、分类柱状图、近期借阅表。

图书管理页里有页面标题、搜索筛选、操作按钮、表格字段、状态标签。

VIP 升级页里有头图、价值点、套餐卡片、交付路径。

如果这些内容都堆在一个页面文件里,文件还是会慢慢变成新的"大杂烩"。

所以这一篇,我们做组件化开发。

先看现在的页面效果

这是当前的仪表盘。

从 UI 上看,它是一张完整页面。

但从代码上看,它不应该是一个完整大组件。

它至少应该拆成:

  • 顶部运营概览
  • 指标卡片组
  • 借阅趋势图
  • 热门分类图
  • 近期借阅表

这样做的目的不是为了目录好看,而是为了让每一块 UI 都有自己的职责。

后续我要改趋势图,就去改趋势图组件。

我要改指标卡片,就去改指标组件。

我要改近期借阅表,就去改借阅表组件。

这就是组件化的价值。

AI 开发为什么更需要组件化?

AI 写 React 页面很快。

你让它写一个仪表盘,它可以一次生成几百行 JSX。

刚开始很爽。

但问题是,AI 后面继续改这个文件时,也会面对几百行上下文。

它可能为了改一个表格字段,顺手影响图表。

也可能为了改一个按钮,把页面布局也改掉。

这不是 AI 故意乱改,而是边界不清楚。

组件化就是给 AI 画边界。

比如以后我可以这样下指令:

text 复制代码
只修改 src/features/books/components/BooksTable.tsx。
不要修改 BooksPage.tsx。
不要修改 shared/ui/DataTable。
修改后运行 pnpm build。

这个任务就很清楚。

AI 不需要理解整个系统,只需要改一个小组件。

我选择的方案:shared 基础组件 + feature 业务组件

这次我没有把所有组件都扔到 components/ 目录。

那样看起来简单,但项目一大就会乱。

我采用的是双层结构:

text 复制代码
shared 基础组件 + feature 业务组件

shared/ui 放跨模块复用的基础组件。

比如:

text 复制代码
src/shared/ui/DataTable.tsx
src/shared/ui/ListPage.tsx
src/shared/ui/PanelTitle.tsx
src/shared/ui/StatCard.tsx
src/shared/ui/Status.tsx

这些组件不属于某一个业务。

图书、借阅、读者、分类都会用表格。

很多页面都会用标题、面板、状态标签。

所以它们适合放到 shared

业务组件则放在自己的 feature 下面。

比如图书管理自己的表格:

text 复制代码
src/features/books/components/BooksTable.tsx

借阅管理自己的表格:

text 复制代码
src/features/loans/components/LoansTable.tsx

这样一看目录,就知道组件属于哪里。

仪表盘怎么拆?

重构前,DashboardPage.tsx 里同时有统计计算、图表配置、表格渲染和页面布局。

这次我把它拆成了 5 个组件:

text 复制代码
src/features/dashboard/components/
  DashboardHero.tsx
  MetricGrid.tsx
  LoanTrendChart.tsx
  CategoryChart.tsx
  RecentLoansTable.tsx

现在 DashboardPage.tsx 只负责组装:

tsx 复制代码
export function DashboardPage() {
  return (
    <div className={styles.stack}>
      <DashboardHero />
      <MetricGrid />
      <div className={styles.gridTwo}>
        <LoanTrendChart />
        <CategoryChart />
      </div>
      <RecentLoansTable />
    </div>
  );
}

这就是我想要的页面文件。

它读起来像页面大纲,而不是一坨实现细节。

以后要讲课,也更容易讲。

先讲页面由哪几块组成,再进入每个组件看细节。

图书、借阅、读者、分类怎么拆?

这几个页面都是后台系统最常见的列表页。

它们的页面结构很像:

  • 页面标题
  • 页面说明
  • 搜索筛选
  • 新增按钮
  • 数据表格

所以页面壳子继续复用 ListPage

但表格字段和数据映射属于业务模块,不能一直写在页面里。

于是我拆成:

text 复制代码
features/books/components/BooksTable.tsx
features/loans/components/LoansTable.tsx
features/readers/components/ReadersTable.tsx
features/categories/components/CategoriesTable.tsx

这样 BooksPage.tsx 就变得非常薄:

tsx 复制代码
export function BooksPage() {
  return (
    <ListPage title="图书馆藏" desc="管理书名、作者、ISBN、分类、库存和馆藏位置。" action="新增图书">
      <BooksTable />
    </ListPage>
  );
}

这个结构很适合 AI 开发。

以后要加图书状态颜色、库存告警、ISBN 链接,基本都进 BooksTable

页面不需要跟着变。

组件拆到什么程度才合适?

组件化不是拆得越碎越好。

我一般按三个标准判断。

第一,这块 UI 有没有独立业务含义。

比如 LoanTrendChart 有明确含义,值得拆。

第二,这块 UI 会不会单独修改。

比如 BooksTable 后续肯定会加字段、状态、操作,值得拆。

第三,这块 UI 会不会复用。

比如 DataTable 多个页面都用,就应该放到 shared/ui

反过来,如果只是两三行普通标签,不需要为了拆而拆。

过度组件化会让目录变复杂,也会让新手找不到代码。

组件化的目标不是"文件变多",而是"职责变清楚"。

这次拆完后的结构

这次组件化之后,核心目录变成这样:

text 复制代码
src/features/
  dashboard/
    DashboardPage.tsx
    components/
      DashboardHero.tsx
      MetricGrid.tsx
      LoanTrendChart.tsx
      CategoryChart.tsx
      RecentLoansTable.tsx
  books/
    BooksPage.tsx
    components/
      BooksTable.tsx
  loans/
    LoansPage.tsx
    components/
      LoansTable.tsx
  readers/
    ReadersPage.tsx
    components/
      ReadersTable.tsx
  categories/
    CategoriesPage.tsx
    components/
      CategoriesTable.tsx
  internal/
    AboutPage.tsx
    vipContent.ts
    components/
      VipHero.tsx
      VipFeatureGrid.tsx
      VipPackageGrid.tsx
      VipDeliveryTimeline.tsx

可以看到,每个页面都更薄了。

页面文件负责组装。

业务组件负责具体展示。

共享组件负责基础 UI。

这就是一个后台项目比较舒服的结构。

登录页也要看,但这次不继续拆

登录页现在也已经独立成页面模块,并有自己的 CSS Module。

这次的验证

组件化重构后,我会继续跑:

bash 复制代码
pnpm build
pnpm exec playwright test tests/e2e/theme.spec.ts
pnpm screenshots:003

这三步分别验证:

  • TypeScript 和构建没问题
  • 主题切换没被组件拆分破坏
  • 关键页面还能稳定截图

纯 AI 开发一定要养成这个习惯。

不是拆完觉得"应该没问题",而是用构建和截图证明没问题。

下一步

下一步可以继续在组件化结构上加真实功能。

我会优先做:

第一,BooksTable 增加操作列。

第二,新增 BookFormDialog,实现新增图书弹窗。

第三,LoansTable 增加还书和续借操作。

第四,把这些功能继续写成图文博客。

到这里,项目已经有了一个比较清晰的演进路线:

先页面跑通。

再模块化。

再主题和 CSS 模块化。

再组件化。

之后再加真实业务功能。

这样做纯 AI 开发,节奏会稳很多。

AI 负责快速实现,人负责拆边界、定规范、做验收。