文档目录
积分系统表

简介

本文件面向DouPHP积分系统的开发者与运营人员,聚焦积分主表与流水表的表结构设计、字段语义、索引策略、以及与用户钱包快照、订单/商城兑换等模块的关联关系。文档基于仓库中实际代码与SQL脚本进行梳理,确保内容可追溯、可落地。

项目结构

积分相关能力分布在以下位置:

  • 数据定义与升级脚本:模块备份SQL与升级脚本
  • 核心写入服务:统一通过钱包服务写入积分流水并同步账户快照
  • 后台管理:列表查询、删除、批量操作、参数初始化
  • 前台展示:会员“我的积分”页面、积分商城入口
  • 国际化:动作文案、字段名等
graph TB
A["业务调用方<br/>订单/活动/分享等"] --> B["钱包服务 WalletService"]
B --> C["积分流水表 point<br/>即 dou_point"]
B --> D["用户钱包快照 user_wallet<br/>point_balance"]
E["后台 PointService"] --> C
F["前台控制器/路由"] --> C
G["订单/商品模块"] --> B

核心组件

  • 积分流水表(point/dou_point):记录每次积分变动明细,包含变动值、余额、来源、操作者、时间戳等。
  • 用户钱包快照(user_wallet):缓存用户当前积分余额等指标,提升读取性能。
  • 钱包服务(WalletService):统一的积分写入入口,负责并发安全校验、落库与快照同步。
  • 后台服务(PointService):提供积分流水分页查询、删除、批量操作及参数初始化。
  • 模型层(Point/PointLog):封装常用筛选、排序与类型转换。
  • 前端与API路由:暴露“我的积分”与积分商城入口。

架构总览

积分写入采用“流水+快照”的双写模式:所有积分变动先写入流水表,再更新用户钱包快照中的积分余额;读取时优先使用快照以提升性能。

sequenceDiagram
participant Biz as "业务侧"
participant WS as "钱包服务 WalletService"
participant DBP as "积分流水表 point"
participant UW as "用户钱包快照 user_wallet"
Biz->>WS : createPoint(user_id, action, point, ...)
WS->>DBP : SELECT total FROM point WHERE user_id=? ORDER BY id DESC FOR UPDATE
WS->>WS : 计算新余额 = 旧total + point
WS->>DBP : INSERT INTO point(...)
WS->>UW : upsert(point_balance=新余额)
WS-->>Biz : 返回成功/失败

详细组件分析

积分主表(dou_point / point)字段设计

说明:该表为积分流水表,记录每一次积分获取或消耗明细,同时维护累计余额用于快速展示与校验。

  • id:自增主键
  • user_id:会员ID(unsigned)
  • operator_type:操作者类型(admin/user/work/system),默认user
  • operator_id:操作者ID(unsigned),默认0
  • action:操作动作标识(如 exchange/shopping/share 等)
  • point:本次变动积分(可为负数)
  • total:变动后的积分余额
  • from:关联来源单号(字符串)
  • source_type:业务来源类型(如 order_pay/sign/recharge 等)
  • source_id:关联业务主键(unsigned),默认0
  • remark:备注
  • ip:来源IP(兼容IPv6)
  • created_at:创建时间(datetime)

索引与约束

  • 主键:id
  • 复合索引:idx_user(user_id, action),便于按用户与动作筛选
  • 复合索引:idx_source(source_type, source_id),便于按业务来源溯源

字段扩容与迁移

  • point、total 由 smallint 升级为 int,避免溢出
  • 补齐 operator_type/operator_id/source_type/source_id/remark/ip 列
  • 时间字段统一为 created_at,废弃 create_time

用户钱包快照(user_wallet)与积分余额

  • point_balance:缓存用户当前积分余额,由钱包服务在写入流水后同步更新
  • 初始化逻辑:从最新流水 total 回填,保证首行存在且一致
  • 读取优化:前端与后台优先读取快照,减少聚合计算

积分写入流程(并发安全与一致性)

  • 使用行级锁(FOR UPDATE)锁定用户最新流水,防止并发导致余额不一致
  • 计算新余额并校验非负,不满足则拒绝写入
  • 插入流水后,upsert 更新 user_wallet.point_balance,保持最终一致
flowchart TD
Start(["开始"]) --> Lock["锁定用户最新流水<br/>SELECT ... FOR UPDATE"]
Lock --> Calc["计算新余额 = 旧total + point"]
Calc --> Check{"新余额 >= 0 ?"}
Check -- 否 --> Fail["返回失败"]
Check -- 是 --> Insert["INSERT 积分流水"]
Insert --> Sync["UPSERT 用户钱包快照<br/>point_balance=新余额"]
Sync --> End(["结束"])

后台积分流水管理

  • 列表查询:支持按用户名(解析为user_id)、时间范围筛选,默认按id倒序
  • 删除与批量删除:带审计日志记录
  • 参数初始化:自动注入积分比例参数项

前台与API入口

  • 前台路由:积分商城与“我的积分”页面入口
  • API路由:对外暴露积分查询接口(会员侧)

与订单/商城兑换的关联

  • 订单商品项展示会携带积分信息,便于结算与兑换场景联动
  • 业务来源字段(source_type/source_id/from)可用于将积分流水追溯到具体订单或活动

动作与文案

  • 常见动作:积分兑换、商品购买、分享奖励等
  • 文案来自语言包,便于多语言扩展

依赖关系分析

  • 钱包服务依赖数据库访问与配置开关(features.point)
  • 后台服务依赖模型与语言包
  • 前台/API路由依赖控制器与服务,间接依赖钱包服务
  • 订单模块通过业务来源字段与积分流水建立关联
graph LR
Order["订单/商品模块"] --> WS["钱包服务"]
WS --> P["积分流水表 point"]
WS --> UW["用户钱包快照 user_wallet"]
Admin["后台服务"] --> P
Front["前台/AI路由"] --> P

性能考虑

  • 读写分离:写入走流水表,读取优先使用 user_wallet 快照,降低聚合开销
  • 并发控制:对最新流水加行锁,避免竞态条件
  • 索引优化:idx_user、idx_source 覆盖高频查询路径
  • 字段类型:point/total 使用 int,避免溢出与精度问题
  • 时间字段:统一为 datetime,便于范围查询与统计

故障排查指南

  • 功能未生效:检查配置开关 features.point 是否开启
  • 余额为负:确认写入前余额校验逻辑与并发锁是否生效
  • 无法溯源:核对 source_type/source_id/from 是否正确填写
  • 列表加载慢:确认 idx_user、idx_source 是否存在且命中
  • 快照不一致:核查 upsert 逻辑与首次初始化脚本执行结果

结论

DouPHP积分系统以“流水+快照”为核心设计,通过严格的并发控制与合理的索引策略,兼顾了数据一致性与查询性能。积分主表(point/dou_point)承载全部变动明细,配合用户钱包快照实现高效读取;通过业务来源字段与订单/活动等模块解耦关联,便于追踪与分析。建议在实际使用中严格遵循钱包服务的写入接口,确保数据一致性与可追溯性。

附录

表结构与索引一览

  • 表:point(即 dou_point)
    • 主键:id
    • 索引:idx_user(user_id, action)、idx_source(source_type, source_id)
  • 快照:user_wallet
    • 关键字段:point_balance(与流水保持一致)

关键业务流程参考

  • 积分写入:钱包服务 createPoint
  • 后台列表:PointService buildPointListData
  • 前台入口:front/route/point.php
  • API入口:api/route/point.php
添加日期:2026-10-05