本卡屬 FR-182(母卡 CM-3609 https://app.notion.com/p/FR-182-Agent-Agent-P1-License-Center-4-3-410346da4cd0816ea5e2c4757ebc4fbb),P2 Agent 端,卡 P2-3,Stage 4(P2 第一批,接在 P1 的批 1~3 之後;P1 LC 端 CM-3610~3613 已 Done 並上 189)。只改 FE(主控台 console/)。依賴:無(同批 P2-1/P2-2/P2-3 平行;P2-2 的 gate 介面以 P2-1 為準,合回後對一次)。
主控台側欄多一個「授權」分頁,給客戶看這台 Agent 的授權狀態、抄機器碼、上傳原廠回寄的照。五種狀態各一個樣子(對照雛形 prototype/agent-console-license.html 場景 1~6):尚未開通(紅標+四步驟說明+機器碼可複製+拖拉上傳區)、已授權(綠標+照資訊+換照區)、到期提醒(黃色一句)、寬限期(紅色一句、剩幾天)、已過期(同尚未開通但說明是過期)、上傳的照是別台的(紅框講綁的是哪台前 12 碼、本機是哪台)。總覽頁頂端在到期提醒/寬限期時顯示一列提醒+「前往授權」。照主控台既有頁(Keys.vue)的樣子刻:dark-card、全站字級、不自訂字型、禁左側粗邊框、資料上下疊不左右排。
new:console/views/License.vue(照雛形 prototype/agent-console-license.html 場景 1~6 的結構,用 Keys.vue 的 dark-card/欄位元件,不自訂字級字型、不用左側粗邊框):狀態 Tag(尚未開通 danger/已授權 ok/到期提醒 warn/寬限期 danger/已過期 danger)、四步驟說明(只在尚未開通/已過期時顯示)、機器碼 <code> 全碼+「複製」鈕(用 navigator.clipboard 要 fallback——主控台常是 http+IP,clipboard 在非 secure context 是 undefined,照 memory 用 document.execCommand('copy') 退路)、照資訊 kv、拖拉上傳區(接受 .license,FileReader 讀文字 POST)、拒收原因紅框(wrong_type/bad_signature/mismatch+綁定前綴/expired/malformed 各一句 i18n);console/licenseApi.js(照 keysApi.js 兩支);console/licenseI18n.js+src/config/locales/i18n/zh-tw/agent-console-license.json、en/agent-console-license.json。extend:console/router.js PAGES 加 { name: 'license', group: 'ops', icon: 'pi pi-id-card', view: 'License', scope: null, dimOn: [] }(任何連線狀態都開——沒照時 NET 會是 unsynced);console/views/Overview.vue 頂端照 overview.license 顯示提醒列(notice 黃、grace/expired 紅,一句+「前往授權」連結);console/Shell.vue 不動(側欄讀 PAGES)。npm run build:CONSOLE。
repo:~/Projects/Billows/Audit-Manager/compliance-manager-fe
改既有:console/router.js(PAGES 加一項)
改既有:console/views/Overview.vue(頂端提醒列)
新開:console/views/License.vue
新開:console/licenseApi.js
新開:console/licenseI18n.js
新開:src/config/locales/i18n/zh-tw/agent-console-license.json
新開:src/config/locales/i18n/en/agent-console-license.json
CLAUDE.md、BE docs/claude/frontend-overview.md §3(設計系統)與 §3.6 PrimeVue 雷區;console/views/Keys.vue(版面與元件範本)、console/keysApi.js、console/keysI18n.js、console/router.js(PAGES 清單與 scope/dimOn 語意)、console/views/Overview.vue(頂端怎麼放提醒列);雛形 ~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/prototype/agent-console-license.html 六場景(結構不是像素);guidant-design-system skill;memory feedback_secure_context_only_browser_apis_break_on_http_ip(clipboard 在 http+IP 是 undefined)。console/licenseApi.js:get: () => request('GET', '/api/license')、upload: (text) => request('POST', '/api/license/upload', text, { headers: { 'Content-Type': 'text/plain' } })(request 若只收 JSON,看 console/api.js 加 raw body 支援或改用 FormData——選一個,不要兩套)。console/views/License.vue:onMounted 拉 GET;版面由上到下:狀態卡(Tag+一句說明;missing/expired 時下面接四步驟 steps,照雛形)→ 機器碼卡(<code> 64 碼 word-break+「複製」:navigator.clipboard?.writeText 失敗或不存在 → 建隱藏 textarea select()+document.execCommand('copy'),成功 toast)→ 照資訊卡(valid/notice/grace 才顯示:照號、客戶、型態、到期日+剩幾天、綁定機器碼前 12 碼+「與本機一致 ✓」、開通時間、簽章鑰 kid)→ 上傳卡(標題依狀態「上傳授權照」/「換照」;拖拉區接受 .license,FileReader.readAsText → upload;成功重拉 GET+toast;400 → 紅框一句:reason 對 i18n lang.agent_console_license.reject.<reason>,mismatch 那句插 bound_fingerprint_prefix 與本機前 12 碼)。資料區塊上下疊、不左右兩欄;不自訂字級字型;禁 border-left。console/router.js PAGES:在 keys 之後加 { name: 'license', group: 'ops', icon: 'pi pi-id-card', view: 'License', scope: null, dimOn: [] }。console/views/Overview.vue:若 overview.license?.status 是 notice → 黃色一列「授權 N 天後到期(YYYY-MM-DD),請洽原廠續約」+router-link 到 /license;grace/expired → 紅色一列。用既有提醒元件(grep Overview 裡 unsynced 的提示怎麼做,同一個)。licenseI18n.js 照 keysI18n.js 註冊 agent-console-license.json(zh-tw、en 兩份);鍵:title、status.<missing|invalid|mismatch|valid|notice|grace|expired>、steps.1~4、machine_code、copy、copied、upload.title、upload.replace、upload.hint、reject.<wrong_type|bad_signature|mismatch|expired|malformed|unbound>、overview.notice、overview.grace、overview.expired。中文不要晶晶體、不要「輪廓」「一句話」這種空殼詞。navigator.clipboard 設 undefined 時 execCommand 被呼叫。npm run build:CONSOLE、npm run lint。npm run build:CONSOLE 綠、npm run lint 無新 error、grep -rn border-left console/views/License.vue 為 0;對照雛形六場景:mock API 回五種 status 各截一張(headless Playwright 或 vitest 快照,不開視窗);http+IP 環境下「複製」鈕有效(fallback 路徑有測);上傳假檔後顯示後端回的 reason 句子;總覽頁 notice/grace 各顯示一列。主控台靜態檔換法見 FR-166.1 STATE §4(本機 ~/guidant-agent-local),P2-1/P2-2 合回後對本機 Agent 實走:無照 → 看到機器碼 → 用 LC CLI 簽綁本機的照 → 拖上去 → 變已授權、側欄其他分頁從反灰恢復
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/design.md(D6 不擋啟動但不起 sync、D8 用既有 integrity 驗章、§4.2 照 payload、§4.8 Agent 端);討論稿 ~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/discussion.md §2.2 Agent 端盤點、§2.4 與 FR-181/FR-179 接點、§3.7 狀態表