| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- import { useState, useCallback } from 'react';
- import { useQuery } from '@tanstack/react-query';
- import { fileClient } from '../api/fileClient';
- import type { FileType } from '../types/file';
- // 文件选择器钩子
- export interface UseFileSelectorOptions {
- filterType?: 'image' | 'all' | string;
- pageSize?: number;
- }
- export const useFileSelector = (options: UseFileSelectorOptions = {}) => {
- const { filterType = 'all', pageSize = 50 } = options;
- const [isOpen, setIsOpen] = useState(false);
- const [selectedFiles, setSelectedFiles] = useState<FileType[]>([]);
- const [searchText, setSearchText] = useState('');
- // 获取文件列表
- const {
- data: filesData,
- isLoading,
- error,
- refetch
- } = useQuery({
- queryKey: ['files-for-selection', filterType, searchText],
- queryFn: async () => {
- const response = await fileClient.$get({
- query: {
- page: 1,
- pageSize,
- keyword: searchText || undefined,
- },
- });
- if (!response.ok) {
- throw new Error('获取文件列表失败');
- }
- return await response.json();
- },
- enabled: isOpen,
- });
- // 过滤文件
- const files = filesData?.data?.filter((file) => {
- if (filterType === 'all') return true;
- if (filterType === 'image') return file?.type?.startsWith('image/');
- return file?.type?.includes(filterType);
- }) || [];
- // 选择文件
- const handleSelectFile = useCallback((file: FileType) => {
- setSelectedFiles(prev => {
- const isSelected = prev.some(f => f.id === file.id);
- if (isSelected) {
- return prev.filter(f => f.id !== file.id);
- } else {
- return [...prev, file];
- }
- });
- }, []);
- // 批量选择文件
- const handleSelectFiles = useCallback((files: FileType[]) => {
- setSelectedFiles(files);
- }, []);
- // 清除选择
- const handleClearSelection = useCallback(() => {
- setSelectedFiles([]);
- }, []);
- // 打开选择器
- const handleOpen = useCallback(() => {
- setIsOpen(true);
- }, []);
- // 关闭选择器
- const handleClose = useCallback(() => {
- setIsOpen(false);
- setSearchText('');
- }, []);
- // 确认选择
- const handleConfirm = useCallback(() => {
- setIsOpen(false);
- setSearchText('');
- return selectedFiles;
- }, [selectedFiles]);
- // 搜索文件
- const handleSearch = useCallback((text: string) => {
- setSearchText(text);
- }, []);
- // 检查文件是否被选中
- const isFileSelected = useCallback((fileId: number) => {
- return selectedFiles.some(file => file.id === fileId);
- }, [selectedFiles]);
- return {
- // 数据
- files,
- selectedFiles,
- // 状态
- isOpen,
- isLoading,
- error,
- searchText,
- // 操作
- handleOpen,
- handleClose,
- handleConfirm,
- handleSelectFile,
- handleSelectFiles,
- handleClearSelection,
- handleSearch,
- refetch,
- // 工具函数
- isFileSelected,
- };
- };
|