import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import api from './api' import { categoryService } from './categoryService' // 照片数据类型 - 统一的显示格式 export interface Photo { id: number title: string description: string src: string category: string tags: string[] date: string exif: { camera: string lens: string settings: string location: string } // 后端原始数据 (仅供内部使用) file_path?: string thumbnail_path?: string user_id?: number category_id?: number created_at?: number updated_at?: number } // 分类数据类型 export interface Category { id: number name: string description: string created_at: number updated_at: number } // 后端分页响应格式 export interface PageResponse { total: number page: number size: number photos?: T[] categories?: T[] } // 后端API基础响应格式 export interface ApiResponse { code: number message: string data: T } // 查询键 export const queryKeys = { photos: ['photos'] as const, photo: (id: number) => ['photo', id] as const, categories: ['categories'] as const, } // 数据转换工具 const transformPhoto = async (backendPhoto: any): Promise => { // 如果使用Mock API,直接返回 if (process.env.NEXT_PUBLIC_USE_REAL_API !== 'true') { return { ...backendPhoto, src: backendPhoto.src || '/placeholder.jpg', category: backendPhoto.category || 'general', tags: backendPhoto.tags || [], date: backendPhoto.date || new Date().toISOString().split('T')[0], exif: backendPhoto.exif || { camera: '未知', lens: '未知', settings: '未知', location: '未知' } } } // 获取分类名称 const categoryName = await categoryService.getCategoryName(backendPhoto.category_id) // 转换后端API数据格式 return { id: backendPhoto.id, title: backendPhoto.title || '无标题', description: backendPhoto.description || '', src: backendPhoto.file_path ? `http://localhost:8080${backendPhoto.file_path}` : '/placeholder.jpg', category: categoryName, tags: [], // 后端暂无标签系统,使用空数组 date: new Date(backendPhoto.created_at * 1000).toISOString().split('T')[0], exif: { camera: '未知', lens: '未知', settings: '未知', location: '未知' }, // 保留原始数据供内部使用 file_path: backendPhoto.file_path, thumbnail_path: backendPhoto.thumbnail_path, user_id: backendPhoto.user_id, category_id: backendPhoto.category_id, created_at: backendPhoto.created_at, updated_at: backendPhoto.updated_at } } const transformCategory = (backendCategory: any): string => { if (process.env.NEXT_PUBLIC_USE_REAL_API !== 'true') { return backendCategory } return backendCategory.name } // 获取所有照片 export const usePhotos = () => { return useQuery({ queryKey: queryKeys.photos, queryFn: async (): Promise => { if (process.env.NEXT_PUBLIC_USE_REAL_API === 'true') { // 使用真实API,带分页参数 const response: any = await api.get('/photos?page=1&page_size=100') const photos = response?.photos || [] // 并发处理所有照片的转换 return Promise.all(photos.map(transformPhoto)) } else { // 使用Mock API const photos: any[] = await api.get('/photos') return Promise.all(photos.map(transformPhoto)) } }, staleTime: 5 * 60 * 1000, // 5分钟内不重新获取 }) } // 获取单张照片 export const usePhoto = (id: number) => { return useQuery({ queryKey: queryKeys.photo(id), queryFn: async (): Promise => { if (process.env.NEXT_PUBLIC_USE_REAL_API === 'true') { const response = await api.get(`/photos/${id}`) return await transformPhoto(response) } else { return api.get(`/photos/${id}`) } }, enabled: !!id, }) } // 获取分类列表 export const useCategories = () => { return useQuery({ queryKey: queryKeys.categories, queryFn: async (): Promise => { if (process.env.NEXT_PUBLIC_USE_REAL_API === 'true') { const response: any = await api.get('/categories?page=1&page_size=100') const categories = response?.categories || [] return categories.map((cat: Category) => cat.name) } else { const categories: string[] = await api.get('/categories') return categories } }, staleTime: 10 * 60 * 1000, // 10分钟内不重新获取 }) } // 添加照片 export const useAddPhoto = () => { const queryClient = useQueryClient() return useMutation({ mutationFn: (photo: Omit) => api.post('/photos', photo), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.photos }) }, }) } // 更新照片 export const useUpdatePhoto = () => { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ id, ...photo }: Partial & { id: number }) => api.put(`/photos/${id}`, photo), onSuccess: (data, variables) => { queryClient.invalidateQueries({ queryKey: queryKeys.photos }) queryClient.invalidateQueries({ queryKey: queryKeys.photo(variables.id) }) }, }) } // 删除照片 export const useDeletePhoto = () => { const queryClient = useQueryClient() return useMutation({ mutationFn: (id: number) => api.delete(`/photos/${id}`), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.photos }) }, }) }