From 0b04abf990c3172b08f00dcd760696da19c3c05a Mon Sep 17 00:00:00 2001 From: OG T Date: Wed, 1 Apr 2026 19:39:41 +0800 Subject: [PATCH] docs(plan): add AI Center v6 redesign implementation plan (13 tasks) --- .../plans/2026-04-01-ai-center-redesign.md | 1751 +++++++++++++++++ 1 file changed, 1751 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-01-ai-center-redesign.md diff --git a/docs/superpowers/plans/2026-04-01-ai-center-redesign.md b/docs/superpowers/plans/2026-04-01-ai-center-redesign.md new file mode 100644 index 000000000..2837bb3d6 --- /dev/null +++ b/docs/superpowers/plans/2026-04-01-ai-center-redesign.md @@ -0,0 +1,1751 @@ +# AI中心 UI 重設計 Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 將現有「戰情中心」(`/` 主頁) 重設計為「AI中心」,採用 Anthropic Warmth 米色系 + OpenClaw Blue 色彩,加入 7 節點流程管線、Q版龍蝦、NemoClaw 截圖風格動畫、完整 Sidebar 菜單。 + +**Architecture:** 全前端重構,後端 API 零修改。新增 3 個獨立元件 (FlowPipeline、NemoNodeAnimation、HostGrid),重構 5 個現有檔案 (page.tsx、sidebar.tsx、header.tsx、incident-card.tsx、openclaw-panel.tsx),廢棄 DualStateIncidentCard(授權邏輯移植後刪除)。 + +**Tech Stack:** Next.js 15、React、Tailwind CSS、next-intl、Zustand、pure CSS keyframes(禁止引入動畫庫) + +**Spec:** `docs/superpowers/specs/2026-04-01-ai-center-redesign-design.md` +**Mockup:** `.superpowers/brainstorm/31359-1775037143/content/final-v6.html` + +--- + +## File Map + +### 新增檔案 + +| 檔案 | 責任 | +|------|------| +| `apps/web/src/components/incident/flow-pipeline.tsx` | 7節點水平管線 + Q版龍蝦 SVG + lobster-bob 動畫 | +| `apps/web/src/components/ai/nemo-node-animation.tsx` | NemoClaw 截圖風格 72×72 SVG(白底圓形 + 藍球 + 輻射臂 + 虛線軌道)| +| `apps/web/src/components/infra/host-grid.tsx` | 2×2 主機緊湊 grid(hostname/IP/CPU/RAM/服務列)| + +### 修改檔案 + +| 檔案 | 修改內容 | +|------|---------| +| `apps/web/tailwind.config.ts` | 新增 Anthropic Warmth 色彩 token | +| `apps/web/src/components/layout/sidebar.tsx` | 4分區19項菜單、移除服務狀態、套用橘紅 active 樣式 | +| `apps/web/src/components/layout/header.tsx` | NemoClaw Logo SVG、P0 Banner、狀態 Pills、UTC+8 時間、Metrics Strip | +| `apps/web/src/components/incident/incident-card.tsx` | 加入 FlowPipeline、移植授權邏輯(handleApprove/handleReject/CSRF/超時重試)、套用新色彩圓角 | +| `apps/web/src/components/ai/openclaw-panel.tsx` | 替換為 NemoNodeAnimation + 思考流(Reasoning Stream)| +| `apps/web/src/app/[locale]/page.tsx` | 全面重構佈局為 3欄(Sidebar 移出、Feed flex:1、RightPanel flex:1)、移除 DataPincerPanel 容器 | +| `apps/web/messages/zh-TW.json` | `戰情中心`/`全局戰情室` → `AI中心` | +| `apps/web/messages/en.json` | `Command Center` → `AI Center` | + +### 廢棄檔案(Task 8 完成後刪除) + +| 檔案 | 原因 | +|------|------| +| `apps/web/src/components/incident/dual-state-incident-card.tsx` | Phase 6.5 舊風格,授權邏輯移植進新 IncidentCard 後廢棄 | + +--- + +## Task 1: Tailwind 色彩 Token + +**Files:** +- Modify: `apps/web/tailwind.config.ts` + +- [ ] **Step 1: 在 tailwind.config.ts colors 區塊新增 Anthropic Warmth tokens** + +找到 `colors:` → `nothing:` 區塊下方,新增: + +```typescript +// ==================== Anthropic Warmth (AI中心 v6) ==================== +'ai-center': { + 'bg-base': '#f5f4ed', // 頁面底色(米色) + 'bg-surface': '#faf9f3', // 表面色(暖白) + 'bg-feed': '#f0efe8', // 事件列底色 + border: '#e0ddd4', // 邊框(暖灰) + 'text-primary': '#141413', // 主文字 + 'text-secondary':'#87867f', // 次要文字 + 'text-muted': '#b0ad9f', // 標籤文字 + accent: '#d97757', // 橘紅 Accent(active/hover/badge) + 'accent-light':'rgba(217,119,87,0.08)', // active 背景 +}, +``` + +- [ ] **Step 2: 確認 claw-blue token 已存在(不重複新增)** + +```bash +grep -n "claw" apps/web/tailwind.config.ts +``` + +Expected: 看到 `claw: { blue: '#4A90D9' ... }` 已存在 + +- [ ] **Step 3: Commit** + +```bash +cd apps/web && git add tailwind.config.ts +git commit -m "feat(design): add Anthropic Warmth ai-center color tokens" +``` + +--- + +## Task 2: FlowPipeline 元件(7節點 + Q版龍蝦) + +**Files:** +- Create: `apps/web/src/components/incident/flow-pipeline.tsx` + +- [ ] **Step 1: 建立元件檔案** + +```typescript +'use client' + +/** + * FlowPipeline - AI中心 v6 事件流程管線 + * ======================================== + * 7節點水平管線:告警→AI偵測→AI分析→提案生成→等待授權→執行→完成 + * Q版龍蝦 SVG:進行中=橘紅 #E85530,完成=綠色 #22C55E + * lobster-bob CSS 動畫:上下浮動 4px,1.5s loop + */ + +export type FlowStage = + | 'alert' + | 'detection' + | 'analysis' + | 'proposal' + | 'approval' + | 'execution' + | 'resolved' + +export type NodeStatus = 'done' | 'active' | 'pending' | 'resolved' + +interface FlowNode { + id: FlowStage + label: string + labelKey: string +} + +export interface FlowPipelineProps { + /** 目前進行到哪個 stage */ + activeStage: FlowStage + /** 是否已全部完成(resolved 狀態,綠色龍蝦靜止)*/ + isResolved?: boolean + /** 各節點 tooltip 資訊(可選)*/ + tooltips?: Partial> +} + +const FLOW_NODES: FlowNode[] = [ + { id: 'alert', label: '告警', labelKey: 'flow.alert' }, + { id: 'detection', label: 'AI偵測', labelKey: 'flow.detection' }, + { id: 'analysis', label: 'AI分析', labelKey: 'flow.analysis' }, + { id: 'proposal', label: '提案生成', labelKey: 'flow.proposal' }, + { id: 'approval', label: '等待授權', labelKey: 'flow.approval' }, + { id: 'execution', label: '執行', labelKey: 'flow.execution' }, + { id: 'resolved', label: '完成', labelKey: 'flow.resolved' }, +] + +/** 根據 activeStage 計算每個節點的狀態 */ +function getNodeStatus(nodeId: FlowStage, activeStage: FlowStage, isResolved: boolean): NodeStatus { + if (isResolved) return 'resolved' + const stageOrder = FLOW_NODES.map(n => n.id) + const nodeIndex = stageOrder.indexOf(nodeId) + const activeIndex = stageOrder.indexOf(activeStage) + if (nodeIndex < activeIndex) return 'done' + if (nodeIndex === activeIndex) return 'active' + return 'pending' +} + +/** Q版龍蝦 SVG (18×20) */ +function LobsterSVG({ color }: { color: string }) { + return ( + + {/* 身體 */} + + {/* 頭部 */} + + {/* 眼睛 */} + + + {/* 左鉗 */} + + + {/* 右鉗 */} + + + {/* 觸鬚 */} + + + {/* 尾部 */} + + + ) +} + +export function FlowPipeline({ activeStage, isResolved = false, tooltips }: FlowPipelineProps) { + const lobsterColor = isResolved ? '#22C55E' : '#E85530' + + return ( +
+ {/* CSS keyframes via style tag */} + + +
+ {FLOW_NODES.map((node, idx) => { + const status = getNodeStatus(node.id, activeStage, isResolved) + const isActive = status === 'active' + const isDone = status === 'done' + const isResNode = status === 'resolved' + const isLast = idx === FLOW_NODES.length - 1 + + // 節點顏色 + const dotBg = isDone || isResNode + ? (isResNode ? '#22C55E' : '#E85530') + : isActive ? '#141413' : '#f8f9fc' + const dotBorder = isActive + ? '1.5px solid #E85530' + : isDone || isResNode + ? 'none' + : '1.5px solid #e0ddd4' + const dotShadow = isActive ? '0 0 0 3px rgba(232,85,48,0.2)' : 'none' + + // 連接線顏色 + const connColor = isDone || isResNode ? 'rgba(232,85,48,0.5)' : '#e0ddd4' + + return ( +
+
+ {/* Q版龍蝦(僅 active 節點顯示)*/} +
+ {isActive && ( +
+ +
+ )} +
+ + {/* 節點圓點 */} +
+ + {/* 節點標籤 */} + + {node.label} + + + {/* Tooltip */} + {tooltips?.[node.id] && ( +
{tooltips[node.id]}
+ )} +
+ + {/* 連接線(最後一個節點後不需要)*/} + {!isLast && ( +
+ )} +
+ ) + })} +
+
+ ) +} + +export default FlowPipeline +``` + +- [ ] **Step 2: 確認檔案正確建立** + +```bash +ls apps/web/src/components/incident/flow-pipeline.tsx +``` + +Expected: 檔案存在 + +- [ ] **Step 3: 確認 TypeScript 無錯誤** + +```bash +cd apps/web && npx tsc --noEmit 2>&1 | grep flow-pipeline +``` + +Expected: 無輸出(無錯誤) + +- [ ] **Step 4: Commit** + +```bash +git add apps/web/src/components/incident/flow-pipeline.tsx +git commit -m "feat(incident): add FlowPipeline 7-node pipeline with lobster animation" +``` + +--- + +## Task 3: NemoNodeAnimation 元件 + +**Files:** +- Create: `apps/web/src/components/ai/nemo-node-animation.tsx` + +- [ ] **Step 1: 建立元件檔案** + +```typescript +'use client' + +/** + * NemoNodeAnimation - NemoClaw 截圖風格節點動畫 + * ================================================ + * 72×72 SVG,白底圓形 + 漸層藍球(orb-pulse) + * 4 主臂 + 4 斜臂 + 白色端點節點 + * 虛線旋轉軌道環(ring-spin 12s) + * ❌ 禁止使用 openclaw-panel.tsx 的龍蝦臂 SVG + */ + +export function NemoNodeAnimation({ size = 72 }: { size?: number }) { + const id = 'nemo-node' + return ( + <> + + + + + + + + + + {/* 白底圓形背景 */} + + + {/* 4 主臂(solid #4A90D9,opacity 0.7)*/} + + + + + + {/* 4 斜臂(細,opacity 0.35)*/} + + + + + + {/* 虛線旋轉軌道環 */} + + + {/* 主臂端點節點(r=3,白底+藍邊)*/} + + + + + + {/* 斜臂端點節點(r=2,白底+藍邊)*/} + + + + + + {/* 中央漸層藍球(orb-pulse 脈動)*/} + + {/* 高光 */} + + + + ) +} + +export default NemoNodeAnimation +``` + +- [ ] **Step 2: Commit** + +```bash +git add apps/web/src/components/ai/nemo-node-animation.tsx +git commit -m "feat(ai): add NemoNodeAnimation 72x72 SVG with orb-pulse and ring-spin" +``` + +--- + +## Task 4: HostGrid 元件 + +**Files:** +- Create: `apps/web/src/components/infra/host-grid.tsx` + +- [ ] **Step 1: 建立 infra 目錄並建立元件** + +```bash +mkdir -p apps/web/src/components/infra +``` + +```typescript +'use client' + +/** + * HostGrid - 2×2 主機緊湊 Grid + * ================================ + * 每格:hostname + IP + CPU/RAM + 3條關鍵服務 mini 列 + * hover 橘紅邊框,異常指標用警示色 + * 統帥鐵律:無數據顯示 "--",禁止假數據 + */ + +export interface HostService { + name: string + healthy: boolean +} + +export interface HostInfo { + hostname: string + ip: string + cpuPct: number | null + ramPct: number | null + services: HostService[] +} + +export interface HostGridProps { + hosts: HostInfo[] +} + +function MetricBar({ value, warn = 80, critical = 90 }: { value: number | null; warn?: number; critical?: number }) { + if (value === null) return -- + const color = value >= critical ? '#cc2200' : value >= warn ? '#F59E0B' : '#22C55E' + return ( + {value}% + ) +} + +export function HostGrid({ hosts }: HostGridProps) { + // 補足至 4 格(不足時顯示空格) + const slots = [...hosts, ...Array(Math.max(0, 4 - hosts.length)).fill(null)] + + return ( +
+ {slots.map((host: HostInfo | null, idx) => ( +
host && ((e.currentTarget as HTMLDivElement).style.borderColor = '#d97757')} + onMouseLeave={e => host && ((e.currentTarget as HTMLDivElement).style.borderColor = '#e0ddd4')} + > + {host ? ( + <> + {/* Hostname + IP */} +
+
+
+ + {host.hostname} + +
+ {host.ip} +
+ + {/* CPU / RAM */} +
+ + CPU + + + RAM + +
+ + {/* 3 關鍵服務 mini 列 */} +
+ {host.services.slice(0, 3).map((svc, si) => ( +
+
+ + {svc.name} + +
+ ))} +
+ + ) : ( +
+ -- +
+ )} +
+ ))} +
+ ) +} + +export default HostGrid +``` + +- [ ] **Step 2: Commit** + +```bash +git add apps/web/src/components/infra/host-grid.tsx +git commit -m "feat(infra): add HostGrid 2x2 compact host grid component" +``` + +--- + +## Task 5: Sidebar 重構 + +**Files:** +- Modify: `apps/web/src/components/layout/sidebar.tsx` + +**注意:修改前必讀檔案頂部所有註解(feedback_read_comments_first 鐵律)** + +- [ ] **Step 1: 讀取現有 sidebar.tsx 完整內容** + +```bash +cat apps/web/src/components/layout/sidebar.tsx +``` + +- [ ] **Step 2: 替換 NAV_ITEMS 常數(4分區)** + +把現有的 `NAV_ITEMS` 陣列和相關 icons import 全部替換為: + +```typescript +import { + LayoutDashboard, ShieldCheck, Bell, Monitor, Activity, + Bug, GitBranch, Shield, ClipboardCheck, + Wrench, Package, Ticket, DollarSign, Zap, FileText, + BookOpen, Terminal, AppWindow, Server, + Users, BellRing, CreditCard, HelpCircle, Settings, +} from 'lucide-react' + +// ============================================================ +// AI中心 v6 — 4分區 Sidebar(統帥批准 2026-04-01) +// ============================================================ + +type NavSection = { + sectionKey: string + sectionLabel: string + items: NavItemConfig[] +} + +const NAV_SECTIONS: NavSection[] = [ + { + sectionKey: 'ai-core', + sectionLabel: 'AI 核心', + items: [ + { id: 'ai-center', href: '/', labelKey: 'dashboard', Icon: LayoutDashboard }, + { id: 'authorizations', href: '/authorizations', labelKey: 'approvals', Icon: ShieldCheck, badge: true }, + { id: 'alerts', href: '/alerts', labelKey: 'alerts', Icon: Bell }, + ], + }, + { + sectionKey: 'monitoring', + sectionLabel: '監控與安全', + items: [ + { id: 'monitoring', href: '/monitoring', labelKey: 'monitoring', Icon: Monitor }, + { id: 'apm', href: '/apm', labelKey: 'apm', Icon: Activity }, + { id: 'errors', href: '/errors', labelKey: 'errors', Icon: Bug }, + { id: 'topology', href: '/topology', labelKey: 'topology', Icon: GitBranch }, + { id: 'security', href: '/security', labelKey: 'security', Icon: Shield }, + { id: 'compliance', href: '/compliance', labelKey: 'compliance', Icon: ClipboardCheck }, + ], + }, + { + sectionKey: 'ops', + sectionLabel: '運維管理', + items: [ + { id: 'auto-repair', href: '/auto-repair', labelKey: 'autoRepair', Icon: Wrench }, + { id: 'deployments', href: '/deployments', labelKey: 'deployments', Icon: Package }, + { id: 'tickets', href: '/tickets', labelKey: 'tickets', Icon: Ticket }, + { id: 'cost', href: '/cost', labelKey: 'cost', Icon: DollarSign }, + { id: 'action-logs', href: '/action-logs', labelKey: 'actions', Icon: Zap }, + { id: 'reports', href: '/reports', labelKey: 'reports', Icon: FileText }, + ], + }, + { + sectionKey: 'knowledge', + sectionLabel: '知識與工具', + items: [ + { id: 'knowledge-base', href: '/knowledge-base', labelKey: 'knowledge', Icon: BookOpen }, + { id: 'terminal', href: '/terminal', labelKey: 'terminal', Icon: Terminal }, + { id: 'apps', href: '/apps', labelKey: 'apps', Icon: AppWindow }, + { id: 'services', href: '/services', labelKey: 'services', Icon: Server }, + ], + }, +] + +const BOTTOM_NAV_ITEMS: NavItemConfig[] = [ + { id: 'users', href: '/users', labelKey: 'users', Icon: Users }, + { id: 'notifications', href: '/notifications', labelKey: 'notifications', Icon: BellRing }, + { id: 'billing', href: '/billing', labelKey: 'billing', Icon: CreditCard }, + { id: 'help', href: '/help', labelKey: 'help', Icon: HelpCircle }, + { id: 'settings', href: '/settings', labelKey: 'settings', Icon: Settings }, +] +``` + +- [ ] **Step 3: 替換 sidebar 渲染邏輯** + +找到 sidebar 的主要渲染區塊,把原本的 `NAV_ITEMS.map(...)` 替換為分區渲染。在 `