docs(spec): 长期监测预设支持隐藏(2026-05-26)
UserProfile 加 hiddenPresetMetrics 字段;IndicatorQuickSheet 长按 tile 出 contextMenu 隐藏,顶部 chip 显示已隐藏数 + 恢复入口。 历史数据/Trends/Reminder 全不动。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
122
docs/superpowers/specs/2026-05-26-hide-monitor-preset-design.md
Normal file
122
docs/superpowers/specs/2026-05-26-hide-monitor-preset-design.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
# Hide Monitor Preset · 设计 v1
|
||||||
|
|
||||||
|
> 「记录指标」sheet 长期监测预设(`MonitorMetric`)支持隐藏
|
||||||
|
>
|
||||||
|
> 日期:2026-05-26 · 状态:approved by user(2026-05-26 对话)
|
||||||
|
> 关联:[CLAUDE.md](../../../CLAUDE.md) §7,[Monitor+Profile spec](./2026-05-26-monitor-and-profile-design.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 背景
|
||||||
|
|
||||||
|
`IndicatorQuickSheet`「长期监测(进趋势)」分组由 `MonitorMetric.allCases` 渲染,目前 6 个硬编码 case(血压/空腹血糖/餐后血糖/体温/心率/血氧)无法隐藏,与下方 `CustomMonitorMetric`(可长按编辑/删除)体验不一致。
|
||||||
|
|
||||||
|
用户场景:不测血氧、不测血压的人想清理 grid;但**不能误删历史数据**——已经测过的折线在 Trends 里还要看。
|
||||||
|
|
||||||
|
## 2. 目标
|
||||||
|
|
||||||
|
- 长按 `MonitorMetric` tile → contextMenu 出"隐藏"
|
||||||
|
- 已隐藏的 tile 从 grid 过滤掉,但已有 `Indicator` 记录、Trends 折线、`MetricReminder` 全不动
|
||||||
|
- 提供可逆恢复入口
|
||||||
|
|
||||||
|
## 3. 非目标(YAGNI)
|
||||||
|
|
||||||
|
- ❌ 化验项快捷预设(labPresets)同款功能 — 本次不动
|
||||||
|
- ❌ 「我的」里集中管理页 — grid 上就近恢复即可
|
||||||
|
- ❌ 批量隐藏 / 拖拽排序
|
||||||
|
- ❌ 二次确认弹窗 — 隐藏可逆,不需要
|
||||||
|
- ❌ 隐藏时联动关掉对应 `MetricReminder` — 用户没说,保守不动
|
||||||
|
|
||||||
|
## 4. 数据模型
|
||||||
|
|
||||||
|
`UserProfile` 增加一个字段:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
var hiddenPresetMetrics: [String] = [] // 存 MonitorMetric.rawValue
|
||||||
|
```
|
||||||
|
|
||||||
|
- 类型沿用 `[String]`,跟 `allergies` / `chronicConditions` 一致,SwiftData 自动 transformable
|
||||||
|
- init 默认 `[]`,无 migration 风险
|
||||||
|
- 写入用 `UserProfile.updatedAt = .now`
|
||||||
|
|
||||||
|
为什么不另开 `@Model HiddenPresetMetric`:8 个 case 的隐藏标记只是 UI 偏好,放 Profile 单例最自然,避免新 entity + 关联查询。
|
||||||
|
|
||||||
|
## 5. UI 行为
|
||||||
|
|
||||||
|
### 5.1 隐藏入口
|
||||||
|
|
||||||
|
`IndicatorQuickSheet.monitorTile(_:)` 加 `.contextMenu`:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
.contextMenu {
|
||||||
|
Button(role: .destructive) {
|
||||||
|
hideMonitor(m)
|
||||||
|
} label: {
|
||||||
|
Label("隐藏", systemImage: "eye.slash")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`hideMonitor` 把 `m.rawValue` 加入 `profile.hiddenPresetMetrics`,save,grid 因 `@Query` 重渲染。被隐藏的 tile 若当前选中,要 `clearMonitor()` 复位。
|
||||||
|
|
||||||
|
### 5.2 grid 过滤
|
||||||
|
|
||||||
|
```swift
|
||||||
|
ForEach(MonitorMetric.allCases.filter { !hiddenSet.contains($0.rawValue) }) { m in
|
||||||
|
monitorTile(m)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`hiddenSet` = `Set(profile?.hiddenPresetMetrics ?? [])`,computed property。
|
||||||
|
|
||||||
|
### 5.3 恢复入口
|
||||||
|
|
||||||
|
`monitorGridSection` 顶部 section label 一行:
|
||||||
|
|
||||||
|
```
|
||||||
|
长期监测(进趋势) 已隐藏 3 ›
|
||||||
|
```
|
||||||
|
|
||||||
|
- chip 仅当 `hiddenSet.nonEmpty` 显示
|
||||||
|
- 点 chip → `.sheet` 弹一个轻量列表(`.medium` detent)
|
||||||
|
- 列表项:每个被隐藏的 `MonitorMetric` 显示 icon + displayName + 右侧"显示"按钮
|
||||||
|
- 点"显示" → `profile.hiddenPresetMetrics.removeAll { $0 == m.rawValue }` + save
|
||||||
|
- 列表空了自动 dismiss
|
||||||
|
|
||||||
|
### 5.4 边界
|
||||||
|
|
||||||
|
- 全部 6 个都隐藏:section 还在(label + chip + addCustomTile),不消失
|
||||||
|
- 隐藏不影响:Trends 折线、`Indicator` 列表查询、`MetricReminder` 调度
|
||||||
|
- `UserProfileStore.loadOrCreate` 已保证 profile 存在,无 nil 分支
|
||||||
|
- `@Query private var profiles: [UserProfile]` 已在 sheet 里,直接取 `profiles.first`
|
||||||
|
|
||||||
|
## 6. 文件改动清单
|
||||||
|
|
||||||
|
1. `Models/UserProfile.swift` — 加 `hiddenPresetMetrics: [String]` 字段 + init 默认值
|
||||||
|
2. `Features/Indicator/IndicatorQuickSheet.swift`
|
||||||
|
- `monitorGridSection`: 过滤 + 顶部 chip
|
||||||
|
- `monitorTile`: 加 contextMenu
|
||||||
|
- 新增 `hideMonitor(_:)` / `unhideMonitor(_:)` / `hiddenSet`
|
||||||
|
- 新增 `HiddenMonitorRestoreSheet` 子 View(同文件内,私有)
|
||||||
|
|
||||||
|
不动:`MonitorMetric.swift`、`CustomMetricEditor.swift`、Trends、`ReminderService`、`MeView`。
|
||||||
|
|
||||||
|
## 7. 测试 / 验证手段
|
||||||
|
|
||||||
|
无单测目标(全 UI 行为)。手测点:
|
||||||
|
|
||||||
|
- [ ] 长按血压 tile → 出现"隐藏",点了 grid 里消失
|
||||||
|
- [ ] 顶部 chip "已隐藏 1" 出现,数字正确
|
||||||
|
- [ ] 点 chip → 弹列表,有 1 行血压,点"显示"恢复
|
||||||
|
- [ ] 全部 6 个隐藏 → grid 只剩 addCustomTile + 自定义指标,不崩
|
||||||
|
- [ ] 隐藏期间去 Trends,血压折线仍在
|
||||||
|
- [ ] 隐藏前若血压已选中,隐藏后选中态清空、字段清空
|
||||||
|
- [ ] 重启 App,隐藏状态持久
|
||||||
|
|
||||||
|
## 8. 红线核查(CLAUDE.md §10)
|
||||||
|
|
||||||
|
- ✅ 不引入云
|
||||||
|
- ✅ 不动 AIRuntime / Service 边界
|
||||||
|
- ✅ 不动 SwiftData 既有 `Indicator` schema
|
||||||
|
- ✅ Tab / RecordSheet 骨架不动
|
||||||
|
- ✅ 不是清单外功能,是对 §7 grid 的小改良
|
||||||
Reference in New Issue
Block a user