主题
管理后台 — 会员管理
上级文档:管理后台 Web
用户管理(会员)
会员列表
| 列 / 区块 | 字段说明 | 枚举 / 备注 |
|---|---|---|
| 会员 ID | 系统内用户/会员唯一标识 | 列表主键 |
| 昵称 / 姓名 | 展示名与真实姓名(按产品口径二选一或并列) | 旁显示性别图标;角色(如普通会员、员工等,与权限枚举对齐) |
| 状态 | 当前会员卡是否可用 | 有效的卡 | 已过期(无有效卡时归为已过期或单独「无卡」,与产品统一) |
| 累计消费金额 | 历史实付累计 | 数字 + 货币单位;统计口径与财务/订单一致 |
| 绑定 | 各绑定项是否完成 | 人脸、微信、实名验证、大学生认证 — 以图标或标签展示已绑定/未绑定/审核中 |
| 操作 | 行内或下拉 | 发卡(办理/关联卡产品,与产品管理中卡类型联动);编辑信息(见下「编辑信息」);进店记录(抽屉或页内展示进店/离店时间线,与门店设备日志对齐);消费记录(跳转订单/核销列表并预筛该会员) |
编辑信息
可修改项如下(保存前校验权限与审计日志,与角色矩阵一致):
| 分组 | 字段 / 能力 | 说明 |
|---|---|---|
| 基础资料 | 姓名 | 与实名信息策略一致时可能只读或需复核 |
| 性别 | ||
| 生日 | ||
| 来源渠道 | 获客渠道枚举(与运营投放/注册来源主数据对齐) | |
| 人脸管理 | 人脸绑定状态、录入/重录、删除 | 与列表「绑定-人脸」一致;删除需符合合规与日志要求 |
| 会员卡管理 | 手动开通 / 关闭 | 对当前有效卡或指定卡产品执行启用/停用;与「发卡」「状态」联动 |
列表层仍可保留搜索、筛选(如按门店、状态、绑定项、注册时间),与会员列表列字段对齐;用户详情可作为只读总览页,或与「编辑信息」合并为同一详情子路由。
店长视角:列表与导出范围仅包含归属本店的会员(与云端「门店—会员归属」数据模型一致;不在本店归属内的用户不可见)。客服等跨店角色按账号权限放开门店筛选后可见多店数据。
会员详情页 Tab 权限设计
会员详情页同样采用多级 Tab 架构,遵循 详情页 Tab 权限分层策略。核心原则:分店店长聚焦于会员的运营数据,平台级账号信息与绑定管理集中在总部专属 Tab。
Tab 权限矩阵
| Tab | 老板 | 财务 | 店长(本店) | 客服 | 说明 |
|---|---|---|---|---|---|
| 会员概览 | ✅ | ✅ | ✅ | ✅ | 基本信息摘要、会员卡状态、累计消费、最近到访 |
| 消费记录 | ✅ | ✅ | ✅(本店) | ✅ | 订单/核销/退款历史 |
| 到访记录 | ✅ | ✅ | ✅(本店) | ✅ | 进店/离店时间线,与门店设备日志对齐 |
| 会员卡管理 | ✅ | ❌ | ✅(本店发卡) | ❌ | 店长可为本店会员办理/续期卡产品 |
| 人脸管理 | ✅ | ❌ | ✅ | 按策略 | 录入/重录/删除人脸(需操作日志) |
| 账号与绑定 | ✅ | ❌ | ❌ | ❌ | 总部专属:微信绑定状态、解绑操作、openID、UID、实名信息、大学生认证等 |
设计依据
- 「账号与绑定」设为总部专属:微信 openID、系统 UID 等属于平台级账号标识,分店店长的日常运营不需要接触这些信息;解绑微信等操作涉及用户在全平台的身份关联,需由总部统一管控,避免分店误操作影响用户跨店使用。
- 人脸管理开放给店长:人脸录入/重录是门店现场操作,需要店长或店员在用户到店时当场完成;但删除操作需留审计日志。
- 消费/到访记录按门店上下文过滤:店长仅看到该会员在本店的消费与到访记录,不可跨店查看(由云端
store_id参数控制)。
「账号与绑定」Tab 内字段
| 分组 | 字段 | 说明 |
|---|---|---|
| 微信绑定 | 绑定状态(已绑定/未绑定) | 展示 + 解绑操作 |
| openID | 用户在小程序的唯一标识 | |
| unionID | 如接入开放平台 | |
| 系统标识 | 用户 UID | 系统内唯一 ID |
| 注册来源 | 来源渠道枚举 | |
| 注册时间 | ||
| 实名信息 | 实名验证状态 | 已实名 / 未实名 / 审核中 |
| 大学生认证状态 | 已认证 / 未认证(若业务支持) |
用户标签体系
标签定义
用户标签用于对会员进行分类和画像,支持手动标注和系统自动标注。标签是后续营销中心用户画像和精准推送的基础数据。
typescript
interface UserTag {
id: string
name: string // 标签名称,如「高价值用户」「活跃用户」「退款用户」
category: 'manual' | 'auto' // 手动标签 / 自动标签
color?: string // 标签颜色(前端展示用)
description?: string // 标签描述
createdBy?: string // 手动标签的创建人
autoRule?: TagAutoRule // 自动标签的触发规则
}自动标签规则
| 自动标签 | 触发条件 | 说明 |
|---|---|---|
| 高消费用户 | 累计消费 ≥ [阈值] | [建议值] ≥ ¥500 |
| 活跃用户 | 近 30 天到店 ≥ [阈值] 次 | [建议值] ≥ 8 次 |
| 沉睡用户 | 近 60 天未到店 | 有历史到店记录但近期不活跃 |
| 退款用户 | 历史上有退款记录 | 标记后持续保留 |
| 多次退款 | 退款次数 ≥ [阈值] | [建议值] ≥ 2 次,可能需要关注 |
| 体验卡未转化 | 购买体验卡后 30 天内未续费 | 可作为营销触达对象 |
| 周末用户 | 近 30 天到店中 ≥ 70% 在周末 | 偏好周末锻炼 |
| 工作日用户 | 近 30 天到店中 ≥ 70% 在工作日 | 偏好工作日锻炼 |
| 晨练用户 | 近 30 天到店中 ≥ 70% 在 6:00-9:00 | 偏好晨练 |
| 夜练用户 | 近 30 天到店中 ≥ 70% 在 20:00-23:00 | 偏好夜练 |
自动标签由系统定时任务每日凌晨批量计算更新。运营也可在管理后台手动创建自定义标签规则。
标签管理页面
| 功能 | 说明 |
|---|---|
| 标签列表 | 查看所有标签(手动 + 自动),按类别分组 |
| 新建标签 | 创建手动标签或自动标签 |
| 编辑标签 | 修改标签名称、颜色、描述、自动规则 |
| 删除标签 | 删除标签后,从所有用户上移除该标签 |
| 标签统计 | 每个标签下有多少用户 |
会员列表 — 标签筛选
会员列表的筛选条件中新增标签筛选维度:
| 筛选项 | 类型 | 说明 |
|---|---|---|
| 用户标签 | 多选 | 选择一个或多个标签进行筛选。多标签默认 OR 关系(满足任一标签即命中);切换为 AND 模式(需同时拥有所有选中标签) |
会员列表中每行用户信息旁展示该用户的标签(最多显示 3 个,点击展开全部)。
会员详情 — 标签管理
在会员详情页「会员概览」Tab 中增加标签区块:
| 功能 | 说明 |
|---|---|
| 查看标签 | 展示该用户当前拥有的所有标签,区分手动/自动 |
| 手动打标 | 搜索并添加标签(从标签库中选择) |
| 移除标签 | 移除手动标签(自动标签不可手动移除,由系统自动计算) |
标签权限
| 操作 | 老板 | 财务 | 店长 | 客服 |
|---|---|---|---|---|
| 查看标签库 | ✅ | ✅ | ✅ | ✅ |
| 创建/编辑/删除标签 | ✅ | ❌ | ❌ | ❌ |
| 按标签筛选会员 | ✅ | ✅ | ✅ | ✅ |
| 给会员手动打标 | ✅ | ❌ | ✅ | ✅ |
| 移除手动标签 | ✅ | ❌ | ✅ | ✅ |
内控模型与风险用户管控
设计目标
通过系统化的内控模型,自动识别和管理有潜在风险的用户,保障门店正常运营秩序和财产安全。
风险等级定义
| 等级 | 标签 | 颜色 | 说明 | 自动触发 |
|---|---|---|---|---|
| 低风险 | risk_low | 🟢 绿色 | 有轻微异常行为,仅观察 | — |
| 中风险 | risk_medium | 🟡 黄色 | 多次异常行为,需要关注 | ✅ |
| 高风险 | risk_high | 🔴 红色 | 严重违规或高度可疑,需立即处理 | ✅ |
| 黑名单 | blacklist | ⚫ 黑色 | 确认违规,限制门店使用权限 | ✅ |
风险评估维度
系统综合以下维度自动计算用户风险分:
| 维度 | 权重 | 评估逻辑 |
|---|---|---|
| 退款频率 | 高 | 近 90 天退款次数 / 订单数。退款率 ≥ 50% 且退款次数 ≥ 2 → 高风险 |
| 退款金额 | 中 | 近 90 天退款总额 / 消费总额。退款金额占比 ≥ 80% → 高风险 |
| 退款后重新购买 | 高 | 退款后 7 天内再次购买同类产品(薅羊毛特征) |
| 体验卡使用 | 中 | 购买多个不同手机号的体验卡进入同一门店(需配合 IP/设备指纹分析) |
| 投诉频率 | 中 | 近 90 天客诉次数。≥ 3 次投诉 → 中风险 |
| 异常进出行为 | 中 | 短时间内频繁进出(如 1 小时内进出 ≥ 3 次) |
| 多账号关联 | 高 | 同一设备/IP/手机号关联多个账号 |
风险分计算
typescript
interface RiskScore {
userId: string
totalScore: number // 0-100,越高越危险
riskLevel: 'low' | 'medium' | 'high'
dimensions: {
refundFrequency: { score: number, detail: string }
refundAmountRatio: { score: number, detail: string }
refundRebuy: { score: number, detail: string }
experienceAbuse: { score: number, detail: string }
complaintFrequency: { score: number, detail: string }
abnormalAccess: { score: number, detail: string }
multiAccount: { score: number, detail: string }
}
evaluatedAt: DateTime
}等级阈值(运营可配置):
| 等级 | 分值范围 |
|---|---|
| 低风险 | 0 - 29 |
| 中风险 | 30 - 59 |
| 高风险 | 60 - 89 |
| 黑名单 | 90 - 100(或手动加入) |
风险用户管控操作
| 操作 | 说明 | 适用等级 |
|---|---|---|
| 查看风险评估 | 查看该用户的风险分、各维度评分、触发原因 | 全部 |
| 加入观察名单 | 标记为关注对象,后续行为变更时通知管理员 | 低风险 / 中风险 |
| 限制退款 | 该用户后续退款申请需总部审批,店长/客服不可直接退款 | 中风险 / 高风险 |
| 限制体验卡购买 | 禁止该用户再次购买体验卡 | 高风险 |
| 加入黑名单 | 冻结开门权限 + 禁止购买任何产品 | 高风险(手动操作) |
| 移出黑名单 | 解除所有限制,风险分重置为 0 | 黑名单(手动操作) |
风险管理 Tab(会员详情页)
在会员详情页新增「风险与管控」Tab:
| Tab | 老板 | 财务 | 店长 | 客服 |
|---|---|---|---|---|
| 风险与管控 | ✅ | ✅(只读) | ✅(只读+观察名单) | ✅(只读) |
操作权限:加入黑名单/移出黑名单仅 boss 可操作。店长可将用户加入观察名单。所有角色均可查看风险信息。
风险用户列表
在会员列表中,可通过「风险等级」筛选维度快速定位风险用户:
| 筛选项 | 类型 | 说明 |
|---|---|---|
| 风险等级 | 多选 | 全部 / 低风险 / 中风险 / 高风险 / 黑名单 |
| 观察名单 | 开关 | 是否在观察名单中 |
权限:风险等级筛选仅 boss/finance 可见。店长和客服默认不展示风险等级列(除非加入观察名单的用户,店长可见「观察中」标记)。
风险通知
| 事件 | 通知方式 | 通知对象 |
|---|---|---|
| 用户风险等级升级 | 管理后台站内通知 + 飞书消息 | boss / finance |
| 用户进入高风险 | 管理后台站内通知 | boss / finance |
| 黑名单用户尝试进店 | 管理后台告警 + 门店设备日志 | boss / 店长 |
| 观察名单用户行为变更 | 管理后台站内通知 | 加入观察名单的管理员 |
API 接口规划
text
# 标签管理
GET /api/v1/admin/tags
POST /api/v1/admin/tags
PUT /api/v1/admin/tags/:id
DELETE /api/v1/admin/tags/:id
# 用户标签
GET /api/v1/admin/users/:id/tags
POST /api/v1/admin/users/:id/tags # 手动打标
DELETE /api/v1/admin/users/:id/tags/:tagId # 移除手动标签
# 风险评估
GET /api/v1/admin/users/:id/risk-assessment
Response: RiskScore
# 风险管控操作
POST /api/v1/admin/users/:id/risk-control
Body: { action: 'watch' | 'restrict_refund' | 'restrict_experience'
| 'blacklist' | 'unblacklist', reason: string }
# 风险用户列表
GET /api/v1/admin/users/risk-list
Query: { riskLevel?, isWatched?, page?, pageSize? }