Files
AIclinicalresearch/docs/03-业务模块/DC-数据清洗整理/02-技术设计/技术设计文档:工具 A - 医疗数据超级合并器 (The Super Merger).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

4.8 KiB
Raw Blame History

技术设计文档:工具 A - 医疗数据超级合并器 (The Super Merger)

文档类型 Technical Design Document (TDD)
对应 PRD PRD_工具A_超级合并器_V2.md
版本 V2.0 (架构升级:访视基准 + 时间窗)
状态 Draft
核心目标 构建一个基于 Web 的 ETL 工具,解决临床科研中“一对多”数据对齐难题,实现基于时间窗的精准合并。

1. 总体架构设计 (Architecture Overview)

鉴于处理 Excel 文件(解析、合并、写入)是 CPU 密集型和内存敏感型操作,为了避免阻塞 Node.js 主线程,我们采用 “异步任务队列 + 流式处理” 的架构模式。

1.1 系统架构图

graph TD
Client[React 前端 (Wizard UI)]

subgraph API\_Server \[Fastify API 服务\]  
    UploadAPI\[上传接口\]  
    TaskAPI\[任务状态接口\]  
    ConfigAPI\[配置接口\]  
end  
  
subgraph Async\_Worker \[后台处理 Worker\]  
    BullMQ\[BullMQ 队列\]  
    Merger\[智能合并引擎 (Time-Window Joiner)\]  
    ExcelParser\[ExcelJS 解析器\]  
    DateEngine\[日期归一化引擎\]  
end  
  
subgraph Storage \[数据存储\]  
    PG\[(PostgreSQL 业务库)\]  
    FileSys\[临时文件存储 (Local/S3)\]  
    Redis\[(Redis 缓存/队列)\]  
end

Client \--1.上传文件--\> UploadAPI  
UploadAPI \--保存临时文件--\> FileSys  
Client \--2.提交基准与时间窗配置--\> ConfigAPI  
ConfigAPI \--创建任务--\> PG  
ConfigAPI \--推入队列--\> BullMQ  
BullMQ \--消费任务--\> Merger  
Merger \--读取辅表(全量)--\> FileSys  
Merger \--读取主表(流式)--\> FileSys  
Merger \--流式合并与写入--\> FileSys  
Merger \--更新状态--\> PG  
Client \--3.轮询/WS 进度--\> TaskAPI  
Client \--4.下载结果--\> API\_Server

2. 技术选型 (Tech Stack)

基于现有技术栈的针对性选择:

层级 技术组件 选型理由
前端 React 19 + Ant Design 5 利用 AntD 的 Steps, Upload, Tree (树状选择器) 快速构建 UI。
后端框架 Fastify 5.x 高性能 HTTP 框架,适合高并发 I/O。
Excel 处理 ExcelJS 核心组件。支持流式读写 (Streaming I/O),这是处理大数据量不崩的关键。
日期处理 Day.js + CustomParseFormat 新增。处理“时间地狱”的核心库,需要极强的容错解析能力。
任务队列 BullMQ + Redis 必须异步处理。合并逻辑复杂,耗时较长,必须用队列。
数据库 PostgreSQL 15 + Prisma 存储任务状态、文件元数据。不建议将原始 Excel 数据存入 PG
验证库 Zod 用于校验前端提交的复杂映射配置结构。

2.1 关键技术决策 (ADR): 为什么不用 Python (Pandas)?

虽然 Python Pandas 在数据合并上代码更简洁,但针对本工具的场景,我们决定坚持使用 Node.js,理由如下:

  1. 流式处理优势: Pandas 倾向于全量加载内存,容易 OOM。Node.js 的 Stream API 天然支持背压,能稳定处理“数据膨胀”问题。
  2. 架构一致性: 避免引入 Python Runtime 带来的运维成本和 IPC 开销。
  3. 结论: 对于精确匹配和逻辑清洗Node.js 性能足够且更可控。

3. 数据库设计 (Database Schema)

Prisma Schema 定义

// 任务状态枚举
enum TaskStatus {
PENDING
PROCESSING
COMPLETED
FAILED
}

// 合并任务表
model MergeTask {
id String @id @default(uuid())
userId String
status TaskStatus @default(PENDING)
progress Int @default(0)

// 核心配置字段 (V2 更新)
// 结构: {
// anchorFileId: string,
// anchorKeys: { id: "住院号", time: "入院日期" },
// window: { daysBefore: 7, daysAfter: 7 },
// files: [{ id: "f2", timeCol: "报告时间", columns: ["白细胞"] }]
// }
config Json?

resultUrl String?
report Json? // 质量报告 { totalRows: 1000, dropped: 50, matchRate: "95%" }
errorMsg String?
createdAt DateTime @default(now())

files SourceFile[]
}

// 源文件表
model SourceFile {
id String @id @default(uuid())
taskId String
task MergeTask @relation(fields: [taskId], references: [id])
filename String
filepath String
headers Json // ["住院号", "姓名", "入院日期"]
rowCount Int
fileSize Int
uploadedAt DateTime @default(now())
}