Job 批次設置匯入匯出 — 前端整合規格

§1

功能概述

新增 Job 批次設置的匯入匯出功能,讓使用者透過 Excel 一次設定專案內所有 Job 的任務類型、指派人員、參與部門、設備。


§2

功能流程

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 → 批次寫入 → 刷新列表

§3

API 規格

1. 匯出 Excel

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 設備 淡黃底(選填) 可見 逗號分隔設備名稱

2. 匯入 Excel(上傳 + 驗證)

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 驗證錯誤清單 空陣列=有效,有值=有錯

3. 重新驗證(JSON)

使用者在前端表格修正錯誤後,送修正後的 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": []
      }
    ]
  }
}

4. 確認匯入(批次寫入)

需要 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
  }
}

§4

前端 UI 建議

按鈕位置

放在 Task Setup 頁面(任務設置樹狀結構頁面)的工具列:

  • 「匯出 Excel」→ 點擊直接下載
  • 「匯入 Excel」→ 點擊開啟 Dialog

匯入 Dialog 設計

Step 1 — 上傳檔案

  • 拖拽或選擇 .xlsx 檔案
  • 上傳後顯示 loading

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... 問卷填答 invalid unknown_user
  • 名稱顯示:control_nameao_namejob_name
  • 錯誤行標紅,hover 顯示 errors[].message
  • 可編輯欄位(錯誤行允許直接修改):
欄位 可編輯 輸入方式
job_type 下拉:general / survey
assignees 文字輸入(逗號分隔 login_name)
departments 文字輸入(逗號分隔部門名稱)
devices 文字輸入(逗號分隔設備名稱)
job_uidjob_namecontrol_nameao_name 唯讀顯示

Step 3 — 重新驗證

  • 「重新驗證」按鈕:表格有被編輯時 enable
  • 點擊 → 收集所有 items → POST /import/validate → 更新表格與摘要
  • 可重複多次直到全部有效

Step 4 — 確認匯入

  • 按鈕:「匯入有效資料(N 筆)」/「取消」
  • 過濾 errors.length === 0 的 items → POST /import/confirm
  • 成功後顯示 已更新 N 筆任務
  • 關閉 Dialog → 刷新 Task Setup 頁面

錯誤處理

HTTP Status 錯誤碼 情境 前端處理
400 GRC_400003 檔案格式無效 提示「請使用匯出的 Excel 範本」
400 GRC_400004 檔案超過 10MB 提示「檔案大小超過限制」
403 GRC_403002 非 manager 角色(confirm 時) 提示「需要管理者角色」
404 GRC_404006 AP 不存在或無 Job 提示錯誤

§5

API 總覽

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)