18 KiB
EwoooC 後台 — Codex 開發交接規格 (HANDOFF.md)
這份文件是給 Codex(或任何工程團隊)將 prototype 重建為正式 production 專案的完整規格。
Prototype 是 React 18 + Babel Standalone(瀏覽器即時 transpile),不是 production build。
請依下方規格,重建為正式專案。
0. 專案概覽
產品名稱:EwoooC(內部後台 / 比價爬蟲監控系統)
目標使用者:採購、行銷、營運人員
核心功能:商品價格監控、活動看板、廠商缺貨追蹤、AI 助手、雲端匯入
資料規模:監控 7,000+ 商品,每日掃描多次,含歷史價格走勢
設計語言(必須沿用):Nothing × Claude 混合風格
- 米色基底(warm paper)+ 黑灰主體 + 焦糖橘 accent
- JetBrains Mono 用於所有數字、ID、時間戳
- Inter 用於介面文字、繁體中文用 Noto Sans TC
- 安靜、結構化、靠留白和排版取勝;避免漸層厚重 hero、彩色表頭、五彩按鈕
1. 技術棧建議
| 類別 | 建議 | 備註 |
|---|---|---|
| Framework | Next.js 14 + App Router | SSR、RSC、檔案路由 |
| 語言 | TypeScript | 全面型別化 |
| 樣式 | Tailwind CSS + CSS Variables | tokens 走 CSS vars,元件用 Tailwind |
| 狀態 / 資料 | TanStack Query (v5) | 抓 API、cache、revalidate |
| 表單 | React Hook Form + Zod | 表單驗證 |
| 圖表 | Recharts 或 Visx | 價格走勢圖、KPI 趨勢 |
| 表格 | TanStack Table v8 | 排序、篩選、虛擬化 |
| Icon | Lucide React(替代現有 SVG icons) | 與 prototype 風格相容 |
| 字型 | next/font 載入 JetBrains Mono + Inter + Noto Sans TC | self-host |
| 部署 | Vercel / 自架 Docker | — |
2. 路由表(Next.js App Router)
app/
├── layout.tsx # 全域 layout(載字型、tokens、TanStack Provider)
├── (auth)/
│ └── login/page.tsx # 登入頁
├── (admin)/
│ ├── layout.tsx # Sidebar + Topbar shell
│ ├── dashboard/page.tsx # 商品看板(首頁,重導 /)
│ ├── campaigns/
│ │ ├── page.tsx # 活動看板(含 tab 切換)
│ │ └── [id]/page.tsx # 單一活動詳情(可選)
│ ├── products/
│ │ ├── page.tsx # 全商品列表
│ │ └── [id]/page.tsx # 商品詳情 + 30 天走勢
│ ├── analytics/page.tsx # 分析報表
│ ├── vendors/page.tsx # 廠商缺貨
│ ├── ai-assistant/page.tsx # AI 助手
│ ├── cloud-import/page.tsx # 雲端匯入
│ └── settings/page.tsx # 系統管理
└── api/ # 若用 BFF,放這
Sidebar 對應:
- 監控:商品看板(dashboard)、活動看板(campaigns)、分析報表(analytics)
- 營運:廠商缺貨(vendors)、商品列表(products)、訂單(orders)
- 智能:AI 助手(ai-assistant)、雲端匯入(cloud-import)
- 系統:系統管理(settings)
3. Design Tokens(必讀,直接搬)
來源:design-tokens.css(已在交付包根目錄)
核心變數(節錄,完整見檔案):
:root {
/* 基底色 */
--momo-bg-primary: #f0eee9; /* 米色頁底 */
--momo-bg-surface: #ffffff; /* 卡片白 */
--momo-bg-paper: #f7f5f0; /* 微暖灰白(hover/header) */
--momo-bg-subtle: #ebe8e0;
--momo-bg-muted: #e6e2d8;
/* 主體色 */
--momo-ink: #1a1a1a; /* Nothing 黑 */
--momo-text-primary: #1a1a1a;
--momo-text-secondary:#4a4a4a;
--momo-text-tertiary: #8a8a8a;
/* Accent */
--momo-accent: #c96442; /* Claude 焦糖橘 */
--momo-accent-hover: #b3553a;
/* 語意色 */
--momo-success: #16a34a;
--momo-danger: #dc2626;
--momo-warning: #ea580c;
--momo-info: #3b5cb8;
/* 邊線 */
--momo-border: #d6d2c8;
--momo-border-light: #e6e2d8;
/* 字型 */
--momo-font-family-base: 'Inter', 'Noto Sans TC', -apple-system, sans-serif;
--momo-font-family-mono: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
/* 字級 */
--momo-font-size-xs: 11px;
--momo-font-size-sm: 13px;
--momo-font-size-base: 14px;
--momo-font-size-lg: 16px;
/* 圓角 */
--momo-radius-sm: 3px;
--momo-radius-md: 4px;
--momo-radius-lg: 8px;
--momo-radius-pill: 999px;
/* 陰影 */
--momo-shadow-sm: 0 1px 2px rgba(0,0,0,0.04);
--momo-shadow-md: 0 2px 8px rgba(0,0,0,0.06);
/* 過場 */
--momo-transition-base: all 0.15s ease;
}
Tailwind 對應建議:在 tailwind.config.ts 用 theme.extend.colors、fontFamily、borderRadius 直接對應上述變數。
4. 元件清單(重建依據 app/ui.jsx)
| 元件 | Props (核心) | 行為 |
|---|---|---|
<Button> |
variant: gradient | solid | outline | ghost | secondary | danger; size: sm/md/lg; icon; iconRight; loading | 主色為 accent,secondary 為米底+黑邊 |
<Badge> |
tone: primary/success/danger/warning/info/secondary; dot | 圓角 pill |
<Card> |
cardStyle: flat/elevated; padding | flat 為主(border-light + 白底) |
<Input> |
icon; size; error | 米底外框,focus 時黑邊 |
<Avatar> |
name; size; gradient | 圓形,預設取首字 |
<Icon> |
name; size | 統一用 Lucide 替代 |
<Modal> |
open; onClose; title; size | 中央 modal,漸出 |
<SectionLabel> |
num; children; sub | 重要 — Dashboard 大區塊用「01 / 02 / 03」編號標籤 |
重要規範:
- 所有「數字、ID、時間戳、價格」必須使用 Mono 字型(class
momo-mono或 Tailwindfont-mono) - 表頭 label 用 Mono + uppercase + letter-spacing 0.08em(看起來像終端機)
- 表格不要用紫色漸層 header(已棄用),改用米色 paper 底 + Mono 小字 label
5. 頁面規格
5.1 商品看板 / Dashboard(/dashboard)
參考:app/page-dashboard.jsx
佈局(從上到下):
-
區塊 01:監控總覽 — 一排 4 個 KPI(horizontal divider 分隔),第二顆「今日變動」用黑底反白
- 監控總數 / 今日變動(accent)/ 漲價(danger)/ 降價(success)
- 大字 44px Mono,下方 sub 11px
-
區塊 02:焦點數據 — 三欄並排
- 最活躍分類 / 最大變動(紅色 +金額)/ 爬蟲排程(綠點 ACTIVE + 上次執行時間)
-
區塊 03:商品列表
- 篩選列:搜尋 + 分類 select + segmented tabs(全部/新上架/漲價/降價/下架)+ 更新/發送通知按鈕
- 表格:分類 / 商品名稱(含 emoji 縮圖 + ID)/ 當天價格 / 昨日漲跌 / 週漲跌 / 更新時間 / 上架時間
- 表頭:米色 paper 底,Mono uppercase 小字
- 漲跌格子:紅色▲ / 綠色▼ + Mono 數字
互動:
- 點 row → 開 Modal 顯示 30 天價格走勢(用 Recharts LineChart)
- 篩選即時觸發(client-side 過濾或 query params)
5.2 活動看板(/campaigns)
參考:app/page-campaigns.jsx
佈局:
-
活動切換 segmented tabs(限時搶購 / 1.1狂歡 / 母親節 / 520 / 勞動節)
- 每顆 tab 含 icon + 名稱 + 商品數 pill
-
Hero 雙欄
- 左 2/3:活動主資訊卡(漸層背景,色相依活動切換)
- flash: 紅橘漸層 / festival: 紫 / mothers: 玫紅 / valentine: 情人紅 / laborday: 藍
- 點陣裝飾背景 + 大圖示 watermark
- CAMPAIGN 標籤 + ID + 大標題 + meta(時段 / 最後更新 / 商品總數)+ 操作按鈕
- 右 1/3:活動數據 KPI(上架/新品/漲價/降價 2x2)+ 底部排程 footer
- 左 2/3:活動主資訊卡(漸層背景,色相依活動切換)
-
時段時間軸(僅限時搶購顯示)
- 24h 條狀圖,當前時段顯示 NOW 標籤
- bar 高度依商品數,accent 色為當前
-
分類 chips(festival / mothers / valentine / laborday)
- 橫向 wrap,每個 chip 有名稱 + count pill,可點選
-
商品列表
- 同 Dashboard 表格樣式,但欄位:分類 / 商品資訊 / 價格 / 倒數組數 (限時) 或狀態
5.3 商品列表(/products)
參考:app/page-products.jsx
全商品 CRUD + 篩選 + 編輯 modal。可重用 Dashboard 的 ProductTable 元件。
5.4 廠商缺貨(/vendors)
簡單表格:vendor / count / lastSeen,資料來源 EWOOOC_DATA.outOfStock。
5.5 其他頁面
- 分析報表:圖表為主(Recharts),尚未在 prototype 完整定義 → 可先做 placeholder
- AI 助手 / 雲端匯入 / 系統管理:prototype 為佔位 → 與 PM 確認需求
6. 資料模型 / API 規格
6.1 Mock 資料來源
app/data.jsx 中 EWOOOC_DATA 為所有假資料。重建時請替換為 API 呼叫。
6.2 建議的 OpenAPI Endpoints
GET /api/dashboard/summary # 監控總覽 + 今日變動
GET /api/dashboard/focus # 最活躍分類 / 最大變動 / 排程狀態
GET /api/products?category=&q=&tab=&page= # 商品列表(含篩選)
GET /api/products/{id} # 商品詳情
GET /api/products/{id}/price-history?days=30 # 30 天價格走勢
POST /api/products/{id}/notify # 發送通知
GET /api/campaigns # 所有活動清單
GET /api/campaigns/{id} # 單一活動詳情(含 timeSlots, categories, products, stats)
POST /api/campaigns/{id}/refresh # 手動觸發爬蟲
POST /api/campaigns/{id}/notify
GET /api/vendors/out-of-stock # 廠商缺貨
GET /api/schedule/status # 爬蟲排程狀態
6.3 Schema 範例(TypeScript)
interface Product {
id: string;
category: string;
name: string;
emoji?: string; // 暫時佔位,正式版改為 imageUrl
imageUrl?: string;
price: number;
yesterdayChange: number | null;
weekChange: number | null;
updatedAt: string; // ISO
listedAt: string; // ISO
isNew?: boolean;
}
interface DashboardSummary {
monitor: { total: number; todayAdded: number; weekGrowth: number; stableCount: number };
dynamics: {
priceUp: number; priceDown: number; delisted: number;
avgUp: number; avgDown: number;
activity: number; activeCount: number;
hottestCategory: string; hottestCount: number;
biggestChange: { product: string; amount: number };
};
schedule: { lastRun: string; scanned: number; added: number; status: 'success' | 'running' | 'failed' };
}
interface Campaign {
id: 'flash' | 'festival' | 'mothers' | 'valentine' | 'laborday';
name: string;
icon: string;
time: string;
lastUpdate: string;
total: number;
schedule: { lastRun: string; anomalies: number; status: string };
timeSlots?: { time: string; count: number; active?: boolean }[];
categories?: { name: string; count: number; active?: boolean }[];
stats: { listed: number; new: number; up: number; down: number; delisted: number };
products: CampaignProduct[];
}
7. 互動行為清單
| 行為 | 描述 |
|---|---|
| Sidebar 折疊 | 寬度從 240 → 64,icon-only |
| Topbar 搜尋 | ⌘K / Ctrl+K 開啟全域搜尋 |
| 表格 row click | 開啟商品詳情 Modal(含 30 天走勢圖) |
| 漲跌欄排序 | 點欄頭 ↕ 切換 asc/desc |
| 篩選 tabs | 即時過濾,URL 同步 query string |
| 匯出報表 | 後端產 CSV 後 download |
| 發送通知 | trigger backend webhook,回應 toast |
| 活動切換 tab | URL ?tab=flash 同步 |
| Tweaks 面板 | 正式版可移除(prototype 用) |
8. 字型與資源
Self-host 字型:
// app/layout.tsx
import { Inter, JetBrains_Mono, Noto_Sans_TC } from 'next/font/google';
// 對應 CSS variable
Icon:用 Lucide 替換現有 SVG,名稱對照:
- dashboard →
LayoutDashboard - megaphone →
Megaphone - chart →
BarChart3 - box / package →
Package - robot / ai →
Bot - cloud →
Cloud - settings →
Settings - search →
Search - bell →
Bell - refresh →
RefreshCw - copy →
Copy - download →
Download - trendUp →
TrendingUp - arrowUp / arrowDown →
ArrowUp/ArrowDown - clock →
Clock - tag →
Tag
9. 必須遵守的視覺紀律 ⚠️
❌ 不要:
- 不要回到原本的紫色漸層 + emoji 圖示風格(舊 momo 後台)
- 不要在表頭用紫色漸層
- 不要用五彩繽紛的按鈕
- 不要在 KPI 卡用厚重藍色 hero 漸層
- 不要使用 Inter 以外的 sans-serif 主體(避開 Roboto, system-ui)
- 數字、ID、時間不要用 sans-serif
✅ 要:
- 米色底 + 黑灰主體 + 焦糖橘 accent
- 區塊用「01 / 02 / 03」編號 + uppercase Mono label
- KPI 大數字 44px+ Mono,靠 horizontal divider 分隔,不要每顆都包卡片
- 活動 hero 才用漸層(且色相依活動主題)
- 表格安靜,靠 Mono 字體和留白做出層次
- 邊框細且淺(border-light),陰影克制
10. 開發里程碑建議
- Week 1:架構 + tokens + 共用元件(Button/Card/Badge/Input/Modal/Icon/SectionLabel)
- Week 2:Sidebar + Topbar shell + 路由 + Auth
- Week 3:Dashboard(KPIRow / FocusRow / ProductTable)+ API 串接
- Week 4:Campaigns(5 個 tab + Hero + Timeline + Products)
- Week 5:Products 詳情 + 30 天走勢圖 modal
- Week 6:Vendors / Analytics / 其他頁面 + 微調 + QA
11. 交付包檔案清單
ewoooc-handoff/
├── HANDOFF.md # ← 本文件
├── EwoooC 後台原型.html # 入口(瀏覽器直開)
├── design-tokens.css # 所有 CSS 變數
├── data.jsx # (根目錄舊版,可忽略)
├── design-canvas.jsx # (prototype 工具,可忽略)
├── tweaks-panel.jsx # (prototype 工具,可忽略)
└── app/
├── data.jsx # 假資料(轉為 API schema 參考)
├── icons.jsx # SVG icon 定義(轉為 Lucide)
├── ui.jsx # 共用元件(轉為 TS components)
├── shell.jsx # Sidebar + Topbar
├── main.jsx # 路由分派 + Tweaks
├── modals.jsx # 商品詳情 / 編輯 modal
├── page-dashboard.jsx # 商品看板
├── page-campaigns.jsx # 活動看板
├── page-products.jsx # 商品列表
└── page-orders.jsx # 訂單(範例頁)
12. 與 PM / Designer 確認清單
開發前請與 PM / Designer 對齊:
- 真實 API endpoint 文件
- 認證 / 權限模型(RBAC?單一管理者?)
- 商品 emoji 是否替換為真實圖片(CDN?)
- Analytics 頁面圖表規格
- AI 助手 / 雲端匯入功能定義
- 多語系需求(目前只有繁中)
- 部署環境(Vercel / 自架 / on-prem)
- 監控與錯誤追蹤(Sentry?)
有任何視覺或行為不確定的地方,以 prototype 的呈現為準。
Prototype 路徑:開啟EwoooC 後台原型.html直接看 live demo,並用右下角 Tweaks 面板觀察可調整的設計變數。
13. 2026-05 增量更新(Codex 必讀)
本章記錄 HANDOFF.md 初稿後追加的所有設計決策。以下優先於前面章節。
13.1 商品看板 — KPI 列強化
KPI 從 4 格擴成 5 格,最後一格為「AI 挑品」入口:
| # | label | value | 互動 |
|---|---|---|---|
| 1 | 監控總數 | 7,234 | — |
| 2 | 今日變動 | 2,180(黑底反白) | — |
| 3 | 漲價(danger) | 458 | 點擊 → tab 切到 up |
| 4 | 降價(success) | 612 | 點擊 → tab 切到 down |
| 5 | AI 挑品 | 50 ↗ | 點擊 → tab 切到 ai 並平滑滾到 §03 商品列表 |
實作:KPI cell 加 cursor: pointer,onClick 設 setTab(...) + document.getElementById('product-table')?.scrollIntoView({behavior:'smooth'})(或等效 ref 滾動)。
13.2 商品看板 — FilterBar tabs 順序
全部 | AI 揀品 | 新上架 | 漲價 | 降價 | 下架
AI 揀品 tab 對應規則:目前用模擬條件(價格波動 > 8% 或標題含關鍵字)挑出約 1/3 商品,正式版請改接 GET /api/products/ai-picks(後端 ML 推薦),schema 同 /api/products response。
13.3 商品看板 — 表格分頁
Client-side 分頁,50 筆/頁。Footer 顯示 1–50 · 共 N 筆 + 上下頁鈕(圖示按鈕,disabled 時 opacity 0.3)。正式版改 server-side:GET /api/products?page=1&pageSize=50。
13.4 商品看板 — Row hover & 警報欄位
- Row hover 時加左側 3px caramel accent 條(
box-shadow: inset 3px 0 0 var(--momo-warm-caramel))。 - 警報 chip 所在
<td>設min-width: 140px; white-space: nowrap,避免 chip 被擠到換行。
13.5 PriceHistoryModal(新元件)
點商品 row → 開全螢幕 modal 顯示價格走勢。
Header:
- 左:商品縮圖 + 名稱 + ID(mono)
- 右:3 顆 icon-only 操作鈕(加入監控 / 匯出 CSV / 分享連結)+ 關閉
Body:
- 區段切換 tabs:
7d/30d/90d/1y - LineChart:
days改變時呼叫buildSeries(days)重算資料點- 7d / 30d / 90d → 每日一點
- 1y → 每週一點,共 52 點
- 下方資訊欄:當前價 / 區間最高 / 區間最低 / 變動幅度
API:GET /api/products/{id}/price-history?range=7d|30d|90d|1y → {points: [{date, price}], stats: {...}}
13.6 活動看板 — Hero 漸層與點陣
§03 三張活動卡(限時搶購 / 1.1 狂歡 / 母親節)背景:
- 加左上 3×36px caramel accent 條
- 疊一層
opacity: 0.18的點陣紋理(background-image: radial-gradient(circle, currentColor 1px, transparent 1px); background-size: 8px 8px) - §02 三張焦點卡 padding 16px(從 18 收緊)
13.7 設計紀律補充
- 絕不使用 emoji 當功能 icon(emoji 只能出現在商品縮圖位置)。
- 絕不用漸層當大面積背景,僅活動 hero 卡可用,且需配點陣紋理壓低彩度。
- 所有數字、ID、時間戳一律 JetBrains Mono;中文標題用 Noto Sans TC。
- 表格 row 高度 56px、表頭 40px,padding 一律走 tokens。
13.8 尚未交付(Phase 2)
以下在 prototype 是 placeholder,正式版需設計 + 實作:
- 分析報表(
/analytics)— 預期:類別趨勢、競品對比、季節性熱圖 - AI 助手對話流(
/ai-assistant)— 串 LLM - 雲端匯入精靈(
/cloud-import)— S3 / GDrive 連接器 - 系統管理 RBAC(
/settings)
若 prototype 與本章描述衝突,以 prototype 的實際行為為準。Codex 可直接讀
app/page-dashboard.jsx、app/modals.jsx、app/page-campaigns.jsx取得真實實作。