mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-08-28 19:46:41 +08:00
refactor(api): streamline imports and enhance type definitions across multiple files
This commit is contained in:
+59
-26
@@ -1,13 +1,42 @@
|
|||||||
import type {
|
import { fetchApi, type PaginatedResult, type BaseResult } from './fetchClient';
|
||||||
PaginatedResult,
|
|
||||||
AlbumResponse,
|
// 相册响应数据
|
||||||
CreateAlbumRequest,
|
export interface AlbumResponse {
|
||||||
UpdateAlbumRequest,
|
id: number;
|
||||||
AlbumPictureRequest,
|
name: string;
|
||||||
AlbumPicturesRequest,
|
description: string;
|
||||||
BaseResult
|
coverImageUrl?: string;
|
||||||
} from './types';
|
pictureCount: number;
|
||||||
import { fetchApi, BASE_URL } from './fetchClient';
|
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(
|
export async function getAlbums(
|
||||||
@@ -16,14 +45,6 @@ export async function getAlbums(
|
|||||||
userId?: number
|
userId?: number
|
||||||
): Promise<PaginatedResult<AlbumResponse>> {
|
): Promise<PaginatedResult<AlbumResponse>> {
|
||||||
try {
|
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();
|
const queryParams = new URLSearchParams();
|
||||||
queryParams.append('page', page.toString());
|
queryParams.append('page', page.toString());
|
||||||
queryParams.append('pageSize', pageSize.toString());
|
queryParams.append('pageSize', pageSize.toString());
|
||||||
@@ -31,19 +52,31 @@ export async function getAlbums(
|
|||||||
queryParams.append('userId', userId.toString());
|
queryParams.append('userId', userId.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = `${BASE_URL}/album/get_albums?${queryParams.toString()}`;
|
const url = `/album/get_albums?${queryParams.toString()}`;
|
||||||
const response = await fetch(url, { headers });
|
const result = await fetchApi<PaginatedResult<AlbumResponse>>(url);
|
||||||
const data = await response.json();
|
if (result.success) {
|
||||||
|
return result as unknown as PaginatedResult<AlbumResponse>;
|
||||||
return data 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) {
|
} catch (error) {
|
||||||
console.error('获取相册列表失败:', error);
|
console.error('获取相册列表时发生意外错误:', error);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: '网络请求失败,请检查您的网络连接',
|
message: '网络请求失败,请检查您的网络连接',
|
||||||
data: [],
|
data: [],
|
||||||
page: 1,
|
page: page,
|
||||||
pageSize: 10,
|
pageSize: pageSize,
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
totalPages: 0,
|
totalPages: 0,
|
||||||
code: 500,
|
code: 500,
|
||||||
|
|||||||
+50
-2
@@ -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, type BaseResult} from './fetchClient';
|
||||||
import {fetchApi, BASE_URL} from './fetchClient';
|
import { type UserRole } from './userManagementApi';
|
||||||
|
|
||||||
// 认证数据本地存储键
|
// 认证数据本地存储键
|
||||||
const TOKEN_KEY = 'token';
|
const TOKEN_KEY = 'token';
|
||||||
const USER_KEY = 'user';
|
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>> {
|
export async function register(data: RegisterRequest): Promise<BaseResult<AuthResponse>> {
|
||||||
return fetchApi<AuthResponse>('/auth/register', {
|
return fetchApi<AuthResponse>('/auth/register', {
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
import { fetchApi } from './fetchClient';
|
import { fetchApi, type BaseResult } from './fetchClient';
|
||||||
import type { BaseResult, PictureProcessingTask } from './types';
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前用户的所有处理任务
|
* 获取当前用户的所有处理任务
|
||||||
|
|||||||
@@ -1,5 +1,23 @@
|
|||||||
import { UserRole, type BaseResult, type ConfigResponse, type SetConfigRequest } from './types';
|
import { fetchApi, type BaseResult } from './fetchClient';
|
||||||
import { fetchApi } 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[]>> => {
|
export const getAllConfigs = async (): Promise<BaseResult<ConfigResponse[]>> => {
|
||||||
|
|||||||
@@ -1,5 +1,25 @@
|
|||||||
import type { BaseResult } from './types';
|
|
||||||
import { clearAuthData } from './index';
|
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 const BASE_URL = import.meta.env.PROD ? '/api' : 'http://localhost:5153/api';
|
||||||
|
|
||||||
export async function fetchApi<T = any>(
|
export async function fetchApi<T = any>(
|
||||||
|
|||||||
+10
-99
@@ -1,100 +1,11 @@
|
|||||||
// 重新导出类型
|
|
||||||
export * from './authApi';
|
export * from './authApi';
|
||||||
export * from './types';
|
export * from './albumApi';
|
||||||
|
export * from './backgroundTaskApi';
|
||||||
// 导出fetch客户端
|
export * from './configApi';
|
||||||
export { fetchApi, BASE_URL } from './fetchClient';
|
export * from './fetchClient';
|
||||||
|
export * from './logManagementApi';
|
||||||
// 导出Auth API
|
export * from './pictureApi';
|
||||||
export {
|
export * from './pictureManagementApi';
|
||||||
register,
|
export * from './tagApi';
|
||||||
login,
|
export * from './userManagementApi';
|
||||||
getCurrentUser,
|
export * from './vectorDbApi';
|
||||||
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';
|
|
||||||
|
|
||||||
@@ -1,13 +1,60 @@
|
|||||||
import { fetchApi } from './fetchClient';
|
import { fetchApi, type BaseResult, type PaginatedResult } from './fetchClient';
|
||||||
import {
|
import { type BatchDeleteResult } from './userManagementApi';
|
||||||
type BaseResult,
|
|
||||||
type PaginatedResult,
|
|
||||||
type LogResponse,
|
// 日志级别枚举
|
||||||
type LogFilterRequest,
|
export type LogLevel = 'Trace' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Critical';
|
||||||
type ClearLogsRequest,
|
|
||||||
type BatchDeleteResult,
|
export const LogLevel = {
|
||||||
type LogStatistics
|
Trace: 'Trace' as LogLevel,
|
||||||
} from './types';
|
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 (
|
export const getLogs = async (
|
||||||
|
|||||||
+143
-44
@@ -1,11 +1,108 @@
|
|||||||
import type { PaginatedResult, PictureResponse, FilteredPicturesRequest, BaseResult, UpdatePictureRequest } from './types';
|
import { fetchApi, BASE_URL, type PaginatedResult, type BaseResult } from './fetchClient';
|
||||||
import { fetchApi, BASE_URL } 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>> {
|
export async function getPictures(params: FilteredPicturesRequest = {}): Promise<PaginatedResult<PictureResponse>> {
|
||||||
// 添加调试日志
|
|
||||||
console.log("Search API 请求参数:", params);
|
|
||||||
|
|
||||||
// 构建查询参数
|
// 构建查询参数
|
||||||
const queryParams = new URLSearchParams();
|
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.ownerId !== undefined) queryParams.append('ownerId', params.ownerId.toString());
|
||||||
if (params.includeAllPublic !== undefined) queryParams.append('includeAllPublic', params.includeAllPublic.toString());
|
if (params.includeAllPublic !== undefined) queryParams.append('includeAllPublic', params.includeAllPublic.toString());
|
||||||
|
|
||||||
// 最终URL调试日志
|
const url = `/picture/get_pictures?${queryParams.toString()}`;
|
||||||
const url = `${BASE_URL}/picture/get_pictures?${queryParams.toString()}`;
|
|
||||||
console.log("发送API请求:", url);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const token = localStorage.getItem('token');
|
const result = await fetchApi<PaginatedResult<PictureResponse>>(url);
|
||||||
const headers: Record<string, string> = {
|
|
||||||
'Content-Type': 'application/json',
|
if (result.success) {
|
||||||
};
|
return result as unknown as PaginatedResult<PictureResponse>;
|
||||||
if (token) {
|
} else {
|
||||||
headers['Authorization'] = `Bearer ${token}`;
|
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) {
|
} catch (error) {
|
||||||
console.error('获取图片列表失败:', error);
|
console.error('获取图片列表时发生意外错误:', error);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: '网络请求失败,请检查您的网络连接',
|
message: '网络请求失败,请检查您的网络连接',
|
||||||
data: [],
|
data: [],
|
||||||
page: 1,
|
page: params.page || 1,
|
||||||
pageSize: 10,
|
pageSize: params.pageSize || 10,
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
totalPages: 0,
|
totalPages: 0,
|
||||||
code: 500,
|
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>> {
|
export async function getUserFavorites(page: number = 1, pageSize: number = 8): Promise<PaginatedResult<PictureResponse>> {
|
||||||
try {
|
try {
|
||||||
const token = localStorage.getItem('token');
|
const url = `/picture/favorites?page=${page}&pageSize=${pageSize}`;
|
||||||
const headers: Record<string, string> = {
|
// 使用 fetchApi 替换原生 fetch
|
||||||
'Content-Type': 'application/json',
|
const result = await fetchApi<PaginatedResult<PictureResponse>>(url);
|
||||||
};
|
|
||||||
if (token) {
|
if (result.success) {
|
||||||
headers['Authorization'] = `Bearer ${token}`;
|
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) {
|
} catch (error) {
|
||||||
console.error('获取收藏图片失败:', error);
|
console.error('获取收藏图片时发生意外错误:', error);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: '网络请求失败,请检查您的网络连接',
|
message: '网络请求失败,请检查您的网络连接',
|
||||||
data: [],
|
data: [],
|
||||||
page: 1,
|
page: page,
|
||||||
pageSize: 10,
|
pageSize: pageSize,
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
totalPages: 0,
|
totalPages: 0,
|
||||||
code: 500,
|
code: 500,
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import { fetchApi } from './fetchClient';
|
import { fetchApi, type BaseResult, type PaginatedResult } from './fetchClient';
|
||||||
import {
|
import { type PictureResponse } from './pictureApi';
|
||||||
type BaseResult,
|
import { type BatchDeleteResult } from './userManagementApi';
|
||||||
type PaginatedResult,
|
|
||||||
type PictureResponse,
|
|
||||||
type BatchDeleteResult
|
|
||||||
} from './types';
|
|
||||||
|
|
||||||
// 获取图片列表
|
// 获取图片列表
|
||||||
export const getManagementPictures = async (
|
export const getManagementPictures = async (
|
||||||
|
|||||||
+20
-18
@@ -1,5 +1,4 @@
|
|||||||
import type { BaseResult, PaginatedResult } from './types';
|
import { fetchApi, type BaseResult, type PaginatedResult } from './fetchClient';
|
||||||
import { fetchApi, BASE_URL } from './fetchClient';
|
|
||||||
|
|
||||||
// 标签响应类型
|
// 标签响应类型
|
||||||
export interface TagResponse {
|
export interface TagResponse {
|
||||||
@@ -50,28 +49,31 @@ export async function getFilteredTags(params: FilteredTagsRequest = {}): Promise
|
|||||||
if (params.sortDirection) queryParams.append('sortDirection', params.sortDirection);
|
if (params.sortDirection) queryParams.append('sortDirection', params.sortDirection);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const token = localStorage.getItem('token');
|
const url = `/tag/get_tags?${queryParams.toString()}`;
|
||||||
const headers: Record<string, string> = {
|
const result = await fetchApi<PaginatedResult<TagResponse>>(url);
|
||||||
'Content-Type': 'application/json',
|
if (result.success) {
|
||||||
};
|
return result as unknown as PaginatedResult<TagResponse>;
|
||||||
|
} else {
|
||||||
if (token) {
|
console.error('获取标签列表失败:', result.message);
|
||||||
headers['Authorization'] = `Bearer ${token}`;
|
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) {
|
} catch (error) {
|
||||||
console.error('获取标签列表失败:', error);
|
console.error('获取标签列表时发生意外错误:', error);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: '网络请求失败,请检查您的网络连接',
|
message: '网络请求失败,请检查您的网络连接',
|
||||||
data: [],
|
data: [],
|
||||||
page: 1,
|
page: params.page || 1,
|
||||||
pageSize: 10,
|
pageSize: params.pageSize || 10,
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
totalPages: 0,
|
totalPages: 0,
|
||||||
code: 500,
|
code: 500,
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,75 @@
|
|||||||
import { fetchApi } from './fetchClient';
|
import { fetchApi, type BaseResult, type PaginatedResult } from './fetchClient';
|
||||||
import {
|
|
||||||
type BaseResult,
|
export type UserRole = "Administrator" | "User" | "";
|
||||||
type PaginatedResult,
|
|
||||||
type UserResponse,
|
export const UserRole = {
|
||||||
type CreateUserRequest,
|
Administrator: "Administrator" as UserRole,
|
||||||
type AdminUpdateUserRequest,
|
User: "User" as UserRole,
|
||||||
type BatchDeleteResult,
|
Guest: "" as UserRole
|
||||||
type UserFilterRequest,
|
};
|
||||||
type UserDetailResponse
|
|
||||||
} from './types';
|
// 用户管理相关类型
|
||||||
|
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 (
|
export const getUsers = async (
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
import { type BaseResult, type VectorDbInfo, VectorDbType } from './types';
|
import { fetchApi, type BaseResult } from './fetchClient';
|
||||||
import { fetchApi } 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>> => {
|
export const getCurrentVectorDb = async (): Promise<BaseResult<VectorDbInfo>> => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { createContext, useState, useEffect, useContext, useCallback } from 'react';
|
import React, { createContext, useState, useEffect, useContext, useCallback } from 'react';
|
||||||
import { getCurrentUser, isAuthenticated, clearAuthData, getStoredUser } from '../api/index';
|
import { getCurrentUser, isAuthenticated, clearAuthData, getStoredUser } from '../api/index';
|
||||||
import type { UserProfile } from '../api/types';
|
import type { UserProfile } from '../api';
|
||||||
import { UserRole } from '../api/types';
|
import { UserRole } from '../api';
|
||||||
|
|
||||||
interface AuthContextType {
|
interface AuthContextType {
|
||||||
user: UserProfile | null;
|
user: UserProfile | null;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
CloseCircleOutlined
|
CloseCircleOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { ProcessingStatus } from '../api/types';
|
import { ProcessingStatus } from '../api';
|
||||||
|
|
||||||
interface TaskProgressBarProps {
|
interface TaskProgressBarProps {
|
||||||
status: ProcessingStatus;
|
status: ProcessingStatus;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Divider } from 'antd';
|
import { Divider } from 'antd';
|
||||||
import { CloseOutlined, DownOutlined, UpOutlined } from '@ant-design/icons';
|
import { CloseOutlined, DownOutlined, UpOutlined } from '@ant-design/icons';
|
||||||
import type { PictureResponse } from '../../api/types';
|
import type { PictureResponse } from '../../api';
|
||||||
import './ImageViewer.css';
|
import './ImageViewer.css';
|
||||||
|
|
||||||
interface ImageInfoProps {
|
interface ImageInfoProps {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
RotateRightOutlined, HeartOutlined, HeartFilled, DownloadOutlined,
|
RotateRightOutlined, HeartOutlined, HeartFilled, DownloadOutlined,
|
||||||
ShareAltOutlined, FolderAddOutlined
|
ShareAltOutlined, FolderAddOutlined
|
||||||
} from '@ant-design/icons';
|
} 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 { getAlbums, addPicturesToAlbum, favoritePicture, unfavoritePicture } from '../../api';
|
||||||
import ImageInfo from './ImageInfo';
|
import ImageInfo from './ImageInfo';
|
||||||
import ShareImageDialog from './ShareImageDialog';
|
import ShareImageDialog from './ShareImageDialog';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import { Modal, Tabs, Input, Button, message, Radio, Space, Typography } from 'antd';
|
import { Modal, Tabs, Input, Button, message, Radio, Space, Typography } from 'antd';
|
||||||
import { CopyOutlined, CheckOutlined } from '@ant-design/icons';
|
import { CopyOutlined, CheckOutlined } from '@ant-design/icons';
|
||||||
import type { PictureResponse } from '../../api/types';
|
import type { PictureResponse } from '../../api';
|
||||||
import './ShareImageDialog.css';
|
import './ShareImageDialog.css';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useAuth } from '../auth/AuthContext';
|
|||||||
import Sidebar from './components/Sidebar';
|
import Sidebar from './components/Sidebar';
|
||||||
import Header from './components/Header';
|
import Header from './components/Header';
|
||||||
import Footer from './components/Footer';
|
import Footer from './components/Footer';
|
||||||
import { UserRole } from '../api/types';
|
import { UserRole } from '../api';
|
||||||
import { getAdminRoutes, type RouteConfig } from '../routes';
|
import { getAdminRoutes, type RouteConfig } from '../routes';
|
||||||
|
|
||||||
const { Content } = Layout;
|
const { Content } = Layout;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import type { ColumnsType } from 'antd/es/table';
|
|||||||
import { useOutletContext } from 'react-router';
|
import { useOutletContext } from 'react-router';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
import { getUsers, getManagementPictures } from '../../../api';
|
import { getUsers, getManagementPictures } from '../../../api';
|
||||||
import type { UserResponse, PictureResponse } from '../../../api/types';
|
import type { UserResponse, PictureResponse } from '../../../api';
|
||||||
|
|
||||||
const { Title, Text } = Typography;
|
const { Title, Text } = Typography;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import {useOutletContext} from 'react-router';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import type {Dayjs} from 'dayjs';
|
import type {Dayjs} from 'dayjs';
|
||||||
import {getLogs, deleteLog, batchDeleteLogs, clearLogs, getLogById, getLogStatistics} from '../../../api';
|
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 {Title, Text, Paragraph} = Typography;
|
||||||
const {RangePicker} = DatePicker;
|
const {RangePicker} = DatePicker;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
getManagementPictures, deleteManagementPicture, batchDeleteManagementPictures,
|
getManagementPictures, deleteManagementPicture, batchDeleteManagementPictures,
|
||||||
getUsers
|
getUsers
|
||||||
} from '../../../api';
|
} from '../../../api';
|
||||||
import type { PictureResponse } from '../../../api/types';
|
import type { PictureResponse } from '../../../api';
|
||||||
import { useOutletContext } from 'react-router';
|
import { useOutletContext } from 'react-router';
|
||||||
import type { Breakpoint } from 'antd';
|
import type { Breakpoint } from 'antd';
|
||||||
|
|
||||||
|
|||||||
@@ -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 { 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 { DatabaseOutlined, SyncOutlined, CheckCircleOutlined, InfoCircleOutlined, SaveOutlined, DeleteOutlined, ReloadOutlined } from '@ant-design/icons';
|
||||||
import { getCurrentVectorDb, switchVectorDb, setConfig, clearVectors, rebuildVectors } from '../../../api';
|
import { getCurrentVectorDb, switchVectorDb, setConfig, clearVectors, rebuildVectors } from '../../../api';
|
||||||
import { VectorDbType } from '../../../api/types';
|
import { VectorDbType } from '../../../api';
|
||||||
|
|
||||||
const { Title, Paragraph } = Typography;
|
const { Title, Paragraph } = Typography;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
getUsers, deleteUser, createUser, updateUser, batchDeleteUsers, UserRole
|
getUsers, deleteUser, createUser, updateUser, batchDeleteUsers, UserRole
|
||||||
} from '../../../api';
|
} 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 { useOutletContext } from 'react-router';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
import type { Breakpoint } from 'antd';
|
import type { Breakpoint } from 'antd';
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { useParams, useNavigate } from 'react-router';
|
import { useParams, useNavigate } from 'react-router';
|
||||||
import { getUserDetail } from '../../../api';
|
import { getUserDetail } from '../../../api';
|
||||||
import type { UserDetailResponse } from '../../../api/types';
|
import type { UserDetailResponse } from '../../../api';
|
||||||
import UserAvatar from '../../../components/UserAvatar';
|
import UserAvatar from '../../../components/UserAvatar';
|
||||||
|
|
||||||
const { Title, Text } = Typography;
|
const { Title, Text } = Typography;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { Link } from 'react-router';
|
|||||||
|
|
||||||
import ShareImageDialog from '../../components/image/ShareImageDialog';
|
import ShareImageDialog from '../../components/image/ShareImageDialog';
|
||||||
import { uploadPicture } from '../../api/pictureApi';
|
import { uploadPicture } from '../../api/pictureApi';
|
||||||
import type { PictureResponse } from '../../api/types';
|
import type { PictureResponse } from '../../api';
|
||||||
|
|
||||||
const { Title, Text } = Typography;
|
const { Title, Text } = Typography;
|
||||||
const { Dragger } = Upload;
|
const { Dragger } = Upload;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
|
|||||||
import { Typography, Table, Card, Tag, Space, Button, Empty, message, Modal } from 'antd';
|
import { Typography, Table, Card, Tag, Space, Button, Empty, message, Modal } from 'antd';
|
||||||
import { SyncOutlined, EyeOutlined } from '@ant-design/icons';
|
import { SyncOutlined, EyeOutlined } from '@ant-design/icons';
|
||||||
import { getUserTasks } from '../../api';
|
import { getUserTasks } from '../../api';
|
||||||
import { type PictureProcessingTask, ProcessingStatus } from '../../api/types';
|
import { type PictureProcessingTask, ProcessingStatus } from '../../api';
|
||||||
import TaskProgressBar from '../../components/TaskProgressBar';
|
import TaskProgressBar from '../../components/TaskProgressBar';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
import ImageGrid from '../../components/image/ImageGrid/ImageGrid';
|
import ImageGrid from '../../components/image/ImageGrid/ImageGrid';
|
||||||
import type { PictureResponse } from '../../api/types';
|
import type { PictureResponse } from '../../api';
|
||||||
import { getFilteredTags } from '../../api/tagApi';
|
import { getFilteredTags } from '../../api/tagApi';
|
||||||
import useIsMobile from '../../hooks/useIsMobile';
|
import useIsMobile from '../../hooks/useIsMobile';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user