Web 平台管理模块 — CUJ 关键用户旅程

Platform Administration · Multi-Tenant · Feature Flags · Monitoring | 更新时间: 2026-02-08

TOUCHES 追溯

📄 Pages (15): platform/tenants/page.tsx (租户列表, 800行), platform/tenants/[id]/page.tsx (租户详情), platform/tenants/[id]/backups/page.tsx (备份管理), platform/analytics/page.tsx (平台分析), platform/feature-flags/page.tsx (功能开关), monitoring/dashboard/page.tsx (系统监控), admin/terminals/page.tsx (终端设备管理), admin/checkin/page.tsx (签到主页 → 重定向), admin/checkin/config/page.tsx (签到配置), admin/checkin/queue/page.tsx (签到队列), admin/checkin/stats/page.tsx (签到统计), admin/dashboard/page.tsx (管理后台仪表板), invoices/[id]/page.tsx (发票详情)
🪝 Hooks: useTenants.ts (租户 CRUD + impersonation), useFeatureFlags.ts (功能开关 CRUD)
⚙️ Backend: api/platform/tenants.js (10 endpoints, 723行), api/platform/backups.js (6 endpoints), api/platform/analytics.js (4 endpoints), api/platform/feature-flags.js (5 endpoints, 318行), api/platform/index.js (入口 + settings), api/tenant-activate.js (公共激活), api/checkin-config.js, monitoring/index.js (MetricsCollector + HealthMonitor + AlertManager), services/tenant/tenant-service.js, services/tenant/backup-service.js, services/audit/tenant-audit.js

架构概览

多租户平台架构

flowchart TD
    PA["platform_superadmin"] --> PM["Platform Management"]
    PM --> TM["Tenant CRUD"]
    PM --> FF["Feature Flags"]
    PM --> AN["Platform Analytics"]
    PM --> MO["System Monitoring"]

    TM --> T1["Create Tenant → Schema"]
    TM --> T2["Suspend / Restore"]
    TM --> T3["Schedule Deletion (30d)"]
    TM --> T4["Switch Context (Impersonate)"]
    TM --> T5["Backup / Restore"]

    FF --> FF1["Global Enable/Disable"]
    FF --> FF2["Target Tenants (array)"]
    FF --> FF3["Rollout % (0-100)"]

    MO --> MO1["CPU / Memory / Uptime"]
    MO --> MO2["HTTP Performance"]
    MO --> MO3["DB Performance"]
    MO --> MO4["Circuit Breakers"]
    MO --> MO5["Alerts (SES)"]

    style PA fill:#9c27b0,stroke:#7b1fa2,color:#fff
    style PM fill:#2196F3,stroke:#1565C0,color:#fff

租户生命周期

stateDiagram-v2
    [*] --> pending : POST /tenants (创建)
    pending --> active : POST /activate (Token 激活, 7天有效)
    active --> suspended : POST /suspend (带原因)
    suspended --> active : POST /restore
    active --> pending_deletion : POST /schedule-deletion (30天宽限)
    suspended --> pending_deletion : POST /schedule-deletion
    pending_deletion --> active : POST /restore (撤销删除)
    pending_deletion --> deleted : DELETE /delete (确认码 DELETE-shortId)
    deleted --> [*]

租户套餐对比

属性trialstandardprofessionalenterprise
存储配额5 GB10 GB50 GB100 GB
门店数限制1310无限
备份策略手动手动+定时手动+定时手动+定时+预删除

访问控制

⚠️ 所有 /api/platform/* 端点均需要:
1. JWT 认证 (authenticateToken())
2. 平台管理员身份 (requirePlatformAdmin())
platform_superadmin 角色可访问。
例外: GET /api/platform/health 为公共健康检查端点。

目录

CUJ 总览与优先级矩阵

CUJ优先级描述触发点业务价值E2E 状态
N1 P0 租户管理全生命周期 Platform → Tenants SaaS 核心 — 租户入驻/退出 部分覆盖
N2 P1 租户上下文切换 租户列表 → Switch 运维支持 — 代客排查问题 缺失
N3 P1 租户备份与恢复 租户详情 → Backups 数据安全 — 灾难恢复 缺失
N4 P1 功能开关管理 Platform → Feature Flags 灰度发布 — 渐进式推出新功能 缺失
N5 P2 平台分析仪表板 Platform → Analytics 全局洞察 — 租户/存储/健康概览 缺失
N6 P1 系统监控与告警 Monitoring → Dashboard 可靠性 — 实时系统健康状态 缺失
N7 P1 签到系统配置与管理 Admin → Checkin Kiosk/终端运营配置 缺失

CUJ-N1: 租户管理 — 创建/激活/暂停/删除

P0 SaaS 核心 — 租户全生命周期管理

TOUCHES: platform/tenants/page.tsx (800行), platform/tenants/[id]/page.tsx, api/platform/tenants.js (10 endpoints), api/tenant-activate.js, services/tenant/tenant-service.js

BDD 场景

场景 N1.1: 创建新租户

Given 用户已登录并拥有对应功能所需权限与范围(scope)
When/platform/tenants 点击"新建租户"
  And 填写: 名称、联系人姓名/邮箱/电话、套餐类型(standard)
Then POST /api/platform/tenants 创建
  And 生成 short_id (≤12 位) 用于 URL 和 Schema 命名
  And 创建 PostgreSQL Schema: tenant_{short_id}
  And 生成激活 Token (7 天有效)
  And 发送激活邮件给联系人

场景 N1.2: 租户管理员激活账户

Given 用户已登录并拥有对应功能所需权限与范围(scope),收到激活邮件
When 点击激活链接 → GET /api/tenants/activate?token=xxx
Then 验证 Token 有效性
When 设置密码 (≥8 位) → POST /api/tenants/activate
Then 账户激活,租户状态 → active
  And 可以登录管理后台
限流保护: 验证链接 10 次/小时,激活操作 5 次/小时

场景 N1.3: 暂停和恢复租户

Given 租户 "Salon ABC" 欠费
When 用户暂停租户并输入原因
Then POST /api/platform/tenants/:id/suspend
  And 状态 → suspended,记录 suspended_at
  And 该租户所有用户无法登录
When 恢复租户
Then 状态 → active,数据完整恢复

场景 N1.4: 计划删除(30 天宽限期)

Given 租户请求注销
When 用户计划删除
Then 状态 → pending_deletion
  And 记录 deletion_scheduled_at
  And 30 天内可通过 POST /restore 撤销
When 30 天后确认永久删除
  And 输入确认码: DELETE-{shortId}
Then 永久删除租户 Schema + 所有数据

CUJ-N2: 租户上下文切换(代入操作)

P1 运维支持 — 以租户身份登录排查问题

TOUCHES: POST /api/platform/tenants/:id/switch, useTenants.switchToTenant(), services/audit/tenant-audit.js

BDD 场景

场景 N2.1: 切换到租户上下文

Given 用户已登录并拥有对应功能所需权限与范围(scope),在租户列表
When 点击 "Switch" 按钮
Then POST /api/platform/tenants/:id/switch 生成临时 JWT (1 小时有效)
  And JWT 包含租户上下文(可访问该租户数据)
  And 审计日志记录 SWITCH_TENANT 事件
  And 界面切换到该租户的管理后台视图

CUJ-N3: 租户备份与恢复

P1 数据安全 — 手动/定时备份,灾难恢复

TOUCHES: platform/tenants/[id]/backups/page.tsx, api/platform/backups.js (6 endpoints), services/tenant/backup-service.js

备份类型

类型触发方式说明
manual管理员手动随时可创建,带描述
scheduled定时任务按策略自动执行
pre_deletion计划删除时删除前自动备份

BDD 场景

场景 N3.1: 创建手动备份

Given 租户详情页 → Backups Tab
When 点击"创建备份",输入描述 "迁移前备份"
Then POST /api/platform/tenants/:id/backups
  And 备份状态流转: pending → in_progress → completed
  And 记录文件大小 (MB)、开始/完成时间

场景 N3.2: 从备份恢复

Given 一个 completed 状态的备份
When 点击"Restore" → 确认
Then POST /api/platform/tenants/:id/backups/:backupId/restore
  And 租户数据恢复到备份时间点
  And 审计日志记录恢复事件

CUJ-N4: 功能开关管理

P1 灰度发布 — 渐进式推出新功能给特定租户

TOUCHES: platform/feature-flags/page.tsx, api/platform/feature-flags.js (5 endpoints), useFeatureFlags.ts

功能开关模型

字段类型说明
flag_keyvarchar(100)代码引用标识 (unique)
namestring显示名称
enabledboolean全局开关
target_tenantstext[]指定租户 short_id 列表
rollout_percent0-100百分比灰度

BDD 场景

场景 N4.1: 创建功能开关并灰度发布

Given 用户已登录并拥有对应功能所需权限与范围(scope),在 /platform/feature-flags
When 创建开关: key="loyalty_v2", name="忠诚度 V2"
  And 设置 target_tenants=["spa001", "salon002"]
  And enabled=true, rollout_percent=0
Then 仅 spa001 和 salon002 两个租户能看到新功能
  And 其他租户不受影响

场景 N4.2: 渐进式全量推出

Given 功能开关 "loyalty_v2" 已在 2 个租户验证
When 清空 target_tenants,设置 rollout_percent=25
Then 25% 的租户随机启用该功能
When 逐步提升到 50% → 100%
Then 全部租户启用
  And 缓存在 flag 更新时自动失效

场景 N4.3: 检查某租户的开关状态

Given 功能开关 "loyalty_v2" 存在
When 调用 GET /api/platform/feature-flags/check/loyalty_v2?tenantId=spa001
Then 返回: enabled=true/false + 原因 (targeted/rollout/global/disabled)

CUJ-N5: 平台分析仪表板

P2 全局洞察 — 租户状态、存储、健康概览

TOUCHES: platform/analytics/page.tsx, GET /api/platform/analytics/* (4 endpoints)

BDD 场景

场景 N5.1: 查看平台概览

Given 用户已登录并拥有对应功能所需权限与范围(scope),导航到 /platform/analytics
When 页面加载
Then Overview 卡片显示: 各状态租户数 (active/suspended/pending_deletion)
  And 套餐分布图 (trial/standard/professional/enterprise)
  And 存储使用汇总: 总已用/总配额/百分比
  And 备份统计
  And 审计日志: 总事件数、违规数
  And 每租户对比表格
  And 系统健康状态
  And 趋势图表

CUJ-N6: 系统监控与告警

P1 可靠性 — 实时系统指标、组件健康、告警管理

TOUCHES: monitoring/dashboard/page.tsx, monitoring/index.js, GET /api/monitoring/* (metrics/health/performance/alerts/components)

监控组件

组件指标
MetricsCollectorCPU、内存、运行时间 (60s 采集间隔)
HealthMonitor数据库连接、API 状态 (30s 检查间隔)
PerformanceTrackerHTTP 请求数/平均时长/慢请求/状态码分布
PerformanceTrackerDB 查询数/平均时长/慢查询 (>100ms)
AlertManager告警列表 + SES 邮件渠道
CircuitBreakerRegistry/api/monitoring/components — 所有熔断器状态

BDD 场景

场景 N6.1: 查看系统监控仪表板

Given 用户已登录并拥有对应功能所需权限与范围(scope),导航到 /monitoring/dashboard
When 页面加载
Then 显示系统指标: CPU 使用率、内存使用、运行时间
  And 组件健康: 数据库状态、API 状态
  And HTTP 性能: 总请求、平均时长、慢请求数、状态码分布
  And 数据库性能: 查询数、平均时长、慢查询
  And 实时告警列表

场景 N6.2: 告警触发

Given CPU 使用率超过 90% 持续 5 分钟
When AlertManager 检测到阈值突破
Then 创建告警记录
  And 通过 SES 发送邮件给 ALERT_EMAIL_RECIPIENTS
  And 仪表板实时显示新告警
  And 冷却期 300s 内不重复告警

CUJ-N7: 签到系统配置与管理

P1 Kiosk 运营 — 签到配置、队列管理、终端管理

TOUCHES: admin/checkin/config/page.tsx, admin/checkin/queue/page.tsx, admin/checkin/stats/page.tsx, admin/terminals/page.tsx, api/checkin-config.js

签到配置项

分组配置说明
欢迎消息welcome_message_en / _zh双语欢迎语
功能开关walk_in_enabled允许 Walk-in
qr_enabledQR 扫码签到
phone_enabled手机号签到
auto_assign_enabled自动分配技师
sound_enabled签到提示音
促销promotional_messages签到屏幕显示的促销信息

BDD 场景

场景 N7.1: 配置签到系统

Given 用户已登录并拥有对应功能所需权限与范围(scope),在 /admin/checkin/config
When 修改欢迎消息、启用 QR 签到、关闭 Walk-in
  And 保存
Then Kiosk 终端实时反映新配置
  And 签到页面不再显示 Walk-in 选项

场景 N7.2: 管理签到队列

Given 用户已登录并拥有对应功能所需权限与范围(scope),在 /admin/checkin/queue
When 查看当前排队
Then 显示所有等待中的签到: 客户名、签到时间、等待时长、预约状态
  And 可手动标记完成/取消

场景 N7.3: 管理终端设备

Given 用户已登录并拥有对应功能所需权限与范围(scope),在 /admin/terminals
When 创建终端并关联到门店
Then 终端注册成功,可以部署 Kiosk App
  And 按门店分组显示所有终端

跨模块链接

关联模块关联点说明
CUJ-A (Auth) platform_superadmin 角色 仅此角色可访问 /platform/* 端点
CUJ-L (Stores) 门店配额限制 checkEntityLimit 根据租户套餐限制门店/员工/服务数量
CUJ-G (Booking) 签到系统 + 终端 admin/checkin 配置影响 Kiosk/Terminal 签到行为
CUJ-J (Settings) 平台级设置 /api/platform/settings 管理全局配置

业务规则

#规则实现位置
1 Schema 隔离: 每个租户独立 PostgreSQL Schema (tenant_{short_id}),数据完全隔离 tenant-service.createTenant()
2 激活 Token: 7 天有效,验证限流 10 次/小时,激活限流 5 次/小时 api/tenant-activate.js
3 删除确认码: 格式 DELETE-{shortId},防止误操作 DELETE /api/platform/tenants/:id/delete
4 Impersonation 审计: 每次上下文切换记录审计日志 (SWITCH_TENANT 事件),临时 JWT 1 小时有效 tenant-audit.js
5 功能开关优先级: enabled=false → 全部关闭;target_tenants 非空 → 仅指定租户;否则按 rollout_percent 灰度 feature-flags.js
6 监控配置: 指标采集 60s,健康检查 30s,最大指标 1000 条,最大告警 500 条,冷却期 300s monitoring/index.js
7 平台数据在 public schema: tenants、feature_flags、platform_settings 等表存储在 public schema,非租户 schema platformDb 数据访问层