Skip to content

客户端小程序 — 个人中心

上级文档:客户端小程序


概述

对应主文档 §8.8

个人中心是用户管理个人信息、查看权益、使用功能的统一入口。同时承载运动日历身体数据记录两大工具性功能,提升用户使用频率和粘性,让小程序不仅是消费工具,更是用户的健身助手。

页面路由

路由页面说明
/pages/profile/index个人中心功能导航主页
/pages/profile/face-manage人脸管理重新录入(从未入场成功时可见)
/pages/profile/workout-calendar运动日历健身打卡记录 + 日历视图
/pages/profile/badges我的勋章勋章成就展示
/pages/profile/body-data身体数据体重/体脂/围度等数据记录与趋势图
/pages/profile/body-data/add记录身体数据新增一条身体数据记录

个人中心页要素

用户信息区

要素说明
头像微信头像或自定义头像
昵称微信昵称或自定义昵称
手机号脱敏展示(如 138****8888)
会员卡摘要当前有效会员卡:套餐名称 + 到期日期(如有)
「编辑资料」入口跳转资料编辑页

运动数据快览卡片

在用户信息区下方展示,吸引用户持续使用。

要素说明
本月打卡如「本月已练 8 天」
累计打卡如「累计 45 天」
连续打卡如「🔥 连续 3 天」
最新勋章如「🏅 坚持达人」+ 勋章图标
「查看运动日历 >」跳转运动日历页

功能菜单列表

菜单项图标跳转说明
我的会员🟢/pages/profile/membership查看有效/历史会员
我的订单📋/pages/order/list订单列表
优惠券🎫/pages/coupon/list我的优惠券(未纳入当前范围时隐藏)
运动日历📅/pages/profile/workout-calendar健身打卡记录
我的勋章🏅/pages/profile/badges勋章成就展示
身体数据📊/pages/profile/body-data体重/体脂/围度记录
人脸管理📸/pages/profile/face-manage重新录入(从未入场成功时可见;入场成功后隐藏)
兑换券码🎁/pages/voucher/redeem外部平台券码兑换
淋浴控制🚿/pages/shower/index启动/查看淋浴
联系客服📞客服方式展示微信号/电话
语言切换🌐语言设置中/EN 切换
关于我们ℹ️关于页面版本信息、隐私政策、用户协议

我的会员摘要区

在用户信息下方展示当前有效会员卡的快捷摘要:

要素说明
会员卡名称 + 状态标签如「月卡 · 有效」
到期时间或剩余天数如「剩余 18 天」或具体到期日期
「查看全部会员 >」跳转会员详情页

运动日历

定位:用户的健身打卡记录工具,通过可视化激励用户高频到店消费。

运动日历页要素

要素说明
返回按钮 + 「运动日历」标题
月份切换左右箭头切换月份,默认当前月
日历视图月度日历,标记到店打卡日期
统计摘要本月打卡天数、累计打卡天数、最长连续打卡
打卡详情点击某天可查看当天的到店/离店时间、运动时长

日历视图规则

规则说明
打卡标记到店记录对应的日期用绿色圆点标记
今日当前日期用蓝色高亮边框
运动时长有多次进出的日期显示总时长(如「1.5h」)
无记录无打卡的日期为空白
月份范围可查看最近 12 个月的记录

打卡数据来源

打卡数据基于刷脸进离店记录自动生成,用户无需手动打卡。

数据项来源说明
到店时间刷脸进门记录faceLog.enteredAt
离店时间刷脸出门记录faceLog.exitedAt
运动时长离店时间 - 到店时间自动计算
打卡天数有到店记录的日期数按日去重

统计指标

指标计算规则展示
本月打卡天数当月有到店记录的日期数X 天
累计打卡天数所有月份有到店记录的日期总数X 天
连续打卡从今天往前连续有到店记录的天数🔥 连续 X 天
本月运动总时长当月所有运动时长之和X.X 小时
本月最长单次当月最长单次运动时长X.X 小时
平均每次时长总时长 / 到店次数X.X 小时

勋章成就体系

通过勋章系统激励用户持续到店健身,提升使用频率和粘性。勋章基于用户行为自动解锁,不可手动领取。

勋章定义

勋章条件图标建议稀有度
初来乍到首次刷脸成功入场🌟普通
连续 3 天连续 3 天有到店记录🔥普通
连续 7 天连续 7 天有到店记录💪稀有
连续 30 天连续 30 天有到店记录👑传说
月度达人单月打卡 ≥ 12 天🏅稀有
坚持不懈累计打卡 ≥ 30 天💎稀有
百日打卡累计打卡 ≥ 100 天🏆传说
晨练达人累计 5 次在 8:00 前到店🌅普通
夜猫子累计 5 次在 21:00 后到店🌙普通
健身老手累计运动时长 ≥ 100 小时⏱️稀有

勋章页面要素

要素说明
返回按钮 + 「我的勋章」标题
勋章统计已解锁 X / 总计 Y 枚
勋章展示网格布局,每枚勋章展示图标 + 名称 + 解锁条件
已解锁彩色图标 + 「已获得 YYYY-MM-DD」
未解锁灰色图标 + 解锁进度(如「3/7 天」) + 解锁条件文字
稀有度标签普通(无标签)/ 稀有(蓝色)/ 传说(金色)

勋章解锁规则

  • 勋章由服务端在每次刷脸入场/离店时异步计算并更新
  • 前端通过 GET /api/v1/user/badges 获取当前勋章列表和解锁状态
  • 新勋章解锁时,运动日历页顶部显示「🎉 恭喜获得 [勋章名]」横幅提示(3 秒后自动消失)
  • 勋章数据仅展示用途,不涉及任何权益发放

运营配置

管理后台可动态增减勋章定义,无需发版。

配置项说明
勋章列表运营可在管理后台新增/编辑/停用勋章
解锁条件支持的条件类型:打卡天数、连续天数、到店时段、运动时长
勋章图标上传 SVG/PNG 图标
稀有度普通 / 稀有 / 传说

运动日历异常处理

异常处理
数据加载失败展示错误态 + 「重试」
无打卡记录展示空态插画 + 「还没有打卡记录,去门店开练吧!」
离店记录缺失进店无离店时,运动时长显示「进行中」或取最新一次离店时间
时区问题统一使用服务器时区(UTC+8),前端按本地时区展示日期

身体数据记录

定位:用户的身体数据管理工具,让小程序成为用户的健身数据仪表盘,提升工具属性和留存。

身体数据列表页要素

要素说明
返回按钮 + 「身体数据」标题
当前数据卡片最新一次记录的核心数据展示
趋势图体重/体脂率的变化趋势折线图
数据维度 Tab体重 / 体脂率 / 身体围度
历史记录列表按时间倒序展示所有记录
「记录数据」按钮右下角悬浮按钮,跳转新增记录页

当前数据卡片

展示最新一条记录的核心数据:

数据项单位说明
体重kg最新记录体重
体脂率%最新记录体脂率
BMI自动计算(体重 / 身高²)
上次记录与上次记录的变化(↑/↓/—)

数据维度

维度字段 key单位说明
体重weightkg手动录入
体脂率bodyFatRate%手动录入
身高heightcm首次设置后通常不变
胸围chestcm手动录入
腰围waistcm手动录入
臀围hipcm手动录入
大臂围armcm手动录入
大腿围thighcm手动录入

趋势图

要素说明
图表类型折线图
时间范围近 30 天 / 近 90 天 / 近半年 / 全部
数据点每个记录点在图上标注
变化标注最新值与首值的变化(↑X.X kg / ↓X.X%)
无数据展示空态 + 「记录第一条数据吧」

新增记录页要素

要素说明
返回按钮 + 「记录数据」标题
日期选择默认今天,可选历史日期
数据输入表单各维度输入框(带单位提示)
备注可选文本输入(如「今天做了力量训练」)
「保存」按钮校验后提交

输入校验规则

字段规则
体重20.0 ~ 300.0 kg,保留 1 位小数
体脂率3.0 ~ 60.0 %,保留 1 位小数
身高100.0 ~ 250.0 cm,保留 1 位小数
围度30.0 ~ 200.0 cm,保留 1 位小数
日期不可选未来日期,最早可选 1 年前

历史记录列表

字段说明
日期记录日期
体重体重值
体脂率体脂率值
变化趋势与上一条的差值(↑/↓)
操作「查看」跳转详情 / 「删除」二次确认

身体数据异常处理

异常处理
数据加载失败展示错误态 + 「重试」
无历史记录展示空态 + 引导记录第一条数据
删除记录二次确认「确定删除该条记录?」→ 确认后删除
同一天重复记录允许,同一天可有多条记录(如晨起和睡前)
输入异常值前端校验拦截 + 提示合理范围

人脸管理页要素

隐私原则:用户不可查看自己已录入的人脸照片,避免不安感。

  • 返回按钮 + 「人脸管理」标题
  • 人脸状态卡片:已录入/未录入 + 录入时间(不展示人脸照片
  • 隐私说明:「人脸数据用于健身房刷脸进出验证,您的照片不会被展示给任何人」
  • 「重新录入」按钮(仅在已录脸且从未入场成功时展示)
  • 删除说明:「如需删除人脸数据,请联系客服」
  • 「📞 联系客服」入口
  • 入场成功后自动隐藏:如用户曾刷脸成功入场,整个人脸管理入口从个人中心菜单消失(前端通过 hasSuccessfulEntry 字段判断)

客服与帮助

客服入口方案

  • 个人中心和首页各保留一个固定客服入口
  • 点击后展示客服微信号/电话号码
  • 支持一键复制微信号
  • 支持拨打电话(wx.makePhoneCall

帮助页要素

  • 常见问题(FAQ)列表
  • 每个问题可展开查看答案
  • 底部固定「联系客服」入口

接口

text
# 用户资料
GET /api/v1/user/profile
  Auth: JWT
  Response: {
    id, nickname, avatarUrl, phone,
    faceEnrolled: boolean,
    faceEnrolledAt: string | null,
    locale: 'zh' | 'en',
    tags: string[]              // 用户标签(用于 Banner 分层)
  }

PUT /api/v1/user/profile
  Auth: JWT
  Body: { nickname?: string, locale?: string }
  Response: { success: boolean }

# 运动日历
GET /api/v1/user/workout-calendar
  Auth: JWT
  Query: { year, month }       // 如 2026, 3
  Response: {
    monthDays: {                // 当月打卡日期列表
      '2026-03-15': {
        enterAt: string,        // 进店时间
        exitAt: string | null,  // 离店时间(null 表示未离店)
        duration: number        // 运动时长(分钟)
      },
      ...
    },
    stats: {
      monthDays: number,        // 本月打卡天数
      totalDays: number,        // 累计打卡天数
      currentStreak: number,    // 连续打卡天数
      monthDuration: number,    // 本月总运动时长(分钟)
      monthMaxSingle: number,   // 本月最长单次(分钟)
      avgDuration: number       // 平均每次时长(分钟)
    },
    newBadges: string[]         // 本次请求新增解锁的勋章 ID 列表
  }

# 我的勋章
GET /api/v1/user/badges
  Auth: JWT
  Response: {
    items: [{
      id: string,
      name: string,             // 勋章名称
      description: string,      // 解锁条件描述
      iconUrl: string,          // 勋章图标 URL
      rarity: 'common' | 'rare' | 'legendary',
      unlocked: boolean,
      unlockedAt: string | null, // 解锁时间(ISO 8601)
      progress: {               // 进度信息(未解锁时)
        current: number,        // 当前值
        target: number,         // 目标值
        label: string           // 进度描述,如「3/7 天」
      }
    }],
    totalBadges: number,         // 勋章总数
    unlockedCount: number        // 已解锁数量
  }

# 身体数据
GET /api/v1/user/body-data
  Auth: JWT
  Query: { startDate?, endDate?, dimension? }
  Response: {
    items: [{
      id, date, weight, bodyFatRate, height,
      chest, waist, hip, arm, thigh,
      note, createdAt
    }],
    latest: BodyDataRecord | null   // 最新一条
  }

POST /api/v1/user/body-data
  Auth: JWT
  Body: {
    date: string,                // YYYY-MM-DD
    weight?: number,
    bodyFatRate?: number,
    height?: number,
    chest?: number,
    waist?: number,
    hip?: number,
    arm?: number,
    thigh?: number,
    note?: string
  }
  Response: { success: boolean, id: string }

DELETE /api/v1/user/body-data/:id
  Auth: JWT
  Response: { success: boolean }

飞创 Fitron 内部规划文档