Files
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

24 KiB
Raw Permalink Blame History

Tool C 技术债务清单

创建日期: 2025-12-06
最后更新: 2025-12-06
当前版本: Day 3 MVP完成
优先级分级: P0-紧急 | P1-重要 | P2-中期优化 | P3-长期规划


📋 技术债务概览

编号 债务项 优先级 预计工时 影响范围 计划时间
TD-C-001 Python Session状态持久化 P1 1天 稳定性 Day 5-6
TD-C-002 数据版本管理与回滚 P2 2天 功能 Week 3
TD-C-003 大文件性能优化 P2 1.5天 性能 Week 3
TD-C-004 AI Prompt持续优化 P1 持续 质量 持续
TD-C-005 前端对话UI开发 P0 3天 功能 Day 4-5
TD-C-006 复杂场景Prompt优化 P2 0.5天 质量 Day 4

🔴 P1: 重要(近期必做)

TD-C-001: Python Session状态持久化

当前问题:

# 当前实现内存维护Session状态
session_data = {}  # 存在内存中

# 问题:
# 1. Python服务重启 → Session数据丢失
# 2. 多实例部署 → 负载均衡会导致状态不一致
# 3. 无法回滚到历史版本

影响:

  • 用户体验差:重启服务后需重新上传文件
  • 无法云原生部署:不支持多实例
  • 数据安全性:内存断电即丢失

优化方案:

方案A: Redis持久化(推荐)

# 使用Redis存储Session状态
import redis
import pickle

class SessionManager:
    def __init__(self):
        self.redis_client = redis.Redis(host='localhost', port=6379)
    
    def save_session(self, session_id, dataframe):
        # 序列化DataFrame
        serialized = pickle.dumps(dataframe)
        
        # 存储到Redis10分钟过期
        self.redis_client.setex(
            f"session:{session_id}",
            600,  # 10分钟
            serialized
        )
    
    def get_session(self, session_id):
        data = self.redis_client.get(f"session:{session_id}")
        if data:
            return pickle.loads(data)
        return None

方案B: OSS持久化

# 每次操作后保存到OSS
def save_to_oss(session_id, dataframe):
    # 序列化为Parquet格式高效
    buffer = io.BytesIO()
    dataframe.to_parquet(buffer)
    
    # 上传到OSS
    oss_key = f"dc/tool-c/sessions/{session_id}/current.parquet"
    oss_client.put_object(oss_key, buffer.getvalue())

实施计划:

  • Day 5: 实现Redis集成
  • Day 6: 测试与部署

TD-C-004: AI Prompt持续优化

当前问题:

  • 10个Few-shot示例可能不够覆盖所有场景
  • 某些复杂医疗场景AI理解不准确
  • 代码生成质量依赖DeepSeek-V3性能

优化方向:

1. 扩展Few-shot库

# 当前10个示例
# 目标20-30个示例分类存储

few_shot_library = {
    "basic": [...],      # 基础清洗10个
    "medical": [...],    # 医疗专业10个
    "advanced": [...]    # 高级分析10个
}

# 根据用户需求动态选择相关示例
def select_relevant_examples(user_message):
    # 语义匹配最相关的5个示例
    ...

2. 用户反馈收集

# 记录AI生成失败的场景
failed_cases = []

# 定期分析,添加新示例
def analyze_failures():
    # 找出高频失败场景
    # 人工编写Few-shot
    # 更新System Prompt

3. 多模型备选

# 主DeepSeek-V3性价比高
# 备GPT-4质量高成本高
# 备Claude-3.5(代码能力强)

if deepseek_fails:
    retry_with_gpt4()

实施计划:

  • 持续收集失败案例
  • 每月优化1次Prompt
  • 测试其他LLM模型

🟡 P2: 中期优化1-2个月

TD-C-002: 数据版本管理与回滚

当前问题:

  • AI每次操作都直接修改当前数据
  • 无法撤销/回滚到之前状态
  • 无法对比不同版本

优化方案:

版本管理架构:

# 每次操作后保存快照
class DataVersionManager:
    def save_version(self, session_id, dataframe, operation_desc):
        version_id = str(uuid.uuid4())
        
        # 保存到OSSParquet格式压缩高效
        oss_key = f"dc/tool-c/sessions/{session_id}/versions/{version_id}.parquet"
        dataframe.to_parquet(oss_key)
        
        # 元数据存数据库
        db.save({
            "session_id": session_id,
            "version_id": version_id,
            "operation": operation_desc,
            "timestamp": now(),
            "row_count": len(dataframe),
            "file_size": ...
        })
    
    def rollback(self, session_id, version_id):
        # 从OSS恢复
        dataframe = pd.read_parquet(oss_key)
        return dataframe

前端展示:

// 版本历史列表
<Timeline>
  <TimelineItem>
    版本1: 上传原始文件 (100)
  </TimelineItem>
  <TimelineItem>
    版本2: 删除缺失值 (95) [回滚]
  </TimelineItem>
  <TimelineItem>
    版本3: 计算BMI (95) [当前]
  </TimelineItem>
</Timeline>

成本估算:

  • 每个版本~1-5MBParquet压缩后
  • 10个版本 = 10-50MB
  • OSS成本¥0.01-0.05/Session

实施计划:

  • Week 3: 后端版本管理
  • Week 4: 前端UI + 测试

TD-C-003: 大文件性能优化

当前限制:

  • 文件大小10MB
  • 行数限制:~50,000行
  • 前端预览100行

优化目标:

  • 文件大小50MB
  • 行数限制500,000行
  • 前端预览:虚拟滚动

技术方案:

1. 流式处理

# 分块读取大文件
def process_large_file(file_path):
    chunk_size = 10000  # 每次处理1万行
    
    for chunk in pd.read_csv(file_path, chunksize=chunk_size):
        # 分块处理
        process_chunk(chunk)

2. Apache Arrow集成

# 使用Arrow高性能列式存储
import pyarrow as pa
import pyarrow.parquet as pq

# Node.js ↔ Python 数据传输
# 使用Arrow IPC格式比JSON快10-100倍

3. 前端虚拟滚动

// 使用AG Grid的虚拟滚动
<AgGridReact
  rowModelType="infinite"
  cacheBlockSize={100}
  maxBlocksInCache={10}
/>

实施计划:

  • Week 3: 流式处理 + Arrow
  • Week 4: 前端虚拟滚动

🟡 P2: 中期优化1-2个月

TD-C-006: 复杂场景Prompt优化Day 3测试遗留

当前问题: Day 3测试中2个复杂场景持续超时失败3次重试都失败

  • 示例2数值列清洗creatinine列处理包含<0.1等特殊符号)
  • 示例7智能去重(日期解析 + 排序 + 去重)

失败原因分析:

❌ 示例2失败: timeout of 60000ms exceeded
   用户需求: 把creatinine列里的非数字符号去掉<0.1按0.05处理,转为数值类型
   
   问题:
   - 需求描述复杂3个子任务去符号 + 特殊值处理 + 类型转换)
   - AI理解不准确生成的代码有逻辑错误
   - 3次重试仍无法修正

❌ 示例7失败: timeout of 60000ms exceeded
   用户需求: 按patient_id去重保留check_date最新的记录
   
   问题:
   - 日期列可能包含多种格式
   - 排序 + 去重的组合逻辑复杂
   - AI生成的代码执行出错后难以自我修正

优化方案:

方案A: 增强Few-shot示例

# 为这两个场景添加更详细的Few-shot示例

### 示例: 复杂数值清洗(含特殊符号)
用户: 把肌酐列里的非数字符号><去掉<0.1按0.05处理转为数值
代码:
\`\`\`python
try:
    # 第1步去除符号
    df['creatinine_clean'] = df['creatinine'].astype(str).str.replace('>', '').str.replace('<', '')
    
    # 第2步处理特殊值
    df.loc[df['creatinine_clean'] == '0.1', 'creatinine_clean'] = '0.05'
    
    # 第3步转为数值
    df['creatinine_numeric'] = pd.to_numeric(df['creatinine_clean'], errors='coerce')
    
    print(f'清洗完成:{df["creatinine_numeric"].notna().sum()}个有效值')
except Exception as e:
    print(f'错误: {e}')
\`\`\`
说明: 分步处理复杂清洗任务先去符号再处理特殊值最后转类型

方案B: 优化System Prompt

## 复杂场景处理建议
1. **数值清洗**:分步处理(去符号  处理特殊值  类型转换)
2. **日期操作**:先用pd.to_datetime()统一格式,再排序去重
3. **调试输出**:每步打印中间结果,便于错误定位
4. **错误处理**:使用try-except包裹每个子步骤

方案C: 调整重试策略

// 针对特定错误类型,提供更明确的修正提示
if (error.includes('日期') || error.includes('datetime')) {
  enhancedMessage = `${userMessage}
  
  注意:日期列可能包含缺失值或格式不一致,请:
  1. 使用 pd.to_datetime(df['date'], errors='coerce')
  2. 删除日期为NaT的行
  3. 再进行排序和去重`;
}

实施计划:

  • Day 4: 实现方案A增强Few-shot示例
  • Day 4: 实现方案B优化System Prompt
  • Day 5: 测试优化效果目标通过率达到95%+

预期效果:

  • 通过率从81.8%提升到95%+
  • 复杂场景一次成功率提升50%
  • 用户体验改善(减少等待时间)

🟢 P3: 长期规划3个月+

TD-C-007: 医学专业功能增强

创建日期: 2025-12-08
来源: 医学统计分析专家审查反馈
优先级: P3功能按钮MVP完成后优先实施

背景 当前工具C功能按钮开发计划V1.0)主要面向通用数据清洗场景。医学专业审查发现,针对临床研究数据的特殊需求,需要增加以下专业功能。


7.1 异常值检测器(优先级:高)

医学背景

  • 临床数据常存在录入错误年龄999岁、体重500kg
  • 仪器故障导致的异常读数
  • 需符合临床范围的数据验证

功能设计

┌─────────────────────────────────────┐
│  异常值检测                          │
├─────────────────────────────────────┤
│  选择列:[血糖 ▼]                   │
│                                     │
│  检测方法:                         │
│  ● 临床范围(推荐)                 │
│     正常范围:[3.9___] - [6.1___]  │
│     来源:[ADA指南 ▼]              │
│                                     │
│  ○ 统计学方法                       │
│     IQR法1.5倍四分位距)         │
│     Z-score法±3标准差          │
│                                     │
│  处理方式:                         │
│  ○ 仅标记  ● 删除  ○ 替换为缺失   │
│                                     │
│  检测到23个异常值                 │
│  [查看详情]                         │
│                                     │
│  [取消]  [执行]                    │
└─────────────────────────────────────┘

实现要点

  • 内置常用临床范围年龄0-120、BMI 10-80、血糖2-30等
  • 支持自定义范围
  • 可视化异常值分布(箱线图)

7.2 单位转换器(优先级:高)

医学背景

  • 不同国家/医院使用不同单位
  • 文献meta分析需要统一单位
  • 常见转换错误导致数据不可用

功能设计

┌─────────────────────────────────────┐
│  医学单位转换                        │
├─────────────────────────────────────┤
│  选择列:[血糖 ▼]                   │
│                                     │
│  当前单位:[mg/dL ▼]               │
│  目标单位:[mmol/L ▼]              │
│                                     │
│  常用转换:                         │
│  • 血糖: mg/dL ↔ mmol/L (÷18.018) │
│  • 血脂: mg/dL ↔ mmol/L            │
│  • 体重: kg ↔ lb (×2.20462)        │
│  • 身高: cm ↔ inch                 │
│  • 肌酐: mg/dL ↔ μmol/L            │
│                                     │
│  ☑️ 创建新列                       │
│  新列名:[血糖_mmol_L_________]    │
│                                     │
│  预览5.5 mg/dL → 0.31 mmol/L     │
│                                     │
│  [取消]  [执行]                    │
└─────────────────────────────────────┘

实现要点

  • 内置医学常用转换公式
  • 支持批量转换
  • 自动验证转换后的合理性

7.3 日期计算器(优先级:高)

医学背景

  • 计算年龄、随访时间、生存时间是高频需求
  • 日期格式不统一2025-01-01 vs 2025/1/1
  • 需要处理闰年、时间窗等复杂场景

功能设计

┌─────────────────────────────────────┐
│  日期/时间计算                       │
├─────────────────────────────────────┤
│  计算类型:                         │
│  ● 计算年龄(从出生日期)           │
│     出生日期列:[birth_date ▼]     │
│     参考日期:● 今天  ○ 指定列    │
│     新列名:[年龄_________]        │
│                                     │
│  ○ 计算时间间隔                     │
│     开始日期:[入院日期 ▼]         │
│     结束日期:[出院日期 ▼]         │
│     单位:[天 ▼](天/周/月/年)    │
│     新列名:[住院天数_____]        │
│                                     │
│  ○ 判断时间窗是否在X天内        │
│     事件日期:[随访日期 ▼]         │
│     基线日期:[入组日期 ▼]         │
│     时间窗:[30____] 天内          │
│     新列名:[30天内随访____]       │
│                                     │
│  [取消]  [预览]  [执行]            │
└─────────────────────────────────────┘

实现要点

  • 自动检测日期格式
  • 处理缺失日期
  • 支持多种时间单位

7.4 临床截断值分箱(优先级:中)

医学背景

  • 医学分类应基于循证医学证据WHO、ADA指南
  • 任意分箱会损失信息且无临床意义
  • 需要可追溯的分类标准

功能改进

在现有"生成分类变量"功能中增加:

┌─────────────────────────────────────┐
│  连续变量分箱                        │
├─────────────────────────────────────┤
│  选择数值列:[BMI ▼]                │
│                                     │
│  分箱方式:                         │
│  ● 临床截断值(推荐)⭐             │
│     标准:[WHO标准 ▼]              │
│     <18.5: 低体重                   │
│     18.5-24.9: 正常                 │
│     25-29.9: 超重                   │
│     ≥30: 肥胖                       │
│     参考WHO 2000                  │
│                                     │
│     [切换为中国标准 ▼]             │
│                                     │
│  ○ 自定义切点(需注明依据)         │
│  ○ 等宽/等频分箱(⚠️会损失信息)   │
│                                     │
│  [取消]  [预览分布]  [执行]        │
└─────────────────────────────────────┘

支持的临床标准:
- BMI分类WHO、中国成人、儿童标准
- 血压分级ESH/ESC高血压指南
- 肾功能分期KDIGO CKD分期
- 年龄分组WHO标准、临床试验常用
- 血糖分类ADA糖尿病诊断标准

实现要点

  • 内置10+常用临床标准
  • 可导出分类依据(供论文写作)
  • 提示等宽分箱的局限性

7.5 高级缺失值填补(优先级:中)

医学背景

  • MICE假设数据MAR随机缺失但临床数据常为MNAR非随机缺失
  • 病情严重患者更易失访(缺失非随机)
  • 需要敏感性分析

功能改进

在现有"缺失值填补"功能中增加:

┌─────────────────────────────────────┐
│  缺失值填补(医学专用)              │
├─────────────────────────────────────┤
│  选择列:[FMA评分 ▼] [+]           │
│                                     │
│  填补方法:                         │
│  ● 末次观测值结转LOCF⭐         │
│     适用:纵向数据,假设无变化      │
│                                     │
│  ○ 基线观测值结转BOCF           │
│     适用:保守估计,假设无改善      │
│                                     │
│  ○ 最坏情况插补Worst Case       │
│     适用:敏感性分析                │
│     最坏值:[0____]                │
│                                     │
│  ○ 中位数/均值填补                  │
│     ☑️ 按分组填补                  │
│        分组列:[性别▼][年龄组▼]   │
│                                     │
│  ○ 多重插补MICE                 │
│     ⚠️ 假设数据MAR需检验适用性  │
│                                     │
│  预览:将填补 32 个缺失值           │
│                                     │
│  [取消]  [敏感性分析]  [执行]      │
└─────────────────────────────────────┘

实现要点

  • 明确各方法的适用前提
  • 提供敏感性分析(对比不同方法结果)
  • 生成填补报告(供论文方法学描述)

7.6 Codebook数据字典生成优先级

医学背景

  • GCP药物临床试验质量管理规范要求可追溯性
  • 期刊要求提供数据字典
  • 伦理审查需要变量说明

功能设计

自动生成数据字典:

┌──────────────────────────────────────┐
│ 变量名 │ 原变量 │ 编码规则 │ 创建时间│
├────────┼────────┼──────────┼─────────┤
│研究中心│研究中心│1=黑龙江  │12-08    │
│_编码   │        │2=山东    │10:30    │
│        │        │3=广州    │         │
├────────┼────────┼──────────┼─────────┤
│BMI分类 │BMI     │1=正常    │12-08    │
│        │        │2=超重    │10:35    │
│        │        │3=肥胖    │         │
│        │        │参考WHO │         │
└────────┴────────┴──────────┴─────────┘

导出选项:
- Excel格式常用
- Word格式伦理报告
- CSV格式SPSS导入

实现要点

  • 每次重编码/分箱自动更新
  • 记录操作人和时间
  • 支持手动添加注释

7.7 样本筛选流程图(优先级:低)

医学背景

  • CONSORT声明要求报告筛选流程
  • 期刊审稿要求提供流程图
  • 有助于发现筛选逻辑错误

功能设计

在"高级筛选"功能中增加:

自动生成筛选流程:

┌──────────────────────┐
│  原始数据: 1000例    │
└──────┬───────────────┘
       │
       ↓ 排除年龄<18岁
┌──────────────────────┐
│  剩余: 950例 (-50)   │
└──────┬───────────────┘
       │
       ↓ 排除主要结局缺失
┌──────────────────────┐
│  剩余: 920例 (-30)   │
└──────┬───────────────┘
       │
       ↓ 排除重复记录
┌──────────────────────┐
│  最终纳入: 910例     │
└──────────────────────┘

[导出为图片] [导出为Word]

实现要点

  • 记录每步筛选的条件和结果
  • 生成可发表的流程图
  • 支持导出为高分辨率图片

7.8 数据质量报告(优先级:低)

医学背景

  • 数据质量直接影响研究结论
  • 需要在分析前进行质量评估
  • 期刊要求描述数据质量

功能设计

点击"生成数据质量报告"

生成PDF报告包含
1. 数据概况
   - 样本量、变量数
   - 数据收集时间跨度

2. 完整性分析
   - 各变量缺失率
   - 缺失模式MCAR/MAR/MNAR检验

3. 一致性检查
   - 逻辑错误(如:出生日期>死亡日期)
   - 重复记录

4. 分布分析
   - 连续变量分布(直方图+Q-Q图
   - 分类变量频数表

5. 异常值检测
   - 箱线图
   - 异常值列表

6. 建议操作
   - 需要处理的问题清单
   - 优先级排序

实现要点

  • 自动生成可发表的表格/图
  • 支持导出为Word/PDF
  • 符合临床研究报告规范

实施计划

功能 优先级 预计工时 计划时间
7.1 异常值检测器 2天 Phase 4
7.2 单位转换器 1.5天 Phase 4
7.3 日期计算器 2天 Phase 4
7.4 临床截断值分箱 1天 Phase 3增强
7.5 高级缺失值填补 1.5天 Phase 3增强
7.6 Codebook生成 1天 Phase 5
7.7 筛选流程图 1.5天 Phase 5
7.8 数据质量报告 2天 Phase 5

总计12.5天工时


TD-C-008: 自定义函数库

愿景: 用户可保存常用代码为函数,一键复用

# 用户保存的自定义函数
my_functions = {
    "血压分类": "df['bp_category'] = ...",
    "年龄分组": "df['age_group'] = ...",
}

# 一键应用
apply_function("血压分类")

TD-C-009: 协作功能

愿景: 多人协作数据清洗

  • 权限管理:查看/编辑/审核
  • 操作日志:谁在什么时候做了什么
  • 评论功能:对特定操作添加备注

TD-C-010: AI智能推荐

愿景: AI主动检测数据问题并推荐操作

quality_check = {
    "发现23个异常值": "建议使用异常值检测器",
    "年龄列缺失32%": "建议使用LOCF填补",
    "BMI未分类": "建议使用WHO标准分箱",
}

📊 债务统计

按优先级

  • P0: 1项前端UI阻塞发布
  • P1: 2项Session持久化、Prompt优化
  • P2: 3项版本管理、大文件、复杂场景优化
  • P3: 4项长期规划 + 医学专业功能增强)

按工时

  • 0.5天: 1项复杂场景优化
  • 1天: 1项Session持久化
  • 1-2天: 2项版本管理、大文件
  • 3天以上: 1项前端UI
  • 持续优化: 1项Prompt优化
  • 医学专业功能: 12.5天8个子功能

总计

  • 技术债务总数: 13项含医学专业功能8个子项
  • 近期必做: 4项P0-P1 + 复杂场景)
  • 预计总工时: ~23-25天
    • MVP相关~10.5-12.5天
    • 医学专业增强:~12.5天

🔄 更新记录

日期 版本 更新内容 更新人
2025-12-08 V1.2 新增TD-C-007医学专业功能增强8项 AI Assistant
2025-12-07 V1.1 新增TD-C-006复杂场景Prompt优化 AI Assistant
2025-12-06 V1.0 初始创建Day 3 MVP完成后梳理 AI Assistant

文档状态: 已更新
下次更新: Phase 4开发完成后