chore(comment): 注释改为英文
This commit is contained in:
@@ -8,17 +8,16 @@ const App: React.FC = () => {
|
|||||||
const { setTheme } = useTheme();
|
const { setTheme } = useTheme();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 在组件挂载时先处理URL中的authToken 和 groupId
|
// Consume authToken & groupId from URL and persist
|
||||||
handleAuthTokenAndGroupIdFromUrl();
|
handleAuthTokenAndGroupIdFromUrl();
|
||||||
|
|
||||||
// 读取并处理URL中的 theme('light'|'dark')参数
|
// Read optional theme ('light' | 'dark') from URL and persist via ThemeProvider
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const themeParam = params.get('theme');
|
const themeParam = params.get('theme');
|
||||||
if (themeParam === 'light' || themeParam === 'dark') {
|
if (themeParam === 'light' || themeParam === 'dark') {
|
||||||
// 使用 ThemeProvider 的 setTheme 应用主题,并存入本地(storageKey: egret-ui-theme)
|
|
||||||
setTheme(themeParam);
|
setTheme(themeParam);
|
||||||
|
|
||||||
// 从URL中移除 theme 参数,保持地址整洁
|
// Clean up URL param after applying
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
url.searchParams.delete('theme');
|
url.searchParams.delete('theme');
|
||||||
window.history.replaceState(null, '', url.toString());
|
window.history.replaceState(null, '', url.toString());
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ interface RequestOptions extends RequestInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一的fetch请求封装
|
* Unified fetch wrapper that adds auth and group headers
|
||||||
* 自动添加Authorization头部
|
|
||||||
*/
|
*/
|
||||||
export const apiRequest = async <T = any>(
|
export const apiRequest = async <T = any>(
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
@@ -17,34 +16,34 @@ export const apiRequest = async <T = any>(
|
|||||||
|
|
||||||
const url = endpoint;
|
const url = endpoint;
|
||||||
|
|
||||||
// 准备请求头
|
// Prepare request headers
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
...options.headers,
|
...options.headers,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 如果有authToken,添加Authorization头
|
// Attach Authorization header if token exists
|
||||||
if (authToken) {
|
if (authToken) {
|
||||||
headers.authorization = `Bearer ${authToken}`;
|
headers.authorization = `Bearer ${authToken}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果有groupId,添加groupId头
|
// Attach groupId header if present
|
||||||
if (groupId) {
|
if (groupId) {
|
||||||
headers.groupId = groupId;
|
headers.groupId = groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发起请求
|
// Fire request
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
...options,
|
...options,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 处理响应
|
// Handle non-2xx
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试解析JSON,如果失败则返回响应对象
|
// Try to parse JSON; fallback to raw response
|
||||||
try {
|
try {
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch {
|
} catch {
|
||||||
@@ -52,7 +51,7 @@ export const apiRequest = async <T = any>(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 便捷的HTTP方法封装
|
// Convenience HTTP helpers
|
||||||
export const api = {
|
export const api = {
|
||||||
get: <T = any>(endpoint: string, options?: RequestOptions): Promise<ApiResponse<T>> =>
|
get: <T = any>(endpoint: string, options?: RequestOptions): Promise<ApiResponse<T>> =>
|
||||||
apiRequest<ApiResponse<T>>(endpoint, { ...options, method: 'GET' }),
|
apiRequest<ApiResponse<T>>(endpoint, { ...options, method: 'GET' }),
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export type UserInfo = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前用户的信息
|
* Get current user information
|
||||||
*/
|
*/
|
||||||
export const getUserInfo = async (): Promise<UserInfo | null> => {
|
export const getUserInfo = async (): Promise<UserInfo | null> => {
|
||||||
const res = await api.get<UserInfo>('/api/user/info');
|
const res = await api.get<UserInfo>('/api/user/info');
|
||||||
@@ -20,7 +20,7 @@ export const getUserInfo = async (): Promise<UserInfo | null> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取群组内所有用户的信息
|
* Get all users in the current group
|
||||||
*/
|
*/
|
||||||
export const getGroupMembers = async (): Promise<UserInfo[]> => {
|
export const getGroupMembers = async (): Promise<UserInfo[]> => {
|
||||||
const res = await api.get<UserInfo[]>('/api/group/members');
|
const res = await api.get<UserInfo[]>('/api/group/members');
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
// 处理认证相关的工具函数
|
// Auth utilities
|
||||||
|
|
||||||
const AUTH_TOKEN_KEY = 'authToken';
|
const AUTH_TOKEN_KEY = 'authToken';
|
||||||
const GROUP_ID_KEY = 'groupId';
|
const GROUP_ID_KEY = 'groupId';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从URL搜索参数中获取authToken
|
* Get authToken from URL search params
|
||||||
*/
|
*/
|
||||||
export const getAuthTokenFromUrl = (): string | null => {
|
export const getAuthTokenFromUrl = (): string | null => {
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
return urlParams.get('authToken');
|
return urlParams.get('authToken');
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* 从URL搜索参数中获取groupId
|
* Get groupId from URL search params
|
||||||
*/
|
*/
|
||||||
export const getGroupIdFromUrl = (): string | null => {
|
export const getGroupIdFromUrl = (): string | null => {
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
@@ -19,21 +19,21 @@ export const getGroupIdFromUrl = (): string | null => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存authToken到localStorage
|
* Save authToken to localStorage
|
||||||
*/
|
*/
|
||||||
export const saveAuthToken = (token: string): void => {
|
export const saveAuthToken = (token: string): void => {
|
||||||
localStorage.setItem(AUTH_TOKEN_KEY, token);
|
localStorage.setItem(AUTH_TOKEN_KEY, token);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存groupId到localStorage
|
* Save groupId to localStorage
|
||||||
*/
|
*/
|
||||||
export const saveGroupId = (groupId: string): void => {
|
export const saveGroupId = (groupId: string): void => {
|
||||||
localStorage.setItem(GROUP_ID_KEY, groupId);
|
localStorage.setItem(GROUP_ID_KEY, groupId);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从localStorage获取authToken
|
* Get authToken with URL fallback
|
||||||
*/
|
*/
|
||||||
export const getAuthToken = (): string | null => {
|
export const getAuthToken = (): string | null => {
|
||||||
const tokenFromUrl = getAuthTokenFromUrl();
|
const tokenFromUrl = getAuthTokenFromUrl();
|
||||||
@@ -41,7 +41,7 @@ export const getAuthToken = (): string | null => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从localStorage获取groupId
|
* Get groupId with URL fallback
|
||||||
*/
|
*/
|
||||||
export const getGroupId = (): string | null => {
|
export const getGroupId = (): string | null => {
|
||||||
const groupIdFromUrl = getGroupIdFromUrl();
|
const groupIdFromUrl = getGroupIdFromUrl();
|
||||||
@@ -49,22 +49,21 @@ export const getGroupId = (): string | null => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除authToken
|
* Clear authToken
|
||||||
*/
|
*/
|
||||||
export const clearAuthToken = (): void => {
|
export const clearAuthToken = (): void => {
|
||||||
localStorage.removeItem(AUTH_TOKEN_KEY);
|
localStorage.removeItem(AUTH_TOKEN_KEY);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除groupId
|
* Clear groupId
|
||||||
*/
|
*/
|
||||||
export const clearGroupId = (): void => {
|
export const clearGroupId = (): void => {
|
||||||
localStorage.removeItem(GROUP_ID_KEY);
|
localStorage.removeItem(GROUP_ID_KEY);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查并处理URL中的authToken
|
* Consume authToken/groupId from URL and persist, then clean URL
|
||||||
* 如果URL中有authToken参数,则保存到localStorage并从URL中移除
|
|
||||||
*/
|
*/
|
||||||
export const handleAuthTokenAndGroupIdFromUrl = (): void => {
|
export const handleAuthTokenAndGroupIdFromUrl = (): void => {
|
||||||
const tokenFromUrl = getAuthTokenFromUrl();
|
const tokenFromUrl = getAuthTokenFromUrl();
|
||||||
@@ -80,7 +79,7 @@ export const handleAuthTokenAndGroupIdFromUrl = (): void => {
|
|||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean URL if we consumed any param
|
// Clean URL if any param was consumed
|
||||||
if (updated) {
|
if (updated) {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
url.searchParams.delete('authToken');
|
url.searchParams.delete('authToken');
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ export const getGroupMembers = async (groupId: number, token: string): Promise<U
|
|||||||
@Tags('Chat Group')
|
@Tags('Chat Group')
|
||||||
export class GroupController extends Controller {
|
export class GroupController extends Controller {
|
||||||
/**
|
/**
|
||||||
* 获取当前聊天群组的全部用户信息
|
* Get all users in the current chat group
|
||||||
* @summary 获取当前聊天群组的全部用户信息
|
* @summary Get group members
|
||||||
* @description 获取当前聊天群组的全部用户信息
|
* @description Returns the full member list of the current chat group
|
||||||
*/
|
*/
|
||||||
@Get('/members')
|
@Get('/members')
|
||||||
@Security("jwt")
|
@Security("jwt")
|
||||||
@@ -65,4 +65,4 @@ export class GroupController extends Controller {
|
|||||||
data: users,
|
data: users,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import type { ApiResponse } from '../types/api';
|
|||||||
@Tags('Test')
|
@Tags('Test')
|
||||||
export class TestController extends Controller {
|
export class TestController extends Controller {
|
||||||
/**
|
/**
|
||||||
* 测试接口
|
* Test endpoint
|
||||||
* @summary 测试接口
|
* @summary Test endpoint
|
||||||
* @description 用于测试API连通性的基础接口
|
* @description Basic endpoint to verify API connectivity
|
||||||
*/
|
*/
|
||||||
@Get('/test')
|
@Get('/test')
|
||||||
@Response<ApiResponse>(200, 'Success')
|
@Response<ApiResponse>(200, 'Success')
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import type {UserInfo} from "../types/user";
|
|||||||
@Tags('User')
|
@Tags('User')
|
||||||
export class UserController extends Controller {
|
export class UserController extends Controller {
|
||||||
/**
|
/**
|
||||||
* 获取当前用户的信息
|
* Get current user information
|
||||||
* @summary 获取当前用户的信息
|
* @summary Get current user information
|
||||||
* @description 获取当前用户的信息
|
* @description Returns the authenticated user's profile
|
||||||
*/
|
*/
|
||||||
@Get('/info')
|
@Get('/info')
|
||||||
@Security('jwt')
|
@Security('jwt')
|
||||||
@@ -24,4 +24,4 @@ export class UserController extends Controller {
|
|||||||
data: rest
|
data: rest
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ dotenv.config({ path: path.resolve(__dirname, "../../../.env") });
|
|||||||
import "./database";
|
import "./database";
|
||||||
import { sequelize } from "./database/instance";
|
import { sequelize } from "./database/instance";
|
||||||
import {errorHandler} from "./middleware/errorHandler";
|
import {errorHandler} from "./middleware/errorHandler";
|
||||||
import {RegisterTsoaRoutes} from "./middleware/tsoa.middleware"; // tsoa 生成的
|
import {RegisterTsoaRoutes} from "./middleware/tsoa.middleware";
|
||||||
|
|
||||||
const port = process.env.PORT || 3005;
|
const port = process.env.PORT || 3005;
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export async function expressAuthentication(
|
|||||||
throw new ApiError(401, "Unauthorized");
|
throw new ApiError(401, "Unauthorized");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回的对象会挂到 request.user 上
|
// Returned object is assigned to request.user
|
||||||
return await getUserInfoByToken(token);
|
return await getUserInfoByToken(token);
|
||||||
}
|
}
|
||||||
throw new ApiError(401, "Unsupported security scheme");
|
throw new ApiError(401, "Unsupported security scheme");
|
||||||
@@ -45,7 +45,7 @@ export const getUserInfoByToken = async (token: string): Promise<UserInfo> => {
|
|||||||
try {
|
try {
|
||||||
const response = await axios.post<ApiResponse<Omit<UserInfo, 'token'>>>(
|
const response = await axios.post<ApiResponse<Omit<UserInfo, 'token'>>>(
|
||||||
"https://egret.byteawake.com/api/user/info",
|
"https://egret.byteawake.com/api/user/info",
|
||||||
{}, // 请求体数据,这里为空对象
|
{}, // Empty request body
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
@@ -74,4 +74,3 @@ export const getUserInfoByToken = async (token: string): Promise<UserInfo> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function errorHandler(err: any, req: Request, res: Response, next: NextFu
|
|||||||
return res.status(err.status).json({code: err.status, message: err.message, data: null});
|
return res.status(err.status).json({code: err.status, message: err.message, data: null});
|
||||||
}
|
}
|
||||||
|
|
||||||
// tsoa 内部生成的验证错误
|
// Validation errors generated by tsoa
|
||||||
if (err.status && err.status >= 400) {
|
if (err.status && err.status >= 400) {
|
||||||
return res.status(err.status).json({ message: err.message });
|
return res.status(err.status).json({ message: err.message });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import swaggerUi from 'swagger-ui-express';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
export function RegisterTsoaRoutes(app: any) {
|
export function RegisterTsoaRoutes(app: any) {
|
||||||
// Register tsoa routes - 动态导入以避免编译时错误
|
// Register tsoa routes via dynamic import to avoid compile-time errors
|
||||||
const { RegisterRoutes } = require('../routes/routes');
|
const { RegisterRoutes } = require('../routes/routes');
|
||||||
RegisterRoutes(app);
|
RegisterRoutes(app);
|
||||||
|
|
||||||
// Serve swagger documentation - 动态导入swagger文档
|
// Serve swagger documentation (dynamic import)
|
||||||
const swaggerDocument = require(path.join(__dirname, '../swagger.json'));
|
const swaggerDocument = require(path.join(__dirname, '../swagger.json'));
|
||||||
app.use('/v3/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
|
app.use('/v3/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user