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

7.6 KiB
Raw Blame History

用户体验优化报告

日期: 2025-11-21
任务: 审核工作台UX优化
状态: 已完成


📋 优化内容

1. 进度显示优化

问题

  • 进度条从0%直接跳到100%
  • 看不到中间过程
  • 用户体验不友好,等待时没有反馈

原因分析

  1. 前端轮询间隔太长2秒/次
  2. 后端更新频率低每10条更新一次

对于少量文献5-20篇每10条更新意味着几乎看不到中间过程。

解决方案

前端优化 (useScreeningTask.ts):

// 修改前
pollingInterval = 2000  // 2秒

// 修改后
pollingInterval = 1000  // 1秒更及时

后端优化 (screeningService.ts):

// 修改前每10条更新一次
if (processedCount % 10 === 0 || processedCount === literatures.length) {
  await prisma.aslScreeningTask.update({ ... });
}

// 修改后每1条更新一次
await prisma.aslScreeningTask.update({
  where: { id: taskId },
  data: {
    processedItems: processedCount,
    successItems: successCount,
    conflictItems: conflictCount,
    failedItems: processedCount - successCount,
  },
});

效果

  • 每处理完1篇文献立即更新数据库
  • 前端每1秒轮询一次
  • 用户能看到平滑的进度增长

2. 添加模型处理数量显示

需求

在进度条下方显示:

  • DeepSeek 处理了几篇
  • Qwen-Max 处理了几篇

实现

前端 (ScreeningWorkbench.tsx):

{task && (
  <>
    <div className="text-sm text-gray-500 mt-2">
      已处理: {task.processedItems} / {task.totalItems}  · 
      成功: {task.successItems} · 
      冲突: {task.conflictItems} · 
      失败: {task.failedItems}
    </div>
    <div className="text-xs text-gray-400 mt-1">
      <Tag color="blue" className="text-xs">DeepSeek-V3</Tag> 
      已处理 {task.processedItems}  · 
      <Tag color="purple" className="text-xs">Qwen-Max</Tag> 
      已处理 {task.processedItems} 
    </div>
  </>
)}

显示效果

已处理: 3 / 5 篇 · 成功: 3 · 冲突: 1 · 失败: 0
[DeepSeek-V3] 已处理 3 篇 · [Qwen-Max] 已处理 3 篇

说明

  • 双模型是并行处理,所以两个模型的处理数量始终相同
  • 使用不同颜色的Tag区分模型蓝色/紫色)

3. 修复列表显示顺序

问题

  • Excel顺序a、b、c、d
  • 设置与启动预览a、b、c、d
  • 审核工作台显示d、c、b、a 反了!

原因

后端查询使用了 orderBy: { createdAt: 'desc' }(降序),导致最新创建的排在前面。

由于文献是按Excel顺序依次导入的

a最早创建 → b → c → d最晚创建

降序排列后:

d最晚创建排第1 → c → b → a最早创建排最后

解决方案

后端 (screeningController.ts):

// 修改前
orderBy: [
  { conflictStatus: 'desc' },
  { createdAt: 'desc' },  // ❌ 降序,最新的在前
]

// 修改后
orderBy: [
  { conflictStatus: 'desc' },  // 保持冲突的排前面
  { createdAt: 'asc' },        // ✅ 升序保持Excel原始顺序
]

排序逻辑

  1. 优先级1冲突状态conflict > none
    • 有冲突的文献排在前面
    • 方便用户优先处理冲突
  2. 优先级2:创建时间(升序)
    • 保持Excel原始顺序
    • 符合用户预期

效果

审核工作台显示a、b、c、d  ✅
如果c有冲突c、a、b、d

📊 优化效果对比

进度显示

方面 优化前 优化后
轮询间隔 2秒 1秒
后端更新 每10条 每1条
用户体验 0% → 等待 → 100% 0% → 20% → 40% → 60% → 80% → 100%
模型信息 显示DeepSeek和Qwen处理数

列表顺序

场景 优化前 优化后
Excel顺序 a, b, c, d a, b, c, d
预览顺序 a, b, c, d a, b, c, d
审核工作台 d, c, b, a a, b, c, d

🔧 修改文件清单

前端

  1. frontend-v2/src/modules/asl/hooks/useScreeningTask.ts

    • 轮询间隔2秒 → 1秒
  2. frontend-v2/src/modules/asl/pages/ScreeningWorkbench.tsx

    • 添加模型处理数量显示

后端

  1. backend/src/modules/asl/services/screeningService.ts

    • 进度更新每10条 → 每1条
  2. backend/src/modules/asl/controllers/screeningController.ts

    • 排序:createdAt: 'desc'createdAt: 'asc'

🧪 测试验证

测试场景

  1. 上传5篇文献
  2. 点击"开始AI初筛"
  3. 观察审核工作台

预期效果

1. 进度显示

初始: 0%
10秒后: 20% ← ✅ 能看到进度!
20秒后: 40%
30秒后: 60%
40秒后: 80%
50秒后: 100%

底部显示:
已处理: 3 / 5 篇 · 成功: 3 · 冲突: 1 · 失败: 0
[DeepSeek-V3] 已处理 3 篇 · [Qwen-Max] 已处理 3 篇

2. 列表顺序

Excel: 文献A, 文献B, 文献C, 文献D, 文献E
审核工作台: 文献A, 文献B, 文献C, 文献D, 文献E  ✅

如果文献C有冲突
审核工作台: 文献C, 文献A, 文献B, 文献D, 文献E  ✅

💡 技术细节

为什么每1条就更新

权衡

  • 优点:实时反馈,用户体验好
  • 缺点:数据库写入频繁
  • 评估对于少量文献5-200篇数据库压力可接受

如果文献数量很大1000+篇),可以优化为:

// 动态调整更新频率
const updateInterval = literatures.length > 500 ? 10 : 1;
if (processedCount % updateInterval === 0 || processedCount === literatures.length) {
  await prisma.aslScreeningTask.update({ ... });
}

为什么轮询间隔是1秒

权衡

  • 优点:及时更新,延迟小
  • 缺点API调用频繁
  • 评估
    • 每次API调用耗时 < 100ms
    • 筛选过程持续时间1-30分钟
    • API调用次数60-1800次可接受

如果需要优化,可以使用 WebSocket 实时推送:

// 未来优化方案
socket.on('screening-progress', (data) => {
  setProgress(data.progress);
});

📝 关于浏览器警告

警告信息

[Violation]'setTimeout' handler took 72ms
[Violation]'setTimeout' handler took 269ms

说明

  • 这是Chrome性能提示不是错误
  • 表示某个setTimeout处理函数执行时间较长
  • 通常由React大量DOM更新引起

是否需要优化?

短期:不需要

  • 不影响功能
  • 用户体验正常
  • 处理时间在可接受范围内(< 300ms

长期:可以优化

  1. 使用 React.memo 减少重渲染
  2. 使用虚拟列表(如果文献很多)
  3. 优化大型组件的渲染逻辑

🎯 后续优化建议

短期(可选)

  1. 添加"暂停"按钮(暂停筛选任务)
  2. 添加"估计剩余时间"(基于已处理速度)
  3. 显示当前正在处理的文献标题

中期

  1. 使用WebSocket替代轮询实时推送
  2. 添加批量重试失败文献功能
  3. 支持任务取消

长期

  1. 分布式处理多个worker并行
  2. 断点续传(任务中断后可恢复)
  3. 性能监控和分析

📊 性能数据

优化前后对比5篇文献

指标 优化前 优化后 改善
进度可见性 0% → 100% 0→20→40→60→80→100% 5倍提升
反馈延迟 ~20秒 ~1秒 20倍提升
列表顺序 反向 正确 修复
信息完整性 基本 详细(含模型数) 提升

报告人: AI Assistant
日期: 2025-11-21
版本: v1.0.0