- 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>
22 KiB
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.dart与lib/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 sheet,FAB 触发)
通用排版 token(延续一迭代规范与现有实现,不新造):
- 页面内边距:
EdgeInsets.fromLTRB(16, 16, 16, 30)(与现有五个 Tab 页一致) - 间距刻度:4 / 8 / 12 / 16 / 24 / 32;卡片间距 10–12,分区间距 22–24
- 圆角:卡片
AppRadius.xl(24,Card 主题默认)、输入框lg(18)、sheet 内 CTAmd(16)、徽章/chippill - 字级:分区标题
titleLarge18/w800;卡内标题titleMedium15/w700;正文bodyMedium14;次级 12(色用inkSoft,不用muted,见 §5 DEBT-2) - Bottom sheet 统一沿用
EditPetSheet既有骨架:_SheetHandle(44×5border色胶囊)+ 标题行(titleLarge+ 右侧 close)+ 内容 + 全宽提交按钮;padding EdgeInsets.fromLTRB(20, 10, 20, viewInsets.bottom + 20)
2. 记录类型体系(图标 + 色彩映射)
M2 记录类型五种(「其他」为扩展兜底)。每种类型 = 图标 + 一族三色:dot 底(基础色 8%,withAlpha(20),与 TagPill/InlineErrorBanner 既有做法一致)、图标色(非文字对比 ≥3:1,WCAG 1.4.11)、文字色(≥4.5:1,WCAG 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圆形裁切(复用其 loadingsurfaceTint块 / 失败Icons.petsmuted 兜底)+ 3pxsurface白描边 + 投影rgba(0,0,0,0.08) 0 4 10(正典.patbond-avatar规格)+ 可选右下编辑徽标。 - 尺寸档:
xl96(档案页头部,收敛现有 104 → 96,与 EditPetSheet 一致)、lg64(宠物列表卡)、md44(头部宠物切换器,恰为最小触控目标)、sm32(记录详情等行内)。徽标:xl/lg 32 圆(primaryStrong底 + 白edit图标 15,白/primaryStrong4.49:1;现实现用primary底,白图标 2.75:1 不达非文字 3:1,本规范修订为primaryStrong),md/sm 不带徽标。 - 可选渐变环:
ring: true时外圈 2pxbrandGradient(正典 story 环),仅用于「当前选中宠物」指示,纯装饰。 - 状态:默认;可点击时
InkWell圆形 ripple;禁用 60% 不透明度(对齐AppTextField禁用惯例);加载/失败由RemoteImage兜底。
3.2 RecordTypeDot 记录类型圆标(lib/core/widgets/record_type_dot.dart)
§2 映射表的唯一渲染出口——类型↔色彩映射内置于组件,调用方只传类型枚举,杜绝散落硬编码。
- 尺寸档:
md40(时间线,正典 30 于 320 画框的真机放大)、lg56(记录详情页头)、sm24(表单类型选择器内)。图标尺寸 = dot 的 50%。 - 规格:正圆,底色/图标色按 §2 表;无自身点击态(点击归属父容器);无禁用态。
- 同文件导出类型→文字色/标签文案的映射常量,供 TagPill、详情页复用。
3.3 HealthTimelineTile 时间线条目(lib/core/widgets/health_timeline_tile.dart)
将 pets_page.dart 私有 _TimelineTile 升级为共享组件(保留其卡片式形态——比正典裸排版更适合可点击的密集列表,判定为可接受偏离)。
- 布局:
Card(主题默认:白底、border1px、圆角 24、零 elevation)内Row,padding 14:RecordTypeDot(md)→ 12 → 内容列(标题titleMedium15/w700ink;第二行 12inkSoft:日期 + " · " + 摘要,如「2026-06-12 · 瑞派宠物医院」)→ 尾部插槽:数值型记录显示大数值(15/w800,类型文字色,如体重「5.2kg」primaryDark),事件型记录显示TagPill(DEBT-1 修复后形态,§5)。 - 左轨连线:相邻条目 dot 间 2px
border色竖线(画在卡外左轨)。实现代价高时可省略——正典 timeline 本无连线,省略不算偏离。 - 状态:默认;按下
InkWellripple(圆角随卡 24);整卡可点进 P3;无禁用态。整卡高约 68,触控达标。
3.4 EmptyStateIllustration 空态插画区(lib/core/widgets/empty_state_illustration.dart)
现有 EmptyState(42 图标 + 一行 bodySmall)不足以承载引导动作,新组件向上兼容。
- 布局(垂直居中,上下留白 48):112 圆形插画区(
surfaceTint底 + 56 图标primary——大面积装饰用法,primary 合法)→ 16 → 标题titleMediumink→ 8 → 说明 12inkSoft(≤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 inkSoft;chevron muted
└──────────────────────────────┘
↓ 10(卡间距)
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
+ 添加宠物 虚线卡:border 色 1.5px dashed,radius 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 条「最近记录」,完整时间线为新增提案 |
| 新增入口 | FAB:56 圆,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 字/w700(7.98:1)。
偏离正典声明:正典 chip.active 为 coral 实底白字(2.75:1,不达 AA),不采纳;选中态改为 surfaceTint + 深字,与 NavigationBar 既有选中指示(surfaceTint indicator)同语言。
状态:加载 = 头部骨架(surfaceTint 块)+ 居中 CircularProgressIndicator;时间线空态 = EmptyStateIllustration(event_note_outlined、「还没有健康记录」、CTA「记录第一条」;筛选后空态文案「暂无某某记录」且无 CTA);加载失败 = InlineErrorBanner + 重试按钮,瞬态错误走 SnackBar(一迭代三层错误模型沿用)。
4.3 P3 记录详情 【设计稿未覆盖,本规范为新增提案,待拍板】
push 页,透明 AppBar 仅返回箭头(ink 色,沿用注册页惯例),右上 edit_outlined IconButton(44 触控)→ 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「已保存」,时间线原位刷新。 - 字段间距 12(EditPetSheet 现值),分组间距 20。
5. 色彩无障碍自查(WCAG AA)
计算方法:WCAG 2.x 相对亮度公式,8% 淡底按 withAlpha(20)(=7.84%)与承载底合成后计算。正文阈值 4.5:1,大字(≥18.7px 加粗 / 24px)3:1,非文字元素 3:1。
5.1 本规范用到的全部文字组合
| 组合 | 对比度 | 判定 |
|---|---|---|
ink / surface、canvas、surfaceTint |
13.50 / 12.71 / 11.42 | 达标 |
inkSoft #6B5A4A / surface、canvas、surfaceTint |
6.59 / 6.21 / 5.58 | 达标(新 token 提案) |
primaryDark / surface、canvas、surfaceTint、primary 8% 底 |
9.43 / 8.88 / 7.98 / 8.74 | 达标 |
primaryStrong / surface(链接、添加宠物字);白字 / primaryStrong(FAB、按钮) |
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.16–7.39 | 均 ≥3,达标 |
5.2 不采纳的正典/现状组合(本规范修订点)
| 组合 | 对比度 | 处置 |
|---|---|---|
正典 chip.active:白字 / primary |
2.75 | 选中 chip 改 surfaceTint 底 + primaryDark 字(§4.2) |
现档案页头像编辑徽标:白图标 / primary 底 |
2.75(非文字需 ≥3) | PetAvatar 徽标底改 primaryStrong(§3.1) |
muted / surface、canvas |
3.36 / 3.16 | 见 DEBT-2 |
TagPill 现状:primary、success、accent 文字于自身 8% 底 |
2.55 / 2.50 / 1.67 | 见 DEBT-1 |
5.3 DEBT-1(TagPill)偿还方案 —— 建议:借 M2 一并偿还
理由:健康档案时间线每条记录带一枚类型标签,TagPill 用量将从当前 5 处增至列表级高频;带着 2.5:1 的标签上新页面等于把债务翻倍,且 §2 的类型文字色映射本身就是 TagPill 需要的深变体映射,修复与新功能是同一套色。
方案(照一迭代 12 报告 §2.3 既定方向细化):
TagPill增加可选inkColor参数:底色维持color.withAlpha(20)不变,文字改用inkColor。- 内置默认映射(
inkColor缺省时按color查表):primary → primaryDark(8.74:1)、success → successInk(7.39:1)、accent → accentDark(7.07:1)、error → errorDark(5.78:1)、未命中 →ink(≥12:1 兜底)。 - 字号 11/w700 维持不变——修色后 11px 小字达标(AA 对小字与正文同阈值,上表均 ≥5.7)。
- 回归范围:现有 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 | 新 token:errorDark #B02C25、inkSoft #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