使用者管理(User Management)
功能群:系統管理|三層 RBAC 模型與租戶/部門組織模型先讀 功能群總覽 §2、§3
事實基準:2026-07-05 從 FE
src/views/user-manage/(UserManageTabView.vue/UserManage.vue)+ BEapi/auth/routes/user_route.py+ jedi-authuser_service.py/user_domain_service.py+ routes.json / db_schema.json 掃出。
變更紀錄
| 日期 | FR | 變更 |
|---|---|---|
| 2026-07-06 | FR-047 | 改造成 hub 導航頁:帳號表單拆至 使用者表單、Excel 匯入拆至 Excel 批次匯入;本頁保留 Tab0 帳號列表與列操作 |
1. 功能描述
使用者管理是本系統帳號本體的維護入口:Tab
結構(UserManageTabView.vue),Tab0「帳號管理」是帳號列表(UserManage.vue,含搜尋
/ 建立導向 / 每列停用啟用刪除),Tab1「Excel
批次上傳」是批次匯入精靈。本頁作為導航 hub:帳號的新增
/ 編輯走獨立表單子頁,Excel
批次匯入走獨立精靈子頁,列表本身與列上的狀態操作留在本頁。
主要使用者:系統 / 租戶管理員。權限治理(角色如何綁能力)由 角色權限管理 負責;本頁只做「使用者 ↔︎ 角色/租戶/部門」的指派入口。
角色速覽(完整定義見 _overview §2、§3):
| 角色 | 一句話 |
|---|---|
| 系統 / 租戶管理員(可見本選單者) | 帳號 CRUD + 授權組合指派 + 批次匯入 |
is_admin(超級管理員 JWT 旗標) |
額外可在編輯他人帳號時代改密碼;admin
帳號本身的敏感欄位(生效/到期日、刪除授權)鎖死 |
| 一般使用者 | 無此選單(ui_routes 可見性未命中) |
1.1 功能總覽(本頁全部功能)
本頁是 hub(帳號列表 + 列操作 + 子頁導航):帳號新增/編輯表單與 Excel 批次匯入各自的 field-level 逐欄規格拆成子頁,見「詳述」欄連結。
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | 帳號列表 | 分頁表列所有使用者(登入代碼 / 名稱 / Email / 電話 / 狀態 / 租戶 / 部門 / 角色 / 登入軌跡 / 建立更新軌跡),多欄排序 | Tab0 DataTable | §6.2 |
| 2 | 搜尋帳號 | 對 login_name / nickname /
email 全域關鍵字搜尋(Enter 觸發) |
Tab0 工具列 | — |
| 3 | 重設搜尋 | 清空關鍵字 / 排序 / 分頁回第一頁 | Tab0 工具列 | — |
| 4 | 租戶 / 部門 / 角色 欄位展開收合 | 每格預設顯示 3 個 Chip,超過顯示 +N...,點擊展開全部 /
收合 |
Tab0 每列 | — |
| 5 | 建立帳號 | 導向 user-form(新增模式) |
Tab0 工具列 | 使用者表單 |
| 6 | 編輯帳號 | 導向
user-form?uid=(編輯模式),可點「編輯」鈕或登入代碼連結 |
Tab0 每列 | 使用者表單 |
| 7 | 停用 / 啟用帳號 | 切換 status(1↔︎-1);對 admin
帳號與登入者自己隱藏此鈕 |
Tab0 每列 | §6.3 |
| 8 | 刪除帳號 | 軟刪除(status=-2);對 admin
與登入者自己隱藏此鈕 |
Tab0 每列 | §6.3 |
| 9 | Excel 批次上傳 | Tab1 三步精靈(下載範本 → 上傳解析 → 勾選批次建立) | Tab1 | Excel 批次匯入 |
展開成 UC(見 §2 索引):帳號本體 CRUD 與授權組合指派在 使用者表單(UC-USER-01/02)、Excel 批次匯入在 Excel 批次匯入(UC-USER-03)。停用 / 刪除屬單一動作,於本頁 §6.3 描述,不另開 UC 流程圖。
2. Use Case(索引)
角色速覽(完整定義見 _overview §2、§3):
| 角色 | 一句話 |
|---|---|
| 系統 / 租戶管理員(可見本選單者) | 帳號 CRUD + 授權組合指派 + 批次匯入 |
is_admin(超級管理員 JWT 旗標) |
額外可在編輯他人帳號時代改密碼;admin
帳號本身的敏感欄位鎖死 |
| 一般使用者 | 無此選單 |
本頁三條核心路徑展開成 UC,逐條在子頁:
| UC | 主題 | 所在子頁 |
|---|---|---|
| UC-USER-01 | 建立 / 編輯帳號主流程 | 使用者表單 |
| UC-USER-02 | 授權組合(租戶 × 部門 × 角色)指派 | 使用者表單 |
| UC-USER-03 | Excel 批次匯入三步 | Excel 批次匯入 |
列上的停用 / 啟用 / 刪除為單一動作,走本頁 §6.3。
3. 權限矩陣
專案層 RBAC 基調見 _overview §5。本頁(列表 + 列操作)的實際檢查點:
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 進入本頁 | ui_routes web-menu 可見性(user
相關能力) |
無端點層強制(僅 @jwt_required) |
api/auth/routes/user_route.py(全部 method) |
| 刪除帳號(軟刪) | FE 對 login_name=='admin' 與登入者自己隱藏刪除鈕 |
⚠️ 僅 @jwt_required,BE 未擋 admin /
自刪 |
user_route.py:103-110(UserRoute.delete) |
| 停用 / 啟用 | 同上(FE 隱藏規則相同) | ⚠️ 僅 @jwt_required,BE 未擋 admin /
自我停用 |
user_route.py:130-138(UserChangeStatusRoute.post) |
建立 / 編輯帳號的權限見 使用者表單 §3;Excel 批次匯入見 Excel 批次匯入 §3。
⚠️ 本頁列操作端點缺角色守門:
UserChangeStatusRoute與UserRoute.delete僅掛@jwt_required(),jedi-authupdate_user_status內部也無角色檢查——任何已登入帳號皆可透過直打 API 停用 / 刪除他人帳號(含admin,因「不可動 admin」只是 FE 隱藏按鈕)。與 _overview §5 及 role-manage.md §3 一致(本群多頁通病)。收進 §12。
4. 狀態機與前置條件
帳號本身狀態單純:users.status(0 未啟用 /
1 啟用 / -1 停用 / -2
軟刪除),無跨頁狀態機(不同於稽核輪次 7 態)。本頁(列表)gate:
| 條件 | 效果 | 出處 |
|---|---|---|
login_name === 'admin' 或
login_name === 登入者自己 |
FE 隱藏停用 / 啟用 / 刪除鈕 | UserManage.vue:254,261(v-if) |
| BE 寫入無狀態前置檢查 | update_user_status
本身不檢查呼叫者角色,任何狀態的帳號都可被切換(唯一狀態轉換在此專職) |
jedi-auth user_domain_service.py:169 |
表單頁 gate(admin 鎖死、mode EDIT 鎖登入名稱、is_admin 代改密碼、is_default 唯一規則)見 使用者表單 §4。
5. UI 設計
📸 實機截圖待補(亮色模式)。待補清單:Tab0 帳號列表(含租戶/部門/角色 Chip 展開態)、Tab1 Step1 上傳 dropzone、Tab1 Step2 預覽表格(含錯誤欄位紅字態)。
Tab0 列表頁骨架
狀態呈現:列表狀態欄以 system_menus 的
USER_STATUS group 轉譯文字(非直接顯示數字);Excel 匯入用
Steps 元件呈現 Step1(上傳)/ Step2(預覽),依
users.length 是否 > 0 自動判定(詳見 Excel 批次匯入
§5);表單頁狀態呈現見 使用者表單
§5。
6. API 規格
Envelope:成功 {"code": 1, "data": …}、失敗
{"code": 0, "msg": "…"}。
6.1 總清單(本 hub 呼叫的 endpoint)
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| 列表 | POST /api/1.0/users |
分頁查詢使用者(body 帶 pager / sort / filters) | §6.2 |
| 選單 | GET /api/1.0/users/menu |
使用者下拉(uid / login_name / nickname / email) | Swagger |
| 選單 | GET /api/1.0/system/menu/USER_STATUS |
帳號狀態下拉(system_menus code table) |
Swagger |
| 刪除 | DELETE /api/1.0/user/<uid> |
軟刪除(實際呼叫 update_user_status(REVOKE)) |
Swagger |
| 狀態 | POST /api/1.0/user/change-status/<uid> |
停用 / 啟用 / 軟刪除(body status) |
§6.3 |
帳號 CRUD(POST/PUT/GET /user)見 使用者表單 §6;Excel 匯入四支見 Excel 批次匯入 §6。
6.2 使用者列表
[POST] /api/1.0/users(列表)
Request(UserPageQueryRequest extends
RequestMetaSchema):
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
pager |
object | 否 | 分頁參數 {page, page_size, with_total} |
sort |
object | 否 | 排序參數 |
filters |
object | 否 | 查詢條件(UserQueryRequest),下列子欄位皆選填 |
filters.uid |
string | 否 | 對外識別碼 |
filters.login_name |
string | 否 | 登入代碼 |
filters.department_id |
int | 否 | 部門 id |
filters.job_title |
string | 否 | 職稱 |
filters.nickname |
string | 否 | 顯示名稱 |
filters.email |
string | 否 | |
filters.tel |
string | 否 | 電話 |
filters.effective_date |
date | 否 | 帳號生效日 |
filters.expire_date |
date | 否 | 帳號到期日 |
Response data[](UserResponse exclude
salt/password,api/auth/serializers/user.py:36-75)(陣列,每項):
| 欄位 | 型別 | 說明 |
|---|---|---|
id |
int | 內部序號 |
uid |
string | 對外識別碼 |
login_name |
string | 登入代碼 |
nickname |
string | 顯示名稱 |
email |
string | |
tel |
string | 電話 |
job_title |
string | 職稱 |
status |
int | 帳號狀態 |
department_id |
int | 部門 id |
tenant_id / tenant_uid /
tenant |
int / string / object | 預設租戶 id / uid / Nested |
tenants[] |
array | Nested TenantResponse,全部租戶 |
org_unit_id / org_unit_uid /
org_unit |
int / string / object | 預設部門 id / uid / Nested |
org_units[] |
array | Nested OrgUnitResponse,全部部門 |
roles[] |
array | Nested RoleResponse |
user_roles[] |
array | Nested UserRoleResponse |
user_tenants[] / user_org_units[] |
array | 使用者 ↔︎ 租戶 / 部門關聯 |
is_super_admin |
bool | 超級管理員旗標 |
employee_id |
string | 員工編號 |
effective_date / expire_date |
datetime | 帳號生效 / 到期日 |
mfa_type |
string | 多因素驗證類型 |
last_login_success_time /
last_login_failed_time /
login_failed_count |
datetime / datetime / int | 登入軌跡 |
created_user(+_name) /
created_at |
string / datetime | 建立者 login_name(+ nickname)/ 建立時間 |
updated_user(+_name) /
updated_at |
string / datetime | 更新者 login_name(+ nickname)/ 更新時間 |
出處:api/auth/routes/user_route.py:37-54(UsersRoute.post)→
app/auth/service/user_app_service.py:19-22(get_users_and_pager,批次
enrich
created_user_name/updated_user_name)。
單一使用者明細 GET /user/<uid>(含
auth_providers[])見 使用者表單
§6.2。
6.3 狀態變更
[POST]
/api/1.0/user/change-status/
Request:
{
"status": 0 // 1 啟用 / -1 停用 / -2 軟刪除
}(FE 只會送這三種值,BE
無值域檢查)。Response:BooleanResponse({result: true})。出處:user_route.py:130-138
→
user_domain_service.py:169(update_user_status)。FE
呼叫點:UserManage.vue:163(停用/啟用切換)、:183(刪除,固定送
-2)。DELETE /user/<uid> 內部亦委派
update_user_status(REVOKE)。
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/views/user-manage/UserManageTabView.vue |
route user-manage 的實際 component;包兩個
Tab(帳號管理 / Excel 批次上傳) |
src/views/user-manage/UserManage.vue |
Tab0:帳號列表 DataTable(搜尋 / 建立 / 每列操作 / 租戶部門角色 Chip 展開) |
src/views/user-manage/UserManageUpload.vue |
Tab1:Excel 批次上傳(詳見 Excel 批次匯入 §7) |
src/views/user-manage/UserMTRBACForm.vue |
route user-form(建立 / 編輯表單,詳見 使用者表單
§7) |
src/views/user-manage/UserProfileForm.vue |
個人資料頁(/user/user-profile),另屬 個人資料,非本頁 |
src/composables/useTableQuery.js |
列表分頁 / 排序 / 搜尋狀態共用邏輯(含 scope-by-route + scope-by-user) |
src/stores/queryStore.js |
持久化查詢狀態(供 useTableQuery
讀寫,支援「重置查詢」) |
src/config/api/api.js:32-42 |
USERS / USER / USER_MENU /
USER_CHANGE_STATUS 等端點常數 |
8. 後端檔案地圖
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| 使用者列表(enrich 暱稱) | api/auth/routes/user_route.py::UsersRoute |
app/auth/service/user_app_service.py::get_users_and_pager |
jedi-auth UserService.get_users_and_pager →
UserDomainService |
| 狀態變更 / 軟刪除 | user_route.py(UserChangeStatusRoute /
UserRoute.delete) |
直接委派 | jedi-auth
user_domain_service.py::update_user_status |
帳號 CRUD 鏈路見 使用者表單 §8;Excel 匯入鏈路見 Excel 批次匯入 §8。
DDD 提醒:使用者列表與狀態變更的 route 直接注入
jedi-auth 的 UserService,主專案在這條鏈路只有
UserAppService(列表暱稱 enrich)一個 app service。大半
domain 邏輯在 jedi-auth
套件(~/Projects/Jedicogy/module/jedi-python-package/jedi-auth/),改行為要分清邊界(CLAUDE.md
外部套件異動規範)。
9. DB
9.1 資料表總清單(本 hub 讀寫的表)
| 表 | 讀/寫 | 說明 | 詳述 |
|---|---|---|---|
public.users |
讀 / 寫(狀態欄) | 帳號本體;本頁列表讀、列操作寫 status |
使用者表單 §9.3 |
public.roles / public.tenants /
public.org_units |
讀 | 列表 Chip 顯示租戶 / 部門 / 角色 | _overview §6 |
public.system_menus |
讀 | USER_STATUS group:帳號狀態下拉文字 |
_overview §4 |
帳號本體與授權組合的寫入表(user_roles /
user_tenants / user_org_units /
改密相關)完整欄位卡見 使用者表單
§9。
9.2 ER 圖
10. 頁面邏輯與資料對應
關鍵欄位對應(列表 API ↔︎ 畫面):
| 畫面元素 | FE state | API 欄位 |
|---|---|---|
| 帳號狀態欄(列表) | statusMenu(system_menus/USER_STATUS)+
data.status |
transStatusCode() 轉譯 i18n |
| 租戶 / 部門 / 角色 Chip(列表) | data.tenants[] / data.org_units[] / data.roles[] |
UserResponse.tenants/org_units/roles(Nested
陣列) |
表單頁與 Excel 匯入的載入時序 / 欄位對應 / 儲存流程見 使用者表單 §10 與 Excel 批次匯入 §10。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| 通知 | 無(列表 / 列操作本身不發通知;帳號建立信在 使用者表單) |
| Job / 排程 | 無 |
| Socket | 無:帳號列表無即時推播,改動後靠前端重打
getUsers() |
| jedi-* 套件 | jedi-auth 擁有使用者 / 角色 / 租戶 / 部門的 service
/ domain / repo / ORM 全部邏輯;主專案僅列表
enrich(UserAppService)一個 wrapper |
| 系統參數 | 無 feature flag |
12. 邊界情況與已知坑
- 本頁列操作端點缺角色守門(同 角色權限管理
模式):
UserChangeStatusRoute與UserRoute.delete僅@jwt_required(),jedi-auth service 層也無角色檢查——任何登入帳號可直打 API 停用 / 軟刪除任何人(含admin,因「不可動」只是 FE 隱藏按鈕)。本 spec 只記錄不修。表單寫入與 Excel 匯入的同類坑見 使用者表單 §12 與 Excel 批次匯入 §12。 login_failed_count/last_login_*唯讀但可排序:這幾欄由登入流程寫入,本頁列表可排序顯示,但無編輯 UI(正確:不該有編輯 UI)。admin帳號的鎖死規則分散在多處判斷(本頁:列表停用/刪除鈕隱藏;表單頁另有生效/到期日禁用等,見 使用者表單 §12):皆為 FE 字串比對login_name==='admin',BE 無對應保護(見坑 1)——非 FE 判斷點若新增功能,記得同步排除admin。
13. 開發與驗證
- 跑起來:BE
python main_socketio.py(port 8000,log 在log/app.log);FE 在compliance-manager-fe/起 Vite dev server。BE 改 service code 後必須重啟(無 hot reload)。 - 測試帳號:管理員帳號見 memory
reference_dev_login/.env(憑證不寫入本文件)。 - 導航路徑:登入 →
側選單「系統管理」→「使用者管理」(
/auth/user-manage)→ Tab「帳號管理」或「Excel 批次上傳」。 - 前置資料:至少一個租戶 + 一個部門 +
一個角色(
tenant_id NULL的系統角色亦可)才能完成授權組合指派。 - E2E:
compliance-manager-test/repo(Cucumber + Playwright);本頁相關 feature 檔以使用者管理/user-manage搜尋。 - 相關文件:使用者表單(帳號本體 CRUD + 授權組合);Excel 批次匯入;權限系統設計說明書
docs/system-design/permission/;角色權限管理;功能群總覽。