Files
testing-tool/entrypoints/popup/pages/FormRecognizerPage.tsx
T
LingandRX 0379f96e80 Develop fill form (#10)
* feat(formRecognizer): 添加表单识别功能及相关组件

添加表单识别功能,包括以下内容:
1. 在路由配置中添加表单识别页面
2. 实现表单识别页面和侧边栏面板
3. 添加表单数据生成工具类
4. 实现与内容脚本的通信机制
5. 添加faker-js依赖用于生成测试数据
6. 支持不同入口点(popup/sidepanel)的组件渲染

* refactor(消息通信): 重构消息通信机制并集中管理消息协议

将分散的消息协议和通信逻辑集中到 utils/messages.ts 中
移除旧的 messages.tsx 文件并更新相关引用
添加消息动作枚举和类型定义,提高类型安全性
优化内容脚本注入失败时的处理逻辑
2026-04-20 22:50:01 +08:00

194 lines
6.3 KiB
TypeScript

import { useState } from 'react';
import {
Box,
Typography,
Container,
Button,
Paper,
CircularProgress,
Stack,
Switch,
FormControlLabel,
} from '@mui/material';
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
import ClearAllIcon from '@mui/icons-material/ClearAll';
import GlobalSnackbar, { useSnackbar } from '@/components/GlobalSnackbar';
import { dashboardPageStyles } from '@/config/pageTheme';
const FormRecognizerPage = () => {
const { snackbarProps, showMessage } = useSnackbar({ autoHideDuration: 1500 });
const [loading, setLoading] = useState(false);
const [includeHidden, setIncludeHidden] = useState(false);
interface MessagePayload {
includeHidden?: boolean;
}
const sendMessageToContent = async (action: string, payload?: MessagePayload) => {
setLoading(true);
try {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab.id) {
showMessage('无法获取当前标签页', { severity: 'error' });
return;
}
const response = await chrome.tabs.sendMessage(tab.id, { action, ...payload });
if (response.success) {
showMessage(response.message, { severity: 'success' });
} else {
showMessage(response.message, { severity: 'error' });
}
} catch (error) {
console.error('发送消息失败:', error);
showMessage('请确保当前页面已加载完成', { severity: 'error' });
} finally {
setLoading(false);
}
};
const handleFillValidData = () => {
sendMessageToContent('fillValidData', { includeHidden });
};
const handleFillInvalidData = () => {
sendMessageToContent('fillInvalidData', { includeHidden });
};
const handleClearAllFields = () => {
sendMessageToContent('clearAllFields');
};
return (
<Box sx={{ bgcolor: dashboardPageStyles.backgroundColor, minHeight: '100%', pb: 4 }}>
<Container maxWidth="sm" sx={{ py: 3, px: 2 }}>
<Box sx={{ mb: 4 }}>
<Typography variant="h6" component="h1" sx={{ fontWeight: 700, mb: 1 }}>
Dummy Data Generator
</Typography>
<Typography variant="body2" color="text.secondary">
一键填充表单测试数据,提升开发和测试效率
</Typography>
</Box>
{/* 主要操作按钮 */}
<Stack spacing={2} sx={{ mb: 4 }}>
<Button
variant="contained"
startIcon={
loading ? <CircularProgress size={16} color="inherit" /> : <AutoAwesomeIcon />
}
onClick={handleFillValidData}
disabled={loading}
fullWidth
sx={{
py: 1.2,
borderRadius: 3,
bgcolor: '#4caf50',
fontWeight: 700,
'&:hover': {
bgcolor: '#388e3c',
},
}}
>
{loading ? '填充中...' : '一键填充(有效数据)'}
</Button>
<Button
variant="contained"
startIcon={
loading ? <CircularProgress size={16} color="inherit" /> : <ErrorOutlineIcon />
}
onClick={handleFillInvalidData}
disabled={loading}
fullWidth
sx={{
py: 1.2,
borderRadius: 3,
bgcolor: '#ff9800',
fontWeight: 700,
'&:hover': {
bgcolor: '#f57c00',
},
}}
>
{loading ? '填充中...' : '一键填充(异常数据)'}
</Button>
<Button
variant="outlined"
startIcon={loading ? <CircularProgress size={16} color="inherit" /> : <ClearAllIcon />}
onClick={handleClearAllFields}
disabled={loading}
fullWidth
sx={{
py: 1.2,
borderRadius: 3,
borderColor: '#f44336',
color: '#f44336',
fontWeight: 700,
'&:hover': {
borderColor: '#d32f2f',
bgcolor: 'rgba(244, 67, 54, 0.05)',
},
}}
>
{loading ? '清空ing...' : '一键清空所有表单'}
</Button>
</Stack>
{/* 选项设置 */}
<Paper elevation={0} sx={{ borderRadius: 4, overflow: 'hidden', mb: 4 }}>
<Box sx={{ borderBottom: 1, borderColor: 'divider', px: 2, py: 1.5 }}>
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>
填充选项
</Typography>
</Box>
<Box sx={{ p: 2 }}>
<FormControlLabel
control={
<Switch
checked={includeHidden}
onChange={(e) => setIncludeHidden(e.target.checked)}
color="primary"
/>
}
label="包含隐藏字段"
sx={{ width: '100%' }}
/>
</Box>
</Paper>
{/* 功能说明 */}
<Paper elevation={0} sx={{ borderRadius: 4, overflow: 'hidden' }}>
<Box sx={{ borderBottom: 1, borderColor: 'divider', px: 2, py: 1.5 }}>
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>
功能说明
</Typography>
</Box>
<Box sx={{ p: 2 }}>
<Typography variant="body2" sx={{ mb: 1 }}>
<strong>有效数据模式:</strong>生成符合格式要求的测试数据,适用于正常功能测试。
</Typography>
<Typography variant="body2" sx={{ mb: 1 }}>
<strong>异常数据模式:</strong>生成边界值或格式错误的数据,适用于异常场景测试。
</Typography>
<Typography variant="body2" sx={{ mb: 1 }}>
<strong>一键清空:</strong>快速清空当前页面所有表单字段的值。
</Typography>
<Typography variant="body2">
<strong>支持的字段类型:</strong>
文本、邮箱、手机号、数字、日期、文本域、密码、身份证号等。
</Typography>
</Box>
</Paper>
<GlobalSnackbar {...snackbarProps} />
</Container>
</Box>
);
};
export default FormRecognizerPage;