Files

221 lines
7.0 KiB
JavaScript
Raw Permalink Normal View History

2026-03-17 14:36:31 +08:00
'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>
);
}