423 lines
14 KiB
C#
Raw Normal View History

2026-03-06 12:10:09 +08:00
using YD_Event.Application.AppUser.Dtos;
using YD_Event.Application.Auth;
using YD_Event.Core.Entities;
using AppUserEntity = YD_Event.Core.Entities.AppUser;
using YD_Event.Core.Infrastructure.Aliyun.Ocr;
2026-03-12 10:30:13 +08:00
using YD_Event.Core.Enum;
using Mapster;
2026-03-06 12:10:09 +08:00
namespace YD_Event.Application.AppUser;
/// <summary>
/// 普通用户服务
/// </summary>
public class AppUserService : BaseService<AppUserEntity>, ITransient
{
private readonly ISqlSugarRepository<AppUserEntity> _appUserRep;
2026-03-11 16:00:09 +08:00
private readonly ISqlSugarClient _db;
2026-03-06 12:10:09 +08:00
private readonly AuthManager _authManager;
2026-03-12 10:30:13 +08:00
private readonly OcrService _ocrService;
2026-03-06 12:10:09 +08:00
public AppUserService(ISqlSugarRepository<AppUserEntity> appUserRep,
2026-03-11 16:00:09 +08:00
ISqlSugarClient db,
2026-03-12 10:30:13 +08:00
AuthManager authManager,
OcrService ocrService) : base(appUserRep)
2026-03-06 12:10:09 +08:00
{
_appUserRep = appUserRep;
2026-03-11 16:00:09 +08:00
_db = db;
2026-03-06 12:10:09 +08:00
_authManager = authManager;
2026-03-12 10:30:13 +08:00
_ocrService = ocrService;
2026-03-06 12:10:09 +08:00
}
/// <summary>
/// 分页查询普通用户
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("分页查询普通用户")]
2026-03-06 12:10:09 +08:00
[HttpGet("page")]
public async Task<PageResult<AppUserOutput>> Page([FromQuery] AppUserPageInput input)
{
var query = _appUserRep.AsQueryable()
2026-03-11 16:00:09 +08:00
.Where(u => u.PersonType == 0) // 仅查询普通用户
2026-03-06 12:10:09 +08:00
.WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
.WhereIF(input.Gender.HasValue, u => u.Gender == input.Gender)
.WhereIF(!string.IsNullOrWhiteSpace(input.Mobile), u => u.Mobile.Contains(input.Mobile))
.WhereIF(input.AuditStatus.HasValue, u => u.AuditStatus == input.AuditStatus)
.WhereIF(input.StartTime.HasValue, u => u.CreatedTime >= input.StartTime)
.WhereIF(input.EndTime.HasValue, u => u.CreatedTime <= input.EndTime)
.OrderByDescending(u => u.CreatedTime);
return await query.Select<AppUserOutput>().ToPagedListAsync(input);
}
/// <summary>
/// 获取普通用户详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("获取普通用户详情")]
2026-03-06 12:10:09 +08:00
[HttpGet("{id}")]
public async Task<AppUserOutput> Detail([FromRoute] long id)
{
return await _appUserRep.AsQueryable()
.Where(u => u.Id == id)
.Select<AppUserOutput>()
.FirstAsync();
}
/// <summary>
/// 审核普通用户
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("审核普通用户")]
2026-03-06 12:10:09 +08:00
[HttpPost("audit")]
[UnitOfWork]
public async Task Audit([FromBody] AuditInput input)
{
if (input.Ids == null || !input.Ids.Any()) return;
// 更新状态
await _appUserRep.UpdateAsync(u => new AppUserEntity
{
AuditStatus = input.Status,
AuditRemark = input.Remark,
UpdatedTime = DateTime.Now,
UpdatedUserId = _authManager.UserId
}, u => input.Ids.Contains(u.Id));
}
2026-03-11 16:00:09 +08:00
#region 领队/教练管理
/// <summary>
/// 领队/教练列表查询
/// </summary>
/// <param name="input"></param>
/// <param name="personType">1-领队,2-教练</param>
/// <returns></returns>
[NonAction]
private async Task<PageResult<AppUserEntity>> GetMemberPage(TeamMemberQueryInput input, int personType)
{
var (userId, merchantId) = await GetCurrentUserAndMerchantId();
var query = _appUserRep.AsQueryable()
.Where(x => x.PersonType == personType && !x.DeleteMark)
.WhereIF(!string.IsNullOrWhiteSpace(input.Name), x => x.Name.Contains(input.Name))
.WhereIF(input.Gender.HasValue, x => x.Gender == input.Gender)
.WhereIF(!string.IsNullOrWhiteSpace(input.Phone), x => x.Mobile.Contains(input.Phone))
.WhereIF(personType == 2 && !string.IsNullOrWhiteSpace(input.SkillLevel), x => x.SkillLevel == input.SkillLevel)
.WhereIF(personType == 2 && input.CertificationStatus.HasValue, x => x.CertificationStatus == input.CertificationStatus)
.OrderByDescending(x => x.CreatedTime);
// 权限过滤
if (merchantId.HasValue)
{
query = query.Where(x => x.MerchantId == merchantId.Value);
}
else
{
query = query.Where(x => x.CreatedUserId == userId && x.MerchantId == null);
}
return await query.ToPagedListAsync(input);
}
/// <summary>
/// 领队列表查询
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("领队列表查询")]
2026-03-11 16:00:09 +08:00
[HttpGet("leader/page")]
public async Task<PageResult<AppUserEntity>> LeaderPage([FromQuery] TeamMemberQueryInput input)
{
return await GetMemberPage(input, 1);
}
/// <summary>
/// 教练列表查询
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("教练列表查询")]
2026-03-11 16:00:09 +08:00
[HttpGet("coach/page")]
public async Task<PageResult<AppUserEntity>> CoachPage([FromQuery] TeamMemberQueryInput input)
{
return await GetMemberPage(input, 2);
}
/// <summary>
/// 新增/更新成员
/// </summary>
/// <param name="input"></param>
/// <param name="personType">1-领队,2-教练</param>
/// <returns></returns>
[NonAction]
private async Task SaveMember(CreateOrUpdateMemberInput input, int personType)
{
var (userId, merchantId) = await GetCurrentUserAndMerchantId();
// 校验手机号
var query = _appUserRep.AsQueryable()
.Where(x => x.Mobile == input.Phone && x.PersonType == personType && !x.DeleteMark);
if (input.Id.HasValue)
{
query = query.Where(x => x.Id != input.Id.Value);
}
if (merchantId.HasValue)
{
query = query.Where(x => x.MerchantId == merchantId.Value);
}
else
{
query = query.Where(x => x.CreatedUserId == userId && x.MerchantId == null);
}
if (await query.AnyAsync()) throw Oops.Bah($"该手机号的{(personType == 1 ? "领队" : "教练")}已存在");
AppUserEntity entity;
if (input.Id.HasValue)
{
entity = await _appUserRep.GetByIdAsync(input.Id.Value);
if (entity == null || entity.DeleteMark) throw Oops.Bah("成员不存在");
await CheckPermission(entity);
entity.UpdatedUserId = _authManager.UserId;
entity.UpdatedTime = DateTime.Now;
}
else
{
entity = new AppUserEntity
{
Id = YitIdHelper.NextId(),
PersonType = personType,
MerchantId = merchantId,
CreatedUserId = userId,
CreatedTime = DateTime.Now,
Status = AvailabilityStatus.Enable,
AuditStatus = AuditStatus.Pass
};
}
entity.Name = input.Name;
entity.Gender = input.Gender;
entity.Age = input.Age;
entity.IdCardNumber = input.IdCard;
entity.IdCardImageUrl = input.IdCardUrl;
entity.Mobile = input.Phone;
entity.Remark = input.Remark;
entity.AuditRemark = ""; // 或者不赋值
if (personType == 2)
{
entity.SkillLevel = input.SkillLevel;
entity.CertificationStatus = input.CertificationStatus;
}
await _appUserRep.InsertOrUpdateAsync(entity);
}
/// <summary>
/// 新增/编辑领队
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("新增/编辑领队")]
2026-03-11 16:00:09 +08:00
[HttpPost("leader/save")]
public async Task SaveLeader(CreateOrUpdateMemberInput input)
{
await SaveMember(input, 1);
}
/// <summary>
/// 新增/编辑教练
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("新增/编辑教练")]
2026-03-11 16:00:09 +08:00
[HttpPost("coach/save")]
public async Task SaveCoach(CreateOrUpdateMemberInput input)
{
await SaveMember(input, 2);
}
/// <summary>
/// 删除成员
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("删除成员")]
2026-03-11 16:00:09 +08:00
[HttpPost("member/delete")]
public async Task DeleteMember([FromBody] long id)
{
var entity = await _appUserRep.GetByIdAsync(id);
if (entity == null || entity.DeleteMark) throw Oops.Bah("成员不存在");
await CheckPermission(entity);
entity.DeleteMark = true;
entity.UpdatedUserId = _authManager.UserId;
entity.UpdatedTime = DateTime.Now;
await _appUserRep.UpdateAsync(entity);
}
/// <summary>
/// 变更成员状态
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
2026-03-17 15:32:01 +08:00
[DisplayName("变更成员状态")]
2026-03-11 16:00:09 +08:00
[HttpPost("member/status")]
public async Task ChangeMemberStatus(ChangeMemberStatusInput input)
{
var entity = await _appUserRep.GetByIdAsync(input.Id);
if (entity == null || entity.DeleteMark) throw Oops.Bah("成员不存在");
await CheckPermission(entity);
entity.Status = input.Status;
entity.UpdatedUserId = _authManager.UserId;
entity.UpdatedTime = DateTime.Now;
await _appUserRep.UpdateAsync(entity);
}
private async Task<(long userId, long? merchantId)> GetCurrentUserAndMerchantId()
{
var userId = _authManager.UserId;
var merchant = await _db.Queryable<YD_Event.Core.Entities.Merchant>()
.FirstAsync(m => m.CreatedUserId == userId && !m.DeleteMark);
return (userId, merchant?.Id);
}
private async Task CheckPermission(AppUserEntity entity)
{
var (userId, merchantId) = await GetCurrentUserAndMerchantId();
if (merchantId.HasValue)
{
if (entity.MerchantId != merchantId.Value) throw Oops.Bah("无权操作该成员");
}
else
{
if (entity.CreatedUserId != userId || entity.MerchantId != null) throw Oops.Bah("无权操作该成员");
}
}
#endregion
2026-03-12 10:30:13 +08:00
#region 运动员管理
/// <summary>
/// 分页查询运动员
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpGet("athlete/page")]
[DisplayName("分页查询运动员")]
2026-03-14 11:25:39 +08:00
public async Task<PageResult<AthleteOutput>> Page([FromQuery] AthleteQueryInput input)
2026-03-12 10:30:13 +08:00
{
var query = _appUserRep.AsQueryable()
// 过滤运动员类型 (PersonType = 3)
.Where(u => u.PersonType == 3)
.WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
.WhereIF(!string.IsNullOrWhiteSpace(input.IdCardNumber), u => u.IdCardNumber.Contains(input.IdCardNumber))
.WhereIF(input.StartTime.HasValue, u => u.CreatedTime >= input.StartTime)
.WhereIF(input.EndTime.HasValue, u => u.CreatedTime <= input.EndTime)
.OrderByDescending(u => u.CreatedTime);
var list = await query.ToPagedListAsync(input);
return list.Adapt<PageResult<AthleteOutput>>();
}
/// <summary>
/// 新增运动员
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("athlete/add")]
[DisplayName("新增运动员")]
2026-03-14 11:25:39 +08:00
public async Task Add([FromBody] AddAthleteInput input)
2026-03-12 10:30:13 +08:00
{
var isExist = await _appUserRep.IsAnyAsync(u => u.IdCardNumber == input.IdCardNumber && !u.DeleteMark);
if (isExist) throw Oops.Bah("身份证号已存在");
var user = input.Adapt<AppUserEntity>();
user.PersonType = 3; // 运动员
user.Status = AvailabilityStatus.Enable;
// 计算年龄
if (input.BirthDate.HasValue)
{
var today = DateTime.Today;
var age = today.Year - input.BirthDate.Value.Year;
if (input.BirthDate.Value.Date > today.AddYears(-age)) age--;
user.Age = age;
}
await _appUserRep.InsertAsync(user);
}
/// <summary>
/// 修改运动员
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPut("athlete/update")]
[DisplayName("修改运动员")]
2026-03-14 11:25:39 +08:00
public async Task Update([FromBody] UpdateAthleteInput input)
2026-03-12 10:30:13 +08:00
{
var user = await _appUserRep.GetFirstAsync(u => u.Id == input.Id);
if (user == null) throw Oops.Bah("运动员不存在");
var isExist = await _appUserRep.IsAnyAsync(u => u.IdCardNumber == input.IdCardNumber && u.Id != input.Id && !u.DeleteMark);
if (isExist) throw Oops.Bah("身份证号已存在");
input.Adapt(user);
// 重新计算年龄
if (input.BirthDate.HasValue)
{
var today = DateTime.Today;
var age = today.Year - input.BirthDate.Value.Year;
if (input.BirthDate.Value.Date > today.AddYears(-age)) age--;
user.Age = age;
}
await _appUserRep.UpdateAsync(user);
}
/// <summary>
/// 识别身份证信息
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("athlete/ocr")]
[DisplayName("OCR识别身份证")]
2026-03-14 11:25:39 +08:00
public async Task<OcrResult> RecognizeIdCard([FromBody] AthleteOcrInput input)
2026-03-12 10:30:13 +08:00
{
return await _ocrService.RecognizeIdCardAsync(input.ImageUrl);
}
/// <summary>
/// 批量删除运动员
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
[HttpPost("athlete/batchDelete")]
[DisplayName("批量删除运动员")]
public async Task BatchDelete([FromBody] List<long> ids)
{
if (ids == null || !ids.Any()) throw Oops.Bah("请选择要删除的记录");
// 逻辑删除
await _appUserRep.UpdateAsync(x => new AppUserEntity { DeleteMark = true }, x => ids.Contains(x.Id));
}
#endregion
2026-03-06 12:10:09 +08:00
}