---
title: FR-164 專案總覽控制項視圖重設計：設計
status: 定案（2026-10-25 決策者核可雛形第三版＋三筆修正）
---

# FR-164 專案總覽「控制項視圖」重設計

## 一句話

專案總覽頁的控制項視圖整個重排：左邊導航三層都能點（群組／控制項／評估目標），右邊固定兩塊——上面「參考資料」只讀（條文、現況說明、備註、參考程序書），下面「任務」是唯一可操作的地方、永遠一張平表、一列一個任務；三塊都可拖曳調整大小。原有功能一個不少。

## 為什麼

使用者反應：看不出哪裡可以操作；左邊導航點不到評估目標；資料東一塊西一塊。實查現況（`ProjectAuditorOverview.vue:1406-2025`）：

- 左樹只到控制項。評估目標要去右邊展開控制項卡、再展開評估目標卡，任務藏在第三層。
- 右邊是「卡片包卡片」：控制項卡 → 現況說明摺疊 → 評估目標卡 → 任務列。每層都像資訊，沒有固定的「這裡可以點」位置。
- 條文、現況說明、評估目標、任務是同一件事的脈絡，卻散在三種深度。

## 決策

| # | 決策 | 理由 | 被排除 |
|---|---|---|---|
| D1 | **左導航三層都可點**（群組／控制項／評估目標），**沿用 FR-163 的 `EvidenceNavTree`**（同一棵資料、同一套視覺）加 prop，不再刻第八棵樹 | 證據視圖已經有一棵三層樹，決策者明示「導航可以用同一模式」；memory `feedback_fe_nav_tree_rewritten_per_page_reuse_first`：重刻＝舊 bug 重長。`ApObjectiveTree` 透過 inject 綁死在稽核計畫頁的資料模型，無法直接搬 | 再刻一棵；用 `ApObjectiveTree` |
| D2 | **右邊固定上下兩塊，不再巢狀**：上「參考資料」只讀、下「任務」唯一可操作 | 決策者原話「看不出來是可以操作的區塊」；把「看」與「做」分成兩塊，可操作的東西只會出現在任務表裡（每列有「執行」／「開啟」鈕，分群小標列上有「標記已審閱」） | 左右並排（決策者選上下） |
| D3 | **任務表永遠一張平表、一列一個任務，表內沒有任何展開收合**；層級只存在左導航 | 雛形第二版做成「控制項卡→評估目標列→任務」三層收合，決策者一眼看穿「跟原本一樣」。照證據視圖（FR-163 D2）到底 | 任何形式的手風琴 |
| D4 | **「分群」（group by）跟著選取層走**：選群組預設「依控制項」、選控制項預設「依評估目標」、選評估目標不分群；使用者改過就記住該層的選擇。分群只在同一張表插小標列 | 決策者裁示預設值；用詞「分群」不用「群組」（這頁的「群組」已是控制項群組） | 預設不分群 |
| D5 | **位置欄**（控制項編號＋評估目標編號＋條文）**完整換行呈現，不截斷**；依評估目標分群時此欄不重印（小標列已寫）；選到評估目標時此欄不顯示 | 決策者原話「這邊要看得到東西才好做事」 | 省略號＋tooltip |
| D6 | **審閱鈕的位置**：分群時長在每條小標列（控制項小標＝控制項審閱、評估目標小標＝評估目標審閱）；不分群時在任務區標題列右側、只對左邊選到的那一層（群組層沒有審閱動作） | 審閱是對「控制項／評估目標」的動作，不是對任務；放在代表該層的那一列 | 放回參考資料區 |
| D7 | **表內不放「只看這條」跳左樹**的連結 | 決策者：換範圍一律從左邊點 | — |
| D8 | **左右可拖曳**：PrimeVue `Splitter`（照 `RoundEvidenceView.vue:97-116`）、`state-key` 記 `localStorage`。**右欄參考資料高度：預設自適應（跟著內容高、上限佔右欄七成、超過才在面板內捲）；拖上下分隔線後改固定成拖的高度並記住；標題列「恢復自動」清掉回自適應**；參考資料可整塊收起只留標題列（收起時分隔線不可拖）。上下分隔線自畫（PrimeVue Splitter 掛載後改不動 size、也做不到自動） | 決策者 2026-10-26 兩度裁示：先「要自適應」、再「兩個都要」；評估目標層條文長，純固定高不夠用 | 純上下 Splitter（第一版，被退）；純自適應不可拖（第二版，被退） |
| D9 | **資料不開新端點**：全部沿用總覽頁已載入的 `groups`／`controlsMap`／`controlDetailMap`／`sspDescriptions`／`sspStatuses`／`sspRemarks`／`controlReferenceDocuments`／`controlReviewMap`／`aoReviewMap`，以及既有的 `fetchControls`／`fetchControlDetail`／`fetchSspDetail`／`toggleReviewed`／`toggleAoReviewed`／`openJobDrawer` | 這次是 UI 重排，BE 行為不變；只是把資料改個方式畫出來 | 新彙總端點 |
| D10 | **新視圖寫在新子元件** `src/components/grc/control-view/`，總覽頁只留掛載與資料透傳；舊的右側面板整段（`:1406-2025`）刪除 | 總覽頁已 2,121 行（上限 800），往裡加是違規；刪舊段還能減量 | 原地改 |

## 畫面（以雛形為準）

雛形：`prototype/index.html`（決策者 2026-10-25 核可第三版＋「位置欄不截斷」「分群預設」「改名分群」三筆）。**雛形只取結構、資訊順序與行為，不取字級、字型、配色**——FE 一律 `dark-card`＋全站字級＋design tokens。

```
┌ 控制項導航 [控制項視圖|證據視圖] ┐┌ 參考資料  只讀·條文與現況      路徑  [收起] ┐
│ 搜尋                             ││ 代號  名稱                          狀態  │
│ [我的待辦]      全部展開 全部收合 ││ 統計：N 評估目標 · k/n 任務完成 · 進度   │
│ ▾ 群組 ⚡ ━━ 38%                ││ 控制項要求（條文）│ 控制項現況說明 [狀態] │
│   ▾ 控制項 ⚡ ✎ ✓ ━━ 0%        ││                   │ 現況描述／備註／程序書 │
│     [a] 評估目標 ⚡ ✓ 0/1       │├────────── 可拖 ──────────────────────────┤
│     [b] 評估目標     0/1        ││ 任務 k/n 已完成 · m 待我執行               │
│   ▸ 控制項 ...                   ││ 篩選[全部|待我執行|未完成|已完成] 分群[…]  │
│ ▸ 群組 ...                       ││ 任務 │ 位置 │ 負責人 │ 證據 │ 狀態 │     │
│                                  ││ ── CRA.I.1 名稱  0/2 ●進行中 [標記已審閱] │
│ 圖例：⚡待執行 ✓已審閱 ✎現況未填 ││ ○ 任務名  CRA.I.1 [a] 條文全文… 👤 📎2 ●進行中 [⚡執行] │
└──────────────────────────────────┘└───────────────────────────────────────────┘
          ↑ 可拖
```

### 左欄：導航（沿用 `EvidenceNavTree`，加 prop）

- 三層節點列：代號徽章（群組實心淡底、控制項外框、評估目標 `[a]` 小字）＋名稱（最多兩行）＋列尾。
- 列尾依視圖不同：證據視圖是「N 份」；**控制項視圖是進度條＋％**（群組、控制項）／「k/n」（評估目標）。
- 列中徽章（控制項視圖才有）：⚡ 有待執行任務（`jobIsExecutable`，脈動圓點，三層都有）；✓ 已審閱（`controlReviewMap`／`aoReviewMap`）；✎ 規劃期現況說明未填（`isPlanningPhase && !ctrlHasSspDesc`，控制項層）。
- 標題列：「控制項導航」＋ `ViewModeSwitch`（已在，FR-163.6）。
- 工具列：搜尋（沿用）、**「我的待辦」開關**（沿用 `showMyTasksOnly`：開了左樹只留有待執行任務的群組／控制項／評估目標，右表也只留）、全部展開／收合（沿用）。
- 底部圖例：⚡／✓／✎ 三個符號各一句。
- 點控制項時順便展開它的評估目標；點評估目標時展開上層。

### 右上：參考資料（新 `ControlReferencePane.vue`）

- 標題列：「參考資料」＋副標「只讀・條文與現況」＋右側路徑（群組 ／ 控制項 ／ [a]）＋「收起」鈕（收起只留標題列，狀態記 `localStorage`）。
- 選**群組**：代號＋名稱＋群組描述；統計列：控制項數、評估目標數、k/n 任務完成、k/n 已審閱、規劃期多一個「k/n 現況已填」（`sspGroupStats`）。
- 選**控制項**：代號＋名稱＋狀態徽章（`ctrlStatusFromAos`）；統計：評估目標數、k/n 任務完成、進度；依序上下疊：「控制項要求」（`ctrl.description`）、「控制項現況說明」（`SspStatusTag` 狀態、`sspDescriptions`、`sspRemarks`、`ReferenceDocumentList` readonly）；**不排左右兩欄**（決策者 2026-10-26「永遠不要左右」）——資料用既有 `fetchSspDetail(controlId)`。
- 選**評估目標**：控制項代號＋名稱小字＋ `[a]`＋狀態徽章（`aoStatusFromAo`）；依序上下疊：「評估目標」（`ao.title`）、「評估目標現況」（`sspDescriptions[ao.id]`／`sspStatuses[ao.id]`，有才顯示）、控制項現況說明（同上）。
- 這塊**沒有任何按鈕**（收起除外）。

### 右下：任務（新 `ControlTaskTable.vue`＋ `useControlTaskRows.js`）

- 標題列：「任務」＋「k/n 已完成 · m 待我執行」（m 橘字，0 不顯示）＋篩選 `全部｜待我執行｜未完成｜已完成`＋分群（D4；選評估目標時不顯示）＋不分群時的審閱鈕（D6）。
- 表格（`DataTable` `p-datatable-sm`，分群用 `rowGroupMode="subheader"`，照 `EvidenceTable.vue`）：

| 欄 | 內容 |
|---|---|
| 任務 | 狀態圓圈（完成實心綠、未完成空心）＋任務名（連結色） |
| 位置 | 選群組：`控制項代號 [a] 條文全文`；選控制項：`[a] 條文全文`；依評估目標分群或選評估目標：不顯示（D5） |
| 負責人 | `UserAvatar` 最多兩個＋「+N」；單人顯示名字 |
| 證據 | 📎 N（0 灰字）＋ `SourceBadge AI_CLASSIFIED`（`hasAiEvidence`） |
| 狀態 | `StatusBadge`（TODO／PROCESSING／COMPLETED） |
| 操作 | `jobIsExecutable` 且非唯讀：「⚡ 執行」實心橘鈕；否則「開啟 ›」外框鈕。兩者都開 `openJobDrawer`（抽屜內才分執行／檢視） |

- 分群小標列：控制項小標＝代號＋名稱＋⚡＋k/n＋狀態徽章＋審閱鈕；評估目標小標＝`[a]`＋條文全文（換行）＋⚡＋k/n＋狀態小點＋審閱鈕（icon 版）。小標列不可點。
- 無任務的評估目標在分群模式出一列灰字「尚無任務」；篩選後沒命中出「沒有符合篩選的任務」。
- 列點擊＝`openJobDrawer(job, ctx)`，ctx 照總覽頁現有簽章（groupId／controlId／aoId／groupCode／controlCode／aoName／workflowExecutionUid）；沒 `grc.job.read` 能力點不接點擊（照 `AoJobSection.vue:34-36`）。
- 審閱鈕規則照舊：`canReviewControl` 才顯示；未完成不能標（tooltip「完成後才可標記已審閱」）；已審閱只有本人能取消（`canUnreview`，tooltip「只有審閱者本人可取消審閱」）；結案輪次整顆反灰（`writeDisabled`／`readonlyReason`）；loading 用 `reviewLoading`。
- 一格一值、不用進度條（memory `feedback_table_one_value_per_cell_and_side_by_side_colors`）；任務表內**不放進度條**，進度只在左樹與參考資料統計列。

### 保留功能對照（逐條對 `ProjectAuditorOverview.vue` 現況）

| 現況功能 | 新位置 |
|---|---|
| 搜尋階層 | 左欄工具列（沿用） |
| 我的待辦開關 | 左欄工具列；過濾左樹＋右表 |
| 全部展開／收合 | 左欄工具列 |
| 群組／控制項進度％ | 左樹列尾＋參考資料統計列 |
| 待執行閃電（群組／控制項／評估目標／任務） | 左樹三層＋任務表小標列＋任務列「執行」鈕 |
| 規劃期現況未填提示 | 左樹控制項列 ✎ ＋參考資料群組層「k/n 現況已填」 |
| 已審閱勾 | 左樹（控制項／評估目標） |
| 標記／取消審閱（控制項、評估目標） | 任務表小標列（分群）／任務區標題列（不分群） |
| 控制項現況說明（實作狀態、現況描述、備註、參考程序書） | 參考資料右欄 |
| 評估目標現況 | 參考資料（選評估目標時） |
| 任務列（負責人、證據數、AI 徽章、狀態、開抽屜） | 任務表 |
| 結案輪次唯讀反灰 | 審閱鈕、執行鈕 |
| 視圖切換鈕 | 左欄標題列（已在） |
| 空狀態「請從左側選擇」 | 不再需要：進頁預選第一個群組（照 `RoundEvidenceView.vue:33-36`） |

## 資料

全部沿用總覽頁已有的 state 與函式（D9），不動 BE。需要透傳給子元件的：

- 資料：`groups`、`controlsMap`、`controlDetailMap`、`controlsLoadingSet`、`controlDetailLoadingSet`、`sspDescriptions`、`sspStatuses`、`sspRemarks`、`controlReferenceDocuments`、`sspDetailLoading`、`controlReviewMap`、`aoReviewMap`、`reviewLoading`、`isPlanningPhase`、`isApClosed`、`readonlyReason`、`userInfo`。
- 函式：`fetchControls`、`fetchControlDetail`、`fetchSspDetail`、`toggleReviewed`、`toggleAoReviewed`、`canReviewControl`、`canUnreview`、`reviewersTooltip`、`writeDisabled`、`jobIsExecutable`、`hasAiEvidence`、`openJobDrawer`。
- 這些現在散在總覽頁 `<script>` 裡。實作時用 `provide/inject` 一次給整棵子元件（key 放 `src/composables/useControlView.js`），避免二十個 prop 往下傳。

## 拆卡

| 批 | 卡 | 做什麼 | Repo |
|---|---|---|---|
| 1 | FR-164.1 | 導航樹抽共用：`EvidenceNavTree` 加 `mode` prop（`evidence`／`control`），控制項視圖模式列尾顯示進度與 ⚡／✓／✎ 徽章、底部圖例、「我的待辦」開關；證據視圖行為不變 | fe |
| 1 | FR-164.2 | 右側兩塊：`ControlReferencePane`（參考資料）＋ `ControlTaskTable`＋`useControlTaskRows`（任務平表、分群、篩選、審閱鈕）；用 provide/inject 接總覽頁資料 | fe |
| 2 | FR-164.3 | 總覽頁接線：`RoundControlView` 容器（Splitter 左右＋上下）掛上總覽頁、刪舊右側面板段、i18n、跑既有測試、實機對照舊版逐條驗保留功能表 | fe |

批 1 兩張不撞檔（.1 只動 `evidence-view/EvidenceNavTree.vue`，.2 只新增 `control-view/` 下的檔）；.3 才碰 `ProjectAuditorOverview.vue` 與 i18n 檔。

## 不做

- 不動 BE、不開端點、不加能力點、不加 migration。
- 不收斂其他六棵導航樹（決策者 2026-10-25 裁「之後再做」，另開 FR）。
- 證據視圖的行為不變（只共用左樹）。
