Files
fitness-coach/PRD-FITCOACH优化方案.md
wm b94eb706ff feat: Kinetic Dark 设计语言 + Lucide 图标迁移 + 首页轻量个性化
- 建立 Lucide 子集 iconfont(49 字形),全站 emoji 替换为 fc-icon 组件
- 重塑 Design Token(冷中性近黑底 + Volt 荧光绿 #B6F24E),消除硬编码颜色
- 首页登录后个性化:我的计划 / 我的收藏 / 今日推荐(纯前端复用现有 API)
- 后端 DEFAULT_EMOJI→Lucide 名,PALETTE 对齐 Kinetic Dark 语义色板
- 修复 person-standing 缺失字形;14 个官方组合 seed emoji 全部映射到现有字形
2026-07-22 21:38:56 +08:00

24 KiB
Raw Blame History

FITCOACH 优化评估与改进方案PRD

文档属性

  • 版本v1.0(方案稿,待产品负责人确认后进入开发)
  • 日期2026-07-22
  • 作者:许清楚(产品经理)
  • 范围:在现有「微信健身小程序 + NestJS 后端 + JSON 数据落地」架构上做体验优化,不新增业务线、不写代码,先方案后开发
  • 目标三大块:① 页面 UI 美观度(重塑设计语言)② 登录后首页个性化(轻量档 + 完整档)③ 综合 UX交互 / 信息架构 / 响应速度 / 导航)

0. 结论速览(给决策者的话)

FITCOACH 当前是一个"功能完整但体验半成品"的产品:后端数据能力(计划、收藏、用户、推荐)已经具备,但首页完全没有用上这些数据,且全站用 emoji 当功能图标(触碰团队 P0 红线),加载/错误态缺失,首页一次请求卡死整页。

三块改进的整体排序建议:

  • P0本期必做低风险高显效emoji 图标清零 + 设计令牌重塑(块一);首页轻量档个性化(块二);全站骨架屏 + 错误重试态(块三)。
  • P1本期第二阶段:完整档个性化(新增训练打卡 + 连续天数 + 进度曲线);用户画像 onboarding全局常驻搜索 + 导航重构;请求超时与缓存 + tab 保活。
  • P2打磨 / 下期):周/月训练报告(雷达图);下拉刷新 / 长按 / 过渡动画等手势完善;无障碍对比度审计。

1. 现状诊断(基于代码实测,含文件与行号证据)

1.1 首页零个性化(核心痛点)

miniprogram/pages/index/ 是一个完全静态的页面:

  • Hero 文案写死为 "今天,练点什么?"index.wxml:5没有任何用户昵称问候、没有时段判断
  • loadData() 只拉取全局数据:getStats() / listExercises() / listCollections()index.js:28-46不带任何 openid / 用户维度
  • 已存在、却未用于首页的个性化数据(接口全部就绪,纯前端即可调用):
    • 我的计划:planSvc.listMine()GET /api/plansservices/plan.js:24,已在 my-plans.js 使用)
    • 收藏动作:favSvc.listExercises()GET /api/favorites/exercisesservices/favorite.js:17,已在 favorites.js 使用)
    • 用户资料(含昵称):auth.getProfile()utils/auth.js:73,本地存储读取,零网络开销)
    • 智能推荐引擎:svc.recommend({target, equipment})services/exercise.js:45)——但需 target 参数,首页当前未调用
  • 交付与文档不一致:OVERVIEW.md:34 声称首页有"渐变 hero + 问候 + 智能推荐 CTA",实际"问候"并未实现,只是通用文案。

结论:个性化不是"从零造数据",而是"把已经存在的能力接到首页上"。这正是轻量档改动小、见效快的根本原因。

1.2 emoji 图标违规(团队 P0 红线,系统性问题)

全站把 emoji 当作功能图标使用,违反"禁止 emoji 作为功能图标"规则。实测清单:

位置 文件:行 emoji 用途
底部导航 components/bottom-nav/index.js:7-10 首页/分类/计划/我的 用 🏠📚📋👤
首页快捷入口 pages/index/index.js:14-19index.wxml:29 💪🏋️📋🗂️👤
首页搜索 / CTA pages/index/index.wxml:9,14 🔍
搜索页图标 pages/search/search.wxml:5 🔍
个人中心单元格 pages/profile/profile.wxml:6,41,46,51,56 💪❤️🗂️📋
空态插画 favorites.wxml:20my-plans.wxml:20detail.wxml:16plan-detail.wxml:23plan-favorites.wxml:16 🔍📋🏋️
练习卡占位图 components/exercise-card/index.wxml:10 🏋️
头像组件默认 components/avatar/index.js:5index.wxml:4 💪
头像/计划 emoji 选择器 pages/profile/profile.js:6pages/plan-edit/plan-edit.js:4 一整组 emoji 数组

数据层也被污染(必须一并清理,否则新用户一进来还是 emoji

  • backend/src/users/users.service.ts:26avatar 默认值 '🏃'
  • backend/src/plans/plans.service.ts:37DEFAULT_EMOJI = '📋',且 PlanRecord.emoji 字段贯穿数据库与前端

影响emoji 在微信不同机型/系统字体下渲染不一致,描边与对比度不可控,品牌感弱,无障碍差(屏幕阅读器念出无意义字符)。

1.3 信息架构与导航

  • 底部导航 4 项:首页 / 分类 / 计划 / 我的。其中"计划"实际指向 my-plans个人计划),与"分类"(内容浏览)并列,语义层级略乱;"官方计划"入口散落在首页快捷入口 + collection 页,缺乏统一归属。
  • 首页单页塞了 6 个 sectionhero / 2×3 快捷 / 精选动作 / 训练组合 / 按部位 / 热门器械)+ 160rpx 底部留白(index.wxml 全篇),首屏重点被稀释。
  • 无全局常驻搜索:搜索只在 hero 内一个 pill点开才进二级 search 页(index.wxml:8-11)。
  • 自定义导航栏 navbar 仅在子页使用(favorites.wxml:2my-plans.wxml:2),首页没有统一导航条,与子页视觉割裂;app.json:18 设了 navigationStyle: custom,每个页面需自行承担导航。

1.4 加载态 / 空态 / 错误态

  • 首页 loading 是死代码index.js:12 声明 loading: true,但 index.wxml 全程未引用任何 wx:if="{{loading}}" → 首屏在数据到达前是空白/白屏,无任何指示。
  • 子页仅有纯文本"加载中…",无骨架屏(favorites.wxml:24my-plans.wxml:25)。
  • 错误态彻底缺失utils/request.js:34-41 失败时只弹 toast页面 catchsetData({loading:false}) 得到空列表(favorites.js:29-31my-plans.js:28-30网络失败与"真·无数据"无法区分,且无重试入口
  • 空态结构本身尚可(插画 + 文案 + 引导按钮),但插画是 emoji见 1.2),随块一替换。

1.5 响应速度 / 交互

  • utils/request.js:16-42wx.request 没有 timeout 配置(微信默认也无强制超时)→ 弱网下可能长时间挂起,用户无感知。
  • 首页 Promise.all 聚合 3 个接口(index.js:30-34),任一慢则整体延迟;无本地缓存、无预取。
  • 底部导航用 wx.reLaunch 重置页面栈(bottom-nav/index.js:18)→ 每次切 tab 整页重建、首页 loadData() 重跑,跨 tab 状态不保留,体验被切断;行业通行做法是保留 tab 状态(如原生 tabBar / 自定义保活)。
  • 全站无下拉刷新onPullDownRefresh 未出现)。
  • GIF 演示走 jsDelivr CDN 直链(OVERVIEW.md:59),弱网加载慢,无占位过渡。

1.6 设计令牌现状(这是"重塑"的有利基础)

暗金奢华风集中定义在 app.wxsspage 选择器内CSS 变量):

  • 主色 --gold:#D9B36C--gold-2:#F0D9B9、点缀 --teal:#58C9B9;底色 --bg:#0E1110app.wxss:4-12
  • 圆角 --radius:28rpx / --radius-sm:18rpx;阴影 --shadowapp.wxss:17-19

利好:令牌高度集中,重塑设计语言只需改 app.wxss 一处 + 个别组件局部样式,几乎不动业务逻辑

风险点navbar / section-header / chip / level-tag / plan-card / exercise-card 等组件各有独立 .wxss,需排查是否存在硬编码色值(如 plan-card 用到计划自带的 color 字段、prog 用到集合 color),重塑时要一并纳入令牌体系。


2. 竞品对标(联网调研 5 家健身 / 运动 App

说明:项目内 references/industries/ 下未提供健身行业文档以下对标全部来自联网调研2026-07-22 检索)。

App 类型 设计语言 / UI 特征 个性化首页做法 可借鉴点 我们的差距
Keep 9.0(直接竞品,国内最大) 课程+计划+社区 信息架构做减法:砍商城、课程/计划双 tab、单列 Feed、灰白一致入口 首页按"往期运动数据"智能推荐课程;"我的"页重构为 数据概览/全部数据/运动记录;健康状态卡片(仪表盘)给当日评估+建议;上周周报五维雷达图+环比箭头1 分钟问卷生成专属计划 ① 个性化 = 用户历史 + 当下状态 ② 进度可视化(雷达/7日图③ AI 克制:每条建议有数据支撑,不煽情 ④ onboarding 问卷建训练画像 我们首页无任何个性化;无状态/周报可视化
Apple Fitness+(标杆) 设备+课程 黑色背景、固定三环配色、高对比无障碍、一致视觉层级 Activity Rings三环Move/Exercise/Stand 游戏化进度三核心指标化简复杂数据降低认知负荷目标可个性化Move goal 最常调) ① 游戏化连续/进度直击"完整档 连续天数" ② 用最少指标表达状态 ③ 黑色背景+固定配色的一致语言 我们无进度/连续概念;图标系统混乱
Fitbod直接竞品AI 力量训练) 计划+记录 干净、聚焦、不堆徽章;肌肉恢复热力图直观 基于训练历史每日更新个性化计划;输入目标/经验/器械/时长 → 生成"living training profile";记录每次训练→算 1RM→推荐下次"今天在哪练"按环境适配 ① 训练画像驱动自适应 ② 身体就绪度可视化(恢复热力图)③ 界面克制 我们无训练记录,无法自适应
Strava(替代方案,社交/连续) 社区+记录 Feed 基于互动行为的个性化排序;收藏运动员置顶 连续/挑战/分段segments机制驱动留存 ① 连续天数 + 挑战的游戏化钩子 ② 但强制非时间序被用户骂 → 教训:个性化要可关闭/可切换 我们无社交层,但连续机制可独立借鉴
Gymshark Training(替代方案,品牌) 品牌+免费计划 极简、品牌一致、快速 onboarding~1 分钟) 个性化弱onboarding 只问年龄性别;进度追踪仅"标记完成/记录组数" 反面教材:好设计 ≠ 好教练;缺 adaptive programming 与 analytics 会被进阶用户抛弃 提醒我们:仅做"好看的首页"不够,需有数据闭环

提炼 6 条可迁移最佳实践

  1. 个性化首页 = "用户已有数据" + "当下状态"Keep 健康状态卡 / Fitbod 恢复热力图)。
  2. 游戏化连续 / 进度Apple 三环 / Strava streak——直接支撑"完整档 连续训练天数"。
  3. 自适应 AI 但克制Keep 不煽情、每条建议有据可依不堆无意义徽章Fitbod
  4. 信息架构做减法Keep 9.0 砍商城、简化导航、单列 Feed——治我们的首页 6 段过载。
  5. onboarding 问卷建训练画像Fitbod / Keep 1 分钟)——支撑完整档要新增的"训练目标"字段。
  6. 进度可视化(雷达图 / 7 日图 / 曲线)而非数字堆砌。

3. 三块改进方案 + 实施优先级

3.1 块一:页面 UI 美观度 —— 重塑设计语言P0用户已确认方向

目标:由设计师重做 Design Token可能换主色 / 排版体系),统一图标体系,彻底清除 emoji。

方案拆项:

  • D1 新 Design Token 体系:在 app.wxss 重定义颜色 / 字体 / 间距 / 圆角 / 阴影 / 层级变量(替换现有 --gold 等)。是否换主色由设计师定,但禁止紫色→粉色渐变(团队红线)。
  • D2 统一 SVG 图标库:引入一套 SVG / iconfont 图标(具体选型由架构师按项目锁定,不预设具体库),全站功能图标改为引用图标名(如 icon-home / icon-search),替换全部 emoji清单见 1.2)。
  • D3 排版体系升级:标题层级、字重、行高、中文间距规范化,解决当前 hero 56rpx 与正文 28rpx 之间缺乏中间层级的问题。
  • D4 组件令牌对齐navbar/section-header/chip/level-tag/plan-card/exercise-card 去硬编码色值,统一引用 D1 令牌;plan-cardcolorprogcolor 改为"用户色板 + 令牌"双轨,避免破坏现有计划配色功能。
  • D5 对比度与无障碍:确保正文/背景对比度达 WCAG 2.1 AA图标有文字标签或 aria 等价。

优先级P0用户已选"重塑设计语言",且 emoji 违规是团队红线,必须清零)。 成本 / 影响:设计约 1 人周 + 前端改造约 35 人日。令牌集中,业务逻辑零改动,影响面 = 全站视觉Impact 高、Effort 中。RICE 视角 Reach=全部用户(10)、Impact=3(巨大)、Confidence=100%(已确认方向)、Effort≈6 → Score≈5.0

3.2 块二:登录后首页个性化(两档都要,分 MVP 切割)

轻量档P0改动小见效快不新建数据

范围:在首页顶部注入"已存在数据"的个性化模块,不新建任何后端数据。

  • 时段问候:读 auth.getProfile().nickname → "早上好 / 下午好 / 晚上好,{昵称}"。零网络开销。
  • 我的计划planSvc.listMine() 取最近 N 个,横滑卡片 + "继续训练"入口。
  • 我的收藏favSvc.listExercises() 取最近 N 个收藏动作。
  • 今日推荐:复用 svc.recommendtarget 由"最近计划 / 收藏"推导(不新建数据,仅做数据派生);若无任何历史,回退到现有"精选动作"。
  • 未登录降级:保留现有通用首页(不报错、不空白)。

依赖:仅前端;全部接口(plan.js / favorite.js / exercise.js / auth.js)已存在。 成本:前端 23 人日零后端改动。RICEReach=登录用户(8)、Impact=2(高)、Confidence=100%、Effort≈3 → Score≈5.3

完整档P1新增训练记录 / 进度历史)

新增后端数据(沿用现有 store.ts JSON 落地模式,成本可控):

  • 数据模型 checkins store{ id, openid, date(YYYY-MM-DD), planId?, exerciseIds[], durationMin?, completed }
  • 派生指标连续训练天数streak、近 30 日训练次数、近 7 日时长 / 动作分布
  • 用户画像扩展(users store + users.servicefitnessGoal(减脂/增肌/塑形/保持健康)、leveltrainFreq 偏好

新增接口

  • POST /api/checkins(打卡,可关联计划)
  • GET /api/checkins/streak(连续天数 + 今日是否已打卡)
  • GET /api/checkins/summary?range=7|30(进度曲线数据)
  • PATCH /api/users/me 扩展画像字段(已有,仅加字段)

首页展示

  • 进度曲线(近 7/30 日训练次数或时长SVG 折线 / 柱状)
  • 连续训练天数徽标(对标 Apple 三环 / Strava streak 的游戏化钩子)
  • "今日打卡"按钮(首页 + 计划详情页)
  • 周/月训练报告(对标 Keep 周报雷达图,列为 P2 增强)

依赖:后端 1 个新 store + controller/service参照 common/store.ts);前端新增打卡与曲线组件;需 onboarding 收集 fitnessGoal(见 P1 画像项)。 成本:后端 34 人日 + 前端 45 人日。RICEReach=活跃训练用户(6)、Impact=3(巨大)、Confidence=80%(模式可参照)、Effort≈9 → Score≈1.6 → 排 P1。 关键约束:连续天数 / 曲线必须有打卡数据沉淀才有意义,故完整档必须在轻量档上线、积累初期数据后跟进。

两档 MVP 切割与依赖关系

[轻量档] 前端 only复用现有 API
   └─ 首页个性化容器(问候 + 我的计划 + 收藏 + 今日推荐)
        │
        ├─(共享)时段问候 + 容器布局,完整档直接复用
        │
[完整档] 新增 checkins store + 打卡接口 + 曲线组件
   └─ 在容器下方追加:进度曲线 + 连续天数 + 今日打卡
        │
        └─ 依赖:用户画像 onboarding收集 fitnessGoal/level
  • 上线顺序轻量档P0先上 → 完整档P1在 12 个迭代后上。
  • 为什么这样切:轻量档零后端风险、当天可见效,先验证"首页个性化"假设并拉高激活;完整档需要新数据闭环,先轻后重可避免一次性大改带来的回归风险。
  • Backlog不在本期 MVP:周/月雷达报告、社交挑战、AI 生成式教练文案。

3.3 块三:综合 UX 优化清单(按维度 + 优先级)

导航 / 信息架构P1

  • 重审底部导航结构:"计划"语义是否改为"我的"(与"首页/发现/进度/我的"更顺);完整档上线后考虑新增"进度"入口。
  • 全局常驻搜索:在导航栏内置搜索图标,替代仅 hero 内 pill。
  • 首页 section 减负:首屏聚焦"个性化区 + 今日推荐",其余(训练组合 / 按部位 / 热门器械)下移或折叠。

加载态 / 空态 / 错误态P0

  • 全站骨架屏(首页 / 列表页),替换死 loading 字段与纯文本"加载中…"。
  • 错误态区分"网络失败"与"无数据",网络失败时提供"重试"按钮(治愈 1.4 的静默失败)。
  • 空态保留结构,插画换 SVG随块一 D2

响应速度P1

  • request.js 增加 timeout(建议 8s+ 统一 loading 策略,避免弱网挂起。
  • 首页接口并行 + 字段裁剪;关键数据(计划 / 收藏 / 资料)本地缓存,进首页即渲染缓存、后台静默刷新。
  • 底部导航 reLaunch 改为保活方案(原生 tabBar 或自定义栈保留),避免切 tab 重拉数据。

手势 / 交互P2

  • 首页 / 列表支持下拉刷新(onPullDownRefresh)。
  • 横滑区增加"更多 / 分页点"提示一致性。
  • 收藏 / 计划卡片增加长按 / 左滑等快捷操作。
  • 统一点击反馈(hover-class)与过渡动画。

4. 实施路线图(优先级总表)

编号 改进项 归属块 优先级 影响 成本(人日) RICE 评分 MVP?
U1 emoji → 统一 SVG 图标替换(全站 + 数据层默认值) UI P0 23 5.0
U2 设计令牌重塑Design Token v2 UI P0 35 5.0
P1 首页轻量档个性化(问候+我的计划+收藏+今日推荐) 个性化 P0 23 5.3
X1 全站骨架屏 + 错误重试态 UX P0 23 4.8
P2 完整档checkins 数据 + 打卡接口 + 首页曲线/连续天数 个性化 P1 巨大 79 1.6 否(第二阶段)
P3 用户画像 onboardingfitnessGoal/level 个性化基建 P1 23 2.4
X2 全局常驻搜索 + 导航结构重构 UX/架构 P1 34 2.0
X3 请求超时 + 缓存 + tab 保活 UX/速度 P1 23 2.6
P4 周/月训练报告(雷达图) 个性化增强 P2 34 1.0
X4 下拉刷新 / 长按 / 过渡动画等手势完善 UX P2 23 1.2
U3 对比度 / 无障碍审计WCAG AA UI P2 12 1.5

本期P0 + P1节奏建议

  1. 第一批P0约 1.5 周U1 + U2 + P1 + X1 —— 视觉焕新 + 首页轻量个性化 + 骨架屏,用户可立刻感知。
  2. 第二批P1约 2 周P2完整档+ P3画像+ X2 + X3 —— 训练闭环与数据沉淀。
  3. 第三批P2打磨P4 + X4 + U3。

5. 明确不在本期范围Out-of-Scope

  • 社交 / 社区Strava 式 feed、好友、排行榜、挑战赛 —— 本期不做(连续天数可借鉴其游戏化,但无社交层)。
  • 商城 / 电商Gymshark 式服饰售卖 —— 不做。
  • 课程体系 / 直播课 / 视频跟练Keep 式 —— 不做FITCOACH 定位为"动作推荐 + 计划"工具。
  • 饮食 / 营养 / 热量Keep 饮食 —— 不做。
  • 智能硬件联动Apple Watch / Keep 硬件 —— 不做。
  • 多语言 / i18n —— 不做。
  • 后端从 JSON store 迁移到 SQL —— 不做(仅新增 checkins store 沿用 JSON 落地)。
  • AI 大模型生成式 coach 文案 —— 克制,不做自由发挥;仅用规则推荐(遵循 Keep"有据可依不煽情"教训)。
  • 付费 / 会员体系 —— 不做。

6. 非功能需求(必含)

类别 要求 优先级
性能 首屏可交互 < 2.5s(弱网下,凭骨架屏 + 缓存达成API p95 < 500ms沿用现有内存数据集 P0
可用性 任一接口失败不白屏,降级到缓存/空态并提供重试 P0
安全 HTTPS + JWT现有新增 checkins 接口纳入 auth.guard 用户隔离(沿用 favorites/plans 的 openid 隔离模式) P0
兼容性 微信最新基础库iOS / Android 微信客户端 P0
可访问性 对比度 WCAG 2.1 AA图标有文字/aria 等价;移除 emoji 功能图标 P1
图标方案 统一 SVG 图标库(具体由架构师按项目选型锁定,不预设具体库) P0
数据埋点 见第 7 节 P0

7. 数据埋点方案(必含,验证产品假设)

MVP 必须埋点的关键事件(不埋 = 上线后无法验证假设):

事件类别 必埋事件 说明
获客 app_launch, login_success 启动量、登录转化
激活 home_view, home_personalized_shown(轻量档命中)、recommend_view 首页个性化模块是否真的展示给用户
留存 session_start, session_duration, checkin_completed(完整档) 次日/7日留存、打卡行为
转化 plan_continue_tap(继续训练)、favorite_item_tapplan_created 个性化模块是否驱动行动
异常 api_error, request_timeout 配合 X3 超时治理

命名规范{对象}_{动作}(如 checkin_completedhome_personalized_shown);每条附带 user_idtimestampdeviceversion;不采集隐私原始输入。


8. 验收标准Given / When / Then节选关键

  • Given 用户已登录,When 打开首页,Then 顶部展示"时段 + 昵称"问候,并出现"我的计划 / 我的收藏 / 今日推荐"模块(轻量档)。
  • Given 用户未登录,When 打开首页,Then 展示通用首页降级版,不报错、不空白。
  • Given 任意页面数据未返回,When 渲染中,Then 显示骨架屏而非空白 / 纯文本"加载中…"。
  • Given 网络请求失败,When 页面进入错误态,Then 出现"重试"按钮且点击可恢复(区分于"无数据"空态)。
  • Given 设计令牌 v2 上线,When 全站渲染,Then 无任何 emoji 功能图标,主色 / 排版符合新规范,且未出现紫色→粉色渐变。
  • Given 完整档已上线且用户完成一次打卡,When 返回首页,Then 连续训练天数 +1进度曲线新增一个数据点。
  • Given 用户首次进入且完整档上线,When 触发 onboardingThen 可填写训练目标 / 水平,并写入用户画像。

9. 给设计 / 架构 / 开发的待办(协作提示)

  • 设计师:输出 Design Token v2 + 统一 SVG 图标清单(替换 1.2 全部 emoji首页个性化容器线框。
  • 架构师:锁定图标库选型;评估 checkins store 与 streak 计算的服务归属;确认请求超时与缓存策略;确保新增接口沿用 openid 隔离。
  • 前端:轻量档复用现有 4 个服务即可开工;骨架屏组件化;底部导航保活方案选型。
  • 后端:仅在完整档阶段新增 checkins 模块store/controller/service沿用 common/store.tsauth.guard

本 PRD 为方案稿,待产品负责人确认范围与优先级后,进入逐批开发。