diff --git a/YD_Event.Application/Auth/AuthService.cs b/YD_Event.Application/Auth/AuthService.cs
index 281a47d..f8db809 100644
--- a/YD_Event.Application/Auth/AuthService.cs
+++ b/YD_Event.Application/Auth/AuthService.cs
@@ -1,4 +1,5 @@
using YD_Event.Application.Auth.Dtos;
+using YD_Event.Core.Enum;
namespace YD_Event.Application.Auth;
///
@@ -8,18 +9,21 @@ namespace YD_Event.Application.Auth;
public class AuthService : IDynamicApiController
{
private readonly ISqlSugarRepository _sysUseRepository;
+ private readonly ISqlSugarRepository _sysUserRoleRepository;
private readonly ICaptcha _captcha;
private readonly IIdGenerator _idGenerator;
private readonly IEasyCachingProvider _easyCachingProvider;
private readonly IHttpContextAccessor _httpContextAccessor;
public AuthService(ISqlSugarRepository sysUseRepository,
+ ISqlSugarRepository sysUserRoleRepository,
ICaptcha captcha,
IIdGenerator idGenerator,
IEasyCachingProvider easyCachingProvider,
IHttpContextAccessor httpContextAccessor)
{
_sysUseRepository = sysUseRepository;
+ _sysUserRoleRepository = sysUserRoleRepository;
_captcha = captcha;
_idGenerator = idGenerator;
_easyCachingProvider = easyCachingProvider;
@@ -95,5 +99,147 @@ public class AuthService : IDynamicApiController
return new FileStreamResult(stream, "image/gif");
}
+ ///
+ /// 用户注册
+ ///
+ ///
+ ///
+ [DisplayName("用户注册")]
+ [HttpPost]
+ [UnitOfWork]
+ public async Task Register(RegisterInput dto)
+ {
+ var codeCacheKey = $"sms:code:{dto.Phone}";
+ var cachedCode = await _easyCachingProvider.GetAsync(codeCacheKey);
+
+ if (!cachedCode.HasValue || cachedCode.Value != dto.Code)
+ {
+ throw Oops.Bah("验证码错误或已过期");
+ }
-}
\ No newline at end of file
+ var existAccount = await _sysUseRepository.IsAnyAsync(x => x.Account == dto.Account);
+ if (existAccount)
+ {
+ throw Oops.Bah("该账号已被注册");
+ }
+
+ var existPhone = await _sysUseRepository.IsAnyAsync(x => x.Mobile == dto.Phone);
+ if (existPhone)
+ {
+ throw Oops.Bah("该手机号已被注册");
+ }
+
+ var user = new SysUser
+ {
+ Id = _idGenerator.NewLong(),
+ Account = dto.Account,
+ Name = dto.Account,
+ Mobile = dto.Phone,
+ Gender = Gender.Unknown,
+ OrgId = 0,
+ Status = AvailabilityStatus.Enable,
+ DeleteMark = false,
+ CreatedTime = DateTime.Now,
+ CreatedUserId = 0
+ };
+
+ user.Password = MD5Encryption.Encrypt($"{_idGenerator.Encode(user.Id)}{dto.Password}");
+
+ await _sysUseRepository.InsertAsync(user);
+
+ // 为新用户分配普通用户角色 (RoleId = 1001)
+ var userRole = new SysUserRole
+ {
+ Id = _idGenerator.NewLong(),
+ UserId = user.Id,
+ RoleId = 1001,
+ CreatedTime = DateTime.Now,
+ CreatedUserId = 0,
+ DeleteMark = false
+ };
+ await _sysUserRoleRepository.InsertAsync(userRole);
+
+ await _easyCachingProvider.RemoveAsync(codeCacheKey);
+ }
+
+ ///
+ /// 短信验证码登录
+ ///
+ ///
+ ///
+ [DisplayName("短信验证码登录")]
+ [HttpPost]
+ public async Task SmsSignIn(SmsLoginInput dto)
+ {
+ var codeCacheKey = $"sms:code:{dto.Phone}";
+ var cachedCode = await _easyCachingProvider.GetAsync(codeCacheKey);
+
+ if (!cachedCode.HasValue || cachedCode.Value != dto.Code)
+ {
+ throw Oops.Bah("验证码错误或已过期");
+ }
+
+ SysUser user = await _sysUseRepository.GetFirstAsync(x => x.Mobile == dto.Phone);
+ if (user == null)
+ {
+ throw Oops.Bah("该手机号尚未注册");
+ }
+
+ var context = _httpContextAccessor.HttpContext;
+ if (user.Status == AvailabilityStatus.Disable || (user.LockExpired.HasValue && DateTime.Now < user.LockExpired))
+ {
+ throw Oops.Bah("您的账号被锁定");
+ }
+
+ long uniqueId = _idGenerator.NewLong();
+ string token = JWTEncryption.Encrypt(new Dictionary()
+ {
+ [AuthClaimsConst.AuthIdKey] = user.Id,
+ [AuthClaimsConst.AccountKey] = user.Account,
+ [AuthClaimsConst.UuidKey] = uniqueId,
+ [AuthClaimsConst.AuthPlatformTypeKey] = AuthPlatformType.Manager
+ });
+ var refreshToken = JWTEncryption.GenerateRefreshToken(token);
+ context.SigninToSwagger(token);
+ context!.Response.Headers["access-token"] = token;
+ context.Response.Headers["x-access-token"] = refreshToken;
+
+ await _easyCachingProvider.RemoveAsync(codeCacheKey);
+ }
+
+ ///
+ /// 重置密码
+ ///
+ ///
+ ///
+ [DisplayName("重置密码")]
+ [HttpPost]
+ public async Task ResetPassword(ResetPasswordInput dto)
+ {
+ var codeCacheKey = $"sms:code:{dto.Phone}";
+ var cachedCode = await _easyCachingProvider.GetAsync(codeCacheKey);
+
+ if (!cachedCode.HasValue || cachedCode.Value != dto.Code)
+ {
+ throw Oops.Bah("验证码错误或已过期");
+ }
+
+ SysUser user = await _sysUseRepository.GetFirstAsync(x => x.Mobile == dto.Phone);
+ if (user == null)
+ {
+ throw Oops.Bah("该手机号尚未注册");
+ }
+
+ if (user.Status == AvailabilityStatus.Disable || (user.LockExpired.HasValue && DateTime.Now < user.LockExpired))
+ {
+ throw Oops.Bah("您的账号被锁定");
+ }
+
+ user.Password = MD5Encryption.Encrypt($"{_idGenerator.Encode(user.Id)}{dto.NewPassword}");
+ user.UpdatedTime = DateTime.Now;
+
+ await _sysUseRepository.UpdateAsync(user);
+
+ await _easyCachingProvider.RemoveAsync(codeCacheKey);
+ }
+}
diff --git a/YD_Event.Application/Auth/Dtos/AuthDtos.cs b/YD_Event.Application/Auth/Dtos/AuthDtos.cs
new file mode 100644
index 0000000..9183f72
--- /dev/null
+++ b/YD_Event.Application/Auth/Dtos/AuthDtos.cs
@@ -0,0 +1,108 @@
+#nullable enable
+using System.ComponentModel.DataAnnotations;
+
+namespace YD_Event.Application.Auth.Dtos;
+
+///
+/// 用户注册输入参数
+///
+public class RegisterInput
+{
+ ///
+ /// 手机号
+ ///
+ [Required(ErrorMessage = "手机号不能为空")]
+ [RegularExpression(@"^1[3456789]\d{9}$", ErrorMessage = "手机号格式不正确")]
+ public string Phone { get; set; } = null!;
+
+ ///
+ /// 账号
+ ///
+ [Required(ErrorMessage = "账号不能为空")]
+ [MinLength(3, ErrorMessage = "账号至少3个字符")]
+ [MaxLength(32, ErrorMessage = "账号最多32个字符")]
+ public string Account { get; set; } = null!;
+
+ ///
+ /// 密码
+ ///
+ [Required(ErrorMessage = "密码不能为空")]
+ [MinLength(6, ErrorMessage = "密码至少6个字符")]
+ [MaxLength(18, ErrorMessage = "密码最多18个字符")]
+ public string Password { get; set; } = null!;
+
+ ///
+ /// 确认密码
+ ///
+ [Required(ErrorMessage = "请再次输入密码")]
+ [Compare(nameof(Password), ErrorMessage = "两次输入的密码不一致")]
+ public string ConfirmPassword { get; set; } = null!;
+
+ ///
+ /// 短信验证码
+ ///
+ [Required(ErrorMessage = "验证码不能为空")]
+ [StringLength(6, MinimumLength = 4, ErrorMessage = "验证码格式不正确")]
+ public string Code { get; set; } = null!;
+
+ ///
+ /// 同意用户协议
+ ///
+ [Required(ErrorMessage = "请同意用户协议")]
+ public bool AgreeTerms { get; set; }
+}
+
+///
+/// 短信登录输入参数
+///
+public class SmsLoginInput
+{
+ ///
+ /// 手机号
+ ///
+ [Required(ErrorMessage = "手机号不能为空")]
+ [RegularExpression(@"^1[3456789]\d{9}$", ErrorMessage = "手机号格式不正确")]
+ public string Phone { get; set; } = null!;
+
+ ///
+ /// 验证码
+ ///
+ [Required(ErrorMessage = "验证码不能为空")]
+ [StringLength(6, MinimumLength = 4, ErrorMessage = "验证码格式不正确")]
+ public string Code { get; set; } = null!;
+}
+
+///
+/// 重置密码输入参数
+///
+public class ResetPasswordInput
+{
+ ///
+ /// 手机号
+ ///
+ [Required(ErrorMessage = "手机号不能为空")]
+ [RegularExpression(@"^1[3456789]\d{9}$", ErrorMessage = "手机号格式不正确")]
+ public string Phone { get; set; } = null!;
+
+ ///
+ /// 验证码
+ ///
+ [Required(ErrorMessage = "验证码不能为空")]
+ [StringLength(6, MinimumLength = 4, ErrorMessage = "验证码格式不正确")]
+ public string Code { get; set; } = null!;
+
+ ///
+ /// 新密码
+ ///
+ [Required(ErrorMessage = "密码不能为空")]
+ [MinLength(6, ErrorMessage = "密码至少6个字符")]
+ [MaxLength(18, ErrorMessage = "密码最多18个字符")]
+ public string NewPassword { get; set; } = null!;
+
+ ///
+ /// 确认新密码
+ ///
+ [Required(ErrorMessage = "请再次输入密码")]
+ [Compare(nameof(NewPassword), ErrorMessage = "两次输入的密码不一致")]
+ public string ConfirmNewPassword { get; set; } = null!;
+}
diff --git a/YD_Event.Application/Client/Dtos/EventClientDtos.cs b/YD_Event.Application/Client/Dtos/EventClientDtos.cs
index 8e14415..0c886f8 100644
--- a/YD_Event.Application/Client/Dtos/EventClientDtos.cs
+++ b/YD_Event.Application/Client/Dtos/EventClientDtos.cs
@@ -3,6 +3,32 @@ using YD_Event.Core.Enum;
namespace YD_Event.Application.Client.Dtos;
+///
+/// 客户端赛事查询输入
+///
+public class EventClientQueryInput : Pagination
+{
+ ///
+ /// 搜索关键字
+ ///
+ public string? Keyword { get; set; }
+
+ ///
+ /// 状态筛选:0-全部 1-报名中 2-比赛中 3-已结束
+ ///
+ public int Status { get; set; } = 0;
+
+ ///
+ /// 赛事类型
+ ///
+ public EventFormat? EventType { get; set; }
+
+ ///
+ /// 收费模式
+ ///
+ public ChargeMode? ChargeMode { get; set; }
+}
+
///
/// 赛事列表项DTO
///
diff --git a/YD_Event.Application/Client/EventClientController.cs b/YD_Event.Application/Client/EventClientController.cs
index 50ef850..db23657 100644
--- a/YD_Event.Application/Client/EventClientController.cs
+++ b/YD_Event.Application/Client/EventClientController.cs
@@ -2,10 +2,8 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
using YD_Event.Application.Client.Dtos;
-using YD_Event.Application.Event;
using YD_Event.Core.Entities;
using YD_Event.Core.Enum;
-using YD_Event.Core.Domain.Pricing;
using YD_Event.Core.Infrastructure.WeChat;
using YD_Event.Core.Infrastructure.WeChat.Dto;
using YD_Event.Core.Options;
@@ -41,6 +39,7 @@ public class EventClientController : IDynamicApiController
private readonly ISqlSugarRepository _merchantRepository;
private readonly ISqlSugarRepository _pointsRuleRepository;
private readonly ISqlSugarRepository _appUserRepository;
+ private readonly ISqlSugarRepository _projectTypeRepository;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IIdGenerator _idGenerator;
private readonly WeChatPayService _weChatPayService;
@@ -64,6 +63,7 @@ public class EventClientController : IDynamicApiController
ISqlSugarRepository merchantRepository,
ISqlSugarRepository pointsRuleRepository,
ISqlSugarRepository appUserRepository,
+ ISqlSugarRepository projectTypeRepository,
IHttpContextAccessor httpContextAccessor,
IIdGenerator idGenerator,
WeChatPayService weChatPayService,
@@ -86,6 +86,7 @@ public class EventClientController : IDynamicApiController
_merchantRepository = merchantRepository;
_pointsRuleRepository = pointsRuleRepository;
_appUserRepository = appUserRepository;
+ _projectTypeRepository = projectTypeRepository;
_httpContextAccessor = httpContextAccessor;
_idGenerator = idGenerator;
_weChatPayService = weChatPayService;
@@ -109,6 +110,7 @@ public class EventClientController : IDynamicApiController
///
[HttpGet("banners")]
[AllowAnonymous]
+ [DisplayName("获取轮播图列表")]
public async Task> GetBannerList()
{
var list = await _bannerRepository.AsQueryable()
@@ -129,43 +131,36 @@ public class EventClientController : IDynamicApiController
///
/// 获取赛事列表
///
- /// 页码
- /// 页大小
- /// 状态筛选:0-全部 1-报名中 2-比赛中 3-已结束
- /// 搜索关键字
+ /// 查询参数
///
[HttpGet("list")]
- [AllowAnonymous] // 允许未登录查看列表?根据需求,原型中有“我的”,可能需要登录。但通常列表可公开。这里先设为允许匿名,获取详情再校验。
- // 修正:Class上有[Authorize],如果需要匿名需显式[AllowAnonymous]。
- // 假设小程序进入即登录,保持Authorize
- public async Task> GetEventList([FromQuery] int page = 1, [FromQuery] int pageSize = 10, [FromQuery] int status = 0, [FromQuery] string? keyword = null)
+ [AllowAnonymous]
+ [DisplayName("获取赛事列表")]
+ public async Task> GetEventList([FromQuery] EventClientQueryInput input)
{
var query = _eventRepository.AsQueryable()
.Where(e => !e.DeleteMark && e.Status == AvailabilityStatus.Enable)
- .WhereIF(!string.IsNullOrEmpty(keyword), e => e.EventName.Contains(keyword));
+ .WhereIF(!string.IsNullOrEmpty(input.Keyword), e => e.EventName.Contains(input.Keyword))
+ .WhereIF(input.EventType.HasValue, e => e.EventType == input.EventType)
+ .WhereIF(input.ChargeMode.HasValue, e => e.ChargeMode == input.ChargeMode);
- // 状态筛选逻辑
- // 1-报名中: Now >= RegStart && Now <= RegEnd
- // 2-比赛中: Now >= MatchStart && Now <= MatchEnd
- // 3-已结束: Now > MatchEnd
var now = DateTime.Now;
- if (status == 1)
+ if (input.Status == 1)
{
query = query.Where(e => now >= e.RegistrationStartTime && now <= e.RegistrationEndTime);
}
- else if (status == 2)
+ else if (input.Status == 2)
{
query = query.Where(e => now >= e.MatchStartTime && now <= e.MatchEndTime);
}
- else if (status == 3)
+ else if (input.Status == 3)
{
query = query.Where(e => now > e.MatchEndTime);
}
- // 排序:优先按报名开始时间倒序
query = query.OrderByDescending(e => e.RegistrationStartTime);
- var list = await query.ToPagedListAsync(new Pagination { PageNo = page, PageSize = pageSize });
+ var list = await query.ToPagedListAsync(input);
var result = new PageResult
{
@@ -178,7 +173,7 @@ public class EventClientController : IDynamicApiController
Id = e.Id,
EventName = e.EventName,
CoverImage = e.CoverImage,
- EventStatus = CalculateEventStatus(e), // 动态计算状态
+ EventStatus = CalculateEventStatus(e),
RegistrationStartTime = e.RegistrationStartTime,
RegistrationEndTime = e.RegistrationEndTime,
MatchStartTime = e.MatchStartTime,
@@ -197,6 +192,7 @@ public class EventClientController : IDynamicApiController
///
[HttpGet("{id}")]
[AllowAnonymous]
+ [DisplayName("获取赛事详情")]
public async Task GetEventDetail(long id)
{
var evt = await _eventRepository.GetFirstAsync(e => e.Id == id && !e.DeleteMark);
@@ -338,6 +334,7 @@ public class EventClientController : IDynamicApiController
///
///
[HttpPost("calculate-amount")]
+ [DisplayName("计算报名金额")]
public async Task CalculateRegistrationAmount([FromBody] CalculateAmountInput input)
{
var evt = await _eventRepository.GetFirstAsync(e => e.Id == input.EventId && !e.DeleteMark);
@@ -431,6 +428,7 @@ public class EventClientController : IDynamicApiController
///
[HttpPost("apply")]
[UnitOfWork]
+ [DisplayName("提交赛事报名")]
public async Task SubmitRegistration([FromBody] SubmitRegistrationInput input)
{
var userId = GetCurrentUserId();
@@ -457,10 +455,32 @@ public class EventClientController : IDynamicApiController
var limit = await _limitRepository.GetFirstAsync(l => l.EventId == input.EventId && !l.DeleteMark);
if (limit != null)
{
- // 简单校验项目总数,更严谨需按项目类型统计
if (input.Items.Count > limit.IndividualProjectLimit)
throw Oops.Bah($"每人最多可报{limit.IndividualProjectLimit}个项目");
}
+
+ var projectLimits = await _projectLimitRepository.AsQueryable()
+ .Where(pl => pl.EventId == input.EventId && !pl.DeleteMark)
+ .ToListAsync();
+
+ foreach (var item in input.Items)
+ {
+ var projectLimit = projectLimits.FirstOrDefault(pl => pl.ProjectId == item.ProjectId);
+ if (projectLimit != null)
+ {
+ var currentCount = await _registrationItemRepository.AsQueryable()
+ .InnerJoin((ri, r) => ri.RegistrationId == r.Id)
+ .Where((ri, r) => ri.ProjectId == item.ProjectId && r.RegistrationStatus != 4)
+ .CountAsync();
+
+ if (currentCount >= projectLimit.LimitCount)
+ {
+ var eventProject = await _eventProjectRepository.GetFirstAsync(ep => ep.Id == item.ProjectId);
+ var project = await _projectRepository.GetFirstAsync(p => p.Id == eventProject.ProjectId);
+ throw Oops.Bah($"项目[{project?.Name}]已达到报名上限,无法继续报名");
+ }
+ }
+ }
// 4. 创建报名主表
var registrationId = _idGenerator.NewLong();
@@ -563,6 +583,7 @@ public class EventClientController : IDynamicApiController
/// 支付信息查询输入参数,包含报名记录ID和OpenId
/// 支付信息,包括微信支付参数(如果是微信支付)
[HttpPost("payment-info")]
+ [DisplayName("获取支付信息")]
public async Task GetPaymentInfo([FromBody] GetPaymentInfoInput input)
{
var userId = GetCurrentUserId();
@@ -573,14 +594,15 @@ public class EventClientController : IDynamicApiController
if (evt == null) throw Oops.Bah("赛事不存在");
var configOptions = _wechatTenpayClientOptionsMonitor.CurrentValue;
+ var merchant = await _merchantRepository.GetFirstAsync(m => m.Id == evt.MerchantId && !m.DeleteMark);
var paymentInfo = new PaymentInfoDto
{
RegistrationId = reg.Id,
Amount = reg.TotalAmount,
PaymentMethod = reg.PaymentMethod,
- BankAccountName = "上海跃动文化科技有限公司",
- BankAccountNo = "456498465198456261",
- BankName = "招商银行"
+ BankAccountName = merchant?.MerchantName ?? "上海跃动文化科技有限公司",
+ BankAccountNo = merchant?.AccountNumber ?? "456498465198456261",
+ BankName = merchant?.BankName ?? "招商银行"
};
if (reg.PaymentMethod == 2 && reg.TotalAmount > 0)
@@ -649,6 +671,7 @@ public class EventClientController : IDynamicApiController
/// 上传支付凭证(线下支付)
///
[HttpPost("upload-voucher/{registrationId}")]
+ [DisplayName("上传支付凭证")]
public async Task UploadPaymentVoucher(long registrationId, [FromBody] UploadVoucherInput input)
{
var userId = GetCurrentUserId();
@@ -668,6 +691,7 @@ public class EventClientController : IDynamicApiController
/// 更新参赛人信息
///
[HttpPost("update-player")]
+ [DisplayName("更新参赛人信息")]
public async Task UpdateRegistrationPlayer([FromBody] UpdatePlayerInput input)
{
var userId = GetCurrentUserId();
@@ -693,6 +717,7 @@ public class EventClientController : IDynamicApiController
///
///
[HttpGet("my-events")]
+ [DisplayName("获取我的已报赛事列表")]
public async Task> GetMyEventList([FromQuery] int page = 1, [FromQuery] int pageSize = 10)
{
var userId = GetCurrentUserId();
@@ -720,6 +745,7 @@ public class EventClientController : IDynamicApiController
/// 获取报名详情(包含参赛人)
///
[HttpGet("my-registration/{registrationId}")]
+ [DisplayName("获取报名详情")]
public async Task GetRegistrationDetail(long registrationId)
{
var userId = GetCurrentUserId();
@@ -749,15 +775,11 @@ public class EventClientController : IDynamicApiController
if (reg == null) throw Oops.Bah("报名记录不存在");
// 计算 EventStatus
+ EventStatus status = EventStatus.Enrolling;
var now = DateTime.Now;
- var tempEvent = new EventInfo
- {
- RegistrationStartTime = reg.RegStart,
- RegistrationEndTime = reg.RegEnd,
- MatchStartTime = reg.MatchStart,
- MatchEndTime = reg.MatchEnd
- };
- EventStatus status = EventStatusUpdateService.CalculateEventStatus(tempEvent, now);
+ if (now >= reg.RegStart && now <= reg.RegEnd) status = EventStatus.Enrolling;
+ else if (now >= reg.MatchStart && now <= reg.MatchEnd) status = EventStatus.Ongoing;
+ else if (now > reg.MatchEnd) status = EventStatus.Ended;
// 获取 Items 和 Persons
var items = await _registrationItemRepository.AsQueryable()
@@ -805,6 +827,7 @@ public class EventClientController : IDynamicApiController
///
///
[HttpGet("status/{registrationId}")]
+ [DisplayName("查询报名状态")]
public async Task GetRegistrationStatus(long registrationId)
{
var userId = GetCurrentUserId();
@@ -826,6 +849,7 @@ public class EventClientController : IDynamicApiController
///
///
[HttpPost("cancel/{registrationId}")]
+ [DisplayName("取消报名")]
public async Task CancelRegistration(long registrationId)
{
var userId = GetCurrentUserId();
@@ -856,6 +880,7 @@ public class EventClientController : IDynamicApiController
/// 操作是否成功
[HttpPost("select-payment-method")]
[UnitOfWork]
+ [DisplayName("选择支付方式")]
public async Task SelectPaymentMethod([FromBody] SelectPaymentMethodInput input)
{
var userId = GetCurrentUserId();
@@ -890,6 +915,7 @@ public class EventClientController : IDynamicApiController
///
[HttpPost("sync-payment/{registrationId}")]
[UnitOfWork]
+ [DisplayName("同步支付状态")]
public async Task SyncPaymentStatus(long registrationId)
{
var userId = GetCurrentUserId();
@@ -1138,6 +1164,9 @@ public class EventClientController : IDynamicApiController
private EventStatus CalculateEventStatus(EventInfo e)
{
var now = DateTime.Now;
- return EventStatusUpdateService.CalculateEventStatus(e, now);
+ if (now >= e.RegistrationStartTime && now <= e.RegistrationEndTime) return EventStatus.Enrolling; // 报名中
+ if (now >= e.MatchStartTime && now <= e.MatchEndTime) return EventStatus.Ongoing; // 比赛中
+ if (now > e.MatchEndTime) return EventStatus.Ended; // 已结束
+ return EventStatus.Enrolling; // 默认? 或者新增未开始状态
}
}
diff --git a/YD_Event.Application/Points/Dtos/AddPointsRuleInput.cs b/YD_Event.Application/Points/Dtos/AddPointsRuleInput.cs
index 9cdca3a..70938e1 100644
--- a/YD_Event.Application/Points/Dtos/AddPointsRuleInput.cs
+++ b/YD_Event.Application/Points/Dtos/AddPointsRuleInput.cs
@@ -38,7 +38,7 @@ public class AddPointsRuleInput
///
/// 参与积分(发放积分个数)
///
- public int ParticipationPoints { get; set; }
+ public int? ParticipationPoints { get; set; }
///
/// 备注
diff --git a/YD_Event.Application/User/Dtos/UpdateSysUserInput.cs b/YD_Event.Application/User/Dtos/UpdateSysUserInput.cs
index b6f62b9..03824f5 100644
--- a/YD_Event.Application/User/Dtos/UpdateSysUserInput.cs
+++ b/YD_Event.Application/User/Dtos/UpdateSysUserInput.cs
@@ -1,12 +1,47 @@
-namespace YD_Event.Application.User.Dtos;
+using System.ComponentModel.DataAnnotations;
+
+namespace YD_Event.Application.User.Dtos;
///
/// 更新系统用户输入
///
-public class UpdateSysUserInput : AddSysUserInput
+public class UpdateSysUserInput
{
///
/// 用户Id
///
+ [Required(ErrorMessage = "用户Id为必填项")]
public long Id { get; set; }
+
+ ///
+ /// 姓名
+ ///
+ [Required(ErrorMessage = "姓名为必填项")]
+ [MaxLength(16, ErrorMessage = "姓名限制16个字符内")]
+ public string Name { get; set; }
+
+ ///
+ /// 账号
+ ///
+ [Required(ErrorMessage = "账号为必填项")]
+ [MaxLength(32, ErrorMessage = "账号限制32个字符内")]
+ public string Account { get; set; }
+
+ ///
+ /// 密码(编辑时可选,不填则不修改)
+ ///
+ [MinLength(6, ErrorMessage = "密码长度至少6位")]
+ [MaxLength(32, ErrorMessage = "密码长度最多32位")]
+ public string? Password { get; set; }
+
+ ///
+ /// 关联角色ID集合
+ ///
+ [Required(ErrorMessage = "请选择关联角色")]
+ public List Roles { get; set; }
+
+ ///
+ /// 状态(默认启用)
+ ///
+ public AvailabilityStatus Status { get; set; } = AvailabilityStatus.Enable;
}
\ No newline at end of file
diff --git a/YD_Event.Application/User/SysUserService.cs b/YD_Event.Application/User/SysUserService.cs
index 0d3f677..8b257ba 100644
--- a/YD_Event.Application/User/SysUserService.cs
+++ b/YD_Event.Application/User/SysUserService.cs
@@ -147,7 +147,17 @@ public class SysUserService : BaseService, ITransient
if (await _repository.IsAnyAsync(x => x.Account == dto.Account && x.Id != dto.Id))
throw new InvalidOperationException($"账号 {dto.Account} 已被使用");
- dto.Adapt(user);
+ // 先更新除密码外的其他字段
+ user.Name = dto.Name;
+ user.Account = dto.Account;
+ user.Status = dto.Status;
+
+ // 只有密码不为空时才更新密码
+ if (!string.IsNullOrWhiteSpace(dto.Password))
+ {
+ string encode = _idGenerator.Encode(user.Id);
+ user.Password = MD5Encryption.Encrypt(encode + dto.Password);
+ }
// 处理角色关联:先删后加
var roles = new List();
diff --git a/YD_Event.Application/YD_Event.Application.xml b/YD_Event.Application/YD_Event.Application.xml
index 3e3e2f7..bd97233 100644
--- a/YD_Event.Application/YD_Event.Application.xml
+++ b/YD_Event.Application/YD_Event.Application.xml
@@ -431,6 +431,27 @@
验证码唯一id
+
+
+ 用户注册
+
+
+
+
+
+
+ 短信验证码登录
+
+
+
+
+
+
+ 重置密码
+
+
+
+
管理员登录输入参数
@@ -456,6 +477,81 @@
验证码
+
+
+ 用户注册输入参数
+
+
+
+
+ 手机号
+
+
+
+
+ 账号
+
+
+
+
+ 密码
+
+
+
+
+ 确认密码
+
+
+
+
+ 短信验证码
+
+
+
+
+ 同意用户协议
+
+
+
+
+ 短信登录输入参数
+
+
+
+
+ 手机号
+
+
+
+
+ 验证码
+
+
+
+
+ 重置密码输入参数
+
+
+
+
+ 手机号
+
+
+
+
+ 验证码
+
+
+
+
+ 新密码
+
+
+
+
+ 确认新密码
+
+
轮播图服务
@@ -1495,6 +1591,31 @@
主键ID
+
+
+ 客户端赛事查询输入
+
+
+
+
+ 搜索关键字
+
+
+
+
+ 状态筛选:0-全部 1-报名中 2-比赛中 3-已结束
+
+
+
+
+ 赛事类型
+
+
+
+
+ 收费模式
+
+
赛事列表项DTO
@@ -2919,14 +3040,11 @@
-
+
获取赛事列表
- 页码
- 页大小
- 状态筛选:0-全部 1-报名中 2-比赛中 3-已结束
- 搜索关键字
+ 查询参数
@@ -9868,6 +9986,31 @@
用户Id
+
+
+ 姓名
+
+
+
+
+ 账号
+
+
+
+
+ 密码(编辑时可选,不填则不修改)
+
+
+
+
+ 关联角色ID集合
+
+
+
+
+ 状态(默认启用)
+
+
系统用户管理
diff --git a/YD_Event.Core/Entities/PointsRule.cs b/YD_Event.Core/Entities/PointsRule.cs
index 5f49b29..4aa137b 100644
--- a/YD_Event.Core/Entities/PointsRule.cs
+++ b/YD_Event.Core/Entities/PointsRule.cs
@@ -16,7 +16,7 @@ public class PointsRule : Entity, ISoftDelete, ICreatedUserId, ICreatedTim
///
/// 参与积分(发放积分个数)
///
- public int ParticipationPoints { get; set; }
+ public int? ParticipationPoints { get; set; }
///
/// 备注