198 lines
6.9 KiB
C#
198 lines
6.9 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 用户信息转换服务实现
|
||
/// </summary>
|
||
public class UserInfoService : IUserInfoService
|
||
{
|
||
private readonly ICertificationTypesCacheService _cacheService;
|
||
private readonly IBaseRepository<T_Users> _userRepository;
|
||
private readonly IOptionsSnapshot<AppSettings> _appSettingsSnapshot;
|
||
|
||
public UserInfoService(
|
||
ICertificationTypesCacheService cacheService,
|
||
IBaseRepository<T_Users> userRepository,
|
||
IOptionsSnapshot<AppSettings> appSettingsSnapshot)
|
||
{
|
||
_cacheService = cacheService;
|
||
_userRepository = userRepository;
|
||
_appSettingsSnapshot = appSettingsSnapshot;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将 T_Users 转换为 UserInfoDto(自动获取认证类型数据)
|
||
/// </summary>
|
||
public async Task<UserInfoDto> 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<UserInfoDto>();
|
||
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
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批量将 T_Users 列表转换为 UserInfoDto 字典(自动获取认证类型数据)
|
||
/// </summary>
|
||
public async Task<Dictionary<long, UserInfoDto>> ToUserInfoDtoDictionaryAsync(IEnumerable<T_Users> users)
|
||
{
|
||
var result = new Dictionary<long, UserInfoDto>();
|
||
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据用户ID获取用户信息
|
||
/// </summary>
|
||
/// <param name="userId">用户ID</param>
|
||
/// <returns>用户信息DTO,如果用户不存在则返回null</returns>
|
||
public async Task<UserInfoDto> 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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成唯一的6位数字UID
|
||
/// </summary>
|
||
/// <returns>唯一的6位数字UID字符串</returns>
|
||
public async Task<string> 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;
|
||
}
|
||
}
|
||
}
|
||
|