简介
本文件面向DouPHP会员系统的开发者与运营人员,聚焦“用户等级体系”的数据模型与业务实现,围绕 dou_user_level(用户等级表)与 dou_user_level_log(等级升级日志表)展开,说明等级名称、升级条件、等级折扣等配置项,解释自动升级规则、日志记录、以及等级与权限/特权(如商品折扣)的关联方式。文档同时给出升级流程、数据一致性与性能建议,便于在二次开发与运维中参考。
项目结构与范围
- 数据库定义与演进脚本位于模块更新与开发手册中,包含等级表、日志表的创建与时间字段统一迁移。
- 后台管理入口通过控制器与服务层完成等级列表、新增、编辑、删除与日志查看。
- 运行时升级逻辑由核心服务负责,结合用户消费/推广累计值进行自动升级并写日志。
- 前端展示通过查询当前等级与下一档目标计算成长进度。
graph TB
A["后台界面<br/>等级管理"] --> B["LevelController<br/>路由与视图"]
B --> C["LevelService / LevelFormRequest<br/>校验与组装"]
C --> D["UserLevel Model<br/>白名单与基础查询"]
D --> E["数据库: dou_user_level"]
B --> F["UserLevelService<br/>checkLevelUpgrade()"]
F --> G["数据库: dou_user_level_log"]
H["订单/统计服务"] --> F
I["UserProfileQuery<br/>currentLevel()/levelName()"] --> J["页面展示<br/>等级名称/折扣"]
核心数据模型
- 用户等级表(dou_user_level)
- 主键:id(或 level_id,随版本迁移差异存在)
- 名称:name
- 升级类型:upgrade_type(noauto/shopping/promote)
- 升级条件:upgrade_condition(数值阈值)
- 等级特权:good_discount(商品折扣)
- 图标:icon
- 时间:created_at(经迁移后统一为datetime)
- 等级升级日志表(dou_user_level_log)
- 自增ID:id
- 用户ID:user_id
- 旧等级ID:old_level_id
- 新等级ID:new_level_id
- 升级类型:upgrade_type
- 触发条件值:condition_value
- 触发订单号:order_sn
- 时间:created_at(经迁移后统一为datetime,并建索引)
说明
- 历史SQL中存在 level_id 作为主键的定义;后续备份与迁移脚本将主键改为 id,并将时间字段从 create_time/add_time 统一为 created_at。
- 升级类型支持:
- noauto:不自动升级,需人工调整
- shopping:按累计消费金额达到阈值升级
- promote:按累计推广金额达到阈值升级
架构总览
用户等级体系由“配置表 + 日志表 + 服务层 + 展示层”构成:
- 配置表:dou_user_level 定义等级、升级条件与特权
- 日志表:dou_user_level_log 记录每次升级事件
- 服务层:UserLevelService 负责读取用户累计值、判断是否满足升级条件、原子更新用户等级并写日志
- 展示层:UserProfileQuery 提供当前等级名称与折扣,用于前台展示与权限判定
sequenceDiagram
participant 订单流 as "订单/统计"
participant 服务 as "UserLevelService"
participant 用户 as "用户(user)"
participant 等级 as "等级(user_level)"
participant 日志 as "日志(user_level_log)"
订单流->>服务 : checkLevelUpgrade(userId, orderSn)
服务->>用户 : 加锁读取当前level_id
服务->>等级 : 读取全部等级(升序)
服务->>服务 : 计算累计消费/推广
alt 满足下一档条件
服务->>用户 : 更新level_id为新等级
服务->>日志 : 写入升级记录
服务-->>订单流 : 返回升级成功
else 未满足
服务-->>订单流 : 返回无升级
end
详细组件分析
用户等级表(dou_user_level)字段与含义
- id/level_id:等级标识(不同版本主键名可能不同,但语义一致)
- name:等级名称,用于展示与识别
- upgrade_type:升级策略
- noauto:手动控制
- shopping:按消费累计值升级
- promote:按推广累计值升级
- upgrade_condition:升级阈值(数值型)
- good_discount:等级折扣(用于商品折扣特权)
- icon:等级图标
- created_at:创建时间(统一后的datetime)
使用要点
- 等级顺序以 id 升序排列,升级时从当前等级之后开始匹配第一档满足条件的等级。
- 若 upgrade_type=noauto,则跳过自动升级,仅允许后台人工调整。
等级升级日志表(dou_user_level_log)字段与用途
- id:自增主键
- user_id:发生升级的用户
- old_level_id/new_level_id:升级前后等级
- upgrade_type:升级类型(shopping/promote/noauto)
- condition_value:触发升级的条件阈值
- order_sn:触发升级的订单号(可选)
- created_at:升级时间(统一后的datetime,带索引)
用途
- 审计与追溯:记录每次自动升级的来源与依据
- 运营看板:统计升级次数、来源、时间分布
- 问题定位:核对升级是否符合预期阈值
升级规则与流程
- 触发点:订单完成后调用 UserLevelService::checkLevelUpgrade
- 关键步骤:
- 锁定用户行,避免并发重复升级
- 读取所有等级并按 id 升序
- 计算用户累计消费/推广值
- 从当前等级的下一档开始检查,遇到满足条件的等级即升级
- 更新用户等级并写入日志
- 事务提交或回滚保证一致性
flowchart TD
Start(["进入升级检查"]) --> Lock["锁定用户行"]
Lock --> ReadLevels["读取等级列表(升序)"]
ReadLevels --> Calc["计算累计消费/推广"]
Calc --> Loop{"遍历当前等级之后的档位"}
Loop --> |满足条件| Upgrade["更新用户等级并写日志"]
Loop --> |不满足| Next["继续下一档"]
Next --> Loop
Upgrade --> Commit["提交事务"]
Commit --> End(["结束"])
等级有效期与继承
- 等级有效期:当前 dou_user_level 表未包含有效期字段;如需有效期能力,可在该表扩展 start_time/end_time 并在升级/过期流程中处理。
- 等级继承:当前设计为“单等级”,用户仅有一个 level_id;不存在多等级叠加继承。若需要继承(如保留上一级部分权益),需在业务层增加额外字段与逻辑。
等级与权限/特权的关系
- 商品折扣:通过等级 good_discount 字段体现,查询当前等级时一并返回,供定价与结算使用。
- 等级名称:通过 UserProfileQuery 根据 level_id 获取名称,用于前端展示与权限提示。
- 权限控制:当前代码中等级主要用于折扣与展示;若需更细粒度权限控制,可基于等级ID扩展权限矩阵或在业务层做判定。
后台管理与表单校验
- 控制器:LevelController 负责列表、新增、编辑、删除与跳转
- 表单请求:LevelFormRequest 对 name、upgrade_type、upgrade_condition、good_discount 进行校验
- 模型:UserLevel 声明可批量写入字段白名单,并提供排序与名称查询方法
依赖关系分析
- 控制器依赖服务层进行数据组装与持久化
- 服务层依赖用户统计服务获取累计值,依赖数据库访问层执行事务操作
- 展示层依赖 ProfileQuery 获取等级名称与折扣
- 日志表与等级表共同支撑升级审计与回溯
graph LR
Ctl["LevelController"] --> Svc["UserLevelService"]
Svc --> DB1["dou_user_level"]
Svc --> DB2["dou_user_level_log"]
Svc --> Stats["用户统计服务"]
UI["前端/后台"] --> Prof["UserProfileQuery"]
Prof --> DB1
性能与一致性
- 事务与锁:升级过程使用事务与行级锁,避免并发导致的重复升级或数据不一致
- 索引优化:日志表对 user_id 与 created_at 建立索引,便于按用户与时间范围查询
- 时间字段统一:通过迁移脚本将 create_time/add_time 统一为 created_at,提升可读性与查询一致性
- 建议
- 对高频升级场景,考虑缓存等级列表与用户累计值,减少频繁读库
- 对日志表实施归档策略,避免大表影响查询性能
- 对升级阈值与类型变更,配合灰度发布与监控告警
故障排查指南
- 日志表缺失:若后台提示等级日志表不存在,请先执行数据库升级脚本
- 升级未生效:检查 upgrade_type 是否为 noauto;确认累计消费/推广值是否达到阈值;查看日志表中是否有对应记录
- 并发异常:确认升级流程是否被多次调用;检查事务是否正确提交/回滚
- 时间显示异常:确认 created_at 是否已正确迁移;必要时重新执行时间字段统一脚本
结论
DouPHP 的用户等级体系以 dou_user_level 为核心配置表,配合 dou_user_level_log 实现可审计的自动升级机制。通过升级类型与阈值灵活配置,结合商品折扣等特权,形成完整的会员等级体系。建议在现有模型基础上按需扩展有效期与继承能力,并通过缓存与归档优化性能。
附录:字段与索引清单
- dou_user_level
- 字段:id/level_id、name、upgrade_type、upgrade_condition、good_discount、icon、created_at
- 主键:id(或 level_id,视版本)
- dou_user_level_log
- 字段:id、user_id、old_level_id、new_level_id、upgrade_type、condition_value、order_sn、created_at
- 索引:user_id、created_at