手冊首頁 / 溝通協作 / 回饋管理

回饋管理(Feedback Management)

功能群:協作(collab)|本群無獨立 _overview;公告見 公告管理 / 公告檢視;SPEC 索引見 README

事實基準:2026-07-05 從 FE / BE code 掃出;BE route 對 api/feedback/routes/feedback_route.py、service app/feedback/service/feedback_service.py、schema 名對 db_schema.json

1. 功能描述

回饋管理讓使用者提交系統使用回饋(bug / 建議),並提供管理者列表檢視、編輯、匯出。回饋記錄實際存於 public.issues(透過外部 jedi-issue 套件),並以 feedback_issues link row 掛租戶 / 部門並可選鏡像到 GitLab / GitHub issue(見 [議題整合設定])。

重要現況(本頁最大坑):UI 上有「系統回饋」與「韌性巡航回饋(巡檢回饋)」兩塊,但只有系統回饋是可用的。巡檢回饋在 FE 是停用中的殘留 scaffolding:TabView 內的巡檢 tab 已被註解掉(FeedbackManageTabView.vue:71-76),其獨立管理頁送 {type:1} 篩選會打爆 BEFeedbackIssueQueryEntitytype 欄,FeedbackIssueQueryEntity(**kwargs)TypeError)。後端無巡檢專屬模組 / 表 / discriminator 欄位——系統 / 巡檢共用同一組 feedback 端點,差別只在 FE 送的 payload。詳見 §12。

主要使用者:一般使用者(提交自己的回饋)、管理者(is_admin,檢視 / 編修 / 匯出全部)。

角色速覽

角色 一句話
一般使用者 提交回饋、檢視 / 編輯 / 刪除自己的回饋(FE 判定)
管理者(is_admin) 檢視 / 編輯 / 刪除 / 匯出全部回饋

1.1 功能總覽(本頁全部功能)

# 功能 說明 位置 詳述
1 系統回饋管理列表 分頁 / 排序 / 搜尋(server-side,useTableQuery);欄:動作 / 類別 / 標題 / 功能 / 建立者 / 時間 系統回饋 tab(SystemFeedbackManage UC-FB-01
2 新增回饋 標題 / 類別(label)/ 功能(label)/ 內文(Editor)/ 附件(多檔 advanced) 系統回饋表單(SystemFeedbackForm UC-FB-02
3 編輯回饋 同新增;per-row canEdit(見 §3) 同上 UC-FB-02
4 刪除回饋 confirm → DELETE;連動關閉 / 刪 GitLab·GitHub issue(best-effort) 列表動作 §6
5 檢視回饋 唯讀:類別 / 功能 / 內文(v-dompurify-html)/ 附件下載 系統回饋檢視(SystemFeedbackView §5
6 附件上傳 / 下載 / 刪除 多檔上傳(≤5MB,白名單副檔);下載走 /file/download;刪走 /feedback/file/{uid}/{fileUid} 表單 / 檢視 §6
7 Excel 匯出 系統回饋列表匯出 xlsx(/feedback/export/excel 系統回饋列表 §6
8 類別 / 功能下拉 類別來源 /labels/menu/FEEDBACK_TYPE、功能 /labels/menu/FUNCTION(依使用者可見選單過濾) 表單 §6
9 巡檢回饋管理 / 表單 / 檢視(停用中 獨立 route 尚存但功能不完整(client-side 分頁、無匯出、無 ownership、下拉 hardcode、{type:1} 會炸 BE) cruising-feedback-* §12

UC(§2)只展開 1(列表檢視)、2(提交 / 編輯)這些系統回饋核心路徑;巡檢回饋因停用不展開 UC,只在 §12 記錄現況。

2. Use Case

角色速覽

角色 一句話
一般使用者 提交回饋、檢視 / 編輯 / 刪除自己的回饋(FE 判定)
管理者(is_admin) 檢視 / 編輯 / 刪除 / 匯出全部回饋

流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。

UC-FB-01 檢視 / 篩選回饋列表

項目 內容
角色 一般使用者 / 管理者
前置條件 已登入
產出 / 後置條件 無寫入;回列表(server-side 分頁 / 排序 / 搜尋 title·建立者·修改者)
feedback_uc_01 start load 進頁 → POST /feedbacks pager / sort / filters(title·建立者·修改者) start->load enrich 逐筆 enrich .issue(title / description / labels / files) load->enrich gate canEdit(item): admin 或 created_user==login_name? enrich->gate ro 只顯示檢視 gate->ro rw 顯示編輯 / 刪除 gate->rw
UC-FB-01 流程:進頁 → POST /feedbacks(pager/sort/filters)→ 逐筆 enrich issue 內容 → 依 canEdit 顯示動作

UC-FB-02 提交 / 編輯回饋

項目 內容
角色 一般使用者(編輯限自己或 admin)
前置條件 已登入;page_permissions 含 CREATE / UPDATE
產出 / 後置條件 建 / 改 issues + feedback_issues + label / file 關聯;可選鏡像 GitLab / GitHub(best-effort,失敗只 log)
feedback_uc_02 start form 填表:標題 / 類別(label) / 功能(label) 內文(Editor) / 附件(多檔) start->form valid vuelidate 必填通過? form->valid bad 聚焦第一個未填欄 valid->bad send multipart(json blob + file[]) POST /feedback 或 PUT /feedback/{uid} valid->send issue 建 issues + issue_label_mapping + issue_upload_file_mapping send->issue mirror (可選)鏡像 GitLab / GitHub issue best-effort(失敗只 log) issue->mirror ok feedback_issues link 寫入 / 更新 issue->ok mirror->ok
UC-FB-02 流程:填表(title/類別/功能/內文/附件)→ multipart(json+file)POST/PUT /feedback → 建 issue + label/file mapping → 選擇性鏡像外部 issue

3. 權限矩陣

操作 FE 判定 BE 強制 BE 檢查位置
進列表 / 檢視 登入即可 @jwt_required() api/feedback/routes/feedback_route.py
新增 / 編輯 page_permissionsgetUserPagePermissions)含 CREATE/UPDATE;per-row canEdit:admin 全部 / 否則 item.created_user === login_name 無角色守門,僅 JWT 同上
刪除 同 canEdit 無角色守門 同上
匯出 頁面可見即可 僅 JWT 同上

⚠️ 安全缺口(§12):回饋所有寫入端點 BE 只驗 JWT,無 owner / role 檢查——非 admin 直接打 PUT/DELETE /feedback/{uid} 可改 / 刪別人的回饋,canEdit 只是 FE 藏按鈕。與公告頁同樣缺口(見 bulletin-manage.md §12)。

4. 狀態機與前置條件

回饋是扁平 CRUD,FE 無狀態工作流(無 status dropdown / badge / 回覆 thread)。注意 public.issuesstate 欄(回饋狀態),但目前 FE 完全不 surface——狀態由外部 issue 生命週期(如關閉)驅動,非本頁 UI 操作。

條件 效果 出處
permissions.length === 1 tab 傳 :view=true → 列表唯讀模式(隱藏 CRUD) FeedbackManageTabView.vue:69
canEdit(item) 決定 per-row 編 / 刪按鈕 SystemFeedbackManage.vue:161-171
匯出型別 ∉ {csv, excel} FEEDBACK_400001(不支援匯出型別) feedback_service.py:348

5. UI 設計

📸 實際畫面截圖待補(一律亮色模式拍攝):以 playwright 對 STG 擷取,預計補三張到 assets/img/:① 系統回饋列表(含匯出 / 搜尋)② 新增回饋表單(Editor + 多檔上傳)③ 回饋檢視(附件下載)。

版面骨架(TabView 僅系統 tab 生效;巡檢 tab 已註解):

FeedbackManageTabView 殼:TabView(系統回饋 tab 生效/巡檢 tab 已註解) FeedbackManageTabView.vue:71-76(巡檢 tab 註解掉,非執行期隱藏) 系統回饋(生效) 巡檢回饋(tab 已註解,停用) 開啟:檢視/篩選回饋列表 UC-FB-01 系統回饋列表:動作/類別/標題/功能/建立者/時間(server-side 分頁 + 匯出) POST /feedbacks(pager/sort/filters;filters 僅認 title/category) POST /feedback/export/{export_type}(csv/excel 匯出) → #uc-fb-01-檢視--篩選回饋列表(點我開啟) 列:類別/標題/功能/建立者/時間 ・ canEdit:admin 全部/否則限本人 動作:[編輯](canEdit 才顯示)[刪除](canEdit 才顯示)[檢視] 開啟:提交/編輯回饋 UC-FB-02 SystemFeedbackForm(獨立 route,非 dialog) POST /feedback(新增,multipart:json blob + file[]) PUT /feedback/{uid}(更新,同 multipart) GET /labels/menu/FEEDBACK_TYPE・/FUNCTION(類別/功能下拉) 標題 / 類別 label / 功能 label(下拉) 內文 Editor / 附件多檔上傳(≤5MB,白名單副檔) → #uc-fb-02-提交--編輯回饋(點我開啟) 開啟:§6 API 規格(檢視回饋唯讀頁對應 GET /feedback/{uid}) SystemFeedbackView(唯讀,獨立 route) GET /feedback/{uid} 類別/功能/內文 v-dompurify-html 淨化 附件下載(GET /file/download/{uid}) → #6-api-規格(點我開啟) 彩色=可點跳轉本頁 §6/UC,灰=本頁結構(TabView 殼/巡檢 tab 已註解停用)|虛線=獨立 route(表單/檢視)
回饋管理 wireframe:灰=TabView 殼與已註解停用的巡檢 tab;teal=系統回饋列表(可點 → UC-FB-01);coral 虛線=提交/編輯表單與檢視頁(獨立 route,可點 → UC-FB-02/§6 API 規格)

狀態呈現:系統列表 server-side 分頁(useTableQuery)、全螢幕 loading overlay;表單 CKEditor 富文本 + FileUpload advanced 多檔;檢視 v-dompurify-html 淨化內文。無 socket。巡檢管理頁為 client-side 分頁(一次撈全量)、較不完整。

6. API 規格

Envelope:成功 {"code": 1, "data": …}、失敗 {"code": 0, "msg": "…"}

6.1 總清單(本頁呼叫的全部 endpoint)

分類 Method + Path 說明 完整規格
列表 POST /feedbacks 回饋分頁列表(pager / sort / filters) §6.2
明細 GET /feedback/{uid} 單筆回饋(含 issue 內容 / labels / files) §6.2
建立 POST /feedback 新增(multipart:json blob + file[] §6.3
更新 PUT /feedback/{uid} 更新(同 multipart) §6.3
刪除 DELETE /feedback/{uid} 刪除(連動關 / 刪外部 issue,best-effort) §6.3
附件 DELETE /feedback/file/{uid}/{file_uid} 刪單一附件 GAI-SD-02
匯出 POST /feedback/export/{export_type} csv / excel 匯出 GAI-SD-02
下拉 GET /labels/menu/FEEDBACK_TYPE/labels/menu/FUNCTION 類別 / 功能 label 下拉 GAI-SD-02
下載 GET /file/download/{file_uid} 附件下載(blob) GAI-SD-02

6.2 讀取類

[POST] /feedbacks

Request(FeedbackPageQueryRequest,繼承 RequestMetaSchema):

欄位 型別 必填 說明
pager object 分頁({page, page_size, with_total}
sort object 排序
filters object 篩選;schema 宣告 title/content/function/category/type/is_delete,但實際 server-side 只認 title / category——傳 content/function/type/is_delete 會落入 FeedbackIssueQueryEntity(**kwargs) 導致 TypeError(§12 坑)

Response(FeedbackPageQueryResponsedata[]FeedbackResponse,見 §6.3)。出處:api/feedback/routes/feedback_route.py:19-36feedback_service.py:65-97

[GET] /feedback/{uid}

Response(FeedbackResponse):

欄位 型別 說明
uid string 回饋識別
issue_uid string → issues.uid
gitlab_issue_uid string 外部 GitLab 鏡像 issue
github_issue_uid string 外部 GitHub 鏡像 issue
title string 標題(由巢狀 .issue 物件取)
description string 內文(由巢狀 .issue 物件取)
labels array 標籤(由巢狀 .issue 物件取)
files array 附件(由巢狀 .issue 物件取)
created_user string 建立者 login_name
created_user_name string 建立者 nickname
updated_user string 修改者 login_name
updated_user_name string 修改者 nickname
created_at date 建立時間
updated_at date 修改時間

出處:api/feedback/serializers/feedback.py:30-58

6.3 寫入類

[POST] /feedback ・ [PUT] /feedback/{uid}

multipart/form-data

欄位 型別 必填 說明
json object (Blob) {title, description, labels:[category_label_uid, function_label_uid]}
file array 附件(多檔)

json blob 內含欄位:

欄位 型別 必填 說明
title string 標題
description string 內文(BE 取為 content
labels array [category_label_uid, function_label_uid]

BE add_feedback / update_feedbacktitle / content(=description) / labels / files;建 issues 記錄 + issue_label_mapping + issue_upload_file_mapping,並可選鏡像 GitLab / GitHub issue(依 議題整合設定,失敗只 log 不擋)。Response:FeedbackResponse。出處:feedback_route.py:49-83feedback_service.py:140-236

[DELETE] /feedback/{uid}

關閉 / 刪除本地 issue + 外部 GitLab·GitHub issue(best-effort)→ 刪 feedback_issues link。出處:feedback_service.py:238-260

7. 前端檔案地圖(compliance-manager-fe/)

檔案 角色
src/views/feedback/FeedbackManageTabView.vue Tab 殼(系統 tab 生效 / 巡檢 tab 註解;path-driven showTab
src/views/feedback/system/SystemFeedbackManage.vue 系統回饋列表(server 分頁 useTableQuery / 匯出 / canEdit
src/views/feedback/system/SystemFeedbackForm.vue 新增 / 編輯(Editor + 多檔 advanced 上傳;type=0)
src/views/feedback/system/SystemFeedbackView.vue 唯讀檢視(labels 推導類別 / 功能 + 附件下載)
src/views/feedback/cruising/* 巡檢回饋(停用中殘留,見 §12)
src/config/api/api.js 端點常數(FEEDBACKS/FEEDBACK/FEEDBACK_FILE/FEEDBACK_EXPORT/LABELS_MENU/DOWNLOAD_FILE
src/config/locales/i18n/{zh-tw,en}/feedback.json i18n(namespace lang.feedback_manage.*
src/service/FeedbackService.js 死碼(讀 demo JSON,未被引用)

8. 後端檔案地圖(本頁核心鏈路)

鏈路 Route App Service 底層
列表 / 明細 api/feedback/routes/feedback_route.py::FeedbacksRoute / FeedbackRoute.get app/feedback/service/feedback_service.py::get_feedbacks_and_pager / get_feedback(enrich IssueService FeedbackIssueDomainServicefeedback_issues repo + 外部 jedi-issueissues
建 / 改 / 刪 同檔 FeedbackRoute.post/put/delete add_feedback / update_feedback / delete_feedback(GitLab / GitHub 鏡像 best-effort) IssueServicejedi-issue LOCAL/GITLAB/GITHUB provider)+ label / file mapping
附件 / 匯出 FeedbackFileRoute / FeedbackExportRoute delete_feedback_file / export_feedbacks jedi-issue attachment + upload_files

DDD 提醒FeedbackService 每個 public method 有 @transaction;外部 jedi-issue provider 呼叫依賴 caller 的 transaction scope。寫入端點無角色檢查(§3 缺口,新 code 不要比照)。

9. DB

9.1 資料表總清單(本頁讀寫的全部表)

讀/寫 說明 欄位詳述
public.issues 回饋主體(jedi-issue 套件:title / description / state) §9.3
public.feedback_issues 回饋 ↔︎ 外部 issue link(gitlab / github uuid、tenant / org) §9.3
public.labels 標籤(scope=FEEDBACK_TYPE / FUNCTION 即類別 / 功能) GAI-SD-03
public.issue_label_mapping 回饋 ↔︎ label 多對多 GAI-SD-03
public.issue_upload_file_mapping 回饋 ↔︎ 附件多對多 GAI-SD-03
public.upload_files 附件本體 GAI-SD-03
public.issue_assignee_mapping (未用) 回饋 ↔︎ 負責人(目前 assignees 恆傳 []) GAI-SD-03

9.3 核心表欄位(取自 DEV DB dump,含 DB comment)

public.issues — 回饋表(jedi-issue)

欄位 型別 說明
uid varchar(50) 回饋 UUID(= FE 的 feedback uid 對應 issue_uid)
project varchar(255) 所屬專案
title / description varchar(255) / text 標題 / 內文
state varchar(50) 回饋狀態(FE 未 surface;外部 issue 生命週期驅動)

public.feedback_issues — 回饋 ↔︎ Issue 關聯

欄位 型別 說明
uid varchar(50) link 識別
issue_uid varchar(50) → issues.uid
gitlab_issue_uid / github_issue_uid varchar(50)|null 外部鏡像 issue(議題整合啟用時)
tenant_id / org_unit_id int|null 租戶 / 部門(FK RESTRICT)

類別 / 功能 = labelsscope FEEDBACK_TYPE / FUNCTION,純字串無 Python enum)經 issue_label_mapping 掛。附件經 issue_upload_file_mappingupload_files

10. 頁面邏輯與資料對應

載入時序:進頁 → POST /feedbacksuseTableQuery 組 pager/sort/filters)→ 逐筆 enrich .issue → 依 canEdit 顯示動作。表單載入時另拉類別 / 功能 label 下拉。

關鍵欄位對應(畫面 ↔︎ API):

畫面元素 FE state API 欄位
類別 / 功能 currData.category / .function labels(scope FEEDBACK_TYPE / FUNCTION)name
內文 currData.description(系統)/ .content(巡檢) issue.description
附件 currData.files issue.upload_files(issue_upload_file_mapping
建立者 item.created_user created_user(enrich _name nickname)

儲存流程:multipart(json blob + files)一次送;BE 建 issue + mapping + 選擇性鏡像外部 issue。刪除連動關外部 issue。

錯誤對應:BE envelope → toast;FEEDBACK_ISSUE_404001(回饋不存在)、FEEDBACK_400001(不支援匯出型別)。

11. 背景行為與外部依賴

類型 內容
GitLab / GitHub 鏡像 建 / 改 / 刪回饋時依「議題整合設定」best-effort 鏡像到外部 issue(失敗只 log 不擋);provider LOCAL / GITLAB / GITHUB(common/code/feedback_code.py
Socket 本頁 socket / 輪詢
jedi-* 套件 jedi-issue(issue 主體 / 附件 / 外部 provider)、jedi-auth(JWT)
系統參數 類別 / 功能來自 labels(scope);議題整合開關來自系統設定

12. 邊界情況與已知坑

  1. 巡檢回饋(cruising)停用 + 會炸:FE 巡檢 tab 已註解(FeedbackManageTabView.vue:71-76);獨立巡檢管理頁送 {type:1},但 BE FeedbackIssueQueryEntitytype 欄 → FeedbackIssueQueryEntity(**kwargs)TypeError後端無巡檢專屬模組 / 表 / discriminator。要復用巡檢前,需 BE 補 type 欄位 / 篩選、FE 修下拉 hardcode。目前只有系統回饋端到端可用
  2. 寫入端點無 BE 角色守門PUT/DELETE /feedback/{uid} 僅 JWT,非 admin 可改 / 刪他人回饋;canEdit 只是 FE 藏鈕(同公告頁缺口)
  3. filters 只認 title / category:schema 宣告多欄,但 server-side FeedbackIssueQueryEntity 只有 title / category——傳其他 filter key 會 TypeError
  4. issues.state 未 surface:有狀態欄但 FE 無工作流 UI(無 status / 回覆 thread)
  5. 系統 vs 巡檢 discriminator 是 FE-only:FE 送 type=0/1,但 BE add_feedback 不消費 type(signature 無此參數);系統 / 巡檢共用同組端點與表,差別只在 FE
  6. 多處死碼FeedbackService.js(demo JSON)、verify_feedback_issue_is_exist(無 call site)、FeedbackRequest/FeedbackFileRequest schema(route 手解 request.files['json'] 未用)、ALLOWED_EXTENSIONS 常數(定義未強制)
  7. 巡檢表單下拉 hardcodeCruisingFeedbackForm.vue 類別 / 功能是寫死 stub(真 API 呼叫定義了但沒接 onMounted);巡檢刪附件 bug(清空全部 files 而非單一)
  8. error code 前綴 FEEDBACK_ 不是 GRC_:在 common/code/error_code.py(共用檔)

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 環境一般使用者(提交)+ admin(管理 / 匯出);密碼見 .env / 部署文件
  • 導航路徑:登入 → 側邊「回饋」→ /feedback/system-feedback-manage
  • 前置資料labels 有 FEEDBACK_TYPE / FUNCTION scope 標籤;議題整合設定(可選)啟用才鏡像外部 issue
  • E2Ecompliance-manager-test/ repo;以 回饋 / feedback 搜尋
  • 相關文件:公告見 公告管理;議題整合設定(GitLab/GitHub)另有系統管理頁 spec;DB / API 全量見 GAI-SD-02/03