import { useState, useRef } from 'react'; import { Box, Typography, Container, Button, CircularProgress } from '@mui/material'; import InputIcon from '@mui/icons-material/Input'; import GlobalSnackbar, { useSnackbar } from '@/components/GlobalSnackbar'; import { dashboardPageStyles, formRecognizerPageStyles } from '@/config/pageTheme'; import { MessageAction, sendMessageToContent, injectContentScript } from '@/utils/messages'; import { DataTemplateManager, type DataTemplate } from '@/utils/dataTemplate'; import FieldList from '@/components/FieldList'; import OperationHistory from '@/components/OperationHistory'; import TemplateManager from '@/components/TemplateManager'; import MainActions from '@/components/MainActions'; import OptionsPanel from '@/components/OptionsPanel'; import FeatureDescription from '@/components/FeatureDescription'; // 字段数据接口 interface FieldData { id: string; fieldType: string; label: string | null; placeholder: string; name: string; value: string; isSelected: boolean; generatedValue: string; } const FormRecognizerPage = () => { const { snackbarProps, showMessage } = useSnackbar({ autoHideDuration: 1500 }); const [loading, setLoading] = useState(false); const [includeHidden, setIncludeHidden] = useState(false); const isProcessingRef = useRef(false); const [fields, setFields] = useState([]); const [scanning, setScanning] = useState(false); const [showFields, setShowFields] = useState(false); const [operationHistory, setOperationHistory] = useState< Array<{ time: string; type: string; content: string; result: string; }> >([]); const [showHistory, setShowHistory] = useState(false); const [templates, setTemplates] = useState([]); const [showTemplates, setShowTemplates] = useState(false); const [templateLoading, setTemplateLoading] = useState(false); // 扫描表单字段 const handleScanFields = async () => { setScanning(true); try { let response = await sendMessageToContent(MessageAction.SCAN_FORM_FIELDS); if (!response.success && response.message && response.message.includes('无法连接')) { showMessage('正在注入内容脚本...', { severity: 'info' }); const injected = await injectContentScript(); if (injected) { response = await sendMessageToContent(MessageAction.SCAN_FORM_FIELDS); } } if (response.success && response.fields) { setFields(response.fields as FieldData[]); showMessage(`扫描完成,发现 ${response.totalCount} 个可填充字段`, { severity: 'success' }); addOperationHistory('扫描', `扫描表单字段,发现 ${response.totalCount} 个字段`, '成功'); } else { showMessage(response.message || '扫描失败', { severity: 'error' }); } } catch (error) { console.error('扫描失败:', error); showMessage('扫描失败,请确保页面已加载', { severity: 'error' }); } finally { setScanning(false); } }; // 添加操作历史记录 const addOperationHistory = (type: string, content: string, result: string) => { const newEntry = { time: new Date().toLocaleString('zh-CN'), type, content, result, }; setOperationHistory((prev) => [newEntry, ...prev].slice(0, 50)); // 最多保留50条记录 }; // 加载模板列表 const loadTemplates = async () => { setTemplateLoading(true); try { const allTemplates = await DataTemplateManager.getAllTemplates(); setTemplates(allTemplates); } catch (error) { console.error('加载模板失败:', error); showMessage('加载模板失败', { severity: 'error' }); } finally { setTemplateLoading(false); } }; // 导出模板 const handleExportTemplates = async () => { const allTemplates = await DataTemplateManager.getAllTemplates(); if (allTemplates.length === 0) { showMessage('没有可导出的模板', { severity: 'warning' }); return; } const jsonStr = DataTemplateManager.exportTemplates(allTemplates); const blob = new Blob([jsonStr], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `templates_${new Date().toISOString().split('T')[0]}.json`; a.click(); URL.revokeObjectURL(url); showMessage(`已导出 ${allTemplates.length} 个模板`, { severity: 'success' }); addOperationHistory('导出', `导出 ${allTemplates.length} 个模板`, '成功'); }; // 导入模板 const handleImportTemplates = () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'; input.onchange = async (e) => { const file = (e.target as HTMLInputElement).files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = async (event) => { const content = event.target?.result as string; const success = await DataTemplateManager.importTemplates(content); if (success) { showMessage('模板导入成功', { severity: 'success' }); addOperationHistory('导入', '导入模板', '成功'); loadTemplates(); } else { showMessage('模板导入失败,请检查文件格式', { severity: 'error' }); } }; reader.readAsText(file); }; input.click(); }; const sendMessageWithHandler = async ( action: MessageAction, payload?: { includeHidden?: boolean }, ) => { // 防抖处理:防止快速点击导致多次请求 if (isProcessingRef.current) { showMessage('操作进行中,请稍候...', { severity: 'warning' }); return; } setLoading(true); isProcessingRef.current = true; try { let response = await sendMessageToContent(action, payload); // 如果连接失败,尝试注入内容脚本 if (!response.success && response.message && response.message.includes('无法连接')) { showMessage('正在注入内容脚本...', { severity: 'info' }); const injected = await injectContentScript(); if (injected) { // 注入成功后再次尝试 response = await sendMessageToContent(action, payload); } else { showMessage('内容脚本注入失败,请刷新页面后重试', { severity: 'error' }); return; } } if (response.success) { showMessage(response.message || '操作成功', { severity: 'success' }); } else { // 增强错误提示信息 const errorMsg = response.message || '操作失败'; const errorDetails = getErrorDetails(errorMsg); showMessage(errorDetails, { severity: 'error' }); } } catch (error) { console.error('发送消息失败:', error); const errorMessage = error instanceof Error ? error.message : '未知错误'; showMessage(`操作失败:${errorMessage},请确保当前页面已加载完成`, { severity: 'error' }); } finally { setLoading(false); isProcessingRef.current = false; } }; // 获取详细的错误信息 const getErrorDetails = (baseMsg: string): string => { if (baseMsg.includes('标签页')) { return `${baseMsg},请确保已打开网页页面`; } if (baseMsg.includes('注入')) { return `${baseMsg},请检查页面是否支持内容脚本`; } return baseMsg; }; const handleFillValidData = () => { sendMessageWithHandler(MessageAction.FILL_VALID_DATA, { includeHidden }); addOperationHistory('填充', '填充有效数据', '成功'); }; const handleFillInvalidData = () => { sendMessageWithHandler(MessageAction.FILL_INVALID_DATA, { includeHidden }); addOperationHistory('填充', '填充异常数据', '成功'); }; const handleClearAllFields = () => { sendMessageWithHandler(MessageAction.CLEAR_ALL_FIELDS); addOperationHistory('清空', '清空所有表单字段', '成功'); }; return ( Dummy Data Generator 一键填充表单测试数据,提升开发和测试效率 {/* 扫描按钮 */} setShowFields(!showFields)} /> setShowHistory(!showHistory)} /> setShowTemplates(!showTemplates)} onLoadTemplates={loadTemplates} onExportTemplates={handleExportTemplates} onImportTemplates={handleImportTemplates} /> ); }; export default FormRecognizerPage;