- feature-device-mgmt-tdd.md + api-device-mgmt.md(B 設備管理 TDD) - feature-model-sharing-tdd.md + api-model-sharing.md + PRD feature + 設計規格(C 模型共享三方規劃) - adr-020-ffmpeg-camera-indev.md(camera 三平台 indev) - PRD.md / TDD.md 索引增補 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 KiB
模型共享 設計規格 — visionA Cloud
L 級新功能「模型共享」的 Design 部分(三方聯合規劃:PM 寫 PRD / Architect 寫 TDD / Design 寫本檔)。
核心定位:本功能是擴充既有模型庫 UI,不是全新模組。100% 沿用既有 Design Tokens(
design-tokens.md)、既有元件(components.md)、既有/models三區版型與ModelCard/ModelGrid/ModelSection/ModelFilters/ModelDetailClient。本檔只定義「共享」這個維度帶來的新視覺 / 互動增量。不新增 Design Token。狀態色沿用既有
chart-*token 與 §2.1 半語義約定。對應頁面:
/models(列表擴充)+/models/[id](詳情頁擴充成 owner / 公開兩態)+ 新增「共享對象設定」互動(Dialog)+ 新增「共享模型庫」瀏覽維度。配套格式參考:
pages.md§8、flows/flow-model-upload.md、components.md。
0. 名詞與待確認前提(先給 PM / Architect)
本設計基於以下假設,凡標 🔶 者為「需 PM 確認需求細節」、標 🔷 者為「需 Architect 確認技術可行性」。設計會標出因假設不同而分歧的 UI 分支。
| # | 名詞 / 假設 | 說明 | 標記 |
|---|---|---|---|
| A1 | 公開對象(visibility)三態 | 假設分 private(僅自己)/ public(所有登入使用者可見)/ shared(指定對象)三種 |
🔶 PM:是否只做 private/public 兩態?「指定對象」Phase 0 是否需要? |
| A2 | 「指定對象」的粒度 | 假設可指定「個別使用者(by email)」。是否還有「群組 / 組織 / 團隊」概念? | 🔶 PM + 🔷 Architect:有無 org/team 資料模型? |
| A3 | 可見模型的三分類 | 列表要區分「我的(owner)/ 公開(public)/ 共享給我的(shared-with-me)」 | 🔶 PM:分類命名與是否需要「我公開出去的」獨立檢視 |
| A4 | 共享 = 唯讀 | 假設別人共享 / 公開給我的模型我只能檢視 + 下載 + 燒錄,不能改名 / 刪除 / 再共享 | 🔶 PM:可否「再共享」(re-share)?可否下載? |
| A5 | profile 頁 = 擴充既有 detail | 假設「模型 profile 頁」就是擴充現有 /models/[id],依 viewer 身份切 owner 版 / 公開版,不另建路由 |
🔷 Architect:是否需要獨立 public 路由(如 /m/[shareId] 供分享連結)? |
| A6 | 分頁(pagination) | 共享模型庫可能量大需分頁。假設用 offset/limit 或 cursor | 🔷 Architect:後端分頁機制(offset vs cursor)決定 UI(頁碼 vs 無限捲動 / 載入更多) |
| A7 | 搜尋範圍 | 假設搜尋 = 對「當前可見的所有模型」搜名稱(+ 選填分類 / 晶片) | 🔶 PM:搜尋要不要跨到「公開但未共享給我」的全庫探索? |
| A8 | 公開對象變更權限 | 假設只有 owner 能改自己模型的公開設定 | 🔷 Architect:權限在 API 層把關(前端只是 UI 便利) |
設計原則:以上假設我採「最完整但可降級」的畫法——先畫三態 visibility + 三分類列表,PM 若砍到兩態 / 兩分類,UI 直接移除對應分支即可,不需重畫。
1. User Story(Design 視角)
作為 一個 Kneron 開發者, 我想要 把我的模型公開或共享給特定同事,並瀏覽別人共享給我的模型, 這樣 團隊就能共用模型,不用每個人重複上傳 / 轉檔。
體驗成功條件:
- 使用者一眼能分辨列表中哪些是「我的 / 公開 / 共享給我的」(不只靠顏色,用 badge 文字 + 圖示雙編碼)
- 設定公開對象在 2 次點擊內可達(卡片選單 or 詳情頁按鈕 → Dialog)
- 共享模型庫量大時,瀏覽 / 搜尋 / 篩選 / 排序不卡頓、狀態清楚(載入 / 空 / 無結果 / 無權限四態齊備)
- 公開版 profile 頁不洩漏 owner 的私有操作(刪除 / 改公開設定按鈕對非 owner 隱藏)
2. 範圍與 Phase 0 降級
| 項目 | Phase 0(本次) | Phase 1+ |
|---|---|---|
| Visibility 態 | private / public / shared(🔶 待 PM 砍) | + 到期共享 / 密碼保護連結 |
| 指定對象粒度 | 個別使用者 by email(🔶) | + 群組 / 組織 |
| 列表分類 | 我的 / 公開 / 共享給我的 三分類(🔶) | + 我公開出去的獨立檢視 |
| 分頁 | 「載入更多」按鈕 or 頁碼(依 🔷 A6) | 無限捲動 + 虛擬列表 |
| 排序 | 名稱 / 建立時間 / 共享時間(3 選項) | + 熱門度 / 下載數 |
| 篩選 | 既有 targetChip + 新增「共享狀態」維度 | + 分類 / 標籤 / owner |
| 搜尋 | 名稱模糊搜(前端 or 後端依 🔷 A6) | 全文 + tag |
| profile 公開版 | owner 版 / 公開版兩態 | 分享連結 /m/[shareId] |
| 再共享 / 轉讓 | 不做(🔶 A4) | 視需求 |
3. 資訊架構變更(IA)
沿用既有 /models 與 /models/[id],不新增頂層導航。共享是「模型」的一個屬性維度,落在既有模型庫內。
/models (模型庫 — 擴充:新增「共享」瀏覽維度)
│
├── 檢視模式切換(新增):
│ ┌─ 依來源分區(既有:preset / converted / uploaded) ← 預設,僅「我的」模型
│ └─ 依共享關係分區(新增):我的 / 公開 / 共享給我的
│
├── 搜尋框(新增,跨當前檢視)
├── 篩選(擴充 ModelFilters:targetChip + 共享狀態)
├── 排序(新增:名稱 / 建立時間 / 共享時間)
├── 分頁 / 載入更多(新增)
│
└── /models/[id] (模型 profile 頁 — 擴充成雙態)
├── owner 版:既有全操作(改名 / 刪除 / 下載 / 燒錄 / 【新增】公開設定)
└── 公開 / 共享版:唯讀(檢視 / 下載 / 燒錄),隱藏 owner-only 操作
+ 新增「擁有者」資訊列(誰共享的 / 共享時間 / 公開對象徽章)
🔶 待 PM 確認:兩種檢視模式(來源分區 vs 共享關係分區)是否都要?還是共享關係分區直接取代來源分區?我建議保留切換(Tab 或 Segmented Control),因為「來源分區」對管理自己的模型仍有用,「共享關係分區」才是本功能重點。
4. 共享模型庫列表設計
4.1 檢視模式切換(新增元件 ModelViewToggle)
在 /models 頁標題列下、ModelFilters 上方,新增一個 Segmented Control(用既有 Tabs 元件實作,variant 沿用):
┌─────────────────────────────────────────────────────────────┐
│ 模型庫 [上傳模型] │
│ 管理、公開與共享你的 Kneron 模型 │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────────┬──────────────┐ │
│ │ 依來源 ● │ 依共享關係 │ ← Tabs(既有元件) │
│ └──────────────┴──────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 🔍 [搜尋模型名稱...........] [晶片 ▾] [共享狀態 ▾] [排序 ▾]│ ← 篩選列(擴充)
├─────────────────────────────────────────────────────────────┤
│ (分區內容依所選檢視模式渲染) │
└─────────────────────────────────────────────────────────────┘
- 依來源(既有預設,不變):preset / converted / uploaded 三區,僅顯示「我的」模型。
- 依共享關係(新增):三區 —
- 🟢 我的(owner):
chart-1色點呼應 - 🔵 公開(public,含我公開的 + 別人公開的,🔶 A7 待確認範圍):
chart-2 - 🟣 共享給我的(shared-with-me):
chart-3
- 🟢 我的(owner):
沿用既有
ModelSection的「色點 + 標題 + 計數」樣式,只是換分組維度。SOURCE_DOT_CLASS邏輯延伸出一份SHARE_DOT_CLASS,色 token 一致。
4.2 卡片上的共享標示(擴充 ModelCard)
既有 ModelCard 已有 status badge + targetChip badge + source badge。新增一個 visibility badge,放在 badge 列,用圖示 + 文字雙編碼(不僅靠顏色,滿足無障礙 De1):
| Visibility | 圖示(Lucide) | 文字 | 配色(沿用 token tint 風格) | 顯示條件 |
|---|---|---|---|---|
| private | Lock |
私有 | text-muted-foreground + border-border(中性) |
owner 檢視自己模型時 |
| public | Globe |
公開 | border-chart-2/30 bg-chart-2/10 text-chart-2 |
任何人 |
| shared | Users |
已共享 / 共享給我 | border-chart-3/30 bg-chart-3/10 text-chart-3 |
owner 看到「已共享給 N 人」;receiver 看到「{owner} 共享」 |
owner 額外資訊:private/shared/public 卡片右上角,owner 檢視時可在 badge 顯示對象數,如「公開」「共享 · 3 人」。
receiver 視角:卡片新增一行次要資訊(text-xs text-muted-foreground):「由 {ownerEmail} 共享 · {relativeTime}」。沿用 RemoteDeviceBadge 的相對時間格式化 util(剛剛 / X 分鐘前 / 絕對時間)。
卡片操作差異:
- owner 卡片:既有下載按鈕(若 downloadable)+ 新增卡片右上角
⋮選單(Dropdown),內含「公開設定」「刪除」等(見 §5 觸發點)。 - receiver 卡片:只保留「下載」(若 A4 允許)+ 點擊進 profile 頁。無
⋮選單(無 owner 權限)。
🔷 Architect 確認:
ModelSummary需新增欄位visibility: 'private' | 'public' | 'shared'、ownerEmail?、sharedAt?、sharedCount?(owner 視角)、isOwner: boolean。前端 UI 依這些欄位渲染,實際權限由 API 把關。
4.3 篩選擴充(擴充 ModelFilters)
既有 ModelFilters 只有 targetChip。新增「共享狀態」維度(第二個 Select),僅在「依共享關係」檢視模式下顯示:
export interface ModelFilterValue {
targetChip: TargetChip | "all";
visibility?: "all" | "private" | "public" | "shared"; // 新增,僅共享關係檢視用
}
- targetChip 篩選跨所有分區作用(沿用既有行為)。
- visibility 篩選:選「公開」時只顯示 public 區,其餘區收合為 0(沿用「區內為空仍顯示標題 + 精簡空狀態」的既有慣例)。
4.4 搜尋框(新增)
- 位置:篩選列最左,
Input+ 前綴Searchicon(既有Input元件 h-9)。 - 行為:🔷 A6 —
- 若後端分頁:搜尋走後端(debounce 300ms,送 query),配合分頁。
- 若前端全量:即時前端 filter(無 debounce 需求)。
- Placeholder:
搜尋模型名稱... - 清除:有輸入時右側顯示
X清除鈕(ghosticon button)。 - 無障礙:
role="searchbox"、aria-label="搜尋模型";搜尋無結果時aria-live="polite"播報結果數。
4.5 排序(新增 ModelSortSelect)
Select(h-9),選項:
| key | 文字 | 說明 |
|---|---|---|
name-asc |
名稱 A→Z | 預設(我的區) |
createdAt-desc |
最新建立 | |
sharedAt-desc |
最近共享 | 僅「共享給我的」區有意義;其他區隱藏此選項 |
🔷 排序在後端還前端由 A6 決定。若後端分頁 → 排序參數送後端。
4.6 分頁(新增,依 🔷 A6 二選一)
方案 P1(cursor / 無限捲動友善)→「載入更多」按鈕(Phase 0 建議,實作簡單、無頁碼狀態同步問題):
┌────────────────────────────────────────────┐
│ [卡片] [卡片] [卡片] [卡片] │
│ [卡片] [卡片] [卡片] [卡片] │
│ │
│ [ 載入更多 (顯示 24 / 87) ] │ ← Button variant=outline,loading 時 Spinner
└────────────────────────────────────────────┘
方案 P2(offset / 傳統頁碼)→ 底部 Pagination 元件(若後端只支援 offset):
‹ 上一頁 1 2 [3] 4 5 … 12 下一頁 ›
🔷 Architect 裁決 A6:後端分頁是 cursor 還 offset?我建議 P1「載入更多」——對「瀏覽型」的共享庫體驗較順、行動裝置友善、無「換頁後捲動位置重置」問題。若 Architect 已定 offset,則走 P2。兩案我都出規格,選一即可,不需重畫卡片。
分頁 UX 細節:
- 每頁 24 筆(3 欄 × 8 列 desktop;卡片沿用既有
grid-cols-1 sm:2 lg:3 xl:4)。 - 載入更多 loading:按鈕內
Spinner+ 文字「載入中」;同時底部補 4 個Skeleton卡片(沿用既有 skeleton 樣式)。 - 搜尋 / 篩選 / 排序變更 → 重置分頁到第 1 頁 / 清空已載入。
5. 模型公開設定 UI(新增 ModelVisibilityDialog)
5.1 觸發點(兩處,owner-only)
- 列表卡片
⋮選單 →「公開設定」(§4.2 新增的 Dropdown)。 - profile 頁(owner 版)操作列 → 新增按鈕
[公開設定](variant=outline+Globeicon),放在既有「下載 / 刪除」旁。
🔶 PM:觸發點以上兩處是否足夠?是否需要在上傳完成後直接引導設定公開對象?(我建議上傳 Dialog 完成後加一句「模型預設為私有,之後可在詳情頁設定公開」的提示,不強迫當下設定。)
5.2 Dialog 版型(沿用既有 Dialog)
┌──────────────────────────────────────────────────┐
│ 公開設定 — {模型名稱} [X] │
├──────────────────────────────────────────────────┤
│ 誰可以看到並使用這個模型? │
│ │
│ ○ 🔒 私有 只有你自己 │
│ ○ 🌐 公開 所有 visionA 使用者 │
│ ● 👥 指定對象 只有你選的人 │ ← RadioGroup
│ │
│ ┌─ 指定對象(僅「指定對象」選中時展開) ──────────┐ │
│ │ [輸入 email 加入........] [加入] │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ alice@corp.com 可檢視+下載 [✕] │ │ │
│ │ │ bob@corp.com 可檢視+下載 [✕] │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ ⚠ 公開後,所有使用者都能下載此模型(若允許下載) │ ← public 選中時的提示
├──────────────────────────────────────────────────┤
│ [取消] [儲存變更] │
└──────────────────────────────────────────────────┘
元件組成(全部沿用既有 shadcn 元件):
- 三態選擇:
RadioGroup(🔷 若 components.md 未列 RadioGroup,需 Architect / Frontend 確認 shadcn 是否已有,或用Select降級)。 - 圖示:
Lock/Globe/Users(與列表 badge 同圖示,維持一致性)。 - 指定對象加入:
Input(email)+Button(加入)。email 格式即時驗證(失焦時),錯誤走既有aria-invalid+border-destructive樣式。 - 對象清單:每列 = email + 權限標籤(Phase 0 固定「可檢視+下載」,🔶 A4)+ 移除鈕(
ghosticonX)。 - public 警告:選 public 時顯示
bg-amber-50 dark:bg-amber-950/30提示條(沿用 §2.1 半語義約定)。 - 底部:
[取消](variant=outline)+[儲存變更](variant=default,loading 時 Spinner)。
🔶 待 PM 確認:
- 「指定對象」若 Phase 0 不做,Dialog 降為 private / public 兩選(RadioGroup 兩項,移除展開區),版型不變。
- 權限粒度:Phase 0 是否只有「可檢視+下載」單一權限?還是要分「僅檢視 / 檢視+下載 / 檢視+燒錄」?
5.3 互動與回饋
| 動作 | 回饋 |
|---|---|
| 切換 private→public | 顯示 amber 警告條;儲存前不生效 |
| 加入 email(格式錯) | Input 紅框 + 下方「Email 格式不正確」 |
| 加入 email(不存在的使用者) | 🔷 Architect:後端驗證,回錯時 toast「找不到使用者 {email}」 |
| 加入重複 email | Input 提示「已在清單中」,不重複加入 |
| 儲存成功 | 關 Dialog + toast「已更新公開設定」+ 列表 / 卡片 badge 即時更新 |
| 儲存失敗 | Dialog 內 error banner「儲存失敗,請重試」,不關閉 |
| public→private(曾共享給人) | AlertDialog 二次確認「改為私有後,已共享的對象將無法再存取,確定?」 |
5.4 UX Writing(本功能新增文案)
| key | 繁中 | English |
|---|---|---|
models.visibility.title |
公開設定 | Visibility |
models.visibility.question |
誰可以看到並使用這個模型? | Who can access this model? |
models.visibility.private |
私有 | Private |
models.visibility.private.desc |
只有你自己 | Only you |
models.visibility.public |
公開 | Public |
models.visibility.public.desc |
所有 visionA 使用者 | All visionA users |
models.visibility.shared |
指定對象 | Specific people |
models.visibility.shared.desc |
只有你選的人 | Only people you choose |
models.visibility.addEmail |
輸入 email 加入 | Add by email |
models.visibility.publicWarning |
公開後,所有使用者都能下載此模型 | Once public, anyone can download this model |
models.visibility.saved |
已更新公開設定 | Visibility updated |
models.visibility.emailInvalid |
Email 格式不正確 | Invalid email format |
models.visibility.emailDuplicate |
已在清單中 | Already in the list |
models.visibility.userNotFound |
找不到使用者 {email} | User {email} not found |
models.visibility.revokeConfirm |
改為私有後,已共享的對象將無法再存取,確定? | Setting to private revokes access for shared users. Continue? |
models.sharedBy |
由 {email} 共享 | Shared by {email} |
6. 模型 profile 頁設計(擴充 /models/[id])
6.1 設計取捨:擴充既有 detail,依身份切兩態
決策:不另建路由,沿用 /models/[id] + ModelDetailClient,依 model.isOwner(🔷 Architect 提供)分支渲染。理由:
- 既有 detail 頁已有完整資訊展示(描述 / 大小 / framework / inputShape / classes / checksum),共享 profile 需要的資訊 90% 重疊,重畫浪費。
- 唯一差異是「操作區權限」與「擁有者資訊」,用條件渲染即可。
🔷 Architect 確認 A5:若未來要「分享連結給未登入者 / 站外」,才需獨立 public 路由
/m/[shareId](免登入、SEO 友善)。Phase 0 假設僅站內登入使用者可見,沿用/models/[id]即可。若需求包含站外分享連結,請 PM 明確,會影響是否要新路由。
6.2 兩態差異表
| 區塊 | owner 版(既有) | 公開 / 共享版(新增分支) |
|---|---|---|
| 返回鈕 | ← 返回(回 /models) |
同 |
| 標題 + badge 列 | name + targetChip + status + source | + visibility badge(公開 / 共享) |
| 擁有者資訊列(新增) | 不顯示(自己就是 owner) | 顯示:由 {ownerEmail} 共享 · {time} + owner 頭像(首字母圓形,沿用 UserMenu avatar 樣式) |
| 操作列 | 下載 + 刪除 + 【新增】公開設定 | 僅下載(若 A4 允許);隱藏刪除 / 公開設定 |
| 描述 / metadata 卡片 | 完整 | 完整(唯讀,相同) |
| classes 區塊 | 完整 | 完整(唯讀) |
| 燒錄至裝置(未來 F7+) | 列出自己在線裝置 | 同(共享模型也能燒錄到自己的裝置) |
6.3 公開版 profile 版型
┌──────────────────────────────────────────────────────┐
│ ← 返回 │
│ │
│ ResNet50-KL720 👥 共享給我 │ ← 標題 + visibility badge
│ [KL720] [就緒] [轉檔] │ ← 既有 badge 列
│ [⬇ 下載] │ ← 僅下載(無刪除/公開設定)
│ ┌──────────────────────────────────────────────────┐│
│ │ 👤 由 alice@corp.com 共享 · 3 天前 ││ ← 擁有者資訊列(新增)
│ └──────────────────────────────────────────────────┘│
│ │
│ ┌─ 模型描述 ─────────────────────────────────────┐ │ ← 既有卡片,唯讀
│ │ 一般物件偵測模型... │ │
│ │ 大小: 24.3 MB 建立: 2026/07/20 │ │
│ │ Framework: onnx Input: 1×3×224×224 │ │
│ │ Classes (80): [person][car][dog] +77 │ │
│ └────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
6.4 擁有者資訊列規格(新增小元件 ModelOwnerBar)
- 容器:
flex items-center gap-2+bg-muted/50 rounded-md px-3 py-2 text-sm - 頭像:40px→改 24px(
h-6 w-6 rounded-full)圓形,email 首字母,沿用 UserMenu avatar 配色 - 文字:
由 {ownerEmail} 共享 · {relativeTime}(相對時間 util 沿用 RemoteDeviceBadge) - 僅在非 owner 檢視時渲染
- 無障礙:
aria-label="模型擁有者資訊"
7. 各狀態設計(空 / 載入 / 無權限 / 無結果)
沿用既有 EmptyState / Skeleton / toast,文案走本功能語氣。
| 狀態 | 觸發 | 呈現 | 文案 |
|---|---|---|---|
| 載入中 | 首次載入 / 換頁 / 搜尋 | 既有 Skeleton 卡片網格(8 個) |
— |
| 空 · 共享給我的(無) | 「共享給我的」區無資料 | EmptyState icon=Users |
標題「還沒有人共享模型給你」/ 描述「當同事把模型共享給你時,會出現在這裡」 |
| 空 · 公開(無) | 公開區無資料 | 精簡 inline 空狀態(沿用區內空狀態樣式) | 「目前沒有公開的模型」 |
| 搜尋無結果 | 搜尋 query 無 match | EmptyState icon=SearchX + [清除搜尋] CTA |
標題「找不到符合『{query}』的模型」/ 描述「試試其他關鍵字或清除篩選」 |
| 無權限 | 直接開別人私有模型的 /models/[id] |
全頁 EmptyState icon=Lock + [返回模型庫] |
標題「沒有權限檢視此模型」/ 描述「這個模型未公開或未共享給你」 |
| 公開設定儲存失敗 | API 錯 | Dialog 內 error banner | 「儲存失敗,請重試」 |
| 載入更多失敗 | 分頁 API 錯 | 「載入更多」按鈕轉為 [重試] + toast |
「載入失敗,點擊重試」 |
無權限狀態(/models/[id] 403)版型:
┌──────────────────────────────────────┐
│ ← 返回 │
│ │
│ 🔒 │
│ 沒有權限檢視此模型 │
│ 這個模型未公開或未共享給你 │
│ │
│ [ 返回模型庫 ] │
└──────────────────────────────────────┘
🔷 Architect:403 vs 404 的取捨——為避免「模型是否存在」的資訊洩漏,建議私有模型對無權限者回 404(當作不存在),UI 走「找不到模型」而非「無權限」。請 Architect 確認採 403 揭露存在 or 404 隱藏存在,UI 兩版文案我都備。
8. 響應式(沿用既有斷點)
沿用 pages.md §11 的斷點與 /models 既有規則(Mobile 單欄 / Tablet 2 欄 / Desktop 3–4 欄)。本功能新增元素的響應式:
| 元素 | Mobile (<640) | Tablet (640–1024) | Desktop (≥1024) |
|---|---|---|---|
| 檢視模式 Tabs | 全寬 2 等分 | 同 | 靠左自然寬 |
| 篩選 / 搜尋 / 排序列 | 堆疊(搜尋佔滿寬一行 + 篩選鈕 wrap 下一行) | 部分同行 wrap | 單行 |
| visibility badge | 顯示(badge 列 flex-wrap 既有) |
同 | 同 |
| 擁有者資訊列 | 全寬,email 過長 truncate |
同 | 同 |
| 公開設定 Dialog | max-w-[calc(100vw-2rem)],對象清單可捲動 |
max-w-lg |
max-w-lg |
| 分頁「載入更多」 | 全寬按鈕 | 置中 | 置中 |
| 頁碼(P2) | 精簡(僅 ‹ 頁 X/Y › ) | 完整頁碼 | 完整頁碼 |
9. 無障礙(沿用既有 + 本功能新增)
- visibility badge:圖示(
aria-hidden)+ 文字雙編碼,不僅靠顏色(De1)。SR 讀得到「公開」「已共享」文字。 - 檢視模式 Tabs:Radix Tabs 內建
role="tablist"+ Arrow 鍵導航 +aria-selected。 - 公開設定 RadioGroup:Arrow 鍵切換選項、
aria-checked、每選項有可見 label。 - email 加入:
Inputaria-label;加入成功後焦點回 input 便於連續加入;對象清單移除鈕aria-label="移除 {email}"。 - 搜尋框:
role="searchbox";無結果aria-live="polite"播報「找到 0 個模型」。 - 載入更多:
aria-label含當前 / 總數「載入更多,已顯示 24 之 87」。 - 狀態改變(儲存 / 共享):toast 走既有 Sonner(
aria-live內建)。 - 觸控目標:所有新增互動元素(
⋮選單鈕、移除鈕、Tab、清除鈕)≥ 44×44px(⋮用iconsize = 36px 需注意,建議 profile / 卡片上用size=icon但外圍點擊區補到 44px,或用既有 button 慣例)。🔷 Frontend 實作注意。 - 對比度:所有新 badge 用既有
chart-*token tint 風格(/10底 + 純色文字),與既有 source badge 同做法,既有已通過 WCAG AA。Dark Mode 由 token 自動處理。
Dark Mode:本功能不新增顏色,全用既有 token(
chart-1/2/3、muted、amber-*半語義),Dark Mode 自動生效。無需獨立 Dark 版設計。(本任務 A 層 Dark Mode 截圖延到 B 層 / 實作期補,因為零新 token、純沿用。)
10. 沿用 vs 新增總表
10.1 沿用既有(不改)
| 既有資產 | 用途 |
|---|---|
| Design Tokens 全部 | 零新增 |
ModelGrid |
卡片網格 + skeleton + 空狀態(分頁時擴充「載入更多」) |
ModelSection |
分區色點 + 標題 + 計數(共享關係分區沿用) |
Card / Badge / Button / Dialog / AlertDialog / Select / Input / Tabs / EmptyState / Skeleton / Sonner |
全部 |
RemoteDeviceBadge 的相對時間 util |
共享時間 / owner 資訊列 |
| UserMenu avatar 樣式 | owner 頭像 |
| §2.1 amber 半語義 | public 警告條 |
10.2 新增(Design 定義,Frontend 實作)
| 新增 | 類型 | 基底 |
|---|---|---|
ModelViewToggle |
元件 | Tabs |
| visibility badge(含於 ModelCard 擴充) | 元件擴充 | Badge + Lucide Lock/Globe/Users |
ModelCard ⋮ owner 選單 |
元件擴充 | DropdownMenu(🔷 確認 shadcn 已有) |
ModelFilters 共享狀態維度 |
元件擴充 | Select |
| 搜尋框 | 元件擴充 | Input + Search icon |
ModelSortSelect |
元件 | Select |
| 分頁「載入更多」or Pagination | 元件 | Button / 新 Pagination(🔷 A6 二選一) |
ModelVisibilityDialog |
元件 | Dialog + RadioGroup + Input + Button |
ModelOwnerBar |
元件 | Card/div + avatar |
| ModelDetailClient owner/公開雙態分支 | 頁面擴充 | 條件渲染 |
| 無權限 / 搜尋無結果 / 共享空狀態 | 狀態 | EmptyState |
11. 給三方互審的重點清單
需 PM 確認需求細節 🔶
- A1 Visibility 態數:private/public/shared 三態 vs 只 private/public 兩態?「指定對象」Phase 0 要不要做?
- A2 指定對象粒度:個別 email vs 群組/組織/團隊?
- A3 列表分類:「我的 / 公開 / 共享給我的」三分類命名 OK 嗎?要不要「我公開出去的」獨立區?
- A4 共享權限:receiver 能否下載?能否再共享(re-share)?權限是否分「僅檢視 / 檢視+下載 / 檢視+燒錄」?
- A7 搜尋範圍:搜尋只搜「可見的」還是要能「探索全站公開庫」?
- 檢視模式:「依來源」與「依共享關係」兩種 Tab 都保留,還是共享關係取代來源?
- 觸發引導:上傳完成後要不要引導設定公開對象?
需 Architect 確認可行性 🔷
- A5 / 6.1 profile 路由:沿用
/models/[id]雙態 vs 需獨立 public 路由/m/[shareId](站外分享連結)? - A6 分頁機制:後端 cursor(→ P1 載入更多)還 offset(→ P2 頁碼)?搜尋 / 排序在前端還後端?
ModelSummary新欄位:visibility/ownerEmail/sharedAt/sharedCount/isOwner可否由 API 提供?- 7 無權限回應碼:私有模型對無權限者回 403(揭露存在)還 404(隱藏存在)?影響 UI 文案。
- RadioGroup / DropdownMenu:shadcn 元件庫是否已含這兩個?未含則需先補 or 用 Select 降級。
- email 對象驗證:加入指定對象時,後端能否即時驗證使用者存在?
12. Verification(本設計任務自檢)
- De-A1 三斷點:§8 已定義 mobile/tablet/desktop 三斷點行為(純規格 + ASCII 版型;實際截圖於 prototype / 實作期補,本階段為規格文件無渲染產出)。
- De-A2 對比度:零新 token,全沿用既有
chart-*tint +muted+amber半語義,既有已過 WCAG AA(design-tokens.md 已確認)。 - De-A3 無 hardcode:本檔所有色彩引用皆為 token 名(
chart-1/2/3、muted-foreground、amber-50半語義約定),無裸 hex / rgb。 - De-A4 三態覆蓋:§7 已定義空 / 載入 / 無結果 / 無權限 / 失敗多態。
- De-A5 觸控目標:§9 已標註新增互動元素 ≥ 44px 需求 +
⋮鈕注意事項。 - De-B1 互動五狀態 / De-B2 Dark Mode / De-B4 三方互審:延到 milestone(互動狀態沿用既有元件既有態;Dark Mode 零新 token 自動生效;三方互審即本檔 §11 待 PM/Architect 回審)。
- No silent failures:所有 🔶🔷 未定項已明確標「待 PM/Architect 確認」+ 對應假設,無「TBD 無負責人」。
- Doc 同步:本檔為新增;pages.md / components.md 的增補建議見下方回報(本任務未直接改,避免撞名覆蓋,交 Orchestrator 決定增補方式)。