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,56 +1,56 @@
# Day 4寮€鍙戣<EFBFBD>褰曪細鏁版嵁搴撹<EFBFBD>笌鎵瑰<EFBFBD>鐞嗘湇鍔″紑鍙?
# Day 4开发记录:数据库设计与批处理服务开发
> **鏃ユ湡**锛?025-11-23
> **寮€鍙戣€?*锛欰SL寮€鍙戝洟闃?
> **日期**2025-11-23
> **开发者**ASL开发团队
> **阶段**全文复筛MVP - Day 4
> **鐘舵€?*锛氣渽 宸插畬鎴?
> **状态**:✅ 已完成
---
## 馃搵 寮€鍙戠洰鏍?
## 📋 开发目标
**Day 4涓婂崍**锛氬畬鎴愭暟鎹<E69A9F>簱璁捐<E79281>涓庤縼绉?
**Day 4涓嬪崍**锛氬紑鍙戞壒澶勭悊鏈嶅姟锛團ulltextScreeningService锛?
**Day 4上午**:完成数据库设计与迁移
**Day 4下午**开发批处理服务FulltextScreeningService
---
## 鉁?Day 4涓婂崍锛氭暟鎹<EFBFBD>簱璁捐<EFBFBD>涓庤縼绉?
## Day 4上午:数据库设计与迁移
### 1. Schema设计
#### 1.1 <EFBFBD> AslLiterature 琛?
#### 1.1 修改 AslLiterature
新增13个全文复筛相关字段
**鏂囩尞鐢熷懡鍛ㄦ湡**锛?
- `stage` - 闃舵<EFBFBD>鏍囪<EFBFBD>锛坕mported/title_screened/fulltext_pending/fulltext_screened锛?
**文献生命周期**
- `stage` - 阶段标记imported/title_screened/fulltext_pending/fulltext_screened
**PDF绠$悊**锛?
**PDF管理**
- `has_pdf` - 是否有PDF
- `pdf_storage_type` - 瀛樺偍绫诲瀷锛坥ss/dify/local锛?
- `pdf_storage_type` - 存储类型oss/dify/local
- `pdf_storage_ref` - 存储引用
- `pdf_status` - 鐘舵€侊紙pending/extracting/completed/failed锛?
- `pdf_status` - 状态(pending/extracting/completed/failed
- `pdf_uploaded_at` - 上传时间
**鍏ㄦ枃绠$悊锛堜簯鍘熺敓锛?*锛?
- `full_text_storage_type` - 瀛樺偍绫诲瀷锛坥ss/dify锛?
**全文管理(云原生)**
- `full_text_storage_type` - 存储类型oss/dify
- `full_text_storage_ref` - 存储引用
- `full_text_url` - 访问URL
**鍏ㄦ枃鍏冩暟鎹?*锛?
- `full_text_format` - 鏍煎紡锛坢arkdown/plaintext锛?
- `full_text_source` - 鎻愬彇鏂瑰紡锛坣ougat/pymupdf锛?
**全文元数据**
- `full_text_format` - 格式markdown/plaintext
- `full_text_source` - 提取方式nougat/pymupdf
- `full_text_token_count` - Token数量
- `full_text_extracted_at` - 提取时间
**璁捐<EFBFBD><EFBFBD>偣**锛?
- 鉁?**浜戝師鐢熸灦鏋?*锛氬叏鏂囧瓨鍌ㄥ湪OSS/Dify锛屾暟鎹<E69A9F>簱鍙<E7B0B1>瓨寮曠敤
- 鉁?**绗﹀悎瑙勮寖**锛氶伒寰<E4BC92>€婁簯鍘熺敓寮€鍙戣<E98D99>鑼冦€嬶紝涓嶅湪鏁版嵁搴撳瓨鍌ㄥぇ鏂囨湰
- 鉁?**鍙<>墿灞曟€?*锛氭敮鎸佸<E98EB8>绉嶅瓨鍌ㄦ柟寮忕殑閫傞厤鍣ㄦā寮?
**设计亮点**
- **云原生架构**全文存储在OSS/Dify数据库只存引用
- **符合规范**:遵循《云原生开发规范》,不在数据库存储大文本
- **可扩展性**:支持多种存储方式的适配器模式
#### 1.2 鏂板缓 AslFulltextScreeningTask 琛?
#### 1.2 新建 AslFulltextScreeningTask
浠诲姟绠悊琛<EFBFBD>紝瀛楁<EFBFBD>鍖呮嫭锛?
任务管理表,字段包括:
- 基础信息:`id`, `project_id`
- 模型配置:`model_a`, `model_b`, `prompt_version`
- 进度跟踪:`total_count`, `processed_count`, `success_count`, `failed_count`, `degraded_count`
@@ -58,34 +58,34 @@
- 状态管理:`status`, `started_at`, `completed_at`, `estimated_end_at`
- 错误记录:`error_message`, `error_stack`
**璁捐<EFBFBD><EFBFBD>偣**锛?
- 鉁?**瀹炴椂杩涘害**锛氭敮鎸佸墠绔<E5A2A0>疆璇<E79686>换鍔¤繘搴?
- 鉁?**鎴愭湰璺熻釜**锛氱疮璁<E796AE>oken鍜岃垂鐢?
- 鉁?**棰勪及鏃堕棿**锛氬姩鎬佽<E98EAC>绠楀墿浣欐椂闂?
**设计亮点**
- **实时进度**:支持前端轮询任务进度
- **成本跟踪**累计Token和费用
- **预估时间**:动态计算剩余时间
#### 1.3 鏂板缓 AslFulltextScreeningResult 琛?
#### 1.3 新建 AslFulltextScreeningResult
缁撴灉瀛樺偍琛<EFBFBD>紙12瀛楁<EFBFBD>妯℃澘锛夛紝瀛楁<EFBFBD>鍖呮嫭锛?
- **鍙屾ā鍨嬬粨鏋?*锛歁odel A (DeepSeek-V3) 鍜?Model B (Qwen-Max) 鐨勫畬鏁磋緭鍑?
结果存储表12字段模板字段包括
- **双模型结果**Model A (DeepSeek-V3) Model B (Qwen-Max) 的完整输出
- **验证结果**:医学逻辑验证、证据链验证
- **鍐茬獊妫€娴?*锛氬瓧娈电骇鍐茬獊瀵规瘮銆佷紭鍏堢骇鎺掑簭
- **浜哄伐澶嶆牳**锛氭渶缁堝喅绛栥€佹帓闄ゅ師鍥犮€佸<E282AC>鏍哥瑪璁?
- **<EFBFBD>拷婧<EFBFBD>€?*锛氬師濮嬭緭鍑恒€丳rompt鐗堟湰銆佸<E98A86>鐞嗘椂闂?
- **冲突检测**:字段级冲突对比、优先级排序
- **人工复核**:最终决策、排除原因、复核笔记
- **可追溯性**原始输出、Prompt版本、处理时间
**璁捐<EFBFBD><EFBFBD>偣**锛?
- 鉁?**JSONB瀛樺偍**锛?2瀛楁<E7809B>鐏垫椿瀛樺偍锛屾敮鎸侀珮鏁堟煡璇?
- 鉁?**鍙屾ā鍨嬪<E98DA8>姣?*锛氬畬鏁翠繚瀛樹袱涓<E8A2B1>ā鍨嬬殑杈撳嚭
- 鉁?**鍐茬獊浼樺厛绾?*锛氳嚜鍔ㄨ<E98D94>绠梤eview_priority锛?-100锛?
- 鉁?**鍙<><E98D99>璁?*锛氫繚鐣檙aw_output锛屽彲杩芥函LLM鍘熷<E98D98>鍝嶅簲
**设计亮点**
- **JSONB存储**12字段灵活存储支持高效查询
- **双模型对比**:完整保存两个模型的输出
- **冲突优先级**自动计算review_priority0-100
- **可审计**保留raw_output可追溯LLM原始响应
### 2. 迁移策略
#### 2.1 问题识别
鍦ㄨ縼绉昏繃绋嬩腑鍙戠幇锛?
在迁移过程中发现:
- ⚠️ 历史遗留问题:部分模块的表创建在 `public` schema
- 鉁?ASL妯″潡鏁版嵁瀹屽叏姝g‘锛氭墍鏈夎〃閮藉湪 `asl_schema`
- 鈿狅笍 Prisma Migrate浼氬皾璇曞垹闄?`public` <EFBFBD>殑閲嶅<EFBFBD>琛?
- ASL模块数据完全正确:所有表都在 `asl_schema`
- ⚠️ Prisma Migrate会尝试删除 `public` 中的重复表
#### 2.2 解决方案手动SQL迁移
@@ -98,46 +98,46 @@ CREATE TABLE IF NOT EXISTS asl_schema.fulltext_screening_tasks (...);
CREATE TABLE IF NOT EXISTS asl_schema.fulltext_screening_results (...);
```
**鎵ц<EFBFBD>**锛?
**执行**
```bash
Get-Content manual_fulltext_screening.sql | docker exec -i ai-clinical-postgres psql ...
```
**楠岃瘉**锛?
**验证**
```sql
\dt asl_schema.*
-- 缁撴灉锛?涓<>
-- 鉁?literatures (宸叉洿鏂?
-- 鉁?screening_projects
-- 鉁?screening_tasks
-- 鉁?screening_results
-- 鉁?fulltext_screening_tasks (鏂板缓)
-- 鉁?fulltext_screening_results (鏂板缓)
-- 结果6个表
-- literatures (已更新)
-- screening_projects
-- screening_tasks
-- screening_results
-- fulltext_screening_tasks (新建)
-- fulltext_screening_results (新建)
```
#### 2.3 Schema隔离验证
**妫€鏌ョ粨鏋?*锛?
- 鉁?ASL妯″潡鎵€鏈?涓<>〃閮藉湪 `asl_schema`
- 鉁?鏃犳暟鎹<E69A9F>硠婕忓埌 `public` schema
- 鉁?澶栭敭绾︽潫鍏ㄩ儴鎸囧悜 `asl_schema` 鍐呴儴
- 鉁?Prisma Model姝g‘鏄犲皠锛坄@@schema("asl_schema")`锛?
**检查结果**
- ASL模块所有6个表都在 `asl_schema`
- ✅ 无数据泄漏到 `public` schema
- ✅ 外键约束全部指向 `asl_schema` 内部
- Prisma Model正确映射(`@@schema("asl_schema")`
**鐩稿叧鏂囨。**锛?
- [鏁版嵁搴撹縼绉荤姸鎬佽<EFBFBD>鏄嶿(./2025-11-23_鏁版嵁搴撹縼绉荤姸鎬佽<E98EAC>鏄?md)
- [鏁版嵁搴撹<EFBFBD>璁℃枃妗<EFBFBD>(../02-鎶€鏈<E282AC><E98F88>璁?01-鏁版嵁搴撹<E690B4>璁?md)
**相关文档**
- [数据库迁移状态说明](./2025-11-23_数据库迁移状态说明.md)
- [数据库设计文档](../02-技术设计/01-数据库设计.md)
### 3. 产出
- 鉁?Prisma Schema鏇存柊锛?涓<>ā鍨嬶級
- 鉁?鎵嬪姩SQL杩佺Щ鑴氭湰锛?41琛岋級
- 鉁?鏁版嵁搴撹縼绉荤姸鎬佽<E98EAC>鏄庢枃妗紙435琛岋級
- 鉁?鏁版嵁搴撹<E690B4>璁℃枃妗洿鏂帮紙v3.0锛?
- 鉁?妯″潡鐘舵€佹枃妗f洿鏂帮紙v1.2锛?
- Prisma Schema更新3个模型
- ✅ 手动SQL迁移脚本141行
- ✅ 数据库迁移状态说明文档435行
- ✅ 数据库设计文档更新(v3.0
- ✅ 模块状态文档更新(v1.2
---
## 鉁?Day 4涓嬪崍锛氭壒澶勭悊鏈嶅姟寮€鍙?
## Day 4下午:批处理服务开发
### 1. 核心服务FulltextScreeningService
@@ -145,11 +145,11 @@ Get-Content manual_fulltext_screening.sql | docker exec -i ai-clinical-postgres
| 职责 | 说明 |
|------|------|
| **浠诲姟璋冨害** | 鎵归噺澶勭悊鏂囩尞锛屽苟鍙戞帶鍒?|
| **鏈嶅姟闆嗘垚** | 璋冪敤LLM鏈嶅姟銆侀獙璇佸櫒銆佸啿绐佹<EFBFBD>娴?|
| **杩涘害璺熻釜** | 瀹炴椂鏇存柊浠诲姟杩涘害锛岃<EFBFBD>绠楅<EFBFBD>浼版椂闂?|
| **瀹归敊澶勭悊** | 閲嶈瘯鏈哄埗銆侀檷绾фā寮忋€侀敊璇<EFBFBD><EFBFBD>褰?|
| **鏁版嵁鎸佷箙鍖?* | 淇濆瓨澶勭悊缁撴灉鍒版暟鎹<E69A9F> |
| **任务调度** | 批量处理文献,并发控制 |
| **服务集成** | 调用LLM服务、验证器、冲突检测 |
| **进度跟踪** | 实时更新任务进度,计算预估时间 |
| **容错处理** | 重试机制、降级模式、错误记录 |
| **数据持久化** | 保存处理结果到数据库 |
#### 1.2 核心方法
@@ -163,10 +163,10 @@ async createAndProcessTask(
): Promise<string>
```
鍔熻兘锛?
- 楠岃瘉椤圭洰鍜屾枃鐚<EFBFBD>暟鎹?
功能:
- 验证项目和文献数据
- 创建任务记录
- <EFBFBD>姩鍚庡彴澶勭悊锛堜笉绛夊緟瀹屾垚锛?
- 启动后台处理(不等待完成)
- 返回任务ID
**2. processTaskInBackground() - 后台批处理逻辑**
@@ -180,15 +180,15 @@ private async processTaskInBackground(
): Promise<void>
```
鍔熻兘锛?
- 鏇存柊浠诲姟鐘舵€佷负"杩愯<E69DA9>涓?
- 鏋勫缓PICOS涓婁笅鏂?
- 浣跨敤 `p-queue` 瀹炵幇骞跺彂鎺у埗锛堥粯璁ゅ苟鍙?锛?
功能:
- 更新任务状态为"运行中"
- 构建PICOS上下文
- 使用 `p-queue` 实现并发控制默认并发3
- 调用 `screenLiteratureWithRetry()` 处理每篇文献
- <EFBFBD><EFBFBD>缁熻<EFBFBD>锛坰uccess/failed/degraded/tokens/cost锛?
- 累计统计success/failed/degraded/tokens/cost
- 标记任务完成
**3. screenLiteratureWithRetry() - 鍗曠瘒澶勭悊锛堝甫閲嶈瘯锛?*
**3. screenLiteratureWithRetry() - 单篇处理(带重试)**
```typescript
private async screenLiteratureWithRetry(
@@ -200,10 +200,10 @@ private async screenLiteratureWithRetry(
): Promise<SingleLiteratureResult>
```
鍔熻兘锛?
- 鏈€澶氶噸璇?娆★紙鍙<E7B499>厤缃<E58EA4>
- 鎸囨暟閫€閬跨瓥鐣ワ紙1s, 2s锛?
- 鎹曡幏骞惰<EFBFBD>褰曢敊璇?
功能:
- 最多重试2次可配置
- 指数退避策略(1s, 2s
- 捕获并记录错误
**4. screenLiterature() - 单篇处理核心逻辑**
@@ -217,14 +217,14 @@ private async screenLiterature(
): Promise<SingleLiteratureResult>
```
鍔熻兘锛?
1. 鑾峰彇鍏ㄦ枃鍐呭<EFBFBD>锛堟敮鎸佹祴璇曟ā寮忥細璺宠繃PDF鎻愬彇锛?
2. 璋冪敤 `LLM12FieldsService.processDualModels()`锛堝弻妯″瀷骞惰<EFBFBD>锛?
3. 鍖诲<EFBFBD>閫昏緫楠岃瘉锛坄MedicalLogicValidator`锛?
4. 璇佹嵁閾鹃獙璇侊紙`EvidenceChainValidator`锛?
5. 鍐茬獊妫€娴嬶紙`ConflictDetectionService`锛?
功能:
1. 获取全文内容支持测试模式跳过PDF提取
2. 调用 `LLM12FieldsService.processDualModels()`(双模型并行)
3. 医学逻辑验证(`MedicalLogicValidator`
4. 证据链验证(`EvidenceChainValidator`
5. 冲突检测(`ConflictDetectionService`
6. 保存结果到数据库(`fulltext_screening_results`表)
7. 杩斿洖澶勭悊缁撴灉锛坱okens銆乧ost銆乮sDegraded锛?
7. 返回处理结果tokens、cost、isDegraded
**5. updateTaskProgress() - 进度更新**
@@ -235,10 +235,10 @@ private async updateTaskProgress(
): Promise<void>
```
鍔熻兘锛?
功能:
- 计算平均处理时间
- 棰勪及鍓╀綑鏃堕棿锛坋stimatedEndAt锛?
- 鏇存柊鏁版嵁搴擄紙processed/success/failed/degraded/tokens/cost锛?
- 预估剩余时间estimatedEndAt
- 更新数据库(processed/success/failed/degraded/tokens/cost
**6. completeTask() - 任务完成**
@@ -249,9 +249,9 @@ private async completeTask(
): Promise<void>
```
鍔熻兘锛?
- 鏍囪<EFBFBD>浠诲姟鐘舵€侊紙completed/failed锛?
- 鏇存柊鏈€缁堢粺璁?
功能:
- 标记任务状态(completed/failed
- 更新最终统计
- 记录完成时间
#### 1.3 查询接口
@@ -262,11 +262,11 @@ private async completeTask(
async getTaskProgress(taskId: string): Promise<ScreeningProgress | null>
```
杩斿洖锛?
- 浠诲姟鐘舵€侊紙pending/running/completed/failed锛?
- 杩涘害缁熻<EFBFBD>锛坧rocessed/success/failed/degraded锛?
- 鎴愭湰缁熻<EFBFBD>锛坱otalTokens/totalCost锛?
- 鏃堕棿淇℃伅锛坰tarted/completed/estimatedEnd锛?
返回:
- 任务状态(pending/running/completed/failed
- 进度统计processed/success/failed/degraded
- 成本统计totalTokens/totalCost
- 时间信息started/completed/estimatedEnd
**getTaskResults() - 查询任务结果**
@@ -277,10 +277,10 @@ async getTaskResults(
): Promise<{ results, total }>
```
鍔熻兘锛?
功能:
- 支持过滤(仅冲突项)
- 分页查询
- 鎸変紭鍏堢骇鎺掑簭锛堝啿绐佷紭鍏堛€乺eview_priority闄嶅簭锛?
- 按优先级排序冲突优先、review_priority降序)
**updateReviewDecision() - 更新人工复核决策**
@@ -291,12 +291,12 @@ async updateReviewDecision(
): Promise<void>
```
鍔熻兘锛?
- 鏇存柊鏈€缁堝喅绛栵紙include/exclude锛?
功能:
- 更新最终决策(include/exclude
- 记录复核人和时间
- 璁板綍鎺掗櫎鍘熷洜鍜岀瑪璁?
- 记录排除原因和笔记
### 2. 鎶€鏈<EFBFBD>寒鐐?
### 2. 技术亮点
#### 2.1 并发控制
@@ -314,26 +314,26 @@ const tasks = literatures.map((literature, index) =>
await Promise.all(tasks);
```
**浼樺娍**锛?
- 鉁?鑷<>姩鎺掗槦锛岄伩鍏嶅悓鏃跺彂璧疯繃澶歀LM璇锋眰
- 鉁?鎺у埗API璋冪敤棰戠巼锛岄槻姝㈣Е鍙戦檺娴?
- 鉁?鍏呭垎鍒╃敤骞跺彂锛屾彁閫?鍊嶏紙涓茶<E6B693>鈫?骞跺彂锛?
**优势**
- ✅ 自动排队避免同时发起过多LLM请求
- ✅ 控制API调用频率防止触发限流
- ✅ 充分利用并发提速3倍串行→3并发
#### 2.2 容错机制
**3灞傚<EFBFBD>閿?*锛?
1. **Retry灞?*锛氬崟绡囨枃鐚<E69E83>け璐ヨ嚜鍔ㄩ噸璇曪紙鏈€澶?娆★級
2. **Degraded灞?*锛歀LM12FieldsService<EFBFBD>寔闄嶇骇妯″紡锛堝崟妯″瀷鎴愬姛鍗冲彲锛?
3. **Continue灞?*锛氬崟绡囧け璐ヤ笉褰卞搷鏁翠綋锛岀户缁<E688B7><E7BC81>鐞嗗叾浠栨枃鐚?
**3层容错**
1. **Retry**单篇文献失败自动重试最多2次
2. **Degraded**LLM12FieldsService支持降级模式(单模型成功即可)
3. **Continue**:单篇失败不影响整体,继续处理其他文献
**鏁堟灉**锛?
- 鉁?闄嶄綆澶辫触鐜?
- 鉁?鎻愰珮浠诲姟瀹屾垚鐜?
- 鉁?瀹屾暣璁板綍澶辫触鍘熷洜
**效果**
- ✅ 降低失败率
- ✅ 提高任务完成率
- ✅ 完整记录失败原因
#### 2.3 测试模式
<EFBFBD> `skipExtraction: true` 娴嬭瘯妯″紡锛?
支持 `skipExtraction: true` 测试模式:
```typescript
if (config.skipExtraction) {
@@ -344,10 +344,10 @@ if (config.skipExtraction) {
}
```
**浼樺娍**锛?
- 鉁?蹇<>€熼獙璇佹湇鍔¢€昏緫
- 鉁?鏃犻渶鐪熷疄PDF鏂囦欢
- 鉁?鑺傜渷娴嬭瘯鎴愭湰
**优势**
- ✅ 快速验证服务逻辑
- ✅ 无需真实PDF文件
- ✅ 节省测试成本
#### 2.4 实时进度跟踪
@@ -359,26 +359,26 @@ const remainingItems = totalCount - processedCount;
const estimatedRemainingTime = avgTimePerItem * remainingItems;
```
**鐢ㄦ埛浣撻獙**锛?
- 鉁?鍓嶇<E98D93><EFBFBD>疆璇㈡樉绀鸿繘搴?
- 鉁?鏄剧ず棰勪及瀹屾垚鏃堕棿
- 鉁?瀹炴椂鏄剧ず鎴愭湰缁熻<E7BC81>
**用户体验**
- ✅ 前端可轮询显示进度
- ✅ 显示预估完成时间
- ✅ 实时显示成本统计
### 3. 集成测试
鍒涘缓浜嗗畬鏁寸殑闆嗘垚娴嬭瘯鑴氭湰锛?
创建了完整的集成测试脚本:
**娴嬭瘯鍦烘櫙**锛?
1. 鉁?鍑嗗<E98D91>娴嬭瘯鏁版嵁锛堟煡鎵鹃」鐩<E3808D>拰鏂囩尞锛?
2. 鉁?鍒涘缓骞跺<E9AA9E>鐞嗕换鍔★紙娴嬭瘯妯″紡锛?绡囨枃鐚<E69E83>紝2骞跺彂锛?
3. 鉁?杞<><E69D9E>浠诲姟杩涘害锛堟瘡5绉掞級
4. 鉁?鏌ヨ<E98F8C>浠诲姟缁撴灉锛堝垎椤碉紝鎺掑簭锛?
5. 鉁?鏇存柊浜哄伐澶嶆牳鍐崇瓥
**测试场景**
1. ✅ 准备测试数据(查找项目和文献)
2. ✅ 创建并处理任务测试模式3篇文献2并发
3. ✅ 轮询任务进度每5秒
4. ✅ 查询任务结果(分页,排序)
5. ✅ 更新人工复核决策
**娴嬭瘯鏂囦欢**锛?
- `service-integration-test.ts` (绾?00琛?
**测试文件**
- `service-integration-test.ts` (约200行)
**杩愯<EFBFBD>鏂瑰紡**锛?
**运行方式**
```bash
cd backend
npx ts-node src/modules/asl/fulltext-screening/services/__tests__/service-integration-test.ts
@@ -386,19 +386,19 @@ npx ts-node src/modules/asl/fulltext-screening/services/__tests__/service-integr
### 4. 产出
**浠g爜**锛?
- 鉁?`FulltextScreeningService.ts` (绾?00琛?
- 鉁?闆嗘垚娴嬭瘯鑴氭湰 (绾?00琛?
- 鉁?TypeScript绫诲瀷瀹氫箟瀹屾暣
- 鉁?浠g爜娉ㄩ噴璇︾粏
**代码**
- `FulltextScreeningService.ts` (约700行)
- ✅ 集成测试脚本 (约200行)
- TypeScript类型定义完整
- ✅ 代码注释详细
**渚濊禆**锛?
- 鉁?瀹夎<E780B9> `p-queue` 搴?
**依赖**
- ✅ 安装 `p-queue`
**璐ㄩ噺**锛?
- 鉁?鏃燣inter閿欒<EFBFBD>
- 鉁?瀹屾暣鐨勯敊璇<E6958A><E79287>鐞?
- 鉁?璇︾粏鐨勬棩蹇楄<E8B987>褰?
**质量**
- ✅ 无Linter错误
- ✅ 完整的错误处理
- ✅ 详细的日志记录
---
@@ -406,101 +406,101 @@ npx ts-node src/modules/asl/fulltext-screening/services/__tests__/service-integr
### 时间分配
| 闃舵<EFBFBD> | 浠诲姟 | 鑰楁椂 | 鐘舵€?|
| 阶段 | 任务 | 耗时 | 状态 |
|------|------|------|------|
| **涓婂崍** | 鏁版嵁搴撹<EFBFBD>璁?| 1h | 鉁?|
| | Schema璁捐<EFBFBD>锛?涓<>ā鍨嬶級 | 30min | 鉁?|
| | 鎵嬪姩SQL杩佺Щ | 20min | 鉁?|
| | Schema闅旂<EFBFBD>楠岃瘉 | 10min | 鉁?|
| | 鏂囨。缂栧啓锛堣縼绉荤姸鎬佽<EFBFBD>鏄庯級 | 30min | 鉁?|
| | 鏂囨。鏇存柊锛堣<EFBFBD>璁℃枃妗€佺姸鎬佹枃妗 | 20min | 鉁?|
| **涓嬪崍** | 鎵瑰<EFBFBD>鐞嗘湇鍔″紑鍙?| 2h | 鉁?|
| | 鏈嶅姟鏍稿績閫昏緫 | 1h | 鉁?|
| | 闆嗘垚娴嬭瘯鑴氭湰 | 30min | 鉁?|
| | 浠g爜瀹℃煡涓庝紭鍖?| 30min | 鉁?|
| **鍚堣<EFBFBD>** | | 3h | 鉁?|
| **上午** | 数据库设计 | 1h | |
| | Schema设计3个模型 | 30min | |
| | 手动SQL迁移 | 20min | |
| | Schema隔离验证 | 10min | |
| | 文档编写(迁移状态说明) | 30min | |
| | 文档更新(设计文档、状态文档) | 20min | |
| **下午** | 批处理服务开发 | 2h | |
| | 服务核心逻辑 | 1h | |
| | 集成测试脚本 | 30min | |
| | 代码审查与优化 | 30min | |
| **合计** | | 3h | |
### 代码产出
| 类别 | 文件 | 行数 | 说明 |
|------|------|------|------|
| **鏍稿績鏈嶅姟** | FulltextScreeningService.ts | ~700 | 鎵瑰<EFBFBD>鐞嗘湇鍔?|
| **核心服务** | FulltextScreeningService.ts | ~700 | 批处理服务 |
| **测试** | service-integration-test.ts | ~200 | 集成测试 |
| **鏁版嵁搴?* | manual_fulltext_screening.sql | 141 | 杩佺Щ鑴氭湰 |
| **鏂囨。** | 鏁版嵁搴撹縼绉荤姸鎬佽<EFBFBD>鏄?| 435 | 璇︾粏璁板綍 |
| **鏂囨。** | Day 4寮€鍙戣<EFBFBD>褰?| ~800 | <EFBFBD>枃妗?|
| **数据库** | manual_fulltext_screening.sql | 141 | 迁移脚本 |
| **文档** | 数据库迁移状态说明 | 435 | 详细记录 |
| **文档** | Day 4开发记录 | ~800 | 本文档 |
| **合计** | | ~2,276 | |
### 鍔熻兘瀹屾垚搴?
### 功能完成度
| 鍔熻兘妯″潡 | 瀹屾垚搴?| 璇存槑 |
| 功能模块 | 完成度 | 说明 |
|---------|--------|------|
| 鏁版嵁搴撹<EFBFBD>璁?| 100% 鉁?| 3<EFBFBD>〃锛?3涓<33>柊瀛楁<E7809B> |
| 鏁版嵁搴撹縼绉?| 100% 鉁?| 鎵嬪姩SQL锛屽畨鍏ㄦ墽琛?|
| 浠诲姟鍒涘缓涓庤皟搴?| 100% 鉁?| 鏀<>寔骞跺彂鎺у |
| 鍗曠瘒鏂囩尞澶勭悊 | 100% 鉁?| 闆嗘垚鎵€鏈夐獙璇佸櫒 |
| 杩涘害璺熻釜 | 100% 鉁?| 瀹炴椂鏇存柊锛岄<E9949B>浼版椂闂?|
| 瀹归敊澶勭悊 | 100% 鉁?| 閲嶈瘯銆侀檷绾с€佺户缁?|
| 鏌ヨ<EFBFBD>鎺ュ彛 | 100% 鉁?| 杩涘害銆佺粨鏋溿€佸喅绛?|
| 闆嗘垚娴嬭瘯 | 100% 鉁?| 绔<>埌绔<E59F8C>祴璇曡剼鏈?|
| 数据库设计 | 100% | 3个表13个新字段 |
| 数据库迁移 | 100% ✅ | 手动SQL安全执行 |
| 任务创建与调度 | 100% ✅ | 支持并发控制 |
| 单篇文献处理 | 100% ✅ | 集成所有验证器 |
| 进度跟踪 | 100% ✅ | 实时更新,预估时间 |
| 容错处理 | 100% ✅ | 重试、降级、继续 |
| 查询接口 | 100% ✅ | 进度、结果、决策 |
| 集成测试 | 100% ✅ | 端到端测试脚本 |
---
## 🎯 关键决策
### 1. 浜戝師鐢熷瓨鍌ㄦ柟妗?鉁?
### 1. 云原生存储方案 ✅
**决策**全文内容存储在OSS/Dify数据库只存引用
**鐞嗙敱**锛?
- 绗﹀悎銆婁簯鍘熺敓寮€鍙戣<EFBFBD>鑼冦€?
**理由**
- 符合《云原生开发规范》
- 避免数据库膨胀
- <EFBFBD>寔澶ц<EFBFBD>妯℃墿灞?
- 支持大规模扩展
**瀹炵幇**锛?
- `full_text_storage_type` - 瀛樺偍绫诲瀷锛坥ss/dify锛?
- `full_text_storage_ref` - 瀛樺偍寮曠敤锛坘ey鎴朓D锛?
**实现**
- `full_text_storage_type` - 存储类型oss/dify
- `full_text_storage_ref` - 存储引用key或ID
- `full_text_url` - 访问URL
### 2. 鎵嬪姩SQL杩佺Щ绛栫暐 鉁?
### 2. 手动SQL迁移策略 ✅
**决策**:不使用 `prisma migrate`而是手动编写SQL脚本
**鐞嗙敱**锛?
- Prisma Migrate浼氬皾璇曞垹闄?`public` schema<EFBFBD>殑閲嶅<EFBFBD>琛?
- <EFBFBD>兘褰卞搷鍏朵粬妯″潡锛圓IA銆丳KB銆丳latform锛?
**理由**
- Prisma Migrate会尝试删除 `public` schema中的重复表
- 可能影响其他模块AIA、PKB、Platform
- 手动SQL更安全、可控、可审计
**鍘熷垯**锛?
**原则**
- "管好自己":只操作 `asl_schema`
- 不动 `public` schema不影响其他模块
### 3. 娴嬭瘯妯″紡璁捐<EFBFBD> 鉁?
### 3. 测试模式设计 ✅
**鍐崇瓥**锛氭敮鎸?`skipExtraction: true` 娴嬭瘯妯″紡
**决策**:支持 `skipExtraction: true` 测试模式
**鐞嗙敱**锛?
**理由**
- 快速验证服务逻辑
- 无需准备真实PDF文件
- 鑺傜渷娴嬭瘯鎴愭湰鍜屾椂闂?
- 节省测试成本和时间
**瀹炵幇**锛?
**实现**
```typescript
if (config.skipExtraction) {
fullText = `# ${title}\n\n## Abstract\n${abstract}`;
}
```
### 4. 骞跺彂鎺у埗绛栫暐 鉁?
### 4. 并发控制策略 ✅
**鍐崇瓥**锛氫娇鐢?`p-queue`锛岄粯璁ゅ苟鍙?
**决策**:使用 `p-queue`默认并发3
**鐞嗙敱**锛?
- 鎻愰€?鍊嶏紙鐩告瘮涓茶<E6B693>澶勭悊锛?
**理由**
- 提速3倍相比串行处理
- 避免触发API限流
- <EFBFBD>姩鎺掗槦锛屼紭闆呮帶鍒?
- 自动排队,优雅控制
**閰嶇疆**锛?
**配置**
```typescript
const queue = new PQueue({ concurrency: 3 });
```
@@ -511,66 +511,66 @@ const queue = new PQueue({ concurrency: 3 });
### 问题1数据库迁移冲突
**<EFBFBD><EFBFBD>**锛歚prisma db push` 妫€娴嬪埌浼氬垹闄?`public` schema<EFBFBD>殑琛?
**问题**`prisma db push` 检测到会删除 `public` schema中的表
**鐜拌薄**锛?
**现象**
```
⚠️ There might be data loss when applying the changes:
鈥?You are about to drop the `users` table, which is not empty (2 rows).
鈥?You are about to drop the `projects` table, which is not empty (2 rows).
You are about to drop the `users` table, which is not empty (2 rows).
You are about to drop the `projects` table, which is not empty (2 rows).
```
**鏍瑰洜**锛?
**根因**
- 历史遗留问题:部分模块的表创建在 `public` schema
- Prisma Migrate会尝试同步所有schema
**喅鏂规<EFBFBD>**锛?
1. 涓嶄娇鐢?`prisma migrate` 鎴?`prisma db push`
**解决方案**
1. 不使用 `prisma migrate``prisma db push`
2. 编写手动SQL脚本只操作 `asl_schema`
3. 执行:`Get-Content xxx.sql | docker exec -i postgres psql ...`
4. 验证:`\dt asl_schema.*`
**棰勯槻鎺<EFBFBD>柦**锛?
**预防措施**
- 未来继续使用手动SQL迁移
- 明确记录在文档中
- 鎻愰啋鍏朵粬妯″潡寮€鍙戣€?
- 提醒其他模块开发者
### 问题2Prisma Client类型生成
**<EFBFBD><EFBFBD>**锛氫慨鏀筍chema鍚庯紝Prisma Client绫诲瀷鏈<EFBFBD>洿鏂?
**问题**修改Schema后,Prisma Client类型未更新
**瑙e喅**锛?
**解决**
```bash
npx prisma generate
```
**棰勯槻鎺<EFBFBD>柦**锛?
- 姣忔<EFBFBD><EFBFBD>敼Schema鍚庣珛鍗虫墽琛?
**预防措施**
- 每次修改Schema后立即执行
- 加入迁移流程文档
---
## 📚 相关文档
**<EFBFBD><EFBFBD>鏇存柊鐨勬枃妗?*锛?
1. [鏁版嵁搴撹縼绉荤姸鎬佽<EFBFBD>鏄嶿(./2025-11-23_鏁版嵁搴撹縼绉荤姸鎬佽<E98EAC>鏄?md) 鈫?鏂板缓
2. [鏁版嵁搴撹<EFBFBD>璁℃枃妗<EFBFBD>(../02-鎶€鏈<E282AC><E98F88>璁?01-鏁版嵁搴撹<E690B4>璁?md) 鈫?鏇存柊v3.0
3. [妯″潡褰撳墠鐘舵€佷笌寮€鍙戞寚鍗梋(../00-妯″潡褰撳墠鐘舵€佷笌寮€鍙戞寚鍗?md) 鈫?鏇存柊v1.2
4. [鎶€鏈<EFBFBD>€哄姟娓呭崟](../06-鎶€鏈<E282AC>€哄姟/鎶€鏈<E282AC>€哄姟娓呭崟.md) 鈫?鏇存柊鍊哄姟7鐘舵€?
5. [鍏ㄦ枃澶嶇瓫寮€鍙戣<EFBFBD>鍒抅(../04-寮€鍙戣<E98D99>鍒?04-鍏ㄦ枃澶嶇瓫寮€鍙戣<E98D99>鍒?md) 鈫?鏇存柊Day 4杩涘害
**本次更新的文档**
1. [数据库迁移状态说明](./2025-11-23_数据库迁移状态说明.md) ← 新建
2. [数据库设计文档](../02-技术设计/01-数据库设计.md) ← 更新v3.0
3. [模块当前状态与开发指南](../00-模块当前状态与开发指南.md) ← 更新v1.2
4. [技术债务清单](../06-技术债务/技术债务清单.md) ← 更新债务7状态
5. [全文复筛开发计划](../04-开发计划/04-全文复筛开发计划.md) ← 更新Day 4进度
**鍙傝€冪殑瑙勮寖鏂囨。**锛?
1. [浜戝師鐢熷紑鍙戣<EFBFBD>鑼僝(../../../../04-寮€鍙戣<EFBFBD>鑼?08-浜戝師鐢熷紑鍙戣<E98D99>鑼?md)
2. [鏁版嵁搴撴灦鏋勮<EFBFBD>鏄嶿(../../../../00-绯荤粺鎬讳綋璁捐<EFBFBD>/03-鏁版嵁搴撴灦鏋勮<E98F8B>鏄?md)
3. [绯荤粺褰撳墠鐘舵€佷笌寮€鍙戞寚鍗梋(../../../../00-绯荤粺鎬讳綋璁捐<E79281>/00-绯荤粺褰撳墠鐘舵€佷笌寮€鍙戞寚鍗?md)
**参考的规范文档**
1. [云原生开发规范](../../../../04-开发规范/08-云原生开发规范.md)
2. [数据库架构说明](../../../../00-系统总体设计/03-数据库架构说明.md)
3. [系统当前状态与开发指南](../../../../00-系统总体设计/00-系统当前状态与开发指南.md)
---
## 馃殌 涓嬩竴姝ヨ<E5A79D>鍒?
## 🚀 下一步计划
### Day 5后端API开发预计1天
**浠诲姟娓呭崟**锛?
**任务清单**
1. 创建 `FulltextScreeningController.ts`
- `createTask()` - 创建任务
- `getTaskProgress()` - 获取进度
@@ -582,50 +582,50 @@ npx prisma generate
4. API测试Postman或集成测试
5. 错误处理完善
**棰勮<EFBFBD>у嚭**锛?
**预计产出**
- 5个API接口
- API文档
- 鍚庣<EFBFBD>瀹屾垚鉁?
- 后端完成✅
---
## 🎉 总结
**Day 4鏍稿績鎴愭灉**锛?
- 鉁?瀹屾垚鏁版嵁搴撹<E690B4>璁★紙浜戝師鐢熸灦鏋勶級
- 鉁?瀹屾垚鏁版嵁搴撹縼绉伙紙瀹夊叏鎵ц<E98EB5>锛屾棤褰卞搷鍏朵粬妯″潡锛?
- 鉁?瀹屾垚鎵瑰<E98EB5>鐞嗘湇鍔″紑鍙戯紙700琛屾牳蹇冧唬鐮侊級
- 鉁?瀹屾垚闆嗘垚娴嬭瘯锛堢<E9949B>鍒扮<E98D92>楠岃瘉锛?
- 鉁?瀹屾垚璇︾粏鏂囨。锛?绡囨枃妗f洿鏂帮級
**Day 4核心成果**
- ✅ 完成数据库设计(云原生架构)
- ✅ 完成数据库迁移(安全执行,无影响其他模块)
- ✅ 完成批处理服务开发700行核心代码
- ✅ 完成集成测试(端到端验证)
- ✅ 完成详细文档5篇文档更新
**鎶€鏈<EFBFBD>寒鐐?*锛?
- 鉁?浜戝師鐢熷瓨鍌ㄦ柟妗堬紙鍏ㄦ枃瀛極SS/Dify锛?
- 鉁?鎵嬪姩SQL杩佺Щ绛栫暐锛堝畨鍏ㄥ彲鎺э級
- 鉁?骞跺彂鎺у埗锛坧-queue锛屾彁閫?鍊嶏級
- 鉁?瀹归敊鏈哄埗锛堥噸璇曘€侀檷绾с€佺户缁<E688B7>
- 鉁?娴嬭瘯妯″紡锛堝揩閫熼獙璇侊級
**技术亮点**
- ✅ 云原生存储方案全文存OSS/Dify
- ✅ 手动SQL迁移策略安全可控
- ✅ 并发控制p-queue提速3倍
- ✅ 容错机制(重试、降级、继续)
- ✅ 测试模式(快速验证)
**璐ㄩ噺淇濋殰**锛?
- 鉁?Schema闅旂<EFBFBD>100%姝g‘锛堟墍鏈夎〃鍦╝sl_schema锛?
- 鉁?浠g爜鏃燣inter閿欒<EFBFBD>
- 鉁?瀹屾暣鐨勯敊璇<E6958A><E79287>鐞嗗拰鏃ュ織
- 鉁?璇︾粏鐨勬枃妗<E5A697>褰?
**质量保障**
- Schema隔离100%正确所有表在asl_schema
- ✅ 代码无Linter错误
- ✅ 完整的错误处理和日志
- ✅ 详细的文档记录
**寮€鍙戞晥鐜?*锛?
**开发效率**
- ⏱️ 上午1h完成数据库设计与迁移
- 鈴憋笍 涓嬪崍2h瀹屾垚鎵瑰<E98EB5>鐞嗘湇鍔″紑鍙?
- ⏱️ 下午2h完成批处理服务开发
- ⏱️ 合计3h完成Day 4全部任务
**MVP杩涘害**锛?
- Week 1锛?0% 鈫?75% 鉁?
- Day 1-3锛氶€氱敤鑳藉姏灞傚畬鎴?鉁?
- Day 4锛氭壒澶勭悊鏈嶅姟瀹屾垚 鉁?
**MVP进度**
- Week 150% 75%
- Day 1-3:通用能力层完成 ✅
- Day 4:批处理服务完成 ✅
- Day 5API开发下一步
---
**寮€鍙戜汉鍛?*锛欰SL寮€鍙戝洟闃?
**鏂囨。缂栧啓鏃堕棿**锛?025-11-23
**开发人员**ASL开发团队
**文档编写时间**2025-11-23
**文档版本**v1.0