260 lines
9.6 KiB
C#
260 lines
9.6 KiB
C#
using System;
|
|||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Linq.Expressions;
|
||
|
|
using System.Threading.Tasks;
|
||
|
|
using Common;
|
||
|
|
using CommonDomain;
|
||
|
|
using CommonDomain.BaseModel;
|
||
|
|
using Domain.Admin.Admin;
|
||
|
|
using DotNetCore.CAP;
|
||
|
|
using Microsoft.Extensions.Logging;
|
||
|
|
using MongoDB.Driver;
|
||
|
|
using MongoRepository;
|
||
|
|
using RedisService;
|
||
|
|
using UserDomain.Entity;
|
||
|
|
using UserService.User;
|
||
|
|
using UserService.Param;
|
||
|
|
using UserDomain.Enum;
|
||
|
|
|
||
|
|
namespace CommonService
|
||
|
|
{
|
||
|
|
public class BackgroundOperationService : IBackgroundOperationService
|
||
|
|
{
|
||
|
|
private readonly IMongoBaseRepository<BackgroundOperationLog> _logRepo;
|
||
|
|
private readonly IUserService _userService;
|
||
|
|
private readonly ICapPublisher _capPublisher;
|
||
|
|
private readonly IMongoBaseRepository<SystemUser> _adminRepo;
|
||
|
|
private readonly IRedisService _redisService;
|
||
|
|
private readonly ILogger<BackgroundOperationService> _logger;
|
||
|
|
|
||
|
|
public BackgroundOperationService(
|
||
|
|
IMongoBaseRepository<BackgroundOperationLog> logRepo,
|
||
|
|
IUserService userService,
|
||
|
|
ICapPublisher capPublisher,
|
||
|
|
IMongoBaseRepository<SystemUser> adminRepo,
|
||
|
|
IRedisService redisService,
|
||
|
|
ILogger<BackgroundOperationService> logger)
|
||
|
|
{
|
||
|
|
_logRepo = logRepo;
|
||
|
|
_userService = userService;
|
||
|
|
_capPublisher = capPublisher;
|
||
|
|
_adminRepo = adminRepo;
|
||
|
|
_redisService = redisService;
|
||
|
|
_logger = logger;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<(bool success, string message)> Charge(
|
||
|
|
string adminUserId, string targetUserId, int currencyType, long amount, string remark)
|
||
|
|
{
|
||
|
|
var targetUser = await _userService.GetUser(targetUserId);
|
||
|
|
if (targetUser == null)
|
||
|
|
return (false, "目标用户不存在");
|
||
|
|
|
||
|
|
var isBuiltInAdmin = adminUserId == "administrator";
|
||
|
|
var adminUser = isBuiltInAdmin
|
||
|
|
? new SystemUser { Id = "administrator", UserName = "administrator" }
|
||
|
|
: await _adminRepo.FindByIdAsync(adminUserId);
|
||
|
|
if (adminUser == null)
|
||
|
|
return (false, "管理员用户不存在");
|
||
|
|
|
||
|
|
if (currencyType == 1)
|
||
|
|
{
|
||
|
|
targetUser.Assets.Gold += amount;
|
||
|
|
}
|
||
|
|
else if (currencyType == 2)
|
||
|
|
{
|
||
|
|
targetUser.Assets.Diamond += (int)amount;
|
||
|
|
var rechargeMoney = amount / 100.0;
|
||
|
|
targetUser.Static.TotalRecharge += rechargeMoney;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var gameConfig = _redisService.GetGameConfig();
|
||
|
|
var newVipLevels = targetUser.VipLevelVerify(gameConfig);
|
||
|
|
if (newVipLevels != null && newVipLevels.Count > 0)
|
||
|
|
{
|
||
|
|
var levelNames = string.Join(",", newVipLevels);
|
||
|
|
_capPublisher.Publish("VipLevelUp", new
|
||
|
|
{
|
||
|
|
UserId = targetUserId,
|
||
|
|
NewLevels = newVipLevels,
|
||
|
|
Remark = $"后台充值钻石触发VIP升级: {levelNames}"
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
_logger.LogError(ex, "后台充值更新VIP失败 userId={UserId}", targetUserId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
return (false, "不支持的货币类型");
|
||
|
|
}
|
||
|
|
|
||
|
|
await _userService.UpdateUser(targetUser);
|
||
|
|
|
||
|
|
var logId = "";
|
||
|
|
if (!isBuiltInAdmin)
|
||
|
|
{
|
||
|
|
var log = new BackgroundOperationLog
|
||
|
|
{
|
||
|
|
AdminUserId = adminUserId,
|
||
|
|
AdminUserName = adminUser.UserName ?? adminUserId,
|
||
|
|
TargetUserId = targetUserId,
|
||
|
|
TargetUserName = targetUser.BaseInfo.UserName,
|
||
|
|
OperationType = 1,
|
||
|
|
CurrencyType = currencyType,
|
||
|
|
Amount = amount,
|
||
|
|
Remark = remark,
|
||
|
|
OperationTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
||
|
|
};
|
||
|
|
await _logRepo.InsertOneAsync(log);
|
||
|
|
logId = log.Id;
|
||
|
|
}
|
||
|
|
|
||
|
|
_capPublisher.Publish("UserAssetChange", new UserAssetParam
|
||
|
|
{
|
||
|
|
UserId = targetUserId,
|
||
|
|
ChangeType = UserAssetChangeTypeEnum.增加,
|
||
|
|
Gold = currencyType == 1 ? amount : 0,
|
||
|
|
Diamond = currencyType == 2 ? (int)amount : 0,
|
||
|
|
Source = RewardSource.后台操作,
|
||
|
|
Remark = $"后台充值:{remark}",
|
||
|
|
OtherId = logId,
|
||
|
|
RoomName = "后台操作",
|
||
|
|
RoomInfo = "后台充值"
|
||
|
|
});
|
||
|
|
|
||
|
|
_capPublisher.Publish("BackgroundOperation.NotifyUser", new BackgroundOperationNotifyMessage
|
||
|
|
{
|
||
|
|
UserId = targetUserId,
|
||
|
|
CurrencyType = currencyType,
|
||
|
|
ChangeType = 1,
|
||
|
|
Amount = amount,
|
||
|
|
NewGold = targetUser.Assets.Gold,
|
||
|
|
NewDiamond = targetUser.Assets.Diamond,
|
||
|
|
Source = "后台充值",
|
||
|
|
Remark = remark
|
||
|
|
});
|
||
|
|
|
||
|
|
return (true, "充值成功");
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<(bool success, string message)> Deduct(
|
||
|
|
string adminUserId, string targetUserId, int currencyType, long amount, string remark)
|
||
|
|
{
|
||
|
|
var targetUser = await _userService.GetUser(targetUserId);
|
||
|
|
if (targetUser == null)
|
||
|
|
return (false, "目标用户不存在");
|
||
|
|
|
||
|
|
if (currencyType == 1)
|
||
|
|
{
|
||
|
|
if (targetUser.Assets.Gold < amount)
|
||
|
|
return (false, "用户金币余额不足");
|
||
|
|
}
|
||
|
|
else if (currencyType == 2)
|
||
|
|
{
|
||
|
|
if (targetUser.Assets.Diamond < amount)
|
||
|
|
return (false, "用户钻石余额不足");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
return (false, "不支持的货币类型");
|
||
|
|
}
|
||
|
|
|
||
|
|
var isBuiltInAdmin2 = adminUserId == "administrator";
|
||
|
|
var adminUser = isBuiltInAdmin2
|
||
|
|
? new SystemUser { Id = "administrator", UserName = "administrator" }
|
||
|
|
: await _adminRepo.FindByIdAsync(adminUserId);
|
||
|
|
var adminUserName = adminUser?.UserName ?? adminUserId;
|
||
|
|
|
||
|
|
if (currencyType == 1)
|
||
|
|
{
|
||
|
|
targetUser.Assets.Gold -= amount;
|
||
|
|
}
|
||
|
|
else if (currencyType == 2)
|
||
|
|
{
|
||
|
|
targetUser.Assets.Diamond -= (int)amount;
|
||
|
|
}
|
||
|
|
|
||
|
|
await _userService.UpdateUser(targetUser);
|
||
|
|
|
||
|
|
var logId2 = "";
|
||
|
|
if (!isBuiltInAdmin2)
|
||
|
|
{
|
||
|
|
var log = new BackgroundOperationLog
|
||
|
|
{
|
||
|
|
AdminUserId = adminUserId,
|
||
|
|
AdminUserName = adminUserName,
|
||
|
|
TargetUserId = targetUserId,
|
||
|
|
TargetUserName = targetUser.BaseInfo.UserName,
|
||
|
|
OperationType = 2,
|
||
|
|
CurrencyType = currencyType,
|
||
|
|
Amount = amount,
|
||
|
|
Remark = remark,
|
||
|
|
OperationTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
||
|
|
};
|
||
|
|
await _logRepo.InsertOneAsync(log);
|
||
|
|
logId2 = log.Id;
|
||
|
|
}
|
||
|
|
|
||
|
|
_capPublisher.Publish("UserAssetChange", new UserAssetParam
|
||
|
|
{
|
||
|
|
UserId = targetUserId,
|
||
|
|
ChangeType = UserAssetChangeTypeEnum.减少,
|
||
|
|
Gold = currencyType == 1 ? amount : 0,
|
||
|
|
Diamond = currencyType == 2 ? (int)amount : 0,
|
||
|
|
Source = RewardSource.后台操作,
|
||
|
|
Remark = $"后台扣除:{remark}",
|
||
|
|
OtherId = logId2,
|
||
|
|
RoomName = "后台操作",
|
||
|
|
RoomInfo = "后台扣除"
|
||
|
|
});
|
||
|
|
|
||
|
|
_capPublisher.Publish("BackgroundOperation.NotifyUser", new BackgroundOperationNotifyMessage
|
||
|
|
{
|
||
|
|
UserId = targetUserId,
|
||
|
|
CurrencyType = currencyType,
|
||
|
|
ChangeType = 2,
|
||
|
|
Amount = amount,
|
||
|
|
NewGold = targetUser.Assets.Gold,
|
||
|
|
NewDiamond = targetUser.Assets.Diamond,
|
||
|
|
Source = "后台扣除",
|
||
|
|
Remark = remark
|
||
|
|
});
|
||
|
|
|
||
|
|
return (true, "扣除成功");
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<(List<BackgroundOperationLog> data, int total)> QueryLogs(
|
||
|
|
string? adminUserId = null,
|
||
|
|
string? targetUserId = null,
|
||
|
|
int? operationType = null,
|
||
|
|
int pageIndex = 1,
|
||
|
|
int pageSize = 20)
|
||
|
|
{
|
||
|
|
var where = LinqExtensions.True<BackgroundOperationLog>();
|
||
|
|
if (!string.IsNullOrEmpty(adminUserId))
|
||
|
|
where = where.And(l => l.AdminUserId == adminUserId);
|
||
|
|
if (!string.IsNullOrEmpty(targetUserId))
|
||
|
|
where = where.And(l => l.TargetUserId == targetUserId);
|
||
|
|
if (operationType.HasValue)
|
||
|
|
where = where.And(l => l.OperationType == operationType.Value);
|
||
|
|
|
||
|
|
var total = await _logRepo.CountAsync(where);
|
||
|
|
var (count, list) = await _logRepo.QueryPageAsync(where, l => l.OperationTime, false, pageSize, pageIndex);
|
||
|
|
|
||
|
|
return (list, (int)total);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<UserEntity> SearchUser(string keyword)
|
||
|
|
{
|
||
|
|
var user = await _userService.SearchUser(keyword);
|
||
|
|
|
||
|
|
|
||
|
|
return user;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|