feat(auth): implement login and user management features

- Added server-side login action with form handling and cookie storage
- Implemented user authentication service with token management
- Created user list page with data fetching from userService
- Developed reusable DataTable component with selection and pagination
- Enhanced AppSidebar with nested navigation and active state tracking
- Updated icon definitions and sprite symbols for UI consistency
- Improved HTTP client to properly handle request bodies for different methods
- Refactored auth store to manage authentication state and cookies
- Added strict typing for navigation items and table columns
- Removed obsolete code and simplified authentication flow
This commit is contained in:
Chaos
2025-11-24 17:11:41 +08:00
parent 3515faa814
commit ed542f108c
16 changed files with 472 additions and 203 deletions

View File

@@ -61,66 +61,68 @@ export class HttpError extends Error {
}
const httpRequest= async <T>(
url:string,
const httpRequest = async <T>(
url: string,
method: HttpMethod,
options: RequestOptions = {}
):Promise<ApiResult<T>> =>{
): Promise<ApiResult<T>> => {
const fullUrl = `${API_BASE_URL}${url}`;
const { body, headers, ...rest} = options;
const { body, headers, ...rest } = options;
const requestHeaders: Record<string, string> = normalizeHeaders(headers);
let requestBody:BodyInit | undefined;
const requestHeaders: Record<string, string> = normalizeHeaders(headers);
let requestBody: BodyInit | undefined;
if (body instanceof FormData){
requestBody = body;
}else if (body){
requestHeaders['content-type'] = 'application/json';
requestBody = JSON.stringify(body);
const canHaveBody = method !== 'GET' ;
// 【修改点 2】只有在允许携带 Body 时才处理
if (canHaveBody) {
if (body instanceof FormData) {
requestBody = body;
} else if (body) {
requestHeaders['content-type'] = 'application/json';
requestBody = JSON.stringify(body);
}
}
// ... Token 处理逻辑保持不变 ...
if (currentToken && currentTokenHead) {
requestHeaders['authorization'] = `${currentTokenHead} ${currentToken}`;
}
try {
const response = await fetch(fullUrl,{
const response = await fetch(fullUrl, {
method,
headers: requestHeaders,
body: requestBody,
// 【修改点 3】确保 GET 请求的 body 显式为 undefined
// 虽然通常 undefined 是被允许的,但加上 canHaveBody 判断更加严谨
body: canHaveBody ? requestBody : undefined,
...rest
})
});
if (!response.ok) {
let errorDetail;
try {
errorDetail = await response.json()
}catch (e){
errorDetail = await response.json();
} catch (e) {
console.error('Error parsing JSON:', e);
errorDetail = await response.text()
errorDetail = await response.text();
}
const message = `HTTP Error ${response.status} (${response.statusText})`;
throw new HttpError(message, response.status, errorDetail);
}
const contentType = response.headers.get('Content-Type');
if (contentType && contentType.includes('application/json')){
return (await response.json() ) as ApiResult<T>;
if (contentType && contentType.includes('application/json')) {
return (await response.json()) as ApiResult<T>;
}
return {code:200, msg:'OK', data:null} ;
return { code: 200, msg: 'OK', data: null } ; // 这里的 as any 是为了兼容 T 可能是 null 的情况
}catch (error){
} catch (error) {
console.error(`API Request Failed to ${fullUrl}:`, error);
throw error;
}
}
};
export const api = {