import React, { useRef, useState } from 'react'; import { Popover, Tooltip } from 'antd'; import { FolderOpenOutlined, DatabaseOutlined, UserOutlined, TeamOutlined } from '@ant-design/icons'; import type { PrivatePortraitLibraryType, PrivatePortraitSelectableAsset, UploadResourceHistoryItem } from '../types'; import PrivatePortraitAssetPicker from './privatePortrait/picker/AssetPicker'; import UploadResourceHistoryPicker from './uploadResource/UploadResourceHistoryPicker'; interface UploadSelectorProps { children: React.ReactNode; accept?: string; multiple?: boolean; onLocalSelect?: (files: File[]) => void; onHistorySelect?: (items: UploadResourceHistoryItem[]) => void; /** 兼容旧页面:由 UploadSelector 内部打开素材选择器,确认后回传素材数组。 */ onPortraitSelect?: (items: PrivatePortraitSelectableAsset[]) => void; onPortraitLibrarySelect?: (libraryType: PrivatePortraitLibraryType) => void; uploading?: boolean; tooltipTitle?: string; maxImageCount?: number; maxVideoCount?: number; usedImageCount?: number; usedVideoCount?: number; usedVideoDuration?: number; maxVideoDuration?: number; maxAudioCount?: number; usedAudioCount?: number; maxAudioDuration?: number; usedAudioDuration?: number; hideLimitHint?: boolean; /** 创作类型:'image' 时隐藏真人素材库/虚拟素材库选项 */ mediaType?: string; } const UploadSelector: React.FC = ({ children, accept = 'image/*,video/*', multiple = true, onLocalSelect, onHistorySelect, onPortraitSelect, onPortraitLibrarySelect, uploading, tooltipTitle, maxImageCount, maxVideoCount, usedImageCount, usedVideoCount, usedVideoDuration, maxVideoDuration, maxAudioCount, usedAudioCount, maxAudioDuration, usedAudioDuration, hideLimitHint, mediaType, }) => { const fileInputRef = useRef(null); const [portraitPickerOpen, setPortraitPickerOpen] = useState(false); const [portraitLibraryType, setPortraitLibraryType] = useState('real_person'); const [historyModalVisible, setHistoryModalVisible] = useState(false); const [popoverOpen, setPopoverOpen] = useState(false); const [isUploading, setIsUploading] = useState(false); const handleLocalSelect = () => { setPopoverOpen(false); fileInputRef.current?.click(); }; const handleFileChange = (e: React.ChangeEvent) => { const files = e.target.files; if (files && onLocalSelect) { const fileList = Array.from(files); onLocalSelect(fileList); } if (fileInputRef.current) { fileInputRef.current.value = ''; } }; const openPortraitPicker = (libraryType: PrivatePortraitLibraryType) => { setPopoverOpen(false); if (onPortraitSelect) { setPortraitLibraryType(libraryType); setPortraitPickerOpen(true); return; } if (onPortraitLibrarySelect) { onPortraitLibrarySelect(libraryType); return; } setPortraitLibraryType(libraryType); setPortraitPickerOpen(true); }; const handleHistorySelect = () => { setPopoverOpen(false); setHistoryModalVisible(true); }; const content = (
{ handleLocalSelect(); }} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '8px 16px', cursor: 'pointer', transition: 'background 0.15s ease', }} onMouseEnter={(e) => { e.currentTarget.style.background = '#f1f5f9'; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }} > 本地上传 {/* {multiple ? '本地上传(可多选拖拽)' : '本地上传'} */}
{ e.currentTarget.style.background = '#f1f5f9'; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }} > 从资产中选择
{mediaType !== 'image' && (
openPortraitPicker('real_person')} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '8px 16px', cursor: 'pointer', transition: 'background 0.15s ease', }} onMouseEnter={(e) => { e.currentTarget.style.background = '#f1f5f9'; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }} > 真人素材库
)} {mediaType !== 'image' && (
openPortraitPicker('aigc_virtual')} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '8px 16px', cursor: 'pointer', transition: 'background 0.15s ease', }} onMouseEnter={(e) => { e.currentTarget.style.background = '#f1f5f9'; }} onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }} > 虚拟素材库
)}
); return ( <> {tooltipTitle ? (
{children}
) : (
{children}
)} setHistoryModalVisible(false)} onSelect={(items) => { onHistorySelect?.(items); setHistoryModalVisible(false); }} allowedTypes={accept.includes('audio') ? ['image', 'video', 'audio'] : ['image', 'video']} maxImageCount={maxImageCount} maxVideoCount={maxVideoCount} usedImageCount={usedImageCount} usedVideoCount={usedVideoCount} maxVideoDuration={maxVideoDuration} usedVideoDuration={usedVideoDuration} maxAudioCount={maxAudioCount} usedAudioCount={usedAudioCount} maxAudioDuration={maxAudioDuration} usedAudioDuration={usedAudioDuration} hideLimitHint={hideLimitHint} defaultResourceType={mediaType === 'image' ? 'image' : ''} /> setPortraitPickerOpen(false)} onSelect={(assets) => { onPortraitSelect?.(assets); setPortraitPickerOpen(false); }} accept={accept} maxCount={accept === 'image/*' && !multiple ? 1 : undefined} maxImageCount={maxImageCount} maxVideoCount={maxVideoCount} usedImageCount={usedImageCount} usedVideoCount={usedVideoCount} usedVideoDuration={usedVideoDuration} maxVideoDuration={maxVideoDuration} /> ); }; export default UploadSelector;