Files
kangkang/docs/superpowers/specs/2026-05-26-hide-monitor-preset-design.md
link2026 599d39af35 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>
2026-05-26 19:37:34 +08:00

4.3 KiB
Raw Permalink Blame History

Hide Monitor Preset · 设计 v1

「记录指标」sheet 长期监测预设(MonitorMetric)支持隐藏

日期:2026-05-26 · 状态:approved by user(2026-05-26 对话) 关联:CLAUDE.md §7,Monitor+Profile spec


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 增加一个字段:

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:

.contextMenu {
    Button(role: .destructive) {
        hideMonitor(m)
    } label: {
        Label("隐藏", systemImage: "eye.slash")
    }
}

hideMonitorm.rawValue 加入 profile.hiddenPresetMetrics,save,grid 因 @Query 重渲染。被隐藏的 tile 若当前选中,要 clearMonitor() 复位。

5.2 grid 过滤

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.swiftCustomMetricEditor.swift、Trends、ReminderServiceMeView

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 的小改良