- Create new frontend project directory with Next.js 15 + React 19 - Migrate from pnpm to bun for faster package management - Add TanStack Query + Axios for dynamic data fetching - Create comprehensive Makefile with development commands - Setup API layer with query hooks and error handling - Configure environment variables and bun settings - Add TypeScript type checking and project documentation - Update CLAUDE.md with bun-specific development workflow
91 lines
2.1 KiB
TypeScript
91 lines
2.1 KiB
TypeScript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
import api from './api'
|
|
|
|
// 照片数据类型
|
|
export interface Photo {
|
|
id: number
|
|
src: string
|
|
title: string
|
|
description: string
|
|
category: string
|
|
tags: string[]
|
|
date: string
|
|
exif: {
|
|
camera: string
|
|
lens: string
|
|
settings: string
|
|
location: string
|
|
}
|
|
}
|
|
|
|
// 查询键
|
|
export const queryKeys = {
|
|
photos: ['photos'] as const,
|
|
photo: (id: number) => ['photo', id] as const,
|
|
categories: ['categories'] as const,
|
|
}
|
|
|
|
// 获取所有照片
|
|
export const usePhotos = () => {
|
|
return useQuery({
|
|
queryKey: queryKeys.photos,
|
|
queryFn: () => api.get('/photos'),
|
|
staleTime: 5 * 60 * 1000, // 5分钟内不重新获取
|
|
})
|
|
}
|
|
|
|
// 获取单张照片
|
|
export const usePhoto = (id: number) => {
|
|
return useQuery({
|
|
queryKey: queryKeys.photo(id),
|
|
queryFn: () => api.get(`/photos/${id}`),
|
|
enabled: !!id,
|
|
})
|
|
}
|
|
|
|
// 获取分类列表
|
|
export const useCategories = () => {
|
|
return useQuery({
|
|
queryKey: queryKeys.categories,
|
|
queryFn: () => api.get('/categories'),
|
|
staleTime: 10 * 60 * 1000, // 10分钟内不重新获取
|
|
})
|
|
}
|
|
|
|
// 添加照片
|
|
export const useAddPhoto = () => {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useMutation({
|
|
mutationFn: (photo: Omit<Photo, 'id'>) => api.post('/photos', photo),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: queryKeys.photos })
|
|
},
|
|
})
|
|
}
|
|
|
|
// 更新照片
|
|
export const useUpdatePhoto = () => {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useMutation({
|
|
mutationFn: ({ id, ...photo }: Partial<Photo> & { 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 })
|
|
},
|
|
})
|
|
} |