本卡屬 FR-163(母卡 CM-3083),批 3,與 FR-163.3 平行(不同檔)。決策者 2026-10-25 實測:點「證據視圖」會頓一下才換畫面,問「可以有讀取畫面嗎」。首腦查過:頓的原因是同步攤平+一次把全部列畫進 DOM,單加 spinner 沒用(主執行緒被佔住,spinner 根本畫不出來),要先讓切換當下就能畫、攤平延後、表格不一次畫全部。只改 FE repo。
按下「證據視圖」那一瞬間,Vue 在同一個畫格裡做完三件事才畫面:①把整棵 control-tree(ISO 專案 93 個控制項 × 評估目標 × 任務 × 證據)攤平成一列一份證據並去重;②算每個群組/控制項/評估目標的份數;③把範圍內全部列一次畫成 DOM(表格沒有虛擬捲動、沒有分頁)。這三步做完之前瀏覽器畫不了任何東西,使用者看到的就是「頓一下」。
首腦核對(合回後 feature/FR-139 HEAD a68ae07f):
src/components/grc/evidence-view/useEvidenceFlatten.js:82-88:rows/groupCounts/controlCounts/aoCounts 四個 computed,第一次被讀到時同步跑 buildRows(五層迴圈建 Map)+三次 countBy。RoundEvidenceView.vue:96 <LoadingState v-if="loading && !groups.length" …/>——切換時 groups 早就載好了,這個條件永遠是 false,讀取狀態從來沒出現過。EvidenceTable.vue:53-55 <DataTable :value="items" … scrollable scrollHeight="flex">——沒有 virtualScrollerOptions、沒有 paginator,群組範圍下幾百列(每列還有位置欄的 Tag)全部進 DOM。useEvidenceTableRows.js:51-62 三層 computed(scoped → filtered → table)都是同步,跟在攤平之後同一畫格。~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/components/grc/evidence-view/RoundEvidenceView.vue:24,96 攤平掛點、讀取狀態條件
~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/components/grc/evidence-view/useEvidenceFlatten.js:82-88 同步 computed
~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/components/grc/evidence-view/EvidenceTable.vue:53-55 DataTable 無虛擬捲動
① 攤平延後、切換當下先畫殼(RoundEvidenceView.vue+useEvidenceFlatten.js):
useEvidenceFlatten 改成:rows 不再是 computed,改 ref([])+一個 ready = ref(false);提供 build(),在 onMounted 用 setTimeout(0)(或 requestAnimationFrame 兩次)等瀏覽器先畫一格再跑 buildRows,跑完填 rows.value、ready.value = true。三個 counts 維持 computed(它們吃 rows,rows 是空陣列時零成本)。groups/controlsMap 變了要重算:watch([groupsRef, controlsMapRef], () => { ready.value = false; schedule(build) }),同樣延後一格。切回控制項視圖再切回來(元件重新 mount)會再算一次——可接受;若要省,把攤平結果用 shallowRef 提到父層 ProjectAuditorOverview.vue 以 projectId 當鍵快取,但那支檔已超標 2,124 行,本卡不做,回寫註明即可。RoundEvidenceView.vue:96 條件改成 v-if="loading || !ready",用既有 <LoadingState size="panel" />(同檔已 import)。這樣按下切換的下一格就看到讀取狀態,再下一格才是表格。② 表格虛擬捲動(EvidenceTable.vue):
DataTable 加 :virtualScrollerOptions="segmented ? undefined : { itemSize: 56 }"(itemSize 量實際一列高度後填,位置欄多行時列高不一,取最常見的一列高;PrimeVue 虛擬捲動要固定列高,位置欄超過 3 行已收成「還有 N 個…」所以列高可控)。scrollable scrollHeight="flex" 保留。segmented)不開虛擬捲動:rowGroupMode="subheader" 與虛擬捲動在 PrimeVue 3 不能並用(首腦查 node_modules 結果寫在卡尾「版本核對」段,runner 開工先看)。分段只在選了範圍後才會開、列數本來就小,維持原樣。先查再寫:FE 既有 virtualScrollerOptions 用法 grep -rn "virtualScrollerOptions" src/ 照抄一處的寫法與 CSS(虛擬捲動需要父容器有明確高度,evidence-pane 的 scrollHeight="flex" 是否夠,實測)。