using FreeSql; using LiveForum.IService.Others; using LiveForum.IService.Users; using LiveForum.Model; using LiveForum.Model.Dto.Others; using LiveForum.Model.Dto.Users; using Mapster; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace LiveForum.Service.Users { /// /// 用户信息转换服务实现 /// public class UserInfoService : IUserInfoService { private readonly ICertificationTypesCacheService _cacheService; private readonly IBaseRepository _userRepository; private readonly IOptionsSnapshot _appSettingsSnapshot; public UserInfoService( ICertificationTypesCacheService cacheService, IBaseRepository userRepository, IOptionsSnapshot appSettingsSnapshot) { _cacheService = cacheService; _userRepository = userRepository; _appSettingsSnapshot = appSettingsSnapshot; } /// /// 将 T_Users 转换为 UserInfoDto(自动获取认证类型数据) /// public async Task ToUserInfoDtoAsync(T_Users user) { if (user == null) { return null; } var certificationTypesDict = await _cacheService.GetAllCertificationTypesDictionaryAsync(); // 获取默认头像(如果用户头像为空) var avatar = user.Avatar ?? ""; if (string.IsNullOrEmpty(avatar)) { var appSettings = _appSettingsSnapshot.Value; avatar = string.IsNullOrEmpty(appSettings.UserDefaultIcon) ? "" : appSettings.UserDefaultIcon; } //user.Adapt(); return new UserInfoDto { UserId = user.Id, NickName = user.NickName ?? "", Avatar = avatar, IsVip = user.IsVip, CertifiedStatus=user.CertifiedStatus, IsCertified = user.IsCertified, CertifiedType = user.CertifiedType.HasValue && user.CertifiedType.Value > 0 ? certificationTypesDict.GetValueOrDefault(user.CertifiedType.Value) : null }; } /// /// 批量将 T_Users 列表转换为 UserInfoDto 字典(自动获取认证类型数据) /// public async Task> ToUserInfoDtoDictionaryAsync(IEnumerable users) { var result = new Dictionary(); if (users == null) { return result; } // 一次性获取所有认证类型数据 var certificationTypesDict = await _cacheService.GetAllCertificationTypesDictionaryAsync(); // 获取默认头像配置(一次性获取,避免重复调用) var appSettings = _appSettingsSnapshot.Value; var defaultAvatar = string.IsNullOrEmpty(appSettings.UserDefaultIcon) ? "" : appSettings.UserDefaultIcon; foreach (var user in users) { if (user == null) { continue; } // 获取用户头像,如果为空则使用默认头像 var avatar = user.Avatar ?? ""; if (string.IsNullOrEmpty(avatar)) { avatar = defaultAvatar; } var dto = new UserInfoDto { UserId = user.Id, NickName = user.NickName ?? "", Avatar = avatar, IsVip = user.IsVip, CertifiedStatus = user.CertifiedStatus, IsCertified = user.IsCertified, CertifiedType = user.CertifiedType.HasValue && user.CertifiedType.Value > 0 ? certificationTypesDict.GetValueOrDefault(user.CertifiedType.Value) : null }; result[user.Id] = dto; } return result; } /// /// 根据用户ID获取用户信息 /// /// 用户ID /// 用户信息DTO,如果用户不存在则返回null public async Task GetUserInfo(long userId) { // 1. 根据用户ID查询用户 var user = await _userRepository.Select .Where(x => x.Id == userId) .FirstAsync(); // 2. 如果用户不存在,返回null if (user == null) { return null; } // 3. 使用已有的转换方法转换为DTO return await ToUserInfoDtoAsync(user); } /// /// 生成唯一的6位数字UID /// /// 唯一的6位数字UID字符串 public async Task GenerateUniqueUIDAsync() { const int maxRetries = 10; // 最大重试次数,避免无限循环 var random = new Random(); for (int i = 0; i < maxRetries; i++) { // 生成6位随机数(100000-999999) string uid = random.Next(100000, 1000000).ToString(); // 检查数据库中是否已存在该UID var exists = await _userRepository.Select .Where(x => x.UID == uid) .AnyAsync(); if (!exists) { return uid; } } // 如果重试多次仍然冲突,使用时间戳+随机数组合 // 格式:后6位时间戳的毫秒部分 + 2位随机数,取最后6位 var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString(); var fallbackUid = (timestamp.Substring(Math.Max(0, timestamp.Length - 4)) + random.Next(10, 100)).PadLeft(6, '0'); // 再次检查是否冲突 var stillExists = await _userRepository.Select .Where(x => x.UID == fallbackUid) .AnyAsync(); if (stillExists) { // 最后备用方案:使用GUID的前6位数字 var guidHash = Math.Abs(Guid.NewGuid().GetHashCode()).ToString(); return guidHash.Substring(0, Math.Min(6, guidHash.Length)).PadLeft(6, '0'); } return fallbackUid; } } }