mi-assessment/server/MiAssessment/src/MiAssessment.Core/Services/UserService.cs
2026-02-23 21:12:09 +08:00

178 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using MiAssessment.Core.Interfaces;
using MiAssessment.Model.Data;
using MiAssessment.Model.Entities;
using MiAssessment.Model.Models.Auth;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace MiAssessment.Core.Services;
/// <summary>
/// <20>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>
/// </summary>
public class UserService : BaseService<User, long>, IUserService
{
private readonly ILogger<UserService> _logger;
public UserService(MiAssessmentDbContext dbContext, ILogger<UserService> logger)
: base(dbContext)
{
_logger = logger;
}
/// <inheritdoc/>
public async Task<User?> GetUserByIdAsync(long userId)
{
return await _dbSet.FirstOrDefaultAsync(u => u.Id == userId);
}
/// <inheritdoc/>
public async Task<User?> GetUserByOpenIdAsync(string openId)
{
if (string.IsNullOrWhiteSpace(openId))
return null;
return await _dbSet.FirstOrDefaultAsync(u => u.OpenId == openId);
}
/// <inheritdoc/>
public async Task<User?> GetUserByUnionIdAsync(string unionId)
{
if (string.IsNullOrWhiteSpace(unionId))
return null;
return await _dbSet.FirstOrDefaultAsync(u => u.UnionId == unionId);
}
/// <inheritdoc/>
public async Task<User?> GetUserByMobileAsync(string mobile)
{
if (string.IsNullOrWhiteSpace(mobile))
return null;
return await _dbSet.FirstOrDefaultAsync(u => u.Phone == mobile);
}
/// <inheritdoc/>
public async Task<User> CreateUserAsync(CreateUserDto dto)
{
if (dto == null)
throw new ArgumentNullException(nameof(dto));
// <20><><EFBFBD><EFBFBD>ΨһUID
var uid = await GenerateUidAsync();
var user = new User
{
OpenId = dto.OpenId ?? string.Empty,
UnionId = dto.UnionId,
Phone = dto.Mobile,
Uid = uid,
Nickname = dto.Nickname ?? $"User{Random.Shared.Next(1000, 9999)}",
Avatar = dto.Headimg ?? string.Empty,
ParentUserId = dto.Pid > 0 ? dto.Pid : null,
Status = 1,
IsTest = 0,
CreateTime = DateTime.Now,
UpdateTime = DateTime.Now
};
await _dbSet.AddAsync(user);
await _dbContext.SaveChangesAsync();
_logger.LogInformation($"User created: Id={user.Id}, Uid={user.Uid}, OpenId={user.OpenId}");
return user;
}
/// <inheritdoc/>
public async Task UpdateUserAsync(long userId, UpdateUserDto dto)
{
if (dto == null)
throw new ArgumentNullException(nameof(dto));
var user = await GetUserByIdAsync(userId);
if (user == null)
throw new InvalidOperationException($"User with id {userId} not found");
if (!string.IsNullOrWhiteSpace(dto.Nickname))
user.Nickname = dto.Nickname;
if (!string.IsNullOrWhiteSpace(dto.Headimg))
user.Avatar = dto.Headimg;
if (!string.IsNullOrWhiteSpace(dto.Mobile))
user.Phone = dto.Mobile;
if (!string.IsNullOrWhiteSpace(dto.UnionId))
user.UnionId = dto.UnionId;
user.UpdateTime = DateTime.Now;
_dbSet.Update(user);
await _dbContext.SaveChangesAsync();
_logger.LogInformation($"User updated: Id={user.Id}");
}
/// <inheritdoc/>
public async Task<UserInfoDto?> GetUserInfoAsync(long userId)
{
var user = await GetUserByIdAsync(userId);
if (user == null)
return null;
var registrationDays = (int)(DateTime.Now - user.CreateTime).TotalDays;
var maskedMobile = MaskMobileNumber(user.Phone);
var mobileIs = string.IsNullOrWhiteSpace(user.Phone) ? 0 : 1;
return new UserInfoDto
{
Id = user.Id,
Uid = user.Uid,
Nickname = user.Nickname,
Headimg = user.Avatar,
Mobile = maskedMobile,
MobileIs = mobileIs,
Vip = 0, // 用户等级,待接入业务逻辑
Day = registrationDays
};
}
/// <inheritdoc/>
public Task<int> CalculateVipLevelAsync(long userId, int currentVip)
{
// VIP<49>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><E3B9A6><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0
return Task.FromResult(0);
}
/// <summary>
/// <20><><EFBFBD><EFBFBD>6λΨһ<CEA8>û<EFBFBD>UID
/// </summary>
private async Task<string> GenerateUidAsync()
{
const int maxAttempts = 10;
for (var i = 0; i < maxAttempts; i++)
{
var uid = Random.Shared.Next(100000, 999999).ToString();
var exists = await _dbSet.AnyAsync(u => u.Uid == uid);
if (!exists)
return uid;
}
// <20><><EFBFBD>ף<EFBFBD>ʹ<EFBFBD><CAB9>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString()[^6..];
}
/// <summary>
/// Mask mobile number for privacy (e.g., 13812345678 -> 138****5678)
/// </summary>
private string? MaskMobileNumber(string? mobile)
{
if (string.IsNullOrWhiteSpace(mobile) || mobile.Length < 11)
return null;
return $"{mobile.Substring(0, 3)}****{mobile.Substring(mobile.Length - 4)}";
}
}