問卷管理頁(Survey Manage)
事實基準:2026-07-05 從 FE(
views/survey-v2/SurveyManage.vue等)/ BE(api/survey、jedi-survey 套件)code 掃出;表結構取自db_schema.json(surveyschema);error code 對jedi_survey/common/enum/error_code.py與common/code/grc_error_code.py
1. 功能描述
問卷管理頁是作者端問卷範本的入口與總覽:左側資料夾樹分類、主區以卡片或表格列出問卷,提供建立 / 複製 / 另存新版 / 發布 / 移動 / 刪除 / 批量匯入。點問卷進問卷設計器編輯題目結構;問卷發布後才能被專案規劃頁的稽核任務選用(綁定時取快照,見 _overview §4)。
主要使用者:問卷範本作者(以選單能力控管,非專案層角色,見
_overview
§5)。清單僅顯示範本(is_snapshot=0),看不到消費端快照。
角色速覽(作者端以選單能力控管,非專案 manager/auditor,見 _overview §5):
| 角色 | 一句話 |
|---|---|
| 問卷作者 | 有問卷管理選單能力者——本頁全部操作(實際 endpoint 僅
jwt_required,無角色細分,見 §3) |
1.1 功能總覽(本頁全部功能)
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | 資料夾樹 | 樹狀分類、搜尋、「所有資料夾」;每夾顯示問卷計數 | 左側邊欄 | UC-SVM-01 |
| 2 | 資料夾 CRUD | 新增 / 編輯 / 刪除資料夾 | 左側邊欄 dialog | 新增 / 更名 UC-SVM-05;刪除 UC-SVM-03 |
| 3 | 批次刪除資料夾 | 勾選多夾一次刪 | 左側邊欄 | §6.2 |
| 4 | 統計腳 | 已發布 / 草稿 / 範本 / 全部計數,可點擊切篩選 | 左側邊欄底 | §10 |
| 5 | 問卷清單(grid / table) | 卡片或表格;後端分頁;顯示狀態、版本、頁 / 題數、建立者 | 主內容區 | UC-SVM-01 |
| 6 | 關鍵字搜尋 | 依問卷名稱模糊搜尋 | 工具列 | UC-SVM-01 |
| 7 | 狀態篩選 | 全部 / 已發布 / 草稿 / 範本 | 工具列 | UC-SVM-01 |
| 8 | 檢視切換 | grid ⇄ table | 工具列 | §5 |
| 9 | 建立問卷 | SplitButton:新增空白 / 從樣板複製 / 批量匯入 | 工具列 | UC-SVM-02 |
| 10 | 進設計器 | 點名稱 / 卡片 menu「編輯」→ 問卷設計器 | 名稱 / menu | →問卷設計器 |
| 11 | 預覽 | 卡片 menu「預覽」→ 唯讀預覽 | 卡片 menu | →問卷填寫 / 預覽 |
| 12 | 複製問卷 | 深度複製(含頁 / 題 / 翻譯)到指定資料夾 | 卡片 menu / SurveyPickerDialog | UC-SVM-02 |
| 13 | 移動問卷 | 改所屬資料夾 | 卡片 menu → dialog | UC-SVM-05 |
| 14 | 發布 / 取消發布 | 切換 release;發布後才能被任務選用 |
設計器 / 狀態 | UC-SVM-02 |
| 15 | 刪除問卷 | 軟刪除(FE 依 hasAnswer 擋,BE 無答案守門) | 卡片 menu / table | UC-SVM-03 |
| 16 | 批次刪除問卷 | 勾選多筆一次刪 | 工具列 | UC-SVM-03 |
| 17 | 批量匯入 | Excel 三 sheet 匯入(可更新既有問卷) | BatchImportDialog | UC-SVM-04 |
UC(§2)已展開本頁所有具實質後端邏輯的功能:瀏覽 / 搜尋 / 篩選(1/5/6/7)、建立 / 複製 / 另存新版 / 發布(9/12/14)、刪除問卷 / 資料夾(15/16/2 刪除路徑)、批量匯入(17)、資料夾建立 / 更名 + 問卷移動(2 建立更名 / 13)。純顯示 / 導覽類(4 統計腳、8 檢視切換)見 §5 / §10;進設計器 / 預覽(10/11)另屬所屬頁面 spec,於此只交叉連結不重複。
2. Use Case
角色速覽(作者端以選單能力控管,非專案 manager/auditor,見 _overview §5):
| 角色 | 一句話 |
|---|---|
| 問卷作者 | 有問卷管理選單能力者——本頁全部操作(實際 endpoint 僅
jwt_required,無角色細分,見 §3) |
流程圖視覺慣例:菱形 = 判斷、橘底 = 例外 / 擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。
UC-SVM-01 瀏覽 / 搜尋 / 篩選問卷
| 項目 | 內容 |
|---|---|
| 角色 | 問卷作者 |
| 前置條件 | 已登入且有問卷管理選單能力 |
| 產出 / 後置條件 | 資料夾樹 + 分頁問卷清單(僅範本
is_snapshot=0、is_delete=0);切資料夾以 reqId
防亂序覆寫 |
UC-SVM-02 建立 / 複製 / 另存新版 / 發布
| 項目 | 內容 |
|---|---|
| 角色 | 問卷作者 |
| 前置條件 | 目標資料夾存在(複製 / 匯入需選資料夾) |
| 產出 / 後置條件 | 新增空白→建 survey(含初始頁)並導向設計器;複製→深度
clone;另存新版→同 group_id 新 version_no
列;發布→release=1 |
UC-SVM-03 刪除問卷 / 資料夾
| 項目 | 內容 |
|---|---|
| 角色 | 問卷作者 |
| 前置條件 | 問卷:FE 依 hasAnswer
決定是否允許刪(有答案則前端擋) |
| 產出 / 後置條件 | 問卷 / 資料夾皆軟刪除(is_delete=1);⚠ BE 端
DELETE /survey/{uid}
不再檢查答案、資料夾刪除不檢查是否含問卷(見 §12) |
UC-SVM-04 批量匯入問卷(Excel 三 sheet)
| 項目 | 內容 |
|---|---|
| 角色 | 問卷作者 |
| 前置條件 | 目標資料夾存在(folder_uid);xlsx 含 Info / Pages /
Questions 三 sheet |
| 產出 / 後置條件 | 解析後寫入 surveys / survey_pages /
survey_questions(含 locale 時寫翻譯表);帶
survey_uid 則更新既有問卷、否則建立新問卷;缺欄擋
TASK_SURVEY_400001 |
UC-SVM-05 資料夾建立 / 更名 + 問卷移動
| 項目 | 內容 |
|---|---|
| 角色 | 問卷作者(寫入僅 @jwt_required(),無角色守門,見 §3 /
§12) |
| 前置條件 | 建立 / 更名:提供 name;移動:目標資料夾存在 |
| 產出 / 後置條件 | survey_folders 增改(同名擋
SURVEY_409007;含 locale 寫
survey_folders_trans);移動改
surveys.folder_id。資料夾刪除見
UC-SVM-03 |
3. 權限矩陣
作者端角色基調見 _overview §5。本頁實際檢查點(FE 判定與 BE 強制分欄並列):
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 進入 / 讀清單 | 需 route
meta.requiresAuth(config/router/index.js:710) |
@jwt_required();無角色細分 |
api/survey/routes/survey_route.py::SurveysRoute |
| 資料夾 / 問卷 CRUD | 選單能力顯示按鈕 | 僅 @jwt_required(),無 manager /
角色守門 |
api/survey/routes/survey_route.py・survey_folder_route.py(全部僅
jwt) |
| 刪除問卷 | 依 survey.hasAnswer 隱藏 / 阻止 |
僅驗證存在→軟刪除,不檢查答案 | jedi_survey/app/service/survey.py::delete_survey:197(無
guard) |
| 刪除資料夾 | — | 僅驗證存在→軟刪除,不檢查是否含問卷 | jedi_survey/domain/service/survey_folder_domain_service.py::delete_folder:116 |
⚠️ 已知安全缺口(維護時注意):作者端問卷 / 資料夾的寫入與刪除只有 JWT、無角色守門——任何登入者只要能到此頁就能改 / 刪任一問卷。清單另附的
GRC_SURVEY_HAS_ANSWERS守門只保護規劃頁任務移除問卷的路徑(app/grc/service/job_service.py:374),不保護本頁刪除。收進 §12。
4. 狀態機與前置條件
本頁的問卷狀態是作者端發布生命週期(surveys.release,見
_overview
§3);消費端填答狀態機不在此頁。
| 條件 | 效果 | 出處 |
|---|---|---|
release=0 |
草稿;統計 / 篩選歸「草稿」 | surveys.release(db_schema) |
release=1 + release_at +
release_target |
已發布;可被規劃頁任務選用(/surveys/menu) |
PUT /survey/{uid}/release(survey_route.py) |
is_sample=1 |
標為範本;「從樣板複製」清單來源(/surveys/menu?type=1) |
surveys.is_sample |
is_delete=1 |
軟刪除,清單以 is_delete=0 過濾不再出現 |
delete_survey(軟刪除) |
is_snapshot=0 |
清單只回範本列;快照列(消費端)永不出現在管理頁 | survey_route.py:71 filters |
5. UI 設計
📸 實際畫面截圖待補(一律亮色模式拍攝;截圖另有專責 session)。預計補到
assets/img/: ① 整頁(左資料夾樹 + grid 卡片)manage-overview.png② 卡片三點選單(編輯 / 預覽 / 複製 / 移動 / 刪除)manage-card-menu.png③ 建立問卷 dialogmanage-create-dialog.png④ BatchImportDialogmanage-import-dialog.png
版面骨架與區塊職責(工具列、左資料夾樹+統計腳選夾 → 右問卷清單分頁,建立/匯入 dialog;彩色區塊可點跳對應小節錨點,API 僅標代表性):
狀態呈現:grid 卡片頂色條依狀態(發布 / 草稿 / 範本);grid / table
由 viewMode 切換;勾選列出現時工具列才顯示批次刪除;卡片
menu 的「刪除」對 hasAnswer=true 的問卷 toast
阻止。切資料夾時多次 fetchSurveys 以遞增 reqId
只保留最新回應(useSurveyApi.js:103-124)。無
socket(作者端管理頁不即時協作;即時協作只在填寫頁)。
6. API 規格
Envelope:成功
{"status": true, "data": …, "meta": …}(清單帶分頁
meta)、失敗 {"error_code": "…", "msg": "…"}。
6.1 總清單(本頁呼叫的全部 endpoint)
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| 資料夾 | POST /survey-folders |
資料夾清單({is_delete:0},直接回陣列無 meta) |
§6.2 |
| 資料夾 | GET /survey-folders/menu |
輕量資料夾下拉 | GAI-SD-02 |
| 資料夾 | POST /survey-folder・PUT
/survey-folder/{uid}・DELETE
/survey-folder/{uid} |
資料夾 CRUD | §6.2 |
| 清單 | POST /surveys |
分頁問卷清單(pager + sort + filters;enrich has_answer) | §6.2 |
| 選單 | GET
/surveys/menu?type=&release=&is_sample= |
輕量問卷下拉(樣板清單來源) | GAI-SD-02 |
| 詳情 | GET /survey/{uid} |
單一問卷(含 pages / questions,供設計器 / 預覽) | →designer |
| 建立 | POST /survey |
建立(含初始頁);as_new_version=true+group_id
= 另存新版 |
§6.2 |
| 更新 | PUT /survey/{uid} |
全量更新(含 pages 結構) | →designer |
| 刪除 | DELETE /survey/{uid} |
軟刪除(無答案守門) | §6.2 |
| 移動 | POST /survey/move |
改所屬資料夾 | §6.2 |
| 複製 | POST /survey/{uid}/clone |
深度複製(頁 / 題 / 翻譯) | §6.2 |
| 發布 | PUT /survey/{uid}/release・DELETE
/survey/{uid}/release |
發布 / 取消發布 | §6.2 |
| 匯入 | POST /survey/excel-import |
Excel 三 sheet 匯入(FormData) | §6.2 |
| 匯入 | GET /survey/import-template |
下載匯入 Excel 範本 | GAI-SD-02 |
6.2 核心 endpoint(欄位對照 serializer / service,出處標段末)
[POST] /surveys — 分頁清單
Request:
{
"pager": {
"page": 0,
"page_size": 0,
"with_total": true
},
"sort": [
{
"field": "string",
"order": "string"
}
],
"filters": {
"is_delete": 0 // 其他 filter 條件
}
}BE 強制 is_snapshot=0(只回範本)。
Response data(陣列,每項 = 問卷 DTO)核心欄位:
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | string | 問卷 UUID |
| name | string | 名稱 |
| description | string | 描述 |
| folder_id | int | 所屬資料夾 |
| version_no | int | 版本號 |
| group_id | int | 問卷群組 ID(版本序列) |
| release | int | 發布旗標 |
| release_at | timestamp | 發布時間 |
| release_target | string | 發布對象 |
| is_sample | int | 是否為範本 |
| page_count | int | 頁數(meta 彙總) |
| question_count | int | 題數(meta 彙總) |
| has_answer | bool | 是否有填答(question_answer_service.survey_has_answer(survey.id)
enrich) |
| created_user(_name) | string | 建立者 login_name(_name = nickname) |
| updated_user(_name) | string | 更新者 login_name(_name = nickname) |
出處:api/survey/routes/survey_route.py:54-96(SurveysRoute
+ has_answer enrich)、DTO jedi_survey SurveyEntity。
[POST] /survey ・ [PUT] /survey/{uid} — 建立 / 更新
Request(建立):
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| name | string | 是 | 問卷名稱 |
| folder_uid | string | 是 | 所屬資料夾 |
| description | string | 否 | 描述 |
| release_target | string | 否 | 發布對象 |
| release_at | date | 否 | YYYY-MM-DD |
| release | int | 否 | 0/1 |
| is_sample | int | 否 | 0/1 |
| pages[] | array | 否 | 建立時 FE 送單一初始頁
{name:'page_structure', no:'#'} |
| as_new_version | bool | 否 | 另存新版:加 as_new_version=true +
group_id(保留舊版、產生新 version_no
列) |
| group_id | int | 否 | 另存新版時指定的問卷群組 ID |
release_at 於 route 層
datetime.strptime(...[:10])
只取日期。出處:api/survey/routes/survey_route.py:99-141、jedi_survey/app/service/survey.py::add_survey。
[POST] /survey/{uid}/clone — 深度複製
Request:
{
"name": "string",
"folder_uid": "string" // 選填
}深度複製 pages / questions / _trans 翻譯,新問卷
group_id = 新 survey.id(獨立版本序列)。同名擋
SURVEY_409002(問卷已存在)。出處:app/survey/service/survey_clone_service.py。
[PUT] /survey/{uid}/release ・ [DELETE] .../release — 發布 / 取消
PUT body {release_target} → release=1 +
release_at;DELETE →
release=0。出處:api/survey/routes/survey_route.py::SurveyReleaseRoute。
[DELETE] /survey/{uid} — 軟刪除
無 body。BE 僅驗證存在後 is_delete=1,不檢查
has_answer(FE
才擋)。出處:api/survey/routes/survey_route.py:145-149 →
jedi_survey/app/service/survey.py::delete_survey:197。
資料夾 CRUD
POST /survey-folder
{name, description};PUT /survey-folder/{uid}
{name, description}(同名擋
SURVEY_409007);DELETE /survey-folder/{uid}
無條件軟刪除(不檢查含問卷)。審計欄位 enrich
created_user_name /
updated_user_name。出處:api/survey/routes/survey_folder_route.py、jedi_survey/app/service/survey_folder.py。
[POST] /survey/excel-import — 批量匯入
FormData:
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| file | file | 是 | xlsx,三 sheet:Info / Pages / Questions |
| folder_uid | string | 是 | 匯入目標資料夾 |
| survey_uid | string | 否 | 選填,更新既有問卷 |
| locale | string | 否 | 語言 |
缺欄擋 TASK_SURVEY_400001(Excel 必含 No / Question
欄——共用匯入驗證)。出處:api/survey/routes/survey_route.py::SurveyExcelImportRoute。
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/views/survey-v2/SurveyManage.vue |
主檢視(資料夾樹 + 清單 + 建立 / 移動 / 匯入彈窗) |
src/views/survey-v2/components/FolderTree.vue・FolderTreeNode.vue |
資料夾樹(CRUD / 批次刪 / 右鍵選單) |
src/views/survey-v2/components/SurveyPickerDialog.vue |
從樣板複製 / 複製問卷選擇器(template / copy mode) |
src/views/survey-v2/components/BatchImportDialog.vue |
Excel 批量匯入(檔案 / 資料夾 / 語言 / 更新既有) |
src/views/survey-v2/composables/useSurveyApi.js |
作者端 API composable(singleton state:folders / surveys;reqId 防亂序) |
src/views/survey-v2/utils/survey-mapper.js |
API ↔︎ FE 欄位轉換(mapSurveyListFromApi 等) |
src/stores/surveyStore.js |
問卷相關 store |
src/config/router/index.js:713-716 |
route
survey-v2-manage(/survey/manage) |
src/config/api/api.js |
endpoint 常數(SURVEY / SURVEYS /
SURVEY_FOLDER(S) / SURVEY_MOVE /
SURVEY_EXCEL_IMPORT …) |
src/config/locales/i18n/*/survey-v2.json |
頁面 i18n |
8. 後端檔案地圖(本頁核心鏈路)
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| 清單 | api/survey/routes/survey_route.py::SurveysRoute |
app/survey/service/survey_app_service.py(enrich 暱稱 +
has_answer) |
jedi_survey SurveyService → repo |
| 建立 / 更新 / 刪除 | 同檔 SurveyRoute |
jedi_survey/app/service/survey.py |
jedi_survey domain / repo |
| 複製 | SurveyCloneRoute |
app/survey/service/survey_clone_service.py |
深度複製 pages / questions / trans |
| 資料夾 | survey_folder_route.py |
jedi_survey/app/service/survey_folder.py |
survey_folder_domain_service |
| has_answer | — | app/task_survey/service/question_answer_service.py::survey_has_answer |
survey.question_answers 查詢 |
DDD 提醒:問卷 domain / repo 在
jedi_survey 外部套件;主專案 route 只做 HTTP 邊界 + audit
欄位 enrich。作者端 route 全部僅
@jwt_required(),未加角色守門(見 §3
缺口)——新增寫入端點時勿比照,應補角色檢查。
9. DB
9.1 資料表總清單(本頁讀寫的全部表)
| 表 | 讀/寫 | 說明 | 欄位詳述 |
|---|---|---|---|
| survey.surveys | 讀 / 寫 | 問卷主檔(範本列 is_snapshot=0);刪除改
is_delete=1 |
§9.3 |
| survey.survey_folders | 讀 / 寫 | 資料夾(樹 pid);刪除改 is_delete=1 |
§9.3 |
| survey.survey_pages | 寫 | 建立時初始頁;複製 / 匯入時整批寫 | designer |
| survey.survey_questions | 寫 | 複製 / 匯入時整批寫 | designer |
| survey.surveys_trans / survey_folders_trans | 寫 | 翻譯表(含 locale 時) | §9.3 |
| survey.question_answers | 讀 | has_answer 判定(survey_has_answer) |
fill |
9.2 ER 圖(本頁讀寫範圍)
9.3 核心表欄位(取自 DEV DB dump,含 DB comment)
survey.surveys — 問卷主檔(20 欄)
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | varchar(36) | 問卷唯一識別碼 UUID |
| folder_id | int | 所屬資料夾(→
survey_folders.id,ON DELETE CASCADE) |
| group_id | int|null | 問卷群組 ID(版本控制:同 group 為同問卷多版本) |
| name / description | varchar(255) / text | 名稱 / 描述 |
| version_no | int|null | 版本號 |
| release | int|null | 是否已發布(1 已發布 / 0 未發布) |
| release_at / release_target | timestamp / varchar(500) | 發布時間 / 發布對象 |
| is_sample | int|null | 是否為範本(1 是 / 0 否) |
| is_snapshot | int NOT NULL | 是否為快照(1 快照 / 0 範本)——管理頁只查 0 |
| source_survey_id | int|null | 來源問卷 ID(快照專用) |
| is_delete | int|null | 軟刪除(1 已刪 / 0 未刪) |
| tenant_id / org_unit_id | int|null | 租戶 / 組織單位(RLS + FK RESTRICT) |
survey.survey_folders — 資料夾(樹)
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | varchar(36) | 資料夾 UUID |
| pid | int|null | 父資料夾(→ survey_folders.id 自參照) |
| name / description | varchar(255) / varchar(500) | 名稱 / 描述(description NOT NULL) |
| is_delete | int|null | 軟刪除 |
| tenant_id / org_unit_id | int|null | 租戶 / 組織單位 |
翻譯表 survey.surveys_trans / survey_folders_trans
surveys_trans:survey_id /
name / description /
release_target /
language_code;survey_folders_trans:survey_folder_id
/ name / description /
language_code。寫入含翻譯欄位要傳 locale(見
_overview §6.3 /
docs/claude/translatable-fields.md)。
10. 頁面邏輯與資料對應
載入時序:見 §2 UC-SVM-01(資料夾與清單並行,reqId 防亂序)。
關鍵欄位對應(API ↔︎ 畫面):
| 畫面元素 | FE state | API 欄位 |
|---|---|---|
| 資料夾樹節點 | folders / folderTree |
/survey-folders
陣列(mapFolderFromApi) |
| 選中資料夾篩選 | selectedFolder |
filters.folder_id(切夾重查) |
| 搜尋框 | filterText |
filters(名稱模糊) |
| 狀態篩選鈕 | filterTab |
前端依 release / is_sample 分類 |
| 卡片 / 列狀態 | — | release(發布 /
草稿)、is_sample(範本) |
| 版本標籤 | — | version_no |
| 頁 / 題數 | — | page_count / question_count |
| 刪除可否 | survey.hasAnswer |
has_answer |
儲存流程:建立 dialog → POST /survey →
成功導向設計器;複製 / 移動 / 發布 / 刪除確認後呼叫對應 endpoint →
重查清單。批量匯入成功後重載 folders + surveys。
錯誤對應:BE error envelope →
toast。常見碼:SURVEY_404002(問卷不存在)、SURVEY_409002(複製同名)、SURVEY_409007(資料夾同名)、TASK_SURVEY_400001(匯入
Excel 缺 No/Question 欄)。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| 通知 | 本頁無通知(通知在填寫頁狀態轉換時發,見 fill §11) |
| Job | 無背景 job;匯入為同步解析 |
| Socket | 本頁無 socket / 輪詢;清單更新靠操作後重查 |
| jedi-* 套件 | jedi-survey(問卷 domain / repo / 錯誤碼 /
匯入解析)、jedi-auth(JWT / RLS session 變數) |
| 系統參數 | 無 feature flag;grid / table 檢視為前端偏好 |
12. 邊界情況與已知坑
- 作者端寫入無角色守門(安全缺口):問卷 /
資料夾的建立 / 更新 / 刪除 route 只有
@jwt_required(),無 manager / 能力層強制——任何能到此頁者皆可改 / 刪任一問卷。修法應在 route 或 app service 補角色 / 能力檢查。 - 刪除問卷 BE
無答案守門:
DELETE /survey/{uid}只軟刪除,不檢查has_answer;守門只在 FE(survey.hasAnswer擋)。GRC_SURVEY_HAS_ANSWERS(GRC_409033)只保護規劃頁任務移除問卷的路徑(job_service.py:374),與本頁刪除無關。繞過 FE 直接呼叫可刪掉已有填答資料的範本。 - 刪資料夾不檢查是否含問卷:
delete_folder無條件軟刪除;夾內問卷folder_id仍指向已軟刪除的資料夾(孤兒)。清單以資料夾is_delete=0過濾,被孤立問卷可能在樹上找不到入口。 - 範本 vs 快照同表:
survey.surveys同時放範本列(is_snapshot=0)與消費端快照列(is_snapshot=1);管理頁一律is_snapshot=0,別在此頁查 / 改到快照。 - 版本語意:「另存新版」= 保留舊版 + 同
group_id新version_no列;「複製」= 全新group_id(獨立序列)。兩者都不影響已綁定任務的快照(快照綁定當下已脫鉤)。 - 切資料夾亂序:
fetchSurveys以遞增reqId保證只有最新請求寫入 state(useSurveyApi.js:103-124);慢回的舊請求丟棄——維護分頁 / 篩選邏輯時勿破壞此保護。 - 可翻譯欄位:改
name/description/release_target未傳locale只更新主表;讀取走 failover 優先翻譯表 → 前端可能看不到主表變更(見docs/claude/translatable-fields.md)。
13. 開發與驗證
- 跑起來:BE
python main_socketio.py(port 8000,log 在log/app.log);FE 在compliance-manager-fe/起 Vite dev server。BE 改 service code 後必須重啟(無 hot reload) - 測試帳號:dev 環境登入帳號密碼見
.env/ 部署文件 - 導航路徑:登入 → 側邊選單「問卷」→
問卷管理(
/survey/manage) - 前置資料:至少一個資料夾才能建問卷;「從樣板複製」需有
is_sample=1的範本 - E2E:
compliance-manager-test/repo(Cucumber + Playwright);以問卷/survey搜尋 feature 檔 - 相關文件:題目編輯見 問卷設計器、填答 / 預覽見 問卷填寫 / 預覽、任務綁定見 project-task-edit.md §6.2;DB / API 全量見 GAI-SD-02/03