2026-03-31 15:54:27 +08:00
|
|
|
using EasyCaching.Core;
|
2026-03-14 06:13:06 +08:00
|
|
|
using Microsoft.Extensions.Logging;
|
2026-08-07 14:59:15 +08:00
|
|
|
using System.Text.RegularExpressions;
|
2025-12-17 11:12:13 +08:00
|
|
|
using YD_Event.Application.Client.Dtos;
|
2025-12-17 10:32:52 +08:00
|
|
|
|
2025-12-17 11:12:13 +08:00
|
|
|
namespace YD_Event.Application.Client;
|
2026-03-14 06:13:06 +08:00
|
|
|
|
2025-12-17 10:32:52 +08:00
|
|
|
/// <summary>
|
2026-03-14 06:13:06 +08:00
|
|
|
/// 微信小程序认证接口
|
2025-12-17 10:32:52 +08:00
|
|
|
/// </summary>
|
2025-12-27 12:53:54 +08:00
|
|
|
[ApiDescriptionSettings("微信小程序接口")]
|
2025-12-17 10:32:52 +08:00
|
|
|
public class OAuthController : IDynamicApiController
|
|
|
|
|
{
|
2026-03-14 06:13:06 +08:00
|
|
|
private readonly ISqlSugarRepository<YD_Event.Core.Entities.AppUser> _appUserRepository;
|
2026-09-17 16:09:08 +08:00
|
|
|
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Referee> _refereeRepository;
|
2026-03-31 15:54:27 +08:00
|
|
|
private readonly IEasyCachingProvider _cachingProvider;
|
2025-12-17 10:32:52 +08:00
|
|
|
private readonly IIdGenerator _idGenerator;
|
2026-03-14 06:13:06 +08:00
|
|
|
private readonly ILogger<OAuthController> _logger;
|
|
|
|
|
|
2026-03-30 21:39:00 +08:00
|
|
|
private const string SmsCodeCachePrefix = "sms:code:";
|
2026-09-30 08:38:21 +08:00
|
|
|
private const long RefereeAccessTokenExpiredMinutes = 24 * 60;
|
|
|
|
|
private const int DefaultAccessTokenExpiresInSeconds = 2 * 60 * 60;
|
|
|
|
|
private const int RefereeAccessTokenExpiresInSeconds = 24 * 60 * 60;
|
2025-12-17 10:32:52 +08:00
|
|
|
|
2026-03-14 06:13:06 +08:00
|
|
|
public OAuthController(
|
|
|
|
|
ISqlSugarRepository<YD_Event.Core.Entities.AppUser> appUserRepository,
|
2026-09-17 16:09:08 +08:00
|
|
|
ISqlSugarRepository<YD_Event.Core.Entities.Referee> refereeRepository,
|
2026-03-31 15:54:27 +08:00
|
|
|
IEasyCachingProvider cachingProvider,
|
2026-03-14 06:13:06 +08:00
|
|
|
IIdGenerator idGenerator,
|
|
|
|
|
ILogger<OAuthController> logger)
|
2025-12-17 10:32:52 +08:00
|
|
|
{
|
2026-03-14 06:13:06 +08:00
|
|
|
_appUserRepository = appUserRepository;
|
2026-09-17 16:09:08 +08:00
|
|
|
_refereeRepository = refereeRepository;
|
2026-03-31 15:54:27 +08:00
|
|
|
_cachingProvider = cachingProvider;
|
2025-12-17 10:32:52 +08:00
|
|
|
_idGenerator = idGenerator;
|
2026-03-14 06:13:06 +08:00
|
|
|
_logger = logger;
|
2025-12-17 10:32:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-08-07 14:59:15 +08:00
|
|
|
/// 登录接口(支持手机号密码登录和短信验证码登录;检录员仅支持密码)
|
2025-12-17 10:32:52 +08:00
|
|
|
/// </summary>
|
2026-03-14 06:13:06 +08:00
|
|
|
/// <param name="input"></param>
|
2025-12-17 10:32:52 +08:00
|
|
|
/// <returns></returns>
|
2026-03-14 06:13:06 +08:00
|
|
|
[HttpPost("login")]
|
2025-12-17 10:32:52 +08:00
|
|
|
[AllowAnonymous]
|
2026-03-30 21:39:00 +08:00
|
|
|
public async Task<MiniProgramLoginOutput> Login([FromBody] MiniProgramLoginInput input)
|
2025-12-17 10:32:52 +08:00
|
|
|
{
|
2026-08-07 14:59:15 +08:00
|
|
|
var mobile = input.Mobile?.Trim() ?? string.Empty;
|
|
|
|
|
if (!Regex.IsMatch(mobile, @"^1[3-9]\d{9}$")) throw Oops.Bah("手机号格式不正确");
|
|
|
|
|
|
2026-03-31 16:31:48 +08:00
|
|
|
var isPasswordLogin = !string.IsNullOrEmpty(input.Password);
|
|
|
|
|
var isSmsLogin = !string.IsNullOrEmpty(input.VerificationCode);
|
|
|
|
|
|
|
|
|
|
if (!isPasswordLogin && !isSmsLogin)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Bah("请选择密码登录或短信验证码登录");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isPasswordLogin && isSmsLogin)
|
2026-03-30 21:39:00 +08:00
|
|
|
{
|
2026-03-31 16:31:48 +08:00
|
|
|
throw Oops.Bah("请选择一种登录方式");
|
2026-03-30 21:39:00 +08:00
|
|
|
}
|
2026-03-14 06:13:06 +08:00
|
|
|
|
2026-08-07 14:59:15 +08:00
|
|
|
YD_Event.Core.Entities.AppUser? appUser;
|
|
|
|
|
if (isPasswordLogin)
|
|
|
|
|
{
|
|
|
|
|
appUser = await _appUserRepository.GetFirstAsync(x => !x.DeleteMark && x.Mobile == mobile);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
appUser = await _appUserRepository.GetFirstAsync(x => !x.DeleteMark && x.Mobile == mobile);
|
|
|
|
|
}
|
2026-04-15 09:58:05 +08:00
|
|
|
|
|
|
|
|
// 统一的未注册账户判断逻辑
|
|
|
|
|
bool isRegistered = appUser != null && !string.IsNullOrEmpty(appUser.Password);
|
|
|
|
|
|
|
|
|
|
if (!isRegistered)
|
2025-12-17 10:32:52 +08:00
|
|
|
{
|
2026-04-16 16:43:11 +08:00
|
|
|
if (appUser == null || string.IsNullOrEmpty(appUser.Password))
|
2026-03-14 06:13:06 +08:00
|
|
|
{
|
2026-04-13 13:23:00 +08:00
|
|
|
throw Oops.Bah("未注册过账户");
|
2026-03-14 06:13:06 +08:00
|
|
|
}
|
2026-04-15 09:58:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isPasswordLogin)
|
|
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUser.Id)}{input.Password}");
|
|
|
|
|
if (appUser.Password != encryptedPassword)
|
2026-03-14 06:13:06 +08:00
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
throw Oops.Bah("密码错误");
|
2026-03-14 06:13:06 +08:00
|
|
|
}
|
|
|
|
|
}
|
2026-03-31 16:31:48 +08:00
|
|
|
else
|
|
|
|
|
{
|
2026-08-07 14:59:15 +08:00
|
|
|
if (appUser.MiniProgramRole == MiniProgramRole.Checker)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Bah("检录员仅支持手机号密码登录");
|
|
|
|
|
}
|
|
|
|
|
var cacheKey = $"{SmsCodeCachePrefix}{mobile}";
|
2026-03-31 16:31:48 +08:00
|
|
|
var cachedCodeResult = _cachingProvider.Get<string>(cacheKey);
|
|
|
|
|
string cachedCode = cachedCodeResult.Value;
|
|
|
|
|
if (!cachedCodeResult.HasValue || cachedCode != input.VerificationCode)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Bah("验证码错误或已过期");
|
|
|
|
|
}
|
|
|
|
|
_cachingProvider.Remove(cacheKey);
|
|
|
|
|
}
|
2026-03-14 06:13:06 +08:00
|
|
|
|
2026-03-30 21:39:00 +08:00
|
|
|
(string accessToken, string refreshToken) = GenerateTokens(appUser);
|
|
|
|
|
|
|
|
|
|
var userInfo = new
|
|
|
|
|
{
|
|
|
|
|
appUser.Name,
|
|
|
|
|
appUser.Id,
|
|
|
|
|
appUser.Mobile,
|
|
|
|
|
appUser.Avatar,
|
2026-08-07 14:59:15 +08:00
|
|
|
appUser.NickName,
|
|
|
|
|
Role = ToRoleCode(appUser.MiniProgramRole),
|
|
|
|
|
RoleType = (int)NormalizeRole(appUser.MiniProgramRole)
|
2026-03-30 21:39:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new MiniProgramLoginOutput
|
2026-03-14 06:13:06 +08:00
|
|
|
{
|
|
|
|
|
AccessToken = accessToken,
|
|
|
|
|
RefreshToken = refreshToken,
|
2026-09-30 08:38:21 +08:00
|
|
|
ExpiresIn = appUser.MiniProgramRole == MiniProgramRole.Referee
|
|
|
|
|
? RefereeAccessTokenExpiresInSeconds
|
|
|
|
|
: DefaultAccessTokenExpiresInSeconds,
|
2026-03-14 06:13:06 +08:00
|
|
|
UserInfo = userInfo
|
2025-12-17 10:32:52 +08:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-03-14 06:13:06 +08:00
|
|
|
/// 注册接口
|
2025-12-17 10:32:52 +08:00
|
|
|
/// </summary>
|
2026-03-14 06:13:06 +08:00
|
|
|
/// <param name="input"></param>
|
2025-12-17 10:32:52 +08:00
|
|
|
/// <returns></returns>
|
2026-03-14 06:13:06 +08:00
|
|
|
[HttpPost("register")]
|
2025-12-17 10:32:52 +08:00
|
|
|
[AllowAnonymous]
|
2026-03-14 06:13:06 +08:00
|
|
|
[UnitOfWork]
|
2026-03-30 21:39:00 +08:00
|
|
|
public async Task<MiniProgramRegisterOutput> Register([FromBody] MiniProgramRegisterInput input)
|
2025-12-17 10:32:52 +08:00
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
var cacheKey = $"{SmsCodeCachePrefix}{input.Mobile}";
|
2026-03-31 15:54:27 +08:00
|
|
|
var cachedCodeResult = _cachingProvider.Get<string>(cacheKey);
|
|
|
|
|
string cachedCode = cachedCodeResult.Value;
|
|
|
|
|
if (!cachedCodeResult.HasValue || cachedCode != input.VerificationCode)
|
2025-12-17 10:32:52 +08:00
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
throw Oops.Bah("验证码错误或已过期");
|
2025-12-17 10:32:52 +08:00
|
|
|
}
|
2026-03-31 15:54:27 +08:00
|
|
|
_cachingProvider.Remove(cacheKey);
|
2026-03-14 06:13:06 +08:00
|
|
|
|
2026-04-13 13:23:00 +08:00
|
|
|
// 检查手机号是否已存在
|
|
|
|
|
var existingUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile && !x.DeleteMark);
|
|
|
|
|
|
|
|
|
|
YD_Event.Core.Entities.AppUser appUser;
|
|
|
|
|
bool isNewUser = false;
|
|
|
|
|
|
|
|
|
|
if (existingUser != null)
|
2026-03-14 06:13:06 +08:00
|
|
|
{
|
2026-04-13 13:23:00 +08:00
|
|
|
// 手机号已存在,检查是否已设置密码
|
|
|
|
|
if (!string.IsNullOrEmpty(existingUser.Password))
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Bah("该手机号已注册");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 未设置密码,更新现有记录
|
|
|
|
|
appUser = existingUser;
|
|
|
|
|
var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUser.Id)}{input.Password}");
|
|
|
|
|
appUser.Password = encryptedPassword;
|
2026-08-07 14:59:15 +08:00
|
|
|
appUser.MiniProgramRole = ParseRole(input);
|
2026-08-24 00:07:15 +08:00
|
|
|
appUser.PersonType = ParsePersonType(input, appUser.MiniProgramRole);
|
2026-04-13 13:23:00 +08:00
|
|
|
appUser.UpdatedTime = DateTime.Now;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 手机号不存在,创建新用户
|
|
|
|
|
isNewUser = true;
|
|
|
|
|
long appUserId = _idGenerator.NewLong();
|
|
|
|
|
var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUserId)}{input.Password}");
|
2026-08-24 00:07:15 +08:00
|
|
|
var role = ParseRole(input);
|
|
|
|
|
|
2026-04-13 13:23:00 +08:00
|
|
|
appUser = new YD_Event.Core.Entities.AppUser
|
|
|
|
|
{
|
|
|
|
|
Id = appUserId,
|
|
|
|
|
Name = input.NickName ?? input.Mobile,
|
|
|
|
|
NickName = input.NickName,
|
|
|
|
|
Avatar = input.Avatar,
|
|
|
|
|
Mobile = input.Mobile,
|
|
|
|
|
Password = encryptedPassword,
|
2026-08-24 00:07:15 +08:00
|
|
|
PersonType = ParsePersonType(input, role),
|
|
|
|
|
MiniProgramRole = role,
|
2026-04-13 13:23:00 +08:00
|
|
|
Status = AvailabilityStatus.Enable,
|
2026-04-13 13:37:50 +08:00
|
|
|
AuditStatus = AuditStatus.PendingSubmission,
|
2026-04-13 13:23:00 +08:00
|
|
|
CreatedTime = DateTime.Now,
|
|
|
|
|
CreatedUserId = 0
|
|
|
|
|
};
|
2026-03-14 06:13:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-13 13:23:00 +08:00
|
|
|
if (isNewUser)
|
|
|
|
|
{
|
|
|
|
|
await _appUserRepository.InsertAsync(appUser);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await _appUserRepository.UpdateAsync(appUser);
|
|
|
|
|
}
|
2026-03-14 06:13:06 +08:00
|
|
|
|
2026-09-17 16:09:08 +08:00
|
|
|
if (appUser.MiniProgramRole == MiniProgramRole.Referee)
|
|
|
|
|
{
|
|
|
|
|
await EnsureRefereeProfileAsync(appUser);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 21:39:00 +08:00
|
|
|
return new MiniProgramRegisterOutput
|
2026-03-14 06:13:06 +08:00
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
UserId = appUser.Id,
|
|
|
|
|
Mobile = appUser.Mobile,
|
|
|
|
|
NickName = appUser.NickName,
|
2026-08-07 14:59:15 +08:00
|
|
|
Role = ToRoleCode(appUser.MiniProgramRole),
|
|
|
|
|
RoleType = (int)NormalizeRole(appUser.MiniProgramRole),
|
2026-08-24 00:07:15 +08:00
|
|
|
PersonType = (int)appUser.PersonType,
|
2026-04-13 13:23:00 +08:00
|
|
|
RegisterTime = isNewUser ? appUser.CreatedTime : (appUser.UpdatedTime ?? appUser.CreatedTime)
|
2026-03-14 06:13:06 +08:00
|
|
|
};
|
2025-12-17 10:32:52 +08:00
|
|
|
}
|
|
|
|
|
|
2026-09-17 16:09:08 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 裁判账号注册完成后立即建立未提交档案,使其能够在后台裁判管理中显示。
|
|
|
|
|
/// 已由后台提前建档的裁判按手机号关联账号,并保留原审核状态及认证资料。
|
|
|
|
|
/// </summary>
|
|
|
|
|
private async Task EnsureRefereeProfileAsync(YD_Event.Core.Entities.AppUser appUser)
|
|
|
|
|
{
|
|
|
|
|
var referee = await _refereeRepository.GetFirstAsync(x =>
|
|
|
|
|
!x.DeleteMark && (x.AppUserId == appUser.Id || x.Mobile == appUser.Mobile));
|
|
|
|
|
if (referee != null)
|
|
|
|
|
{
|
|
|
|
|
if (referee.AppUserId.HasValue && referee.AppUserId.Value != appUser.Id)
|
|
|
|
|
throw Oops.Bah("该手机号已关联其他裁判账号,请联系赛事组委会处理");
|
|
|
|
|
|
|
|
|
|
if (!referee.AppUserId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
referee.AppUserId = appUser.Id;
|
|
|
|
|
referee.UpdatedUserId = appUser.Id;
|
|
|
|
|
referee.UpdatedTime = DateTime.Now;
|
|
|
|
|
await _refereeRepository.UpdateAsync(referee);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await _refereeRepository.InsertAsync(new YD_Event.Core.Entities.Referee
|
|
|
|
|
{
|
|
|
|
|
Id = _idGenerator.NextId(),
|
|
|
|
|
AppUserId = appUser.Id,
|
|
|
|
|
Name = appUser.Name ?? appUser.NickName ?? appUser.Mobile,
|
|
|
|
|
Mobile = appUser.Mobile,
|
|
|
|
|
ProvinceCode = string.Empty,
|
|
|
|
|
ProvinceName = string.Empty,
|
|
|
|
|
CityCode = string.Empty,
|
|
|
|
|
CityName = string.Empty,
|
|
|
|
|
DistrictCode = string.Empty,
|
|
|
|
|
DistrictName = string.Empty,
|
|
|
|
|
Level = 0,
|
|
|
|
|
CertificateUrl = string.Empty,
|
|
|
|
|
Roles = RefereeRole.None,
|
|
|
|
|
AuditStatus = AuditStatus.PendingSubmission,
|
|
|
|
|
Status = AvailabilityStatus.Enable,
|
|
|
|
|
CreatedUserId = appUser.Id,
|
|
|
|
|
CreatedTime = DateTime.Now
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-17 10:32:52 +08:00
|
|
|
/// <summary>
|
2026-03-30 21:39:00 +08:00
|
|
|
/// 重置密码接口
|
2025-12-17 10:32:52 +08:00
|
|
|
/// </summary>
|
2026-03-14 06:13:06 +08:00
|
|
|
/// <param name="input"></param>
|
2025-12-17 10:32:52 +08:00
|
|
|
/// <returns></returns>
|
2026-03-14 06:13:06 +08:00
|
|
|
[HttpPost("reset-password")]
|
2025-12-17 10:32:52 +08:00
|
|
|
[AllowAnonymous]
|
2026-03-30 21:39:00 +08:00
|
|
|
public async Task ResetPassword([FromBody] MiniProgramResetPasswordInput input)
|
2025-12-17 10:32:52 +08:00
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
var cacheKey = $"{SmsCodeCachePrefix}{input.Mobile}";
|
2026-03-31 15:54:27 +08:00
|
|
|
var cachedCodeResult = _cachingProvider.Get<string>(cacheKey);
|
|
|
|
|
string cachedCode = cachedCodeResult.Value;
|
|
|
|
|
if (!cachedCodeResult.HasValue || cachedCode != input.VerificationCode)
|
2025-12-17 10:32:52 +08:00
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
throw Oops.Bah("验证码错误或已过期");
|
2026-03-14 06:13:06 +08:00
|
|
|
}
|
2026-03-31 15:54:27 +08:00
|
|
|
_cachingProvider.Remove(cacheKey);
|
2026-03-14 06:13:06 +08:00
|
|
|
|
2026-03-30 21:39:00 +08:00
|
|
|
var appUser = await _appUserRepository.GetFirstAsync(x => x.Mobile == input.Mobile);
|
|
|
|
|
if (appUser == null)
|
2026-03-14 06:13:06 +08:00
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
throw Oops.Bah("用户不存在");
|
2026-03-14 06:13:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-30 21:39:00 +08:00
|
|
|
var encryptedPassword = MD5Encryption.Encrypt($"{_idGenerator.Encode(appUser.Id)}{input.NewPassword}");
|
|
|
|
|
appUser.Password = encryptedPassword;
|
|
|
|
|
appUser.UpdatedTime = DateTime.Now;
|
|
|
|
|
appUser.UpdatedUserId = appUser.Id;
|
2025-12-17 10:32:52 +08:00
|
|
|
|
2026-03-30 21:39:00 +08:00
|
|
|
await _appUserRepository.UpdateAsync(appUser);
|
2026-03-14 06:13:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 生成自定义 Token
|
|
|
|
|
/// </summary>
|
2026-03-30 21:39:00 +08:00
|
|
|
private (string AccessToken, string RefreshToken) GenerateTokens(YD_Event.Core.Entities.AppUser appUser)
|
2026-03-14 06:13:06 +08:00
|
|
|
{
|
|
|
|
|
long uniqueId = _idGenerator.NewLong();
|
2026-09-30 08:38:21 +08:00
|
|
|
long? accessTokenExpiredMinutes = appUser.MiniProgramRole == MiniProgramRole.Referee
|
|
|
|
|
? RefereeAccessTokenExpiredMinutes
|
|
|
|
|
: null;
|
2026-03-14 06:13:06 +08:00
|
|
|
string accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()
|
|
|
|
|
{
|
2026-03-30 21:39:00 +08:00
|
|
|
[AuthClaimsConst.AuthIdKey] = appUser.Id,
|
|
|
|
|
[AuthClaimsConst.AccountKey] = appUser.Mobile,
|
2026-03-14 06:13:06 +08:00
|
|
|
[AuthClaimsConst.UuidKey] = uniqueId,
|
|
|
|
|
[AuthClaimsConst.AuthPlatformTypeKey] = AuthPlatformType.WeChatApplet
|
2026-09-30 08:38:21 +08:00
|
|
|
}, accessTokenExpiredMinutes);
|
2026-03-14 06:13:06 +08:00
|
|
|
|
|
|
|
|
string refreshToken = JWTEncryption.GenerateRefreshToken(accessToken);
|
|
|
|
|
|
|
|
|
|
return (accessToken, refreshToken);
|
2025-12-17 10:32:52 +08:00
|
|
|
}
|
2026-08-07 14:59:15 +08:00
|
|
|
|
|
|
|
|
private static MiniProgramRole ParseRole(MiniProgramRegisterInput input)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(input.Role))
|
|
|
|
|
{
|
|
|
|
|
return input.Role.Trim().ToLowerInvariant() switch
|
|
|
|
|
{
|
|
|
|
|
"participant" or "athlete" or "user" => MiniProgramRole.Participant,
|
|
|
|
|
"referee" or "judge" => MiniProgramRole.Referee,
|
|
|
|
|
"checker" or "checkin" or "inspector" => throw Oops.Bah("检录员账号只能由后台添加并绑定赛事"),
|
|
|
|
|
_ => throw Oops.Bah("不支持的注册角色")
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input.RoleType == (int)MiniProgramRole.Checker)
|
|
|
|
|
{
|
|
|
|
|
throw Oops.Bah("检录员账号只能由后台添加并绑定赛事");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input.RoleType is >= 1 and <= 2)
|
|
|
|
|
{
|
|
|
|
|
return (MiniProgramRole)input.RoleType.Value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MiniProgramRole.Participant;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-24 00:07:15 +08:00
|
|
|
/// <summary>参赛者可选择运动员或教练身份;裁判、检录员统一按普通用户处理。</summary>
|
|
|
|
|
private static PersonType ParsePersonType(MiniProgramRegisterInput input, MiniProgramRole role)
|
|
|
|
|
{
|
|
|
|
|
if (role != MiniProgramRole.Participant) return PersonType.User;
|
|
|
|
|
return input.PersonType switch
|
|
|
|
|
{
|
|
|
|
|
(int)PersonType.Coach => PersonType.Coach,
|
|
|
|
|
(int)PersonType.Athlete => PersonType.Athlete,
|
|
|
|
|
null => PersonType.Athlete,
|
|
|
|
|
_ => throw Oops.Bah("参赛者身份只能选择运动员或教练")
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-07 14:59:15 +08:00
|
|
|
private static MiniProgramRole NormalizeRole(MiniProgramRole role)
|
|
|
|
|
{
|
|
|
|
|
return role is MiniProgramRole.Participant or MiniProgramRole.Referee or MiniProgramRole.Checker
|
|
|
|
|
? role
|
|
|
|
|
: MiniProgramRole.Participant;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string ToRoleCode(MiniProgramRole role)
|
|
|
|
|
{
|
|
|
|
|
return NormalizeRole(role) switch
|
|
|
|
|
{
|
|
|
|
|
MiniProgramRole.Referee => "referee",
|
|
|
|
|
MiniProgramRole.Checker => "checker",
|
|
|
|
|
_ => "participant"
|
|
|
|
|
};
|
|
|
|
|
}
|
2026-03-02 11:19:25 +08:00
|
|
|
}
|