添加运动员号码去重

This commit is contained in:
马梓彭 2026-06-17 15:42:32 +08:00
parent d2d0db5f87
commit 3efa40ce08
7 changed files with 136 additions and 1 deletions

View File

@ -180,6 +180,39 @@ public class AppUserService : BaseService<AppUserEntity>, ITransient
// 手机号为空时,跳过基于手机号的重复检测(单位添加运动员时,联系电话非必填)
var mobileIsEmpty = string.IsNullOrWhiteSpace(input.Mobile);
// ============== 新增:证件号查重验证 ==============
// 身份证/户口本认证时检查身份证号是否重复
if ((input.AuthType == 1 || input.AuthType == 3) && !string.IsNullOrWhiteSpace(input.IdCardNumber))
{
var duplicateIdCard = await _appUserRep.AsQueryable()
.Where(x => x.IdCardNumber == input.IdCardNumber
&& x.PersonType == input.PersonType
&& !x.DeleteMark
&& (!input.Id.HasValue || x.Id != input.Id.Value))
.FirstAsync();
if (duplicateIdCard != null)
{
throw Oops.Bah($"系统中已存在相同身份证号的{GetPersonTypeDisplay(input.PersonType)},请核对信息");
}
}
// 护照认证时检查护照号是否重复
if (input.AuthType == 2 && !string.IsNullOrWhiteSpace(input.PassportNumber))
{
var duplicatePassport = await _appUserRep.AsQueryable()
.Where(x => x.PassportNumber == input.PassportNumber
&& x.PersonType == input.PersonType
&& !x.DeleteMark
&& (!input.Id.HasValue || x.Id != input.Id.Value))
.FirstAsync();
if (duplicatePassport != null)
{
throw Oops.Bah($"系统中已存在相同护照号的{GetPersonTypeDisplay(input.PersonType)},请核对信息");
}
}
// 先检查是否存在相同手机号且相同类型的运动员在其他单位
AppUserEntity? existingInOtherUnit = null;
if (!mobileIsEmpty)
@ -319,21 +352,24 @@ public class AppUserService : BaseService<AppUserEntity>, ITransient
entity.BirthDate = input.BirthDate;
entity.Age = input.Age;
// 根据认证类型把图片URL写入对应字段,并清空其他类型图片
// 根据认证类型把图片URL和证件号写入对应字段,并清空其他类型图片
if (input.AuthType == 1)
{
entity.AuthType = 1;
entity.IdCardImageUrl = input.IdCardImageUrl;
entity.IdCardBackImageUrl = input.IdCardBackImageUrl;
entity.PassportPhotoUrl = null;
entity.PassportNumber = null;
entity.HouseholdPhotoUrl = null;
}
else if (input.AuthType == 2)
{
entity.AuthType = 2;
entity.PassportPhotoUrl = input.PassportPhotoUrl ?? input.IdCardImageUrl;
entity.PassportNumber = input.PassportNumber;
entity.IdCardImageUrl = null;
entity.IdCardBackImageUrl = null;
entity.IdCardNumber = null;
entity.HouseholdPhotoUrl = null;
}
else if (input.AuthType == 3)
@ -343,6 +379,7 @@ public class AppUserService : BaseService<AppUserEntity>, ITransient
entity.IdCardImageUrl = null;
entity.IdCardBackImageUrl = null;
entity.PassportPhotoUrl = null;
entity.PassportNumber = null;
}
else
{
@ -352,6 +389,7 @@ public class AppUserService : BaseService<AppUserEntity>, ITransient
entity.IdCardImageUrl = null;
entity.IdCardBackImageUrl = null;
entity.PassportPhotoUrl = null;
entity.PassportNumber = null;
entity.HouseholdPhotoUrl = null;
}
@ -411,6 +449,22 @@ public class AppUserService : BaseService<AppUserEntity>, ITransient
}
}
/// <summary>
/// 获取人员类型显示名称
/// </summary>
/// <param name="personType"></param>
/// <returns></returns>
private static string GetPersonTypeDisplay(PersonType personType)
{
return personType switch
{
PersonType.Athlete => "运动员",
PersonType.Coach => "教练",
PersonType.Leader => "领队",
_ => "成员"
};
}
#endregion
#region 领队/教练管理 (向下兼容)

View File

@ -172,6 +172,11 @@ public class CreateOrUpdateMemberInput
//[RegularExpression(@"(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)", ErrorMessage = "身份证号格式不正确")]
public string IdCardNumber { get; set; }
/// <summary>
/// 护照号码(护照认证时使用)
/// </summary>
public string? PassportNumber { get; set; }
/// <summary>
/// 身份证图片URL
/// </summary>
@ -282,6 +287,11 @@ public class AppUserOutput
/// </summary>
public string IdCardNumber { get; set; }
/// <summary>
/// 护照号码
/// </summary>
public string? PassportNumber { get; set; }
/// <summary>
/// 身份证图片URL
/// </summary>

View File

@ -97,6 +97,11 @@ public class MyAuthInfoDto
/// </summary>
public string? IdCardNumber { get; set; }
/// <summary>
/// 护照号码(认证类型2时使用)
/// </summary>
public string? PassportNumber { get; set; }
/// <summary>
/// 身份证正面图片(认证类型1时使用)
/// </summary>
@ -175,6 +180,12 @@ public class SubmitAuthInput
[MaxLength(20, ErrorMessage = "身份证号不能超过20个字符")]
public string? IdCardNumber { get; set; }
/// <summary>
/// 护照号码(认证类型2时必填)
/// </summary>
[MaxLength(20, ErrorMessage = "护照号码不能超过20个字符")]
public string? PassportNumber { get; set; }
/// <summary>
/// 身份证正面图片(认证类型1时必填)
/// </summary>

View File

@ -145,6 +145,7 @@ public class MyController : IDynamicApiController
IdCardNumber = user.IdCardNumber,
IdCardImageUrl = user.IdCardImageUrl,
IdCardBackImageUrl = user.IdCardBackImageUrl,
PassportNumber = user.PassportNumber,
PassportPhotoUrl = user.PassportPhotoUrl,
HouseholdPhotoUrl = user.HouseholdPhotoUrl,
AuditStatus = user.AuditStatus,
@ -172,17 +173,33 @@ public class MyController : IDynamicApiController
if (string.IsNullOrEmpty(input.IdCardNumber)) throw Oops.Bah("身份证号不能为空");
if (string.IsNullOrEmpty(input.IdCardImageUrl)) throw Oops.Bah("身份证正面图片不能为空");
if (string.IsNullOrEmpty(input.IdCardBackImageUrl)) throw Oops.Bah("身份证背面图片不能为空");
// 身份证号查重
var duplicateIdCard = await _appUserRepository.GetFirstAsync(u =>
u.IdCardNumber == input.IdCardNumber && u.Id != userId && !u.DeleteMark);
if (duplicateIdCard != null) throw Oops.Bah("该身份证号已被其他用户使用");
}
else if (input.AuthType == 2)
{
if (string.IsNullOrEmpty(input.PassportPhotoUrl)) throw Oops.Bah("护照图片不能为空");
if (string.IsNullOrEmpty(input.PassportNumber)) throw Oops.Bah("护照号码不能为空");
if (!input.Gender.HasValue) throw Oops.Bah("性别不能为空");
if (!input.BirthDate.HasValue) throw Oops.Bah("出生日期不能为空");
// 护照号查重
var duplicatePassport = await _appUserRepository.GetFirstAsync(u =>
u.PassportNumber == input.PassportNumber && u.Id != userId && !u.DeleteMark);
if (duplicatePassport != null) throw Oops.Bah("该护照号码已被其他用户使用");
}
else if (input.AuthType == 3)
{
if (string.IsNullOrEmpty(input.HouseholdPhotoUrl)) throw Oops.Bah("户口本图片不能为空");
if (string.IsNullOrEmpty(input.IdCardNumber)) throw Oops.Bah("身份证号不能为空");
// 身份证号查重
var duplicateIdCard = await _appUserRepository.GetFirstAsync(u =>
u.IdCardNumber == input.IdCardNumber && u.Id != userId && !u.DeleteMark);
if (duplicateIdCard != null) throw Oops.Bah("该身份证号已被其他用户使用");
}
else
{
@ -226,15 +243,18 @@ public class MyController : IDynamicApiController
user.IdCardImageUrl = input.IdCardImageUrl;
user.IdCardBackImageUrl = input.IdCardBackImageUrl;
user.PassportPhotoUrl = null;
user.PassportNumber = null;
user.HouseholdPhotoUrl = null;
user.Gender = (Gender)input.Gender.Value;
user.BirthDate = input.BirthDate.Value;
}
else if (input.AuthType == 2)
{
user.PassportNumber = input.PassportNumber;
user.PassportPhotoUrl = input.PassportPhotoUrl;
user.IdCardImageUrl = null;
user.IdCardBackImageUrl = null;
user.IdCardNumber = null;
user.HouseholdPhotoUrl = null;
user.Gender = (Gender)input.Gender.Value;
user.BirthDate = input.BirthDate.Value;
@ -247,6 +267,7 @@ public class MyController : IDynamicApiController
user.IdCardImageUrl = null;
user.IdCardBackImageUrl = null;
user.PassportPhotoUrl = null;
user.PassportNumber = null;
if (input.Gender.HasValue)
{
user.Gender = (Gender)input.Gender.Value;
@ -264,6 +285,7 @@ public class MyController : IDynamicApiController
user.IdCardImageUrl = null;
user.IdCardBackImageUrl = null;
user.PassportPhotoUrl = null;
user.PassportNumber = null;
user.HouseholdPhotoUrl = null;
}

View File

@ -95,6 +95,13 @@
<param name="newMerchantId">新单位ID</param>
<returns></returns>
</member>
<member name="M:YD_Event.Application.AppUser.AppUserService.GetPersonTypeDisplay(YD_Event.Core.Enum.PersonType)">
<summary>
获取人员类型显示名称
</summary>
<param name="personType"></param>
<returns></returns>
</member>
<member name="M:YD_Event.Application.AppUser.AppUserService.DeleteMember(System.Int64)">
<summary>
删除成员(解除与单位的关联,而非删除用户)
@ -267,6 +274,11 @@
身份证号
</summary>
</member>
<member name="P:YD_Event.Application.AppUser.Dtos.CreateOrUpdateMemberInput.PassportNumber">
<summary>
护照号码(护照认证时使用)
</summary>
</member>
<member name="P:YD_Event.Application.AppUser.Dtos.CreateOrUpdateMemberInput.IdCardImageUrl">
<summary>
身份证图片URL
@ -372,6 +384,11 @@
身份证号
</summary>
</member>
<member name="P:YD_Event.Application.AppUser.Dtos.AppUserOutput.PassportNumber">
<summary>
护照号码
</summary>
</member>
<member name="P:YD_Event.Application.AppUser.Dtos.AppUserOutput.IdCardImageUrl">
<summary>
身份证图片URL
@ -3067,6 +3084,11 @@
身份证号(认证类型1时使用)
</summary>
</member>
<member name="P:YD_Event.Application.Client.Dtos.MyAuthInfoDto.PassportNumber">
<summary>
护照号码(认证类型2时使用)
</summary>
</member>
<member name="P:YD_Event.Application.Client.Dtos.MyAuthInfoDto.IdCardImageUrl">
<summary>
身份证正面图片(认证类型1时使用)
@ -3137,6 +3159,11 @@
身份证号(认证类型1时必填)
</summary>
</member>
<member name="P:YD_Event.Application.Client.Dtos.SubmitAuthInput.PassportNumber">
<summary>
护照号码(认证类型2时必填)
</summary>
</member>
<member name="P:YD_Event.Application.Client.Dtos.SubmitAuthInput.IdCardImageUrl">
<summary>
身份证正面图片(认证类型1时必填)

View File

@ -84,6 +84,12 @@ public class AppUser : Entity<long>, ISoftDelete, ICreatedUserId, ICreatedTime,
[SugarColumn(Length = 20, IsNullable = true)]
public string? IdCardNumber { get; set; }
/// <summary>
/// 护照号码
/// </summary>
[SugarColumn(Length = 20, IsNullable = true)]
public string? PassportNumber { get; set; }
/// <summary>
/// 身份证正面图片URL
/// </summary>

View File

@ -632,6 +632,11 @@
身份证号码
</summary>
</member>
<member name="P:YD_Event.Core.Entities.AppUser.PassportNumber">
<summary>
护照号码
</summary>
</member>
<member name="P:YD_Event.Core.Entities.AppUser.IdCardImageUrl">
<summary>
身份证正面图片URL