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>
public bool IsSuccess => ErrorMessages == null || !ErrorMessages.Any();
/// <summary>
/// 获取成功消息(如果为空则返回默认消息)
/// </summary>
public string GetSuccessMessage() => SuccessMessage ?? "操作成功";
/// <summary>
/// 创建成功结果(仅包含数据)
/// </summary>
@ -35,7 +40,7 @@ public sealed record OperationResult<T>(
/// <returns>成功结果</returns>
public static OperationResult<T> CreateSuccess(T data)
{
return new OperationResult<T>(null, null, data);
return new OperationResult<T>("操作成功", null, data);
}
/// <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.Status400BadRequest)]
[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
{
@ -92,8 +92,7 @@ public class AuthController : ApiController
if (attempts >= _authConfig.MaxLoginAttempts)
{
_logger.LogWarning("账号 {UserName} 登录尝试次数过多", command.UserName);
return StatusCode(StatusCodes.Status429TooManyRequests,
OperationResult<AuthenticateUserResponse>.CreateFailure("登录尝试次数过多,请稍后再试"));
return OperationResult<AuthenticateUserResponse>.CreateFailure("登录尝试次数过多,请稍后再试");
}
// 执行登录
@ -123,13 +122,12 @@ public class AuthController : ApiController
_logger.LogWarning($"Bearer {result.Data.AccessToken}");
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "账号 {UserName} 登录时发生异常", command.UserName);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -156,10 +154,10 @@ public class AuthController : ApiController
/// <response code="400">登录失败,返回错误信息</response>
/// <response code="429">登录尝试次数过多</response>
[HttpPost("email")]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status429TooManyRequests)]
public async Task<ActionResult<OperationResult<AuthenticateUserResponse>>> LoginWithEmail([FromBody] EmailLoginCommand command)
[ProducesResponseType(typeof(OperationResult<EmailLoginResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<EmailLoginResponse>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<EmailLoginResponse>), StatusCodes.Status429TooManyRequests)]
public async Task<OperationResult<EmailLoginResponse>> LoginWithEmail([FromBody] EmailLoginCommand command)
{
try
{
@ -170,8 +168,7 @@ public class AuthController : ApiController
if (attempts >= _authConfig.MaxLoginAttempts)
{
_logger.LogWarning("邮箱 {Email} 登录尝试次数过多", command.Email);
return StatusCode(StatusCodes.Status429TooManyRequests,
OperationResult<AuthenticateUserResponse>.CreateFailure("登录尝试次数过多,请稍后再试"));
return OperationResult<EmailLoginResponse>.CreateFailure("登录尝试次数过多,请稍后再试");
}
// 执行登录
@ -201,13 +198,12 @@ public class AuthController : ApiController
_logger.LogWarning($"Bearer {result.Data.AccessToken}");
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "邮箱 {Email} 登录时发生异常", command.Email);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<EmailLoginResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -238,7 +234,7 @@ public class AuthController : ApiController
[HttpPost("register")]
[ProducesResponseType(typeof(OperationResult<RegisterUserResponse>), StatusCodes.Status200OK)]
[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
{
@ -256,13 +252,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "用户 {UserName} 注册时发生异常", command.UserName);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<RegisterUserResponse>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<RegisterUserResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -289,7 +284,7 @@ public class AuthController : ApiController
[HttpPost("refresh-token")]
[ProducesResponseType(typeof(OperationResult<AuthenticateUserResponse>), StatusCodes.Status200OK)]
[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
{
@ -305,13 +300,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "刷新令牌时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<AuthenticateUserResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -338,7 +332,7 @@ public class AuthController : ApiController
[HttpPost("verification-codes")]
[ProducesResponseType(typeof(OperationResult<SendVerificationCodeResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<SendVerificationCodeResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<SendVerificationCodeResponse>>> SendVerificationCode(
public async Task<OperationResult<SendVerificationCodeResponse>> SendVerificationCode(
[FromBody] SendVerificationCodeCommand command)
{
try
@ -357,13 +351,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "向邮箱 {Email} 发送验证码时发生异常", command.Email);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<SendVerificationCodeResponse>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<SendVerificationCodeResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -391,7 +384,7 @@ public class AuthController : ApiController
[HttpPost("verification-codes/verify")]
[ProducesResponseType(typeof(OperationResult<VerifyCodeResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<VerifyCodeResponse>), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OperationResult<VerifyCodeResponse>>> VerifyCode(
public async Task<OperationResult<VerifyCodeResponse>> VerifyCode(
[FromBody] VerifyCodeCommand command)
{
try
@ -410,13 +403,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "验证邮箱 {Email} 的验证码时发生异常", command.Email);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<VerifyCodeResponse>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<VerifyCodeResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -432,7 +424,7 @@ public class AuthController : ApiController
[HttpGet("captcha")]
[ProducesResponseType(typeof(OperationResult<GenerateCaptchaResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<GenerateCaptchaResponse>), StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<OperationResult<GenerateCaptchaResponse>>> GetCaptcha()
public async Task<OperationResult<GenerateCaptchaResponse>> GetCaptcha()
{
try
{
@ -455,13 +447,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "生成图形验证码时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<GenerateCaptchaResponse>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<GenerateCaptchaResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -488,7 +479,7 @@ public class AuthController : ApiController
[HttpPost("logout")]
[ProducesResponseType(typeof(OperationResult<bool>), StatusCodes.Status200OK)]
[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
{
@ -504,13 +495,12 @@ public class AuthController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "用户登出时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<bool>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<bool>.CreateFailure("系统错误,请稍后重试");
}
}
}

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

@ -38,7 +38,7 @@ namespace CellularManagement.Presentation.Controllers
/// 获取设备列表
/// </summary>
[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}",
query.PageNumber, query.PageSize, query.SearchTerm);
@ -47,18 +47,18 @@ namespace CellularManagement.Presentation.Controllers
if (!result.IsSuccess)
{
_logger.LogWarning("获取设备列表失败: {Message}", result.ErrorMessages);
return BadRequest(result);
return result;
}
_logger.LogInformation("成功获取设备列表,共 {Count} 条记录", result.Data?.TotalCount ?? 0);
return Ok(result);
return result;
}
/// <summary>
/// 获取设备详情
/// </summary>
[HttpGet("{id}")]
public async Task<ActionResult<OperationResult<GetDeviceByIdResponse>>> GetById(string id)
public async Task<OperationResult<GetDeviceByIdResponse>> GetById(string id)
{
_logger.LogInformation("开始获取设备详情,设备ID: {DeviceId}", id);
@ -66,18 +66,18 @@ namespace CellularManagement.Presentation.Controllers
if (!result.IsSuccess)
{
_logger.LogWarning("获取设备详情失败: {Message}", result.ErrorMessages);
return NotFound(result);
return result;
}
_logger.LogInformation("成功获取设备详情,设备ID: {DeviceId}", id);
return Ok(result);
return result;
}
/// <summary>
/// 创建设备
/// </summary>
[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);
@ -85,46 +85,43 @@ namespace CellularManagement.Presentation.Controllers
if (!result.IsSuccess)
{
_logger.LogWarning("创建设备失败: {Message}", result.ErrorMessages);
return BadRequest(result);
return result;
}
_logger.LogInformation("成功创建设备,设备ID: {DeviceId}", result.Data.DeviceId);
return CreatedAtAction(
nameof(GetById),
new { id = result.Data.DeviceId },
result);
return result;
}
/// <summary>
/// 更新设备
/// </summary>
[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);
if (id != command.DeviceId)
{
_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);
if (!result.IsSuccess)
{
_logger.LogWarning("更新设备失败: {Message}", result.ErrorMessages);
return NotFound(result);
return result;
}
_logger.LogInformation("成功更新设备,设备ID: {DeviceId}", id);
return Ok(result);
return result;
}
/// <summary>
/// 删除设备
/// </summary>
[HttpDelete("{id}")]
public async Task<ActionResult<OperationResult<bool>>> Delete(string id)
public async Task<OperationResult<bool>> Delete(string id)
{
_logger.LogInformation("开始删除设备,设备ID: {DeviceId}", id);
@ -132,11 +129,11 @@ namespace CellularManagement.Presentation.Controllers
if (!result.IsSuccess)
{
_logger.LogWarning("删除设备失败: {Message}", result.ErrorMessages);
return NotFound(result);
return result;
}
_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]
[ProducesResponseType(typeof(OperationResult<CreatePermissionResponse>), StatusCodes.Status200OK)]
[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
{
@ -74,13 +74,12 @@ public class PermissionsController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "创建权限 {PermissionName} 时发生异常", command.Name);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<CreatePermissionResponse>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<CreatePermissionResponse>.CreateFailure("系统错误,请稍后重试");
}
}
}

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

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

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

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

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

@ -64,7 +64,7 @@ public class UsersController : ApiController
[HttpPost]
[ProducesResponseType(typeof(OperationResult<CreateUserResponse>), StatusCodes.Status201Created)]
[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
{
@ -73,20 +73,19 @@ public class UsersController : ApiController
if (result.IsSuccess)
{
_logger.LogInformation("创建用户成功,用户ID: {UserId}", result.Data?.UserId);
return CreatedAtAction(nameof(GetUserById), new { id = result.Data?.UserId }, result);
}
else
{
_logger.LogWarning("创建用户失败: {Error}",
result.ErrorMessages?.FirstOrDefault());
return BadRequest(result);
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "创建用户时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<CreateUserResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -117,7 +116,7 @@ public class UsersController : ApiController
[HttpGet]
[ProducesResponseType(typeof(OperationResult<GetAllUsersResponse>), StatusCodes.Status200OK)]
[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
{
@ -135,13 +134,12 @@ public class UsersController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "获取用户列表时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<GetAllUsersResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -167,7 +165,7 @@ public class UsersController : ApiController
[ProducesResponseType(typeof(OperationResult<GetUserByIdResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)]
[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
{
@ -185,13 +183,12 @@ public class UsersController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "获取用户 {UserId} 信息时发生异常", id);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<GetUserByIdResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -223,13 +220,18 @@ public class UsersController : ApiController
[ProducesResponseType(typeof(OperationResult<UpdateUserResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<UpdateUserResponse>>> UpdateUser(
public async Task<OperationResult<UpdateUserResponse>> UpdateUser(
[FromRoute] string id,
[FromBody] UpdateUserCommand command)
{
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);
if (result.IsSuccess)
@ -243,13 +245,12 @@ public class UsersController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "更新用户 {UserId} 信息时发生异常", id);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<UpdateUserResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -272,10 +273,10 @@ public class UsersController : ApiController
/// <response code="400">删除失败,返回错误信息</response>
/// <response code="404">用户不存在</response>
[HttpDelete("{id}")]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<object>>> DeleteUser([FromRoute] string id)
[ProducesResponseType(typeof(OperationResult<DeleteUserResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<DeleteUserResponse>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(OperationResult<DeleteUserResponse>), StatusCodes.Status404NotFound)]
public async Task<OperationResult<DeleteUserResponse>> DeleteUser([FromRoute] string id)
{
try
{
@ -293,13 +294,12 @@ public class UsersController : ApiController
result.ErrorMessages?.FirstOrDefault());
}
return Ok(result);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "删除用户 {UserId} 时发生异常", id);
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<DeleteUserResponse>.CreateFailure("系统错误,请稍后重试");
}
}
@ -324,15 +324,15 @@ public class UsersController : ApiController
[ProducesResponseType(typeof(OperationResult<GetUserByIdResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(OperationResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<OperationResult<GetUserByIdResponse>>> CurrentUser()
public async Task<OperationResult<GetUserByIdResponse>> CurrentUser()
{
try
{
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
var userId = User.FindFirst("sub")?.Value;
if (string.IsNullOrEmpty(userId))
{
_logger.LogWarning("获取当前用户信息失败:未找到用户ID");
return Unauthorized(OperationResult<object>.CreateFailure("未授权,请先登录"));
_logger.LogWarning("无法获取当前用户ID");
return OperationResult<GetUserByIdResponse>.CreateFailure("无法获取当前用户信息");
}
var query = new GetUserByIdQuery(userId);
@ -340,21 +340,20 @@ public class UsersController : ApiController
if (result.IsSuccess)
{
_logger.LogInformation("获取当前用户信息成功,用户ID: {UserId}", userId);
return Ok(result);
_logger.LogInformation("获取当前用户信息成功");
}
else
{
_logger.LogWarning("获取当前用户信息失败: {Error}",
result.ErrorMessages?.FirstOrDefault());
return NotFound(result);
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "获取当前用户信息时发生异常");
return StatusCode(StatusCodes.Status500InternalServerError,
OperationResult<object>.CreateFailure("系统错误,请稍后重试"));
return OperationResult<GetUserByIdResponse>.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 { apiService } from '@/services/apiService';
import { toast } from '@/components/ui/use-toast';
import { getErrorMessage } from '@/types/auth';
interface LoginFormProps {
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 {
setCaptchaAvailable(false);
const result = await apiService.getCaptcha();
if (result.success && result.data) {
// 业务逻辑判断
if (result.isSuccess && result.data) {
setCaptchaImage(result.data.imageBase64);
setCaptchaId(result.data.captchaId);
setCaptchaAvailable(true);
console.log('验证码获取成功:', result.successMessage);
} else {
// 业务操作失败
setCaptchaImage('');
setCaptchaId('');
setCaptchaAvailable(false);
const errorMessage = getErrorMessage(result);
console.warn('验证码获取业务操作失败:', errorMessage);
toast({
title: '获取验证码失败',
description: result.message || '请点击验证码图片重试',
description: errorMessage || '请点击验证码图片重试',
variant: 'destructive',
duration: 3000,
});
}
} catch (error) {
// HTTP 错误处理
setCaptchaImage('');
setCaptchaId('');
setCaptchaAvailable(false);
console.error('验证码获取HTTP错误:', error);
toast({
title: '获取验证码失败',
description: '请点击验证码图片重试',
description: '网络错误,请点击验证码图片重试',
variant: 'destructive',
duration: 3000,
});
@ -123,31 +132,37 @@ export function LoginForm({ onSubmit }: LoginFormProps) {
}
try {
const response = await apiService.sendVerificationCode({
const result = await apiService.sendVerificationCode({
email: `${email}@qq.com`,
captchaId,
captchaCode
});
if (response.success) {
// 业务逻辑判断
if (result.isSuccess) {
setCountdown(120); // 设置120秒倒计时
toast({
title: '验证码已发送',
description: '请查收您的QQ邮箱',
description: result.successMessage || '请查收您的QQ邮箱',
duration: 3000,
});
} else {
// 业务操作失败
const errorMessage = getErrorMessage(result);
console.warn('发送验证码业务操作失败:', errorMessage);
toast({
title: '发送失败',
description: response.message || '请稍后重试',
description: errorMessage || '请稍后重试',
variant: 'destructive',
duration: 3000,
});
}
} catch (error) {
// HTTP 错误处理
console.error('发送验证码HTTP错误:', error);
toast({
title: '发送失败',
description: '请稍后重试',
description: '网络错误,请稍后重试',
variant: 'destructive',
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 { toast } from '@/components/ui/use-toast';
import { apiService } from '@/services/apiService';
import { getErrorMessage } from '@/types/auth';
// 定义表单验证规则
const registerSchema = z.object({
@ -70,40 +71,53 @@ export function RegisterForm({ onSubmit }: RegisterFormProps) {
// 获取验证码
const fetchCaptcha = async () => {
console.log('fetchCaptcha 被调用'); // 添加调试日志
try {
setCaptchaAvailable(false);
setCaptchaAvailable(false); // 开始获取时设置为不可用
const result = await apiService.getCaptcha();
if (result.success && result.data) {
// 业务逻辑判断
if (result.isSuccess && result.data) {
setCaptchaImage(result.data.imageBase64);
setCaptchaId(result.data.captchaId);
setCaptchaAvailable(true);
setCaptchaAvailable(true); // 成功时设置为可用
setError(null);
console.log('验证码获取成功:', result.successMessage);
} else {
setCaptchaImage('');
setCaptchaId('');
setCaptchaAvailable(false);
// 业务操作失败 - 保持图片但重置状态
setCaptchaAvailable(false); // 失败时重置为不可用
const errorMessage = getErrorMessage(result);
setError('获取验证码失败,请重试');
console.warn('验证码获取业务操作失败:', errorMessage);
toast({
title: '获取验证码失败',
description: result.message || '请点击验证码图片重试',
description: errorMessage || '请点击验证码图片重试',
variant: 'destructive',
duration: 3000,
});
}
} catch (error) {
setCaptchaImage('');
setCaptchaId('');
setCaptchaAvailable(false);
// HTTP 错误处理 - 保持图片但重置状态
setCaptchaAvailable(false); // 失败时重置为不可用
setError('获取验证码失败,请重试');
console.error('验证码获取HTTP错误:', error);
toast({
title: '获取验证码失败',
description: '请点击验证码图片重试',
description: '网络错误,请点击验证码图片重试',
variant: 'destructive',
duration: 3000,
});
}
};
// 添加专门的点击处理函数
const handleCaptchaClick = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
console.log('验证码图片被点击'); // 添加调试日志
fetchCaptcha();
};
// 组件加载时获取验证码
useEffect(() => {
fetchCaptcha();
@ -424,10 +438,14 @@ export function RegisterForm({ onSubmit }: RegisterFormProps) {
src={`data:image/png;base64,${captchaImage}`}
alt="验证码"
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="点击刷新验证码"
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">
<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>

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

@ -41,7 +41,8 @@ export const AUTH_CONSTANTS = {
RESET_PASSWORD_EMAIL_SENT: '验证码已发送到您的邮箱',
RESET_PASSWORD_EMAIL_FAILED: '验证码发送失败,请稍后重试',
PASSWORD_RESET_SUCCESS: '密码重置成功',
PASSWORD_RESET_FAILED: '密码重置失败,请稍后重试'
PASSWORD_RESET_FAILED: '密码重置失败,请稍后重试',
ACCOUNT_LOCKED: '账号已被锁定,请稍后再试'
}
} 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 { apiService } from '@/services/apiService';
import { toast } from '@/components/ui/use-toast';
import { getErrorMessage } from '@/types/auth';
export function ForgotPasswordPage() {
const navigate = useNavigate();
@ -20,28 +21,36 @@ export function ForgotPasswordPage() {
try {
setCaptchaAvailable(false);
const result = await apiService.getCaptcha();
if (result.success && result.data) {
// 业务逻辑判断:检查业务操作是否成功
if (result.isSuccess && result.data) {
setCaptchaImage(result.data.imageBase64);
setCaptchaId(result.data.captchaId);
setCaptchaAvailable(true);
console.log('验证码获取成功:', result.successMessage);
} else {
// 业务操作失败
setCaptchaImage('');
setCaptchaId('');
setCaptchaAvailable(false);
const errorMessage = getErrorMessage(result);
console.warn('验证码获取业务操作失败:', errorMessage);
toast({
title: '获取验证码失败',
description: result.message || '请点击验证码图片重试',
description: errorMessage || '请点击验证码图片重试',
variant: 'destructive',
duration: 3000,
});
}
} catch (error) {
// HTTP 错误处理
setCaptchaImage('');
setCaptchaId('');
setCaptchaAvailable(false);
console.error('验证码获取HTTP错误:', error);
toast({
title: '获取验证码失败',
description: '请点击验证码图片重试',
description: '网络错误,请点击验证码图片重试',
variant: 'destructive',
duration: 3000,
});
@ -77,24 +86,31 @@ export function ForgotPasswordPage() {
try {
setIsLoading(true);
const result = await apiService.sendResetPasswordEmail(email, captchaId, captchaCode);
if (result.success) {
// 业务逻辑判断
if (result.isSuccess) {
toast({
title: '验证码已发送',
description: '请查收您的邮箱',
description: result.successMessage || '请查收您的邮箱',
duration: 3000,
});
} else {
// 业务操作失败
const errorMessage = getErrorMessage(result);
console.warn('发送验证码业务操作失败:', errorMessage);
toast({
title: '发送失败',
description: result.message || '请稍后重试',
description: errorMessage || '请稍后重试',
variant: 'destructive',
duration: 3000,
});
}
} catch (error) {
// HTTP 错误处理
console.error('发送验证码HTTP错误:', error);
toast({
title: '发送失败',
description: '请稍后重试',
description: '网络错误,请稍后重试',
variant: 'destructive',
duration: 3000,
});
@ -129,25 +145,32 @@ export function ForgotPasswordPage() {
try {
setIsLoading(true);
const result = await apiService.resetPassword(email, verificationCode, newPassword);
if (result.success) {
// 业务逻辑判断
if (result.isSuccess) {
toast({
title: '密码重置成功',
description: '请使用新密码登录',
description: result.successMessage || '请使用新密码登录',
duration: 3000,
});
navigate('/login');
} else {
// 业务操作失败
const errorMessage = getErrorMessage(result);
console.warn('密码重置业务操作失败:', errorMessage);
toast({
title: '重置失败',
description: result.message || '请稍后重试',
description: errorMessage || '请稍后重试',
variant: 'destructive',
duration: 3000,
});
}
} catch (error) {
// HTTP 错误处理
console.error('密码重置HTTP错误:', error);
toast({
title: '重置失败',
description: '请稍后重试',
description: '网络错误,请稍后重试',
variant: 'destructive',
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 { AUTH_CONSTANTS } from '@/constants/auth';
@ -7,13 +7,6 @@ interface CaptchaResponse {
imageBase64: string;
}
interface ApiResponse<T> {
successMessage: string | null;
errorMessages: string[] | null;
data: T;
isSuccess: boolean;
}
export interface ApiService {
login: (request: LoginRequest) => 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>>;
}
class ApiError extends Error {
constructor(message: string, public statusCode?: number) {
super(message);
this.name = 'ApiError';
}
}
export const apiService: ApiService = {
login: async (request: LoginRequest): Promise<OperationResult<LoginResponse>> => {
try {
const response = await httpClient.post<ApiResponse<LoginResponse>>('/auth/login', request);
if (response.isSuccess) {
return {
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
};
const result = await httpClient.post<LoginResponse>('/auth/login', request);
if (!result.isSuccess) {
console.warn('登录业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED
successMessage: null,
errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED],
data: null,
isSuccess: false
};
}
},
emailLogin: async (request: { email: string; verificationCode: string }): Promise<OperationResult<LoginResponse>> => {
try {
const response = await httpClient.post<ApiResponse<LoginResponse>>('/auth/email', request);
if (response.isSuccess) {
return {
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
};
const result = await httpClient.post<LoginResponse>('/auth/email', request);
if (!result.isSuccess) {
console.warn('邮箱登录业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED
successMessage: null,
errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGIN_FAILED],
data: null,
isSuccess: false
};
}
},
register: async (request: RegisterRequest): Promise<OperationResult<void>> => {
try {
const response = await httpClient.post<ApiResponse<void>>('/auth/register', request);
if (response.isSuccess) {
return {
success: true,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.REGISTER_SUCCESS
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.REGISTER_FAILED
};
const result = await httpClient.post<void>('/auth/register', request);
if (!result.isSuccess) {
console.warn('注册业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.REGISTER_FAILED
successMessage: null,
errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.REGISTER_FAILED],
data: null,
isSuccess: false
};
}
},
refreshToken: async (refreshToken: string): Promise<OperationResult<LoginResponse>> => {
try {
const response = await httpClient.post<ApiResponse<LoginResponse>>('/auth/refresh-token', { refreshToken });
if (response.isSuccess) {
return {
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
};
const result = await httpClient.post<LoginResponse>('/auth/refresh-token', { refreshToken });
if (!result.isSuccess) {
console.warn('刷新令牌业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.TOKEN_REFRESH_FAILED
successMessage: null,
errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.TOKEN_REFRESH_FAILED],
data: null,
isSuccess: false
};
}
},
logout: async (): Promise<OperationResult<void>> => {
try {
const response = await httpClient.post<ApiResponse<void>>('/auth/logout');
if (response.isSuccess) {
return {
success: true,
message: response.successMessage || AUTH_CONSTANTS.MESSAGES.LOGOUT_SUCCESS
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || AUTH_CONSTANTS.MESSAGES.LOGOUT_FAILED
};
const result = await httpClient.post<void>('/auth/logout');
if (!result.isSuccess) {
console.warn('登出业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGOUT_FAILED
successMessage: null,
errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.LOGOUT_FAILED],
data: null,
isSuccess: false
};
}
},
getCurrentUser: async (): Promise<OperationResult<User>> => {
try {
const response = await httpClient.get<ApiResponse<User>>('/users/current');
if (response.isSuccess) {
return {
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
};
const result = await httpClient.get<User>('/users/current');
if (!result.isSuccess) {
console.warn('获取当前用户业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.USER_FETCH_FAILED
successMessage: null,
errorMessages: [error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.USER_INFO_FAILED],
data: null,
isSuccess: false
};
}
},
getCaptcha: async (): Promise<OperationResult<CaptchaResponse>> => {
try {
const response = await httpClient.get<ApiResponse<CaptchaResponse>>('/auth/captcha');
if (response.isSuccess) {
return {
success: true,
data: response.data,
message: response.successMessage || '验证码获取成功'
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || '验证码获取失败'
};
const result = await httpClient.get<CaptchaResponse>('/auth/captcha');
if (!result.isSuccess) {
console.warn('获取验证码业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || '验证码获取失败'
successMessage: null,
errorMessages: [error.response?.data?.message || '验证码获取失败'],
data: null,
isSuccess: false
};
}
},
sendResetPasswordEmail: async (email: string, captchaId: string, captchaCode: string): Promise<OperationResult<void>> => {
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`,
captchaId,
captchaCode
});
if (response.isSuccess) {
return {
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
};
if (!result.isSuccess) {
console.warn('发送重置密码邮件业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.RESET_PASSWORD_EMAIL_FAILED
successMessage: null,
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>> => {
try {
const response = await httpClient.post<ApiResponse<void>>('/auth/reset-password', {
const result = await httpClient.post<void>('/auth/reset-password', {
email: `${email}@qq.com`,
verificationCode,
newPassword
});
if (response.isSuccess) {
return {
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
};
if (!result.isSuccess) {
console.warn('重置密码业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || AUTH_CONSTANTS.MESSAGES.PASSWORD_RESET_FAILED
successMessage: null,
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>> => {
try {
const response = await httpClient.post<ApiResponse<void>>('/auth/verification-codes', request);
if (response.isSuccess) {
return {
success: true,
message: response.successMessage || '验证码发送成功'
};
} else {
return {
success: false,
message: response?.errorMessages?.join(', ') || '验证码发送失败'
};
const result = await httpClient.post<void>('/auth/verification-codes', request);
if (!result.isSuccess) {
console.warn('发送验证码业务操作失败:', getErrorMessage(result));
}
return result;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || '验证码发送失败'
successMessage: null,
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 { apiService } from '@/services/apiService';
import { AUTH_CONSTANTS } from '@/constants/auth';
import { getErrorMessage } from '@/types/auth';
export interface AuthService {
isTokenExpired: () => boolean;
@ -70,9 +71,11 @@ export const authService: AuthService = {
}
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 expiryTime = Date.now() + AUTH_CONSTANTS.AUTH_CONFIG.TOKEN_EXPIRY_TIME;
storageService.setAccessToken(accessToken);
@ -100,9 +103,11 @@ export const authService: AuthService = {
dispatch({ type: 'REGISTER_START' });
const result = await apiService.register(request);
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' });
} catch (error: any) {
console.error('[authService] handleRegister error', error);
@ -119,9 +124,11 @@ export const authService: AuthService = {
console.log('[authService] handleLogout start');
const result = await apiService.logout();
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();
console.log('[authService] tokens cleared');
dispatch({ type: 'LOGOUT' });
@ -144,9 +151,11 @@ export const authService: AuthService = {
}
const result = await apiService.refreshToken(refreshToken);
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 expiryTime = Date.now() + AUTH_CONSTANTS.AUTH_CONFIG.TOKEN_EXPIRY_TIME;
storageService.setAccessToken(accessToken);
@ -204,13 +213,13 @@ export const authService: AuthService = {
console.log('[authService] 开始获取当前用户信息');
const result = await apiService.getCurrentUser();
console.log('[authService] getCurrentUser 结果', {
success: result.success,
message: result.message,
isSuccess: result.isSuccess,
errorMessage: getErrorMessage(result),
hasData: !!result.data,
data: result.data
});
if (!result.success || !result.data) {
if (!result.isSuccess || !result.data) {
console.log('[authService] 获取用户信息失败,返回初始状态');
dispatch({ type: 'LOGOUT' });
return;

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

@ -58,8 +58,16 @@ export interface AuthContextType extends AuthState {
}
export interface OperationResult<T = void> {
success: boolean;
data?: T;
message?: string;
errorMessages?: string[];
}
successMessage: string | null;
errorMessages: string[] | null;
data: T | null;
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