import React, { useEffect, useState, useRef } from 'react'; import { Button, Empty, Input, Select, Space, Typography, Tag, message, Modal, Table, DatePicker, Tabs, Transfer, Tooltip } from 'antd'; import dayjs from 'dayjs'; import JSZip from 'jszip'; import { FilterOutlined, VideoCameraOutlined, PictureOutlined, FolderOpenOutlined, FileTextOutlined, DownloadOutlined, ClockCircleOutlined, UploadOutlined, ReloadOutlined, StarOutlined, PlayCircleOutlined, } from '@ant-design/icons'; import { gethistory, gethistoryItems, getOAuthList, asyncBatchUploadMaterial, updateFilename, getUploadHistory, getAllOAuthAccountList, getOpenTypeAll, getPreTestList, getDefaultPreTest } from '../api'; const { Search } = Input; const { Text } = Typography; const GeneratedRecord: React.FC = () => { const [filterType, setFilterType] = useState<'project' | 'creation' | 'hot_opening_replicate' | 'shot_replicate'>('project'); const [filterMedia, setFilterMedia] = useState<'video' | 'image'>('video'); const [recordlist, setRecordList] = useState([]); const [Pagebreak, setPagebreak] = useState({ page: 1, pageSize: 10, }); const [Totalnumber, setTotalnumber] = useState(0); const [loading, setLoading] = useState(false); const [loadingGroups, setLoadingGroups] = useState>(new Set()); const [previewVisible, setPreviewVisible] = useState(false); const [previewItem, setPreviewItem] = useState(null); const videoRef = React.createRef(); const [selectedDate, setSelectedDate] = useState(''); const [uploading, setUploading] = useState(false); // 推送配置弹窗相关状态 const [uploadConfigModalVisible, setUploadConfigModalVisible] = useState(false); const [accountIdLists, setAccountIdLists] = useState<{ accountId: string; }[][]>([[]]); const [accountIdInputs, setAccountIdInputs] = useState(['']); const [oauthList, setOauthList] = useState([]); const [oauthLoading, setOauthLoading] = useState(false); const [oauthTotal, setOauthTotal] = useState(0); const [selectedOauthItems, setSelectedOauthItems] = useState<({ value: string; label: string } | undefined)[]>([undefined]); const [materialFileNames, setMaterialFileNames] = useState>(new Map()); const [unifiedFileName, setUnifiedFileName] = useState(''); const updateFilenameDebounceRef = useRef>>(new Map()); useEffect(() => { return () => { updateFilenameDebounceRef.current.forEach(timer => clearTimeout(timer)); updateFilenameDebounceRef.current.clear(); }; }, []); const [oauthPage, setOauthPage] = useState(1); const [oauthPageSize, setOauthPageSize] = useState(10); const [oauthSelectOpens, setOauthSelectOpens] = useState([false]); const [accountTab, setAccountTab] = useState<'new' | 'history'>('new'); const [historyOAuthList, setHistoryOAuthList] = useState([]); const [historyOAuthLoading, setHistoryOAuthLoading] = useState(false); const [selectedHistoryAccounts, setSelectedHistoryAccounts] = useState([]); const [openTypeMap, setOpenTypeMap] = useState>({}); const [isPreTest, setIsPreTest] = useState('2'); const [preTestTemplate, setPreTestTemplate] = useState(''); const [preTestTemplates, setPreTestTemplates] = useState([]); const [preTestTemplatesLoading, setPreTestTemplatesLoading] = useState(false); // 推送任务历史弹窗相关状态 const [uploadHistoryModalVisible, setUploadHistoryModalVisible] = useState(false); const [uploadHistoryList, setUploadHistoryList] = useState([]); const [uploadHistoryTotal, setUploadHistoryTotal] = useState(0); const [uploadHistoryPage, setUploadHistoryPage] = useState(1); const [uploadHistoryPageSize, setUploadHistoryPageSize] = useState(10); const [uploadHistoryLoading, setUploadHistoryLoading] = useState(false); const [uploadHistoryStatus, setUploadHistoryStatus] = useState(''); const [isSelectionMode, setIsSelectionMode] = useState(false); const [selectedItems, setSelectedItems] = useState>(new Set()); // 从URL中提取exp时间戳(支持相对路径和完整URL) const extractExpTimestamp = (url: string): number | null => { if (!url) return null; try { // 尝试作为完整URL解析 const urlObj = new URL(url); const expStr = urlObj.searchParams.get('exp'); if (expStr) { return parseInt(expStr, 10); } return null; } catch { // 如果完整URL解析失败,尝试解析相对路径中的查询参数 try { const queryStart = url.indexOf('?'); if (queryStart !== -1) { const queryString = url.substring(queryStart + 1); const params = new URLSearchParams(queryString); const expStr = params.get('exp'); if (expStr) { return parseInt(expStr, 10); } } return null; } catch { return null; } } }; // 检查媒体是否过期 const isMediaExpired = (url: string): boolean => { const expTimestamp = extractExpTimestamp(url); if (!expTimestamp) { return false; // 没有exp参数,视为不过期 } const currentTimestamp = Math.floor(Date.now() / 1000); return currentTimestamp > expTimestamp; }; const buildUrl = (path: string, isImage: boolean = false): string => { const baseUrl = import.meta.env.VITE_API_BASE || "http://localhost:8000"; const cleanPath = path.startsWith('/') ? path.slice(1) : path; const cleanBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl; if (isImage) { return `${cleanBase}/static/${cleanPath}&w=300&q=50`; } return `${cleanBase}/${cleanPath}`; }; // 下载文件 const handleDownload = (item: any) => { const url = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${item.videoUrl || item.imageUrl}`; const link = document.createElement('a'); link.href = url; link.download = item.title || item.id || 'download'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; // 预览文件 const handlePreview = (item: any) => { setPreviewItem(item); setPreviewVisible(true); // 触发事件通知布局组件关闭浮动按钮 window.dispatchEvent(new Event('previewOpen')); }; // 关闭预览并暂停视频 const handleClosePreview = () => { // 方法1: 使用 ref if (videoRef.current) { videoRef.current.pause(); videoRef.current.currentTime = 0; } // 方法2: 直接通过 DOM 查询(备用) const videoElements = document.querySelectorAll('video'); videoElements.forEach(video => { video.pause(); video.currentTime = 0; }); setPreviewVisible(false); }; // 获取item的资源ID(优先使用generatedResourceId,否则使用id) const getItemResourceId = (item: any): string => { return item.generatedResourceId || item.id; }; // 判断item是否有generatedResourceId const hasGeneratedResourceId = (item: any): boolean => { return Boolean(item.generatedResourceId); }; // 多选相关函数 const handleToggleSelect = (itemId: string) => { setSelectedItems(prev => { const newSet = new Set(prev); if (newSet.has(itemId)) { newSet.delete(itemId); } else { newSet.add(itemId); } return newSet; }); }; const handleSelectAll = () => { const allItemIds = recordlist.flatMap((group: any) => group.items.map((item: any) => getItemResourceId(item)) ); if (selectedItems.size === allItemIds.length) { setSelectedItems(new Set()); } else { setSelectedItems(new Set(allItemIds)); } }; const handleDownloadSelected = async () => { if (selectedItems.size === 0) { message.warning('请先选择要下载的媒体'); return; } // 检查下载数量限制 if (selectedItems.size > 10) { message.warning('最多只能单次下载10个文件'); return; } const selectedContent: any[] = []; recordlist.forEach((group: any) => { group.items.forEach((item: any) => { if (selectedItems.has(getItemResourceId(item))) { selectedContent.push(item); } }); }); const zip = new JSZip(); const baseUrl = import.meta.env.VITE_API_BASE || "http://localhost:8000"; const folder = zip.folder('downloads'); let hasError = false; let successCount = 0; message.loading({ content: '下载中,请稍候...', key: 'downloadProgress' }); for (const item of selectedContent) { const url = `${baseUrl}${item.videoUrl || item.imageUrl}`; const filename = ((item.videoUrl || item.imageUrl).split('/').pop() || `file_${Date.now()}`).split('?')[0]; try { const response = await fetch(url); if (!response.ok) throw new Error('Network response was not ok'); const blob = await response.blob(); folder?.file(filename, blob); successCount++; } catch (error) { console.warn(`文件下载失败(CORS限制): ${filename},将使用备用方式下载`); hasError = true; break; } } if (hasError) { // Fallback: 逐个打开文件下载(不受 CORS 限制) message.destroy('downloadProgress'); message.info('由于跨域限制,将逐个下载文件'); selectedContent.forEach((item, index) => { setTimeout(() => { const url = `${baseUrl}${item.videoUrl || item.imageUrl}&download=1`; const link = document.createElement('a'); link.href = url; link.download = ''; document.body.appendChild(link); link.click(); document.body.removeChild(link); }, index * 500); }); return; } const zipBlob = await zip.generateAsync({ type: 'blob' }); const link = document.createElement('a'); link.href = URL.createObjectURL(zipBlob); link.download = `downloads_${Date.now()}.zip`; link.click(); URL.revokeObjectURL(link.href); message.destroy('downloadProgress'); message.success(`下载完成,共 ${successCount} 个文件`); }; const loadPreTestTemplates = async () => { setPreTestTemplatesLoading(true); try { const res = await getPreTestList({ page: 1, pageSize: 100 }); setPreTestTemplates(res.data?.data || res.data || []); } catch (error) { console.error('加载前测模板失败:', error); } finally { setPreTestTemplatesLoading(false); } }; const handleBatchUploadSelected = () => { if (selectedItems.size === 0) { message.warning('请先选择要推送的媒体'); return; } setAccountIdLists([[]]); setAccountIdInputs(['']); setSelectedOauthItems([undefined]); setIsPreTest('2'); setPreTestTemplate(''); loadPreTestTemplates(); setUploadConfigModalVisible(true); }; const handleSinglePushToMedia = () => { if (!previewItem) return; const resourceId = getItemResourceId(previewItem); setSelectedItems(new Set([resourceId])); setAccountIdLists([[]]); setAccountIdInputs(['']); setSelectedOauthItems([undefined]); setMaterialFileNames(new Map()); setUnifiedFileName(''); setIsPreTest('2'); setPreTestTemplate(''); loadPreTestTemplates(); setUploadConfigModalVisible(true); }; const loadOAuthList = async (page: number, pageSize: number) => { setOauthLoading(true); try { const res = await getOAuthList({ page, page_size: pageSize }); const data = res?.data || res; setOauthList(data || []); setOauthTotal(res.pagination.total || 0); } catch (error) { console.error('加载授权列表失败:', error); setOauthList([]); setOauthTotal(0); } finally { setOauthLoading(false); } }; const loadHistoryOAuthList = async () => { setHistoryOAuthLoading(true); try { const [oauthRes, openTypeRes] = await Promise.all([ getAllOAuthAccountList(), getOpenTypeAll(), ]); const oauthData = oauthRes?.data || []; setHistoryOAuthList(oauthData); const openTypeData = openTypeRes?.data || []; const map: Record = {}; openTypeData.forEach((item: any) => { map[item.openType] = item.typeName; }); setOpenTypeMap(map); } catch (error) { console.error('加载历史授权账户列表失败:', error); setHistoryOAuthList([]); setOpenTypeMap({}); } finally { setHistoryOAuthLoading(false); } }; const loadUploadHistory = async () => { setUploadHistoryLoading(true); try { const res = await getUploadHistory({ status: uploadHistoryStatus || undefined, page: uploadHistoryPage, pageSize: uploadHistoryPageSize, }); const data = res?.data || res; setUploadHistoryList(data || []); setUploadHistoryTotal(res.pagination?.total || res.total || 0); } catch (error) { console.error('加载推送历史失败:', error); setUploadHistoryList([]); setUploadHistoryTotal(0); } finally { setUploadHistoryLoading(false); } }; const handleOpenUploadHistory = () => { setUploadHistoryModalVisible(true); setUploadHistoryPage(1); setUploadHistoryStatus(''); loadUploadHistory(); }; const handleUploadHistorySearch = () => { setUploadHistoryPage(1); loadUploadHistory(); }; const handleUploadHistoryPageChange = (page: number, pageSize: number) => { setUploadHistoryPage(page); setUploadHistoryPageSize(pageSize); loadUploadHistory(); }; // 批量推送素材 const handleStartBatchUpload = async () => { if (selectedItems.size === 0) { message.warning('请先选择要推送的媒体'); return; } const itemMap = new Map(); recordlist.forEach((group: any) => { group.items.forEach((item: any) => { const resourceId = getItemResourceId(item); itemMap.set(resourceId, item); }); }); let tasks: { advertiser_ids: string[]; resource_ids: string[]; is_pre_test: string; pre_test_template: string; oauth_id: string; source_model: string; }[] = []; if (accountTab === 'new') { const validOauthItems = selectedOauthItems.filter(item => item !== undefined); if (validOauthItems.length === 0) { message.warning('请先选择授权账户'); return; } for (let i = 0; i < validOauthItems.length; i++) { const oauthItem = validOauthItems[i]; const advertiserIds = accountIdLists[i]?.map(account => account.accountId) || []; if (advertiserIds.length === 0) { message.warning(`第 ${i + 1} 组授权账户未设置账户ID,已跳过`); continue; } const sourceModelMap = new Map(); for (const itemId of selectedItems) { const item = itemMap.get(itemId); let sourceModel: string; if (item && hasGeneratedResourceId(item)) { sourceModel = 'generated_resources'; } // else { // sourceModel = filterType === 'project' ? 'generation_records' : 'chat_generation_tasks'; // } if (!sourceModelMap.has(sourceModel)) { sourceModelMap.set(sourceModel, []); } sourceModelMap.get(sourceModel)!.push(itemId); } sourceModelMap.forEach((resourceIds, sourceModel) => { tasks.push({ advertiser_ids: advertiserIds, resource_ids: resourceIds, oauth_id: oauthItem.value, source_model: sourceModel, is_pre_test: isPreTest, pre_test_template: preTestTemplate, }); }); } } else { if (selectedHistoryAccounts.length === 0) { message.warning('请先选择历史账户'); return; } for (const account of selectedHistoryAccounts) { const sourceModelMap = new Map(); for (const itemId of selectedItems) { const item = itemMap.get(itemId); let sourceModel: string; if (item && hasGeneratedResourceId(item)) { sourceModel = 'generated_resources'; } else { sourceModel = filterType === 'project' ? 'generation_records' : 'chat_generation_tasks'; } if (!sourceModelMap.has(sourceModel)) { sourceModelMap.set(sourceModel, []); } sourceModelMap.get(sourceModel)!.push(itemId); } sourceModelMap.forEach((resourceIds, sourceModel) => { tasks.push({ advertiser_ids: [account.advertiserId], resource_ids: resourceIds, oauth_id: String(account.oauthId), source_model: sourceModel, is_pre_test: isPreTest, pre_test_template: preTestTemplate, }); }); } } setUploading(true); try { const res = await asyncBatchUploadMaterial({ tasks }); if (res.errors?.length > 0) { message.warning(res.message); } else if (res.code === 0) { message.success(res.message); } else { message.error(res.message); } setIsSelectionMode(false); setSelectedItems(new Set()); setUploadConfigModalVisible(false); setAccountIdLists([[]]); setAccountIdInputs(['']); setSelectedOauthItems([undefined]); setSelectedHistoryAccounts([]); setMaterialFileNames(new Map()); setUnifiedFileName(''); setIsPreTest('2'); setPreTestTemplate(''); } catch (error: any) { console.error('批量推送失败:', error); message.error(error.message || '批量推送失败'); } finally { setUploading(false); } }; // 更新文件名函数 const handleUpdateFileName = async (sourceId: string, newFileName: string) => { if (!newFileName.trim()) return; try { const response = await updateFilename({ filenames: [{ source_id: sourceId, file_name: newFileName }], }); // 更新 recordlist 中的文件名,使用 API 返回的 new_file_name const result = response?.results?.find((r: any) => r.source_id === sourceId); const actualFileName = result?.new_file_name || newFileName; setRecordList(prevList => { return prevList.map(group => ({ ...group, items: group.items.map((item: any) => { const resourceId = getItemResourceId(item); if (resourceId === sourceId) { return { ...item, fileName: actualFileName }; } return item; }), })); }); message.success('文件名更新成功'); } catch (error: any) { console.error('文件名更新失败:', error); message.error(error.message || '文件名更新失败'); } }; // 批量更新文件名函数 const handleBatchUpdateFileName = async (sourceIds: string[], newFileName: string) => { if (!newFileName.trim() || sourceIds.length === 0) return; try { const filenames = sourceIds.map(sourceId => ({ source_id: sourceId, file_name: newFileName, })); const response = await updateFilename({ filenames }); // 批量更新 recordlist 中的文件名,使用 API 返回的 new_file_name const resultsMap = new Map(); response?.results?.forEach((r: any) => { if (r.success && r.newFileName) { resultsMap.set(r.sourceId, r.newFileName); } }); setRecordList(prevList => { const sourceIdSet = new Set(sourceIds); return prevList.map(group => ({ ...group, items: group.items.map((item: any) => { const resourceId = getItemResourceId(item); if (sourceIdSet.has(resourceId)) { const actualFileName = resultsMap.get(resourceId) || newFileName; return { ...item, fileName: actualFileName }; } return item; }), })); }); console.log(response); const successCount = response?.successCount || 0; message.success(`已更新 ${successCount} 个文件名`); } catch (error: any) { console.error('文件名更新失败:', error); message.error(error.message || '文件名更新失败'); } }; // 日期选择器变化处理函数 const handleDateChange = (dateString: string) => { setSelectedDate(dateString); }; useEffect(() => { setLoading(true); let historySource = ''; if (filterType === 'project') { historySource = 'generation_record'; } else if (filterType === 'hot_opening_replicate') { historySource = 'hot_opening_replicate'; } else if (filterType === 'shot_replicate') { historySource = 'shot_replicate'; } let parameters = `?gen_type=${filterMedia}&page=${Pagebreak.page}&page_size=${Pagebreak.pageSize}`; if (historySource) { parameters = `?gen_type=${filterMedia}&history_source=${historySource}&page=${Pagebreak.page}&page_size=${Pagebreak.pageSize}`; } if (selectedDate) { let parameters = `${selectedDate}?gen_type=${filterMedia}&page=${Pagebreak.page}&page_size=${Pagebreak.pageSize}`; if (historySource) { parameters = `${selectedDate}?gen_type=${filterMedia}&history_source=${historySource}&page=${Pagebreak.page}&page_size=${Pagebreak.pageSize}`; } gethistoryItems(parameters).then((res: any) => { const data = Array.isArray(res) ? res : (res?.items || []); let recordList = [{ generatedDate: res.generatedDate, items: data, total: res.total, page: res.page, }]; if (recordList && recordList[0].items.length > 0) { setRecordList(recordList); } else { setRecordList([]); } }).catch((err) => { }).finally(() => { setLoading(false); }); try { } catch (err) { } finally { } } else { gethistory(parameters).then((res: any) => { const data = Array.isArray(res) ? res : (res?.groups || []); data.forEach(group => { group.page = 1; }); // 如果是第一页,替换数据;否则追加数据 if (Pagebreak.page === 1) { setRecordList(data); } else { setRecordList(prev => [...prev, ...data]); } setTotalnumber(res?.totalDays || 0); }).catch((err) => { if (Pagebreak.page === 1) { setRecordList([]); } }).finally(() => { setLoading(false); }); } }, [filterType, filterMedia, Pagebreak.page, selectedDate]); // 加载更多 const handleLoadMore = () => { if (loading) return; setPagebreak(prev => ({ ...prev, page: prev.page + 1 })); }; // 分组加载更多 const handleGroupLoadMore = async (time: string, date: string, page: number) => { if (loadingGroups.has(date)) return; setLoadingGroups(prev => new Set([...prev, date])); const addpage = page + 1; let historySource = ''; if (filterType === 'project') { historySource = 'generation_record'; } else if (filterType === 'hot_opening_replicate') { historySource = 'hot_opening_replicate'; } else if (filterType === 'shot_replicate') { historySource = 'shot_replicate'; } let parameters = `${time}?gen_type=${filterMedia}&page=${addpage}&page_size=${Pagebreak.pageSize}`; if (historySource) { parameters = `${time}?gen_type=${filterMedia}&history_source=${historySource}&page=${addpage}&page_size=${Pagebreak.pageSize}`; } try { const res: any = await gethistoryItems(parameters); // gethistoryItems 返回数组,直接使用 const newItems: any[] = res.items || []; if (newItems && newItems.length > 0) { setRecordList(prev => prev.map(group => { if (group.generatedDate === time) { return { ...group, items: [...group.items, ...newItems], page: addpage }; } return group; })); } } catch (err) { } finally { setLoadingGroups(prev => { const next = new Set(prev); next.delete(date); return next; }); } }; // 当筛选条件改变时,重置页码 useEffect(() => { setPagebreak(prev => ({ ...prev, page: 1 })); }, [filterType, filterMedia]); return (
{/* 操作栏:筛选 + 推送按钮 */}
{/* 多选模式按钮 */} {isSelectionMode ? ( ) : ( )}
{/* Second row filter: 视频 / 图片 */}
媒体类型: handleDateChange(dateString || '')} format="YYYY-MM-DD" style={{ width: 160, borderRadius: 8, border: '1px solid #e2e8f0' }} placeholder="选择日期" /> {selectedDate && ( )}
{/* Content area */} {recordlist.length === 0 ? ( ) : (
{recordlist.map((group: any, index: number) => (
{/* Date label */}
{group.generatedDate}
{/* Media grid */}
{group.items.map((item: any) => { const displayUrl = filterMedia === 'video' && item.videoCoverUrl ? buildUrl(item.videoCoverUrl, true) : buildUrl(filterMedia === 'video' ? item.videoUrl : item.imageUrl, true); const hasCover = filterMedia === 'video' && item.videoCoverUrl; const showImage = hasCover || filterMedia === 'image'; const isSelectedItem = selectedItems.has(getItemResourceId(item)); return (
isSelectionMode ? handleToggleSelect(getItemResourceId(item)) : handlePreview(item)} onMouseEnter={(e) => { if (!isSelectionMode) { (e.currentTarget as HTMLElement).style.transform = 'scale(1.05)'; (e.currentTarget as HTMLElement).style.boxShadow = '0 4px 16px rgba(0,0,0,0.2)'; } }} onMouseLeave={(e) => { if (!isSelectionMode) { (e.currentTarget as HTMLElement).style.transform = 'scale(1)'; (e.currentTarget as HTMLElement).style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)'; } }} > {showImage ? ( 预览 ) : (
暂无封面
)} {isSelectionMode && (
{ e.stopPropagation(); handleToggleSelect(getItemResourceId(item)); }} > {isSelectedItem && ( )}
)} {!isSelectionMode && ( <>
{ (e.currentTarget as HTMLElement).style.opacity = '1'; }} onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.opacity = '0'; }} > 点击预览
{ e.stopPropagation(); const url = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${item.videoUrl || item.imageUrl}&download=1`; const link = document.createElement('a'); link.href = url; link.download = ''; document.body.appendChild(link); link.click(); document.body.removeChild(link); }} >
)} {isSelectionMode && isSelectedItem && (
)}
); })}
{/* 分组内加载更多 */} {group.total && group.total > group.items.length && (
)}
))} {/* 加载更多按钮 */} {recordlist.length > 0 && Totalnumber > recordlist.length && (
)}
)} {/* 推送任务历史弹窗 */} setUploadHistoryModalVisible(false)} footer={null} width={800} style={{ borderRadius: 8 }} mask={{ closable: false }} >
setUnifiedFileName(e.target.value)} placeholder="输入名称后点击应用" style={{ flex: 1, borderRadius: 8 }} size="small" />
{(() => { const itemMap = new Map(); recordlist.forEach((group: any) => { group.items.forEach((item: any) => { const resourceId = getItemResourceId(item); itemMap.set(resourceId, item); }); }); return Array.from(selectedItems).map((itemId) => { const item = itemMap.get(itemId); return (
{(() => { const coverField = filterMedia === 'video' ? item?.videoCoverUrl : item?.imageUrl; if (!coverField) { return 预览; } const baseUrl = import.meta.env.VITE_API_BASE || "http://localhost:8000"; const cleanPath = coverField.startsWith('/') ? coverField.slice(1) : coverField; const cleanBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl; const coverUrl = `${cleanBase}/static/${cleanPath}&w=300&q=50`; return ( ); })()}
{item?.fileName || `素材 ${item.id}`}
{ const newName = e.target.value; const newNames = new Map(materialFileNames); newNames.set(itemId, newName); setMaterialFileNames(newNames); }} onBlur={() => { const newName = materialFileNames.get(itemId) || item?.fileName || ''; if (newName.trim()) { handleUpdateFileName(itemId, newName); } }} onKeyDown={(e) => { if (e.key === 'Enter') { const newName = materialFileNames.get(itemId) || item?.fileName || ''; if (newName.trim()) { handleUpdateFileName(itemId, newName); } } }} placeholder="输入新名称" style={{ width: 200, borderRadius: 4 }} size="small" />
); }); })()}
是否开启前测: setPreTestTemplate(value)} style={{ width: 200 }} disabled={isPreTest !== '1'} loading={preTestTemplatesLoading} placeholder={isPreTest !== '1' ? '请先开启前测' : '选择前测模板'} options={preTestTemplates.map((item) => ({ value: item.id, label: item.name, }))} />
{ setAccountTab(key as 'new' | 'history'); if (key === 'history') { loadHistoryOAuthList(); } }} items={[ { key: 'new', label: '新增账户', }, { key: 'history', label: '历史账户', }, ]} /> {accountTab === 'new' && (
{selectedOauthItems.map((oauthItem, index) => (
授权账户 {index + 1} {selectedOauthItems.length > 1 && ( )}