60537f6e2e
✨新功能 (Features) 智能表单引擎: 新增智能表单填充功能,内置模糊匹配引擎、Mock数据生成器与视觉反馈渲染器。 表单映射与导出: 实现表单映射页面(包含扫描器和高亮器),并支持将配置导出为 JSON 文件,附带 Snackbar 状态提示。 表单识别增强: 增加按域名保存字段类型偏好的功能;添加字段定位闪烁以辅助查找;优化填充逻辑(支持单字段覆盖默认模式);重构 FieldList 组件以提升操作体验。 ♻️ 代码重构 (Refactor) 通用组件提取: 提取并统一应用通用的 PageHeader 组件,移除独立的侧边栏页面及未使用的组件文件。 状态与逻辑优化: 改进 useStorageState 钩子(增加加载状态管理与防抖处理);将二维码解析功能重构为独立模块。 类型与依赖简化: 统一使用 SnackbarOptions 类型;简化假数据生成器中 faker 的导入与使用逻辑。 💄 样式与界面 (Style) UI 细节打磨: 统一各页面头部图标颜色,调整表单输入框与按钮交互样式;优化时间戳页面、结果视图布局(增加圆角、调整内边距/对齐方式);重构存储选项网格及自动刷新开关样式。 代码格式: 优化项目中导入语句的顺序与格式。 👷 持续集成 (CI) 流程提效: 移除 Firefox 测试步骤以减少资源消耗;收紧工作流触发条件,移除 develop 及其变体分支,仅保留 main 分支触发。 📝 文档 (Docs) 代码维护: 补充组件的文档注释与类型导入。
117 lines
3.3 KiB
TypeScript
117 lines
3.3 KiB
TypeScript
import { useState } from 'react';
|
|
import { Box, TextField, Alert, Stack, alpha } from '@mui/material';
|
|
import AddIcon from '@mui/icons-material/Add';
|
|
import Button from '@/components/Button';
|
|
import type { OpenUrlEntry } from '@/types/storage';
|
|
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
|
import { openUrlPageStyles } from '@/config/pageTheme';
|
|
|
|
interface UrlEntryFormProps {
|
|
onAddEntry: (entry: OpenUrlEntry) => void;
|
|
showMessage: (message: string, options?: SnackbarOptions) => void;
|
|
}
|
|
|
|
const UrlEntryForm = ({ onAddEntry, showMessage }: UrlEntryFormProps) => {
|
|
const [newName, setNewName] = useState<string>('');
|
|
const [newUrl, setNewUrl] = useState<string>('');
|
|
|
|
const showMixedContentWarning =
|
|
newUrl.startsWith('http://') && !newUrl.includes('localhost') && !newUrl.includes('127.0.0.1');
|
|
|
|
const isValidUrl = (url: string) => {
|
|
if (!url.trim()) return false;
|
|
try {
|
|
new URL(url);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const handleAddEntry = () => {
|
|
if (!newName.trim()) {
|
|
showMessage('请输入名称', { severity: 'error' });
|
|
return;
|
|
}
|
|
if (!isValidUrl(newUrl)) {
|
|
showMessage('请输入有效的 URL', { severity: 'error' });
|
|
return;
|
|
}
|
|
|
|
onAddEntry({ name: newName.trim(), url: newUrl.trim() });
|
|
setNewName('');
|
|
setNewUrl('');
|
|
showMessage('添加成功', { severity: 'success' });
|
|
};
|
|
|
|
return (
|
|
<Box
|
|
sx={{
|
|
bgcolor: 'background.paper',
|
|
p: 2,
|
|
borderRadius: 4,
|
|
border: '1px solid',
|
|
borderColor: 'grey.100',
|
|
mb: 3,
|
|
boxShadow: '0 4px 12px rgba(0,0,0,0.02)',
|
|
}}
|
|
>
|
|
<Stack spacing={2}>
|
|
<TextField
|
|
label="环境名称"
|
|
placeholder="例如: 本地文档"
|
|
value={newName}
|
|
onChange={(e) => setNewName(e.target.value)}
|
|
fullWidth
|
|
variant="outlined"
|
|
sx={openUrlPageStyles.INPUT_STYLE}
|
|
/>
|
|
<TextField
|
|
label="目标 URL"
|
|
placeholder="例如: http://localhost:8000/docs"
|
|
value={newUrl}
|
|
onChange={(e) => setNewUrl(e.target.value)}
|
|
fullWidth
|
|
variant="outlined"
|
|
sx={openUrlPageStyles.INPUT_STYLE}
|
|
/>
|
|
|
|
{showMixedContentWarning && (
|
|
<Alert
|
|
severity="warning"
|
|
sx={{
|
|
borderRadius: 3,
|
|
'& .MuiAlert-message': { fontSize: '0.7rem', fontWeight: 600, lineHeight: 1.4 },
|
|
}}
|
|
>
|
|
混合内容警告:当前 HTTPS 页面无法加载 HTTP 资源。
|
|
</Alert>
|
|
)}
|
|
|
|
<Button
|
|
variant="contained"
|
|
onClick={handleAddEntry}
|
|
disabled={!newName.trim() || !isValidUrl(newUrl)}
|
|
fullWidth
|
|
startIcon={<AddIcon />}
|
|
sx={{
|
|
py: 1.2,
|
|
borderRadius: 4,
|
|
bgcolor: openUrlPageStyles.themeColor,
|
|
fontWeight: 800,
|
|
boxShadow: 'none',
|
|
'&:hover': {
|
|
bgcolor: openUrlPageStyles.primaryDark,
|
|
boxShadow: `0 8px 24px ${alpha(openUrlPageStyles.primaryColor, 0.2)}`,
|
|
},
|
|
}}
|
|
>
|
|
添加快捷方式
|
|
</Button>
|
|
</Stack>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default UrlEntryForm;
|