Skip to content

管理后台门店上下文系统

涉及子系统:管理后台(核心)、云端 API(参数透传)
核心业务:在管理后台顶部提供全局门店切换器,切换为单店模式后,受影响的功能页面自动追加该门店的数据筛选范围


系统概述

健身房系统支持多门店运营。管理后台提供两种数据视角:

模式说明
全体店模式(默认)数据跨所有门店汇总展示,不限定门店范围
单店模式顶部选择某一门店后,受影响的页面自动在查询中附加该门店的筛选条件

门店上下文是一个全局状态,保存在前端应用的全局 Store(如 Pinia / Vuex)中,页面切换时保持不变,刷新后可从 localStorage 恢复。


UI 设计

门店切换器位置

门店切换器位于管理后台顶部导航栏右侧,始终可见。

┌─────────────────────────────────────────────────────┐
│  Logo   菜单项...                 [🏪 全体店 ▼]  👤  │
└─────────────────────────────────────────────────────┘

点击后展开下拉菜单:

┌──────────────┐
│ ✓ 全体店     │
│   朝阳门店   │
│   西二旗门店 │
│   ...        │
└──────────────┘

单店模式视觉标识

选中某门店后,切换器显示该门店名称,并在顶部导航栏增加一条醒目的颜色条(如橙色),提示当前处于单店筛选模式,避免管理员误以为在查看全量数据。

┌─────────────────────────────────────────────────────┐
│  当前视图:朝阳门店                                   │  ← 橙色提示条
├─────────────────────────────────────────────────────┤
│  Logo   菜单项...             [🏪 朝阳门店 ▼]  👤   │
└─────────────────────────────────────────────────────┘

受影响的功能模块

以下功能模块在单店模式下,会自动在数据请求中附加当前门店的筛选条件(store_id 参数),无需用户在每个页面手动选择门店:

功能模块自动追加筛选的数据范围
订单列表 / 订单详情仅展示该门店产生的订单
用户列表 / 会员管理仅展示在该门店注册或有消费记录的用户
门禁事件日志仅展示该门店的门禁事件
硬件控制面板仅展示该门店的硬件设备
数据分析 / 经营报表仅统计该门店的数据
优惠券核销记录仅展示该门店的核销记录
外部券码核销记录仅展示该门店的核销记录
淋浴使用记录仅展示该门店的淋浴使用记录

不受门店上下文影响的功能

以下功能属于全局配置,不跟随门店上下文切换:

功能模块原因
系统账号 / 角色权限管理属于平台级配置
产品/套餐配置套餐通常全局共享,若有门店差异则单独处理
优惠券模板管理优惠券模板为全局配置,发放记录受门店影响

前端实现

全局状态结构

typescript
interface StoreContext {
  mode: 'all' | 'single'   // 当前模式
  storeId: string | null   // 单店模式下的门店 ID,全体店模式为 null
  storeName: string | null // 单店模式下的门店名称,用于 UI 展示
}

API 请求拦截器

在 HTTP 请求拦截器中,自动将当前门店上下文注入到受影响接口的请求参数中:

typescript
// 请求拦截器
axios.interceptors.request.use((config) => {
  const storeContext = useStoreContextStore()
  if (storeContext.mode === 'single' && storeContext.storeId) {
    // 仅对受影响的接口路径追加 store_id
    if (isStoreContextAwareApi(config.url)) {
      config.params = { ...config.params, store_id: storeContext.storeId }
    }
  }
  return config
})

通过维护一个受影响接口路径白名单isStoreContextAwareApi)来控制哪些接口自动追加门店筛选,避免对全局接口产生副作用。

本地持久化

门店上下文持久化到 localStorage,key 为 admin_store_context,页面刷新后自动恢复上次选择的门店。


后端 API 层

受影响的查询接口需支持可选的 store_id 参数:

  • 传入 store_id:仅返回该门店数据
  • 不传 store_id(或传 null):返回所有门店数据(即全体店模式)

后端无需感知"全体店/单店"概念,仅需处理 store_id 是否存在的过滤逻辑。


权限约束

角色可选门店范围
超级管理员所有门店 + 全体店
门店管理员仅限其被授权的门店,无全体店选项

门店管理员登录后,门店切换器默认且锁定为其所属门店,不允许切换至其他门店或全体店视图。


待确认事项

  • [ ] 门店列表的数据来源:是否有独立的"门店管理"模块维护门店信息
  • [ ] 套餐/产品是否存在门店差异,若有则产品配置页也需纳入受影响模块
  • [ ] 门店管理员的权限边界(是否可以看到跨店用户信息)

健身房服务系统内部规划文档