Files
lixi 1891d9b7b4
CI / docs-build (push) Successful in 1m3s
docs: M2 开工前分析 10 份报告入档 + ADR-009~015 拍板决策
- iteration-2 报告 01-08(PM 拆解/后端/Flutter 评估/现实核查/UI 规范/埋点规划/证据基线/Git 规划),04、06 已由正式角色复核定稿
- mkdocs 挂「第二迭代」导航,build --strict 通过
- ADR-009 新建 patbond-pet 模块、ADR-010 照片剪出 M2、ADR-011 dev 主干/master 发布、ADR-012 北极星与 H1-H4、ADR-013 废弃 health_record_action、ADR-014 DEBT-1 随 M2、ADR-015 照护人邀请后置

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-07 13:54:35 +08:00

22 KiB
Raw Permalink Blame History

05 · 第二迭代 宠物健康档案 UI 设计规范

作者:UI Designer 日期:2026-09-07 迭代:Iteration 2「M2 宠物健康档案」 素材来源:AI宠物_iOS_UI设计稿.html(品牌正典,ADR-005)、patbond-flutter/lib/core/theme/app_theme.dart(已落地 token)、lib/widgets/common.dartlib/core/widgets/(既有组件)、lib/features/pets/pets_page.dart(档案页现状)、第一迭代 04/12 号 UI 报告(规范基线) 性质:开工前设计规范;只定规格,不改代码


0. 正典设计语言提炼(宠物档案相关)

正典 HTML「宠物成长档案」画框已给出的语言,本规范全部延续:

正典元素 描述 对应 Flutter 现状
patbond-header 居中头像(76,3px 白描边 + 轻投影)+ 名字(Baloo 2 17+ 元信息(11 muted pets_page.dart 头部已实现(头像 104
stat-row / stat-card 三等分白卡:大数值(coral-dark 加粗)+ 小标签(muted _StatCard 已实现
alert-card sage 底 AI 健康提醒卡(dot + 文字) 健康提醒卡已实现(successSurface 族标准用法,12 报告 §3 认可)
timeline-item 30px peach 圆底 emoji 图标 + 标题(12/w600+ 日期(10 muted),无卡片包裹 _TimelineTile 实现为卡片式(CircleAvatar + SectionCard),比正典重
section-title 分区标题 titleLarge 18/w800
chip / chip.active 胶囊筛选:白底 border 描边 muted 字;选中态 coral 实底白字 未实现共享组件
stories 头像环 brandGradient 2px 渐变环 + 白描边头像 首页已有

正典未覆盖(详见 §6 待拍板清单):宠物列表页(多宠物)、完整时间线与类型筛选(正典只有「最近记录」3 条)、记录详情页、新增/编辑记录表单、体重/驱虫/就医的记录类型视觉。这些页面为本规范新增提案。


1. 页面族总览

档案 Tab
  └─ P1 宠物列表(多宠物入口;单宠物时直进 P2,见 §6 D1)
       └─ P2 健康档案页(宠物头 + 数据卡 + 提醒 + 时间线 + 筛选 + 新增入口)
            ├─ P3 记录详情(push 页)
            │     └─ P4 编辑记录(modal bottom sheet
            └─ P4 新增记录(modal bottom sheetFAB 触发)

通用排版 token(延续一迭代规范与现有实现,不新造):

  • 页面内边距:EdgeInsets.fromLTRB(16, 16, 16, 30)(与现有五个 Tab 页一致)
  • 间距刻度:4 / 8 / 12 / 16 / 24 / 32;卡片间距 1012,分区间距 22–24
  • 圆角:卡片 AppRadius.xl(24Card 主题默认)、输入框 lg(18)、sheet 内 CTA md(16)、徽章/chip pill
  • 字级:分区标题 titleLarge 18/w800;卡内标题 titleMedium 15/w700;正文 bodyMedium 14;次级 12色用 inkSoft,不用 muted,见 §5 DEBT-2
  • Bottom sheet 统一沿用 EditPetSheet 既有骨架:_SheetHandle44×5 border 色胶囊)+ 标题行(titleLarge + 右侧 close)+ 内容 + 全宽提交按钮;padding EdgeInsets.fromLTRB(20, 10, 20, viewInsets.bottom + 20)

2. 记录类型体系(图标 + 色彩映射)

M2 记录类型五种(「其他」为扩展兜底)。每种类型 = 图标 + 一族三色:dot 底(基础色 8%withAlpha(20),与 TagPill/InlineErrorBanner 既有做法一致)、图标色(非文字对比 ≥3:1WCAG 1.4.11)、文字色(≥4.5:1WCAG AA)。

类型 图标(Material dot 底(8% tint/白底合成值) 图标色 图标对比 文字/标签色 文字对比(于 dot 底)
体重 monitor_weight_outlined primary 8% → #FFF4F1 primaryStrong 4.16:1 primaryDark 8.74:1
疫苗 vaccines_outlined success 8% → #F5F8F6 successInk 7.39:1 successInk 7.39:1
驱虫 pest_control accent 8% → #FFF9F1 accentDark 7.07:1 accentDark 7.07:1
就医 medical_services_outlined error 8% → #FBEFEE error 4.44:1 errorDark(新 token 提案) 5.78:1
其他 sticky_note_2_outlined muted 8% → #F7F6F4 inkSoft(新 token 提案) 6.10:1 inkSoft 6.10:1

映射依据:体重是核心品牌数据 → primary 族(正典 stat-card 数值即 coral-dark);疫苗延续现有实现的 success 族(疫苗进度环、健康提醒已用 sage);驱虫用 accent 族(提醒/预防语义,正典徽章族);就医用 error 族(医疗警示语义)。

新增语义 token 提案(2 个,待拍板):

Token 派生逻辑 用途
errorDark #B02C25 error #D0342C 加深(与 primary→primaryStrong 同构) error 淡底上的文字(error 本身在自家 8% 底上仅 4.44:1,贴线不过);就医类型文字
inkSoft #6B5A4A 直接取自正典feed-caption 文字色,非新造) 承载信息的次级文字(日期、元数据);白底 6.59:1、canvas 底 6.21:1、surfaceTint 底 5.58:1 全达标

注:疫苗/驱虫/其他三型图标直接用深变体(success #7FA88A 在白底仅 2.67:1,无中间档可用);体重/就医图标可用中强度变体保留彩度,均 ≥3:1。所有类型图标必须与文字标签成对出现,不得单独用色彩区分类型(色盲可辨性)。


3. 新组件规格(4 个)

3.1 PetAvatar 宠物头像(lib/core/widgets/pet_avatar.dart

统一现有两处各写一遍的头像代码(pets_page.dart 档案头 104、EditPetSheet 96)。

  • 构成RemoteImage 圆形裁切(复用其 loading surfaceTint 块 / 失败 Icons.pets muted 兜底)+ 3px surface 白描边 + 投影 rgba(0,0,0,0.08) 0 4 10(正典 .patbond-avatar 规格)+ 可选右下编辑徽标。
  • 尺寸档xl 96(档案页头部,收敛现有 104 → 96,与 EditPetSheet 一致)、lg 64(宠物列表卡)、md 44(头部宠物切换器,恰为最小触控目标)、sm 32(记录详情等行内)。徽标:xl/lg 32 圆(primaryStrong 底 + 白 edit 图标 15,白/primaryStrong 4.49:1;现实现用 primary 底,白图标 2.75:1 不达非文字 3:1,本规范修订为 primaryStrong),md/sm 不带徽标。
  • 可选渐变环ring: true 时外圈 2px brandGradient(正典 story 环),仅用于「当前选中宠物」指示,纯装饰。
  • 状态:默认;可点击时 InkWell 圆形 ripple;禁用 60% 不透明度(对齐 AppTextField 禁用惯例);加载/失败由 RemoteImage 兜底。

3.2 RecordTypeDot 记录类型圆标(lib/core/widgets/record_type_dot.dart

§2 映射表的唯一渲染出口——类型↔色彩映射内置于组件,调用方只传类型枚举,杜绝散落硬编码。

  • 尺寸档md 40(时间线,正典 30 于 320 画框的真机放大)、lg 56(记录详情页头)、sm 24(表单类型选择器内)。图标尺寸 = dot 的 50%。
  • 规格:正圆,底色/图标色按 §2 表;无自身点击态(点击归属父容器);无禁用态。
  • 同文件导出类型→文字色/标签文案的映射常量,供 TagPill、详情页复用。

3.3 HealthTimelineTile 时间线条目(lib/core/widgets/health_timeline_tile.dart

pets_page.dart 私有 _TimelineTile 升级为共享组件(保留其卡片式形态——比正典裸排版更适合可点击的密集列表,判定为可接受偏离)。

  • 布局Card(主题默认:白底、border 1px、圆角 24、零 elevation)内 Rowpadding 14RecordTypeDot(md) → 12 → 内容列(标题 titleMedium 15/w700 ink;第二行 12 inkSoft:日期 + " · " + 摘要,如「2026-06-12 · 瑞派宠物医院」)→ 尾部插槽:数值型记录显示大数值(15/w800,类型文字色,如体重「5.2kg」primaryDark),事件型记录显示 TagPillDEBT-1 修复后形态,§5)。
  • 左轨连线:相邻条目 dot 间 2px border 色竖线(画在卡外左轨)。实现代价高时可省略——正典 timeline 本无连线,省略不算偏离。
  • 状态:默认;按下 InkWell ripple(圆角随卡 24);整卡可点进 P3;无禁用态。整卡高约 68,触控达标。

3.4 EmptyStateIllustration 空态插画区(lib/core/widgets/empty_state_illustration.dart

现有 EmptyState42 图标 + 一行 bodySmall)不足以承载引导动作,新组件向上兼容。

  • 布局(垂直居中,上下留白 48):112 圆形插画区(surfaceTint 底 + 56 图标 primary——大面积装饰用法,primary 合法)→ 16 → 标题 titleMedium ink → 8 → 说明 12 inkSoft(≤2 行居中)→ 24 → 可选 CTA(FilledButton,主题默认 52 高,非全宽自适应内容 + 水平 padding 24)。
  • 插画v1 用 Material 图标(无宠物态 Icons.pets;无记录态 Icons.event_note_outlined);正式插画素材待品牌侧供给后原位替换,尺寸档不变。
  • 状态:静态组件,仅 CTA 有按下/禁用(随按钮主题)。

4. 页面规范

4.1 P1 宠物列表 【设计稿未覆盖,本规范为新增提案,待拍板】

档案 Tab 落地页(多宠物时)。页面 padding 通用值。

我的宠物                     titleLarge,与「添加」TextButton.icon 同行
  ↓ 12
┌──────────────────────────────┐
│ [PetAvatar lg64]  豆豆        │  宠物卡:Card 主题默认,padding 14
│      柴犬 · 2岁 · 5.2kg      │  名字 titleMedium;元信息 12 inkSoftchevron muted
└──────────────────────────────┘
  ↓ 10(卡间距)
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
   + 添加宠物                     虚线卡:border 色 1.5px dashedradius 24
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘  高 64,文字 14/w600 primaryStrong(白底 4.49:1
  • 宠物卡状态:默认 / 按下 ripple → push P2;当前选中宠物可加 PetAvatar ring
  • 空态0 宠物):EmptyStateIllustration——Icons.pets、「还没有宠物档案」、「添加毛孩子,开始记录 TA 的健康点滴」、CTA「添加宠物」→ 复用 EditPetSheet
  • 既有组件:Card、TextButton;新组件:PetAvatar、EmptyStateIllustration。

4.2 P2 健康档案页(正典「宠物成长档案」画框的扩展)

结构自上而下(既有实现骨架保留,标注改动点):

区块 规格 出处
宠物头部 PetAvatar(xl 96, 编辑徽标) + 8 + 名字 headlineSmall + 4 + 元信息 12 inkSoft(现为 muted,随 DEBT-2 修订);多宠物时名字旁加切换箭头,点开 md 44 头像横排选择 sheet 正典 patbond-header;切换器为新增提案
数据卡行 三张 _StatCard(升共享):体重 / 疫苗进度 / 本月记录数。图标色按 §2 类型色(体重卡图标 primaryStrong,修订现值 primary);数值 15/w800 ink;标签 12 inkSoft。点击体重卡 → 时间线过滤体重;点疫苗卡 → 疫苗管理 sheet(既有) 正典 stat-row出入:正典第三卡为「本月花费 ¥328」,花费域不在 M2 范围,改为「本月记录」,待拍板
AI 健康提醒 现有 successSurface 提醒卡原样保留 正典 alert-card
分区标题 「健康时间线」titleLarge 正典 section-title(原文案「最近记录」)
类型筛选 chips 见下 正典 chip 形态 + 无障碍修订
时间线 HealthTimelineTile 列表,按月分组,组头 12/w700 inkSoft(「2026 年 9 月」)上 16 下 8 正典仅 3 条「最近记录」,完整时间线为新增提案
新增入口 FAB56 圆,primaryStrong 底 + 白 add 图标(4.49:1),右下距边 16、距 TabBar 上沿 16 → 打开 P4 sheet 【设计稿未覆盖,新增提案,待拍板】

筛选 chip 规格(全部 / 体重 / 疫苗 / 驱虫 / 就医):高 36(上下各留 4 达 44 触控),水平 padding 14,圆角 pill,文字 13/w600,间距 8,横向滚动。未选中:surface 底 + border 1px + inkSoft 字(6.59:1)。选中:surfaceTint 底 + primaryDark 字/w7007.98:1)。 偏离正典声明:正典 chip.active 为 coral 实底白字(2.75:1,不达 AA),不采纳;选中态改为 surfaceTint + 深字,与 NavigationBar 既有选中指示(surfaceTint indicator)同语言。

状态:加载 = 头部骨架(surfaceTint 块)+ 居中 CircularProgressIndicator;时间线空态 = EmptyStateIllustrationevent_note_outlined、「还没有健康记录」、CTA「记录第一条」;筛选后空态文案「暂无某某记录」且无 CTA);加载失败 = InlineErrorBanner + 重试按钮,瞬态错误走 SnackBar(一迭代三层错误模型沿用)。

4.3 P3 记录详情 【设计稿未覆盖,本规范为新增提案,待拍板】

push 页,透明 AppBar 仅返回箭头(ink 色,沿用注册页惯例),右上 edit_outlined IconButton44 触控)→ P4 编辑态。

[RecordTypeDot lg56]  ← 左对齐,与标题同行或其上
狂犬疫苗接种               headlineSmall 22 ink
[疫苗]  2026-06-12        TagPill(修复后) + 日期 14 inkSoft,间距 8
  ↓ 24
┌ SectionCard(padding 18) ───────┐
│ 字段名  12 inkSoft              │   键值对列表,行距 14;
│ 字段值  bodyMedium 14 ink       │   体重类数值行:值 20/w800 primaryDark
│ ────── 分隔线 border 1px ────── │
│ …                              │
└────────────────────────────────┘
  ↓ 16
备注:SectionCard 内 bodyMedium ink、行高 1.5(无备注则整卡不渲染)
照片:3 列网格,间距 8,RemoteImage 1:1 圆角 sm12(无照片不渲染)
  ↓ 24
删除记录     TextButton 全宽居中,error 色字(白底 4.99:1

删除走 AlertDialog 确认(「删除后不可恢复」,确认钮 FilledButton error 底白字 4.99:1,取消 TextButton)。删除属破坏性动作,必须确认。

4.4 P4 新增/编辑记录表单 【设计稿未覆盖,本规范为新增提案,待拍板;骨架沿用既有 EditPetSheet 模式】

showModalBottomSheet(isScrollControlled: true, useSafeArea: true),§1 通用 sheet 骨架。标题「新增记录」/「编辑记录」。

  • 类型选择器(仅新增态;编辑态锁定,显示为静态 dot+标签):五个垂直单元(RecordTypeDot sm24 上、11/w600 标签下)横排等分;选中单元 surfaceTint 底圆角 sm12 + primaryDark 标签,未选中标签 inkSoft;单元 ≥44×52 触控。
  • 动态字段(全部走既有 inputDecorationTheme;日期用 EditPetSheet 的 ListTile + showDatePicker 模式;标 * 为必填):
类型 字段
体重 体重 kg*(数字键盘,>0 且 ≤200 校验)、日期*(默认今天)
疫苗 疫苗名称*、接种日期*、医院/机构、下次接种提醒日期
驱虫 体内/体外/体内外*SegmentedButton,主题派生色)、日期*、药品名称
就医 主题/症状*、就诊日期*、医院、诊断结果(多行)、花费 ¥(数字,选填)
其他 标题*、日期*
通用尾部 备注(多行 3 行高)、照片(64 方格「+」添加,border 虚线,最多 9 张,RemoteImage 预览 + 右上删除角标)
  • 校验与错误:失焦 + 提交双校验,字段错误走 errorText(一迭代惯例:onChanged 即清除);不可归属错误 → 提交按钮上方 InlineErrorBanner;网络瞬态 → SnackBar+重试。文案示例:「请输入体重」「体重需在 0–200kg 之间」「请选择日期」。
  • 提交PrimaryButton(isLoading 转圈锁尺寸)「保存记录」;成功 pop 并 SnackBar「已保存」,时间线原位刷新。
  • 字段间距 12EditPetSheet 现值),分组间距 20。

5. 色彩无障碍自查(WCAG AA

计算方法:WCAG 2.x 相对亮度公式,8% 淡底按 withAlpha(20)(=7.84%)与承载底合成后计算。正文阈值 4.5:1,大字(≥18.7px 加粗 / 24px3:1,非文字元素 3:1。

5.1 本规范用到的全部文字组合

组合 对比度 判定
ink / surfacecanvassurfaceTint 13.50 / 12.71 / 11.42 达标
inkSoft #6B5A4A / surfacecanvassurfaceTint 6.59 / 6.21 / 5.58 达标(新 token 提案)
primaryDark / surfacecanvassurfaceTint、primary 8% 底 9.43 / 8.88 / 7.98 / 8.74 达标
primaryStrong / surface(链接、添加宠物字);白字 / primaryStrongFAB、按钮) 4.49 / 4.49 达标(一迭代已裁决按 ≈4.5 采纳)
successInk / success 8% 底、successSurface 7.39 / 6.79 达标
accentDark / accent 8% 底 7.07 达标
errorDark #B02C25 / error 8% 底(就医标签) 5.78 达标(新 token 提案)
error / surface(删除按钮);白字 / error(确认删除钮) 4.99 / 4.99 达标
非文字:各类型图标于 dot 底(§2 表) 4.167.39 均 ≥3,达标

5.2 不采纳的正典/现状组合(本规范修订点)

组合 对比度 处置
正典 chip.active:白字 / primary 2.75 选中 chip 改 surfaceTint 底 + primaryDark 字(§4.2
现档案页头像编辑徽标:白图标 / primary 2.75(非文字需 ≥3 PetAvatar 徽标底改 primaryStrong(§3.1
muted / surfacecanvas 3.36 / 3.16 见 DEBT-2
TagPill 现状:primarysuccessaccent 文字于自身 8% 底 2.55 / 2.50 / 1.67 见 DEBT-1

5.3 DEBT-1TagPill)偿还方案 —— 建议:借 M2 一并偿还

理由:健康档案时间线每条记录带一枚类型标签,TagPill 用量将从当前 5 处增至列表级高频;带着 2.5:1 的标签上新页面等于把债务翻倍,且 §2 的类型文字色映射本身就是 TagPill 需要的深变体映射,修复与新功能是同一套色。

方案(照一迭代 12 报告 §2.3 既定方向细化):

  1. TagPill 增加可选 inkColor 参数:底色维持 color.withAlpha(20) 不变,文字改用 inkColor
  2. 内置默认映射(inkColor 缺省时按 color 查表):primary → primaryDark8.74:1)、success → successInk7.39:1)、accent → accentDark7.07:1)、error → errorDark5.78:1)、未命中 → ink(≥12:1 兜底)。
  3. 字号 11/w700 维持不变——修色后 11px 小字达标(AA 对小字与正文同阈值,上表均 ≥5.7)。
  4. 回归范围:现有 5 处调用(服务页「认证服务」、档案时间线状态标签等)零参数变更、仅视觉变深;flutter test 全量回归。工作量一行映射表 + 一个参数,建议与 RecordTypeDot 同一工单。

5.4 DEBT-2(新发现,提案):muted 作信息文字不达 AA

muted #9C8977 在白底 3.36:1、canvas 底 3.16:1,低于正文 4.5:1。这是随正典色板继承的既有债(一迭代自查只覆盖了 primaryStrong/ink/error 三组,未查 muted),全 app bodySmall 均受影响,不阻塞 M2、不在 M2 全局翻修。M2 范围内的处置:

  • 健康档案页面族中承载信息的次级文字(记录日期、宠物元信息、字段名、月份组头)一律用 inkSoft #6B5A4A(正典既有色,6.59:1);muted 仅限占位符、禁用态、纯装饰。
  • 全局层面(bodySmall 默认色是否切 inkSoft)另立议题,交 M2 之后拍板——影响面是全部五个 Tab,需要整体视觉复核。

6. 与正典出入 / 待拍板清单

# 事项 性质
D1 P1 宠物列表页整页(正典档案 Tab 直落单宠物页)。附决策点:单宠物时是否跳过列表直进 P2(本规范建议:跳过,P2 头部留切换器) 设计稿未覆盖,新增提案
D2 完整健康时间线 + 类型筛选 chips(正典仅「最近记录」3 条) 设计稿未覆盖,新增提案
D3 P3 记录详情页整页 设计稿未覆盖,新增提案
D4 P4 新增/编辑表单(骨架沿用既有 EditPetSheet 先例,仅字段为新) 设计稿未覆盖,新增提案
D5 FAB 新增入口(正典无浮动按钮语言;备选:时间线分区标题右侧「+记录」TextButton) 设计稿未覆盖,新增提案
D6 stat-row 第三卡「本月花费」→「本月记录」(花费域不在 M2) 与正典有出入
D7 选中 chip 弃用正典 coral 实底白字(2.75:1),改 surfaceTint + primaryDark 无障碍修订偏离
D8 新 tokenerrorDark #B02C25inkSoft #6B5A4A(后者取自正典既有色值) token 提案
D9 DEBT-1 随 M2 偿还(§5.3);DEBT-2 记账、M2 内局部规避(§5.4) 债务处置提案
D10 时间线条目维持卡片式(偏离正典裸排版,沿用现实现形态) 可接受偏离,随 D2 一并确认

7. 交付验收对照(供开发/QA

  • 4 个新组件(PetAvatar / RecordTypeDot / HealthTimelineTile / EmptyStateIllustration)落位 lib/core/widgets/,类型色彩映射只存在于 RecordTypeDot 一处。
  • 4 个页面均具备 loading / empty / error / retry 态;错误三层模型(字段 errorText / InlineErrorBanner / SnackBar)与一迭代一致。
  • 本规范全部文字组合按 §5.1 达 AA;类型仅靠「图标+文字」双通道区分,不单靠颜色。
  • TagPill 修复合入(若 D9 拍板通过),现有 5 处调用回归无布局变化。
  • 删除记录有确认对话框;所有触控目标 ≥44×44。
  • AuthScaffold 内禁用 Spacer、按钮 minimumSize Size(64,52) 等一迭代既定约束不回退(本页面族不涉及 AuthScaffold,sheet/页面沿用各自既有骨架)。

UI Designer · 2026-09-07