新增 Job 批次設置的匯入匯出功能,讓使用者透過 Excel 一次設定專案內所有 Job 的任務類型、指派人員、參與部門、設備。
Step 1: 匯出 Excel
GET /export → 瀏覽器下載 .xlsx(A 欄隱藏 job_uid,可編輯欄位為淡黃底)
Step 2: 上傳 Excel
POST /import (multipart/form-data) → 回傳驗證結果
Step 3: 驗證結果預覽
→ 有效行 ✓ / 錯誤行 ✗(標紅,顯示錯誤訊息)
→ 使用者可在表格中直接編輯修正
Step 4: 重新驗證(可重複多次)
POST /import/validate (JSON) → 送修正後的 items → 回傳新的驗證結果
Step 5: 確認匯入
POST /import/confirm (JSON) → 送有效 items → 批次寫入 → 刷新列表
GET /api/1.0/grc/project/<project_uid>/ap/<ap_uid>/jobs/export
Authorization: Bearer <token>
Response: 直接下載 .xlsx 檔案
前端處理:
const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } })
const blob = await res.blob()
const a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = `job-setup.xlsx`
a.click()Excel 結構(10 欄,A 欄隱藏):
| 欄 | 標題 | 底色 | 可見 | 說明 |
|---|---|---|---|---|
| A | job_uid | 隱藏 | 隱藏 | 程式用,使用者看不到 |
| B | 控制項群組 | 灰底(唯讀) | 可見 | group name |
| C | 控制項識別碼 | 灰底(唯讀) | 可見 | e.g. AC.L1-3.1.1 |
| D | 控制項名稱 | 灰底(唯讀) | 可見 | control title |
| E | 檢查項目名稱 | 灰底(唯讀) | 可見 | AO name |
| F | 任務名稱 | 灰底(唯讀) | 可見 | job name |
| G | 任務類型 | 淡黃底(必填) | 可見 | 下拉:general / survey |
| H | 指派人員 | 淡黃底(必填) | 可見 | 逗號分隔 login_name |
| I | 參與部門 | 淡黃底(選填) | 可見 | 逗號分隔部門名稱 |
| J | 設備 | 淡黃底(選填) | 可見 | 逗號分隔設備名稱 |
POST /api/1.0/grc/project/<project_uid>/ap/<ap_uid>/jobs/import
Authorization: Bearer <token>
Content-Type: multipart/form-data
file: <.xlsx,上限 10MB>
Response:
{
"status": true,
"data": {
"valid_count": 30,
"error_count": 2,
"items": [
{
"row": 2,
"job_uid": "uuid-string",
"job_name": "佐證文件上傳",
"control_name": "授權存取控制",
"ao_name": "[a] authorized users are identified",
"job_type": "general",
"assignees": "user1, user2",
"departments": "資訊部",
"devices": "Server-01",
"errors": []
},
{
"row": 5,
"job_uid": "uuid-string",
"job_name": "問卷填答",
"control_name": "身份識別",
"ao_name": "[a] identify system users",
"job_type": "invalid",
"assignees": "unknown_user",
"departments": "",
"devices": "",
"errors": [
{"field": "job_type", "message": "無效的任務類型,允許值:general, survey"},
{"field": "assignees", "message": "使用者不存在:unknown_user"}
]
}
]
}
}欄位說明:
| 欄位 | 說明 | 前端用途 |
|---|---|---|
row |
Excel 行號 | 顯示錯誤位置 |
job_uid |
Job 內部 ID | 不要顯示,validate/confirm 時原封帶回 |
job_name |
任務名稱 | 表格顯示 |
control_name |
控制項名稱 | 表格顯示 |
ao_name |
檢查項目名稱 | 表格顯示 |
job_type |
任務類型 | 表格顯示,可編輯 |
assignees |
指派人員(逗號分隔) | 表格顯示,可編輯 |
departments |
參與部門(逗號分隔) | 表格顯示,可編輯 |
devices |
設備(逗號分隔) | 表格顯示,可編輯 |
errors |
驗證錯誤清單 | 空陣列=有效,有值=有錯 |
使用者在前端表格修正錯誤後,送修正後的 items 重新驗證,不需重新上傳 Excel。
POST /api/1.0/grc/project/<project_uid>/ap/<ap_uid>/jobs/import/validate
Authorization: Bearer <token>
Content-Type: application/json
Request Body: 與 /import/confirm 相同格式
{
"items": [
{
"job_uid": "uuid-string",
"job_type": "general",
"assignees": "user1, corrected_user",
"departments": "資訊部",
"devices": "Server-01"
},
{
"job_uid": "uuid-string-2",
"job_type": "survey",
"assignees": "user3",
"departments": "",
"devices": ""
}
]
}Response: 與 POST /import(上傳 Excel)完全相同格式
{
"status": true,
"data": {
"valid_count": 2,
"error_count": 0,
"items": [
{
"job_uid": "uuid-string",
"job_type": "general",
"assignees": "user1, corrected_user",
"departments": "資訊部",
"devices": "Server-01",
"errors": []
},
{
"job_uid": "uuid-string-2",
"job_type": "survey",
"assignees": "user3",
"departments": "",
"devices": "",
"errors": []
}
]
}
}需要 manager 角色才能執行。
POST /api/1.0/grc/project/<project_uid>/ap/<ap_uid>/jobs/import/confirm
Authorization: Bearer <token>
Content-Type: application/json
Request Body: 將驗證結果中 errors 為空的項目 原封送回。
{
"items": [
{
"job_uid": "uuid-string",
"job_type": "general",
"assignees": "user1, user2",
"departments": "資訊部",
"devices": "Server-01"
}
]
}Response:
{
"status": true,
"data": {
"updated_count": 30
}
}放在 Task Setup 頁面(任務設置樹狀結構頁面)的工具列:
Step 1 — 上傳檔案
.xlsx 檔案Step 2 — 驗證結果預覽(支援編輯 + 重新驗證)
有效 30 筆 / 錯誤 2 筆| 行號 | 控制項 | 檢查項目 | 任務名稱 | 任務類型 | 指派人員 | 部門 | 設備 | 狀態 |
|---|---|---|---|---|---|---|---|---|
| 2 | AC.L1-3.1.1 授權存取控制 | [a] authorized users... | 佐證上傳 | general | user1, user2 | 資訊部 | Server-01 | ✓ |
| 5 | IA.L1-3.5.1 身份識別 | [a] identify... | 問卷填答 | ✗ |
control_name、ao_name、job_nameerrors[].message| 欄位 | 可編輯 | 輸入方式 |
|---|---|---|
job_type |
是 | 下拉:general / survey |
assignees |
是 | 文字輸入(逗號分隔 login_name) |
departments |
是 | 文字輸入(逗號分隔部門名稱) |
devices |
是 | 文字輸入(逗號分隔設備名稱) |
job_uid、job_name、control_name、ao_name |
否 | 唯讀顯示 |
Step 3 — 重新驗證
POST /import/validate → 更新表格與摘要Step 4 — 確認匯入
errors.length === 0 的 items → POST /import/confirm已更新 N 筆任務| HTTP Status | 錯誤碼 | 情境 | 前端處理 |
|---|---|---|---|
| 400 | GRC_400003 |
檔案格式無效 | 提示「請使用匯出的 Excel 範本」 |
| 400 | GRC_400004 |
檔案超過 10MB | 提示「檔案大小超過限制」 |
| 403 | GRC_403002 |
非 manager 角色(confirm 時) | 提示「需要管理者角色」 |
| 404 | GRC_404006 |
AP 不存在或無 Job | 提示錯誤 |
| Method | URL | 說明 |
|---|---|---|
| GET | /api/1.0/grc/project/<pid>/ap/<apid>/jobs/export |
匯出 Excel |
| POST | /api/1.0/grc/project/<pid>/ap/<apid>/jobs/import |
上傳 Excel + 驗證 |
| POST | /api/1.0/grc/project/<pid>/ap/<apid>/jobs/import/validate |
JSON 重新驗證 |
| POST | /api/1.0/grc/project/<pid>/ap/<apid>/jobs/import/confirm |
確認匯入(需 manager) |