From c67c6661353fbff03e90d2ffac080d3e87083c75 Mon Sep 17 00:00:00 2001 From: nanxun Date: Sun, 19 Oct 2025 14:56:05 +0800 Subject: [PATCH] =?UTF-8?q?add(=E6=8E=A5=E5=8F=A3)=EF=BC=9A=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=8E=88=E6=9D=83=E3=80=81=E7=94=A8=E6=88=B7=E3=80=81?= =?UTF-8?q?=E5=A5=BD=E5=8F=8B=E5=85=B3=E7=B3=BB=E6=9C=8D=E5=8A=A1=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/IM_API/Dtos/BaseResponse.cs | 57 +++ backend/IM_API/Dtos/FriendRequestDto.cs | 9 + backend/IM_API/Dtos/LoginDto.cs | 9 + backend/IM_API/Dtos/LoginRequestDto.cs | 8 + backend/IM_API/Dtos/RegisterRequestDto.cs | 8 + backend/IM_API/Dtos/UpdateUserDto.cs | 7 + backend/IM_API/Dtos/UserInfoDto.cs | 38 ++ backend/IM_API/IM_API.csproj | 1 + .../IM_API/Interface/Services/IAuthService.cs | 39 ++ .../Interface/Services/IFriendSerivce.cs | 32 ++ .../IM_API/Interface/Services/IUserService.cs | 39 ++ backend/IM_API/Models/FriendStatus.cs | 7 + backend/IM_API/Models/User.cs | 4 +- backend/IM_API/Models/UserOlineStatus.cs | 18 + backend/IM_API/Models/UserStatus.cs | 9 + backend/IM_API/Tools/PasswordHasher.cs | 22 + frontend/web/src/App.vue | 16 +- frontend/web/src/components/Layout.vue | 262 ++++++++++++ frontend/web/src/router/index.js | 4 +- frontend/web/src/views/auth/Login.vue | 386 ++++++++++++++++++ 20 files changed, 967 insertions(+), 8 deletions(-) create mode 100644 backend/IM_API/Dtos/BaseResponse.cs create mode 100644 backend/IM_API/Dtos/FriendRequestDto.cs create mode 100644 backend/IM_API/Dtos/LoginDto.cs create mode 100644 backend/IM_API/Dtos/LoginRequestDto.cs create mode 100644 backend/IM_API/Dtos/RegisterRequestDto.cs create mode 100644 backend/IM_API/Dtos/UpdateUserDto.cs create mode 100644 backend/IM_API/Dtos/UserInfoDto.cs create mode 100644 backend/IM_API/Interface/Services/IAuthService.cs create mode 100644 backend/IM_API/Interface/Services/IFriendSerivce.cs create mode 100644 backend/IM_API/Interface/Services/IUserService.cs create mode 100644 backend/IM_API/Models/FriendStatus.cs create mode 100644 backend/IM_API/Models/UserOlineStatus.cs create mode 100644 backend/IM_API/Models/UserStatus.cs create mode 100644 backend/IM_API/Tools/PasswordHasher.cs create mode 100644 frontend/web/src/components/Layout.vue create mode 100644 frontend/web/src/views/auth/Login.vue diff --git a/backend/IM_API/Dtos/BaseResponse.cs b/backend/IM_API/Dtos/BaseResponse.cs new file mode 100644 index 0000000..e238946 --- /dev/null +++ b/backend/IM_API/Dtos/BaseResponse.cs @@ -0,0 +1,57 @@ +namespace IM_API.Dtos +{ + public class BaseResponse + { + //响应状态码 + public int Code { get; set; } + //响应消息 + public string Message { get; set; } + //响应数据 + public T? Data { get; set; } + /// + /// 默认成功响应返回 + /// + /// + /// + public BaseResponse(string msg,T data) + { + this.Code = 0; + this.Message = msg; + this.Data = data; + } + /// + /// 默认成功响应返回,不带数据 + /// + /// + /// + public BaseResponse(string msg) + { + this.Code = 0; + this.Message = msg; + } + /// + /// 非成功响应且带数据 + /// + /// + /// + /// + public BaseResponse(int code, string message, T? data) + { + Code = code; + Message = message; + Data = data; + } + /// + /// 非成功响应且不带数据 + /// + /// + /// + /// + public BaseResponse(int code, string message) + { + Code = code; + Message = message; + } + public BaseResponse() { } + } +} diff --git a/backend/IM_API/Dtos/FriendRequestDto.cs b/backend/IM_API/Dtos/FriendRequestDto.cs new file mode 100644 index 0000000..8990d96 --- /dev/null +++ b/backend/IM_API/Dtos/FriendRequestDto.cs @@ -0,0 +1,9 @@ +namespace IM_API.Dtos +{ + public class FriendRequestDto + { + public int FromUserId { get; set; } + public int ToUserId { get; set; } + public string? Description { get; set; } + } +} diff --git a/backend/IM_API/Dtos/LoginDto.cs b/backend/IM_API/Dtos/LoginDto.cs new file mode 100644 index 0000000..03cd5e0 --- /dev/null +++ b/backend/IM_API/Dtos/LoginDto.cs @@ -0,0 +1,9 @@ +namespace IM_API.Dtos +{ + public class LoginDto + { + public int Id { get; set; } + public string Token { get; set; } + public string RefreshToken { get; set; } + } +} diff --git a/backend/IM_API/Dtos/LoginRequestDto.cs b/backend/IM_API/Dtos/LoginRequestDto.cs new file mode 100644 index 0000000..b1c1b1f --- /dev/null +++ b/backend/IM_API/Dtos/LoginRequestDto.cs @@ -0,0 +1,8 @@ +namespace IM_API.Dtos +{ + public class LoginRequestDto + { + public string Username { get; set; } + public string Password { get; set; } + } +} diff --git a/backend/IM_API/Dtos/RegisterRequestDto.cs b/backend/IM_API/Dtos/RegisterRequestDto.cs new file mode 100644 index 0000000..e4ac4d0 --- /dev/null +++ b/backend/IM_API/Dtos/RegisterRequestDto.cs @@ -0,0 +1,8 @@ +namespace IM_API.Dtos +{ + public class RegisterRequestDto + { + public string Username { get; set; } + public string Password { get; set; } + } +} diff --git a/backend/IM_API/Dtos/UpdateUserDto.cs b/backend/IM_API/Dtos/UpdateUserDto.cs new file mode 100644 index 0000000..279018d --- /dev/null +++ b/backend/IM_API/Dtos/UpdateUserDto.cs @@ -0,0 +1,7 @@ +namespace IM_API.Dtos +{ + public class UpdateUserDto + { + public string? NickName { get; set; } + } +} diff --git a/backend/IM_API/Dtos/UserInfoDto.cs b/backend/IM_API/Dtos/UserInfoDto.cs new file mode 100644 index 0000000..fff482a --- /dev/null +++ b/backend/IM_API/Dtos/UserInfoDto.cs @@ -0,0 +1,38 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace IM_API.Dtos +{ + public class UserInfoDto + { + public int Id { get; set; } + + /// + /// 唯一用户名 + /// + public string Username { get; set; } + + /// + /// 用户昵称 + /// + public string NickName { get; set; } + + /// + /// 用户在线状态 + /// 0(默认):不在线 + /// 1:在线 + /// + public sbyte OlineStatus { get; set; } + + /// + /// 创建时间 + /// + public DateTime Created { get; set; } + + /// + /// 账户状态 + /// (0:未激活,1:正常,2:封禁) + /// + public sbyte Status { get; set; } + } +} diff --git a/backend/IM_API/IM_API.csproj b/backend/IM_API/IM_API.csproj index 4610176..1f6fe1f 100644 --- a/backend/IM_API/IM_API.csproj +++ b/backend/IM_API/IM_API.csproj @@ -21,6 +21,7 @@ + diff --git a/backend/IM_API/Interface/Services/IAuthService.cs b/backend/IM_API/Interface/Services/IAuthService.cs new file mode 100644 index 0000000..38b493f --- /dev/null +++ b/backend/IM_API/Interface/Services/IAuthService.cs @@ -0,0 +1,39 @@ +using IM_API.Dtos; +using IM_API.Models; + +namespace IM_API.Interface.Services +{ + public interface IAuthService + { + /// + /// 登录 + /// + /// + /// + Task LoginAsync(LoginRequestDto dto); + /// + /// 注册 + /// + /// + /// + Task RegisterAsync(RegisterRequestDto dto); + /// + /// 生成登录凭证 + /// + /// + /// + string GenerateToken(User user); + /// + /// 验证登录凭证 + /// + /// + /// + int? ValidateToken(string token); + /// + /// 刷新令牌 + /// + /// + /// + LoginDto RefreshToken(string refreshToken); + } +} diff --git a/backend/IM_API/Interface/Services/IFriendSerivce.cs b/backend/IM_API/Interface/Services/IFriendSerivce.cs new file mode 100644 index 0000000..ecd620d --- /dev/null +++ b/backend/IM_API/Interface/Services/IFriendSerivce.cs @@ -0,0 +1,32 @@ +using IM_API.Dtos; +using IM_API.Models; + +namespace IM_API.Interface.Services +{ + public interface IFriendSerivce + { + /// + /// 获取好友列表 + /// + /// 指定用户 + /// 当前页 + /// 分页大小 + /// + Task> GetFriendListAsync(int userId,int page,int limit); + /// + /// 新增好友请求 + /// + /// + /// + Task SendFriendRequestAsync(FriendRequestDto friendRequest); + /// + /// 获取好友请求 + /// + /// + /// 是否为接受请求方 + /// + /// + /// + Task GetFriendRequestListAsync(int userId,bool isReceived,int page,int limit); + } +} diff --git a/backend/IM_API/Interface/Services/IUserService.cs b/backend/IM_API/Interface/Services/IUserService.cs new file mode 100644 index 0000000..b11f2c3 --- /dev/null +++ b/backend/IM_API/Interface/Services/IUserService.cs @@ -0,0 +1,39 @@ +using IM_API.Dtos; +using IM_API.Models; + +namespace IM_API.Interface.Services +{ + public interface IUserService + { + /// + /// 获取用户信息 + /// + /// + /// + Task GetUserInfoAsync(int userId); + /// + /// 用户名查找用户 + /// + /// + /// + Task GetUserInfoByUsernameAsync(string username); + /// + /// 更新用户信息 + /// + /// + /// + Task UpdateUserAsync(UpdateUserDto dto); + /// + /// 重置用户密码 + /// + /// + /// + Task ResetPasswordAsync(string password); + /// + /// 更新用户在线状态 + /// + /// + /// + Task UpdateOlineStatusAsync(UserOnlineStatus onlineStatus); + } +} diff --git a/backend/IM_API/Models/FriendStatus.cs b/backend/IM_API/Models/FriendStatus.cs new file mode 100644 index 0000000..08324a8 --- /dev/null +++ b/backend/IM_API/Models/FriendStatus.cs @@ -0,0 +1,7 @@ +namespace IM_API.Models +{ + public enum FriendStatus:SByte + { + + } +} diff --git a/backend/IM_API/Models/User.cs b/backend/IM_API/Models/User.cs index 55bcdb3..b1639a3 100644 --- a/backend/IM_API/Models/User.cs +++ b/backend/IM_API/Models/User.cs @@ -41,7 +41,7 @@ public partial class User /// 1:在线 /// [Column(TypeName = "tinyint(4)")] - public sbyte OlineStatus { get; set; } + public UserOnlineStatus OlineStatus { get; set; } /// /// 创建时间 @@ -60,7 +60,7 @@ public partial class User /// (0:未激活,1:正常,2:封禁) /// [Column(TypeName = "tinyint(4)")] - public sbyte Status { get; set; } + public UserStatus Status { get; set; } /// /// 软删除标识 diff --git a/backend/IM_API/Models/UserOlineStatus.cs b/backend/IM_API/Models/UserOlineStatus.cs new file mode 100644 index 0000000..ac3f15f --- /dev/null +++ b/backend/IM_API/Models/UserOlineStatus.cs @@ -0,0 +1,18 @@ +namespace IM_API.Models +{ + /// + /// 用户在线状态 + /// + public enum UserOnlineStatus : sbyte + { + /// + /// 不在线 (0) + /// + Offline = 0, + + /// + /// 在线 (1) + /// + Online = 1 + } +} diff --git a/backend/IM_API/Models/UserStatus.cs b/backend/IM_API/Models/UserStatus.cs new file mode 100644 index 0000000..e08f38b --- /dev/null +++ b/backend/IM_API/Models/UserStatus.cs @@ -0,0 +1,9 @@ +namespace IM_API.Models +{ + public enum UserStatus:SByte + { + Inactive = 0, + Normal = 1, + Banned = 2 + } +} diff --git a/backend/IM_API/Tools/PasswordHasher.cs b/backend/IM_API/Tools/PasswordHasher.cs new file mode 100644 index 0000000..b567cc4 --- /dev/null +++ b/backend/IM_API/Tools/PasswordHasher.cs @@ -0,0 +1,22 @@ +using System.Security.Cryptography; +using System.Text; + +namespace IM_API.Tools +{ + public static class PasswordHasher + { + public static string HashPassword(string password) + { + using var sha256 = SHA256.Create(); + var hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password)); + return Convert.ToBase64String(hashedBytes); + } + + public static bool VerifyPassword(string password, string hashedPassword) + { + var hashedInput = HashPassword(password); + return hashedInput == hashedPassword; + } + } +} +} diff --git a/frontend/web/src/App.vue b/frontend/web/src/App.vue index 6ec9f60..af331b0 100644 --- a/frontend/web/src/App.vue +++ b/frontend/web/src/App.vue @@ -1,11 +1,17 @@ + + diff --git a/frontend/web/src/components/Layout.vue b/frontend/web/src/components/Layout.vue new file mode 100644 index 0000000..c00ea60 --- /dev/null +++ b/frontend/web/src/components/Layout.vue @@ -0,0 +1,262 @@ + + + + + \ No newline at end of file diff --git a/frontend/web/src/router/index.js b/frontend/web/src/router/index.js index e1eab52..29e07eb 100644 --- a/frontend/web/src/router/index.js +++ b/frontend/web/src/router/index.js @@ -1,8 +1,10 @@ import { createRouter, createWebHistory } from 'vue-router' +const routes = [{ path: '/auth/login', component: () => import('@/views/auth/Login.vue') }] + const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), - routes: [], + routes, }) export default router diff --git a/frontend/web/src/views/auth/Login.vue b/frontend/web/src/views/auth/Login.vue new file mode 100644 index 0000000..7bd501e --- /dev/null +++ b/frontend/web/src/views/auth/Login.vue @@ -0,0 +1,386 @@ + + + + + \ No newline at end of file