Files
AIclinicalresearch/docs/03-业务模块/DC-数据清洗整理/02-技术设计/工具 C:AI 辅助医疗数据清洗场景分级清单.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

114 lines
6.4 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.
# **工具 CAI 辅助医疗数据清洗场景分级清单**
这份清单按**技术实现难度**和**业务逻辑复杂度**从简单到复杂排列。所有场景均假设数据已加载为 Pandas DataFrame (df)。
## **Level 1: 基础卫生清理 (Data Hygiene)**
*目标把“脏”数据变成“能读”的数据。Excel 也能做,但 Python 更快更准。*
### **1.1 变量名标准化 (Rename)**
* **场景:** 原始表头是中文或含特殊符号(年龄(岁), 性别/Gender, 入院\_日期SPSS 报错。
* **用户指令:** “把所有列名转为纯英文小写,去掉括号。”
* **Python 逻辑:** 使用映射字典或正则替换列名。
### **1.2 数值列“排毒” (Clean Numeric)**
* **场景:** 检验科导出的数据,数值列混入了符号(\>100, \<0.1, 12.5+, 未查)。
* **用户指令:** “把‘肌酐’列里的非数字符号去掉,‘\<0.10.05’处理,转为浮点数。”
* **Python 逻辑:** str.replace \+ 正则提取 \+ pd.to\_numeric(errors='coerce')。
### **1.3 统一缺失值 (Standardize Nulls)**
* **场景:** 数据里混杂了各种代表“空”的词NA, N/A, \-, \\, 不详。
* **用户指令:** “把所有代表‘没有’的字符都统一替换为标准的空值。”
* **Python 逻辑:** df.replace(\['-', '不详', 'NA'\], np.nan, inplace=True)。
## **Level 2: 变量标准化与重编码 (Recode & Standardization)**
*目标:为统计分析准备分类变量。*
### **2.1 文本转数值映射 (Map Categorical)**
* **场景:** 性别列是 Male/Female吸烟史是 Yes/No。
* **用户指令:** “把性别转为 1(男)/0(女),把吸烟史转为 1/0。”
* **Python 逻辑:** df\['sex'\].map({'Male': 1, 'Female': 0})。
### **2.2 连续变量分箱 (Binning)**
* **场景:** 需要按年龄分组进行卡方检验。
* **用户指令:** “把年龄按 0-18, 19-60, 60+ 分为‘未成年’, ‘成年’, ‘老年’三组。”
* **Python 逻辑:** pd.cut() 函数。
### **2.3 复杂日期计算 (Date Logic)**
* **场景:** 计算生存时间OS。Excel 经常算错闰年或月份。
* **用户指令:** “根据确诊日期随访日期计算生存月数保留1位小数。”
* **Python 逻辑:** (df\['end\_date'\] \- df\['start\_date'\]).dt.days / 30.4。
## **Level 3: 临床逻辑特征工程 (Feature Engineering)**
*目标:基于医学知识生成新的分析指标。*
### **3.1 复合公式计算 (Complex Formula)**
* **场景:** 计算 eGFR (肾小球滤过率) 或 BMI。
* **用户指令:** “帮我计算 BMI。如果 BMI \> 28生成新列标记为肥胖。”
* **Python 逻辑:** 向量化计算 df\['weight'\] / (df\['height'\]/100)\*\*2 \+ 条件赋值 np.where。
### **3.2 提取入排标准 (Cohort Selection)**
* **场景:** 筛选符合条件的入组人群。
* **用户指令:** “筛选出确诊为肺腺癌且年龄大于18岁且没有高血压病史的病人。”
* **Python 逻辑:** df.query("diagnosis \== 'Lung Adenocarcinoma' & age \> 18 & hypertension \== 0")。
### **3.3 哑变量生成 (One-Hot Encoding)**
* **场景:** 准备做 Logistic 回归,有一个无序多分类变量“血型 (A, B, AB, O)”。
* **用户指令:** “把血型生成哑变量。”
* **Python 逻辑:** pd.get\_dummies(df\['blood\_type'\], prefix='blood')。
## **Level 4: 结构重塑与高级治理 (Reshaping & Governance)**
*目标:改变表格结构以适应特定的统计模型,或进行高阶数据修复。*
### **4.1 长宽表转换 (Pivot/Melt) —— Excel 的噩梦**
* **场景:** 目前是“一人多行”(张三-第1次化验张三-第2次化验要做重复测量分析需要变成“一人一行”张三-化验1-化验2
* **用户指令:** “把表格从长表转为宽表按病人ID索引访视次序做后缀铺开白细胞列。”
* **Python 逻辑:** df.pivot(index='id', columns='visit', values='wbc')。
### **4.2 智能去重 (Smart Deduplication)**
* **场景:** 同一个病人有两条记录,一条信息全,一条信息缺。
* **用户指令:** “按病人ID去重。如果有重复保留检查日期最近的那一条如果日期一样保留数据完整度最高的那条。”
* **Python 逻辑:** df.sort\_values(\['date', 'completeness'\]).drop\_duplicates(subset=\['id'\], keep='last')。
### **4.3 跨列逻辑校验 (Cross-Check)**
* **场景:** 发现脏数据。
* **用户指令:** “检查一下有没有‘男性’但是‘怀孕次数\>0的错误数据标记出来。”
* **Python 逻辑:** df.loc\[(df\['sex'\]=='男') & (df\['preg\_count'\]\>0), 'error\_flag'\] \= 1。
### **4.4 多重插补 (Multiple Imputation) —— 统计学的高级填补**
* **场景:** 数据集有缺失值(如 BMI 缺失),单纯用均值填补会破坏数据分布。需要利用其他变量(如年龄、性别、肌酐)的相关性来预测填补。
* **用户指令:** “使用多重插补法(MICE)对BMI年龄列的缺失值进行填补。”
* # **Python 逻辑: \`\`\`python** **from sklearn.experimental import enable\_iterative\_imputer** **from sklearn.impute import IterativeImputer** **仅针对数值列进行插补** **cols \= \['bmi', 'age', 'creatinine'\]** **imp \= IterativeImputer(max\_iter=10, random\_state=0)** **df\[cols\] \= imp.fit\_transform(df\[cols\])**
## **Level 5: 非结构化文本挖掘 (Text Mining) —— Python 的绝对统治区**
*目标:从备注或报告文本中“抠”出数据。这是 Excel 绝对做不到的。*
### **5.1 正则表达式提取 (Regex Extraction)**
* **场景:** 只有一列文本“病理诊断”,内容如:“(左肺上叶)浸润性腺癌大小3.5\*2cm”。需要提取肿瘤大小。
* **用户指令:** “从‘病理诊断’里提取出肿瘤的长径(最大的那个数字)。”
* **Python 逻辑:** df\['text'\].str.extract(r'(\\d+\\.?\\d\*)\\s\*\[\\\*xX\]\\s\*(\\d+\\.?\\d\*)') 并取最大值。
### **5.2 字符串模糊匹配 (Fuzzy Matching)**
* **场景:** 医院名称录入混乱:“协和医院”、“北京协和”、“协和”。需要统一。
* **用户指令:** “把医院名称列里所有包含协和都统一改为PUMCH。”
* **Python 逻辑:** df.loc\[df\['hospital'\].str.contains('协和'), 'hospital'\] \= 'PUMCH'。