Files
lixi 209021e7d2 docs: 迁入第一迭代过程报告并建立进展看板
- 新增 development/iterations/iteration-1/:15 份角色报告 + 进展看板(已完成/未闭环/下一步),作为双人协作的进度事实来源
- 新增 ADR-006:测试与交付容器化策略(Testcontainers / 交付 Docker 包 / 本机库仅个人联调)
- Git 工作流规范补充:敏感信息只进忽略文件或 sample、测试数据不入库、测试代码限标准测试目录
- 门禁:mkdocs build --strict 通过(零警告)
2026-09-04 10:45:05 +08:00

6.9 KiB
Raw Permalink Blame History

08 · Flutter 主题迁移与登录组件实现报告

作者:Frontend Developer 日期:2026-09-03 依据:ADR-005patbond-doc/docs/architecture/decisions.md)、04-ui-login-design-spec.md

1. 完成内容

  1. lib/core/theme/app_theme.dart 重写为语义 token 组织(AppColors + 新增 AppRadius),落地珊瑚橙正典色板;补齐 filledButtonTheme(高 52、圆角 16、primaryStrong 填充、显式 disabled 色)、errorBorder / focusedErrorBorder / errorStylecolorScheme.error 覆盖。主题仍集中在单一文件。
  2. 五个 Tab 页面及公共组件逐处替换旧靛蓝/冷灰硬编码色值为语义 token,仅换色、未动布局。
  3. 新建 5 个可复用组件于 lib/core/widgets/BrandMarkAppTextFieldPrimaryButton(含 isLoading)、InlineErrorBannerAuthScaffold。本次未建登录页面(等后端契约冻结)。
  4. PrimaryButtonAppTextField 各写 3 个 widget 测试。

2. Token 映射表(旧 → 新)

2.1 AppColors 字段值变化(字段名不变,引用处无需改)

Token 旧值(脚手架靛蓝) 新值(珊瑚橙正典)
primary #4F46E5 #FF6F4C(仅装饰/图标,不承载实心填充上的文字)
canvas #F8FAFC #FFF7ED 奶油底
ink #0F172A #3E2A1F
muted #64748B #9C8977
border #E2E8F0 #F0DCC8
success #10B981 #7FA88A sage
warning #F59E0B #F59E0B(不变)

2.2 新增 token

Token 用途
primaryStrong #D6431A 实心按钮填充、可点击文字链接(白字 ≈4.5:1,WCAG AA
primaryDark #7A2E12 浅色底上的强调文字
accent / accentDark #FFB648 / #7A4B0A 渐变终点、徽章 / amber 底文字
surface #FFFFFF 卡片、输入框背景(原为字面量 Colors.white
surfaceTint #FFE8D6 peach 图标底、占位块、选中指示
successInk / successSurface #3F5744 / #E8F0E8 成功提示的文字 / 底色
error #D0342C 错误文字、错误描边(白底 ≈5.4:1,AA)
brandGradient 135° #FF6F4C → #FFB648 品牌渐变(装饰,不承载正文文字)
AppRadius.sm/md/lg/xl/pill 12 / 16 / 18 / 24 / 999 圆角刻度(§1.3

2.3 页面内硬编码旧色值 → token

旧硬编码 新写法 位置
#F1F5F9(图片占位底) AppColors.surfaceTint common.dart ×2
#EEF2FFindigo-50 图标底) AppColors.surfaceTint home ×2、profile
#E0E7FF(导航指示/渐变上副文字) AppColors.surfaceTint / Colors.white 主题、home 促销卡
[#4F46E5→#8B5CF6][primary→#7C3AED] 渐变 AppColors.brandGradient home 故事环、促销卡
#ECFDF5→#FFF7ED 问候卡渐变 surfaceTint → canvas home
0x224F46E5 装饰爪印 primary.withAlpha(34) home
#475569slate 次级文字/阴天色) AppColors.primaryDark / AppColors.ink home
#64748B#F59E0B(多云/晴天) AppColors.muted / AppColors.warning home 天气色
0xCC0F172A 图片压暗渐变 ink.withAlpha(204) create
#E2E8F0scrim 上副文字/进度轨道) Colors.white70 / AppColors.border create、pets
#ECFDF5 / #A7F3D0 / #047857 健康提醒卡 successSurface / success.withAlpha(140) / successInk pets
#A5B4FC / #334155 / #94A3B8(深色卡上) AppColors.accent / Colors.white24 / Colors.white70 profile
促销卡反白按钮前景 primary primaryStrongAA home
导航选中 label primary primaryStrong11px 文字保 AA 主题

保留未动:天气雨/雪的功能性蓝色(#0284C7#0891B2,非旧品牌色)、点赞红、卡片主题 #F1F5F9 描边改为 AppColors.border

3. 改动文件清单

修改(7):

  • patbond-flutter/lib/core/theme/app_theme.dart(重写)
  • patbond-flutter/lib/widgets/common.dart
  • patbond-flutter/lib/features/home/home_page.dart
  • patbond-flutter/lib/features/create/create_page.dart
  • patbond-flutter/lib/features/pets/pets_page.dart
  • patbond-flutter/lib/features/profile/profile_page.dart
  • services / post_detail / main_shell 仅引用 token 字段,值随主题自动切换,无需改动)

新增(7):

  • patbond-flutter/lib/core/widgets/brand_mark.dart
  • patbond-flutter/lib/core/widgets/app_text_field.dart
  • patbond-flutter/lib/core/widgets/primary_button.dart
  • patbond-flutter/lib/core/widgets/inline_error_banner.dart
  • patbond-flutter/lib/core/widgets/auth_scaffold.dart
  • patbond-flutter/test/core/widgets/primary_button_test.dart
  • patbond-flutter/test/core/widgets/app_text_field_test.dart

4. 验收命令输出摘要

$ dart format --output=none --set-exit-if-changed lib test
Formatted 22 files (0 changed) in 0.15 seconds.   # exit 0

$ flutter analyze
Analyzing patbond-flutter...
No issues found! (ran in 0.7s)                    # 无 error、无 warning

$ flutter test
00:01 +7: All tests passed!                       # 含原有导航冒烟测试,未改断言

5. 实现说明与遗留问题

  1. filledButtonTheme 的 minimumSize 用了 Size(64, 52) 而非规范建议的 Size.fromHeight(52):后者会给所有 FilledButton 无限最小宽度,令 Row 内既有按钮(首页促销卡「去使用」、服务页「立即预约」、对话框「确认恢复」)布局异常。改为仅约束高度 52;登录页的全宽由 PrimaryButton 自身 width: double.infinity 保证。副作用:既有小按钮从默认 40 高变为 52 高,视觉更厚重但协调,未破坏布局。
  2. PrimaryButton 的 loading 态通过 disabledBackgroundColor: primaryStrong 保持珊瑚填充(规范 §4.3/§4.4:loading 不是置灰禁用态),已有测试锁定该行为。
  3. ColorScheme.fromSeed 仍以 #FF6F4C 为种子Material 组件(Chip、SegmentedButton、tonal 按钮等)使用生成的暖色调色板,与正典色板协调但非逐一指定;error 已显式覆盖为 #D0342C。若后续设计对某组件色不满意,在主题内补对应 componentTheme 即可。
  4. 天气语义色:雨 #0284C7、雪 #0891B2 为功能色保留硬编码;阴天映射为 ink、多云映射为 muted,如需更细的天气色阶可后续补 token。
  5. 品牌字体(Baloo 2 / 圆润中文标题体)未引入,规范允许后置;BrandMark 字标暂用系统字体 32/w700。
  6. 成功色 sage #7FA88A 作 11px TagPill 文字对比度偏弱(约 2.4:1,沿用既有 TagPill 模式);正文类成功文字请用 successInk。此为设计规范自带取舍,未在本次擅改。
  7. Splash / 登录 / 注册页、认证状态机、flutter_secure_storage 依赖均未实现,按计划等后端契约冻结后进行。

Frontend Developer · 2026-09-03