refactor(api): 提取公共API默认配置并修复积分并发问题
1. 新增InteractiveMagazineApiDefaultsExtensions统一注册共享服务,简化WeChatApi和WebApi的Program.cs代码 2. 修复积分增减的并发问题,改用原子更新操作,添加余额校验避免超扣 3. 修复注释乱码问题,将简体中文注释替换为正确文本 4. 新增.editorconfig配置统一代码格式
This commit is contained in:
@ -73,7 +73,18 @@ public class PointsService(
|
||||
if (input.Amount <= 0)
|
||||
throw new BusinessException("增加积分数量必须大于0", ResultCode.BAD_REQUEST);
|
||||
|
||||
// 查询用户当前积分
|
||||
var now = DateTime.Now;
|
||||
|
||||
// 原子增加积分,避免并发写回旧余额覆盖新余额
|
||||
var affectedRows = await Context.Updateable<Users>()
|
||||
.SetColumns(u => u.Points == u.Points + input.Amount)
|
||||
.SetColumns(u => u.UpdatedAt == now)
|
||||
.Where(u => u.Id == input.UserId && !u.IsDeleted)
|
||||
.ExecuteCommandAsync();
|
||||
|
||||
if (affectedRows <= 0)
|
||||
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||
|
||||
var user = await Context.Queryable<Users>()
|
||||
.Where(u => u.Id == input.UserId && !u.IsDeleted)
|
||||
.FirstAsync();
|
||||
@ -81,15 +92,8 @@ public class PointsService(
|
||||
if (user == null)
|
||||
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||
|
||||
var previousBalance = user.Points;
|
||||
var newBalance = previousBalance + input.Amount;
|
||||
|
||||
// 更新用户积分
|
||||
await Context.Updateable<Users>()
|
||||
.SetColumns(u => u.Points == newBalance)
|
||||
.SetColumns(u => u.UpdatedAt == DateTime.Now)
|
||||
.Where(u => u.Id == input.UserId && !u.IsDeleted)
|
||||
.ExecuteCommandAsync();
|
||||
var newBalance = user.Points;
|
||||
var previousBalance = newBalance - input.Amount;
|
||||
|
||||
// 插入积分流水记录
|
||||
var record = new PointsRecord
|
||||
@ -104,9 +108,9 @@ public class PointsService(
|
||||
Status = (int)PointsRecordStatusEnum.Success,
|
||||
IsDeleted = false,
|
||||
CreatedBy = input.OperatorName ?? user.Name ?? input.UserId.ToString(),
|
||||
CreatedAt = DateTime.Now,
|
||||
CreatedAt = now,
|
||||
UpdatedBy = input.OperatorName ?? user.Name ?? input.UserId.ToString(),
|
||||
UpdatedAt = DateTime.Now
|
||||
UpdatedAt = now
|
||||
};
|
||||
|
||||
var recordEntity = await InsertReturnEntityAsync(record);
|
||||
@ -131,7 +135,27 @@ public class PointsService(
|
||||
if (input.Amount <= 0)
|
||||
throw new BusinessException("扣除积分数量必须大于0", ResultCode.BAD_REQUEST);
|
||||
|
||||
// 查询用户当前积分
|
||||
var now = DateTime.Now;
|
||||
|
||||
// 带余额条件的原子扣减,避免并发扣减时超扣或覆盖余额
|
||||
var affectedRows = await Context.Updateable<Users>()
|
||||
.SetColumns(u => u.Points == u.Points - input.Amount)
|
||||
.SetColumns(u => u.UpdatedAt == now)
|
||||
.Where(u => u.Id == input.UserId && !u.IsDeleted && u.Points >= input.Amount)
|
||||
.ExecuteCommandAsync();
|
||||
|
||||
if (affectedRows <= 0)
|
||||
{
|
||||
var currentUser = await Context.Queryable<Users>()
|
||||
.Where(u => u.Id == input.UserId && !u.IsDeleted)
|
||||
.FirstAsync();
|
||||
|
||||
if (currentUser == null)
|
||||
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||
|
||||
throw new BusinessException($"积分不足,需要 {input.Amount} 积分,当前余额 {currentUser.Points}", ResultCode.BAD_REQUEST);
|
||||
}
|
||||
|
||||
var user = await Context.Queryable<Users>()
|
||||
.Where(u => u.Id == input.UserId && !u.IsDeleted)
|
||||
.FirstAsync();
|
||||
@ -139,20 +163,8 @@ public class PointsService(
|
||||
if (user == null)
|
||||
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||
|
||||
var previousBalance = user.Points;
|
||||
|
||||
// 余额不足校验
|
||||
if (previousBalance < input.Amount)
|
||||
throw new BusinessException($"积分不足,需要 {input.Amount} 积分,当前余额 {previousBalance}", ResultCode.BAD_REQUEST);
|
||||
|
||||
var newBalance = previousBalance - input.Amount;
|
||||
|
||||
// 更新用户积分
|
||||
await Context.Updateable<Users>()
|
||||
.SetColumns(u => u.Points == newBalance)
|
||||
.SetColumns(u => u.UpdatedAt == DateTime.Now)
|
||||
.Where(u => u.Id == input.UserId && !u.IsDeleted)
|
||||
.ExecuteCommandAsync();
|
||||
var newBalance = user.Points;
|
||||
var previousBalance = newBalance + input.Amount;
|
||||
|
||||
// 插入积分流水记录
|
||||
var record = new PointsRecord
|
||||
@ -167,9 +179,9 @@ public class PointsService(
|
||||
Status = (int)PointsRecordStatusEnum.Success,
|
||||
IsDeleted = false,
|
||||
CreatedBy = input.OperatorName ?? user.Name ?? input.UserId.ToString(),
|
||||
CreatedAt = DateTime.Now,
|
||||
CreatedAt = now,
|
||||
UpdatedBy = input.OperatorName ?? user.Name ?? input.UserId.ToString(),
|
||||
UpdatedAt = DateTime.Now
|
||||
UpdatedAt = now
|
||||
};
|
||||
|
||||
var recordEntity = await InsertReturnEntityAsync(record);
|
||||
|
||||
Reference in New Issue
Block a user