Files
awoooi/docs/superpowers/specs/2026-04-08-sprint5-component-extraction.md
OG T 83e9d3eef8 docs(specs): Sprint 5 四份技術文檔 — Tab 規格/路由對照/元件抽取/API 變更
1. Tab 結構規格書: 每個新頁面的 Tab 配置、區塊佈局、元件複用方式
2. 路由對照表: 26 個舊 URL → 新位置的精確映射 + redirect 實作方式
3. 元件抽取計畫: 17 個頁面抽取為 Panel 元件的步驟和目錄結構
4. API 變更規格: DashboardResponse +3 欄位 + SSE +1 事件 (不新增 API)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-08 16:03:58 +08:00

4.8 KiB

Sprint 5 — 元件抽取計畫

哪些頁面需要抽取為獨立元件,以便在 Tab 容器中複用


抽取原則

  1. 只移動,不修改邏輯 — 確保功能零損失
  2. 保留原始 page.tsx 做 redirect — 舊連結不失效
  3. 元件接收 props 而非自行 fetch — 父層 (Tab 容器) 負責資料載入
  4. i18n 不變 — 繼續使用原有的 useTranslations() namespace

抽取清單

高優先 (AI 指令中心需要)

# 原始頁面 抽取為 放置位置 行數 用於
1 /alerts/page.tsx AlertsPanel.tsx components/panels/ 183 AI 中心 Tab 2 左側
2 /reports/page.tsx DispositionPanel.tsx components/panels/ 317 AI 中心 Tab 4

中優先 (其他整合頁面需要)

# 原始頁面 抽取為 放置位置 行數 用於
3 /monitoring/page.tsx MonitoringPanel.tsx components/panels/ 269 可觀測性 Tab 1
4 /apm/page.tsx APMPanel.tsx components/panels/ 128 可觀測性 Tab 2
5 /errors/page.tsx ErrorsPanel.tsx components/panels/ 164 可觀測性 Tab 3
6 /apps/page.tsx AppsPanel.tsx components/panels/ 103 可觀測性 Tab 4
7 /services/page.tsx ServicesPanel.tsx components/panels/ 120 可觀測性 Tab 5
8 /auto-repair/page.tsx AutoRepairPanel.tsx components/panels/ 460 自動化 Tab 1
9 /neural-command/page.tsx NeuralCommandPanel.tsx components/panels/ 209 自動化 Tab 2
10 /drift/page.tsx DriftPanel.tsx components/panels/ 324 自動化 Tab 3
11 /deployments/page.tsx DeploymentsPanel.tsx components/panels/ 113 營運 Tab 1
12 /tickets/page.tsx TicketsPanel.tsx components/panels/ 120 營運 Tab 2
13 /cost/page.tsx CostPanel.tsx components/panels/ 95 營運 Tab 3
14 /action-logs/page.tsx ActionLogsPanel.tsx components/panels/ 551 營運 Tab 4
15 /billing/page.tsx BillingPanel.tsx components/panels/ 113 營運 Tab 5
16 /security/page.tsx SecurityPanel.tsx components/panels/ 137 安全合規 Tab 1
17 /compliance/page.tsx CompliancePanel.tsx components/panels/ 124 安全合規 Tab 2

抽取步驟 (以 AlertsPanel 為例)

Step 1: 建立 Panel 元件

// apps/web/src/components/panels/AlertsPanel.tsx

'use client'

// 從原始 /alerts/page.tsx 移入完整內容
// 唯一差異: 移除 AppLayout wrapper (由 Tab 容器提供)

import { useTranslations } from 'next-intl'
// ... 原始 import 保留 ...

// 移除 export default function AlertsPage({ params })
// 改為:
export function AlertsPanel() {
  const t = useTranslations('alerts')
  
  // ... 原始邏輯完全不動 ...
  
  return (
    // 移除 <AppLayout> wrapper
    // 只保留內部內容
    <div className="space-y-4">
      {/* 原始告警列表內容 */}
    </div>
  )
}

Step 2: 原始頁面改為 redirect

// apps/web/src/app/[locale]/alerts/page.tsx
import { redirect } from 'next/navigation'

export default function AlertsPage() {
  redirect('/?tab=alerts')
}

Step 3: 在 Tab 容器中使用

// apps/web/src/app/[locale]/page.tsx (AI 指令中心)
import { lazy, Suspense } from 'react'

const AlertsPanel = lazy(() => import('@/components/panels/AlertsPanel').then(m => ({ default: m.AlertsPanel })))

// Tab 2 內容:
<Suspense fallback={<Skeleton />}>
  <AlertsPanel />
</Suspense>

新建目錄結構

apps/web/src/components/panels/
├── index.ts                    # 匯出所有 Panel
├── AlertsPanel.tsx             # 從 /alerts 抽取
├── DispositionPanel.tsx        # 從 /reports 抽取
├── MonitoringPanel.tsx         # 從 /monitoring 抽取
├── APMPanel.tsx                # 從 /apm 抽取
├── ErrorsPanel.tsx             # 從 /errors 抽取
├── AppsPanel.tsx               # 從 /apps 抽取
├── ServicesPanel.tsx           # 從 /services 抽取
├── AutoRepairPanel.tsx         # 從 /auto-repair 抽取
├── NeuralCommandPanel.tsx      # 從 /neural-command 抽取
├── DriftPanel.tsx              # 從 /drift 抽取
├── DeploymentsPanel.tsx        # 從 /deployments 抽取
├── TicketsPanel.tsx            # 從 /tickets 抽取
├── CostPanel.tsx               # 從 /cost 抽取
├── ActionLogsPanel.tsx         # 從 /action-logs 抽取
├── BillingPanel.tsx            # 從 /billing 抽取
├── SecurityPanel.tsx           # 從 /security 抽取
└── CompliancePanel.tsx         # 從 /compliance 抽取

共 17 個 Panel 元件