简介
本开发文档面向DouPHP会员等级系统的开发者,围绕“等级定义、升级条件、等级权益、自动升级机制、积分转换规则、有效期管理、差异化服务与专属功能、折扣优惠实现”等主题进行系统化说明。同时提供新增等级、设置升级条件、实现等级特权、等级变更通知、统计报表与数据分析的落地方案与代码级指引。
项目结构
会员等级体系由“用户资料查询层、等级数据模型、后台管理控制器与服务、VIP套餐与有效期引擎、事件驱动升级”等模块组成。关键路径如下:
- 用户资料与等级读取:UserProfileQuery、UserService
- 等级数据模型与日志:UserLevel、UserLevelLog
- 后台等级管理:LevelController
- VIP套餐与有效期:VipService(核心)、VipStatus(状态枚举)
- 后台VIP记录:VipService(后台)、VipController(后台)、Vip(模型)
graph TB
subgraph "用户与等级"
UQ["UserProfileQuery"]
US["UserService"]
UL["UserLevel(模型)"]
ULL["UserLevelLog(模型)"]
end
subgraph "VIP与有效期"
VS["VipService(核心)"]
VSS["VipService(后台)"]
VC["VipController(后台)"]
VM["Vip(模型)"]
VSU["VipStatus"]
end
subgraph "后台管理"
LC["LevelController"]
end
UQ --> US
US --> UL
LC --> UL
LC --> ULL
VS --> VM
VSS --> VC
VC --> VSS
VS --> VSU
核心组件
- 用户等级读取与展示
- UserProfileQuery:提供当前等级解析、等级名称获取、用户资料格式化;在启用 user 模块且存在 user_level 表时生效。
- UserService:对外暴露 levelName/currentLevel/format 等方法,屏蔽底层细节。
- 等级数据模型
- UserLevel:维护等级元数据(名称、升级方式、升级条件、商品折扣、图标等),并提供排序与名称互查方法。
- UserLevelLog:记录等级变动日志(旧等级、新等级、触发条件值、时间等)。
- VIP套餐与有效期
- VipService(核心):监听订单支付成功场景,幂等地为用户授予或顺延VIP有效期,写入vip表并记录订单号、价格、时间等。
- VipStatus:将VIP生命周期抽象为三态(生效中/已过期/无记录),供前端与业务判断。
- 后台管理
- LevelController:等级列表、创建、编辑、删除入口,调用LevelService完成数据组装与持久化。
- 后台VIP服务与控制器:提供VIP购买记录的筛选、分页、删除与批量操作。
架构总览
会员等级体系采用“读模型+写模型+事件驱动”的分层设计:
- 读模型:UserProfileQuery负责等级名称与当前等级解析,UserService统一对外接口。
- 写模型:UserLevel/UserLevelLog承载等级配置与变更记录;VIP授予逻辑通过VipService在订单支付成功后执行。
- 事件驱动:VipService实现SceneHandler,监听ORDER_PAID场景,确保幂等授予VIP。
- 后台管理:LevelController与VIP后台控制器提供可视化配置与运维能力。
sequenceDiagram
participant 订单 as "订单系统"
participant 场景 as "场景派发器"
participant 服务 as "VipService(核心)"
participant 数据库 as "vip/vip_package/order"
participant 状态 as "VipStatus"
订单->>场景 : 订单支付成功(ORDER_PAED)
场景->>服务 : handle(scene, payload)
服务->>数据库 : 校验order_sn幂等
服务->>数据库 : 查询vip_package(day)
服务->>数据库 : 查询最近有效VIP(end_at)
服务->>数据库 : 计算start_at/end_at并插入vip
服务-->>场景 : 返回是否新建记录
场景-->>订单 : 处理完成
Note over 状态,服务 : 前端/业务通过VipStatus判断active/expired/none
详细组件分析
用户等级读取与展示(UserProfileQuery / UserService)
- 等级名称:当启用user模块且存在user_level表时,按level_id取name,否则回退到默认文案。
- 当前等级:根据user.level_id取出对应等级的id与good_discount,未开启或未登录返回null。
- 用户资料格式化:补齐username/avatar,合并默认联系人快照,便于模板/API使用。
flowchart TD
Start(["进入 currentLevel"]) --> CheckCfg{"启用user模块?"}
CheckCfg --> |否| ReturnNull["返回 null"]
CheckCfg --> |是| GetLevelId["读取 user.level_id"]
GetLevelId --> HasLevel{"存在等级ID?"}
HasLevel --> |否| ReturnNull
HasLevel --> |是| QueryLevel["查询 user_level(id, good_discount)"]
QueryLevel --> ReturnLevel["返回等级信息"]
等级数据模型与日志(UserLevel / UserLevelLog)
- UserLevel:维护等级元数据(名称、升级方式、升级条件、商品折扣、图标),支持按id升序全量列表、名称互查。
- UserLevelLog:记录等级变更(old/new level、condition_value、upgrade_type、created_at),支持按用户与升级方式筛选。
classDiagram
class UserLevel {
+string name
+string upgrade_type
+float upgrade_condition
+int good_discount
+string icon
+datetime created_at
+selectAllOrdered() array
+getNameById(levelId) mixed
+getLevelIdByName(name) int
}
class UserLevelLog {
+int id
+int user_id
+int old_level_id
+int new_level_id
+float condition_value
+datetime created_at
+filterByUserId(query, userId) Builder
+filterByUpgradeType(query, type) Builder
}
UserLevel <.. UserLevelLog : "关联等级变更"
后台等级管理(LevelController)
- 提供等级列表、创建、编辑、删除入口,表单参数经LevelFormRequest校验后交由服务层处理。
- 页面动作包含跳转到等级日志与会员中心,便于运营查看与联动。
VIP套餐与有效期(VipService / VipStatus)
- 事件监听:仅对ORDER_PAID场景且item.module=vip_package进行处理。
- 幂等授予:以order_sn为唯一键避免重复落库。
- 有效期顺延:若上次VIP未到期则从其end_at顺延,否则从当前时间起算;end_at为datetime字符串,需转时间戳比较。
- 状态判定:VipStatus将VIP生命周期抽象为active/expired/none,供前端展示与续费提示。
sequenceDiagram
participant 订单 as "订单系统"
participant 场景 as "场景派发器"
participant 服务 as "VipService.grant"
participant 包 as "vip_package"
participant 历史 as "vip(最近有效)"
participant 存储 as "vip(插入)"
订单->>场景 : ORDER_PAID(payload)
场景->>服务 : handle(...)
服务->>服务 : 校验order_sn幂等
服务->>包 : 查询day
服务->>历史 : 查询最近completed记录
服务->>服务 : 计算start_at/end_at
服务->>存储 : 插入vip记录(order_status=completed)
服务-->>场景 : 返回是否新建
后台VIP记录(VipService后台 / VipController / Vip模型)
- 列表构建:支持按用户名(手机号/邮箱/user_sn/联系人)、起止时间筛选,分页返回,附带套餐名称与用户信息。
- 删除与批量:单条删除确认、批量删除审计记录。
- 模型过滤:scopeFilterByUserId/TimeStart/TimeEnd/ApplyDefaultOrder,统一查询语义。
依赖关系分析
- 用户等级读取链路:UserService -> UserProfileQuery -> DB(user/user_level)。
- 等级配置与日志:LevelController -> UserLevel/UserLevelLog -> DB。
- VIP授予链路:订单支付 -> 场景派发 -> VipService -> DB(vip/vip_package/order)。
- 状态判定:VipStatus作为纯枚举,被上层用于展示与策略判断。
graph LR
A["UserService"] --> B["UserProfileQuery"]
B --> C["DB: user/user_level"]
D["LevelController"] --> E["UserLevel/UserLevelLog"]
E --> F["DB: user_level/user_level_log"]
G["订单支付"] --> H["场景派发"]
H --> I["VipService"]
I --> J["DB: vip/vip_package/order"]
K["VipStatus"] -.-> I
性能与扩展性
- 幂等与去重:VIP授予基于order_sn去重,避免重复落库与重复计费。
- 时间比较优化:end_at为datetime字符串,先转为时间戳再比较,避免年份截断导致的错误。
- 只读路径优化:UserProfileQuery仅在启用user模块且表存在时访问user_level,减少无效IO。
- 可扩展点:
- 升级条件:可在UserLevel中扩展更多upgrade_type与条件字段,结合业务事件触发升级。
- 权益应用:good_discount可用于商品折扣计算;分销佣金可结合分销模块扩展。
- 通知与审计:可在VipService与等级变更处接入消息队列与审计日志。
故障排查指南
- 等级名称为空
- 检查是否启用user模块且user_level表存在;确认level_id是否正确。
- 参考:等级名称读取逻辑。
- 当前等级为空
- 检查user.level_id是否存在;确认currentLevel调用传入userId是否有效。
- 参考:当前等级解析逻辑。
- VIP未生效
- 检查订单是否支付成功并触发ORDER_PAID场景;确认order_sn幂等检查未拦截;确认vip_package.day配置正确;确认最近有效VIP的end_at计算无误。
- 参考:VIP授予流程与有效期顺延逻辑。
- 后台VIP记录无法筛选
- 检查用户名关键字是否能匹配到user_id;检查时间范围格式;确认分页参数合法。
- 参考:后台VIP列表构建与模型过滤。
结论
DouPHP会员等级系统通过清晰的读写分离、事件驱动的VIP授予与完善的后台管理能力,实现了等级定义、升级条件、有效期管理与差异化权益的可配置化与可扩展化。开发者可基于现有模型与服务快速扩展新的等级类型、升级策略与权益规则,并通过日志与报表支撑运营决策。
附录:配置与示例
新增会员等级
- 步骤
- 在后台等级管理中新增等级,填写名称、升级方式、升级条件、商品折扣、图标等。
- 保存后,可通过等级名称互查方法获取level_id,用于业务逻辑。
- 相关实现
- 后台控制器:LevelController提供创建/编辑入口。
- 模型白名单:UserLevel的fillable字段限制入库字段。
- 语言文案:user.lang.php定义了等级相关文案。
设置升级条件
- 升级方式
- 支持消费金额满、推广金额满、后台调整等;满足条件后将升级到该等级。
- 实现要点
- 在UserLevel中配置upgrade_type与upgrade_condition。
- 在业务事件中(如订单完成、分销结算)评估条件并触发等级变更,写入UserLevelLog。
实现等级特权功能
- 商品折扣
- 通过UserProfileQuery.currentLevel获取good_discount,在商品定价或结算时应用。
- 专属功能
- 结合VIP状态(VipStatus)与等级信息,控制菜单、页面或API权限。
- 实现要点
- 在业务层读取当前等级与VIP状态,按需放行或降级。
等级变更通知与审计
- 通知
- 可在等级变更或VIP授予时发送站内信/短信/邮件通知。
- 审计
- 后台删除VIP记录会写入管理员操作日志;等级变更建议同样记录审计日志。
等级统计报表与数据分析
- 报表维度
- 按用户、时间范围筛选VIP购买记录;按升级方式统计等级变更趋势。
- 实现要点
- 使用后台VIP服务的列表构建方法,结合模型过滤条件生成报表数据。
- 对UserLevelLog按upgrade_type聚合,输出升级方式分布。