功能
- 增加用户积分
- 消耗用户积分
- 查询用户积分
- 到期积分清理
- 查询用户的积分明细
积分分为
- 有过期时间
- 无过期时间的
用户可以通过做任务获得积分,也可以通过充值会员获得积分。通过充会员获得的积分就是有期限的。 对于前端需要提供一个查询用户积分的接口
表结构设计
用户积分表
| id | uid | score |
|---|---|---|
| 1 | 232 | 60 |
| 2 | 234 | 70 |
积分明细表
CREATE TABLE `user_score_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`record_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '积分记录id',
`uid` bigint(20) NOT NULL DEFAULT '0' COMMENT '用户id',
`in_out` tinyint(4) NOT NULL DEFAULT '0' COMMENT '积分操作类型 1/添加, 2/减少',
`deal_time` int(10) NOT NULL DEFAULT '0' COMMENT '交易时间:充值或消费时间',
`event_id` varchar(128) NOT NULL DEFAULT '' COMMENT '事件ID,任务id、订单ID、签到ID、聊天msgID等',
`expired_time` bigint(20) NOT NULL DEFAULT '0' COMMENT '积分过期时间:0/不限制时间,大于0是对应的过期时间',
`score_code` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '积分编码',
`score` int(10) NOT NULL DEFAULT '0' COMMENT '积分',
`create_time` int(10) NOT NULL DEFAULT '0' COMMENT '赚取或消费创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_code_eventid` (`uid`,`score_code`,`event_id`),
KEY `idx_record_id` (`record_id`),
KEY `idx_channel_id` (`uid`,`deal_time`),
KEY `idx_deal_time` (`deal_time`)
) ENGINE=InnoDB AUTO_INCREMENT=115 DEFAULT CHARSET=utf8mb4 COMMENT='积分明细表';
userUsable 表
CREATE TABLE `userUsableScore` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`uid` bigint(20) NOT NULL DEFAULT '0' COMMENT '用户id',
`event_id` varchar(128) NOT NULL DEFAULT '' COMMENT '事件ID,任务id、订单ID、签到ID、聊天msgID等',
`score_code` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '积分编码',
`score` int(10) NOT NULL DEFAULT '0' COMMENT '积分',
`score_usable` int(10) NOT NULL DEFAULT '0' COMMENT '可以用积分',
`deal_time` int(10) NOT NULL DEFAULT '0' COMMENT '交易时间:充值',
`expired_time` bigint(20) NOT NULL DEFAULT '0' COMMENT '积分过期时间',
`deleted` int(10) NOT NULL DEFAULT '0' COMMENT '删除状态:0正常,大于0删除时间',
`update_time` int(10) NOT NULL DEFAULT '0' COMMENT '修改时间',
`create_time` int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_user_cuid` (`uid`,`score_code`,`event_id`,`deleted`),
KEY `idx_usable_id` (`usable_id`),
KEY `idx_deal_time` (`deal_time`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='可用积分表';
由于积分是有过期时间的属性。会抽象一个用户可用表来便于对积分的处理,方便控制表的大小 。usableScore它是明细表的聚合,无过期时间的积分会聚合为一条数据,且他的score_code=1001, 1001表示的是无过期时间的积分 有过期时间的会在这个表里有多条数据。
对外接口
GET /user/score 返回用户的积分余额和即将到期的积分,即将到期的积分可以自定义时间,比如1天,3天。 查询用户余额:查用户积分表,可以使用redis提高查询速度,设置超时时间。 查询快要到期的积分:查询明细表,未做缓存,指定读库,加了for update
增加积分
流程图
消耗积分
for _, row := range UsableRows {
if unallocScore > 0 {
//当前记录够扣除
if row.ScoreUsable-unallocScore >= 0 {
row.ScoreUsable = row.ScoreUsable - unallocScore
unallocScore = 0
_, err := e.DaoUserUsableScore.Update(row)
if err != nil {
return false, score.ErrorDbUpdate
}
break
}
//当前记录不够扣除
unallocScore = unallocScore - row.ScoreUsable
row.ScoreUsable = 0
_, err := e.DaoUserUsableScore.Update(row)
if err != nil {
return false, score.ErrorDbUpdate
}
}
}
积分到期清理
目前只有充值vip给的积分才有过期时间 积分提供了一个接口
func CleanByCodeEvent(req ScoreConsumeReq) error
大致逻辑如下
row = getUsableScoreByCodeEventId(uid,req.ConsumeScoreCode.Int(), req.ConsumeEventId)
req.Score = tmpRow.ScoreUsable
req.IsConsumeScoreCode = true
consumeScore(req)