import { Box, Typography, Container, List, ListItem, ListItemText, IconButton, Switch, Divider, Paper, alpha, Snackbar, Alert, } from '@mui/material'; import DeleteIcon from '@mui/icons-material/Delete'; import AutoFixHighIcon from '@mui/icons-material/AutoFixHigh'; import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'; import FileDownloadIcon from '@mui/icons-material/FileDownload'; import { useEffect, useState } from 'react'; import { storageUtil } from '@/utils/chromeStorage'; import { FormMapEntry } from '@/types/storage'; import PageHeader from '@/components/PageHeader'; import Button from '@/components/Button'; import { globalStyles, formMappingPageStyles } from '@/config/pageTheme.ts'; export default function FormMappingPage() { const [entries, setEntries] = useState([]); const [isPicking, setIsPicking] = useState(false); const [exportError, setExportError] = useState(null); const [showExportSuccess, setShowExportSuccess] = useState(false); useEffect(() => { const loadData = async () => { const data = (await storageUtil.get('active_form_map')) as FormMapEntry[]; setEntries(data || []); const picking = (await storageUtil.get('app/formMapping/isPicking')) as boolean; setIsPicking(picking || false); }; loadData(); const listener = (changes: { [key: string]: chrome.storage.StorageChange }, area: string) => { if (area === 'local') { if (changes['active_form_map']) { setEntries((changes['active_form_map'].newValue as FormMapEntry[]) || []); } if (changes['app/formMapping/isPicking']) { setIsPicking((changes['app/formMapping/isPicking'].newValue as boolean) || false); } } }; chrome.storage.onChanged.addListener(listener); return () => chrome.storage.onChanged.removeListener(listener); }, []); const togglePicking = async () => { await storageUtil.set('app/formMapping/isPicking', !isPicking); }; const deleteEntry = async (id: string) => { const newEntries = entries.filter((e) => e.id !== id); await storageUtil.set('active_form_map', newEntries); }; const toggleSelection = async (id: string) => { const newEntries = entries.map((e) => e.id === id ? { ...e, ui_state: { ...e.ui_state, is_selected: !e.ui_state.is_selected } } : e, ); await storageUtil.set('active_form_map', newEntries); }; const clearAll = async () => { await storageUtil.set('active_form_map', []); await storageUtil.set('app/formMapping/isPicking', false); }; const exportConfig = () => { try { if (entries.length === 0) { setExportError('没有可导出的配置数据'); return; } const jsonStr = JSON.stringify(entries, null, 2); const blob = new Blob([jsonStr], { type: 'application/json' }); const url = URL.createObjectURL(blob); const date = new Date(); const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; const filename = `form-mapping-config-${dateStr}.json`; const link = document.createElement('a'); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); setShowExportSuccess(true); } catch (error) { console.error('导出配置失败:', error); setExportError(error instanceof Error ? error.message : '导出失败,请重试'); } }; return ( } /> 状态控制 点击“开始拾取”后,直接在网页上点击想要映射的表单元素。 已拾取字段 ({entries.length}) {entries.length === 0 ? ( ) : ( entries.map((entry, index) => ( {index > 0 && } deleteEntry(entry.id)} sx={{ color: 'error.light' }} > } sx={{ py: 1.5 }} > toggleSelection(entry.id)} /> )) )} {entries.length > 0 && ( 映射配置导出 (JSON)
{JSON.stringify(entries, null, 2)}
)}
setExportError(null)} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} > setExportError(null)}> {exportError} setShowExportSuccess(false)} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} > setShowExportSuccess(false)}> 配置导出成功!
); }