209021e7d2
- 新增 development/iterations/iteration-1/:15 份角色报告 + 进展看板(已完成/未闭环/下一步),作为双人协作的进度事实来源 - 新增 ADR-006:测试与交付容器化策略(Testcontainers / 交付 Docker 包 / 本机库仅个人联调) - Git 工作流规范补充:敏感信息只进忽略文件或 sample、测试数据不入库、测试代码限标准测试目录 - 门禁:mkdocs build --strict 通过(零警告)
6.9 KiB
6.9 KiB
08 · Flutter 主题迁移与登录组件实现报告
作者:Frontend Developer 日期:2026-09-03 依据:ADR-005(patbond-doc/docs/architecture/decisions.md)、04-ui-login-design-spec.md
1. 完成内容
lib/core/theme/app_theme.dart重写为语义 token 组织(AppColors+ 新增AppRadius),落地珊瑚橙正典色板;补齐filledButtonTheme(高 52、圆角 16、primaryStrong填充、显式 disabled 色)、errorBorder/focusedErrorBorder/errorStyle、colorScheme.error覆盖。主题仍集中在单一文件。- 五个 Tab 页面及公共组件逐处替换旧靛蓝/冷灰硬编码色值为语义 token,仅换色、未动布局。
- 新建 5 个可复用组件于
lib/core/widgets/:BrandMark、AppTextField、PrimaryButton(含 isLoading)、InlineErrorBanner、AuthScaffold。本次未建登录页面(等后端契约冻结)。 - 为
PrimaryButton、AppTextField各写 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 |
#EEF2FF(indigo-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 |
#475569(slate 次级文字/阴天色) |
AppColors.primaryDark / AppColors.ink |
home |
#64748B、#F59E0B(多云/晴天) |
AppColors.muted / AppColors.warning |
home 天气色 |
0xCC0F172A 图片压暗渐变 |
ink.withAlpha(204) |
create |
#E2E8F0(scrim 上副文字/进度轨道) |
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 |
primaryStrong(AA) |
home |
导航选中 label primary |
primaryStrong(11px 文字保 AA) |
主题 |
保留未动:天气雨/雪的功能性蓝色(#0284C7、#0891B2,非旧品牌色)、点赞红、卡片主题 #F1F5F9 描边改为 AppColors.border。
3. 改动文件清单
修改(7):
patbond-flutter/lib/core/theme/app_theme.dart(重写)patbond-flutter/lib/widgets/common.dartpatbond-flutter/lib/features/home/home_page.dartpatbond-flutter/lib/features/create/create_page.dartpatbond-flutter/lib/features/pets/pets_page.dartpatbond-flutter/lib/features/profile/profile_page.dart- (services / post_detail / main_shell 仅引用 token 字段,值随主题自动切换,无需改动)
新增(7):
patbond-flutter/lib/core/widgets/brand_mark.dartpatbond-flutter/lib/core/widgets/app_text_field.dartpatbond-flutter/lib/core/widgets/primary_button.dartpatbond-flutter/lib/core/widgets/inline_error_banner.dartpatbond-flutter/lib/core/widgets/auth_scaffold.dartpatbond-flutter/test/core/widgets/primary_button_test.dartpatbond-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. 实现说明与遗留问题
- filledButtonTheme 的 minimumSize 用了
Size(64, 52)而非规范建议的Size.fromHeight(52):后者会给所有 FilledButton 无限最小宽度,令 Row 内既有按钮(首页促销卡「去使用」、服务页「立即预约」、对话框「确认恢复」)布局异常。改为仅约束高度 52;登录页的全宽由PrimaryButton自身width: double.infinity保证。副作用:既有小按钮从默认 40 高变为 52 高,视觉更厚重但协调,未破坏布局。 - PrimaryButton 的 loading 态通过
disabledBackgroundColor: primaryStrong保持珊瑚填充(规范 §4.3/§4.4:loading 不是置灰禁用态),已有测试锁定该行为。 ColorScheme.fromSeed仍以#FF6F4C为种子,Material 组件(Chip、SegmentedButton、tonal 按钮等)使用生成的暖色调色板,与正典色板协调但非逐一指定;error已显式覆盖为#D0342C。若后续设计对某组件色不满意,在主题内补对应 componentTheme 即可。- 天气语义色:雨
#0284C7、雪#0891B2为功能色保留硬编码;阴天映射为ink、多云映射为muted,如需更细的天气色阶可后续补 token。 - 品牌字体(Baloo 2 / 圆润中文标题体)未引入,规范允许后置;
BrandMark字标暂用系统字体 32/w700。 - 成功色 sage
#7FA88A作 11px TagPill 文字对比度偏弱(约 2.4:1,沿用既有 TagPill 模式);正文类成功文字请用successInk。此为设计规范自带取舍,未在本次擅改。 - Splash / 登录 / 注册页、认证状态机、flutter_secure_storage 依赖均未实现,按计划等后端契约冻结后进行。
Frontend Developer · 2026-09-03