Commit 23e3ae0b authored by qionghong liu's avatar qionghong liu
Browse files

initial commit

parent 3bf09937
"use client";
import { useState, useEffect } from "react";
// 引入 authStore 和 AuthState,用于管理认证状态
import { authStore, AuthState } from "@/lib/authStore";
// 定义 useAuth 自定义钩子,返回认证状态和方法
export function useAuth() {
const [state, setState] = useState<AuthState>(authStore.getState());
// 使用 useEffect 订阅 authStore 的状态变化
useEffect(() => {
const unsubscribe = authStore.subscribe(setState);
return unsubscribe;
}, []);
// 返回认证状态和方法
return {
...state,
login: authStore.login.bind(authStore), //authStore.login 方法,绑定到 authStore 上下文,用于处理登录。
logout: authStore.logout.bind(authStore), //authStore.logout 方法,绑定到 authStore 上下文,用于处理退出登录。
getAuthHeader: authStore.getAuthHeader.bind(authStore), //authStore.getAuthHeader 方法,绑定到 authStore 上下文,可能用于生成认证请求头(如 Authorization: Bearer token)。
};
}
// 文件位置:src/lib/api.ts
// 管理认证 token(从 localStorage 获取,设置 Authorization 头)。
// 定义通用 fetcher 函数(getFetcher、postFetcher、getMessageUpdateFetcher),处理 GET/POST 请求、错误和 JSON 解析。
// 封装具体 API 接口(api 对象),如获取/创建/删除房间、发送/获取消息,支持认证和类型安全。
// 引入 API 响应类型,用于定义各种接口返回数据的结构
import {
RoomListRes, //(房间列表响应)
RoomMessageListRes, //(房间消息列表响应)
RoomAddRes, //(创建房间响应)
RoomMessageGetUpdateRes, //(消息更新响应)
ApiResponse, //(通用 API 响应类型)
} from "@/types/api";
// 认证状态管理 - 简单版本,避免循环依赖
// authToken 像一个“临时身份证”,用来证明用户已登录
let authToken: string | null = null;
// 设置认证 token
// 定义了一个导出函数 setAuthToken,接收一个 token 参数(字符串或 null),将它赋值给全局的 authToken。
export function setAuthToken(token: string | null) {
authToken = token;
}
// 获取认证头
function getAuthHeaders(): Record<string, string> {
const headers: Record<string, string> = {
"Content-Type": "application/json",
};
// 从 localStorage 获取 token(客户端)
if (typeof window !== "undefined") {
const token = localStorage.getItem("chatroom_token");
if (token) {
headers["Authorization"] = `Bearer ${token}`;
}
}
return headers;
}
// GET请求的fetcher函数
// 定义了一个导出的常量函数 getFetcher,用于发送 GET 请求(获取数据),接收 url 参数(字符串)。使用 fetch API 发送请求,传入 getAuthHeaders() 生成的头。
export const getFetcher = async (url: string) => {
const response = await fetch(url, {
headers: getAuthHeaders(),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result: ApiResponse = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "请求失败");
}
return result.data;
};
// POST请求的fetcher函数
export const postFetcher = async (url: string, { arg }: { arg: any }) => {
const response = await fetch(url, {
method: "POST",
headers: getAuthHeaders(),
body: JSON.stringify(arg),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result: ApiResponse = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "请求失败");
}
return result.data;
};
// 专门用于获取消息更新的fetcher
export const getMessageUpdateFetcher = async (url: string) => {
const response = await fetch(url, {
headers: getAuthHeaders(),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result: ApiResponse<RoomMessageGetUpdateRes> = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "获取消息更新失败");
}
// 确保数据存在,否则抛出错误
if (!result.data) {
throw new Error("服务器返回的数据为空");
}
return result.data;
};
// API接口封装函数 - 更新为使用认证
export const api = {
// 获取房间列表
getRoomList: async (): Promise<RoomListRes> => {
return getFetcher("/api/room/list");
},
// 创建房间 - 不再需要传递 user 参数
createRoom: async (roomName: string): Promise<RoomAddRes> => {
return postFetcher("/api/room/add", { arg: { roomName } });
},
// 删除房间 - 不再需要传递 user 参数
deleteRoom: async (roomId: number): Promise<void> => {
return postFetcher("/api/room/delete", { arg: { roomId } });
},
// 获取房间消息列表
getRoomMessages: async (roomId: number): Promise<RoomMessageListRes> => {
return getFetcher(`/api/room/message/list?roomId=${roomId}`);
},
// 发送消息 - 不再需要传递 sender 参数
sendMessage: async (roomId: number, content: string): Promise<void> => {
return postFetcher("/api/message/add", { arg: { roomId, content } });
},
// 获取消息更新
getMessageUpdate: async (
roomId: number,
sinceMessageId: number
): Promise<RoomMessageGetUpdateRes> => {
return getMessageUpdateFetcher(
`/api/room/message/getUpdate?roomId=${roomId}&sinceMessageId=${sinceMessageId}`
);
},
};
// 用户认证系统,使用 JWT 进行身份验证,并使用 bcrypt 加密和验证密码。
// jsonwebtoken 是一个用于处理 JSON Web Token(JWT)的库
import jwt from "jsonwebtoken";
// bcryptjs 是一个用于加密和解密密码的库
import bcrypt from "bcryptjs";
// 这里导入了我们自己定义的类型 JWTPayload 和 AuthenticatedUser,用于描述用户的 JWT 载荷(payload)和已认证的用户信息。
import { JWTPayload, AuthenticatedUser } from "@/types/auth";
const JWT_SECRET =
process.env.JWT_SECRET || "your-secret-key-change-in-production";
const JWT_EXPIRES_IN = "7d";
// 生成 JWT token
export function generateToken(user: AuthenticatedUser): string {
return jwt.sign(
{
userId: user.userId,
username: user.username,
},
JWT_SECRET,
{ expiresIn: JWT_EXPIRES_IN }
);
}
// 验证 JWT token
export function verifyToken(token: string): JWTPayload | null {
try {
return jwt.verify(token, JWT_SECRET) as JWTPayload;
} catch (error) {
return null;
}
}
// 密码加密
// 这是一个异步函数,用于加密用户的密码。它接受一个明文的 password 作为参数,并返回加密后的密码。
export async function hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, 12);
}
// 密码验证
// 这个函数用于验证用户输入的密码是否与存储在数据库中的加密密码(hashedPassword)相匹配。它返回一个布尔值(true 或 false)。
export async function verifyPassword(
password: string,
hashedPassword: string
): Promise<boolean> {
return bcrypt.compare(password, hashedPassword);
}
// 从请求头中提取用户信息
export function extractUserFromRequest(
request: Request
): AuthenticatedUser | null {
const authHeader = request.headers.get("Authorization");
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return null;
}
const token = authHeader.substring(7);
const payload = verifyToken(token);
if (!payload) {
return null;
}
return {
userId: payload.userId,
username: payload.username,
};
}
// 这段代码实现了一个用于管理用户认证状态的 AuthStore 类,它通过 localStorage 持久化存储认证信息,并提供了登录、登出、状态订阅等功能
"use client";
import { AuthResponse } from "@/types/auth";
const TOKEN_KEY = "chatroom_token";
const USER_KEY = "chatroom_user";
// AuthState 是认证状态的接口定义
export interface AuthState {
isAuthenticated: boolean; //表示用户是否已认证。
user: {
userId: number;
username: string;
email?: string;
} | null;
token: string | null;
}
class AuthStore {
//state 保存了当前的认证状态,初始值表示用户未认证,user 和 token 都是 null。
private state: AuthState = {
isAuthenticated: false,
user: null,
token: null,
};
// listeners 是一个函数数组,每个函数都会在认证状态发生变化时被调用,用于通知状态变化
private listeners: ((state: AuthState) => void)[] = [];
constructor() {
// 从localStorage恢复状态
if (typeof window !== "undefined") {
this.loadFromStorage();
}
}
// 订阅状态变化
subscribe(listener: (state: AuthState) => void) {
this.listeners.push(listener);
return () => {
this.listeners = this.listeners.filter((l) => l !== listener);
};
}
// 通知所有订阅者
private notify() {
this.listeners.forEach((listener) => listener(this.state));
}
// 获取当前状态
getState(): AuthState {
return { ...this.state };
}
// 登录
login(authResponse: AuthResponse) {
this.state = {
isAuthenticated: true,
user: authResponse.user,
token: authResponse.token,
};
this.saveToStorage();
this.notify();
}
// 登出
logout() {
this.state = {
isAuthenticated: false,
user: null,
token: null,
};
this.clearStorage();
this.notify();
}
// 获取认证头
getAuthHeader(): Record<string, string> {
if (!this.state.token) {
return {};
}
return {
Authorization: `Bearer ${this.state.token}`,
};
}
// 保存到本地存储
// saveToStorage 方法将当前的认证信息(token 和 user)保存到 localStorage 中。在保存之前,首先检查是否在浏览器环境中。
private saveToStorage() {
if (typeof window === "undefined") return;
localStorage.setItem(TOKEN_KEY, this.state.token || "");
localStorage.setItem(USER_KEY, JSON.stringify(this.state.user));
}
// 从本地存储加载
// loadFromStorage 方法从 localStorage 中获取保存的认证信息。如果存在有效的 token 和用户信息,它会将这些信息加载到 state 中。若加载过程中出错(例如数据损坏),则清除存储。
private loadFromStorage() {
if (typeof window === "undefined") return;
const token = localStorage.getItem(TOKEN_KEY);
const userStr = localStorage.getItem(USER_KEY);
if (token && userStr) {
try {
const user = JSON.parse(userStr);
this.state = {
isAuthenticated: true,
user,
token,
};
} catch (error) {
console.error("Failed to load auth state from storage:", error);
this.clearStorage();
}
}
}
// 清除本地存储
private clearStorage() {
if (typeof window === "undefined") return;
localStorage.removeItem(TOKEN_KEY);
localStorage.removeItem(USER_KEY);
}
}
export const authStore = new AuthStore();
// 文件位置:src/lib/dataStore.ts
// 简单的内存数据存储,用于模拟数据库
// 实际项目中应该使用真正的数据库(因为实验文档使用数据库的要求放在后面,我写完才看见,所以只能维持之前用内存存储的方法了)
import { RoomPreviewInfo, Message } from "@/types";
// 声明全局变量类型
declare global {
var __chatroom_messages__: Message[] | undefined;
var __chatroom_rooms__: RoomPreviewInfo[] | undefined;
var __chatroom_users__: UserData[] | undefined;
var __chatroom_next_user_id__: number | undefined;
}
// 初始房间数据
const initialRooms: RoomPreviewInfo[] = [
{
roomId: 1,
roomName: "技术交流",
lastMessage: {
messageId: 1,
roomId: 1,
sender: "张三",
content: "大家好!",
time: Date.now() - 300000,
},
},
{
roomId: 2,
roomName: "项目讨论",
lastMessage: {
messageId: 2,
roomId: 2,
sender: "李四",
content: "会议改时间了",
time: Date.now() - 600000,
},
},
];
// 初始消息数据
const initialMessages: Message[] = [
{
messageId: 1,
roomId: 1,
sender: "张三",
content: "大家好!",
time: Date.now() - 3600000,
},
{
messageId: 2,
roomId: 1,
sender: "李四",
content: "你好呀!",
time: Date.now() - 1800000,
},
{
messageId: 3,
roomId: 2,
sender: "王五",
content: "项目进度如何?",
time: Date.now() - 2400000,
},
{
messageId: 4,
roomId: 2,
sender: "李四",
content: "会议改时间了",
time: Date.now() - 600000,
},
];
// 初始化全局数据
if (typeof global !== "undefined") {
// 初始化房间数据
if (!global.__chatroom_rooms__) {
global.__chatroom_rooms__ = [...initialRooms];
console.log("[全局初始化] 初始化房间数据");
}
// 初始化消息数据
if (!global.__chatroom_messages__) {
global.__chatroom_messages__ = [...initialMessages];
console.log("[全局初始化] 初始化消息数据");
}
// 初始化用户数据
if (!global.__chatroom_users__) {
global.__chatroom_users__ = [];
console.log("[全局初始化] 初始化用户数据");
}
if (!global.__chatroom_next_user_id__) {
global.__chatroom_next_user_id__ = 1;
console.log("[全局初始化] 初始化用户ID计数器");
}
}
// 房间数据
export let rooms: RoomPreviewInfo[] = [];
// 消息数据
export let messages: Message[] = [];
// 用户数据
let users: UserData[] = [];
let nextUserId = 1;
// 在模块加载时同步全局数据
if (typeof global !== "undefined") {
// 同步房间数据
if (global.__chatroom_rooms__) {
rooms = global.__chatroom_rooms__;
console.log("[模块加载] 已从全局变量加载房间数据,房间数:", rooms.length);
} else {
rooms = [...initialRooms];
console.log("[模块加载] 使用初始房间数据,房间数:", rooms.length);
}
// 同步消息数据
if (global.__chatroom_messages__) {
messages = global.__chatroom_messages__;
console.log(
"[模块加载] 已从全局变量加载消息数据,消息数:",
messages.length
);
} else {
messages = [...initialMessages];
console.log("[模块加载] 使用初始消息数据,消息数:", messages.length);
}
// 同步用户数据
if (global.__chatroom_users__) {
users = global.__chatroom_users__;
console.log("[模块加载] 已从全局变量加载用户数据,用户数:", users.length);
}
if (global.__chatroom_next_user_id__) {
nextUserId = global.__chatroom_next_user_id__;
console.log("[模块加载] 已从全局变量加载用户ID计数器:", nextUserId);
}
} else {
rooms = [...initialRooms];
messages = [...initialMessages];
console.log("[模块加载] global不可用,使用初始数据");
}
// 同步房间数据到全局变量
function syncRoomsToGlobal(): void {
if (typeof global !== "undefined") {
global.__chatroom_rooms__ = rooms;
console.log(
"[syncRoomsToGlobal] 房间数据已同步到全局变量,房间数:",
rooms.length
);
}
}
// 同步消息数据到全局变量
function syncMessagesToGlobal(): void {
if (typeof global !== "undefined") {
global.__chatroom_messages__ = messages;
console.log(
"[syncMessagesToGlobal] 消息数据已同步到全局变量,消息数:",
messages.length
);
}
}
// 获取下一个房间ID
export function getNextRoomId(): number {
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_rooms__) {
rooms = global.__chatroom_rooms__;
}
const nextId = Math.max(...rooms.map((r) => r.roomId), 0) + 1;
console.log(`[getNextRoomId] 生成的下一个房间ID: ${nextId}`);
return nextId;
}
// 获取下一个消息ID
export function getNextMessageId(): number {
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_messages__) {
messages = global.__chatroom_messages__;
}
const nextId = Math.max(...messages.map((m) => m.messageId), 0) + 1;
console.log(
`[getNextMessageId] 当前消息数量: ${messages.length}, 生成的下一个ID: ${nextId}`
);
return nextId;
}
// 添加房间
export function addRoom(room: RoomPreviewInfo): void {
console.log(`\n[addRoom] ===== 开始添加房间 =====`);
console.log(`[addRoom] 要添加的房间:`, {
roomId: room.roomId,
roomName: room.roomName,
});
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_rooms__) {
rooms = global.__chatroom_rooms__;
}
console.log(`[addRoom] 添加前房间数量: ${rooms.length}`);
rooms.push(room);
// 同步到全局变量
syncRoomsToGlobal();
console.log(`[addRoom] 添加后房间数量: ${rooms.length}`);
console.log(
`[addRoom] 所有房间:`,
rooms.map((r) => `${r.roomName}(ID:${r.roomId})`)
);
console.log(`[addRoom] ===== 房间添加完成 =====\n`);
}
// 删除房间
export function removeRoom(roomId: number): boolean {
console.log(`\n[removeRoom] ===== 开始删除房间 =====`);
console.log(`[removeRoom] 要删除的房间ID: ${roomId}`);
// 确保从全局变量同步最新数据
if (typeof global !== "undefined") {
if (global.__chatroom_rooms__) {
rooms = global.__chatroom_rooms__;
}
if (global.__chatroom_messages__) {
messages = global.__chatroom_messages__;
}
}
console.log(`[removeRoom] 删除前房间数量: ${rooms.length}`);
console.log(`[removeRoom] 删除前消息数量: ${messages.length}`);
const index = rooms.findIndex((r) => r.roomId === roomId);
if (index !== -1) {
rooms.splice(index, 1);
// 同时删除该房间的所有消息
const originalMessageCount = messages.length;
messages = messages.filter((m) => m.roomId !== roomId);
const deletedMessageCount = originalMessageCount - messages.length;
// 同步到全局变量
syncRoomsToGlobal();
syncMessagesToGlobal();
console.log(`[removeRoom] 房间删除成功`);
console.log(`[removeRoom] 删除后房间数量: ${rooms.length}`);
console.log(`[removeRoom] 删除了 ${deletedMessageCount} 条消息`);
console.log(`[removeRoom] 删除后消息数量: ${messages.length}`);
console.log(
`[removeRoom] 剩余房间:`,
rooms.map((r) => `${r.roomName}(ID:${r.roomId})`)
);
console.log(`[removeRoom] ===== 房间删除完成 =====\n`);
return true;
}
console.log(`[removeRoom] 房间不存在,删除失败`);
console.log(`[removeRoom] ===== 房间删除失败 =====\n`);
return false;
}
// 添加消息
export function addMessage(message: Message): void {
console.log(`\n[addMessage] ===== 开始添加消息 =====`);
console.log(`[addMessage] 传入的消息:`, {
messageId: message.messageId,
roomId: message.roomId,
sender: message.sender,
content: message.content,
time: new Date(message.time).toLocaleString(),
});
// 确保从全局变量同步最新数据
if (typeof global !== "undefined") {
if (global.__chatroom_messages__) {
messages = global.__chatroom_messages__;
}
if (global.__chatroom_rooms__) {
rooms = global.__chatroom_rooms__;
}
}
console.log(`[addMessage] 添加前消息总数: ${messages.length}`);
messages.push(message);
// 同步消息到全局变量
syncMessagesToGlobal();
console.log(`[addMessage] 添加后消息总数: ${messages.length}`);
// 更新对应房间的最后一条消息
const roomIndex = rooms.findIndex((r) => r.roomId === message.roomId);
if (roomIndex !== -1) {
rooms[roomIndex].lastMessage = message;
// 同步房间数据到全局变量
syncRoomsToGlobal();
console.log(`[addMessage] 房间 ${message.roomId} 的最后消息已更新`);
} else {
console.log(`[addMessage] 警告: 未找到房间 ${message.roomId}`);
}
console.log(`[addMessage] ===== 消息添加完成 =====\n`);
}
// 获取房间消息
export function getRoomMessages(roomId: number): Message[] {
console.log(`\n[getRoomMessages] ===== 开始获取房间消息 =====`);
console.log(`[getRoomMessages] 请求的房间ID: ${roomId}`);
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_messages__) {
messages = global.__chatroom_messages__;
console.log(`[getRoomMessages] 已从全局变量同步消息数据`);
}
console.log(`[getRoomMessages] 当前全部消息数量: ${messages.length}`);
const roomMessages = messages.filter((m) => m.roomId === roomId);
console.log(
`[getRoomMessages] 找到房间 ${roomId} 的消息数量: ${roomMessages.length}`
);
console.log(`[getRoomMessages] ===== 房间消息获取完成 =====\n`);
return roomMessages;
}
// 获取房间更新消息
export function getRoomUpdateMessages(
roomId: number,
sinceMessageId: number
): Message[] {
console.log(
`[getRoomUpdateMessages] 获取房间 ${roomId} 自消息ID ${sinceMessageId} 以来的更新`
);
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_messages__) {
messages = global.__chatroom_messages__;
}
const updateMessages = messages.filter(
(m) => m.roomId === roomId && m.messageId > sinceMessageId
);
console.log(
`[getRoomUpdateMessages] 找到 ${updateMessages.length} 条更新消息`
);
return updateMessages;
}
// 获取所有房间(用于API)
export function getAllRooms(): RoomPreviewInfo[] {
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_rooms__) {
rooms = global.__chatroom_rooms__;
}
console.log(`[getAllRooms] 返回 ${rooms.length} 个房间`);
return rooms;
}
// 登录鉴权
interface UserData {
userId: number;
username: string;
email?: string;
passwordHash: string;
createdAt: number;
}
// 保存用户数据到全局变量
function saveUsersToGlobal(): void {
if (typeof global !== "undefined") {
global.__chatroom_users__ = users;
global.__chatroom_next_user_id__ = nextUserId;
console.log(
"[saveUsersToGlobal] 用户数据已保存到全局变量,用户数:",
users.length
);
}
}
// 用户相关操作
export const userStore = {
// 创建用户
createUser: async (
username: string,
email: string | undefined,
passwordHash: string
): Promise<UserData> => {
// 确保从全局变量同步最新数据
if (typeof global !== "undefined") {
if (global.__chatroom_users__) {
users = global.__chatroom_users__;
}
if (global.__chatroom_next_user_id__) {
nextUserId = global.__chatroom_next_user_id__;
}
}
const user: UserData = {
userId: nextUserId++,
username,
email,
passwordHash,
createdAt: Date.now(),
};
users.push(user);
// 保存到全局变量
saveUsersToGlobal();
console.log(`用户创建成功: ${username}, ID: ${user.userId}`);
console.log(`当前用户总数: ${users.length}`);
return user;
},
// 根据用户名查找用户
findUserByUsername: (username: string): UserData | undefined => {
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_users__) {
users = global.__chatroom_users__;
}
const user = users.find((user) => user.username === username);
console.log(`查找用户 "${username}":`, user ? "找到" : "未找到");
return user;
},
// 根据用户ID查找用户
findUserById: (userId: number): UserData | undefined => {
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_users__) {
users = global.__chatroom_users__;
}
return users.find((user) => user.userId === userId);
},
// 检查用户名是否已存在
isUsernameExists: (username: string): boolean => {
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_users__) {
users = global.__chatroom_users__;
}
const exists = users.some((user) => user.username === username);
console.log(
`检查用户名 "${username}" 是否存在:`,
exists ? "存在" : "不存在"
);
return exists;
},
// 获取所有用户 (调试用)
getAllUsers: (): UserData[] => {
// 确保从全局变量同步最新数据
if (typeof global !== "undefined" && global.__chatroom_users__) {
users = global.__chatroom_users__;
}
console.log(
"当前所有用户:",
users.map((u) => ({
userId: u.userId,
username: u.username,
createdAt: new Date(u.createdAt).toLocaleString(),
}))
);
return users.map(({ passwordHash, ...user }) => user as any);
},
};
// 文件位置:src/types/api.ts
// API接口参数和响应类型定义
// === 创建房间 ===
export interface RoomAddArgs {
user: string;
roomName: string;
}
export interface RoomAddRes {
roomId: number;
}
// === 获取房间列表 ===
export interface RoomListRes {
rooms: import('./index').RoomPreviewInfo[];
}
// === 删除房间 ===
export interface RoomDeleteArgs {
user: string;
roomId: number;
}
// === 添加消息 ===
export interface MessageAddArgs {
roomId: number;
content: string;
sender: string;
}
// === 获取房间消息列表 ===
export interface RoomMessageListArgs {
roomId: number;
}
export interface RoomMessageListRes {
messages: import('./index').Message[];
}
// === 获取消息更新 ===
export interface RoomMessageGetUpdateArgs {
roomId: number;
sinceMessageId: number;
}
export interface RoomMessageGetUpdateRes {
messages: import('./index').Message[];
}
// === 通用响应格式 ===
export interface ApiResponse<T = any> {
code: number;
data?: T;
message?: string;
}
// 用户认证相关类型
// 这个接口表示用户的 登录凭据,即用户用来登录的 用户名 和 密码。
export interface UserCredentials {
username: string;
password: string;
}
//这个接口表示 注册时 传递的参数,它继承了 UserCredentials 接口(意味着注册时也需要用户名和密码),并且新增了一个可选的 电子邮件 字段。
export interface RegisterArgs extends UserCredentials {
email?: string;
}
export interface LoginArgs extends UserCredentials {}
// 这个接口表示 认证响应,即用户成功登录后,后端返回的用户信息和 JWT token。它包含了用户的基本信息和一个 JWT token,该 token 用于后续的身份验证。
export interface AuthResponse {
user: {
userId: number;
username: string;
email?: string;
};
token: string;
}
// 这个接口表示 JWT payload,即存储在 JWT token 中的用户信息。JWT token 是一个自包含的令牌,包含用户认证所需的最小信息,这些信息是经过加密后可以验证的。
export interface JWTPayload {
userId: number; // 用户的唯一 ID,类型为 number
username: string; // 用户的用户名,类型为 string。
iat: number; //表示 token 颁发的时间戳,类型为 number(单位是秒)。
exp: number; //表示 token 过期的时间戳,类型为 number(单位是秒)。
}
// 认证用户信息 (用于API中间件)
// 这个接口表示 已认证用户,即认证过程完成后,系统中表示用户身份的最简信息
export interface AuthenticatedUser {
userId: number;
username: string;
}
// src/types/index.ts
export interface Message {
messageId: number; // 消息 id
roomId: number; // 房间 id
sender: string; // 发送人的 username
content: string; // 消息内容
time: number; // 消息发送时间戳
}
export interface RoomPreviewInfo {
roomId: number;
roomName: string;
// UPDATE 20230814: 这里增加了 null 的可能性
lastMessage: Message | null;
}
// 额外添加的有用类型
export interface User {
userId: number;
username: string;
isOnline?: boolean;
}
export interface ChatRoomData {
roomId: number;
roomName: string;
messages: Message[];
participants: User[];
}
// 导出API类型
export * from './api';
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment