Skip to content

管理后台 — 产品管理

上级文档:管理后台 Web


模块概述

产品管理负责健身房所有可售卖产品套餐的全生命周期管理,包括创建、编辑、上下架、价格管理。产品是订单系统的上游,是会员资格验证的依据。


页面路由

路由页面说明
/products产品列表所有产品套餐列表,支持筛选与排序
/products/new新增产品创建新产品套餐
/products/:id/edit编辑产品编辑已有产品信息

产品列表页

列表字段定义

列名字段 key类型说明排序
产品 IDidString系统唯一标识
产品名称nameString如「月卡」「次卡10次」「新用户体验卡」
产品类型typeEnum月卡 / 季卡 / 年卡 / 次卡 / 体验卡
售价priceDecimal当前售价,元
划线价originalPriceDecimal?展示用划线价;无则显示
有效期durationDaysInt天数;月卡=30,季卡=90,年卡=365
次数timesTotalInt?次卡总次数;不限次显示 不限次
适用门店storeIdString?通用(所有门店可用)/ 门店名称
上架状态isOnSaleBoolean上架中 / 已下架
排序sortOrderInt小程序展示顺序,越小越靠前
已售数量soldCountInt该产品已创建的有效订单数(统计值)
创建时间createdAtDateTimeYYYY-MM-DD HH:mm:ss

产品类型枚举

类型值中文标签说明
monthly月卡有效期内无限次进入
quarterly季卡有效期内无限次进入
yearly年卡有效期内无限次进入
times次卡固定次数,有效期内使用
experience体验卡首次用户限购 1 次,支持条件退款
off_peak闲时卡仅限闲时时段进入,价格低于同时长普通卡

闲时卡设计

闲时卡是一种特殊的产品类型,允许用户以更优惠的价格购买限时时段使用的会员卡。每个门店可以独立配置自己的闲时时段。

闲时卡与普通卡的区别

维度普通卡(月卡/季卡/年卡)闲时卡
进入时段全天可用(或产品级时段限制)仅限门店配置的闲时时段
价格标准价低于同时长普通卡(如月卡 ¥99 → 闲时月卡 ¥59)
闲时时段来源产品级配置(全局统一)门店级配置(每个门店可独立设置闲时时段)
门店配置无需额外配置门店需先在门店管理中配置闲时时段

门店闲时时段配置

门店的闲时时段在门店管理 → 基本信息中配置,属于门店维度的运营配置。

typescript
interface StoreOffPeakConfig {
  storeId: string
  isEnabled: boolean           // 是否启用闲时卡
  offPeakSlots: {              // 闲时时段列表
    dayOfWeek: 1-7             // 周几
    startTime: string          // 如 "06:00"
    endTime: string            // 如 "14:00"
  }[]
}

设计说明:闲时时段由门店维度定义,而非产品维度。原因:不同门店的客流高峰不同,商场店可能下午闲,写字楼店可能上午闲。产品只需标记为「闲时卡」类型,具体时段读取目标门店的配置。

闲时卡产品表单新增字段

字段key类型必填条件显示说明
闲时卡提示文案offPeakHintString仅类型=闲时卡时显示小程序端展示的闲时说明,如「本卡仅限 06:00-14:00 使用」

闲时卡提示文案为多语言字段。若留空,系统根据门店闲时时段自动生成,如「仅限周一至周五 06:00-14:00 可用」。

闲时卡校验规则

  1. 进店校验:用户刷脸进店时,服务端检查当前时间是否在目标门店的闲时时段内。非闲时时段拒绝开门,返回提示「闲时卡仅在 XX:XX-XX:XX 可用」。
  2. 闲时时段变更:门店修改闲时时段后,已售出的闲时卡不受影响(按购买时的时段规则执行),新购买的闲时卡按新时段执行。
  3. 跨门店:闲时卡为通用产品时,各门店的闲时时段可能不同。用户在不同门店使用时,按该门店的闲时时段校验。
  4. 闲时卡购买前提:门店必须已配置闲时时段,小程序端才展示该门店可用的闲时卡产品。未配置闲时时段的门店,闲时卡不展示。

筛选条件

筛选项类型说明
关键词输入框产品名称模糊搜索
产品类型多选月卡 / 季卡 / 年卡 / 次卡 / 体验卡 / 闲时卡
上架状态单选全部 / 上架中 / 已下架
适用门店下拉全部 / 通用 / 指定门店

新增 / 编辑产品页

表单字段

基本信息

字段组件必填校验规则说明
产品名称文本输入2-20 字符如「月卡」「次卡10次」
产品类型单选枚举值月卡/季卡/年卡/次卡/体验卡
售价数字输入≥ 0.01,2 位小数当前售价
划线价数字输入≥ 售价,2 位小数展示用划线价,营造折扣感

有效期与次数

字段组件必填校验规则条件显示
有效期天数数字输入≥ 1始终显示
总次数数字输入≥ 1仅类型=次卡/体验卡时显示
退款窗口(分钟)数字输入≥ 1仅类型=体验卡时显示

[建议值] 体验卡退款窗口默认 30 分钟。

使用限制

字段组件必填校验规则说明
允许进入时段时间范围06:00-22:00;留空=全天可用
适用门店下拉选择通用(所有门店)或选择指定门店

展示配置

字段组件必填校验规则说明
产品描述多行文本≤ 500 字小程序端展示的产品介绍文案
排序权重数字输入≥ 0越小越靠前
是否上架开关新建时默认下架,手动上架

表单交互规则

  1. 产品类型切换时,动态显示/隐藏相关字段(总次数、退款窗口)
  2. 售价修改时,若已有用户购买该产品,需弹出提示:「修改价格不影响已购订单,仅对新订单生效」
  3. 下架操作:已上架产品点击下架时,弹出确认:「下架后新用户将无法在小程序中看到该产品。已购订单不受影响。确认下架?」
  4. 删除限制:已产生订单的产品不允许删除,仅支持下架。无订单的产品可删除。

权限控制

操作老板财务店长客服说明
查看产品列表✅(只读)✅(只读)
新增产品产品创建涉及定价策略,仅总部可操作
编辑产品信息
上架/下架
删除产品无订单的产品才可删除
查看价格历史

产品管理是全局配置,不受门店上下文影响。但可创建门店专属产品。


价格变更记录

每次修改产品售价时,自动记录价格变更历史,供审计和财务分析使用。

价格历史表结构

字段说明
产品 ID关联产品
变更前价格旧价格
变更后价格新价格
操作人管理员账号
变更时间时间戳
备注操作备注(可选)

展示方式:在编辑产品页面底部以时间线形式展示价格变更历史。


小程序展示规则(管理后台侧配置)

配置项说明默认值
体验卡限购每个用户仅可购买 1 次体验卡[建议值] 开启
通用产品优先通用产品排在门店专属产品前面[建议值] 开启
排序规则sortOrder 升序排列升序
划线价展示小程序端是否展示划线价[建议值] 开启

用户故事

US-PRD-01:管理员创建新产品套餐

作为管理员,我想创建一个新的产品套餐,设置名称、类型、价格、有效期,以便在小程序端售卖。

验收标准

  • [ ] 表单校验完整:名称必填、价格 ≥ 0.01、有效期 ≥ 1 天
  • [ ] 产品类型切换时动态显示/隐藏相关字段
  • [ ] 保存后返回产品列表,新记录出现在列表中
  • [ ] 新建产品默认为「已下架」状态
  • [ ] 可选择「保存并上架」一键完成

US-PRD-02:管理员调整产品价格

作为管理员,我想修改现有产品的售价,系统应记录价格变更历史,且不影响已购买用户。

验收标准

  • [ ] 修改价格后,已存在的订单不受影响
  • [ ] 自动生成价格变更记录(变更前/变更后/操作人/时间)
  • [ ] 编辑页底部可查看价格变更历史时间线
  • [ ] 若产品已售出,修改价格时弹出提示

US-PRD-03:管理员下架产品

作为管理员,我想下架某个产品套餐,使新用户无法在小程序看到和购买。

验收标准

  • [ ] 下架操作需二次确认
  • [ ] 下架后小程序端不再展示该产品
  • [ ] 已购买该产品的用户权益不受影响
  • [ ] 下架产品可随时重新上架

US-PRD-04:运营人员查看各产品销售情况

作为运营人员,我想在产品列表中看到各产品的已售数量,以便了解哪些产品更受欢迎。

验收标准

  • [ ] 产品列表展示「已售数量」列
  • [ ] 已售数量 = 该产品所有非 CANCELLED 状态的订单数
  • [ ] 支持按已售数量排序

API 接口规划

# 产品列表
GET /api/v1/admin/products
  Query: { keyword?, type[], isOnSale?, storeId?, sortBy, sortOrder }
  Response: { items: Product[], total: number }

# 产品详情
GET /api/v1/admin/products/:id
  Response: Product { ...全部字段, soldCount: number }

# 创建产品
POST /api/v1/admin/products
  Body: ProductCreateDTO
  Response: Product

# 更新产品
PUT /api/v1/admin/products/:id
  Body: ProductUpdateDTO
  Response: Product

# 上下架切换
PATCH /api/v1/admin/products/:id/sale-status
  Body: { isOnSale: boolean }
  Response: { success: boolean }

# 删除产品(仅无订单时)
DELETE /api/v1/admin/products/:id
  Response: { success: boolean, message: string }

# 价格变更历史
GET /api/v1/admin/products/:id/price-history
  Response: PriceChangeRecord[]

飞创 Fitron 内部规划文档