Files
YG-Datasets/easy-dataset-main/app/projects/[projectId]/questions/components/QuestionEditDialog.js

221 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useState, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Button,
Box,
Autocomplete,
TextField as MuiTextField,
FormControl,
InputLabel,
Select,
MenuItem
} from '@mui/material';
import axios from 'axios';
export default function QuestionEditDialog({
open,
onClose,
onSubmit,
initialData,
projectId,
tags,
mode = 'create' // 'create' or 'edit'
}) {
const [chunks, setChunks] = useState([]);
const [images, setImages] = useState([]);
const { t } = useTranslation();
// 获取文本块的标题
const getChunkTitle = chunkId => {
const chunk = chunks.find(c => c.id === chunkId);
return chunk?.name || chunkId; // 直接使用文件名
};
const [formData, setFormData] = useState({
id: '',
question: '',
sourceType: 'text', // 新增:数据源类型
chunkId: '',
imageId: '', // 新增图片ID
label: '' // 默认不选中任何标签
});
const getChunks = async projectId => {
// 获取文本块列表
const response = await axios.get(`/api/projects/${projectId}/split`);
if (response.status !== 200) {
throw new Error(t('common.fetchError'));
}
setChunks(response.data.chunks || []);
};
const getImages = async projectId => {
// 获取图片列表只获取ID和名称
try {
const response = await axios.get(`/api/projects/${projectId}/images?page=1&pageSize=10000&simple=true`);
if (response.status === 200) {
setImages(response.data.data || []);
}
} catch (error) {
console.error('Failed to fetch images:', error);
}
};
useEffect(() => {
getChunks(projectId);
getImages(projectId);
if (initialData) {
// 根据 imageId 判断数据源类型
console.log('initialData:', initialData);
const sourceType = initialData.imageId ? 'image' : 'text';
setFormData({
id: initialData.id,
question: initialData.question || '',
sourceType: sourceType,
chunkId: initialData.chunkId || '',
imageId: initialData.imageId || '',
label: initialData.label || 'other' // 改用 label 而不是 label
});
} else {
setFormData({
id: '',
question: '',
sourceType: 'text',
chunkId: '',
imageId: '',
label: ''
});
}
}, [initialData]);
const handleSubmit = () => {
onSubmit(formData);
onClose();
};
const flattenTags = (tags = [], prefix = '') => {
let flatTags = [];
const traverse = node => {
flatTags.push({
id: node.label, // 使用标签名作为 id
label: node.label, // 直接使用原始标签名
originalLabel: node.label
});
if (node.child && node.child.length > 0) {
node.child.forEach(child => traverse(child));
}
};
tags.forEach(tag => traverse(tag));
flatTags.push({
id: 'other',
label: t('datasets.uncategorized'),
originalLabel: 'other'
});
return flatTags;
};
const flattenedTags = useMemo(() => flattenTags(tags), [tags, t]);
return (
<Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
<DialogTitle>{mode === 'create' ? t('questions.createQuestion') : t('questions.editQuestion')}</DialogTitle>
<DialogContent>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, mt: 2 }}>
{/* 数据源类型选择 */}
<FormControl fullWidth>
<InputLabel>{t('questions.sourceType', { defaultValue: '数据源类型' })}</InputLabel>
<Select
value={formData.sourceType}
label={t('questions.sourceType', { defaultValue: '数据源类型' })}
onChange={e => {
setFormData({
...formData,
sourceType: e.target.value,
chunkId: '',
imageId: ''
});
}}
>
<MenuItem value="text">{t('questions.template.sourceType.text')}</MenuItem>
<MenuItem value="image">{t('questions.template.sourceType.image')}</MenuItem>
</Select>
</FormControl>
{/* 问题内容 */}
<TextField
label={t('questions.questionContent')}
multiline
rows={4}
fullWidth
value={formData.question}
onChange={e => setFormData({ ...formData, question: e.target.value })}
/>
{/* 文本块选择(仅当数据源为文本时显示) */}
{formData.sourceType === 'text' && (
<Autocomplete
fullWidth
options={chunks}
getOptionLabel={chunk => getChunkTitle(chunk.id)}
value={chunks.find(chunk => chunk.id === formData.chunkId) || null}
onChange={(e, newValue) => setFormData({ ...formData, chunkId: newValue ? newValue.id : '' })}
renderInput={params => (
<MuiTextField {...params} label={t('questions.selectChunk')} placeholder={t('questions.searchChunk')} />
)}
/>
)}
{/* 图片选择(仅当数据源为图片时显示) */}
{formData.sourceType === 'image' && (
<Autocomplete
fullWidth
options={images}
getOptionLabel={image => image.imageName || ''}
value={images.find(image => image.id === formData.imageId) || null}
onChange={(e, newValue) => setFormData({ ...formData, imageId: newValue ? newValue.id : '' })}
renderInput={params => (
<MuiTextField
{...params}
label={t('questions.selectImage', { defaultValue: '选择图片' })}
placeholder={t('questions.searchImage', { defaultValue: '搜索图片...' })}
/>
)}
/>
)}
{/* 标签选择 */}
{formData.sourceType === 'text' && (
<Autocomplete
fullWidth
options={flattenedTags}
getOptionLabel={tag => tag.label}
value={flattenedTags.find(tag => tag.id === formData.label) || null}
onChange={(e, newValue) => setFormData({ ...formData, label: newValue ? newValue.id : '' })}
renderInput={params => (
<MuiTextField {...params} label={t('questions.selectTag')} placeholder={t('questions.searchTag')} />
)}
/>
)}
</Box>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>{t('common.cancel')}</Button>
<Button
onClick={handleSubmit}
variant="contained"
disabled={!formData.question || (formData.sourceType === 'text' ? !formData.chunkId : !formData.imageId)}
>
{mode === 'create' ? t('common.create') : t('common.save')}
</Button>
</DialogActions>
</Dialog>
);
}