Browse Source

feat: 同步最新代码,修复和优化相关功能

feature/x1-owen-debug
root 4 weeks ago
parent
commit
da43347ac2
  1. 7
      src/X1.Domain/Common/OperationResult.cs
  2. 68
      src/X1.Presentation/Controllers/AuthController.cs
  3. 35
      src/X1.Presentation/Controllers/DevicesController.cs
  4. 7
      src/X1.Presentation/Controllers/PermissionsController.cs
  5. 21
      src/X1.Presentation/Controllers/RolePermissionController.cs
  6. 37
      src/X1.Presentation/Controllers/RolesController.cs
  7. 67
      src/X1.Presentation/Controllers/UsersController.cs
  8. 31
      src/X1.WebUI/src/components/auth/LoginForm.tsx
  9. 44
      src/X1.WebUI/src/components/auth/RegisterForm.tsx
  10. 3
      src/X1.WebUI/src/constants/auth.ts
  11. 45
      src/X1.WebUI/src/pages/auth/ForgotPasswordPage.tsx
  12. 231
      src/X1.WebUI/src/services/apiService.ts
  13. 31
      src/X1.WebUI/src/services/authService.ts
  14. 18
      src/X1.WebUI/src/types/auth.ts

7
src/X1.Domain/Common/OperationResult.cs

@ -28,6 +28,11 @@ public sealed record OperationResult<T>(
/// </summary> /// </summary>
public bool IsSuccess => ErrorMessages == null || !ErrorMessages.Any(); public bool IsSuccess => ErrorMessages == null || !ErrorMessages.Any();
/// <summary>
/// 获取成功消息(如果为空则返回默认消息)
/// </summary>
public string GetSuccessMessage() => SuccessMessage ?? "操作成功";
/// <summary> /// <summary>
/// 创建成功结果(仅包含数据) /// 创建成功结果(仅包含数据)
/// </summary> /// </summary>
@ -35,7 +40,7 @@ public sealed record OperationResult<T>(
/// <returns>成功结果</returns> /// <returns>成功结果</returns>
public static OperationResult<T> CreateSuccess(T data) public static OperationResult<T> CreateSuccess(T data)
{ {
return new OperationResult<T>(null, null, data); return new OperationResult<T>("操作成功", null, data);
} }
/// <summary> /// <summary>

68
src/X1.Presentation/Controllers/AuthController.cs

@ -81,7 +81,7 @@ public class AuthController : ApiController
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status429TooManyRequests)] [ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status429TooManyRequests)]
public async Task<ActionResult<OperationResult<AuthenticateUserResponse>>> Login([FromBody] AuthenticateUserCommand command) public async Task<OperationResult<AuthenticateUserResponse>> Login([FromBody] AuthenticateUserCommand command)
{ {
try try
{ {
@ -92,8 +92,7 @@ public class AuthController : ApiController
if (attempts >= _authConfig.MaxLoginAttempts) if (attempts >= _authConfig.MaxLoginAttempts)
{ {
_logger.LogWarning("账号 {UserName} 登录尝试次数过多", command.UserName); _logger.LogWarning("账号 {UserName} 登录尝试次数过多", command.UserName);
return StatusCode(StatusCodes.Status429TooManyRequests, return OperationResult<AuthenticateUserResponse>.CreateFailure("登录尝试次数过多,请稍后再试");
OperationResult<AuthenticateUserResponse>.CreateFailure("登录尝试次数过多,请稍后再试"));
} }
// 执行登录 // 执行登录
@ -123,13 +122,12 @@ public class AuthController : ApiController
_logger.LogWarning($"Bearer {result.Data.AccessToken}"); _logger.LogWarning($"Bearer {result.Data.AccessToken}");
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "账号 {UserName} 登录时发生异常", command.UserName); _logger.LogError(ex, "账号 {UserName} 登录时发生异常", command.UserName);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -156,10 +154,10 @@ public class AuthController : ApiController
/// <response code="400">登录失败,返回错误信息</response> /// <response code="400">登录失败,返回错误信息</response>
/// <response code="429">登录尝试次数过多</response> /// <response code="429">登录尝试次数过多</response>
[HttpPost("email")] [HttpPost("email")]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<EmailLoginResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<EmailLoginResponse>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status429TooManyRequests)] [ProducesResponseType(typeof(OperationResult<EmailLoginResponse>), StatusCodes.Status429TooManyRequests)]
public async Task<ActionResult<OperationResult<AuthenticateUserResponse>>> LoginWithEmail([FromBody] EmailLoginCommand command) public async Task<OperationResult<EmailLoginResponse>> LoginWithEmail([FromBody] EmailLoginCommand command)
{ {
try try
{ {
@ -170,8 +168,7 @@ public class AuthController : ApiController
if (attempts >= _authConfig.MaxLoginAttempts) if (attempts >= _authConfig.MaxLoginAttempts)
{ {
_logger.LogWarning("邮箱 {Email} 登录尝试次数过多", command.Email); _logger.LogWarning("邮箱 {Email} 登录尝试次数过多", command.Email);
return StatusCode(StatusCodes.Status429TooManyRequests, return OperationResult<EmailLoginResponse>.CreateFailure("登录尝试次数过多,请稍后再试");
OperationResult<AuthenticateUserResponse>.CreateFailure("登录尝试次数过多,请稍后再试"));
} }
// 执行登录 // 执行登录
@ -201,13 +198,12 @@ public class AuthController : ApiController
_logger.LogWarning($"Bearer {result.Data.AccessToken}"); _logger.LogWarning($"Bearer {result.Data.AccessToken}");
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "邮箱 {Email} 登录时发生异常", command.Email); _logger.LogError(ex, "邮箱 {Email} 登录时发生异常", command.Email);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<EmailLoginResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -238,7 +234,7 @@ public class AuthController : ApiController
[HttpPost("register")] [HttpPost("register")]
[ProducesResponseType(typeof(OperationResult<RegisterUserResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<RegisterUserResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<RegisterUserResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<RegisterUserResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<RegisterUserResponse>>> Register([FromBody] RegisterUserCommand command) public async Task<OperationResult<RegisterUserResponse>> Register([FromBody] RegisterUserCommand command)
{ {
try try
{ {
@ -256,13 +252,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "用户 {UserName} 注册时发生异常", command.UserName); _logger.LogError(ex, "用户 {UserName} 注册时发生异常", command.UserName);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<RegisterUserResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<RegisterUserResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -289,7 +284,7 @@ public class AuthController : ApiController
[HttpPost("refresh-token")] [HttpPost("refresh-token")]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<AuthenticateUserResponse>>> RefreshToken([FromBody] RefreshTokenCommand command) public async Task<OperationResult<AuthenticateUserResponse>> RefreshToken([FromBody] RefreshTokenCommand command)
{ {
try try
{ {
@ -305,13 +300,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "刷新令牌时发生异常"); _logger.LogError(ex, "刷新令牌时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -338,7 +332,7 @@ public class AuthController : ApiController
[HttpPost("verification-codes")] [HttpPost("verification-codes")]
[ProducesResponseType(typeof(OperationResult<SendVerificationCodeResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<SendVerificationCodeResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<SendVerificationCodeResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<SendVerificationCodeResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<SendVerificationCodeResponse>>> SendVerificationCode( public async Task<OperationResult<SendVerificationCodeResponse>> SendVerificationCode(
[FromBody] SendVerificationCodeCommand command) [FromBody] SendVerificationCodeCommand command)
{ {
try try
@ -357,13 +351,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "向邮箱 {Email} 发送验证码时发生异常", command.Email); _logger.LogError(ex, "向邮箱 {Email} 发送验证码时发生异常", command.Email);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<SendVerificationCodeResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<SendVerificationCodeResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -391,7 +384,7 @@ public class AuthController : ApiController
[HttpPost("verification-codes/verify")] [HttpPost("verification-codes/verify")]
[ProducesResponseType(typeof(OperationResult<VerifyCodeResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<VerifyCodeResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<VerifyCodeResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<VerifyCodeResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<VerifyCodeResponse>>> VerifyCode( public async Task<OperationResult<VerifyCodeResponse>> VerifyCode(
[FromBody] VerifyCodeCommand command) [FromBody] VerifyCodeCommand command)
{ {
try try
@ -410,13 +403,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "验证邮箱 {Email} 的验证码时发生异常", command.Email); _logger.LogError(ex, "验证邮箱 {Email} 的验证码时发生异常", command.Email);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<VerifyCodeResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<VerifyCodeResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -432,7 +424,7 @@ public class AuthController : ApiController
[HttpGet("captcha")] [HttpGet("captcha")]
[ProducesResponseType(typeof(OperationResult<GenerateCaptchaResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<GenerateCaptchaResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<GenerateCaptchaResponse>), StatusCodes.Status500InternalServerError)] [ProducesResponseType(typeof(OperationResult<GenerateCaptchaResponse>), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<OperationResult<GenerateCaptchaResponse>>> GetCaptcha() public async Task<OperationResult<GenerateCaptchaResponse>> GetCaptcha()
{ {
try try
{ {
@ -455,13 +447,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "生成图形验证码时发生异常"); _logger.LogError(ex, "生成图形验证码时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<GenerateCaptchaResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<GenerateCaptchaResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -488,7 +479,7 @@ public class AuthController : ApiController
[HttpPost("logout")] [HttpPost("logout")]
[ProducesResponseType(typeof(OperationResult<bool>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<bool>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<bool>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<bool>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<bool>>> Logout([FromBody] LogoutCommand command) public async Task<OperationResult<bool>> Logout([FromBody] LogoutCommand command)
{ {
try try
{ {
@ -504,13 +495,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "用户登出时发生异常"); _logger.LogError(ex, "用户登出时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<bool>.CreateFailure("系统错误,请稍后重试");
OperationResult<bool>.CreateFailure("系统错误,请稍后重试"));
} }
} }
} }

35
src/X1.Presentation/Controllers/DevicesController.cs

@ -38,7 +38,7 @@ namespace CellularManagement.Presentation.Controllers
/// 获取设备列表 /// 获取设备列表
/// </summary> /// </summary>
[HttpGet] [HttpGet]
public async Task<ActionResult<OperationResult<GetDevicesResponse>>> GetAll([FromQuery] GetDevicesQuery query) public async Task<OperationResult<GetDevicesResponse>> GetAll([FromQuery] GetDevicesQuery query)
{ {
_logger.LogInformation("开始获取设备列表,页码: {PageNumber}, 每页数量: {PageSize}, 搜索关键词: {SearchTerm}", _logger.LogInformation("开始获取设备列表,页码: {PageNumber}, 每页数量: {PageSize}, 搜索关键词: {SearchTerm}",
query.PageNumber, query.PageSize, query.SearchTerm); query.PageNumber, query.PageSize, query.SearchTerm);
@ -47,18 +47,18 @@ namespace CellularManagement.Presentation.Controllers
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
_logger.LogWarning("获取设备列表失败: {Message}", result.ErrorMessages); _logger.LogWarning("获取设备列表失败: {Message}", result.ErrorMessages);
return BadRequest(result); return result;
} }
_logger.LogInformation("成功获取设备列表,共 {Count} 条记录", result.Data?.TotalCount ?? 0); _logger.LogInformation("成功获取设备列表,共 {Count} 条记录", result.Data?.TotalCount ?? 0);
return Ok(result); return result;
} }
/// <summary> /// <summary>
/// 获取设备详情 /// 获取设备详情
/// </summary> /// </summary>
[HttpGet("{id}")] [HttpGet("{id}")]
public async Task<ActionResult<OperationResult<GetDeviceByIdResponse>>> GetById(string id) public async Task<OperationResult<GetDeviceByIdResponse>> GetById(string id)
{ {
_logger.LogInformation("开始获取设备详情,设备ID: {DeviceId}", id); _logger.LogInformation("开始获取设备详情,设备ID: {DeviceId}", id);
@ -66,18 +66,18 @@ namespace CellularManagement.Presentation.Controllers
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
_logger.LogWarning("获取设备详情失败: {Message}", result.ErrorMessages); _logger.LogWarning("获取设备详情失败: {Message}", result.ErrorMessages);
return NotFound(result); return result;
} }
_logger.LogInformation("成功获取设备详情,设备ID: {DeviceId}", id); _logger.LogInformation("成功获取设备详情,设备ID: {DeviceId}", id);
return Ok(result); return result;
} }
/// <summary> /// <summary>
/// 创建设备 /// 创建设备
/// </summary> /// </summary>
[HttpPost] [HttpPost]
public async Task<ActionResult<OperationResult<CreateDeviceResponse>>> Create([FromBody] CreateDeviceCommand command) public async Task<OperationResult<CreateDeviceResponse>> Create([FromBody] CreateDeviceCommand command)
{ {
_logger.LogInformation("开始创建设备,设备名称: {DeviceName}", command.DeviceName); _logger.LogInformation("开始创建设备,设备名称: {DeviceName}", command.DeviceName);
@ -85,46 +85,43 @@ namespace CellularManagement.Presentation.Controllers
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
_logger.LogWarning("创建设备失败: {Message}", result.ErrorMessages); _logger.LogWarning("创建设备失败: {Message}", result.ErrorMessages);
return BadRequest(result); return result;
} }
_logger.LogInformation("成功创建设备,设备ID: {DeviceId}", result.Data.DeviceId); _logger.LogInformation("成功创建设备,设备ID: {DeviceId}", result.Data.DeviceId);
return CreatedAtAction( return result;
nameof(GetById),
new { id = result.Data.DeviceId },
result);
} }
/// <summary> /// <summary>
/// 更新设备 /// 更新设备
/// </summary> /// </summary>
[HttpPut("{id}")] [HttpPut("{id}")]
public async Task<ActionResult<OperationResult<bool>>> Update(string id, [FromBody] UpdateDeviceCommand command) public async Task<OperationResult<UpdateDeviceResponse>> Update(string id, [FromBody] UpdateDeviceCommand command)
{ {
_logger.LogInformation("开始更新设备,设备ID: {DeviceId}", id); _logger.LogInformation("开始更新设备,设备ID: {DeviceId}", id);
if (id != command.DeviceId) if (id != command.DeviceId)
{ {
_logger.LogWarning("设备ID不匹配,路径ID: {PathId}, 命令ID: {CommandId}", id, command.DeviceName); _logger.LogWarning("设备ID不匹配,路径ID: {PathId}, 命令ID: {CommandId}", id, command.DeviceName);
return BadRequest(OperationResult<bool>.CreateFailure("设备ID不匹配")); return OperationResult<UpdateDeviceResponse>.CreateFailure("设备ID不匹配");
} }
var result = await mediator.Send(command); var result = await mediator.Send(command);
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
_logger.LogWarning("更新设备失败: {Message}", result.ErrorMessages); _logger.LogWarning("更新设备失败: {Message}", result.ErrorMessages);
return NotFound(result); return result;
} }
_logger.LogInformation("成功更新设备,设备ID: {DeviceId}", id); _logger.LogInformation("成功更新设备,设备ID: {DeviceId}", id);
return Ok(result); return result;
} }
/// <summary> /// <summary>
/// 删除设备 /// 删除设备
/// </summary> /// </summary>
[HttpDelete("{id}")] [HttpDelete("{id}")]
public async Task<ActionResult<OperationResult<bool>>> Delete(string id) public async Task<OperationResult<bool>> Delete(string id)
{ {
_logger.LogInformation("开始删除设备,设备ID: {DeviceId}", id); _logger.LogInformation("开始删除设备,设备ID: {DeviceId}", id);
@ -132,11 +129,11 @@ namespace CellularManagement.Presentation.Controllers
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
_logger.LogWarning("删除设备失败: {Message}", result.ErrorMessages); _logger.LogWarning("删除设备失败: {Message}", result.ErrorMessages);
return NotFound(result); return result;
} }
_logger.LogInformation("成功删除设备,设备ID: {DeviceId}", id); _logger.LogInformation("成功删除设备,设备ID: {DeviceId}", id);
return Ok(result); return result;
} }
} }
} }

7
src/X1.Presentation/Controllers/PermissionsController.cs

@ -57,7 +57,7 @@ public class PermissionsController : ApiController
[HttpPost] [HttpPost]
[ProducesResponseType(typeof(OperationResult<CreatePermissionResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<CreatePermissionResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<CreatePermissionResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<CreatePermissionResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<CreatePermissionResponse>>> CreatePermission([FromBody] CreatePermissionCommand command) public async Task<OperationResult<CreatePermissionResponse>> CreatePermission([FromBody] CreatePermissionCommand command)
{ {
try try
{ {
@ -74,13 +74,12 @@ public class PermissionsController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "创建权限 {PermissionName} 时发生异常", command.Name); _logger.LogError(ex, "创建权限 {PermissionName} 时发生异常", command.Name);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<CreatePermissionResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<CreatePermissionResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
} }

21
src/X1.Presentation/Controllers/RolePermissionController.cs

@ -54,7 +54,7 @@ public class RolePermissionController : ApiController
[HttpGet("{roleId}")] [HttpGet("{roleId}")]
[ProducesResponseType(typeof(OperationResult<GetRolePermissionsResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<GetRolePermissionsResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<GetRolePermissionsResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<GetRolePermissionsResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<GetRolePermissionsResponse>>> GetRolePermissions( public async Task<OperationResult<GetRolePermissionsResponse>> GetRolePermissions(
string roleId, string roleId,
[FromQuery] bool includeDetails = true) [FromQuery] bool includeDetails = true)
{ {
@ -83,13 +83,12 @@ public class RolePermissionController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "获取角色 {RoleId} 的权限信息时发生异常", roleId); _logger.LogError(ex, "获取角色 {RoleId} 的权限信息时发生异常", roleId);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<GetRolePermissionsResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<GetRolePermissionsResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -117,7 +116,7 @@ public class RolePermissionController : ApiController
[HttpPost] [HttpPost]
[ProducesResponseType(typeof(OperationResult<AddRolePermissionsResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<AddRolePermissionsResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<AddRolePermissionsResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<AddRolePermissionsResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<AddRolePermissionsResponse>>> AddRolePermissions( public async Task<OperationResult<AddRolePermissionsResponse>> AddRolePermissions(
[FromBody] AddRolePermissionsCommand command) [FromBody] AddRolePermissionsCommand command)
{ {
try try
@ -140,13 +139,12 @@ public class RolePermissionController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "为角色 {RoleId} 添加权限时发生异常", command.RoleId); _logger.LogError(ex, "为角色 {RoleId} 添加权限时发生异常", command.RoleId);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<AddRolePermissionsResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<AddRolePermissionsResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -174,7 +172,7 @@ public class RolePermissionController : ApiController
[HttpDelete] [HttpDelete]
[ProducesResponseType(typeof(OperationResult<DeleteRolePermissionsResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<DeleteRolePermissionsResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<DeleteRolePermissionsResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<DeleteRolePermissionsResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<DeleteRolePermissionsResponse>>> DeleteRolePermissions( public async Task<OperationResult<DeleteRolePermissionsResponse>> DeleteRolePermissions(
[FromBody] DeleteRolePermissionsCommand command) [FromBody] DeleteRolePermissionsCommand command)
{ {
try try
@ -197,13 +195,12 @@ public class RolePermissionController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "从角色 {RoleId} 删除权限时发生异常", command.RoleId); _logger.LogError(ex, "从角色 {RoleId} 删除权限时发生异常", command.RoleId);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<DeleteRolePermissionsResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<DeleteRolePermissionsResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
} }

37
src/X1.Presentation/Controllers/RolesController.cs

@ -78,7 +78,7 @@ public class RolesController : ApiController
[HttpPost] [HttpPost]
[ProducesResponseType(typeof(OperationResult<CreateRoleResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<CreateRoleResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<CreateRoleResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<CreateRoleResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<CreateRoleResponse>>> CreateRole([FromBody] CreateRoleCommand command) public async Task<OperationResult<CreateRoleResponse>> CreateRole([FromBody] CreateRoleCommand command)
{ {
try try
{ {
@ -95,13 +95,12 @@ public class RolesController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "创建角色 {RoleName} 时发生异常", command.Name); _logger.LogError(ex, "创建角色 {RoleName} 时发生异常", command.Name);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<CreateRoleResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<CreateRoleResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -127,7 +126,7 @@ public class RolesController : ApiController
[ProducesResponseType(typeof(OperationResult<DeleteRoleResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<DeleteRoleResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<DeleteRoleResponse>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<DeleteRoleResponse>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<DeleteRoleResponse>), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(OperationResult<DeleteRoleResponse>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<DeleteRoleResponse>>> DeleteRole(string roleId) public async Task<OperationResult<DeleteRoleResponse>> DeleteRole(string roleId)
{ {
try try
{ {
@ -145,13 +144,12 @@ public class RolesController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "删除角色 {RoleId} 时发生异常", roleId); _logger.LogError(ex, "删除角色 {RoleId} 时发生异常", roleId);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<DeleteRoleResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<DeleteRoleResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -175,7 +173,7 @@ public class RolesController : ApiController
[HttpGet("{roleId}")] [HttpGet("{roleId}")]
[ProducesResponseType(typeof(OperationResult<GetRoleResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<GetRoleResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<GetRoleResponse>), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(OperationResult<GetRoleResponse>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<GetRoleResponse>>> GetRole(string roleId) public async Task<OperationResult<GetRoleResponse>> GetRole(string roleId)
{ {
try try
{ {
@ -193,13 +191,12 @@ public class RolesController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "获取角色 {RoleId} 信息时发生异常", roleId); _logger.LogError(ex, "获取角色 {RoleId} 信息时发生异常", roleId);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<GetRoleResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<GetRoleResponse>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -223,7 +220,7 @@ public class RolesController : ApiController
[HttpGet] [HttpGet]
[ProducesResponseType(typeof(OperationResult<GetAllRolesResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<GetAllRolesResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<GetAllRolesResponse>>> GetAllRoles([FromQuery] GetAllRolesQuery query) public async Task<OperationResult<GetAllRolesResponse>> GetAllRoles([FromQuery] GetAllRolesQuery query)
{ {
try try
{ {
@ -231,23 +228,21 @@ public class RolesController : ApiController
if (result.IsSuccess) if (result.IsSuccess)
{ {
_logger.LogInformation("获取角色列表成功,共 {TotalCount} 条记录,当前第 {PageNumber} 页", _logger.LogInformation("获取所有角色成功,共 {Count} 个角色",
result.Data?.TotalCount, result.Data?.Roles.Count());
result.Data?.PageNumber);
} }
else else
{ {
_logger.LogWarning("获取角色列表失败: {Error}", _logger.LogWarning("获取所有角色失败: {Error}",
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "获取角色列表时发生异常"); _logger.LogError(ex, "获取所有角色时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<GetAllRolesResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
} }
} }
} }

67
src/X1.Presentation/Controllers/UsersController.cs

@ -64,7 +64,7 @@ public class UsersController : ApiController
[HttpPost] [HttpPost]
[ProducesResponseType(typeof(OperationResult<CreateUserResponse>), StatusCodes.Status201Created)] [ProducesResponseType(typeof(OperationResult<CreateUserResponse>), StatusCodes.Status201Created)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<CreateUserResponse>>> CreateUser([FromBody] CreateUserCommand command) public async Task<OperationResult<CreateUserResponse>> CreateUser([FromBody] CreateUserCommand command)
{ {
try try
{ {
@ -73,20 +73,19 @@ public class UsersController : ApiController
if (result.IsSuccess) if (result.IsSuccess)
{ {
_logger.LogInformation("创建用户成功,用户ID: {UserId}", result.Data?.UserId); _logger.LogInformation("创建用户成功,用户ID: {UserId}", result.Data?.UserId);
return CreatedAtAction(nameof(GetUserById), new { id = result.Data?.UserId }, result);
} }
else else
{ {
_logger.LogWarning("创建用户失败: {Error}", _logger.LogWarning("创建用户失败: {Error}",
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
return BadRequest(result);
} }
return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "创建用户时发生异常"); _logger.LogError(ex, "创建用户时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<CreateUserResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -117,7 +116,7 @@ public class UsersController : ApiController
[HttpGet] [HttpGet]
[ProducesResponseType(typeof(OperationResult<GetAllUsersResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<GetAllUsersResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<GetAllUsersResponse>>> GetUsers([FromQuery] GetAllUsersQuery query) public async Task<OperationResult<GetAllUsersResponse>> GetUsers([FromQuery] GetAllUsersQuery query)
{ {
try try
{ {
@ -135,13 +134,12 @@ public class UsersController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "获取用户列表时发生异常"); _logger.LogError(ex, "获取用户列表时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<GetAllUsersResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -167,7 +165,7 @@ public class UsersController : ApiController
[ProducesResponseType(typeof(OperationResult<GetUserByIdResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<GetUserByIdResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<GetUserByIdResponse>>> GetUserById([FromRoute] string id) public async Task<OperationResult<GetUserByIdResponse>> GetUserById([FromRoute] string id)
{ {
try try
{ {
@ -185,13 +183,12 @@ public class UsersController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "获取用户 {UserId} 信息时发生异常", id); _logger.LogError(ex, "获取用户 {UserId} 信息时发生异常", id);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<GetUserByIdResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -223,13 +220,18 @@ public class UsersController : ApiController
[ProducesResponseType(typeof(OperationResult<UpdateUserResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<UpdateUserResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<UpdateUserResponse>>> UpdateUser( public async Task<OperationResult<UpdateUserResponse>> UpdateUser(
[FromRoute] string id, [FromRoute] string id,
[FromBody] UpdateUserCommand command) [FromBody] UpdateUserCommand command)
{ {
try try
{ {
command = command with { UserId = id }; if (id != command.UserId)
{
_logger.LogWarning("用户ID不匹配,路径ID: {PathId}, 命令ID: {CommandId}", id, command.UserId);
return OperationResult<UpdateUserResponse>.CreateFailure("用户ID不匹配");
}
var result = await mediator.Send(command); var result = await mediator.Send(command);
if (result.IsSuccess) if (result.IsSuccess)
@ -243,13 +245,12 @@ public class UsersController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "更新用户 {UserId} 信息时发生异常", id); _logger.LogError(ex, "更新用户 {UserId} 信息时发生异常", id);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<UpdateUserResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -272,10 +273,10 @@ public class UsersController : ApiController
/// <response code="400">删除失败,返回错误信息</response> /// <response code="400">删除失败,返回错误信息</response>
/// <response code="404">用户不存在</response> /// <response code="404">用户不存在</response>
[HttpDelete("{id}")] [HttpDelete("{id}")]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<DeleteUserResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(OperationResult<DeleteUserResponse>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(OperationResult<DeleteUserResponse>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<object>>> DeleteUser([FromRoute] string id) public async Task<OperationResult<DeleteUserResponse>> DeleteUser([FromRoute] string id)
{ {
try try
{ {
@ -293,13 +294,12 @@ public class UsersController : ApiController
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
} }
return Ok(result); return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "删除用户 {UserId} 时发生异常", id); _logger.LogError(ex, "删除用户 {UserId} 时发生异常", id);
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<DeleteUserResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
} }
} }
@ -324,15 +324,15 @@ public class UsersController : ApiController
[ProducesResponseType(typeof(OperationResult<GetUserByIdResponse>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(OperationResult<GetUserByIdResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status401Unauthorized)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<GetUserByIdResponse>>> CurrentUser() public async Task<OperationResult<GetUserByIdResponse>> CurrentUser()
{ {
try try
{ {
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value; var userId = User.FindFirst("sub")?.Value;
if (string.IsNullOrEmpty(userId)) if (string.IsNullOrEmpty(userId))
{ {
_logger.LogWarning("获取当前用户信息失败:未找到用户ID"); _logger.LogWarning("无法获取当前用户ID");
return Unauthorized(OperationResult<object>.CreateFailure("未授权,请先登录")); return OperationResult<GetUserByIdResponse>.CreateFailure("无法获取当前用户信息");
} }
var query = new GetUserByIdQuery(userId); var query = new GetUserByIdQuery(userId);
@ -340,21 +340,20 @@ public class UsersController : ApiController
if (result.IsSuccess) if (result.IsSuccess)
{ {
_logger.LogInformation("获取当前用户信息成功,用户ID: {UserId}", userId); _logger.LogInformation("获取当前用户信息成功");
return Ok(result);
} }
else else
{ {
_logger.LogWarning("获取当前用户信息失败: {Error}", _logger.LogWarning("获取当前用户信息失败: {Error}",
result.ErrorMessages?.FirstOrDefault()); result.ErrorMessages?.FirstOrDefault());
return NotFound(result);
} }
return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "获取当前用户信息时发生异常"); _logger.LogError(ex, "获取当前用户信息时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError, return OperationResult<GetUserByIdResponse>.CreateFailure("系统错误,请稍后重试");
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
} }
} }
} }

31
src/X1.WebUI/src/components/auth/LoginForm.tsx

@ -4,6 +4,7 @@ import { useAuth } from '@/contexts/AuthContext';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { apiService } from '@/services/apiService'; import { apiService } from '@/services/apiService';
import { toast } from '@/components/ui/use-toast'; import { toast } from '@/components/ui/use-toast';
import { getErrorMessage } from '@/types/auth';
interface LoginFormProps { interface LoginFormProps {
onSubmit: (username: string, password: string, rememberMe: boolean, loginType: 'account' | 'email', verificationCode?: string, captchaId?: string, captchaCode?: string) => Promise<void>; onSubmit: (username: string, password: string, rememberMe: boolean, loginType: 'account' | 'email', verificationCode?: string, captchaId?: string, captchaCode?: string) => Promise<void>;
@ -44,28 +45,36 @@ export function LoginForm({ onSubmit }: LoginFormProps) {
try { try {
setCaptchaAvailable(false); setCaptchaAvailable(false);
const result = await apiService.getCaptcha(); const result = await apiService.getCaptcha();
if (result.success && result.data) {
// 业务逻辑判断
if (result.isSuccess && result.data) {
setCaptchaImage(result.data.imageBase64); setCaptchaImage(result.data.imageBase64);
setCaptchaId(result.data.captchaId); setCaptchaId(result.data.captchaId);
setCaptchaAvailable(true); setCaptchaAvailable(true);
console.log('验证码获取成功:', result.successMessage);
} else { } else {
// 业务操作失败
setCaptchaImage(''); setCaptchaImage('');
setCaptchaId(''); setCaptchaId('');
setCaptchaAvailable(false); setCaptchaAvailable(false);
const errorMessage = getErrorMessage(result);
console.warn('验证码获取业务操作失败:', errorMessage);
toast({ toast({
title: '获取验证码失败', title: '获取验证码失败',
description: result.message || '请点击验证码图片重试', description: errorMessage || '请点击验证码图片重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
} }
} catch (error) { } catch (error) {
// HTTP 错误处理
setCaptchaImage(''); setCaptchaImage('');
setCaptchaId(''); setCaptchaId('');
setCaptchaAvailable(false); setCaptchaAvailable(false);
console.error('验证码获取HTTP错误:', error);
toast({ toast({
title: '获取验证码失败', title: '获取验证码失败',
description: '请点击验证码图片重试', description: '网络错误,请点击验证码图片重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
@ -123,31 +132,37 @@ export function LoginForm({ onSubmit }: LoginFormProps) {
} }
try { try {
const response = await apiService.sendVerificationCode({ const result = await apiService.sendVerificationCode({
email: `${email}@qq.com`, email: `${email}@qq.com`,
captchaId, captchaId,
captchaCode captchaCode
}); });
if (response.success) { // 业务逻辑判断
if (result.isSuccess) {
setCountdown(120); // 设置120秒倒计时 setCountdown(120); // 设置120秒倒计时
toast({ toast({
title: '验证码已发送', title: '验证码已发送',
description: '请查收您的QQ邮箱', description: result.successMessage || '请查收您的QQ邮箱',
duration: 3000, duration: 3000,
}); });
} else { } else {
// 业务操作失败
const errorMessage = getErrorMessage(result);
console.warn('发送验证码业务操作失败:', errorMessage);
toast({ toast({
title: '发送失败', title: '发送失败',
description: response.message || '请稍后重试', description: errorMessage || '请稍后重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
} }
} catch (error) { } catch (error) {
// HTTP 错误处理
console.error('发送验证码HTTP错误:', error);
toast({ toast({
title: '发送失败', title: '发送失败',
description: '请稍后重试', description: '网络错误,请稍后重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });

44
src/X1.WebUI/src/components/auth/RegisterForm.tsx

@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
import { z } from 'zod'; import { z } from 'zod';
import { toast } from '@/components/ui/use-toast'; import { toast } from '@/components/ui/use-toast';
import { apiService } from '@/services/apiService'; import { apiService } from '@/services/apiService';
import { getErrorMessage } from '@/types/auth';
// 定义表单验证规则 // 定义表单验证规则
const registerSchema = z.object({ const registerSchema = z.object({
@ -70,40 +71,53 @@ export function RegisterForm({ onSubmit }: RegisterFormProps) {
// 获取验证码 // 获取验证码
const fetchCaptcha = async () => { const fetchCaptcha = async () => {
console.log('fetchCaptcha 被调用'); // 添加调试日志
try { try {
setCaptchaAvailable(false); setCaptchaAvailable(false); // 开始获取时设置为不可用
const result = await apiService.getCaptcha(); const result = await apiService.getCaptcha();
if (result.success && result.data) {
// 业务逻辑判断
if (result.isSuccess && result.data) {
setCaptchaImage(result.data.imageBase64); setCaptchaImage(result.data.imageBase64);
setCaptchaId(result.data.captchaId); setCaptchaId(result.data.captchaId);
setCaptchaAvailable(true); setCaptchaAvailable(true); // 成功时设置为可用
setError(null); setError(null);
console.log('验证码获取成功:', result.successMessage);
} else { } else {
setCaptchaImage(''); // 业务操作失败 - 保持图片但重置状态
setCaptchaId(''); setCaptchaAvailable(false); // 失败时重置为不可用
setCaptchaAvailable(false); const errorMessage = getErrorMessage(result);
setError('获取验证码失败,请重试'); setError('获取验证码失败,请重试');
console.warn('验证码获取业务操作失败:', errorMessage);
toast({ toast({
title: '获取验证码失败', title: '获取验证码失败',
description: result.message || '请点击验证码图片重试', description: errorMessage || '请点击验证码图片重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
} }
} catch (error) { } catch (error) {
setCaptchaImage(''); // HTTP 错误处理 - 保持图片但重置状态
setCaptchaId(''); setCaptchaAvailable(false); // 失败时重置为不可用
setCaptchaAvailable(false);
setError('获取验证码失败,请重试'); setError('获取验证码失败,请重试');
console.error('验证码获取HTTP错误:', error);
toast({ toast({
title: '获取验证码失败', title: '获取验证码失败',
description: '请点击验证码图片重试', description: '网络错误,请点击验证码图片重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
} }
}; };
// 添加专门的点击处理函数
const handleCaptchaClick = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
console.log('验证码图片被点击'); // 添加调试日志
fetchCaptcha();
};
// 组件加载时获取验证码 // 组件加载时获取验证码
useEffect(() => { useEffect(() => {
fetchCaptcha(); fetchCaptcha();
@ -424,10 +438,14 @@ export function RegisterForm({ onSubmit }: RegisterFormProps) {
src={`data:image/png;base64,${captchaImage}`} src={`data:image/png;base64,${captchaImage}`}
alt="验证码" alt="验证码"
className="h-[42px] min-w-[100px] max-w-full cursor-pointer rounded-lg shadow-sm hover:shadow transition-all duration-200" className="h-[42px] min-w-[100px] max-w-full cursor-pointer rounded-lg shadow-sm hover:shadow transition-all duration-200"
onClick={fetchCaptcha} onClick={handleCaptchaClick} // 使用新的处理函数
title="点击刷新验证码" title="点击刷新验证码"
style={{ pointerEvents: 'auto' }} // 确保可以点击
/> />
<div className="absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/5 transition-colors duration-200 rounded-lg"> <div
className="absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/5 transition-colors duration-200 rounded-lg"
style={{ pointerEvents: 'none' }} // 防止覆盖层阻止点击
>
<svg className="w-5 h-5 text-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <svg className="w-5 h-5 text-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg> </svg>

3
src/X1.WebUI/src/constants/auth.ts

@ -41,7 +41,8 @@ export const AUTH_CONSTANTS = {
RESET_PASSWORD_EMAIL_SENT: '验证码已发送到您的邮箱', RESET_PASSWORD_EMAIL_SENT: '验证码已发送到您的邮箱',
RESET_PASSWORD_EMAIL_FAILED: '验证码发送失败,请稍后重试', RESET_PASSWORD_EMAIL_FAILED: '验证码发送失败,请稍后重试',
PASSWORD_RESET_SUCCESS: '密码重置成功', PASSWORD_RESET_SUCCESS: '密码重置成功',
PASSWORD_RESET_FAILED: '密码重置失败,请稍后重试' PASSWORD_RESET_FAILED: '密码重置失败,请稍后重试',
ACCOUNT_LOCKED: '账号已被锁定,请稍后再试'
} }
} as const; } as const;

45
src/X1.WebUI/src/pages/auth/ForgotPasswordPage.tsx

@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { apiService } from '@/services/apiService'; import { apiService } from '@/services/apiService';
import { toast } from '@/components/ui/use-toast'; import { toast } from '@/components/ui/use-toast';
import { getErrorMessage } from '@/types/auth';
export function ForgotPasswordPage() { export function ForgotPasswordPage() {
const navigate = useNavigate(); const navigate = useNavigate();
@ -20,28 +21,36 @@ export function ForgotPasswordPage() {
try { try {
setCaptchaAvailable(false); setCaptchaAvailable(false);
const result = await apiService.getCaptcha(); const result = await apiService.getCaptcha();
if (result.success && result.data) {
// 业务逻辑判断:检查业务操作是否成功
if (result.isSuccess && result.data) {
setCaptchaImage(result.data.imageBase64); setCaptchaImage(result.data.imageBase64);
setCaptchaId(result.data.captchaId); setCaptchaId(result.data.captchaId);
setCaptchaAvailable(true); setCaptchaAvailable(true);
console.log('验证码获取成功:', result.successMessage);
} else { } else {
// 业务操作失败
setCaptchaImage(''); setCaptchaImage('');
setCaptchaId(''); setCaptchaId('');
setCaptchaAvailable(false); setCaptchaAvailable(false);
const errorMessage = getErrorMessage(result);
console.warn('验证码获取业务操作失败:', errorMessage);
toast({ toast({
title: '获取验证码失败', title: '获取验证码失败',
description: result.message || '请点击验证码图片重试', description: errorMessage || '请点击验证码图片重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
} }
} catch (error) { } catch (error) {
// HTTP 错误处理
setCaptchaImage(''); setCaptchaImage('');
setCaptchaId(''); setCaptchaId('');
setCaptchaAvailable(false); setCaptchaAvailable(false);
console.error('验证码获取HTTP错误:', error);
toast({ toast({
title: '获取验证码失败', title: '获取验证码失败',
description: '请点击验证码图片重试', description: '网络错误,请点击验证码图片重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
@ -77,24 +86,31 @@ export function ForgotPasswordPage() {
try { try {
setIsLoading(true); setIsLoading(true);
const result = await apiService.sendResetPasswordEmail(email, captchaId, captchaCode); const result = await apiService.sendResetPasswordEmail(email, captchaId, captchaCode);
if (result.success) {
// 业务逻辑判断
if (result.isSuccess) {
toast({ toast({
title: '验证码已发送', title: '验证码已发送',
description: '请查收您的邮箱', description: result.successMessage || '请查收您的邮箱',
duration: 3000, duration: 3000,
}); });
} else { } else {
// 业务操作失败
const errorMessage = getErrorMessage(result);
console.warn('发送验证码业务操作失败:', errorMessage);
toast({ toast({
title: '发送失败', title: '发送失败',
description: result.message || '请稍后重试', description: errorMessage || '请稍后重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
} }
} catch (error) { } catch (error) {
// HTTP 错误处理
console.error('发送验证码HTTP错误:', error);
toast({ toast({
title: '发送失败', title: '发送失败',
description: '请稍后重试', description: '网络错误,请稍后重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
@ -129,25 +145,32 @@ export function ForgotPasswordPage() {
try { try {
setIsLoading(true); setIsLoading(true);
const result = await apiService.resetPassword(email, verificationCode, newPassword); const result = await apiService.resetPassword(email, verificationCode, newPassword);
if (result.success) {
// 业务逻辑判断
if (result.isSuccess) {
toast({ toast({
title: '密码重置成功', title: '密码重置成功',
description: '请使用新密码登录', description: result.successMessage || '请使用新密码登录',
duration: 3000, duration: 3000,
}); });
navigate('/login'); navigate('/login');
} else { } else {
// 业务操作失败
const errorMessage = getErrorMessage(result);
console.warn('密码重置业务操作失败:', errorMessage);
toast({ toast({
title: '重置失败', title: '重置失败',
description: result.message || '请稍后重试', description: errorMessage || '请稍后重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });
} }
} catch (error) { } catch (error) {
// HTTP 错误处理
console.error('密码重置HTTP错误:', error);
toast({ toast({
title: '重置失败', title: '重置失败',
description: '请稍后重试', description: '网络错误,请稍后重试',
variant: 'destructive', variant: 'destructive',
duration: 3000, duration: 3000,
}); });

231
src/X1.WebUI/src/services/apiService.ts

@ -1,4 +1,4 @@
import { LoginRequest, RegisterRequest, LoginResponse, User, OperationResult } from '@/types/auth'; import { LoginRequest, RegisterRequest, LoginResponse, User, OperationResult, getSuccessMessage, getErrorMessage } from '@/types/auth';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
import { AUTH_CONSTANTS } from '@/constants/auth'; import { AUTH_CONSTANTS } from '@/constants/auth';
@ -7,13 +7,6 @@ interface CaptchaResponse {
imageBase64: string; imageBase64: string;
} }
interface ApiResponse<T> {
successMessage: string | null;
errorMessages: string[] | null;
data: T;
isSuccess: boolean;
}
export interface ApiService { export interface ApiService {
login: (request: LoginRequest) => Promise<OperationResult<LoginResponse>>; login: (request: LoginRequest) => Promise<OperationResult<LoginResponse>>;
emailLogin: (request: { email: string; verificationCode: string }) => Promise<OperationResult<LoginResponse>>; emailLogin: (request: { email: string; verificationCode: string }) => Promise<OperationResult<LoginResponse>>;
@ -27,243 +20,181 @@ export interface ApiService {
sendVerificationCode: (request: { email: string; captchaId: string; captchaCode: string }) => Promise<OperationResult<void>>; sendVerificationCode: (request: { email: string; captchaId: string; captchaCode: string }) => Promise<OperationResult<void>>;
} }
class ApiError extends Error {
constructor(message: string, public statusCode?: number) {
super(message);
this.name = 'ApiError';
}
}
export const apiService: ApiService = { export const apiService: ApiService = {
login: async (request: LoginRequest): Promise<OperationResult<LoginResponse>> => { login: async (request: LoginRequest): Promise<OperationResult<LoginResponse>> => {
try { try {
const response = await httpClient.post<ApiResponse<LoginResponse>>('/auth/login', request); const result = await httpClient.post<LoginResponse>('/auth/login', request);
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('登录业务操作失败:', getErrorMessage(result));
success: true,
data: response.data,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.LOGIN_SUCCESS
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED],
data: null,
isSuccess: false
}; };
} }
}, },
emailLogin: async (request: { email: string; verificationCode: string }): Promise<OperationResult<LoginResponse>> => { emailLogin: async (request: { email: string; verificationCode: string }): Promise<OperationResult<LoginResponse>> => {
try { try {
const response = await httpClient.post<ApiResponse<LoginResponse>>('/auth/email', request); const result = await httpClient.post<LoginResponse>('/auth/email', request);
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('邮箱登录业务操作失败:', getErrorMessage(result));
success: true,
data: response.data,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.LOGIN_SUCCESS
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED],
data: null,
isSuccess: false
}; };
} }
}, },
register: async (request: RegisterRequest): Promise<OperationResult<void>> => { register: async (request: RegisterRequest): Promise<OperationResult<void>> => {
try { try {
const response = await httpClient.post<ApiResponse<void>>('/auth/register', request); const result = await httpClient.post<void>('/auth/register', request);
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('注册业务操作失败:', getErrorMessage(result));
success: true,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.REGISTER_SUCCESS
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.REGISTER_FAILED
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.REGISTER_FAILED errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.REGISTER_FAILED],
data: null,
isSuccess: false
}; };
} }
}, },
refreshToken: async (refreshToken: string): Promise<OperationResult<LoginResponse>> => { refreshToken: async (refreshToken: string): Promise<OperationResult<LoginResponse>> => {
try { try {
const response = await httpClient.post<ApiResponse<LoginResponse>>('/auth/refresh-token', { refreshToken }); const result = await httpClient.post<LoginResponse>('/auth/refresh-token', { refreshToken });
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('刷新令牌业务操作失败:', getErrorMessage(result));
success: true,
data: response.data,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.TOKEN_REFRESHED
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.TOKEN_REFRESH_FAILED
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.TOKEN_REFRESH_FAILED errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.TOKEN_REFRESH_FAILED],
data: null,
isSuccess: false
}; };
} }
}, },
logout: async (): Promise<OperationResult<void>> => { logout: async (): Promise<OperationResult<void>> => {
try { try {
const response = await httpClient.post<ApiResponse<void>>('/auth/logout'); const result = await httpClient.post<void>('/auth/logout');
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('登出业务操作失败:', getErrorMessage(result));
success: true,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.LOGOUT_SUCCESS
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.LOGOUT_FAILED
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGOUT_FAILED errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGOUT_FAILED],
data: null,
isSuccess: false
}; };
} }
}, },
getCurrentUser: async (): Promise<OperationResult<User>> => { getCurrentUser: async (): Promise<OperationResult<User>> => {
try { try {
const response = await httpClient.get<ApiResponse<User>>('/users/current'); const result = await httpClient.get<User>('/users/current');
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('获取当前用户业务操作失败:', getErrorMessage(result));
success: true,
data: response.data,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.USER_FETCHED
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.USER_FETCH_FAILED
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.USER_FETCH_FAILED errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.USER_INFO_FAILED],
data: null,
isSuccess: false
}; };
} }
}, },
getCaptcha: async (): Promise<OperationResult<CaptchaResponse>> => { getCaptcha: async (): Promise<OperationResult<CaptchaResponse>> => {
try { try {
const response = await httpClient.get<ApiResponse<CaptchaResponse>>('/auth/captcha'); const result = await httpClient.get<CaptchaResponse>('/auth/captcha');
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('获取验证码业务操作失败:', getErrorMessage(result));
success: true,
data: response.data,
message: response.successMessage || '验证码获取成功'
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || '验证码获取失败'
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || '验证码获取失败' errorMessages: [error.response?.data?.message || '验证码获取失败'],
data: null,
isSuccess: false
}; };
} }
}, },
sendResetPasswordEmail: async (email: string, captchaId: string, captchaCode: string): Promise<OperationResult<void>> => { sendResetPasswordEmail: async (email: string, captchaId: string, captchaCode: string): Promise<OperationResult<void>> => {
try { try {
const response = await httpClient.post<ApiResponse<void>>('/auth/reset-password/email', { const result = await httpClient.post<void>('/auth/reset-password/email', {
email: `${email}@qq.com`, email: `${email}@qq.com`,
captchaId, captchaId,
captchaCode captchaCode
}); });
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('发送重置密码邮件业务操作失败:', getErrorMessage(result));
success: true,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.RESET_PASSWORD_EMAIL_SENT
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.RESET_PASSWORD_EMAIL_FAILED
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.RESET_PASSWORD_EMAIL_FAILED errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.RESET_PASSWORD_EMAIL_FAILED],
data: null,
isSuccess: false
}; };
} }
}, },
resetPassword: async (email: string, verificationCode: string, newPassword: string): Promise<OperationResult<void>> => { resetPassword: async (email: string, verificationCode: string, newPassword: string): Promise<OperationResult<void>> => {
try { try {
const response = await httpClient.post<ApiResponse<void>>('/auth/reset-password', { const result = await httpClient.post<void>('/auth/reset-password', {
email: `${email}@qq.com`, email: `${email}@qq.com`,
verificationCode, verificationCode,
newPassword newPassword
}); });
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('重置密码业务操作失败:', getErrorMessage(result));
success: true,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.PASSWORD_RESET_SUCCESS
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.PASSWORD_RESET_FAILED
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.PASSWORD_RESET_FAILED errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.PASSWORD_RESET_FAILED],
data: null,
isSuccess: false
}; };
} }
}, },
sendVerificationCode: async (request: { email: string; captchaId: string; captchaCode: string }): Promise<OperationResult<void>> => { sendVerificationCode: async (request: { email: string; captchaId: string; captchaCode: string }): Promise<OperationResult<void>> => {
try { try {
const response = await httpClient.post<ApiResponse<void>>('/auth/verification-codes', request); const result = await httpClient.post<void>('/auth/verification-codes', request);
if (response.isSuccess) { if (!result.isSuccess) {
return { console.warn('发送验证码业务操作失败:', getErrorMessage(result));
success: true,
message: response.successMessage || '验证码发送成功'
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || '验证码发送失败'
};
} }
return result;
} catch (error: any) { } catch (error: any) {
return { return {
success: false, successMessage: null,
message: error.response?.data?.message || '验证码发送失败' errorMessages: [error.response?.data?.message || '验证码发送失败'],
data: null,
isSuccess: false
}; };
} }
} }

31
src/X1.WebUI/src/services/authService.ts

@ -2,6 +2,7 @@ import { LoginRequest, RegisterRequest, User, OperationResult, AuthAction } from
import { storageService } from './storageService'; import { storageService } from './storageService';
import { apiService } from '@/services/apiService'; import { apiService } from '@/services/apiService';
import { AUTH_CONSTANTS } from '@/constants/auth'; import { AUTH_CONSTANTS } from '@/constants/auth';
import { getErrorMessage } from '@/types/auth';
export interface AuthService { export interface AuthService {
isTokenExpired: () => boolean; isTokenExpired: () => boolean;
@ -70,9 +71,11 @@ export const authService: AuthService = {
} }
console.log('[authService] login result', result); console.log('[authService] login result', result);
if (!result.success) {
throw new AuthError(result.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED); if (!result.isSuccess) {
throw new AuthError(getErrorMessage(result));
} }
const { accessToken, refreshToken, user } = result.data!; const { accessToken, refreshToken, user } = result.data!;
const expiryTime = Date.now() + AUTH_CONSTANTS.AUTH_CONFIG.TOKEN_EXPIRY_TIME; const expiryTime = Date.now() + AUTH_CONSTANTS.AUTH_CONFIG.TOKEN_EXPIRY_TIME;
storageService.setAccessToken(accessToken); storageService.setAccessToken(accessToken);
@ -100,9 +103,11 @@ export const authService: AuthService = {
dispatch({ type: 'REGISTER_START' }); dispatch({ type: 'REGISTER_START' });
const result = await apiService.register(request); const result = await apiService.register(request);
console.log('[authService] register result', result); console.log('[authService] register result', result);
if (!result.success) {
throw new AuthError(result.message || AUTH_CONSTANTS.MESSAGES.REGISTER_FAILED); if (!result.isSuccess) {
throw new AuthError(getErrorMessage(result));
} }
dispatch({ type: 'REGISTER_SUCCESS' }); dispatch({ type: 'REGISTER_SUCCESS' });
} catch (error: any) { } catch (error: any) {
console.error('[authService] handleRegister error', error); console.error('[authService] handleRegister error', error);
@ -119,9 +124,11 @@ export const authService: AuthService = {
console.log('[authService] handleLogout start'); console.log('[authService] handleLogout start');
const result = await apiService.logout(); const result = await apiService.logout();
console.log('[authService] logout result', result); console.log('[authService] logout result', result);
if (!result.success) {
throw new AuthError(result.message || AUTH_CONSTANTS.MESSAGES.LOGOUT_FAILED); if (!result.isSuccess) {
throw new AuthError(getErrorMessage(result));
} }
storageService.clearAuth(); storageService.clearAuth();
console.log('[authService] tokens cleared'); console.log('[authService] tokens cleared');
dispatch({ type: 'LOGOUT' }); dispatch({ type: 'LOGOUT' });
@ -144,9 +151,11 @@ export const authService: AuthService = {
} }
const result = await apiService.refreshToken(refreshToken); const result = await apiService.refreshToken(refreshToken);
console.log('[authService] refreshToken result', result); console.log('[authService] refreshToken result', result);
if (!result.success || !result.data) {
throw new AuthError(result.message || AUTH_CONSTANTS.MESSAGES.TOKEN_REFRESH_FAILED); if (!result.isSuccess || !result.data) {
throw new AuthError(getErrorMessage(result));
} }
const { accessToken, refreshToken: newRefreshToken, user } = result.data; const { accessToken, refreshToken: newRefreshToken, user } = result.data;
const expiryTime = Date.now() + AUTH_CONSTANTS.AUTH_CONFIG.TOKEN_EXPIRY_TIME; const expiryTime = Date.now() + AUTH_CONSTANTS.AUTH_CONFIG.TOKEN_EXPIRY_TIME;
storageService.setAccessToken(accessToken); storageService.setAccessToken(accessToken);
@ -204,13 +213,13 @@ export const authService: AuthService = {
console.log('[authService] 开始获取当前用户信息'); console.log('[authService] 开始获取当前用户信息');
const result = await apiService.getCurrentUser(); const result = await apiService.getCurrentUser();
console.log('[authService] getCurrentUser 结果', { console.log('[authService] getCurrentUser 结果', {
success: result.success, isSuccess: result.isSuccess,
message: result.message, errorMessage: getErrorMessage(result),
hasData: !!result.data, hasData: !!result.data,
data: result.data data: result.data
}); });
if (!result.success || !result.data) { if (!result.isSuccess || !result.data) {
console.log('[authService] 获取用户信息失败,返回初始状态'); console.log('[authService] 获取用户信息失败,返回初始状态');
dispatch({ type: 'LOGOUT' }); dispatch({ type: 'LOGOUT' });
return; return;

18
src/X1.WebUI/src/types/auth.ts

@ -58,8 +58,16 @@ export interface AuthContextType extends AuthState {
} }
export interface OperationResult<T = void> { export interface OperationResult<T = void> {
success: boolean; successMessage: string | null;
data?: T; errorMessages: string[] | null;
message?: string; data: T | null;
errorMessages?: string[]; isSuccess: boolean;
} }
export const getSuccessMessage = (result: OperationResult<any>): string => {
return result.successMessage || '操作成功';
};
export const getErrorMessage = (result: OperationResult<any>): string => {
return result.errorMessages?.join(', ') || '操作失败';
};
Loading…
Cancel
Save