using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AdminService.GameConfigs; using AdminService.User; using AdminService.User.Param; using AdminService.User.Response; using Common; using Common.Utils; using CommonDomain; using CommonDomain.BaseModel; using CommonDomain.Enum; using CommonInfrastructure; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using RedisService; using UserDomain.Entity; namespace AdminApi.AdminUser { [ApiController, Route("adminapi/[controller]")] [Authorize] public class AdminUserController : BaseController { private readonly IAdminUserService _userService; private readonly IRedisService _redisService; public AdminUserController(IAdminUserService userService, IRedisService redisService) { _userService = userService; _redisService = redisService; } /// /// 获取用户列表(管理员专用,增强版) /// [HttpPost("GetUserList")] public async Task> GetUserList(AdminUserListParam param) { var result = await _userService.GetAdminUserList(param); var onlineUserIds = _redisService.GetAllLoginUserIds().ToHashSet(StringComparer.Ordinal); var dtos = (result.list ?? new List()).Select(u => { var dto = MapToUserListItemDto(u); dto.IsOnline = onlineUserIds.Contains(u.Id); if (dto.CurrentGameType != 3) { var session = _redisService.GetRedisUserCId(u.Id); if (session == null || string.IsNullOrWhiteSpace(session.RoomId)) { dto.CurrentGameType = 0; dto.RoomNumber = ""; } } return dto; }).ToList(); return this.ToPageResult(dtos, result.count); } /// /// 获取用户详情 /// [HttpGet("GetUserDetail")] public async Task> GetUserDetail(string userId) { var result = await _userService.GetUser(userId); if (result == null) return this.ToFailResult("用户不存在"); return this.ToResult(result); } /// /// 修改用户资产 /// [HttpPost("UpdateUserAssets")] public async Task> UpdateUserAssets(UpdateUserAssetsParam param) { var result = await _userService.UpdateUserAssets(param); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 获取用户统计数据 /// [HttpGet("GetUserStatistics")] public async Task> GetUserStatistics() { var result = await _userService.GetUserStatistics(); return this.ToResult(MapToUserStatisticsDto(result)); } /// /// 获取邮件统计数据 /// [HttpGet("GetEmailStatistics")] public async Task> GetEmailStatistics() { var result = await _userService.GetEmailStatistics(); return this.ToResult(MapToEmailStatisticsDto(result)); } /// /// 批量封号 /// [HttpPost("BatchBanUser")] public async Task> BatchBanUser(BatchBanUserParam param) { var result = await _userService.BatchBanUser(param); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 解封用户 /// [HttpGet("UnbanUser")] public async Task> UnbanUser(string userId) { var result = await _userService.UnbanUser(userId); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 批量发送邮件 /// [HttpPost("BatchSendEmail")] public async Task> BatchSendEmail(BatchSendEmailParam param) { var result = await _userService.BatchSendEmail(param); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 注销用户 /// [HttpGet("CancelUser")] [Authorize] public async Task> CancelUser() { var result = await _userService.CancelUser(loginUser); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 删除用户 /// [HttpGet("DeleteUser")] [Authorize] public async Task> DeleteUser(string id) { var result = await _userService.DeleteUser(id); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 批量删除用户 /// [HttpPost("BatchDeleteUser")] [Authorize] public async Task> BatchDeleteUser([FromBody] BatchDeleteUserParam param) { var result = await _userService.BatchDeleteUser(param.UserIds); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 封号 /// [HttpPost("BanUser")] [Authorize] public async Task> BanUser([FromBody] BanUserParam param) { var result = await _userService.BanUser(param.UserId, param.Reason, param.Days); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 更新用户信息 /// [HttpPost("UpdateUser")] [Authorize] public async Task> UpdateUser(UpdateUserDataParam param) { var result = await _userService.UpdateUser(param); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 发送邮件 /// [HttpPost("SendEmail")] [Authorize] public async Task> SendEmail(SendEmailParam param) { var result = await _userService.SendEmail(param, loginUser); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 分页查询邮件列表 /// [HttpPost("GetEmailList")] [Authorize] public async Task> GetEmailList([FromBody] EmailListQueryParam param) { var (list, count) = await _userService.GetEmailList(param); var userIds = list.Where(e => !string.IsNullOrWhiteSpace(e.UserId)) .Select(e => e.UserId).Distinct().ToList(); var userNames = await _userService.GetEmailUserNamesAsync(userIds); var dtos = list.Select(e => { userNames.TryGetValue(e.UserId ?? "", out var info); return new EmailListItemDto { Id = e.Id, UserId = e.UserId ?? "", UserName = info.UserName, UserNumber = info.UserNumber, Title = e.Title ?? "", IsRead = e.IsRead, IsReward = e.IsReward, RewardGold = e.RewardGold, RewardDiamond = e.RewardDiamond, SendTime = e.SendTime, ReadTime = e.ReadTime, ExpireTime = e.ExpireTime, RewardText = BuildRewardText(e) }; }).ToList(); return this.ToPageResult(dtos, (int)count); } /// /// 删除邮件 /// [HttpGet("DeleteEmail")] [Authorize] public async Task> DeleteEmail(string id) { var result = await _userService.DeleteEmail(id); if (result.ok) return this.ToResult("删除成功"); else return this.ToFailResult(result.message ?? "删除失败"); } /// /// 批量删除邮件 /// [HttpPost("BatchDeleteEmail")] [Authorize] public async Task> BatchDeleteEmail([FromBody] List ids) { var (success, fail) = await _userService.BatchDeleteEmail(ids); if (fail == 0) return this.ToResult($"成功删除 {success} 条"); return this.ToResult($"删除完成:成功 {success} 条,失败 {fail} 条"); } /// /// 设置用户类型 /// [HttpPost("SetUserType")] public async Task> SetUserType(string userId, int userType) { var result = await _userService.SetUserType(userId, userType); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 批量设置用户类型 /// [HttpPost("BatchSetUserType")] public async Task> BatchSetUserType([FromBody] BatchSetUserTypeParam param) { var result = await _userService.BatchSetUserType(param.UserIds, param.UserType); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 设置屏蔽状态 /// [HttpPost("SetBlackUser")] public async Task> SetBlackUser(string userId, bool isBlack) { var result = await _userService.SetBlackUser(userId, isBlack); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 批量设置屏蔽状态 /// [HttpPost("BatchSetBlackUser")] public async Task> BatchSetBlackUser([FromBody] BatchSetBlackUserParam param) { var result = await _userService.BatchSetBlackUser(param.UserIds, param.IsBlack); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 更新用户因子 /// [HttpPost("UpdateUserFactor")] public async Task> UpdateUserFactor([FromBody] UpdateUserFactorFlatParam param) { var factor = new PlayerFactor { ViolateValue = param.ViolateValue, MissRate = param.MissRate, CompensateQuota = param.CompensateQuota, PenaltyQuota = param.PenaltyQuota, CompensateRate = param.CompensateRate, PenaltyRate = param.PenaltyRate, AdditionalFactor = param.AdditionalFactor }; var result = await _userService.UpdateUserFactor(param.UserId, factor); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 获取屏蔽用户因子配置 /// [HttpGet("GetBlackFactorConfig")] public async Task> GetBlackFactorConfig() { var result = await _userService.GetBlackFactorConfig(); return this.ToResult(MapToPlayerFactorDto(result)); } /// /// 重置用户因子为默认值 /// [HttpPost("ResetUserFactor")] public async Task> ResetUserFactor(string userId) { var result = await _userService.ResetUserFactor(userId); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 初始化用户密码为123456 /// [HttpGet("InitUserPassword")] public async Task> InitUserPassword([FromQuery] string userId) { var result = await _userService.InitUserPassword(userId); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 初始化保险箱密码为123456 /// [HttpGet("InitSafeBoxPassword")] public async Task> InitSafeBoxPassword([FromQuery] string userId) { var result = await _userService.InitSafeBoxPassword(userId); if (result.isok) return this.ToResult(result.msg); else return this.ToFailResult(result.msg); } /// /// 获取用户因子列表 /// [HttpPost("GetUserFactorList")] public async Task> GetUserFactorList([FromBody] UserFactorListParam param) { var result = await _userService.GetUserFactorList(param); var pageIps = (result.list ?? new List()) .Where(u => !string.IsNullOrEmpty(u.RegisterIp)) .Select(u => u.RegisterIp!) .Distinct() .ToList(); Dictionary ipCounts = new Dictionary(); if (pageIps.Count > 0) { var allUsersWithSameIp = await _userService.GetUsersByRegisterIps(pageIps); ipCounts = allUsersWithSameIp .GroupBy(u => u.RegisterIp) .ToDictionary(g => g.Key, g => g.Count()); } var dtos = (result.list ?? new List()).Select(u => new UserFactorListItemDto { Id = u.Id, Number = u.BaseInfo?.Number ?? "", UserName = u.BaseInfo?.UserName ?? "", Mobile = u.BaseInfo?.Mobile ?? "", UserType = u.UserType, RegisterIp = u.RegisterIp ?? "", LoginIp = u.Static?.LastLoginIp ?? "", IpCount = !string.IsNullOrEmpty(u.RegisterIp) && ipCounts.ContainsKey(u.RegisterIp) ? ipCounts[u.RegisterIp] : 1, IsBlack = u.PlayerFactor?.IsBlack ?? false, ViolateValue = u.PlayerFactor?.ViolateValue ?? 0.2, MissRate = u.PlayerFactor?.MissRate ?? 0, CompensateQuota = u.PlayerFactor?.CompensateQuota ?? 0, PenaltyQuota = u.PlayerFactor?.PenaltyQuota ?? 0, CompensateRate = u.PlayerFactor?.CompensateRate != null ? new CompensateRateDto { BossRate = u.PlayerFactor.CompensateRate.BossRate, GoldRate = u.PlayerFactor.CompensateRate.GoldRate, SpecialRate = u.PlayerFactor.CompensateRate.SpecialRate, Ordinary = u.PlayerFactor.CompensateRate.Ordinary } : new CompensateRateDto(), PenaltyRate = u.PlayerFactor?.PenaltyRate != null ? new PenaltyRateDto { BossRate = u.PlayerFactor.PenaltyRate.BossRate, GoldRate = u.PlayerFactor.PenaltyRate.GoldRate, SpecialRate = u.PlayerFactor.PenaltyRate.SpecialRate, Ordinary = u.PlayerFactor.PenaltyRate.Ordinary } : new PenaltyRateDto(), CreateTime = u.CreateTime, TotalRecharge = u.Static?.TotalRecharge ?? 0, TotalRechargeGold = u.Static?.TotalRechargeGold ?? 0, TotalConsumeGold = u.Static?.TotalConsumeGold ?? 0, CurrentGold = u.Assets?.Gold ?? 0, Profit = (u.Assets?.Gold ?? 0) - ((u.Static?.TotalRechargeGold ?? 0) + (u.PlayerFactor?.StartingBonus ?? 0)), AdditionalFactor = u.PlayerFactor?.AdditionalFactor ?? 0, StartingBonus = u.PlayerFactor?.StartingBonus ?? 0 }); return this.ToPageResult(dtos, result.count); } private static UserListItemDto MapToUserListItemDto(UserEntity entity) { return new UserListItemDto { Id = entity.Id, Number = entity.BaseInfo?.Number ?? "", NickName = entity.BaseInfo?.UserName ?? "", Avatar = entity.BaseInfo?.AvatarUrl ?? "", Mobile = entity.BaseInfo?.Mobile ?? "", Diamond = entity.Assets?.Diamond ?? 0, Gold = entity.Assets?.Gold ?? 0, SafeBoxGold = entity.SafeBox?.Amount ?? 0, VipLevel = entity.Assets?.VipLevel ?? 0, UserType = entity.UserType, IsBan = entity.BanInfo?.IsBan ?? false, BanReason = entity.BanInfo?.BanReason, BanEndTime = entity.BanInfo?.BanEndTime ?? 0, IsBlack = entity.PlayerFactor?.IsBlack ?? false, RegisterTime = entity.CreateTime, RegisterIp = entity.RegisterIp ?? "", LastLoginIp = entity.Static?.LastLoginIp ?? "", LastLoginTime = entity.Static?.LastLoginTime ?? 0, RoomNumber = entity.Static?.RoomNumber ?? "", CurrentGameType = entity.Static?.CurrentGameType ?? 0, Channel = entity.BaseInfo?.Channel ?? "", TotalRecharge = (long)(entity.Static?.TotalRecharge ?? 0) }; } private static UserStatisticsDto MapToUserStatisticsDto(UserStatistics stat) { return new UserStatisticsDto { TotalUsers = stat.TotalUsers, TodayRegisteredUsers = stat.TodayRegisteredUsers, MonthRegisteredUsers = stat.MonthRegisteredUsers, OnlineUsers = stat.OnlineUsers, BannedUsers = stat.BannedUsers, VipUsers = stat.VipUsers, VipLevelCount = stat.VipLevelCount ?? new Dictionary(), TotalGold = stat.TotalGold, TotalDiamond = stat.TotalDiamond }; } private static EmailStatisticsDto MapToEmailStatisticsDto(EmailStatistics stat) { return new EmailStatisticsDto { TotalEmails = stat.TotalEmails, RewardEmails = stat.RewardEmails, UnclaimedEmails = stat.UnclaimedEmails, TodayEmails = stat.TodayEmails, MonthEmails = stat.MonthEmails }; } private static PlayerFactorDto MapToPlayerFactorDto(PlayerFactor factor) { if (factor == null) return new PlayerFactorDto(); return new PlayerFactorDto { IsBlack = factor.IsBlack, IsIgnore = factor.IsIgnore, ViolateValue = factor.ViolateValue, CompensateRate = factor.CompensateRate?.BossRate ?? 1, PenaltyRate = factor.PenaltyRate?.BossRate ?? 0, CompensateQuota = factor.CompensateQuota, PenaltyQuota = factor.PenaltyQuota, StartingBonus = factor.StartingBonus }; } private static string BuildRewardText(UserEmail email) { var parts = new List(); if (email.RewardGold > 0) parts.Add($"金币{email.RewardGold:N0}"); if (email.RewardDiamond > 0) parts.Add($"钻石{email.RewardDiamond}"); if (email.RewardItems != null) { foreach (var item in email.RewardItems) { if (item != null && !string.IsNullOrWhiteSpace(item.Name)) parts.Add($"{item.Name}*{item.Count}"); } } return parts.Count > 0 ? string.Join(" ", parts) : "无"; } /// /// 获取用户背包道具 /// [HttpGet("GetUserProps")] public async Task>> GetUserProps(string userId) { var result = await _userService.GetUserProps(userId); return this.ToResult(result); } /// /// 添加用户背包道具 /// [HttpPost("AddUserProp")] public async Task> AddUserProp(string userId, string propNumber, int count) { var res = await _userService.AddUserProp(userId, propNumber, count); if (res.isok) return this.ToResult(res.msg); return this.ToFailResult(res.msg); } /// /// 修改用户道具数量(数量设为0则删除) /// [HttpPost("UpdateUserPropCount")] public async Task> UpdateUserPropCount(string userId, string propNumber, int count) { var res = await _userService.UpdateUserPropCount(userId, propNumber, count); if (res.isok) return this.ToResult(res.msg); return this.ToFailResult(res.msg); } /// /// 删除用户道具 /// [HttpPost("DeleteUserProp")] public async Task> DeleteUserProp(string userId, string propNumber) { var res = await _userService.DeleteUserProp(userId, propNumber); if (res.isok) return this.ToResult(res.msg); return this.ToFailResult(res.msg); } /// /// 同步所有玩家的等级(根据经验值+充值重新计算) /// [HttpGet("SyncAllUserLevel")] public async Task> SyncAllUserLevel() { var (total, updated, msg) = await _userService.SyncAllUserLevel(); return this.ToResult(msg); } } public class UserListItemDto { public string Id { get; set; } public string Number { get; set; } public string NickName { get; set; } public string Avatar { get; set; } public string Mobile { get; set; } public int Diamond { get; set; } public long Gold { get; set; } public long SafeBoxGold { get; set; } public int VipLevel { get; set; } public int UserType { get; set; } public bool IsBan { get; set; } public string BanReason { get; set; } public long BanEndTime { get; set; } public bool IsBlack { get; set; } public long RegisterTime { get; set; } public string RegisterIp { get; set; } public string LastLoginIp { get; set; } public long LastLoginTime { get; set; } public string RoomNumber { get; set; } public int CurrentGameType { get; set; } public bool IsOnline { get; set; } public string Channel { get; set; } public long TotalRecharge { get; set; } } public class UserStatisticsDto { public long TotalUsers { get; set; } public long TodayRegisteredUsers { get; set; } public long MonthRegisteredUsers { get; set; } public long OnlineUsers { get; set; } public long BannedUsers { get; set; } public long VipUsers { get; set; } public Dictionary VipLevelCount { get; set; } public long TotalGold { get; set; } public long TotalDiamond { get; set; } } public class EmailStatisticsDto { public long TotalEmails { get; set; } public long RewardEmails { get; set; } public long UnclaimedEmails { get; set; } public long TodayEmails { get; set; } public long MonthEmails { get; set; } } public class PlayerFactorDto { public bool IsBlack { get; set; } public bool IsIgnore { get; set; } public double ViolateValue { get; set; } public double CompensateRate { get; set; } public double PenaltyRate { get; set; } public int CompensateQuota { get; set; } public int PenaltyQuota { get; set; } public long StartingBonus { get; set; } } public class UserFactorListItemDto { public string Id { get; set; } public string Number { get; set; } public string UserName { get; set; } public string Mobile { get; set; } public int UserType { get; set; } public string RegisterIp { get; set; } public string LoginIp { get; set; } public int IpCount { get; set; } public bool IsBlack { get; set; } public double ViolateValue { get; set; } public double MissRate { get; set; } public int CompensateQuota { get; set; } public int PenaltyQuota { get; set; } public CompensateRateDto CompensateRate { get; set; } public PenaltyRateDto PenaltyRate { get; set; } public long CreateTime { get; set; } public double TotalRecharge { get; set; } public long TotalRechargeGold { get; set; } public long TotalConsumeGold { get; set; } public long CurrentGold { get; set; } public long Profit { get; set; } public double AdditionalFactor { get; set; } public long StartingBonus { get; set; } } public class CompensateRateDto { public double BossRate { get; set; } = 1; public double GoldRate { get; set; } = 1; public double SpecialRate { get; set; } = 1; public double Ordinary { get; set; } = 1; } public class PenaltyRateDto { public double BossRate { get; set; } = 1; public double GoldRate { get; set; } = 1; public double SpecialRate { get; set; } = 1; public double Ordinary { get; set; } = 1; } public class BanUserParam { public string UserId { get; set; } = ""; public string Reason { get; set; } = ""; public int Days { get; set; } = 0; } public class EmailListItemDto { public string Id { get; set; } = ""; public string UserId { get; set; } = ""; public string UserName { get; set; } = ""; public string UserNumber { get; set; } = ""; public string Title { get; set; } = ""; public bool IsRead { get; set; } public bool IsReward { get; set; } public long RewardGold { get; set; } public int RewardDiamond { get; set; } public long SendTime { get; set; } public long ReadTime { get; set; } public long ExpireTime { get; set; } public string RewardText { get; set; } = ""; } }