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 _logRepo; private readonly IUserService _userService; private readonly ICapPublisher _capPublisher; private readonly IMongoBaseRepository _adminRepo; private readonly IRedisService _redisService; private readonly ILogger _logger; public BackgroundOperationService( IMongoBaseRepository logRepo, IUserService userService, ICapPublisher capPublisher, IMongoBaseRepository adminRepo, IRedisService redisService, ILogger 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 data, int total)> QueryLogs( string? adminUserId = null, string? targetUserId = null, int? operationType = null, int pageIndex = 1, int pageSize = 20) { var where = LinqExtensions.True(); 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 SearchUser(string keyword) { var user = await _userService.SearchUser(keyword); return user; } } }