diff --git a/src/components/ExportSidebar.tsx b/src/components/ExportSidebar.tsx index 3779a2f..50c5aa2 100644 --- a/src/components/ExportSidebar.tsx +++ b/src/components/ExportSidebar.tsx @@ -1,7 +1,9 @@ import { useState } from 'react'; -import { X, Check, Copy, Download, Code2, Image as ImageIcon, FileText, ChevronRight } from 'lucide-react'; +import { X, Check, Copy, Download, Code2, Image as ImageIcon, FileText, Loader2 } from 'lucide-react'; import { RecognitionResult } from '../types'; import { convertMathmlToOmml, wrapOmmlForClipboard } from '../lib/ommlConverter'; +import { API_BASE_URL } from '../config/env'; +import { tokenManager } from '../lib/api'; interface ExportSidebarProps { isOpen: boolean; @@ -22,6 +24,7 @@ interface ExportOption { export default function ExportSidebar({ isOpen, onClose, result }: ExportSidebarProps) { const [copiedId, setCopiedId] = useState(null); + const [exportingId, setExportingId] = useState(null); if (!result) return null; @@ -84,7 +87,62 @@ export default function ExportSidebar({ isOpen, onClose, result }: ExportSidebar } ]; + // Handle DOCX/PDF export via API + const handleFileExport = async (type: 'docx' | 'pdf') => { + if (!result?.id) return; + + setExportingId(type); + try { + const token = tokenManager.getToken(); + const response = await fetch(`${API_BASE_URL}/task/export`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...(token ? { 'Authorization': token } : {}), + }, + body: JSON.stringify({ + task_id: parseInt(result.id, 10), + type: type, + }), + }); + + if (!response.ok) { + throw new Error(`Export failed: ${response.statusText}`); + } + + // Get the blob from response + const blob = await response.blob(); + + // Create download link + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `export.${type}`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + + setCopiedId(type); + setTimeout(() => { + setCopiedId(null); + onClose(); + }, 1000); + } catch (err) { + console.error('Export failed:', err); + alert('导出失败,请重试'); + } finally { + setExportingId(null); + } + }; + const handleAction = async (option: ExportOption) => { + // Handle DOCX/PDF export via API + if (option.id === 'docx' || option.id === 'pdf') { + await handleFileExport(option.id as 'docx' | 'pdf'); + return; + } + let content = option.getContent(result); // Fallback: If Word MathML is missing, try to convert from MathML @@ -122,7 +180,7 @@ export default function ExportSidebar({ isOpen, onClose, result }: ExportSidebar await navigator.clipboard.writeText(content); } } else if (option.isDownload) { - // Simulate download + // Simulate download (for other file types if any) const blob = new Blob([content], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); @@ -200,7 +258,9 @@ export default function ExportSidebar({ isOpen, onClose, result }: ExportSidebar
- {copiedId === option.id ? ( + {exportingId === option.id ? ( + + ) : copiedId === option.id ? ( ) : option.isDownload ? (