diff --git a/backend/IM_API/Configs/ServiceCollectionExtensions.cs b/backend/IM_API/Configs/ServiceCollectionExtensions.cs index f811e2e..20a931d 100644 --- a/backend/IM_API/Configs/ServiceCollectionExtensions.cs +++ b/backend/IM_API/Configs/ServiceCollectionExtensions.cs @@ -1,5 +1,9 @@ -using IM_API.Interface.Services; +using IM_API.Dtos; +using IM_API.Interface.Services; using IM_API.Services; +using IM_API.Tools; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; namespace IM_API.Configs { @@ -7,6 +11,7 @@ namespace IM_API.Configs { public static IServiceCollection AddAllService(this IServiceCollection services, IConfiguration configuration) { + services.AddAutoMapper(typeof(MapperConfig)); services.AddTransient(); services.AddTransient(); @@ -14,8 +19,28 @@ namespace IM_API.Configs services.AddTransient(); services.AddTransient(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); return services; } - } + public static IServiceCollection AddModelValidation(this IServiceCollection services, IConfiguration configuration) + { + services.Configure(options => + { + options.InvalidModelStateResponseFactory = context => + { + var errors = context.ModelState + .Where(e => e.Value.Errors.Count > 0) + .Select(e => new + { + Field = e.Key, + Message = e.Value.Errors.First().ErrorMessage + }); + + return new BadRequestObjectResult(new BaseResponse(CodeDefine.PARAMETER_ERROR.Code, errors.First().Message)); + }; + }); + return services; + } + + } } diff --git a/backend/IM_API/Controllers/ConversationController.cs b/backend/IM_API/Controllers/ConversationController.cs index 77db965..d04c63b 100644 --- a/backend/IM_API/Controllers/ConversationController.cs +++ b/backend/IM_API/Controllers/ConversationController.cs @@ -28,6 +28,20 @@ namespace IM_API.Controllers var res = new BaseResponse>(list); return Ok(res); } + [HttpPost] + public async Task Clear() + { + var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier); + await _conversationSerivice.ClearConversationsAsync(int.Parse(userIdStr)); + return Ok(new BaseResponse()); + } + [HttpPost] + public async Task Delete(int cid) + { + await _conversationSerivice.DeleteConversationAsync(cid); + return Ok(new BaseResponse()); + } + } } diff --git a/backend/IM_API/Controllers/UserController.cs b/backend/IM_API/Controllers/UserController.cs index cbd7ed9..074a9ca 100644 --- a/backend/IM_API/Controllers/UserController.cs +++ b/backend/IM_API/Controllers/UserController.cs @@ -83,7 +83,7 @@ namespace IM_API.Controllers { var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier); int userId = int.Parse(userIdStr); - await _userService.ResetPasswordAsync(userId,dto.oldPassword,dto.Password); + await _userService.ResetPasswordAsync(userId,dto.OldPassword,dto.Password); return Ok(new BaseResponse()); } /// diff --git a/backend/IM_API/Dtos/FriendDto.cs b/backend/IM_API/Dtos/FriendDto.cs index e21e06f..1a12449 100644 --- a/backend/IM_API/Dtos/FriendDto.cs +++ b/backend/IM_API/Dtos/FriendDto.cs @@ -1,7 +1,31 @@ using IM_API.Models; +using System.ComponentModel.DataAnnotations; namespace IM_API.Dtos { - public record FriendInfoDto(int Id, int UserId,int FriendId,FriendStatus StatusEnum,DateTime Created,string RemarkName,string? Avatar); - public record FriendRequestHandleDto(HandleFriendRequestAction action,string? remarkName); + public record FriendInfoDto + { + public int Id { get; init; } + + public int UserId { get; init; } + + public int FriendId { get; init; } + + public FriendStatus StatusEnum { get; init; } + + public DateTime Created { get; init; } + + public string RemarkName { get; init; } = string.Empty; + + public string? Avatar { get; init; } + } + + public record FriendRequestHandleDto + { + [Required(ErrorMessage = "操作必填")] + public HandleFriendRequestAction Action { get; init; } + + [StringLength(20, ErrorMessage = "备注名最大20个字符")] + public string? RemarkName { get; init; } + } } diff --git a/backend/IM_API/Dtos/FriendRequestDto.cs b/backend/IM_API/Dtos/FriendRequestDto.cs index e9c83da..34460a4 100644 --- a/backend/IM_API/Dtos/FriendRequestDto.cs +++ b/backend/IM_API/Dtos/FriendRequestDto.cs @@ -1,10 +1,15 @@ -namespace IM_API.Dtos +using System.ComponentModel.DataAnnotations; + +namespace IM_API.Dtos { public class FriendRequestDto { public int FromUserId { get; set; } public int ToUserId { get; set; } + [Required(ErrorMessage = "备注名必填")] + [StringLength(20, ErrorMessage = "备注名不能超过20位字符")] public string? RemarkName { get; set; } + [StringLength(50, ErrorMessage = "描述不能超过50字符")] public string? Description { get; set; } } } diff --git a/backend/IM_API/Dtos/LoginRequestDto.cs b/backend/IM_API/Dtos/LoginRequestDto.cs index b1c1b1f..16cd470 100644 --- a/backend/IM_API/Dtos/LoginRequestDto.cs +++ b/backend/IM_API/Dtos/LoginRequestDto.cs @@ -1,8 +1,17 @@ -namespace IM_API.Dtos +using IM_API.Tools; +using System.ComponentModel.DataAnnotations; + +namespace IM_API.Dtos { public class LoginRequestDto { + [Required(ErrorMessage = "用户名不能为空")] + [StringLength(20, ErrorMessage = "用户名不能超过20字符")] + [RegularExpression(@"^[A-Za-z0-9]+$",ErrorMessage = "用户名只能为英文或数字")] public string Username { get; set; } + + [Required(ErrorMessage = "密码不能为空")] + [StringLength(50, ErrorMessage = "密码不能超过50字符")] public string Password { get; set; } } } diff --git a/backend/IM_API/Dtos/RegisterRequestDto.cs b/backend/IM_API/Dtos/RegisterRequestDto.cs index 0bc05e0..83aaea4 100644 --- a/backend/IM_API/Dtos/RegisterRequestDto.cs +++ b/backend/IM_API/Dtos/RegisterRequestDto.cs @@ -1,9 +1,19 @@ -namespace IM_API.Dtos +using System.ComponentModel.DataAnnotations; + +namespace IM_API.Dtos { public class RegisterRequestDto { + [Required(ErrorMessage = "用户名不能为空")] + [MaxLength(20, ErrorMessage = "用户名不能超过20字符")] + [RegularExpression(@"^[A-Za-z0-9]+$", ErrorMessage = "用户名只能为英文或数字")] public string Username { get; set; } + [Required(ErrorMessage = "密码不能为空")] + [MaxLength(50, ErrorMessage = "密码不能超过50字符")] public string Password { get; set; } + [Required(ErrorMessage = "昵称不能为空")] + [MaxLength(20, ErrorMessage = "昵称不能超过20字符")] + public string? NickName { get; set; } } } diff --git a/backend/IM_API/Dtos/UpdateUserDto.cs b/backend/IM_API/Dtos/UpdateUserDto.cs index 86e2560..e7949e7 100644 --- a/backend/IM_API/Dtos/UpdateUserDto.cs +++ b/backend/IM_API/Dtos/UpdateUserDto.cs @@ -1,7 +1,10 @@ -namespace IM_API.Dtos +using System.ComponentModel.DataAnnotations; + +namespace IM_API.Dtos { public class UpdateUserDto { + [MaxLength(20, ErrorMessage = "昵称不能超过50字符")] public string? NickName { get; set; } public string? Avatar { get; set; } diff --git a/backend/IM_API/Dtos/UserDto.cs b/backend/IM_API/Dtos/UserDto.cs index 8d21169..655d1a1 100644 --- a/backend/IM_API/Dtos/UserDto.cs +++ b/backend/IM_API/Dtos/UserDto.cs @@ -1,7 +1,21 @@ using IM_API.Models; +using System.ComponentModel.DataAnnotations; namespace IM_API.Dtos { - public record PasswordResetDto(string oldPassword,string Password); - public record OnlineStatusSetDto(UserOnlineStatus OnlineStatus); + public record PasswordResetDto + { + [Required(ErrorMessage = "旧密码不能为空")] + public string OldPassword { get; init; } + + [Required(ErrorMessage = "新密码不能为空")] + [MaxLength(50, ErrorMessage = "密码不能超过50个字符")] + public string Password { get; init; } + } + + public record OnlineStatusSetDto + { + [Required] + public UserOnlineStatus OnlineStatus { get; init; } + } } diff --git a/backend/IM_API/Program.cs b/backend/IM_API/Program.cs index 954ebbc..9695881 100644 --- a/backend/IM_API/Program.cs +++ b/backend/IM_API/Program.cs @@ -102,6 +102,7 @@ namespace IM_API { options.Filters.Add(); }); + builder.Services.AddModelValidation(configuration); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); diff --git a/frontend/web/src/services/api.js b/frontend/web/src/services/api.js index dc5fd77..70d3c76 100644 --- a/frontend/web/src/services/api.js +++ b/frontend/web/src/services/api.js @@ -38,6 +38,11 @@ api.interceptors.response.use( message.error('未登录,请登录后操作。'); router.push('/auth/login') break; + case 400: + if (err.response.data && err.response.data.code == 1003) { + message.error(err.response.data.message); + break; + } default: message.error('请求错误,请检查网络。'); break; diff --git a/frontend/web/src/views/auth/Login.vue b/frontend/web/src/views/auth/Login.vue index 7ad5f10..7e20aba 100644 --- a/frontend/web/src/views/auth/Login.vue +++ b/frontend/web/src/views/auth/Login.vue @@ -102,7 +102,6 @@ const handleLogin = async () => { } } catch (e) { console.error(e) - message.error('登录请求异常') } finally{ loading.value = false; }