返回 AiToEarn
ImgChoose.tsx
1 /**
2 * ImgChoose - 图片选择组件
3 * 用于选择本地图片文件
4 */
5
6 import type { FC } from 'react'
7 import type { IImgFile } from '@/components/PublishDialog/publishDialog.type'
8 import { useCallback, useRef } from 'react'
9 import { formatImg } from '@/components/PublishDialog/PublishDialog.util'
10 import { Button } from '@/components/ui/button'
11 import { toast } from '@/utils/ui/toast'
12
13 interface ImgChooseProps {
14 // 单选就使用单选方法,多选就使用单选方法
15
16 // 单选返回
17 onChoose?: (_: IImgFile) => void
18 // 多选返回方法
19 onMultipleChoose?: (_: IImgFile[]) => void
20 children?: React.ReactNode
21 }
22
23 const ImgChoose: FC<ImgChooseProps> = ({ onChoose, onMultipleChoose, children }) => {
24 const fileInputRef = useRef<HTMLInputElement>(null)
25
26 /**
27 * 处理文件选择
28 */
29 const handleFileChange = useCallback(
30 async (event: React.ChangeEvent<HTMLInputElement>) => {
31 const files = event.target.files
32 if (!files || files.length === 0)
33 return
34
35 try {
36 const tasks: Promise<IImgFile>[] = []
37 for (const file of Array.from(files)) {
38 tasks.push(
39 formatImg({
40 path: file.name,
41 blob: file,
42 }),
43 )
44 }
45 const imgFiles = await Promise.all(tasks)
46 if (onMultipleChoose) {
47 onMultipleChoose(imgFiles)
48 }
49 else if (onChoose) {
50 onChoose(imgFiles[0])
51 }
52 }
53 catch (e) {
54 toast.error('选择图片失败')
55 console.error(e)
56 }
57 finally {
58 // 清空 input 以便下次选择同一文件
59 if (fileInputRef.current) {
60 fileInputRef.current.value = ''
61 }
62 }
63 },
64 [onChoose, onMultipleChoose],
65 )
66
67 /**
68 * 触发文件选择
69 */
70 const triggerFileInput = useCallback(() => {
71 fileInputRef.current?.click()
72 }, [])
73
74 return (
75 <>
76 <input
77 ref={fileInputRef}
78 type="file"
79 accept="image/*"
80 multiple={!!onMultipleChoose}
81 onChange={handleFileChange}
82 style={{ display: 'none' }}
83 />
84 {children ? (
85 <div className="imgChoose cursor-pointer" onClick={triggerFileInput}>
86 {children}
87 </div>
88 ) : (
89 <Button className="cursor-pointer" onClick={triggerFileInput}>
90 选择图片
91 </Button>
92 )}
93 </>
94 )
95 }
96
97 export default ImgChoose
98
98 lines Plain Text