feat: UI全面改造 + 后端多项修复
【后端修复】 - 删除diet/consultation agent假工具声明 - 修复DayOfWeek实体注释 - 修复Vision API content序列化 - cleanup_service级联删除修复 - 用药提醒时区偏差修复 - 统一DateTime处理(UtcNow+8) - 新增UTC DateTime JSON转换器 【前端UI重构】 - 配色体系全面更新(#8B5CF6淡紫+#F0ECFF背景) - 登录页重设计 - 首页重设计(透明顶栏、渐变背景、胶囊输入区) - 聊天卡片加白蓝边框、渐变标题 - 侧边栏重构(渐变背景、合并顶部、删除底部设置) - 确认卡片可编辑字段恢复 - 所有子页面加返回按钮 - catch异常加日志 - 删除后refresh provider缓存
This commit is contained in:
438
docs/BUG_REVIEW.md
Normal file
438
docs/BUG_REVIEW.md
Normal file
@@ -0,0 +1,438 @@
|
||||
# 健康管家 — 全面代码审查与Bug文档
|
||||
|
||||
> 审查日期:2026-06-10 | 范围:全栈(后端 .NET 10 + 前端 Flutter)
|
||||
|
||||
---
|
||||
|
||||
## 测试结果汇总
|
||||
|
||||
| 测试集 | 通过 | 失败 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| 后端单元测试 (entity_tests) | 10 | 0 | 实体/数据库操作全通过 |
|
||||
| 后端单元测试 (auth_tests) | 4 | 0 | 认证流程全通过 |
|
||||
| 后端单元测试 (ai_agent_tests - PromptManager) | 8 | 0 | AI提示词全通过 |
|
||||
| 后端集成测试 (ai_agent_tests - AI对话) | 0 | 5 | 需要后端运行中 |
|
||||
| Flutter 测试 (widget_test) | - | - | sqlite3 原生库下载失败,无法运行 |
|
||||
|
||||
**总计:22/27 通过(5个集成测试需要后端在线)**
|
||||
|
||||
---
|
||||
|
||||
## 一、后端 Bug
|
||||
|
||||
### B1. 缺少 consultation DELETE 端点
|
||||
- **位置**:`consultation_endpoints.cs`
|
||||
- **问题**:问诊创建后无删除/取消接口。患者无法取消发起的问诊
|
||||
- **影响**:患者发起错误问诊后无法撤销
|
||||
- **建议**:添加 `MapDelete("/consultations/{id:guid}", ...)`
|
||||
|
||||
### B2. ai_chat_endpoints 中 unified agent 缺少部分工具
|
||||
- **位置**:`ai_chat_endpoints.cs:340-347`
|
||||
- **问题**:unified agent 虽聚合了 7 种工具,但缺少 `manage_archive` 和 `request_doctor`
|
||||
- **影响**:用户在 unified 模式无法通过对话修改档案或请求医生
|
||||
|
||||
### B3. CompressImage 未释放 GDI 资源
|
||||
- **位置**:`ai_chat_endpoints.cs:484-503`
|
||||
- **问题**:`Image.FromFile`、`Bitmap`、`Graphics` 均 `using` 包裹,但 `EncoderParameters` 未释放
|
||||
- **影响**:每次食物识别可能泄漏少量非托管内存
|
||||
- **修复**:`using var parameters = new EncoderParameters(1);`
|
||||
|
||||
### B4. 用药提醒服务可能定时查询过于频繁
|
||||
- **位置**:`BackgroundServices/medication_reminder_service.cs`
|
||||
- **问题**:需要检查轮询间隔,每分钟查一次可能对数据库压力大
|
||||
|
||||
### B5. 开发数据种子硬编码 API Key 检查
|
||||
- **位置**:`dev_data_seeder.cs`
|
||||
- **问题**:`DEVDATA_ENABLED=true` 创建测试用户,生产环境可能误开启
|
||||
|
||||
---
|
||||
|
||||
## 二、前端 Bug
|
||||
|
||||
### C1. ~~聊天列表从顶部跳到底部~~ ✅ 已修复
|
||||
- **修复**:`chat_messages_view.dart` 改为 `reverse:true`
|
||||
- **修复**:`home_page.dart` 滚动逻辑简化
|
||||
|
||||
### C2. ~~SwipeDeleteTile 内层手势冲突~~ ✅ 已修复
|
||||
- **修复**:`common_widgets.dart` 滑动状态下用 `AbsorbPointer` 屏蔽内部按钮
|
||||
|
||||
### C3. ~~SwipeDeleteTile 红色溢出~~ ✅ 已修复
|
||||
- **修复**:margin 参数从 Stack 内部移到外部 Padding
|
||||
|
||||
### C4. ~~运动打卡 dayOfWeek 索引偏差~~ ✅ 已修复
|
||||
- **修复**:`remaining_pages.dart` 改为 `weekday % 7` 与 C# DayOfWeek 对齐
|
||||
|
||||
### C5. ~~用药管理 Dismissible 一步删除~~ ✅ 已修复
|
||||
- **修复**:统一使用 `SwipeDeleteTile`
|
||||
|
||||
### C6. Flutter 测试断言错误
|
||||
- **位置**:`health_app/test/widget_test.dart:9`
|
||||
- **代码**:`expect(AppTheme.primary, AppTheme.primaryLight);`
|
||||
- **问题**:`primary` (0xFF6366F1) ≠ `primaryLight` (0xFFEEF2FF),这个断言必然失败
|
||||
- **修复**:改为 `expect(AppTheme.primary, const Color(0xFF6366F1));`
|
||||
|
||||
### C7. home_page.dart onTap 手误写了 `?.()`
|
||||
- **位置**:`home_page.dart:115`
|
||||
- **代码**:`onTap: () => pushRoute(ref, 'notificationPrefs')` 实际没有 `?.()` 问题(之前看错了),此处无误
|
||||
|
||||
### C8. 报告详情返回按钮:popRoute 在 setState 后
|
||||
- **位置**:`report_pages.dart:449-454`
|
||||
- **问题**:`clearAnalysis()` 调用 `state.copyWith(...)` 然后立即 `popRoute(ref)`,在 pop 过程中可能访问已 dispose 的 provider
|
||||
- **风险**:中等
|
||||
|
||||
### C9. DietCapturePage TextField 内存泄漏
|
||||
- **位置**:`diet_capture_page.dart:465,479,495`
|
||||
- **问题**:每个食物项创建 `TextEditingController(text: food.name)` 但从不 dispose
|
||||
- **修复**:用 `TextFormField` + `initialValue` 或缓存 controller
|
||||
|
||||
### C10. 报告上传错误吞没
|
||||
- **位置**:`report_pages.dart:199`
|
||||
- **代码**:`} catch (_) {}` — 上传失败无任何反馈
|
||||
- **修复**:至少显示 snackbar 提示
|
||||
|
||||
---
|
||||
|
||||
## 三、前端缺失功能
|
||||
|
||||
### M1. 饮食记录无编辑/修改功能
|
||||
- 当前只能查看(`DietRecordDetailPage`)和删除,无法修改已有记录
|
||||
|
||||
### M2. 运动计划详情页缺失
|
||||
- `ExercisePlanPage` 的 `onTap: () {}` 为空,点卡片无反应
|
||||
- 没有类似 `ExercisePlanDetailPage` 的页面
|
||||
|
||||
### M3. 问诊列表无前端入口
|
||||
- 后端有 `/api/consultations` GET,但前端没有问诊历史列表页
|
||||
|
||||
### M4. 对话无删除/清空功能
|
||||
- 后端有 `DELETE /api/ai/conversations/{id}`,但前端无对应UI
|
||||
|
||||
### M5. 无数据导出功能
|
||||
- 用户无法导出健康数据(血压记录、饮食记录等)
|
||||
|
||||
---
|
||||
|
||||
## 四、安全与代码质量
|
||||
|
||||
### S1. JWT Secret 开发默认值
|
||||
- **位置**:`Program.cs:46`
|
||||
- **问题**:`jwtSecret ??= "dev-secret-key-change-in-production-min-32-chars!!";`
|
||||
- **风险**:若忘记设环境变量,生产环境用弱密钥
|
||||
|
||||
### S2. token 通过 query string 传输(SSE)
|
||||
- **位置**:`ai_chat_endpoints.cs:25`, `sse_handler.dart:17`
|
||||
- **问题**:`token` 放在 URL query string,会被服务器日志、代理缓存
|
||||
- **风险**:中等(含过期时间的 token,但仍有泄露风险)
|
||||
|
||||
### S3. CORS 全开
|
||||
- **位置**:`Program.cs:96-98`
|
||||
- **代码**:`policy.SetIsOriginAllowed(_ => true)`
|
||||
- **风险**:生产环境应限定具体 origin
|
||||
|
||||
### S4. 全局异常中间件可能泄露内部错误
|
||||
- **位置**:`exception_middleware.cs`
|
||||
- **需要检查**:是否在生产环境返回了调用栈
|
||||
|
||||
### S5. Flutter 硬编码后端 IP
|
||||
- **位置**:`api_client.dart:6`
|
||||
- **代码**:`const String baseUrl = 'http://10.4.164.158:5000';`
|
||||
- **问题**:每次换网络都需改代码
|
||||
|
||||
---
|
||||
|
||||
## 五、未使用代码(可清理)
|
||||
|
||||
- `chat_messages_view.dart`: `_cardFilledBtn`, `_cardOutlineBtn`, `_agentColors`, `_taskRow` 未使用
|
||||
- `chat_provider.dart`: `_parseAgent` 未使用
|
||||
- `remaining_pages.dart`: `shadcn_ui` 导入未使用
|
||||
- `report_pages.dart`: `shadcn_ui` 导入未使用,`reportId` 变量未使用
|
||||
- `service_package_detail_page.dart`: `navigation_provider` 导入未使用
|
||||
|
||||
---
|
||||
|
||||
## 六、Agent 自动审查新增发现
|
||||
|
||||
### A1. app_router.dart 无防御 null 断言(🔴严重)
|
||||
- **位置**:`app_router.dart:41-73`
|
||||
- **代码示例**:`ReportDetailPage(id: params['id']!)` 等多处
|
||||
- **问题**:`params['id']!` 若 params 中无 'id' 键,会抛出 null 断言异常导致崩溃
|
||||
- **影响**:任何路由参数拼写错误或缺少都会 crash
|
||||
- **修复**:使用 `params['id'] ?? ''` 并提供 fallback
|
||||
|
||||
### A2. device_scan_page.dart BLE 流订阅未取消(🔴严重)
|
||||
- **位置**:`device_scan_page.dart`
|
||||
- **问题**:BLE stream subscription 在 dispose 时未 cancel,导致蓝牙连接泄漏
|
||||
- **影响**:多次进出扫描页会积累未释放的 BLE 连接
|
||||
|
||||
### A3. 静默吞错误(🟡中)
|
||||
- **范围**:全前端 28 处 `catch (_) {}`
|
||||
- **问题**:所有 API 错误、解析错误均无日志或用户提示
|
||||
- **修复**:至少加上 `debugPrint('Error: $e')` 或显示 snackbar
|
||||
|
||||
### A4. 删除后未刷新 Provider(🟡中)
|
||||
- **范围**:多个页面
|
||||
- **问题**:删除操作后调用了 `_load()` 或 `_refresh()`(setState),但未调用 `ref.invalidate(someProvider)`,导致 Riverpod 缓存未更新
|
||||
- **影响**:切换到其他页面再回来,旧数据可能仍显示
|
||||
|
||||
### A5. FutureProvider + setState 双重模式(🟢低)
|
||||
- **范围**:`DietRecordListPage`, `ExercisePlanPage` 等
|
||||
- **问题**:同时使用 Riverpod FutureProvider 和本地 setState,导致 provider 失效无效
|
||||
|
||||
---
|
||||
|
||||
## 七、全部问题汇总(含Agent发现)
|
||||
|
||||
| # | 优先级 | 位置 | 问题描述 |
|
||||
|---|--------|------|----------|
|
||||
| 1 | 🔴 | `app_router.dart` | null 断言无防御,参数缺失即崩溃 |
|
||||
| 2 | 🔴 | `device_scan_page.dart` | BLE 流订阅未取消 |
|
||||
| 3 | 🔴 | `B1` consultation | 缺少 DELETE 端点 |
|
||||
| 4 | 🔴 | `S1` Program.cs | JWT 开发默认弱密钥 |
|
||||
| 5 | 🔴 | `C9` diet_capture | TextEditingController 泄漏 |
|
||||
| 6 | 🟡 | 全局 28处 | catch(_){} 静默吞错 |
|
||||
| 7 | 🟡 | 多页面 | 删除后无 ref.invalidate |
|
||||
| 8 | 🟡 | `C6` widget_test | 断言 primary == primaryLight 错误 |
|
||||
| 9 | 🟡 | `C10` report | 上传失败无提示 |
|
||||
| 10 | 🟡 | `M2` exercise | 运动详情页缺失,onTap 空 |
|
||||
| 11 | 🟡 | `C8` report | pop 时序问题 |
|
||||
| 12 | 🟡 | `A5` 多页面 | FutureProvider+setState 双重模式 |
|
||||
| 13 | 🟢 | `B3` ai_chat | EncoderParameters 未释放 |
|
||||
| 14 | 🟢 | `B4` bg_service | 用药提醒轮询频率需审视 |
|
||||
| 15 | 🟢 | `B5` dev_data | 生产环境可能误开启测试数据 |
|
||||
| 16 | 🟢 | `S2` SSE | token 走 query string |
|
||||
| 17 | 🟢 | `S3` CORS | 全开 AllowCredentials |
|
||||
| 18 | 🟢 | `S5` api_client | 硬编码 IP |
|
||||
| 19 | 🟢 | 多处 | 未使用代码可清理 |
|
||||
| 20 | 🟢 | `B2` unified | unified agent 缺少 manage_archive 工具 |
|
||||
|
||||
---
|
||||
|
||||
## 八、后端 Agent 审查新增发现(关键)
|
||||
|
||||
### D1. 运动计划 DayOfWeek 跨层不一致(🔴严重)
|
||||
- **位置**:`prompt_manager.cs` vs `exercise_plan.cs` 实体注释
|
||||
- **问题**:Prompt 告诉 AI `day_of_week: 0-6(周日=0)`,但实体注释 `// 0=周一, 6=周日`。AI 按周日=0 生成数据,后端按周一=0 解析,运动计划星期全偏一天
|
||||
- **修复**:统一为 C# DayOfWeek 枚举(0=周日)
|
||||
|
||||
### D2. SMS 验证码使用伪随机数(🔴安全漏洞)
|
||||
- **位置**:`sms_service.cs`
|
||||
- **问题**:`Random.Shared.Next(100000, 1000000)` 使用 PRNG,攻击者可预测验证码
|
||||
- **修复**:改用 `RandomNumberGenerator.GetInt32(100000, 999999)`
|
||||
|
||||
### D3. checkin 无所有权验证(🔴越权漏洞)
|
||||
- **位置**:`medication_agent_handler.cs:99`、`exercise_agent_handler.cs:69`
|
||||
- **问题**:`confirm_medication` 和 `exercise checkin` 直接通过 itemId 操作,不验证是否属于当前用户。任何认证用户可操作他人数据
|
||||
- **修复**:添加 `&& item.Plan.UserId == userId` 检查
|
||||
|
||||
### D4. VisionAsync content 序列化错误(🔴严重)
|
||||
- **位置**:`open_ai_compatible_client.cs:136`
|
||||
- **问题**:将图片 contentParts 先序列化为 JSON 字符串再赋值给 Content,但 OpenAI 兼容 API 期望 Content 为数组格式
|
||||
- **影响**:食物识别 VLM 调用可能失败
|
||||
|
||||
### D5. diet/consultation agent 工具声明但未实现(🔴严重)
|
||||
- **位置**:`diet_agent_handler.cs`、`consultation_agent_handler.cs`
|
||||
- **问题**:`EstimateFoodTool` 和 `RequestDoctorTool` 在 Tools 列表中声明,但 Execute 方法无对应 case,调用返回"未知工具"
|
||||
- **影响**:饮食识别和请求医生功能不可用
|
||||
|
||||
### D6. CleanupService 删除未级联(🔴严重)
|
||||
- **位置**:`cleanup_service.cs:28`
|
||||
- **问题**:`db.Conversations.RemoveRange(oldConversations)` 未先删除关联的 ConversationMessage,可能因 FK 约束抛异常
|
||||
- **修复**:先删除 Messages 再删 Conversations,或使用 ExecuteDeleteAsync
|
||||
|
||||
### D7. 用药提醒时区计算 bug(🔴严重)
|
||||
- **位置**:`medication_reminder_service.cs:37`
|
||||
- **问题**:`DateTime.SpecifyKind(beijingNow.Date, DateTimeKind.Utc)` — 北京时间 00:00 被标记为 UTC 00:00,导致打卡检测有 8 小时偏差
|
||||
- **影响**:提醒时间错位、重复提醒或漏提醒
|
||||
|
||||
### D8. DbContext 未配置外键和级联删除(🟡中等)
|
||||
- **位置**:`app_db_context.cs`
|
||||
- **问题**:`OnModelCreating` 没有任何 `HasOne/WithMany/HasForeignKey/OnDelete` 配置,全凭约定
|
||||
- **影响**:数据库无 FK 约束、级联行为不明确、RefreshToken 全表扫描
|
||||
|
||||
### D9. 缺少多个数据库索引(🟡中等)
|
||||
- RefreshToken: 无索引,认证查询全表扫描
|
||||
- FollowUp: 无 (UserId, ScheduledAt) 索引
|
||||
- DeviceToken: 无 UserId 索引
|
||||
- Report: 无 (UserId, CreatedAt) 索引
|
||||
|
||||
### D10. ExceptionMiddleware 统一返回500(🟡中等)
|
||||
- **位置**:`exception_middleware.cs`
|
||||
- **问题**:所有异常都返回 500,不区分 400/401/404
|
||||
- **影响**:客户端无法根据状态码处理不同类型的错误
|
||||
|
||||
### D11. 用药提醒未实际推送(🟡中等)
|
||||
- **位置**:`medication_reminder_service.cs`
|
||||
- **问题**:TODO 注释表明推送尚未实现,只记录日志
|
||||
|
||||
### D12. Prompt 文本硬编码(🟢低)
|
||||
- 不支持热更新,修改需重新编译
|
||||
|
||||
---
|
||||
|
||||
## 九、最终汇总(所有发现)
|
||||
|
||||
| # | 优先级 | 类别 | 位置 | 问题 |
|
||||
|---|--------|------|------|------|
|
||||
| 1 | 🔴 | 安全 | sms_service | 验证码用 PRNG 可预测 |
|
||||
| 2 | 🔴 | 安全 | agent handlers | checkin 越权漏洞 |
|
||||
| 3 | 🔴 | 逻辑 | prompt/entity | DayOfWeek 跨层不一致 |
|
||||
| 4 | 🔴 | 功能 | diet/consult agent | 工具声明但未实现 |
|
||||
| 5 | 🔴 | 功能 | open_ai_client | Vision content 序列化错误 |
|
||||
| 6 | 🔴 | 稳定性 | cleanup_service | 删除未级联 FK 冲突 |
|
||||
| 7 | 🔴 | 功能 | reminder_service | 时区计算 8h 偏差 |
|
||||
| 8 | 🔴 | 崩溃 | app_router.dart | null 断言无防御 |
|
||||
| 9 | 🔴 | 泄漏 | device_scan_page | BLE 流未取消 |
|
||||
| 10 | 🔴 | 安全 | Program.cs | CORS 全开+AllowCredentials |
|
||||
| 11 | 🔴 | 安全 | Program.cs | JWT 默认弱密钥 |
|
||||
| 12 | 🔴 | 泄漏 | diet_capture | TextEditingController 未释放 |
|
||||
| 13 | 🟡 | 体验 | 28处 | catch(_){} 静默吞错 |
|
||||
| 14 | 🟡 | 逻辑 | 多页面 | 删除后未 invalidate provider |
|
||||
| 15 | 🟡 | 配置 | app_db_context | 无 FK/级联/索引 |
|
||||
| 16 | 🟡 | 体验 | exception_middleware | 统一返回 500 |
|
||||
| 17 | 🟡 | 测试 | widget_test | 断言永远失败 |
|
||||
| 18 | 🟡 | 功能 | 用药提醒 | 推送未实现 |
|
||||
| 19 | 🟡 | 架构 | 多页面 | FutureProvider+setState 混用 |
|
||||
| 20 | 🟡 | 缺失 | exercise | 计划详情页缺失 |
|
||||
| 21 | 🟢 | 代码 | 多处 | 未使用代码/本地时间/冗余 |
|
||||
|
||||
---
|
||||
|
||||
## 十、后端端点 Agent 审查新增发现(关键)
|
||||
|
||||
### E1. 医生端点零授权(🔴阻断级)
|
||||
- **位置**:`doctor_endpoints.cs:19`
|
||||
- **问题**:`MapGroup("/api/doctor")` **没有 `.RequireAuthorization()`**,所有医生端点(患者详情、健康数据、问诊、报告、随访)对公网开放
|
||||
- **影响**:任何人可查看所有患者隐私数据、修改报告、创建/删除随访
|
||||
|
||||
### E2. consultation POST 消息无所有权检查(🔴阻断级)
|
||||
- **位置**:`consultation_endpoints.cs:48-75`
|
||||
- **问题**:发消息只检查 consultation 存在,不验证是否属于当前用户。用户A可向用户B的问诊发消息
|
||||
|
||||
### E3. exercise checkin 无所有权检查(🔴阻断级)
|
||||
- **位置**:`exercise_endpoints.cs:119`
|
||||
- **问题**:`FindAsync([itemId])` 只按ID查,不验证 `item.Plan.UserId == userId`。用户可操作他人运动计划
|
||||
|
||||
### E4. SMS验证码在响应中暴露(🔴严重)
|
||||
- **位置**:`auth_endpoints.cs:34`
|
||||
- **问题**:`devCode = code` 将6位验证码直接返回在JSON中,无 `#if DEBUG` 守卫
|
||||
|
||||
### E5. Task.Run 火后不理模式(🔴严重)
|
||||
- **位置**:`report_endpoints.cs:67`
|
||||
- **问题**:`_ = Task.Run(async () => { ... }, CancellationToken.None)` 在请求结束后 scope 可能已释放,后台任务崩溃
|
||||
|
||||
### E6. System.Drawing 仅Windows(🔴严重)
|
||||
- **位置**:`ai_chat_endpoints.cs:486-494`
|
||||
- **问题**:`Image.FromFile`/`Bitmap`/`Graphics` 在Linux容器中崩溃
|
||||
|
||||
### E7. 健康数据 N+1 查询(🟡中等)
|
||||
- **位置**:`health_endpoints.cs:78-89`
|
||||
- **问题**:`/latest` 对5种指标类型分别发一次SQL查询
|
||||
|
||||
### E8. 日历用药事件显示错误(🟡中等)
|
||||
- **位置**:`calendar_endpoints.cs:49`
|
||||
- **问题**:用户有任意活跃用药就在每月每天标记"用药",不区分具体哪天该吃药
|
||||
|
||||
### E9. 手动JSON解析绕过模型绑定(🟡中等)
|
||||
- **范围**:diet、medication、exercise、doctor endpoints
|
||||
- **问题**:`JsonDocument.Parse` 手动解析导致 Swagger 无法文档化、无自动验证、拼写错误抛500
|
||||
|
||||
### E10. 缺失端点
|
||||
- health:缺 DELETE
|
||||
- diet:缺 PUT
|
||||
- exercise:缺 PUT
|
||||
- report:缺 DELETE
|
||||
- file:缺 GET/DELETE/list
|
||||
- followup:缺 detail/confirm
|
||||
|
||||
---
|
||||
|
||||
## 十一、完整问题排名
|
||||
|
||||
| # | 等级 | 文件 | 问题 |
|
||||
|---|------|------|------|
|
||||
| 1 | 🔴🔴 | doctor_endpoints | **零授权** — 所有患者数据公开 |
|
||||
| 2 | 🔴🔴 | consultation | 发消息无所有权检查 |
|
||||
| 3 | 🔴🔴 | exercise | checkin无所有权检查 |
|
||||
| 4 | 🔴 | auth | SMS验证码响应暴露 |
|
||||
| 5 | 🔴 | report | Task.Run火后不理 |
|
||||
| 6 | 🔴 | ai_chat | System.Drawing仅Windows |
|
||||
| 7 | 🔴 | sms_service | PRNG可预测验证码 |
|
||||
| 8 | 🔴 | agent handlers | checkin越权 |
|
||||
| 9 | 🔴 | prompt_manager | DayOfWeek不一致 |
|
||||
| 10 | 🔴 | diet/consult agent | 工具声明未实现 |
|
||||
| 11 | 🔴 | open_ai_client | Vision序列化错误 |
|
||||
| 12 | 🔴 | cleanup_service | 删除未级联 |
|
||||
| 13 | 🔴 | reminder_service | 时区8h偏差 |
|
||||
| 14 | 🔴 | app_router | null断言崩溃 |
|
||||
| 15 | 🔴 | device_scan | BLE泄漏 |
|
||||
| 16 | 🔴 | Program.cs | CORS全开 |
|
||||
| 17 | 🔴 | Program.cs | JWT弱密钥 |
|
||||
| 18 | 🔴 | diet_capture | Controller泄漏 |
|
||||
| 19 | 🟡 | 28处 | catch(_){}吞错 |
|
||||
| 20 | 🟡 | 多页面 | 删除未invalidate |
|
||||
| 21 | 🟡 | health | N+1查询 |
|
||||
| 22 | 🟡 | calendar | 用药事件逻辑错误 |
|
||||
| 23 | 🟡 | app_db_context | 无FK/索引配置 |
|
||||
| 24 | 🟡 | exception_mw | 统一500 |
|
||||
| 25 | 🟡 | 提醒服务 | 推送未实现 |
|
||||
| 26 | 🟡 | 多端点 | 缺PUT/DELETE |
|
||||
| 27 | 🟡 | 多端点 | 手动JSON无验证 |
|
||||
|
||||
---
|
||||
|
||||
## 优先级排序
|
||||
|
||||
| 优先级 | Bug | 影响范围 |
|
||||
|--------|-----|----------|
|
||||
| 🔴 高 | C9: TextEditingController 内存泄漏 | 饮食识别页面 |
|
||||
| 🔴 高 | B1: 缺少 consultation DELETE | 问诊功能 |
|
||||
| 🔴 高 | S1: JWT 弱密钥默认值 | 安全 |
|
||||
| 🟡 中 | C6: Flutter 测试断言错误 | CI/CD |
|
||||
| 🟡 中 | C10: 报告上传错误吞没 | 用户体验 |
|
||||
| 🟡 中 | M2: 运动计划详情页缺失 | 用户体验 |
|
||||
| 🟡 中 | C8: report pop 时序问题 | 潜在崩溃 |
|
||||
| 🟢 低 | B3: EncoderParameters 未释放 | 极少量泄漏 |
|
||||
| 🟢 低 | S5: 硬编码 IP | 开发体验 |
|
||||
| 🟢 低 | 未使用代码 | 代码质量 |
|
||||
|
||||
---
|
||||
|
||||
*共发现 15 个问题,5 个缺失功能。其中 5 个 Bug 已在本轮修复。*
|
||||
|
||||
---
|
||||
|
||||
## 第二轮换角度审查(新增 10 个问题)
|
||||
|
||||
### F1. uploadFile 响应解析崩溃 🔴
|
||||
`api_client.dart:60-69` — 后端返回 `data: [{id, name, size}]`(List),前端做 `data['data']?['url']` 对List用字符串索引,运行时异常。聊天图片上传全部无声失败。
|
||||
|
||||
### F2. consultationChatProvider SignalR 永停不了 🔴
|
||||
`consultation_provider.dart` — `stop()` 定义了但无 Widget dispose 调用。离开问诊页后 SignalR 连接和 5秒轮询永续运行。
|
||||
|
||||
### F3. chatProvider 流订阅无 dispose 🔴
|
||||
`chat_provider.dart` — `_subscription`/`_streamTimer` 无 dispose,provider 销毁即泄漏。
|
||||
|
||||
### F4. ChatMessage 原地修改破坏不可变性 🔴
|
||||
`msg.confirmed = true` 直接修改 state 中的对象 → 违反 Riverpod 不可变契约。
|
||||
|
||||
### F5. 所有 FutureProvider 无 autoDispose 🟡
|
||||
6 个 FutureProvider 缓存永不过期,页面级数据不释放。
|
||||
|
||||
### F6. authProvider Token 刷新窗口期 id/phone 为空 🟡
|
||||
`auth_provider.dart:59` — `UserInfo(id: '', phone: '')` 然后等 `_loadProfile()` 异步补全。
|
||||
|
||||
### F7. 医生 Web 零认证 🔴🔴
|
||||
`doctor_web/src/services/api-client.ts` — 不发送 Authorization 头。叠加后端 doctor_endpoints 零授权(E1),任何人可访问所有患者数据。
|
||||
|
||||
### F8. 医生 Web SignalR handler 泄漏 🔴
|
||||
`ChatPage.tsx:28-65` — 组件卸载时若在 Reconnecting 状态,跳过 `off('ReceiveMessage')`,重复挂载累积 handler。
|
||||
|
||||
### F9. 6个后端端点前端从未调用 🟢
|
||||
`GET/DELETE /api/ai/conversations`、`GET /api/consultations`、`PUT /api/health-records/{id}`、全部 `/api/doctor/*`
|
||||
|
||||
### F10. 37 对 API 契约中 1 对崩溃 + 多端手动JSON脆弱 🟡
|
||||
`uploadFile` 是唯一崩溃的。其余 36 对匹配但 `TryGetProperty` 区分大小写,依赖前端恰好用 camelCase。
|
||||
|
||||
---
|
||||
|
||||
*两轮共发现 37 个问题,其中 5 个阻断级、19 个严重、10 个中等、3 个低。*
|
||||
Reference in New Issue
Block a user