本卡屬 FR-147,棒 4 第一張。建一支資源庫與專案共用的 Excel 產生與解析器,先接資源庫端三支端點。依賴 3a 的 readmodel。
顧問想用 Excel 一次填很多任務的說明。匯出的檔一列一個任務,同一條評估目標有多個任務時左邊的群組/控制項/評估目標欄合併儲存格(跟改善計畫那份一樣),只有名稱、描述、指南三欄黃底可改;改完同一份匯回,預覽只標出有變更的格,確認後寫入。範例檔:prototype/sample/FR-147-任務說明範例.xlsx(產生腳本 make_sample_xlsx.py,欄位與著色可直接照它)。
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/app/flow_control/service/poam_workbook_export.py:131-205 _plan_sheet:AO 多列 merge_cells、列高平分、灰黃著色 ← 寫法借用
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/app/flow_control/service/job_import_service.py:49-66 HEADER_LABELS/_EXPORT_COLUMNS 既有十欄;:217-268 檔案驗證與列迭代(串流、上限)← 借用
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/infra/readmodel/tasks/job_export_query.py:85 get_export_data:按輪次撈任務,已回 job_name,沒 description/guide ← 加兩欄
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-147-2610-resource-library-task-guidance/prototype/sample/make_sample_xlsx.py 範例產生腳本(欄位、著色、填寫說明頁)
app/flow_control/service/task_guidance_workbook.py:build(rows, extra_columns=()) -> BytesIO,rows 形狀 [{key, group_name, control_code, control_name, ao_name, order, name, description, guide, ...extra}];兩頁「填寫說明」「任務說明」;欄 A 比對鍵隱藏、B~E 灰底同 AO 合併、F 順序、G~I 黃底,extra_columns 接在 I 之後(專案端用);parse(file) -> [{key, name, description, guide}] 只讀 A、G、H、I,表頭對不上回 BadRequest;列數上限與空列中止照 job_import_service._iter_data_rows。export_xlsx(mf_uid)(template 模式 key <part_id>|<node_id>、project 模式 key job_uid,資料從 3a readmodel 撈整本);import_parse(mf_uid, file) 回 {changed:[{key, control_code, ao_name, task_name, field, old, new}], unchanged:n, skipped:[{row, key, reason}]};import_confirm(mf_uid, items) 只寫 changed 的三欄、key 對不到跳過不報錯(D4)、走 3a 的 save。POST /module-frame/<uid>/task-guidance/export、POST .../task-guidance/import/parse(multipart)、POST .../task-guidance/import/confirm;守門同 3a。job_export_query.get_export_data 回傳 dict 加 description/guide(4b 要用)。test/test_task_guidance_workbook.py——① 三列同 AO build 後 B2:B4 是 merged range、G 欄填充色是黃;② build 再 parse 回同一組三欄;③ parse 一份表頭錯的檔拋 BadRequest;④ parse 刪掉 A 欄的檔回空清單。ModuleFrameTemplateEditView.vue 1,954 行、job_import_service.py 546 行)一律新開檔再一行呼叫,不往裡塞。python main.py),驗收打端點用 curl;不開任何瀏覽器視窗,前端只用 vite build/dev server 取 SFC 200 驗編譯,畫面留給決策者複測。