'use client'; import { useState, useRef } from 'react'; import { Dialog, DialogContent, DialogActions, Button, Box, Typography, TextField, Alert, LinearProgress, Chip, IconButton, Radio } from '@mui/material'; import CloudUploadIcon from '@mui/icons-material/CloudUpload'; import DownloadIcon from '@mui/icons-material/Download'; import CloseIcon from '@mui/icons-material/Close'; import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'; import { useTranslation } from 'react-i18next'; import * as XLSX from 'xlsx'; import { QUESTION_TYPES, FORMAT_PREVIEW, getJsonTemplateData, getExcelTemplateData, getColumnWidths } from '../constants'; import { StyledDialogTitle, UploadBox, PreviewPaper, CodeBlock, ErrorContainer, TypeRadioGroup, TypeFormControlLabel } from './ImportDialog.styles'; export default function ImportDialog({ open, onClose, projectId, onSuccess }) { const { t } = useTranslation(); const fileInputRef = useRef(null); const [questionType, setQuestionType] = useState('open_ended'); const [tags, setTags] = useState(''); const [file, setFile] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [errorDetails, setErrorDetails] = useState([]); // 处理文件选择 const handleFileChange = e => { const selectedFile = e.target.files[0]; if (selectedFile) { const ext = selectedFile.name.split('.').pop().toLowerCase(); if (!['json', 'xls', 'xlsx'].includes(ext)) { setError(t('evalDatasets.import.invalidFileType', '不支持的文件格式,请上传 json、xls 或 xlsx 文件')); return; } setFile(selectedFile); setError(null); setErrorDetails([]); } }; // 下载模板 const handleDownloadTemplate = format => { if (!questionType) { setError(t('evalDatasets.import.selectTypeFirst', '请先选择题型')); return; } if (format === 'json') { // JSON 模板动态生成并下载 const templateData = getJsonTemplateData(questionType); const jsonContent = JSON.stringify(templateData, null, 2); const blob = new Blob([jsonContent], { type: 'application/json' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = `eval-dataset-template-${questionType}.json`; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } else { // Excel 模板动态生成 const templateData = getExcelTemplateData(questionType); const worksheet = XLSX.utils.json_to_sheet(templateData); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, 'Template'); // 设置列宽 const colWidths = getColumnWidths(questionType); worksheet['!cols'] = colWidths; // 下载文件 XLSX.writeFile(workbook, `eval-dataset-template-${questionType}.xlsx`); } }; // 提交导入 const handleSubmit = async () => { if (!questionType) { setError(t('evalDatasets.import.selectTypeFirst', '请先选择题型')); return; } if (!file) { setError(t('evalDatasets.import.selectFile', '请选择要导入的文件')); return; } setLoading(true); setError(null); setErrorDetails([]); try { const formData = new FormData(); formData.append('file', file); formData.append('questionType', questionType); formData.append('tags', tags); const response = await fetch(`/api/projects/${projectId}/eval-datasets/import`, { method: 'POST', body: formData }); const result = await response.json(); if (result.code === 0) { onSuccess?.(result.data); handleClose(); } else { setError(result.error || result.message); if (result.details) { setErrorDetails(result.details); } } } catch (err) { setError(err.message || t('evalDatasets.import.failed', '导入失败')); } finally { setLoading(false); } }; // 关闭对话框 const handleClose = () => { if (loading) return; setQuestionType('open_ended'); setTags(''); setFile(null); setError(null); setErrorDetails([]); onClose(); }; // 获取当前题型的格式预览 const formatPreview = questionType ? FORMAT_PREVIEW[questionType] : null; return ( {t('evalDatasets.import.title', '导入评估数据集')} {loading && } {/* 错误提示 */} {error && ( {error} {errorDetails.length > 0 && ( {errorDetails.map((detail, index) => ( {detail} ))} {errorDetails.length < 10 && ( {t('evalDatasets.import.showingErrors', '显示前 {{count}} 条错误', { count: errorDetails.length })} )} )} )} {/* 题型选择 - 使用封装好的样式组件 */} {t('evalDatasets.import.questionType', '选择题型')} setQuestionType(e.target.value)}> {QUESTION_TYPES.map(type => ( } label={t(type.label, type.labelZh)} /> ))} {/* 数据格式预览 */} {formatPreview && ( {t('evalDatasets.import.formatPreview', '数据格式预览')} {formatPreview.fields.map(field => ( ))} {formatPreview.description}
{JSON.stringify(formatPreview.example, null, 2)}
{/* 下载模板按钮 */}
)} {/* 文件上传 */} fileInputRef.current?.click()}> {file ? ( {file.name} {t('common.clickToReplace', '点击更换文件')} ) : ( {t('evalDatasets.import.dropOrClick', '点击或拖拽文件到此处')} {t('evalDatasets.import.supportedFormats', '支持 JSON、XLS、XLSX 格式')} )} {/* 标签输入 */} setTags(e.target.value)} disabled={loading} helperText={t('evalDatasets.import.tagsHelp', '导入的所有数据将打上这些标签')} InputProps={{ startAdornment: tags ? # : null }} />
); }