Files
AIclinicalresearch/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-11-21-字段映射问题修复.md
HaHafeng 66255368b7 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
2026-01-16 13:42:10 +08:00

285 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 字段映射问题修复报告
**日期**: 2025-11-21
**问题**: 真实LLM筛选失败成功0/20
**原因**: 字段名不匹配
**状态**: ✅ 已修复
---
## 🔍 问题诊断
### 症状
```
任务状态: completed
进度: 20/20
成功: 0 ❌
筛选结果数: 0
```
**表现**
- 任务瞬间完成1秒
- 所有文献处理失败
- 没有保存任何筛选结果
---
## 🎯 根本原因
### 问题1: PICOS字段名不匹配
**前端/数据库格式** (`TitleScreeningSettings.tsx`):
```typescript
picoCriteria: {
P: '2型糖尿病患者...',
I: 'SGLT2抑制剂...',
C: '安慰剂或常规治疗...',
O: '心血管结局...',
S: 'RCT'
}
```
**LLM服务期望格式** (`llmScreeningService.ts`):
```typescript
// 实际上支持两种格式,但优先使用短格式
picoCriteria: {
P: '...', // ✅
I: '...', // ✅
C: '...', // ✅
O: '...', // ✅
S: '...' // ✅
}
```
**诊断**:前端使用 P/I/C/O/S 格式,但 `screeningService.ts` 直接传递了数据库的原始格式,未做映射。
---
### 问题2: 模型名格式不匹配
**前端格式** (`TitleScreeningSettings.tsx`):
```typescript
models: ['DeepSeek-V3', 'Qwen-Max']
```
**LLM服务期望格式** (`llmScreeningService.ts`):
```typescript
models: ['deepseek-chat', 'qwen-max']
```
**原因**前端使用展示名称后端需要API名称。
---
### 问题3: 缺少字段验证
文献可能缺少 `title``abstract`导致LLM调用失败。
---
## ✅ 修复方案
### 修复1: 添加PICOS字段映射
**文件**: `backend/src/modules/asl/services/screeningService.ts`
```typescript
// 🔧 修复:字段名映射(数据库格式 → LLM服务格式
const rawPicoCriteria = project.picoCriteria as any;
const picoCriteria = {
P: rawPicoCriteria?.P || rawPicoCriteria?.population || '',
I: rawPicoCriteria?.I || rawPicoCriteria?.intervention || '',
C: rawPicoCriteria?.C || rawPicoCriteria?.comparison || '',
O: rawPicoCriteria?.O || rawPicoCriteria?.outcome || '',
S: rawPicoCriteria?.S || rawPicoCriteria?.studyDesign || '',
};
```
**优势**
- ✅ 兼容两种格式P/I/C/O/S 或 population/intervention/...
- ✅ 防御性编程避免undefined
---
### 修复2: 添加模型名映射
```typescript
// 🔧 修复:模型名映射(前端格式 → API格式
const MODEL_NAME_MAP: Record<string, string> = {
'DeepSeek-V3': 'deepseek-chat',
'Qwen-Max': 'qwen-max',
'GPT-4o': 'gpt-4o',
'Claude-4.5': 'claude-sonnet-4.5',
'deepseek-chat': 'deepseek-chat', // 兼容直接使用API名
'qwen-max': 'qwen-max',
// ... 更多映射
};
const rawModels = screeningConfig?.models || ['deepseek-chat', 'qwen-max'];
const models = rawModels.map((m: string) => MODEL_NAME_MAP[m] || m);
```
**映射表**
| 前端展示名 | API名称 |
|-----------|---------|
| DeepSeek-V3 | deepseek-chat |
| Qwen-Max | qwen-max |
| GPT-4o | gpt-4o |
| Claude-4.5 | claude-sonnet-4.5 |
---
### 修复3: 添加文献验证
```typescript
// 🔧 验证:必须有标题和摘要
if (!literature.title || !literature.abstract) {
logger.warn('Skipping literature without title or abstract', {
literatureId: literature.id,
hasTitle: !!literature.title,
hasAbstract: !!literature.abstract,
});
console.log(`⚠️ 跳过文献 ${processedCount + 1}: 缺少标题或摘要`);
processedCount++;
continue;
}
```
---
### 修复4: 增强调试日志
```typescript
console.log('\n🚀 开始真实LLM筛选:');
console.log(' 任务ID:', taskId);
console.log(' 项目ID:', projectId);
console.log(' 文献数:', literatures.length);
console.log(' 模型(映射后):', models); // ⭐ 显示映射后的值
console.log(' PICOS-P:', picoCriteria.P?.substring(0, 50) || '(空)');
console.log(' PICOS-I:', picoCriteria.I?.substring(0, 50) || '(空)');
console.log(' PICOS-C:', picoCriteria.C?.substring(0, 50) || '(空)');
console.log(' 纳入标准:', inclusionCriteria?.substring(0, 50) || '(空)');
console.log(' 排除标准:', exclusionCriteria?.substring(0, 50) || '(空)');
```
---
## 🧪 测试步骤
### 1. 重启后端(必须!)
```bash
# 停止当前后端Ctrl+C
cd D:\MyCursor\AIclinicalresearch\backend
npm run dev
```
### 2. 测试(小规模)
1. 访问前端
2. 填写PICOS
3. **上传5篇文献**(先测试小规模)
4. 点击"开始AI初筛"
### 3. 查看后端控制台
**应该看到**
```
🚀 开始真实LLM筛选:
任务ID: xxx
文献数: 5
模型(映射后): [ 'deepseek-chat', 'qwen-max' ]
PICOS-P: 2型糖尿病患者...
PICOS-I: SGLT2抑制剂...
PICOS-C: 安慰剂...
纳入标准: 成人2型糖尿病...
排除标准: 综述、系统评价...
[等待10-20秒]
✅ 文献 1/5 处理成功
DS: include / Qwen: include
冲突: 否
[等待10-20秒]
✅ 文献 2/5 处理成功
DS: exclude / Qwen: exclude
冲突: 否
...
```
---
## 📊 预期效果
### 修复前
- ⏱️ 1秒完成20篇
- ❌ 成功0
- ❌ 筛选结果数0
### 修复后
- ⏱️ 50-100秒完成5篇每篇10-20秒
- ✅ 成功5
- ✅ 筛选结果数5
- ✅ 证据包含真实的AI分析
- ✅ 证据不包含"模拟证据"
---
## 🔧 修改文件
-`backend/src/modules/asl/services/screeningService.ts`
- 添加PICOS字段映射
- 添加模型名映射
- 添加文献验证
- 增强调试日志
---
## 💡 经验教训
### 1. 前后端数据格式一致性
- 前端使用的展示格式 ≠ 后端API格式
- 需要在集成层做映射
### 2. 防御性编程
- 使用 `||` 提供默认值
- 验证必需字段
- 兼容多种格式
### 3. 调试日志的重要性
- 显示映射后的值(不是原始值)
- 输出所有关键参数
- 帮助快速定位问题
---
## 🎯 后续优化
### 短期
1. ✅ 字段映射(已完成)
2. ✅ 模型名映射(已完成)
3. ✅ 验证必需字段(已完成)
### 中期
1. 统一前后端数据格式(使用 TypeScript 接口)
2. 添加数据格式验证中间件
3. 改进错误提示
### 长期
1. 使用 tRPC 或 GraphQL 确保类型安全
2. 自动化测试覆盖
3. Schema验证
---
**报告人**: AI Assistant
**日期**: 2025-11-21
**版本**: v1.0.0