diff --git a/src/pages/ExportPage.tsx b/src/pages/ExportPage.tsx index e8dd8ca..f5c2b39 100644 --- a/src/pages/ExportPage.tsx +++ b/src/pages/ExportPage.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useLocation } from 'react-router-dom' import { Aperture, @@ -237,6 +237,60 @@ const timestampOrDash = (timestamp?: number): string => { const createTaskId = (): string => `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` +const WriteLayoutSelector = memo(function WriteLayoutSelector({ + writeLayout, + onChange +}: { + writeLayout: configService.ExportWriteLayout + onChange: (value: configService.ExportWriteLayout) => Promise +}) { + const [isOpen, setIsOpen] = useState(false) + const containerRef = useRef(null) + + useEffect(() => { + if (!isOpen) return + + const handleOutsideClick = (event: MouseEvent) => { + if (containerRef.current?.contains(event.target as Node)) return + setIsOpen(false) + } + + document.addEventListener('mousedown', handleOutsideClick) + return () => document.removeEventListener('mousedown', handleOutsideClick) + }, [isOpen]) + + const writeLayoutLabel = writeLayoutOptions.find(option => option.value === writeLayout)?.label || 'A(类型分目录)' + + return ( +
+ 写入目录方式 + +
+ {writeLayoutOptions.map(option => ( + + ))} +
+
+ ) +}) + function ExportPage() { const location = useLocation() @@ -255,7 +309,6 @@ function ExportPage() { const [exportFolder, setExportFolder] = useState('') const [writeLayout, setWriteLayout] = useState('A') - const [showWriteLayoutSelect, setShowWriteLayoutSelect] = useState(false) const [options, setOptions] = useState({ format: 'excel', @@ -302,7 +355,6 @@ function ExportPage() { const sessionLoadTokenRef = useRef(0) const loadingMetricsRef = useRef>(new Set()) const preselectAppliedRef = useRef(false) - const writeLayoutControlRef = useRef(null) useEffect(() => { tasksRef.current = tasks @@ -526,18 +578,6 @@ function ExportPage() { preselectAppliedRef.current = false }, [location.key, preselectSessionIds]) - useEffect(() => { - if (!showWriteLayoutSelect) return - - const handleOutsideClick = (event: MouseEvent) => { - if (writeLayoutControlRef.current?.contains(event.target as Node)) return - setShowWriteLayoutSelect(false) - } - - document.addEventListener('mousedown', handleOutsideClick) - return () => document.removeEventListener('mousedown', handleOutsideClick) - }, [showWriteLayoutSelect]) - useEffect(() => { if (preselectAppliedRef.current) return if (sessions.length === 0 || preselectSessionIds.length === 0) return @@ -1306,7 +1346,6 @@ function ExportPage() { return count }, [visibleSessions, selectedSessions]) - const writeLayoutLabel = writeLayoutOptions.find(option => option.value === writeLayout)?.label || 'A(类型分目录)' const tableColSpan = activeTab === 'group' ? 14 : (activeTab === 'private' || activeTab === 'former_friend' ? 11 : 10) const canCreateTask = exportDialog.scope === 'sns' ? Boolean(exportFolder) @@ -1330,6 +1369,10 @@ function ExportPage() { const taskRunningCount = tasks.filter(task => task.status === 'running').length const taskQueuedCount = tasks.filter(task => task.status === 'queued').length const showInitialSkeleton = isLoading && sessions.length === 0 + const tableBodyRows = useMemo( + () => visibleSessions.map(renderRow), + [visibleSessions, selectedSessions, sessionMetrics, activeTab, runningSessionIds, queuedSessionIds, nowTick, lastExportBySession] + ) return (
@@ -1371,33 +1414,13 @@ function ExportPage() {
-
- 写入目录方式 - -
- {writeLayoutOptions.map(option => ( - - ))} -
-
+ { + setWriteLayout(value) + await configService.setExportWriteLayout(value) + }} + /> @@ -1585,7 +1608,7 @@ function ExportPage() { ) : ( - visibleSessions.map(renderRow) + tableBodyRows )}