feat(admin): Add user management and upgrade to module permission system

Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
This commit is contained in:
2026-01-16 13:42:10 +08:00
parent 98d862dbd4
commit 66255368b7
560 changed files with 70424 additions and 52353 deletions

View File

@@ -1,9 +1,10 @@
# **IIT Manager Agent 技术方案审查与补丁 (V1.1)**
## **1\. <EFBFBD><EFBFBD>靽格迤嚗朞圾<EFBFBD>喳龫<EFBFBD><EFBFBD>蝵𤏸<EFBFBD><EFBFBD>𡁏<EFBFBD>?*
## **1\. 架构修正:解决医院内网连通性**
<EFBFBD><EFBFBD> **憌𡡞埯銝<EFBFBD> (蝵𤑳<E89DB5>餈鮋<E9A488>𡁏<EFBFBD>?**嚗<>遣霈桀銁 3.1 REDCap <20><><EFBFBD> 銝剖<E98A9D><E58996>?**"瘛瑕<E7989B><E79195>峕郊璅<E79285>"**<EFBFBD>?
### **<2A><EFBFBD><E79285>嚗锭yncManager (<28>峕郊蝞∠<E89D9E><E288A0>?**
针对 **风险一 (网络连通性)**,建议在 3.1 REDCap 集成 中增加 **"混合同步模式"**
### **新增模块SyncManager (同步管理器)**
// backend/src/modules/iit-manager/services/SyncManager.ts
@@ -20,13 +21,13 @@ export class SyncManager {
}
/\*\*
\* 頧株砭隞餃𦛚憭<EFBFBD><EFBFBD><EFBFBD>?
\* 轮询任务处理器
\*/
async handlePoll(projectId: string) {
// 1\. 获取上次同步时间
const lastSync \= await this.getLastSyncTime(projectId);
// 2\. <EFBFBD> REDCap API <EFBFBD><EFBFBD><EFBFBD>冽迨銋见<EFBFBD>靽格㺿<EFBFBD><EFBFBD>扇敶?
// 2\. 调用 REDCap API 获取在此之后修改的记录
// API: 'export', content: 'record', dateRangeBegin: lastSync
const records \= await this.redcapAdapter.fetchModifiedRecords(projectId, lastSync);
@@ -41,31 +42,39 @@ export class SyncManager {
}
}
**靽格㺿撱箄悅**嚗?
* <20>?MVP <20>嗆挾嚗?*<EFBFBD><EFBFBD>摰䂿緵頧株砭 (Polling)**<2A><><EFBFBD><EFBFBD><E996AC><EFBFBD>駁堺<E9A781><E5A0BA><EFBFBD>蝏𦦵㴓憓<E3B493><E68693>?
## **2\. <20><EFBFBD>銵亙<E98AB5>嚗𡁜<E59A97><F0A1819C>脫㺭<E884AB><EFBFBD><E6A180>𤩺醌<F0A4A9BA>?*
**修改建议**
<EFBFBD><EFBFBD>笆 **憌𡡞埯鈭?(摮㗛<E691AE><E3979B>唳旿)**嚗<>遣霈桀⏚<E6A180>函緵<E587BD><EFBFBD> CheckpointService 摰䂿緵<E482BF><EFBFBD><E588B8><EFBFBD><E680A5>?
### **<2A><EFBFBD> API嚗𡁜<E59A97><F0A1819C>讛捶<E8AE9B>扯圻<E689AF>?*
* 在 MVP 阶段,**务必实现轮询 (Polling)**。不要赌医院的网络环境。
## **2\. 功能补充:历史数据全量扫描**
针对 **风险二 (存量数据)**,建议利用现有的 CheckpointService 实现全量扫描。
### **新增 API全量质控触发**
**Endpoint**: POST /api/v1/iit/projects/:id/scan-all
**<EFBFBD><EFBFBD>摰䂿緵 (憭滨鍂<E6BBA8><EFBFBD> ASL/DC 璅<E79285><E288AA><EFBFBD>鸌憭<E9B88C><E686AD>蝏誯<E89D8F>)**嚗?
1.<>鍂 REDCap API 隞<><E99A9E>頧賣<E9A0A7><E8B3A3>?record\_id (頧駁<E9A0A7>蝥?<3F>?
2. 撠?ID <20>𡑒”<F0A19192><E2809D><EFBFBD> (Chunk)嚗峕<E59A97><E5B395>?50 銝?ID<49>?
3. <EFBFBD>拍鍂 pg-boss <20><EFBFBD>?iit:quality-check:batch 隞餃𦛚<E9A483>?
4. Worker <20>𣂷葵<F0A382B7><EFBFBD>摰峕㟲<E5B395>唳旿撟嗉<E6929F>銵?Agent<6E>?
**逻辑实现 (复用现有 ASL/DC 模块的批处理经验)**
1. 调用 REDCap API 仅下载所有 record\_id (轻量级)。
2. 将 ID 列表分片 (Chunk),每片 50 个 ID。
3. 利用 pg-boss 推送 iit:quality-check:batch 任务。
4. Worker 逐个拉取完整数据并运行 Agent。
## **3\. 前端技术栈明确**
<EFBFBD><EFBFBD>銝剜<EFBFBD><EFBFBD><EFBFBD> "敺桐縑撠讐<E692A0>摨?嚗䔶<E59A97><E494B6><EFBFBD>蝖格<E89D96><E6A0BC><EFBFBD><E88880><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞祉緵<E7A589><EFBFBD> React <EFBFBD><EFBFBD>嚗?
* **<2A><EFBFBD><E588BB><EFBFBD>**嚗帋蝙<E5B88B>?**Taro** (React 霂剜<E99C82>) 撘<><E69298><EFBFBD>蝔见<E89D94><E8A781>?
* **<2A><>眏**嚗?
1. <20>臭誑霈拙<E99C88>蝡臬𣪧<E887AC><EFBFBD><E7AC94>?React <20><EFBFBD>嚗𠃍ooks, Components嚗剹<E59A97>?
2. <EFBFBD>臭誑憭滨鍂 shared/components 銝剔<E98A9D><E58994><EFBFBD><E585B8><EFBFBD><EFBFBD><E59A97><EFBFBD>唳旿<E594B3><EFBFBD><E6BE86><EFBFBD><E59094>?
3. Taro <20><EFBFBD><EFBFBD><E98A9D><EFBFBD>霂睲蛹 敺桐縑撠讐<E692A0>摨?\+ H5 (<28><EFBFBD><EFBFBD>凝靘扯器<E689AF>?嚗?*銝<>敼潔舅<E6BD94>?*<2A>?
## **4\. <20>唳旿摨?Schema 敺株<E695BA>**
方案中提到了 "微信小程序",但未明确技术栈。考虑到你们现有的 React 基因:
* **推荐方案**:使用 **Taro** (React 语法) 开发小程序。
* **理由**
1. 可以让前端团队复用 React 知识Hooks, Components
2. 可以复用 shared/components 中的部分逻辑(如数据格式化)。
3. Taro 支持一键编译为 微信小程序 \+ H5 (用于企微侧边栏)**一鱼两吃**。
## **4\. 数据库 Schema 微调**
在 IitUserMapping 表中,建议增加 Token 字段,用于小程序 Session 维护。
<EFBFBD>?IitUserMapping 銵其葉嚗<E89189>遣霈桀<E99C88><E6A180>?Token 摮埈挾嚗𣬚鍂鈭𤾸<E988AD>蝔见<E89D94> Session 蝏湔擪<E6B994>?
model IitUserMapping {
// ... 现有字段
@@ -76,17 +85,21 @@ model IitUserMapping {
@@index(\[miniProgramOpenId\])
}
## **5\. Dify RAG <EFBFBD><EFBFBD>隡睃<EFBFBD> (憸<><E686B8>頧?**
## **5\. Dify RAG 性能优化 (预加载)**
PRD 提到 "Protocol 往往很长"。
* **风险**:每次质控都让 Dify 重新检索整个 PDF速度慢且 Token 消耗大。
* **优化**:在 ProtocolService 中增加 **"关键规则缓存"**。
* 在上传 Protocol 后,让 Agent 预先提取出 "入排标准" (Inclusion/Exclusion Criteria) 并存入 PostgreSQL JSONB 字段。
* 在做基础质控时,优先匹配 DB 里的规则,匹配不到再由 Agent 去 RAG 检索。
PRD <20>𣂼<EFBFBD> "Protocol 敺<><EFBFBD><EFBFBD>鵭"<22>?
* **憌𡡞埯**嚗𡁏<E59A97>甈∟捶<E2889F><EFBFBD>霈?Dify <20>齿鰵璉<E9B0B5>㟲銝?PDF嚗屸<E59A97>笔漲<E7AC94><EFBFBD> Token 瘨<><E798A8>堒之<E5A092>?
* **隡睃<E99AA1>**嚗𡁜銁 ProtocolService 銝剖<E98A9D><E58996>?**"<22>喲睸閫<E79DB8><E996AB>蝻枏<E89DBB>"**<2A>?
* <20><EFBFBD>隡?Protocol <20>𠬍<EFBFBD>霈?Agent 憸<><E686B8><EFBFBD>𣂼<EFBFBD><F0A382BC>?"<22><EFBFBD><E4BAA4><EFBFBD><EFBFBD>" (Inclusion/Exclusion Criteria) 撟嗅<E6929F><E59785>?PostgreSQL JSONB 摮埈挾<E59F88>?
* <20><EFBFBD><E585B8><EFBFBD>韐冽綉<E586BD><EFBFBD>隡睃<E99AA1><E79D83><EFBFBD> DB <20>𣬚<EFBFBD><EFBFBD><E996AB><EFBFBD><EFBFBD><EFBFBD><E6BBA2><EFBFBD><E595A3>?Agent <20>?RAG 璉<><E89D9D>?
## **结论**
**甇斗䲮獢?V1.0 <20>臭誑<E887AD><EFBFBD><EFBFBD>恣嚗䔶<E59A97><EFBFBD>◆銵亙<E98AB5>銝𡃏膩 "Plan B" (頧株砭<EFBFBD><EFBFBD>)**<EFBFBD>?
**撘<><E69298><EFBFBD><E79DB2><EFBFBD>漣靚<E6BCA3>㟲撱箄悅**嚗?
1. **Day 1**: <20>唳旿摨?& <20><EFBFBD><E7AE87><EFBFBD> (銝滚<E98A9D>)
2. **Day 2**: **隡睃<E99AA1>摰䂿緵 REDCap API Adapter (<28><EFBFBD><E58CA7><EFBFBD>)**嚗諹<E59A97><EFBFBD><E494B6>?Webhook (<28><EFBFBD><E588B8><EFBFBD><EFBFBD>?<3F><><EFBFBD>銝?API <20><EFBFBD><E58CA7>游虾<E6B8B8><EFBFBD>銝磰<E98A9D><EFBFBD><E996AB><EFBFBD><EFBFBD><EFBFBD>唳旿<E594B3><EFBFBD><E6A185>?
3. **Day 3**: Webhook 銵亙<E98AB5>摰䂿緵 (雿靝蛹<E99D9D>單𧒄<E596AE><EFBFBD>撘?<3F>
**此方案 V1.0 可以通过评审,但必须补充上述 "Plan B" (轮询机制)**
**开发优先级调整建议**
1. **Day 1**: 数据库 & 基础架构 (不变)
2. **Day 2**: **优先实现 REDCap API Adapter (拉取能力)**,而不是 Webhook (推送能力)。因为 API 拉取更可控,且能解决历史数据问题。
3. **Day 3**: Webhook 补充实现 (作为即时性增强)。