refactor(api): streamline imports and enhance type definitions across multiple files

This commit is contained in:
shiyu
2025-06-07 15:58:25 +08:00
parent 8127d1f570
commit 4e66cbf563
28 changed files with 498 additions and 610 deletions

View File

@@ -1,13 +1,42 @@
import type {
PaginatedResult,
AlbumResponse,
CreateAlbumRequest,
UpdateAlbumRequest,
AlbumPictureRequest,
AlbumPicturesRequest,
BaseResult
} from './types';
import { fetchApi, BASE_URL } from './fetchClient';
import { fetchApi, type PaginatedResult, type BaseResult } from './fetchClient';
// 相册响应数据
export interface AlbumResponse {
id: number;
name: string;
description: string;
coverImageUrl?: string;
pictureCount: number;
userId: number;
username?: string;
createdAt: Date;
updatedAt: Date;
}
// 创建相册请求
export interface CreateAlbumRequest {
name: string;
description: string;
}
// 更新相册请求
export interface UpdateAlbumRequest {
id: number;
name: string;
description: string;
}
// 相册图片操作请求
export interface AlbumPictureRequest {
albumId: number;
pictureId: number;
}
// 批量添加图片到相册请求
export interface AlbumPicturesRequest {
albumId: number;
pictureIds: number[];
}
// 获取相册列表
export async function getAlbums(
@@ -16,14 +45,6 @@ export async function getAlbums(
userId?: number
): Promise<PaginatedResult<AlbumResponse>> {
try {
const token = localStorage.getItem('token');
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const queryParams = new URLSearchParams();
queryParams.append('page', page.toString());
queryParams.append('pageSize', pageSize.toString());
@@ -31,19 +52,31 @@ export async function getAlbums(
queryParams.append('userId', userId.toString());
}
const url = `${BASE_URL}/album/get_albums?${queryParams.toString()}`;
const response = await fetch(url, { headers });
const data = await response.json();
return data as PaginatedResult<AlbumResponse>;
const url = `/album/get_albums?${queryParams.toString()}`;
const result = await fetchApi<PaginatedResult<AlbumResponse>>(url);
if (result.success) {
return result as unknown as PaginatedResult<AlbumResponse>;
} else {
console.error('获取相册列表失败:', result.message);
return {
success: false,
message: result.message || '获取相册列表失败',
data: [],
page: page,
pageSize: pageSize,
totalCount: 0,
totalPages: 0,
code: result.code || 500,
};
}
} catch (error) {
console.error('获取相册列表失败:', error);
console.error('获取相册列表时发生意外错误:', error);
return {
success: false,
message: '网络请求失败,请检查您的网络连接',
data: [],
page: 1,
pageSize: 10,
page: page,
pageSize: pageSize,
totalCount: 0,
totalPages: 0,
code: 500,

View File

@@ -1,10 +1,58 @@
import {type BaseResult, type AuthResponse, type LoginRequest, type RegisterRequest, type UserProfile, type UpdateUserRequest, type BindAccountRequest} from './types';
import {fetchApi, BASE_URL} from './fetchClient';
import {fetchApi, BASE_URL, type BaseResult} from './fetchClient';
import { type UserRole } from './userManagementApi';
// 认证数据本地存储键
const TOKEN_KEY = 'token';
const USER_KEY = 'user';
// 登录请求参数
export interface LoginRequest {
email: string;
password: string;
}
// 注册请求参数
export interface RegisterRequest {
username: string;
email: string;
password: string;
}
// 用户信息
export interface UserProfile {
id: number;
userName: string;
email: string;
roleName: UserRole | string; // roleName can be UserRole or a string from server
}
// 认证响应
export interface AuthResponse {
token: string;
user: UserProfile;
}
export interface UpdateUserRequest {
userName?: string;
email?: string;
currentPassword?: string;
newPassword?: string;
}
export type BindType = 0 | 1;
export const BindType = {
GitHub: 0 as BindType,
LinuxDo: 1 as BindType,
};
export interface BindAccountRequest {
email: string;
password: string;
bindType: BindType;
thirdPartyUserId: string;
}
// 用户注册
export async function register(data: RegisterRequest): Promise<BaseResult<AuthResponse>> {
return fetchApi<AuthResponse>('/auth/register', {

View File

@@ -1,5 +1,17 @@
import { fetchApi } from './fetchClient';
import type { BaseResult, PictureProcessingTask } from './types';
import { fetchApi, type BaseResult } from './fetchClient';
import type { ProcessingStatus } from './pictureApi';
// 图片处理任务
export interface PictureProcessingTask {
pictureId: number;
taskId: string;
pictureName: string;
status: ProcessingStatus;
progress: number; // 0-100
error?: string;
createdAt: Date;
completedAt?: Date;
}
/**
* 获取当前用户的所有处理任务

View File

@@ -1,5 +1,23 @@
import { UserRole, type BaseResult, type ConfigResponse, type SetConfigRequest } from './types';
import { fetchApi } from './fetchClient';
import { fetchApi, type BaseResult } from './fetchClient';
import { UserRole } from './userManagementApi';
// 配置响应数据
export interface ConfigResponse {
id: number;
key: string;
value: string;
description: string;
isSecret: boolean;
createdAt: Date;
updatedAt?: Date;
}
export interface SetConfigRequest {
key: string;
value: string;
description?: string;
}
// 获取所有配置
export const getAllConfigs = async (): Promise<BaseResult<ConfigResponse[]>> => {

View File

@@ -1,5 +1,25 @@
import type { BaseResult } from './types';
import { clearAuthData } from './index';
// API响应的基础结构
export interface BaseResult<T> {
success: boolean;
message: string;
data?: T;
code: number;
}
// 分页结果通用结构
export interface PaginatedResult<T> {
success: boolean;
message: string;
data: T[];
page: number;
pageSize: number;
totalCount: number;
totalPages: number;
code: number;
}
export const BASE_URL = import.meta.env.PROD ? '/api' : 'http://localhost:5153/api';
export async function fetchApi<T = any>(

View File

@@ -1,100 +1,11 @@
// 重新导出类型
export * from './authApi';
export * from './types';
// 导出fetch客户端
export { fetchApi, BASE_URL } from './fetchClient';
// 导出Auth API
export {
register,
login,
getCurrentUser,
updateUserInfo,
saveAuthData,
clearAuthData,
isAuthenticated,
getStoredUser,
bindAccount,
getGitHubLoginUrl,
getLinuxDoLoginUrl
} from './authApi';
// 导出Picture API
export {
getPictures,
favoritePicture,
unfavoritePicture,
getUserFavorites,
uploadPicture,
deleteMultiplePictures,
updatePicture,
} from './pictureApi';
// 导出Album API
export {
getAlbums,
getAlbumById,
createAlbum,
updateAlbum,
deleteAlbum,
addPictureToAlbum,
addPicturesToAlbum,
removePictureFromAlbum
} from './albumApi';
// 导出BackgroundTask API
export {
getUserTasks,
getPictureProcessingStatus,
} from './backgroundTaskApi';
// 导出Config API
export {
getAllConfigs,
getConfig,
setConfig,
deleteConfig,
hasRole,
backupConfigs,
restoreConfigs
} from './configApi';
// 导出UserManagement API
export {
getUsers,
getUserById,
createUser,
updateUser,
deleteUser,
batchDeleteUsers,
getUserDetail
} from './userManagementApi';
// 导出PictureManagement API
export {
getManagementPictures,
getManagementPictureById,
deleteManagementPicture,
batchDeleteManagementPictures,
getManagementPicturesByUserId
} from './pictureManagementApi';
// 导出向量数据库 API
export {
getCurrentVectorDb,
switchVectorDb,
clearVectors,
rebuildVectors
} from './vectorDbApi';
// 导出LogManagement API
export {
getLogs,
getLogById,
deleteLog,
batchDeleteLogs,
clearLogs,
getLogStatistics
} from './logManagementApi';
export * from './albumApi';
export * from './backgroundTaskApi';
export * from './configApi';
export * from './fetchClient';
export * from './logManagementApi';
export * from './pictureApi';
export * from './pictureManagementApi';
export * from './tagApi';
export * from './userManagementApi';
export * from './vectorDbApi';

View File

@@ -1,13 +1,60 @@
import { fetchApi } from './fetchClient';
import {
type BaseResult,
type PaginatedResult,
type LogResponse,
type LogFilterRequest,
type ClearLogsRequest,
type BatchDeleteResult,
type LogStatistics
} from './types';
import { fetchApi, type BaseResult, type PaginatedResult } from './fetchClient';
import { type BatchDeleteResult } from './userManagementApi';
// 日志级别枚举
export type LogLevel = 'Trace' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Critical';
export const LogLevel = {
Trace: 'Trace' as LogLevel,
Debug: 'Debug' as LogLevel,
Information: 'Information' as LogLevel,
Warning: 'Warning' as LogLevel,
Error: 'Error' as LogLevel,
Critical: 'Critical' as LogLevel
};
// 日志响应数据
export interface LogResponse {
id: number;
level: LogLevel | number; // 支持数字和字符串两种形式
message: string;
category: string;
eventId?: number;
timestamp: Date;
exception?: string;
requestPath?: string;
requestMethod?: string;
statusCode?: number;
ipAddress?: string;
userId?: string;
properties?: string;
}
// 日志筛选请求参数
export interface LogFilterRequest {
page?: number;
pageSize?: number;
searchQuery?: string;
level?: LogLevel | number; // 支持数字和字符串两种形式
startDate?: string;
endDate?: string;
}
// 清空日志请求
export interface ClearLogsRequest {
clearAll?: boolean;
beforeDate?: Date;
}
// 日志统计信息
export interface LogStatistics {
totalCount: number;
todayCount: number;
errorCount: number;
warningCount: number;
}
// 获取日志列表
export const getLogs = async (

View File

@@ -1,11 +1,108 @@
import type { PaginatedResult, PictureResponse, FilteredPicturesRequest, BaseResult, UpdatePictureRequest } from './types';
import { fetchApi, BASE_URL } from './fetchClient';
import { fetchApi, BASE_URL, type PaginatedResult, type BaseResult } from './fetchClient';
// 图片请求参数
export interface FilteredPicturesRequest {
page?: number;
pageSize?: number;
searchQuery?: string;
tags?: string;
startDate?: string;
endDate?: string;
userId?: number;
sortBy?: string;
onlyWithGps?: boolean;
useVectorSearch?: boolean;
similarityThreshold?: number;
excludeAlbumId?: number;
albumId?: number;
onlyFavorites?: boolean;
ownerId?: number;
includeAllPublic?: boolean;
}
// 将类型定义改为枚举,这样既可以作为类型也可以作为值使用
export type ProcessingStatus = 'Pending' | 'Processing' | 'Completed' | 'Failed';
// 添加常量对象提供运行时值
export const ProcessingStatus = {
Pending: 'Pending' as ProcessingStatus,
Processing: 'Processing' as ProcessingStatus,
Completed: 'Completed' as ProcessingStatus,
Failed: 'Failed' as ProcessingStatus
};
// 图片响应数据
export interface PictureResponse {
id: number;
name: string;
path: string;
thumbnailPath: string;
description: string;
takenAt?: Date;
createdAt: Date;
exifInfo?: any;
tags?: string[];
userId: number;
username?: string;
isFavorited: boolean;
favoriteCount: number;
permission: number;
albumId?: number;
albumName?: string;
processingStatus: ProcessingStatus;
processingError?: string;
processingProgress: number;
}
// 收藏请求
export interface FavoriteRequest {
pictureId: number;
}
// 上传队列中的文件项
export interface UploadFile {
id: string; // 本地ID用于跟踪状态
file: File; // 原始文件
status: 'pending' | 'uploading' | 'success' | 'error'; // 上传状态
percent: number; // 上传进度百分比 0-100
error?: string; // 错误信息
response?: PictureResponse; // 上传成功后的响应
}
// 图片格式类型
export type ImageFormat = 0 | 1 | 2 | 3;
// 添加常量对象提供运行时值
export const ImageFormat = {
Original: 0 as ImageFormat,
Jpeg: 1 as ImageFormat,
Png: 2 as ImageFormat,
WebP: 3 as ImageFormat
};
// 上传图片参数
export interface UploadPictureParams {
permission?: number;
albumId?: number;
convertToFormat?: ImageFormat;
quality?: number;
onProgress?: (percent: number) => void;
}
// 删除多张图片请求
export interface DeleteMultiplePicturesRequest {
pictureIds: number[];
}
export interface UpdatePictureRequest {
id: number;
name?: string;
description?: string;
tags?: string[];
}
// 获取图片列表
export async function getPictures(params: FilteredPicturesRequest = {}): Promise<PaginatedResult<PictureResponse>> {
// 添加调试日志
console.log("Search API 请求参数:", params);
// 构建查询参数
const queryParams = new URLSearchParams();
@@ -27,38 +124,34 @@ export async function getPictures(params: FilteredPicturesRequest = {}): Promise
if (params.ownerId !== undefined) queryParams.append('ownerId', params.ownerId.toString());
if (params.includeAllPublic !== undefined) queryParams.append('includeAllPublic', params.includeAllPublic.toString());
// 最终URL调试日志
const url = `${BASE_URL}/picture/get_pictures?${queryParams.toString()}`;
console.log("发送API请求:", url);
const url = `/picture/get_pictures?${queryParams.toString()}`;
try {
const token = localStorage.getItem('token');
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
const result = await fetchApi<PaginatedResult<PictureResponse>>(url);
if (result.success) {
return result as unknown as PaginatedResult<PictureResponse>;
} else {
console.error('获取图片列表失败:', result.message);
return {
success: false,
message: result.message || '获取图片列表失败',
data: [],
page: params.page || 1,
pageSize: params.pageSize || 10,
totalCount: 0,
totalPages: 0,
code: result.code || 500,
};
}
const response = await fetch(url, { headers });
const data = await response.json();
// 添加结果日志
console.log("API 响应结果:", {
success: data.success,
totalCount: data.totalCount,
resultsCount: data.data?.length || 0
});
return data as PaginatedResult<PictureResponse>;
} catch (error) {
console.error('获取图片列表失败:', error);
console.error('获取图片列表时发生意外错误:', error);
return {
success: false,
message: '网络请求失败,请检查您的网络连接',
data: [],
page: 1,
pageSize: 10,
page: params.page || 1,
pageSize: params.pageSize || 10,
totalCount: 0,
totalPages: 0,
code: 500,
@@ -85,27 +178,33 @@ export async function unfavoritePicture(pictureId: number): Promise<BaseResult<b
// 获取用户收藏的图片
export async function getUserFavorites(page: number = 1, pageSize: number = 8): Promise<PaginatedResult<PictureResponse>> {
try {
const token = localStorage.getItem('token');
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
const url = `/picture/favorites?page=${page}&pageSize=${pageSize}`;
// 使用 fetchApi 替换原生 fetch
const result = await fetchApi<PaginatedResult<PictureResponse>>(url);
if (result.success) {
return result as unknown as PaginatedResult<PictureResponse>;
} else {
console.error('获取收藏图片失败:', result.message);
return {
success: false,
message: result.message || '获取收藏图片失败',
data: [],
page: page,
pageSize: pageSize,
totalCount: 0,
totalPages: 0,
code: result.code || 500,
};
}
const url = `${BASE_URL}/picture/favorites?page=${page}&pageSize=${pageSize}`;
const response = await fetch(url, { headers });
const data = await response.json();
return data as PaginatedResult<PictureResponse>;
} catch (error) {
console.error('获取收藏图片失败:', error);
console.error('获取收藏图片时发生意外错误:', error);
return {
success: false,
message: '网络请求失败,请检查您的网络连接',
data: [],
page: 1,
pageSize: 10,
page: page,
pageSize: pageSize,
totalCount: 0,
totalPages: 0,
code: 500,

View File

@@ -1,10 +1,7 @@
import { fetchApi } from './fetchClient';
import {
type BaseResult,
type PaginatedResult,
type PictureResponse,
type BatchDeleteResult
} from './types';
import { fetchApi, type BaseResult, type PaginatedResult } from './fetchClient';
import { type PictureResponse } from './pictureApi';
import { type BatchDeleteResult } from './userManagementApi';
// 获取图片列表
export const getManagementPictures = async (

View File

@@ -1,5 +1,4 @@
import type { BaseResult, PaginatedResult } from './types';
import { fetchApi, BASE_URL } from './fetchClient';
import { fetchApi, type BaseResult, type PaginatedResult } from './fetchClient';
// 标签响应类型
export interface TagResponse {
@@ -50,28 +49,31 @@ export async function getFilteredTags(params: FilteredTagsRequest = {}): Promise
if (params.sortDirection) queryParams.append('sortDirection', params.sortDirection);
try {
const token = localStorage.getItem('token');
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
const url = `/tag/get_tags?${queryParams.toString()}`;
const result = await fetchApi<PaginatedResult<TagResponse>>(url);
if (result.success) {
return result as unknown as PaginatedResult<TagResponse>;
} else {
console.error('获取标签列表失败:', result.message);
return {
success: false,
message: result.message || '获取标签列表失败',
data: [],
page: params.page || 1,
pageSize: params.pageSize || 10,
totalCount: 0,
totalPages: 0,
code: result.code || 500,
};
}
const url = `${BASE_URL}/tag/get_tags?${queryParams.toString()}`;
const response = await fetch(url, { headers });
const data = await response.json();
return data as PaginatedResult<TagResponse>;
} catch (error) {
console.error('获取标签列表失败:', error);
console.error('获取标签列表时发生意外错误:', error);
return {
success: false,
message: '网络请求失败,请检查您的网络连接',
data: [],
page: 1,
pageSize: 10,
page: params.page || 1,
pageSize: params.pageSize || 10,
totalCount: 0,
totalPages: 0,
code: 500,

View File

@@ -1,370 +0,0 @@
// API响应的基础结构
export interface BaseResult<T> {
success: boolean;
message: string;
data?: T;
code: number;
}
// 分页结果通用结构
export interface PaginatedResult<T> {
success: boolean;
message: string;
data: T[];
page: number;
pageSize: number;
totalCount: number;
totalPages: number;
code: number;
}
// 登录请求参数
export interface LoginRequest {
email: string;
password: string;
}
// 注册请求参数
export interface RegisterRequest {
username: string;
email: string;
password: string;
}
// 用户信息
export interface UserProfile {
id: number;
userName: string;
email: string;
roleName: string;
}
// 认证响应
export interface AuthResponse {
token: string;
user: UserProfile;
}
// 图片请求参数
export interface FilteredPicturesRequest {
page?: number;
pageSize?: number;
searchQuery?: string;
tags?: string;
startDate?: string;
endDate?: string;
userId?: number;
sortBy?: string;
onlyWithGps?: boolean;
useVectorSearch?: boolean;
similarityThreshold?: number;
excludeAlbumId?: number;
albumId?: number;
onlyFavorites?: boolean;
ownerId?: number;
includeAllPublic?: boolean;
}
// 图片响应数据
export interface PictureResponse {
id: number;
name: string;
path: string;
thumbnailPath: string;
description: string;
takenAt?: Date;
createdAt: Date;
exifInfo?: any;
tags?: string[];
userId: number;
username?: string;
isFavorited: boolean;
favoriteCount: number;
permission: number;
albumId?: number;
albumName?: string;
processingStatus: ProcessingStatus;
processingError?: string;
processingProgress: number;
}
// 收藏请求
export interface FavoriteRequest {
pictureId: number;
}
// 上传队列中的文件项
export interface UploadFile {
id: string; // 本地ID用于跟踪状态
file: File; // 原始文件
status: 'pending' | 'uploading' | 'success' | 'error'; // 上传状态
percent: number; // 上传进度百分比 0-100
error?: string; // 错误信息
response?: PictureResponse; // 上传成功后的响应
}
// 图片格式类型
export type ImageFormat = 0 | 1 | 2 | 3;
// 添加常量对象提供运行时值
export const ImageFormat = {
Original: 0 as ImageFormat,
Jpeg: 1 as ImageFormat,
Png: 2 as ImageFormat,
WebP: 3 as ImageFormat
};
// 上传图片参数
export interface UploadPictureParams {
permission?: number;
albumId?: number;
convertToFormat?: ImageFormat;
quality?: number;
onProgress?: (percent: number) => void;
}
// 相册响应数据
export interface AlbumResponse {
id: number;
name: string;
description: string;
coverImageUrl?: string;
pictureCount: number;
userId: number;
username?: string;
createdAt: Date;
updatedAt: Date;
}
// 创建相册请求
export interface CreateAlbumRequest {
name: string;
description: string;
}
// 更新相册请求
export interface UpdateAlbumRequest {
id: number;
name: string;
description: string;
}
// 相册图片操作请求
export interface AlbumPictureRequest {
albumId: number;
pictureId: number;
}
// 批量添加图片到相册请求
export interface AlbumPicturesRequest {
albumId: number;
pictureIds: number[];
}
// 删除多张图片请求
export interface DeleteMultiplePicturesRequest {
pictureIds: number[];
}
// 将类型定义改为枚举,这样既可以作为类型也可以作为值使用
export type ProcessingStatus = 'Pending' | 'Processing' | 'Completed' | 'Failed';
// 添加常量对象提供运行时值
export const ProcessingStatus = {
Pending: 'Pending' as ProcessingStatus,
Processing: 'Processing' as ProcessingStatus,
Completed: 'Completed' as ProcessingStatus,
Failed: 'Failed' as ProcessingStatus
};
// 图片处理任务
export interface PictureProcessingTask {
pictureId: number;
taskId: string;
pictureName: string;
status: ProcessingStatus;
progress: number; // 0-100
error?: string;
createdAt: Date;
completedAt?: Date;
}
// 配置响应数据
export interface ConfigResponse {
id: number;
key: string;
value: string;
description: string;
isSecret: boolean;
createdAt: Date;
updatedAt?: Date;
}
export interface SetConfigRequest {
key: string;
value: string;
description?: string;
}
export type UserRole = "Administrator" | "User" | "";
export const UserRole = {
Administrator: "Administrator" as UserRole,
User: "User" as UserRole,
Guest: "" as UserRole
};
export interface UpdateUserRequest {
userName?: string;
email?: string;
currentPassword?: string;
newPassword?: string;
}
export interface UpdatePictureRequest {
id: number;
name?: string;
description?: string;
tags?: string[];
}
// 用户管理相关类型
export interface UserResponse {
id: number;
userName: string;
email: string;
role: string;
createdAt: Date;
lastLoginAt?: Date;
}
// 管理员创建用户请求
export interface CreateUserRequest {
userName: string;
email: string;
password: string;
role: string;
}
// 管理员更新用户请求
export interface AdminUpdateUserRequest {
id: number;
userName?: string;
email?: string;
role?: string;
}
// 批量删除结果
export interface BatchDeleteResult {
successCount: number;
failedCount: number;
failedIds?: number[];
}
export type VectorDbType = "InMemory" | "Qdrant";
export const VectorDbType = {
InMemory: "InMemory" as VectorDbType,
Qdrant: "Qdrant" as VectorDbType,
};
export interface VectorDbInfo {
type: string;
}
export type BindType = 0 | 1;
export const BindType = {
GitHub: 0 as BindType,
LinuxDo: 1 as BindType,
};
export interface BindAccountRequest {
email: string;
password: string;
bindType: BindType;
thirdPartyUserId: string;
}
// 用户筛选请求参数
export interface UserFilterRequest {
page?: number;
pageSize?: number;
searchQuery?: string;
role?: string;
startDate?: string;
endDate?: string;
}
// 用户统计信息
export interface UserStatistics {
totalPictures: number;
totalAlbums: number;
totalFavorites: number;
favoriteReceivedCount: number;
diskUsageMB: number;
accountAgeDays: number;
}
// 用户详情响应
export interface UserDetailResponse {
id: number;
userName: string;
email: string;
role: string;
createdAt: Date;
statistics: UserStatistics;
}
// 日志级别枚举
export type LogLevel = 'Trace' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Critical';
export const LogLevel = {
Trace: 'Trace' as LogLevel,
Debug: 'Debug' as LogLevel,
Information: 'Information' as LogLevel,
Warning: 'Warning' as LogLevel,
Error: 'Error' as LogLevel,
Critical: 'Critical' as LogLevel
};
// 日志响应数据
export interface LogResponse {
id: number;
level: LogLevel | number; // 支持数字和字符串两种形式
message: string;
category: string;
eventId?: number;
timestamp: Date;
exception?: string;
requestPath?: string;
requestMethod?: string;
statusCode?: number;
ipAddress?: string;
userId?: string;
properties?: string;
}
// 日志筛选请求参数
export interface LogFilterRequest {
page?: number;
pageSize?: number;
searchQuery?: string;
level?: LogLevel | number; // 支持数字和字符串两种形式
startDate?: string;
endDate?: string;
}
// 清空日志请求
export interface ClearLogsRequest {
clearAll?: boolean;
beforeDate?: Date;
}
// 日志统计信息
export interface LogStatistics {
totalCount: number;
todayCount: number;
errorCount: number;
warningCount: number;
}

View File

@@ -1,14 +1,75 @@
import { fetchApi } from './fetchClient';
import {
type BaseResult,
type PaginatedResult,
type UserResponse,
type CreateUserRequest,
type AdminUpdateUserRequest,
type BatchDeleteResult,
type UserFilterRequest,
type UserDetailResponse
} from './types';
import { fetchApi, type BaseResult, type PaginatedResult } from './fetchClient';
export type UserRole = "Administrator" | "User" | "";
export const UserRole = {
Administrator: "Administrator" as UserRole,
User: "User" as UserRole,
Guest: "" as UserRole
};
// 用户管理相关类型
export interface UserResponse {
id: number;
userName: string;
email: string;
role: string;
createdAt: Date;
lastLoginAt?: Date;
}
// 管理员创建用户请求
export interface CreateUserRequest {
userName: string;
email: string;
password: string;
role: string;
}
// 管理员更新用户请求
export interface AdminUpdateUserRequest {
id: number;
userName?: string;
email?: string;
role?: string;
}
// 批量删除结果
export interface BatchDeleteResult {
successCount: number;
failedCount: number;
failedIds?: number[];
}
// 用户筛选请求参数
export interface UserFilterRequest {
page?: number;
pageSize?: number;
searchQuery?: string;
role?: string;
startDate?: string;
endDate?: string;
}
// 用户统计信息
export interface UserStatistics {
totalPictures: number;
totalAlbums: number;
totalFavorites: number;
favoriteReceivedCount: number;
diskUsageMB: number;
accountAgeDays: number;
}
// 用户详情响应
export interface UserDetailResponse {
id: number;
userName: string;
email: string;
role: string;
createdAt: Date;
statistics: UserStatistics;
}
// 获取用户列表
export const getUsers = async (

View File

@@ -1,5 +1,15 @@
import { type BaseResult, type VectorDbInfo, VectorDbType } from './types';
import { fetchApi } from './fetchClient';
import { fetchApi, type BaseResult } from './fetchClient';
export type VectorDbType = "InMemory" | "Qdrant";
export const VectorDbType = {
InMemory: "InMemory" as VectorDbType,
Qdrant: "Qdrant" as VectorDbType,
};
export interface VectorDbInfo {
type: string;
}
// 获取当前向量数据库类型
export const getCurrentVectorDb = async (): Promise<BaseResult<VectorDbInfo>> => {

View File

@@ -1,7 +1,7 @@
import React, { createContext, useState, useEffect, useContext, useCallback } from 'react';
import { getCurrentUser, isAuthenticated, clearAuthData, getStoredUser } from '../api/index';
import type { UserProfile } from '../api/types';
import { UserRole } from '../api/types';
import type { UserProfile } from '../api';
import { UserRole } from '../api';
interface AuthContextType {
user: UserProfile | null;

View File

@@ -6,7 +6,7 @@ import {
CheckCircleOutlined,
CloseCircleOutlined
} from '@ant-design/icons';
import { ProcessingStatus } from '../api/types';
import { ProcessingStatus } from '../api';
interface TaskProgressBarProps {
status: ProcessingStatus;

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { Divider } from 'antd';
import { CloseOutlined, DownOutlined, UpOutlined } from '@ant-design/icons';
import type { PictureResponse } from '../../api/types';
import type { PictureResponse } from '../../api';
import './ImageViewer.css';
interface ImageInfoProps {

View File

@@ -6,7 +6,7 @@ import {
RotateRightOutlined, HeartOutlined, HeartFilled, DownloadOutlined,
ShareAltOutlined, FolderAddOutlined
} from '@ant-design/icons';
import type { PictureResponse, AlbumResponse } from '../../api/types';
import type { PictureResponse, AlbumResponse } from '../../api';
import { getAlbums, addPicturesToAlbum, favoritePicture, unfavoritePicture } from '../../api';
import ImageInfo from './ImageInfo';
import ShareImageDialog from './ShareImageDialog';

View File

@@ -1,7 +1,7 @@
import React, { useState, useRef } from 'react';
import { Modal, Tabs, Input, Button, message, Radio, Space, Typography } from 'antd';
import { CopyOutlined, CheckOutlined } from '@ant-design/icons';
import type { PictureResponse } from '../../api/types';
import type { PictureResponse } from '../../api';
import './ShareImageDialog.css';
const { Text } = Typography;

View File

@@ -7,7 +7,7 @@ import { useAuth } from '../auth/AuthContext';
import Sidebar from './components/Sidebar';
import Header from './components/Header';
import Footer from './components/Footer';
import { UserRole } from '../api/types';
import { UserRole } from '../api';
import { getAdminRoutes, type RouteConfig } from '../routes';
const { Content } = Layout;

View File

@@ -12,7 +12,7 @@ import type { ColumnsType } from 'antd/es/table';
import { useOutletContext } from 'react-router';
import { useNavigate } from 'react-router';
import { getUsers, getManagementPictures } from '../../../api';
import type { UserResponse, PictureResponse } from '../../../api/types';
import type { UserResponse, PictureResponse } from '../../../api';
const { Title, Text } = Typography;

View File

@@ -38,7 +38,7 @@ import {useOutletContext} from 'react-router';
import dayjs from 'dayjs';
import type {Dayjs} from 'dayjs';
import {getLogs, deleteLog, batchDeleteLogs, clearLogs, getLogById, getLogStatistics} from '../../../api';
import type {LogResponse, LogLevel, LogFilterRequest, LogStatistics} from '../../../api/types';
import type {LogResponse, LogLevel, LogFilterRequest, LogStatistics} from '../../../api';
const {Title, Text, Paragraph} = Typography;
const {RangePicker} = DatePicker;

View File

@@ -13,7 +13,7 @@ import {
getManagementPictures, deleteManagementPicture, batchDeleteManagementPictures,
getUsers
} from '../../../api';
import type { PictureResponse } from '../../../api/types';
import type { PictureResponse } from '../../../api';
import { useOutletContext } from 'react-router';
import type { Breakpoint } from 'antd';

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { Card, Radio, Button, message, Spin, Space, Typography, notification, Form, Input, Modal } from 'antd';
import { DatabaseOutlined, SyncOutlined, CheckCircleOutlined, InfoCircleOutlined, SaveOutlined, DeleteOutlined, ReloadOutlined } from '@ant-design/icons';
import { getCurrentVectorDb, switchVectorDb, setConfig, clearVectors, rebuildVectors } from '../../../api';
import { VectorDbType } from '../../../api/types';
import { VectorDbType } from '../../../api';
const { Title, Paragraph } = Typography;

View File

@@ -13,7 +13,7 @@ import {
import {
getUsers, deleteUser, createUser, updateUser, batchDeleteUsers, UserRole
} from '../../../api';
import type { UserResponse, CreateUserRequest, AdminUpdateUserRequest, UserFilterRequest } from '../../../api/types';
import type { UserResponse, CreateUserRequest, AdminUpdateUserRequest, UserFilterRequest } from '../../../api';
import { useOutletContext } from 'react-router';
import { useNavigate } from 'react-router';
import type { Breakpoint } from 'antd';

View File

@@ -11,7 +11,7 @@ import {
} from '@ant-design/icons';
import { useParams, useNavigate } from 'react-router';
import { getUserDetail } from '../../../api';
import type { UserDetailResponse } from '../../../api/types';
import type { UserDetailResponse } from '../../../api';
import UserAvatar from '../../../components/UserAvatar';
const { Title, Text } = Typography;

View File

@@ -24,7 +24,7 @@ import { Link } from 'react-router';
import ShareImageDialog from '../../components/image/ShareImageDialog';
import { uploadPicture } from '../../api/pictureApi';
import type { PictureResponse } from '../../api/types';
import type { PictureResponse } from '../../api';
const { Title, Text } = Typography;
const { Dragger } = Upload;

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import { Typography, Table, Card, Tag, Space, Button, Empty, message, Modal } from 'antd';
import { SyncOutlined, EyeOutlined } from '@ant-design/icons';
import { getUserTasks } from '../../api';
import { type PictureProcessingTask, ProcessingStatus } from '../../api/types';
import { type PictureProcessingTask, ProcessingStatus } from '../../api';
import TaskProgressBar from '../../components/TaskProgressBar';
import dayjs from 'dayjs';
import { Link } from 'react-router';

View File

@@ -17,7 +17,7 @@ import {
} from '@ant-design/icons';
import ImageGrid from '../../components/image/ImageGrid/ImageGrid';
import type { PictureResponse } from '../../api/types';
import type { PictureResponse } from '../../api';
import { getFilteredTags } from '../../api/tagApi';
import useIsMobile from '../../hooks/useIsMobile';