简介
本文件面向VIP服务开发者,系统化梳理DouPHP的VIP会员体系:包括VIP套餐定义、购买记录、后台管理、小程序/前端展示、以及可扩展的权益与状态管理机制。本次更新重点增强了VIP服务的历史数据管理能力,新增了完整的数据备份功能,支持多种订阅类型和价格区间的历史记录存储。
更新 本次更新完成了VIP服务历史数据管理的重大增强,包括完整的历史数据备份能力、多订阅类型支持和价格区间扩展,同时通过升级脚本确保了数据结构的向后兼容性。
项目结构
VIP功能在系统中按"前台/小程序/后台"三端分层组织,采用控制器-服务-模型的分层架构:新增的历史数据备份功能为整个系统提供了更强的数据持久化和恢复能力。
graph TB
subgraph "后台 Admin"
AC["VipController"]
ASvc["VipService"]
AModel["Vip"]
end
subgraph "前台 Front"
FC["VipController / UserController"]
FSvc["VipService"]
end
subgraph "小程序 API"
APCtrl["VipController / UserController"]
ASvc2["VipService"]
end
subgraph "核心领域层"
VS["VipSource (Domain) - 动态配置"]
VSt["VipStatus (Domain)"]
CoreSvc["Core VipService"]
UMQ["UserMembershipQuery"]
DS["Data Sanitization (Str)"]
DB["Database Backup"]
end
AC --> ASvc --> AModel
FC --> FSvc
APCtrl --> ASvc2
ASvc --> CoreSvc
CoreSvc --> VS
CoreSvc --> VSt
UMQ --> VSt
FSvc --> DS
ASvc --> DB
图表来源
- admin/controller/vip/VipController.php:22
- admin/service/vip/VipService.php:20
- core/domain/vip/VipSource.php:15
- core/domain/vip/VipStatus.php:15
- core/service/user/UserMembershipQuery.php:20
- core/support/Str.php:441
核心组件
- 领域模型
- VipSource:统一管理VIP来源类型,支持动态配置,提供来源验证、徽章配色、订单关联判断等功能
- VipStatus:基于时间有效性管理VIP生命周期状态,提供状态分类和徽章配色功能
- 数据脱敏工具
- Str::maskPhone():手机号脱敏显示,保留前缀和后缀,中间用星号替代
- Str::maskEmail():邮箱地址脱敏显示,保留@符号前的部分字符和完整域名
- 数据模型
- VIP购买记录模型:维护user_id、package_id、起止时间、订单状态等字段,新增source、admin_id、remark字段
- VIP套餐模型:维护套餐名称、时长、价格、促销价、颜色、图片、内容、排序等
- 服务层
- 后台VIP记录服务:构建列表数据、删除单条、批量删除,支持源追踪和操作员记录,集成数据脱敏
- 前台VIP服务:提供套餐列表和用户VIP日志查询功能,简化订单链接显示逻辑
- 用户会员查询服务:基于新的VipStatus进行智能VIP状态判断,支持批量查询优化
- 数据备份系统
- 完整历史数据备份:支持2023-2025年VIP用户订阅记录的完整备份
- 多订阅类型支持:月费$598、季度$298、年费$998、终身订阅等
- 价格区间管理:支持$0.10-$998的广泛价格范围
- 数据结构升级:通过升级脚本实现字段迁移和状态机同步
章节来源
- core/domain/vip/VipSource.php:35-112
- core/domain/vip/VipStatus.php:32-95
- core/support/Str.php:441-475
- core/service/user/UserMembershipQuery.php:71-153
- admin/service/vip/VipService.php:44-123
- front/service/vip/VipService.php:38-118
架构总览
系统围绕"套餐配置—购买记录—多端展示—历史备份"的主线展开。新增的历史数据备份功能使系统具备了完整的数据持久化能力,支持多种订阅类型和价格区间的历史记录存储。后台负责套餐与记录的维护;前台与小程序通过各自的服务获取套餐与日志数据;支付流程由外部订单/支付模块驱动,VIP记录用于沉淀购买结果与有效期;数据备份系统确保所有历史数据的完整性和可恢复性。
sequenceDiagram
participant U as "用户/小程序"
participant F as "前台/小程序控制器"
participant S as "VIP服务"
participant VS as "VipSource (Domain)
participant VSt as "VipStatus (Domain)"
participant DS as "数据脱敏工具"
participant M as "VIP模型"
participant P as "VIP套餐模型"
participant B as "数据备份系统"
U->>F : 请求VIP套餐列表
F->>S : buildVipPackageListData()
S->>P : 读取套餐(排序/过滤)
P-->>S : 套餐集合
S-->>F : 套餐数据
F-->>U : 返回套餐列表
U->>F : 查看我的VIP日志
F->>S : buildVipLogListData(userId, page)
S->>M : 分页查询(用户/时间范围/来源)
M-->>S : 记录集合
Note over S,DS : 使用数据脱敏处理敏感信息
S->>DS : maskPhone(maskEmail)
DS-->>S : 脱敏后的数据
Note over S,VSt : 使用VipStatus进行智能状态判断
S->>VSt : classify(start_at, end_at)
VSt-->>S : ACTIVE/EXPIRED/NONE
Note over S,B : 触发历史数据备份
S->>B : 备份VIP记录(2023-2025)
B-->>S : 备份完成确认
S-->>F : 日志+分页(含脱敏数据)
F-->>U : 返回日志列表
图表来源
- front/service/vip/VipService.php:66-118
- core/domain/vip/VipStatus.php:46-61
- core/service/user/UserMembershipQuery.php:92-106
- core/support/Str.php:441-475
详细组件分析
历史数据备份系统(新增)
新增的完整历史数据备份功能为VIP服务提供了强大的数据持久化和恢复能力:
- 时间跨度覆盖:支持2023-2025年完整年份的VIP用户订阅记录备份
- 多订阅类型:涵盖月费$598、季度$298、年费$998、终身订阅等多种订阅模式
- 价格区间管理:支持从$0.10到$998的广泛价格范围,满足不同用户需求
- 数据结构完整性:通过升级脚本确保历史数据的完整性和一致性
- 自动备份机制:在VIP记录创建时自动触发备份流程
classDiagram
class BackupSystem {
+backupVipRecords(years) array
+restoreFromBackup(file) bool
+validateBackupIntegrity() bool
}
class VipRecord {
+user_id int
+package_id int
+price decimal
+sale_price decimal
+start_at datetime
+end_at datetime
+order_status string
}
class SubscriptionType {
+monthly $598
+quarterly $298
+yearly $998
+lifetime unlimited
}
BackupSystem --> VipRecord : "备份"
BackupSystem --> SubscriptionType : "支持"
图表来源
- _'/module/vip/storage/backup/vip.sql:7-25
- _'/module/vip/_update/data/upgrade.php:49-61
数据结构和字段迁移(新增)
通过升级脚本实现了完整的数据结构迁移和字段标准化:
- 时间字段统一:将旧的时间字段(start_time、end_time、add_time)统一迁移为新的标准格式(start_at、end_at、created_at)
- 状态机同步:将数字状态值映射为字符串状态枚举(pending/paid/completed/cancelled)
- 新字段添加:增加level_price、promote_price、promote_start_at、promote_end_at等促销相关字段
- 索引优化:为source字段添加索引,提升查询性能
章节来源
- _'/module/vip/_update/data/upgrade.php:65-93
- _'/module/vip/_update/data/upgrade.php:96-114
- _'/module/vip/_update/data/upgrade.php:118-132
数据脱敏功能(新增)
新增的数据脱敏方法为VIP服务提供了完善的用户隐私保护机制:
- 手机号脱敏:根据手机号长度自动调整脱敏策略,保留前缀和后缀,中间用星号替代
- 邮箱脱敏:保留@符号前的部分字符(默认前2个)和完整的域名部分
- 安全展示:在VIP记录列表中展示用户联系方式时,自动应用脱敏规则
- 统一接口:通过Str类的静态方法提供统一的脱敏接口
classDiagram
class Str {
+static maskPhone(value) string
+static maskEmail(value) string
}
class VipService {
+buildVipLogListData(userId, page, pageUrl) array
+buildVipPackageListData() array
}
class VipSource {
+all() array
+isValid(source) bool
+isOrderBacked(source) bool
+badgeClass(source) string
}
VipService --> Str : "使用"
VipService --> VipSource : "使用"
图表来源
- core/support/Str.php:441-475
- front/service/vip/VipService.php:66-118
- core/domain/vip/VipSource.php:69-157
VIP源渠道动态配置(新增)
VipSource类现在支持通过配置文件动态添加自定义VIP来源类型:
- 配置文件支持:通过config/vip_source.php文件定义自定义来源
- 自动加载机制:系统启动时自动加载配置文件中的自定义来源
- 白名单验证:所有来源值都经过严格验证,确保安全性
- 无缝集成:自定义来源自动出现在后台表单和筛选选项中
- 语言包支持:通过vipsource<值>键名提供多语言支持
flowchart TD
Start(["系统启动"]) --> LoadConfig{"检查配置文件"}
LoadConfig --> |存在| ReadFile["读取config/vip_source.php"]
LoadConfig --> |不存在| UseDefault["使用内置来源"]
ReadFile --> Validate["验证配置格式"]
Validate --> |有效| Merge["合并到来源列表"]
Validate --> |无效| UseDefault
Merge --> Cache["缓存来源列表"]
UseDefault --> Cache
Cache --> End(["完成"])
图表来源
- core/domain/vip/VipSource.php:69-94
订单链接显示逻辑简化(优化)
简化了VIP记录中订单链接的显示逻辑,提升用户体验:
- 统一显示规则:任何有订单号的VIP记录都会显示订单链接
- 移除来源限制:不再限制只有特定来源类型的记录才显示订单链接
- 简化判断逻辑:只需检查order_sn字段是否为空
- 提升一致性:所有VIP记录都能方便地跳转到相关订单详情
章节来源
- core/support/Str.php:441-475
- core/domain/vip/VipSource.php:69-94
- admin/service/vip/VipService.php:97-101
- front/service/vip/VipService.php:90-94
基于时间的VIP状态管理
新的状态管理机制完全基于时间有效性,不再依赖数据库中的静态状态标志:
- 动态状态计算:每次查询时根据当前时间与VIP记录的时间范围实时计算状态
- 自动过期处理:无需定时任务或手动更新,到期后自动变为过期状态
- 续费叠加支持:支持多次续费的场景,正确处理时间区间的重叠
- 批量查询优化:通过vipMap方法避免N+1查询问题,提升性能
flowchart TD
Start(["开始"]) --> CheckTime{"检查时间"}
CheckTime --> |start_at <= now < end_at| Active["ACTIVE 生效中"]
CheckTime --> |end_at <= now| Expired["EXPIRED 已过期"]
CheckTime --> |no record| None["NONE 无记录"]
Active --> Badge["success 徽章"]
Expired --> Badge2["danger 徽章"]
None --> Badge3["info 徽章"]
Badge --> End(["结束"])
Badge2 --> End
Badge3 --> End
图表来源
- core/domain/vip/VipStatus.php:46-61
- core/domain/vip/VipStatus.php:83-94
领域模型重构
所有VIP相关的领域模型都已迁移到统一的领域层:
- VipSource类增强:从基础枚举升级为支持动态配置的来源管理器
- VipStatus类保持:时间驱动的状态管理,位于
core/domain/vip/ - 命名空间统一:所有类现在都使用
Dou\Core\Domain\Vip\命名空间 - 功能增强:VipSource提供了完整的来源管理和验证能力
章节来源
- core/domain/vip/VipSource.php:15-157
- core/domain/vip/VipStatus.php:15-95
- core/service/user/UserMembershipQuery.php:20-153
依赖关系更新
所有引用VipSource和VipStatus的类都已更新为新的命名空间,并集成了数据脱敏功能:
- 后台VIP控制器:
use Dou\Core\Domain\Vip\VipSource; - 后台VIP服务:
use Dou\Core\Domain\Vip\VipSource;,集成Str脱敏功能 - 前台VIP服务:
use Dou\Core\Domain\Vip\VipSource;,集成Str脱敏功能 - 用户会员查询:
use Dou\Core\Domain\Vip\VipStatus;
graph LR
AC["后台VIP控制器"] --> VS["VipSource (Domain)"]
ASvc["后台VIP服务"] --> VS
ASvc --> DS["Str (脱敏)"]
FSvc["前台VIP服务"] --> VS
FSvc --> DS
UMQ["用户会员查询"] --> VSt["VipStatus (Domain)"]
图表来源
- admin/controller/vip/VipController.php:22
- admin/service/vip/VipService.php:20
- front/service/vip/VipService.php:18
- core/service/user/UserMembershipQuery.php:20
章节来源
- admin/controller/vip/VipController.php:22
- admin/service/vip/VipService.php:20
- front/service/vip/VipService.php:18
- core/service/user/UserMembershipQuery.php:20
依赖关系分析
- 控制器依赖服务,服务依赖模型与基础工具(如审计、附件、配置)
- 套餐与记录通过package_id建立逻辑关联
- 前台/小程序共享同一业务语义,但入口不同
- 新增依赖:所有VIP相关类现在都依赖
core/domain/vip/下的领域模型,特别是增强的VipSource和数据脱敏工具 - 备份依赖:历史数据备份功能依赖于数据库连接和文件系统权限
graph LR
AC["后台VIP控制器"] --> ASvc["后台VIP服务"]
ASvc --> AM["VIP模型"]
ASvc --> VS["VipSource (Domain)"]
ASvc --> DS["Str (脱敏)"]
FSvc["前台VIP服务"] --> VS
FSvc --> DS
UMQ["用户会员查询"] --> VSt["VipStatus (Domain)"]
ASvc --> DB["数据备份系统"]
图表来源
- admin/controller/vip/VipController.php:22
- admin/service/vip/VipService.php:20
- front/service/vip/VipService.php:18
- core/service/user/UserMembershipQuery.php:20
章节来源
- admin/controller/vip/VipController.php:22
- admin/service/vip/VipService.php:20
- front/service/vip/VipService.php:18
- core/service/user/UserMembershipQuery.php:20
性能与扩展性
- 列表分页:VIP记录与服务层均采用分页查询,避免全表扫描
- 排序优化:套餐列表按sort/id排序,利于稳定展示
- 附件处理:图片上传走统一附件服务,减少耦合
- 性能优化:新增的VipStatus::classify()方法支持传入自定义时间戳,便于测试和批量处理
- 批量查询优化:UserMembershipQuery::vipMap()方法避免了N+1查询问题
- 架构优化:领域模型分离提高了代码的可维护性和测试性
- 数据安全:新增的数据脱敏功能保护用户隐私信息
- 备份性能:历史数据备份采用增量备份策略,减少数据库负载
- 扩展点
- 套餐内容字段可通过参数动态配置,便于扩展权益描述
- 可在服务层增加"到期提醒""自动续费"钩子,结合定时任务或消息队列实现
- 可在权限层对VIP专属功能进行鉴权拦截
- 新增扩展点:领域模型位于domain层,便于添加新的业务规则和验证逻辑
- 时间扩展:可基于VipStatus.extend()方法添加自定义状态判断逻辑
- 来源扩展:通过config/vip_source.php文件轻松添加新的VIP来源类型
- 脱敏扩展:可基于Str类的方法扩展其他类型的数据脱敏功能
- 备份扩展:可基于备份系统添加新的数据源和恢复策略
故障排查指南
- 列表为空
- 检查筛选条件是否过严(用户名/时间范围/来源)
- 确认分页参数是否正确
- 删除失败
- 确认传入ID有效
- 检查二次确认参数是否存在
- 套餐内容未显示
- 检查参数表中是否已初始化套餐内容字段
- 确认内容字段配置是否为空
- 图片未生效
- 检查上传是否成功,路径是否回写到记录
- 权限问题
- 确认当前登录态与角色权限是否允许访问VIP相关页面
- 新增问题:领域模型引用错误
- 检查命名空间是否正确更新为
Dou\Core\Domain\Vip\ - 确认use语句是否指向新的文件路径
- 验证类名大小写是否正确
- 检查命名空间是否正确更新为
- 新增问题:VIP状态判断异常
- 检查VipStatus::classify()方法的调用参数
- 确认时间戳格式是否正确
- 验证数据库中的start_at和end_at字段值
- 检查时区设置是否正确
- 新增问题:时间计算错误
- 确认服务器时区配置正确
- 检查时间戳转换逻辑
- 验证夏令时处理
- 新增问题:数据脱敏异常
- 检查Str::maskPhone()和Str::maskEmail()方法的输入参数
- 确认手机号和邮箱格式是否正确
- 验证脱敏后的数据显示是否符合预期
- 新增问题:VIP来源配置错误
- 检查config/vip_source.php文件格式是否正确
- 确认自定义来源值的格式符合要求(小写字母开头,2-20位)
- 验证语言包中是否添加了相应的翻译键
- 新增问题:历史数据备份失败
- 检查数据库连接权限和存储空间
- 确认备份文件的写入权限
- 验证备份数据的完整性校验
- 检查时间字段迁移是否成功
- 新增问题:订阅类型识别错误
- 检查套餐价格配置是否正确
- 确认订阅类型映射逻辑
- 验证价格区间边界处理
章节来源
- core/domain/vip/VipSource.php:76-79
- core/domain/vip/VipStatus.php:46-61
- core/service/user/UserMembershipQuery.php:92-106
- core/support/Str.php:441-475
结论
该VIP模块以清晰的三层架构实现了套餐管理与购买记录沉淀,并通过前后端分离的方式提供一致的套餐与日志能力。本次更新完成了VIP服务历史数据管理的重大增强,新增了完整的历史数据备份功能,支持多种订阅类型和价格区间的历史记录存储。新的历史数据备份功能提升了系统的可靠性,多订阅类型支持满足了不同用户的需求,价格区间扩展提供了更灵活的定价策略。基于现有模型与服务,可快速扩展到期提醒、自动续费、权益控制与数据分析等高级能力。
附录:开发示例与最佳实践
- 创建VIP套餐
- 使用后台套餐服务的插入方法,填写名称、时长、价格、排序等字段,必要时上传封面图
- 参考路径:insert:133-159
- 配置会员权益
- 通过参数初始化套餐内容字段,并在套餐详情页渲染对应内容
- 参考路径:seed参数:237-251、内容字段读取:80-85
- 实现基于时间的VIP状态检查
- 使用新的VipStatus领域模型进行状态判断
- 通过
VipStatus::classify($startTime, $endTime)方法进行智能状态分类 - 支持传入自定义时间戳进行精确控制
- 参考路径:状态分类:46-61
- 集成数据脱敏功能(新增)
- 使用Str::maskPhone()方法脱敏手机号显示
- 使用Str::maskEmail()方法脱敏邮箱地址显示
- 在VIP记录列表中展示用户联系方式时应用脱敏规则
- 参考路径:手机号脱敏:441-455、邮箱脱敏:466-475
- 配置动态VIP来源(新增)
- 在config/vip_source.php文件中定义自定义来源类型
- 遵循命名规范:小写字母开头,2-20位小写字母/数字/下划线
- 在语言包中添加相应的翻译键(vipsource<值>)
- 参考路径:动态配置:69-94
- 实现历史数据备份(新增)
- 使用备份系统API进行VIP记录备份
- 支持指定时间范围的备份(如2023-2025年)
- 实现增量备份策略,减少数据库负载
- 参考路径:备份SQL结构:7-25
- 开通/续费流程对接
- 在支付回调中写入VIP购买记录(user_id、package_id、起止时间、订单号、IP、状态等),并记录审计日志
- 设置source字段为'purchase',记录admin_id为0(购买记录无管理员操作)
- 利用时间字段自动管理状态:start_at和end_at字段决定VIP的有效性,无需手动更新状态
- 触发历史数据备份:新创建的VIP记录自动纳入历史备份
- 参考路径:记录模型:33-42、审计日志:126-127
- 使用新的领域模型
- 通过
use Dou\Core\Domain\Vip\VipSource;引入VipSource类 - 通过
use Dou\Core\Domain\Vip\VipStatus;引入VipStatus类 - 参考路径:导入语句:20
- 通过
- VIP状态管理
- 使用VipStatus::classify()方法进行智能状态判断
- 根据返回的ACTIVE/EXPIRED/NONE状态进行相应处理
- 使用VipStatus::badgeClass()获取状态对应的徽章样式
- 支持批量查询优化,避免N+1问题
- 参考路径:状态判断:92-106
- 管理员手动分发VIP
- 管理员可通过后台界面手动为用户开通VIP,设置source为'manual'或'gift',记录管理员信息和备注
- 支持覆盖套餐天数、指定生效时间、设置价格等高级选项
- 时间字段自动管理:手动开通时设置的start_at和end_at将自动决定VIP状态
- 纳入历史备份:手动开通记录同样纳入历史数据备份
- 参考路径:手动分发:177-219
- 简化订单链接显示(优化)
- 任何有订单号的VIP记录都会显示订单链接,不再限制特定来源类型
- 简化了订单链接的判断逻辑,提升用户体验
- 参考路径:订单链接逻辑:97-101、90-94:90-94
- 源追踪和审计
- 所有VIP记录都带有明确的来源标识,支持按来源筛选和统计
- 管理员手动分发记录包含管理员ID和备注信息
- 购买记录通过订单号关联,支持订单跳转
- 历史追溯:通过source字段可以追溯VIP记录的来源历史
- 参考路径:列表构建:44-123
- 到期提醒与自动续费
- 基于新的时间驱动状态管理,可轻松实现到期提醒功能
- 通过查询end_at接近当前时间的记录,触发通知或续订流程
- 可利用VipStatus::classify()方法判断即将过期的VIP
- 建议实现定时任务扫描即将到期的VIP记录
- 续费记录备份:续费操作会生成新的VIP记录,纳入历史备份
- 数据统计与收益分析
- 基于VIP记录聚合统计:按日期/套餐维度统计销量、收入、转化率
- 可按source维度分析VIP开通渠道效果,评估手动激活和赠送活动的ROI
- 可结合订单模块数据进行交叉分析
- 新增统计维度:可基于VIP状态(ACTIVE/EXPIRED)进行统计分析
- 历史数据分析:利用2023-2025年的历史数据进行趋势分析和预测
- 订阅类型分析:分析不同订阅类型(月费/季度/年费/终身)的用户偏好
- 会员画像
- 结合VIP购买频次、套餐偏好、活跃时段等指标,形成用户标签与画像
- 可根据source字段分析用户获取VIP的方式,识别高价值用户特征
- 新增画像维度:可基于VIP状态变化轨迹分析用户行为模式
- 隐私保护:使用数据脱敏功能保护用户敏感信息
- 历史行为分析:基于完整的历史数据构建更准确的用户画像
- 可在服务层扩展聚合方法,供报表或推荐系统使用
- 生命周期自动化管理
- 系统自动处理VIP状态的变更,无需人工干预
- 到期自动失效,续费自动延长有效期
- 支持复杂的续费场景,如多次续费、部分退款等
- 可结合业务规则实现自动化的会员生命周期管理
- 完整生命周期记录:所有生命周期变更都纳入历史备份
- 数据结构和字段迁移
- 使用升级脚本进行数据库结构迁移
- 确保时间字段的正确转换(start_time→start_at等)
- 验证状态机的正确映射(数字→字符串状态)
- 参考路径:字段迁移:65-93、状态迁移:49-61
章节来源
- core/domain/vip/VipSource.php:35-157
- core/domain/vip/VipStatus.php:32-95
- core/support/Str.php:441-475
- core/service/user/UserMembershipQuery.php:71-153
- admin/service/vip/VipService.php:44-219
- front/service/vip/VipService.php:38-118
- _'/module/vip/storage/backup/vip.sql:7-47
- _'/module/vip/_update/data/upgrade.php:1-133