feat: 二级页面色彩刷新 + 用药/通知/设备重构 + 后端健康档案/通知管线增强 + 大量测试
## 后端 - 健康档案: 新增手术状态字段 + EF 迁移; HealthArchiveService 新增查询方法 - 健康记录: HealthRecordService 新增批量/统计方法; 契约扩展 - 用药: 新增 MedicationScheduleStatus 枚举; MedicationService 排班逻辑调整 - 通知: EfUserNotificationPipeline 重构; 新增 EfReminderCatchUpService; 通知管线支持更多场景 - 用户: UserService 账号删除逻辑; 新增 local_account_file_cleanup; EfUserRepository 扩展 - AI: medication_agent_handler 微调; prompt_manager 优化; AiConversationService 上下文处理 - Endpoint: doctor/medication/exercise/health/notification/user 等多接口调整 - BackgroundService: health_record_reminder_service 重构, 提醒补漏逻辑 - 测试: 新增 account_deletion/doctor_endpoint/medication_schedule/medication_update/prompt_manager 测试 ## 前端 - UI 系统: app_theme 大幅重构; app_colors/app_design_tokens/app_module_visuals 调整; 二级页面色彩刷新 - 主页: home_page 背景渐变 + 消息列表提取 _HomeMessages + 通知检查逻辑; chat_messages_view 全面重构 - 用药: medication_list/edit/checkin 三页重构, 新增 medication_ui_logic 抽取 - 通知: notification_prefs_page 重构, 新增 notification_prefs_logic; notification_center 优化 - 设备: device_management 重构, 新增 device_sync_ui_logic; device_scan 优化 - 趋势图: trend_page 大幅重构 - 登录: login_page 重构 - 个人资料: 新增 profile_edit_page; profile_page 优化 - 运动: 新增 exercise/ 目录 + care_plan_ui_logic - 其他: remaining_pages/report_pages/health_drawer/admin/doctor 等多页面调整 - 组件: common_widgets/app_empty_state/app_error_state/app_future_view/app_toast/ai_content 优化 - Provider: chat_provider/consultation_provider/data_providers/auth_provider 调整 - AndroidManifest: 移除多余权限 - 测试: 新增 ai_content/care_plan/home_message/login_flow/medication_checkin/medication_ui/notification_prefs/profile_device/secondary_page/swipe_delete 等大量测试 ## 文档 - 新增 ui-design-system.md 设计系统文档 - 新增 secondary-page-color-refresh 计划 + specs 目录
This commit is contained in:
1
audit/2026-07-13/window.xml
Normal file
1
audit/2026-07-13/window.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/01-current.xml
Normal file
1
audit/2026-07-14/01-current.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/02-drawer.xml
Normal file
1
audit/2026-07-14/02-drawer.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/03-health-archive.xml
Normal file
1
audit/2026-07-14/03-health-archive.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/04-reports.xml
Normal file
1
audit/2026-07-14/04-reports.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/05-medications.xml
Normal file
1
audit/2026-07-14/05-medications.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/06-diet-records.xml
Normal file
1
audit/2026-07-14/06-diet-records.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/07-calendar.xml
Normal file
1
audit/2026-07-14/07-calendar.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/08-followups.xml
Normal file
1
audit/2026-07-14/08-followups.xml
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><hierarchy rotation="0"><node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,3200]"><node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,3200]"><node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,3200]"><node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="true" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,3200]"><node index="0" text="" resource-id="" class="android.view.View" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,3200]"><node index="0" text="" resource-id="" class="android.view.View" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,3200]"><node index="0" text="" resource-id="" class="android.view.View" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,3200]"><node index="0" text="" resource-id="" class="android.view.View" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,3200]"><node index="0" text="" resource-id="" class="android.view.View" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1440,302]"><node NAF="true" index="0" text="" resource-id="" class="android.widget.Button" package="com.datalumina.YYA" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[14,127][182,295]" /><node index="1" text="" resource-id="" class="android.view.View" package="com.datalumina.YYA" content-desc="复查随访" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[600,173][840,250]" /></node><node index="1" text="" resource-id="" class="android.view.View" package="com.datalumina.YYA" content-desc="暂无随访安排" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[600,1816][840,1872]" /><node index="2" text="" resource-id="" class="android.view.View" package="com.datalumina.YYA" content-desc="医生创建随访后将显示在这里" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[401,1886][1039,1952]" /></node></node></node></node></node></node></node></node></hierarchy>
|
||||
1
audit/2026-07-14/09-exercise.xml
Normal file
1
audit/2026-07-14/09-exercise.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/10-devices.xml
Normal file
1
audit/2026-07-14/10-devices.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/11-notifications.xml
Normal file
1
audit/2026-07-14/11-notifications.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/12-settings.xml
Normal file
1
audit/2026-07-14/12-settings.xml
Normal file
File diff suppressed because one or more lines are too long
1
audit/2026-07-14/13-profile.xml
Normal file
1
audit/2026-07-14/13-profile.xml
Normal file
File diff suppressed because one or more lines are too long
261
audit/2026-07-14/project-audit-report.md
Normal file
261
audit/2026-07-14/project-audit-report.md
Normal file
@@ -0,0 +1,261 @@
|
||||
# 小脉健康项目全面检查报告
|
||||
|
||||
检查日期:2026-07-14
|
||||
检查范围:Flutter Android 真机主要用户路径、Flutter 静态检查与测试、.NET 后端测试、前后端接口对应关系、用户/医生/管理员业务逻辑、权限安全、合规页面与 Android/iOS 发布准备。
|
||||
本轮只检查,没有修改业务代码,也没有使用 Docker。
|
||||
|
||||
## 一、总体结论
|
||||
|
||||
项目主体功能已经比较完整,普通用户主路径能进入,当前 Flutter 静态检查通过,Flutter 47 项测试和后端 44 项测试全部通过。但测试通过不等于已经稳定:本次仍确认了多项自动测试没有覆盖的真实断点。
|
||||
|
||||
当前不适合进入正式环境或商店审核。最优先的不是继续统一小间距,而是先处理问诊鉴权、管理员验证码、上传文件访问、蓝牙上传、账号注销清理和正式包权限。这些问题会影响真实数据、安全或用户是否能完成任务。
|
||||
|
||||
## 二、必须先修的问题
|
||||
|
||||
### 1. AI 流式聊天的 token 只被“读出来”,没有验证真伪
|
||||
|
||||
- 用户表现:正常用户不一定马上发现,但攻击者可以自己伪造一个 token,冒充任意用户进入 AI 对话、读取该用户上下文,并可能触发健康数据写入。
|
||||
- 原因:SSE 接口没有强制登录;备用 token 处理只解析 JWT 内容,没有校验签名、过期时间、签发方和接收方。
|
||||
- 位置:`backend/src/Health.WebApi/Endpoints/ai_chat_endpoints.cs` 的 `GetUserIdFromToken`。
|
||||
- 优先级:最高。
|
||||
|
||||
### 2. 医生问诊实时通道没有登录和问诊归属校验
|
||||
|
||||
- 用户表现:知道问诊编号的人可以加入房间,甚至把自己声明成“用户”或“医生”发送消息;消息还会真实写入数据库。
|
||||
- 原因:SignalR Hub 没有鉴权,加入房间和发送消息时也没有核对当前账号是否属于该患者或医生。
|
||||
- 位置:`backend/src/Health.WebApi/Hubs/ConsultationHub.cs`。
|
||||
- 优先级:最高。
|
||||
|
||||
### 3. 管理员存在固定手机号和固定验证码
|
||||
|
||||
- 用户表现:正式环境若沿用当前代码,知道固定号码的人可用 `000000` 登录管理员端。
|
||||
- 原因:管理员手机号和验证码直接写在认证服务中,而且不只在开发环境生效。
|
||||
- 位置:`backend/src/Health.Infrastructure/Auth/AuthService.cs`。
|
||||
- 优先级:最高。
|
||||
|
||||
### 4. 上传的报告、聊天图片和 PDF 可被未登录访问
|
||||
|
||||
- 用户表现:文件链接一旦泄露,不登录也能打开健康报告或聊天附件。
|
||||
- 原因:整个 `/uploads` 目录作为公开静态目录提供,没有按用户、医生关系或临时授权校验。
|
||||
- 位置:`backend/src/Health.WebApi/Program.cs` 的上传目录静态映射。
|
||||
- 优先级:最高。
|
||||
|
||||
### 5. 蓝牙血压计能读到数据,但自动上传会失败
|
||||
|
||||
- 用户表现:设备连接成功、血压已经读取,最后却提示上传失败;血压和心率不会真正保存到后端。
|
||||
- 原因:前端提交到 `/api/health-records/batch`,当前后端没有这个接口。
|
||||
- 位置:`health_app/lib/pages/device/device_management_page.dart` 与 `backend/src/Health.WebApi/Endpoints/health_endpoints.cs`。
|
||||
- 优先级:高。
|
||||
|
||||
### 6. 每次打开医生问诊页都会创建一条新问诊并消耗次数
|
||||
|
||||
- 用户表现:只是进入页面看一下、没有发送任何内容,也会新增问诊;反复进出会快速消耗每月次数。显示剩余 0 次时仍可能继续创建,甚至出现负数。
|
||||
- 原因:前端初始化先查次数,然后无条件创建;后端创建接口没有真正执行三次上限,也没有验证医生仍然有效。
|
||||
- 位置:`health_app/lib/providers/consultation_provider.dart`、`backend/src/Health.WebApi/Endpoints/consultation_endpoints.cs`。
|
||||
- 优先级:高。
|
||||
|
||||
### 7. 问诊消息发送失败时仍显示为已发送
|
||||
|
||||
- 用户表现:网络断开或服务器失败后,消息仍留在聊天里,没有失败标记和重试入口,用户会误以为医生已经收到。
|
||||
- 原因:发送异常被静默忽略,本地消息没有回滚或转成失败状态。
|
||||
- 位置:`health_app/lib/providers/consultation_provider.dart` 的 `sendMessage`。
|
||||
- 优先级:高,且不符合“不能假成功”的项目要求。
|
||||
|
||||
### 8. Android 正式包没有网络权限
|
||||
|
||||
- 用户表现:Debug 真机可联网,但以后构建 release 包后,所有登录、数据、AI 和报告请求都无法联网。
|
||||
- 原因:`INTERNET` 只在 debug/profile Manifest 中,main Manifest 没有;release 不会合并 debug 配置。
|
||||
- 位置:`health_app/android/app/src/main/AndroidManifest.xml`。
|
||||
- 优先级:正式包前必须修。
|
||||
|
||||
### 9. 账号注销只删数据库记录,不会清理服务器上传文件
|
||||
|
||||
- 用户表现:App 显示账号已删除,但报告原图、聊天图片、PDF 等仍可能留在服务器目录;公开链接仍可能继续访问。
|
||||
- 原因:账号注销批量删除数据库数据时没有收集并删除物理文件。单独删除报告有删文件,注销账号没有走同一流程。
|
||||
- 位置:`backend/src/Health.Infrastructure/Users/EfUserRepository.cs`。
|
||||
- 优先级:高,涉及合规承诺和真实删除。
|
||||
|
||||
### 10. iOS 相机和相册权限说明缺失
|
||||
|
||||
- 用户表现:以后在 iPhone 上拍饮食、拍报告或选相册时,系统可能直接终止 App,而不是正常弹出权限框。
|
||||
- 原因:Info.plist 有蓝牙说明,但没有 `NSCameraUsageDescription` 和 `NSPhotoLibraryUsageDescription`。
|
||||
- 位置:`health_app/ios/Runner/Info.plist`。
|
||||
- 优先级:iOS 调试前必须修。
|
||||
|
||||
## 三、重要功能和稳定性问题
|
||||
|
||||
### 11. 多个请求同时遇到登录过期时,可能刚刷新成功又被强制退出
|
||||
|
||||
多个 401 会同时拿同一个刷新 token。第一个请求刷新并保存新 token 后,第二个请求可能因旧 token 已失效而失败,随后把刚保存的新 token 一并清掉。用户会偶发跳回登录页。
|
||||
|
||||
位置:`health_app/lib/core/api_client.dart` 的 401 刷新逻辑。
|
||||
|
||||
### 12. 启动时只要服务器暂时连不上,就把用户当成未登录
|
||||
|
||||
刷新 token 的请求遇到断网或本地后端未启动时,认证状态直接变为未登录,但本地 token 又没有清除。用户会看到登录页,网络恢复后也不会自动重试,只能重启或重新操作。
|
||||
|
||||
位置:`health_app/lib/providers/auth_provider.dart` 的 `_checkAuth`。
|
||||
|
||||
### 13. 问诊轮询用随机 GUID 判断“之后的消息”,可能漏消息
|
||||
|
||||
SignalR 失败后会回退轮询。后端把随机消息 ID 与上一条随机 ID 做大小比较,这不等于消息时间顺序,可能漏掉医生新回复。正确游标应基于服务器时间或稳定递增字段。
|
||||
|
||||
位置:`backend/src/Health.WebApi/Endpoints/consultation_endpoints.cs`。
|
||||
|
||||
### 14. 问诊 AI 开场白只存在前端,没有保存
|
||||
|
||||
用户看到的“AI 分身问候”不是数据库消息,医生端看不到;重新进入又会新建问诊并生成另一条本地问候,历史不连续。
|
||||
|
||||
位置:`health_app/lib/providers/consultation_provider.dart`。
|
||||
|
||||
### 15. 短信验证码没有频率、次数和防刷限制
|
||||
|
||||
发送接口可反复调用,验证码校验也没有失败次数限制。正式短信接入后会产生短信轰炸、费用和验证码暴力尝试风险。
|
||||
|
||||
位置:认证端点和 `AuthService`。
|
||||
|
||||
### 16. 管理员新增、停用、修改、删除医生时,几套医生数据可能不同步
|
||||
|
||||
- 手机号已属于普通用户时,仍可创建医生实体,但不会把已有用户升级并绑定医生档案。
|
||||
- 修改医生手机号/姓名时,没有同步医生登录账号与医生档案。
|
||||
- 停用医生只改一处状态,医生档案的状态可能仍是启用。
|
||||
- 删除医生后,医生登录用户仍可能保留 Doctor 角色,但档案已失去关联,登录后只能看到“档案未关联”。
|
||||
- 医生手机号没有唯一约束,可能出现重复医生。
|
||||
|
||||
位置:`backend/src/Health.Infrastructure/Admin/AdminService.cs`。
|
||||
|
||||
### 17. 附件本地路径没有限制在 uploads 目录内
|
||||
|
||||
附件 URL 中的相对路径直接拼到服务器路径,没有做规范化后再确认最终路径仍位于 uploads 内,也没有核对文件是否属于当前用户。这会带来跨用户读取或路径越界风险。
|
||||
|
||||
位置:`backend/src/Health.Infrastructure/AI/AttachmentContextBuilder.cs`。
|
||||
|
||||
### 18. 通知点击先联网标记已读,失败时目的页面也打不开
|
||||
|
||||
用户点一条未读通知时,先请求后端标记已读;如果这一步失败,后续报告/用药/健康页面不会打开,也没有明确提示。
|
||||
|
||||
位置:`health_app/lib/pages/notifications/notification_center_page.dart`。
|
||||
|
||||
### 19. 用户端与医生端部分“今天/本月”按 UTC 计算
|
||||
|
||||
中国时区的凌晨时段可能被算到上一天或上个月,影响问诊次数、今日随访和提醒归类。正式环境应统一明确业务时区。
|
||||
|
||||
位置:问诊和医生工作台中使用 `DateTime.UtcNow.Date` 或 UTC 月份的逻辑。
|
||||
|
||||
## 四、UI 与交互问题
|
||||
|
||||
### 20. 用药和运动列表默认露出整片红色删除背景
|
||||
|
||||
真机截图中,用药行和运动行在没有滑动时已经整行变红;运动行还出现“打卡”和“删除”重叠。用户会误以为数据异常或正处于危险删除状态。
|
||||
|
||||
原因是通用滑动删除组件始终铺红色底层,而这些列表行本身透明。测试只验证滑动动作,没有验证未滑动时的最终视觉。
|
||||
|
||||
证据:`05-medications.png`、`09-exercise.png`。
|
||||
位置:`health_app/lib/widgets/common_widgets.dart`。
|
||||
|
||||
### 21. 首页多个纯图标按钮缺少无障碍名称
|
||||
|
||||
真机可访问性结构中,菜单、附件、输入框和发送按钮等多个可点击区域没有名称。普通用户能凭图标猜,读屏用户无法知道用途。
|
||||
|
||||
证据:`01-current.xml`。
|
||||
|
||||
### 22. 删除动作风格不统一
|
||||
|
||||
报告、用药、运动使用滑动删除,通知使用整行侧滑,蓝牙设备直接显示红色垃圾桶,设置页则用大按钮。交互成本和误触风险不同。建议统一为“列表行滑动后显示删除 + 二次确认用于高价值数据”。
|
||||
|
||||
### 23. 设置页的红色占比过重
|
||||
|
||||
“删除账号”和“退出登录”两个大面积危险操作占据页面最强视觉层级,反而压过消息、隐私和服务协议。删除账号保持红色是合理的,但退出登录不必使用整块高饱和红色。
|
||||
|
||||
证据:`12-settings.png`。
|
||||
|
||||
### 24. 侧边栏健康仪表盘过于抢眼
|
||||
|
||||
大面积蓝紫粉渐变和四个小框成为最强区域,与项目“克制、专业、模块色只做识别”的偏好有偏差;指标小字和透明边框的对比度也偏弱。
|
||||
|
||||
证据:`02-drawer.png`。
|
||||
|
||||
### 25. 空状态表达不统一
|
||||
|
||||
复查随访使用居中图标和说明;饮食使用一条白色容器;其他页面可能只留空白。建议统一空状态的标题、原因和下一步操作,但不需要每页再套一张大卡片。
|
||||
|
||||
证据:`06-diet-records.png`、`08-followups.png`。
|
||||
|
||||
### 26. 部分图标按钮只有约 40dp
|
||||
|
||||
例如蓝牙页顶部新增按钮使用固定 40×40,低于常见的 48dp 触控建议;对手部不便或视力较弱的健康类用户不够友好。
|
||||
|
||||
### 27. 大字体、横屏、小屏和读屏尚无验证证据
|
||||
|
||||
许多页面使用固定高度、固定行布局和多个并排信息块。当前只在一台 1440×3200 Android 真机、默认字体比例下检查,不能据此确认大字体和 iOS 横屏不会溢出。
|
||||
|
||||
## 五、合规与发布准备问题
|
||||
|
||||
### 28. 合规文档仍有主体和联系方式占位符
|
||||
|
||||
隐私政策、服务协议、个人信息清单和 SDK 清单里仍有 `xxx`、待定短信服务商等内容,不能用于正式审核。
|
||||
|
||||
### 29. App 内文档与 H5 文档存在多套日期和内容
|
||||
|
||||
App 内隐私/协议日期为 6 月 29 日,个人信息与 SDK 清单为 7 月 9 日;H5 清单日期为 7 月 7 日。以后修改一处很容易漏另一处。建议确定单一内容源或至少增加一致性测试。
|
||||
|
||||
### 30. “关于我们”写了并不存在的意见反馈入口
|
||||
|
||||
文档提示“设置 → 意见反馈”,实际设置页没有该入口;版本还写成 `Build 20260101`,与当前 `1.0.0+1` 不一致。
|
||||
|
||||
### 31. 用户同意协议没有服务端记录
|
||||
|
||||
当前“同意”只是登录页内存中的一个布尔值,未保存同意时间、协议版本或政策更新后的重新同意记录。服务端接口也不要求同意状态,无法证明用户同意了哪一版条款。
|
||||
|
||||
### 32. Android 权限声明偏多且缺少版本限制
|
||||
|
||||
当前声明了蓝牙广播权限,但 App 主要是扫描/连接;旧版存储和蓝牙权限也没有按 Android 版本加 `maxSdkVersion`。正式个人信息清单应与实际最小权限保持一致。
|
||||
|
||||
### 33. 本地 token 使用普通 SQLite 明文保存
|
||||
|
||||
符合项目“不用 shared_preferences”的约定,但 access token 和 refresh token 没有系统级加密保护;同时 Android 也未显式关闭备份。正式版本需要决定是否改用系统安全存储或加密数据库,并限制备份。
|
||||
|
||||
### 34. iOS 名称和方向仍是模板状态
|
||||
|
||||
Info.plist 的显示名称还是 `Health App`,并允许 iPhone 横屏;当前页面主要按竖屏设计,尚未验证横屏。Bundle ID、签名和证书则仍按项目计划待配置。
|
||||
|
||||
### 35. CORS 当前允许任意来源并携带凭据
|
||||
|
||||
本地调试方便,但正式环境应只允许确定的 H5/管理端域名,不能继续接受任意 Origin。
|
||||
|
||||
## 六、已确认正常或已有保护的部分
|
||||
|
||||
- 当前 Flutter `analyze` 无错误。
|
||||
- Flutter 47 项测试全部通过。
|
||||
- 后端 44 项测试全部通过。
|
||||
- 报告、用药、饮食、运动、健康数据等主要删除接口都按当前用户筛选,不是只删前端显示。
|
||||
- 单独删除报告时会同时删除报告原文件。
|
||||
- AI 历史对话恢复后仍保留原 conversationId,可以继续发送新消息;历史确认卡只读是合理保护。
|
||||
- 管理员和医生普通 HTTP 端点已有角色过滤,问题主要集中在固定管理员验证码、医生数据同步和未鉴权 SignalR Hub。
|
||||
- 设置、通知、报告列表已经较接近“一行一行、文字区分隔线”的目标风格。
|
||||
- 隐私政策、服务协议、个人信息清单、SDK 清单和关于我们均已有 App 内入口与 H5 文件。
|
||||
|
||||
## 七、真机流程健康度
|
||||
|
||||
1. 首页与 AI 对话:可进入;视觉基本完整,但纯图标无障碍名称不足,AI SSE 鉴权有严重后端风险。
|
||||
2. 侧边栏:可打开;功能入口齐全,仪表盘色彩和层级偏重。
|
||||
3. 健康档案:可加载和编辑;固定保存区需要继续验证大字体遮挡。
|
||||
4. 报告管理:列表正常;文件公开访问是严重隐私风险。
|
||||
5. 用药管理:数据能加载;列表红底显示错误明显。
|
||||
6. 饮食记录:日期、空状态和趋势能显示;空状态样式与其他页不统一。
|
||||
7. 健康日历:日期和计划能显示;业务时区需要后端统一。
|
||||
8. 复查随访:空状态清楚;本次账号没有数据,未实测详情。
|
||||
9. 运动计划:数据能加载;红底和操作文字重叠明显。
|
||||
10. 蓝牙设备:绑定设备能显示;自动读取后的批量上传链路断开。
|
||||
11. 通知中心:历史和未读数能显示;未读通知在网络失败时可能打不开目的页。
|
||||
12. 设置与合规入口:入口齐全;危险操作权重过高,文档仍有占位和不一致。
|
||||
13. 个人信息:真机运行版本可进入;检查期间源代码刚加入新的基本资料编辑入口,当前运行包尚未热更新到这一版。
|
||||
14. 医生端:已完成代码与接口核对;没有医生测试账号,本次未做完整真机流程。
|
||||
15. 管理员端:已完成代码与接口核对;没有实际执行新增/停用/删除,避免改变真实数据。
|
||||
16. iOS:仅做配置与代码检查;没有证书、Mac 构建和 iPhone 实测,不能确认界面与权限流程。
|
||||
|
||||
## 八、证据限制
|
||||
|
||||
- 真机截图来自本次检查时设备上正在运行的调试包。检查过程中项目源代码仍在被更新,后加入的个人资料编辑和设备错误文案没有重新构建到该运行包,因此相关结论以当前代码为准、旧界面截图只用于对应未变化页面。
|
||||
- 没有执行真实删除、账号注销、医生管理、短信发送或蓝牙测量,避免改变现有数据;这些部分通过前后端代码和接口对应关系确认。
|
||||
- 没有正式域名、HTTPS、短信服务商、对象存储、iOS 签名和商店账号,因此只检查了当前准备缺口。
|
||||
1
audit/ui-pages/window.xml
Normal file
1
audit/ui-pages/window.xml
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user