Merge pull request 'feature-nxdev' (#33) from feature-nxdev into main

Reviewed-on: #33
This commit is contained in:
西街长安 2025-12-29 21:57:59 +08:00
commit 600272486b
12 changed files with 122 additions and 13 deletions

View File

@ -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<IAuthService, AuthService>();
services.AddTransient<IUserService, UserService>();
@ -14,8 +19,28 @@ namespace IM_API.Configs
services.AddTransient<IMessageSevice, MessageService>();
services.AddTransient<IConversationService, ConversationService>();
services.AddSingleton<IJWTService, JWTService>();
services.AddSingleton<IRefreshTokenService,RedisRefreshTokenService>();
services.AddSingleton<IRefreshTokenService, RedisRefreshTokenService>();
return services;
}
}
public static IServiceCollection AddModelValidation(this IServiceCollection services, IConfiguration configuration)
{
services.Configure<ApiBehaviorOptions>(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<object?>(CodeDefine.PARAMETER_ERROR.Code, errors.First().Message));
};
});
return services;
}
}
}

View File

@ -28,6 +28,20 @@ namespace IM_API.Controllers
var res = new BaseResponse<List<Conversation>>(list);
return Ok(res);
}
[HttpPost]
public async Task<IActionResult> Clear()
{
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
await _conversationSerivice.ClearConversationsAsync(int.Parse(userIdStr));
return Ok(new BaseResponse<object?>());
}
[HttpPost]
public async Task<IActionResult> Delete(int cid)
{
await _conversationSerivice.DeleteConversationAsync(cid);
return Ok(new BaseResponse<object?>());
}
}
}

View File

@ -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<object?>());
}
/// <summary>

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }

View File

@ -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; }
}
}

View File

@ -102,6 +102,7 @@ namespace IM_API
{
options.Filters.Add<GlobalExceptionFilter>();
});
builder.Services.AddModelValidation(configuration);
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

View File

@ -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;

View File

@ -102,7 +102,6 @@ const handleLogin = async () => {
}
} catch (e) {
console.error(e)
message.error('登录请求异常')
} finally{
loading.value = false;
}