import { useState, useEffect, useCallback, useRef } from 'react'; import { Box, Typography, TextField, Button, Stack, Alert, Accordion, AccordionSummary, AccordionDetails, CircularProgress, InputAdornment, IconButton, } from '@mui/material'; import LinkIcon from '@mui/icons-material/Link'; import ImageIcon from '@mui/icons-material/Image'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ClearIcon from '@mui/icons-material/Clear'; import CopyButton from '@/components/CopyButton'; import { qrCodePageStyles } from '@/config/pageTheme'; import type { SnackbarOptions } from '@/components/GlobalSnackbar'; import { parseQrCodeFromFile } from '@/utils/qrCodeParser'; interface QrCodeToUrlSectionProps { expanded: boolean; onExpandedChange: (expanded: boolean) => void; showMessage: (message: string, options?: SnackbarOptions) => void; } const QrCodeToUrlSection = ({ expanded, onExpandedChange, showMessage, }: QrCodeToUrlSectionProps) => { const [qrCodeFile, setQrCodeFile] = useState(null); const [parsedUrl, setParsedUrl] = useState(''); const [parseError, setParseError] = useState(''); const [parsing, setParsing] = useState(false); const [dragging, setDragging] = useState(false); const fileInputRef = useRef(null); const handleFileChange = useCallback((file: File) => { setQrCodeFile(file); setParseError(''); setParsedUrl(''); }, []); const handleInputChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { handleFileChange(e.target.files[0]); } }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); setDragging(true); }; const handleDragLeave = () => { setDragging(false); }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); setDragging(false); const droppedFile = e.dataTransfer.files?.[0]; if (droppedFile) { handleFileChange(droppedFile); } }; const parseQrCode = async () => { if (!qrCodeFile) { showMessage('请选择二维码图片', { severity: 'error', autoHideDuration: 300 }); return; } try { setParsing(true); setParseError(''); setParsedUrl(''); const result = await parseQrCodeFromFile(qrCodeFile); if (result.success && result.data) { setParsedUrl(result.data); showMessage('二维码解析成功', { severity: 'success', autoHideDuration: 1000 }); } else { showMessage(result.error || '未检测到二维码', { severity: 'error', autoHideDuration: 1000, }); } } catch (error) { console.error('解析二维码失败:', error); showMessage('解析二维码失败,请重试', { severity: 'error', autoHideDuration: 300 }); } finally { setParsing(false); } }; // 监听粘贴事件 useEffect(() => { const handlePaste = async (e: ClipboardEvent) => { if (!expanded) return; const items = e.clipboardData?.items; if (!items) return; for (let i = 0; i < items.length; i++) { if (items[i].type.startsWith('image/')) { e.preventDefault(); const file = items[i].getAsFile(); if (file) { try { handleFileChange(file); showMessage('图片粘贴成功', { severity: 'success', autoHideDuration: 1000 }); } catch (error) { console.error('处理粘贴图片失败:', error); showMessage('粘贴图片失败,请重试', { severity: 'error', autoHideDuration: 3000 }); } } break; } } }; document.addEventListener('paste', handlePaste); return () => { document.removeEventListener('paste', handlePaste); }; }, [expanded, showMessage, handleFileChange]); return ( onExpandedChange(isExpanded)} sx={{ borderRadius: 4, boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)', '&:before': { display: 'none' }, }} > } sx={{ borderBottom: 'none' }}> 二维码转 URL ), }, }} sx={qrCodePageStyles.INPUT_STYLE} /> {parseError && ( {parseError} )} ); }; export default QrCodeToUrlSection;