本卡屬 FR-132(母卡 CM-2510),A.5 存取管理前端第 1 張,取代作廢的 CM-2536。依賴:T-3.4(已完成)。後續 T-5.2~T-5.4 都用本卡的元件。建議 model:opus。
新的角色頁不再是「模組 × 動詞」的大矩陣,而是照左側選單的樣子排:先是選單分組(例如「專案稽核」),展開是畫面(例如「專案管理」),再展開是這個畫面上能給的權限(例如「建立專案:新增專案、從範本建立、CSV 匯入」)。管理員勾的時候,右邊即時顯示「被指派這個角色的人登入後會看到哪些選單」。
本卡做這兩塊共用元件,加一支後端端點讓前端能問「這一組權限能看到哪些頁」。角色明細、新增指派對話框、檢查存取三個地方都會用到。
ui_routes 根節點 8 組、子頁 41 頁;route_capabilities 119 筆綁在 38 頁上(ALL 38 筆、ANY 81 筆),每頁至多一顆 ALL=進入該頁的門檻。專案儀表板、我的任務、我的授權狀態三頁沒綁任何權限=登入即可見。is_platform 40 項),其中 66 項非原廠權限沒綁任何頁(多半是 create/delete 空殼與 import/export 等獨立動詞)。~/Projects/Jedicogy/module/jedi-python-package/jedi-iam/jedi_iam/infra/repository/ui_route_repo_impl.py:64 get_viewable_by_capability_names(ANY 命中任一、或 ALL 全有、或無規則即可見),經 ui_route_domain_service.py:70 get_viewable_routes_by_capability_names;側欄 /user/web-menu(user_service.py:515)就是走這條,再交 hooks.web_menu_postprocess 濾未授權模組。api/routing.py:113-128 只有 /ui-routes(整棵樹,守 iam.role.read,api/routes/ui_route_route.py:9-50)與 /user/web-menu(只算登入者本人)。/ui-routes 回的每頁帶 route_capabilities[](capability{id,name,display_name,module,resource_type,action,is_platform}、requirement、is_licensed),api/serializers/ui_route.py:3-27——樹的資料源就用它,不用另開。~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/views/role-manage/RoleForm.vue:41-54,171-180)、未授權模組反灰附原因(RoleForm.vue:231-256 的 isRcLicensed)、矩陣本體 RoleForm.vue:456-516。docs/features/FR-132-2610-access-management/mockup/role-detail-v3.html 定稿:樹(左)與可見選單卡(右)長相
~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/views/role-manage/RoleForm.vue (605 行) 現有矩陣,可抽判斷邏輯,畫面不沿用
~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/config/api/api.js:29-32,45,481 ROLES/ROLE/ROLE_STATUS/UI_ROUTES/ROLE_MENU/CAPABILITIES_MENU 常數
~/Projects/Jedicogy/module/jedi-python-package/jedi-iam/jedi_iam/api/routing.py:113-128 新端點掛這裡
~/Projects/Jedicogy/module/jedi-python-package/jedi-iam/jedi_iam/api/routes/ui_route_route.py 新 Resource 放同檔或新檔
~/Projects/Jedicogy/module/jedi-python-package/jedi-iam/jedi_iam/domain/service/ui_route_domain_service.py:70 get_viewable_routes_by_capability_names
~/Projects/Jedicogy/module/jedi-python-package/jedi-iam/jedi_iam/domain/service/capability_expansion_service.py:50,61 expand/expand_roles(角色 uid → 展開後權限)
POST /api/1.0/ui-routes/visible-by-capabilities(jedi-iam):body {capability_names?: [...], role_uids?: [...], tenant_id?: int},兩者可並用(取聯集;role_uids 走 CapabilityExpansionService.expand_roles 展開)。回可見頁的扁平清單 [{id, pid, name, url}],判定只呼叫既有 get_viewable_routes_by_capability_names,再套 hooks.web_menu_postprocess/ui_routes_postprocess 同一份 license 過濾,不另寫查詢(另寫=第二套真相)。掛 @auth_required + @capability_required("iam.role.read")。T-5.2 的列表「可見頁面數」與 T-5.3 的對話框預覽都用它。路徑也要登記到 routing.py 尾端的 route 清單與 BE test/security/code/test_route_guard_inventory.py(若該守衛測試要求)。PermissionTree.vue(建議放 src/components/access/):props routes(/ui-routes 樹)、modelValue(已勾權限 id 的 Set)、capabilities(/capabilities/menu 全清單)、readonly、tenantIsRoot;emit update:modelValue。主視角「依功能選單」三層:分組 › 畫面 › 權限,每項一行「動作名+涵蓋哪些操作」(顯示名走 i18n);ALL 那顆標「進入此頁所需」。route_capabilities 綁在該頁的;② 沒綁任何頁的,跟同一個「模組.資源」已綁的那頁走(綁多頁時取它 read 當 ALL 的那頁);③ 資源名帶連字號的(grc.job-comment)找前綴資源(grc.job)所在頁;④ 都找不到的放最後一組「其他動作」。首腦用 DEV 實算:206 項中 167 項放進畫面、39 項進「其他動作」(SSP、證據分類、AI 服務設定、AI 小幫手、系統設定、原廠類)。把這段做成純函式(例 src/composables/usePermissionGrouping.js),樹與「依資源」視角共用。aria-checked 帶 mixed);畫面列另有「只給檢視」一鍵只勾 ALL 門檻項;工具列「全部展開 | 全部收合」與「依功能選單 | 依資源」切換(SelectButton,記得 :unselectable="false")。「依資源」視角=模組 › 資源列 × 動詞欄矩陣,跟主視角吃同一個 modelValue。未授權權限反灰不可勾、v-tooltip 給原因;非 root 租戶角色時原廠權限不出現。版面用 PrimeVue TreeTable 或 DataTable+Checkbox(:binary),不手刻 div 樹。VisibleMenuPreview.vue:props routes、visibleIds、readonly;照選單分組列 41 頁,可見綠點(--color-green)、不可見灰點(--text-muted)+「加入」文字按鈕(emit add-gate(routeId),由父層勾該頁 ALL 項);分組可收合並顯示「可見 N / M」,標題旁「展開 | 收合」;License 授權管理頁標「原廠管理員專用」不給加入;底部說明「另有 N 個頁面登入即可見,不受角色影響」。另支援 diff 模式給 T-5.3 對話框用:baseIds(目前就有,灰字)+visibleIds(加上後)→ 新增的綠色加號。勾選變動時用 debounce(約 300ms)呼叫 ① 端點。