'use client';
import { useState, useEffect } from 'react';
import {
Typography,
Box,
Button,
TextField,
Grid,
Card,
CardContent,
Slider,
InputAdornment,
Alert,
Snackbar,
FormControl,
Select,
InputLabel,
MenuItem,
Chip,
FormHelperText
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import SaveIcon from '@mui/icons-material/Save';
import useTaskSettings from '@/hooks/useTaskSettings';
export default function TaskSettings({ projectId }) {
const { t } = useTranslation();
const { taskSettings, setTaskSettings, loading, error, success, setSuccess } = useTaskSettings(projectId);
// 确保 multiTurnRounds 有正确的初始值
useEffect(() => {
if (
!loading &&
taskSettings &&
(taskSettings.multiTurnRounds === undefined || taskSettings.multiTurnRounds === null)
) {
setTaskSettings(prev => ({
...prev,
multiTurnRounds: 3 // 默认值
}));
}
}, [loading, taskSettings, setTaskSettings]);
// 处理设置变更
const handleSettingChange = e => {
const { name, value } = e.target;
setTaskSettings(prev => ({
...prev,
[name]: value
}));
};
// 处理滑块变更
const handleSliderChange = name => (event, newValue) => {
setTaskSettings(prev => ({
...prev,
[name]: newValue
}));
};
// 保存任务配置
const handleSaveTaskSettings = async () => {
try {
// 确保数组类型的数据被正确处理
const settingsToSave = { ...taskSettings };
// 确保递归分块的分隔符数组存在
if (settingsToSave.splitType === 'recursive' && settingsToSave.separatorsInput) {
if (!settingsToSave.separators || !Array.isArray(settingsToSave.separators)) {
settingsToSave.separators = settingsToSave.separatorsInput.split(',').map(item => item.trim());
}
}
console.log('Saving settings:', settingsToSave);
const response = await fetch(`/api/projects/${projectId}/tasks`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(settingsToSave)
});
if (!response.ok) {
throw new Error(t('settings.saveTasksFailed'));
}
setSuccess(true);
} catch (error) {
console.error('保存任务配置出错:', error);
//setError(error.message);
}
};
const handleCloseSnackbar = () => {
setSuccess(false);
//setError(null);
};
if (loading) {
return {t('common.loading')};
}
return (
{' '}
{/* 添加底部填充,为固定按钮留出空间 */}
{t('settings.textSplitSettings')}
{/* 分块策略选择 */}
{t('settings.splitType')}
{/* Markdown模式设置 */}
{(!taskSettings.splitType || taskSettings.splitType === 'markdown') && (
<>
{t('settings.minLength')}: {taskSettings.textSplitMinLength}
{t('settings.maxLength')}: {taskSettings.textSplitMaxLength}
>
)}
{/* 通用 LangChain 参数设置 */}
{taskSettings.splitType && taskSettings.splitType !== 'markdown' && (
<>
{t('settings.chunkSize')}: {taskSettings.chunkSize || 3000}
{t('settings.chunkOverlap')}: {taskSettings.chunkOverlap || 200}
>
)}
{/* Text 分块器特殊设置 */}
{taskSettings.splitType === 'text' && (
)}
{/* 自定义符号分块器特殊设置 */}
{taskSettings.splitType === 'custom' && (
)}
{/* Code 分块器特殊设置 */}
{taskSettings.splitType === 'code' && (
{t('settings.codeLanguage')}
{t('settings.codeLanguageHelper')}
)}
{/* Recursive 分块器特殊设置 */}
{taskSettings.splitType === 'recursive' && (
{t('settings.separators')}
,-'}
onChange={e => {
const value = e.target.value;
// 同时更新输入框值和分隔符数组
setTaskSettings(prev => ({
...prev,
separatorsInput: value,
separators: value.split(',').map(item => item.trim())
}));
}}
helperText={t('settings.separatorsHelper')}
/>
{(taskSettings.separators || ['|', '##', '>', '-']).map((sep, index) => (
))}
)}
{t('settings.textSplitDescription')}
{t('settings.questionGenSettings')}
{t('settings.questionGenLength', { length: taskSettings.questionGenerationLength })}
{t('settings.questionGenDescription')}
{t('settings.questionMaskRemovingProbability', {
probability: taskSettings.questionMaskRemovingProbability
})}
{t('settings.pdfSettings')}
{/* 多轮对话数据集设置 */}
{t('settings.multiTurnSettings')}
{/* 系统提示词 */}
{/* 对话场景 */}
{/* 对话轮数 */}
{t('settings.multiTurnRounds', { rounds: taskSettings.multiTurnRounds || 3 })}
{/* 角色A设定 */}
{/* 角色B设定 */}
{t('settings.multiTurnDescription')}
{/* 测试集生成设置 */}
{t('settings.evalQuestionSettings')}
{t('settings.evalQuestionSettingsDescription')}
{
const value = Math.max(0, parseInt(e.target.value) || 0);
setTaskSettings(prev => ({
...prev,
evalQuestionTypeRatios: {
...prev.evalQuestionTypeRatios,
true_false: value
}
}));
}}
InputProps={{ inputProps: { min: 0 } }}
/>
{/* 单选题 */}
{
const value = Math.max(0, parseInt(e.target.value) || 0);
setTaskSettings(prev => ({
...prev,
evalQuestionTypeRatios: {
...prev.evalQuestionTypeRatios,
single_choice: value
}
}));
}}
InputProps={{ inputProps: { min: 0 } }}
/>
{/* 多选题 */}
{
const value = Math.max(0, parseInt(e.target.value) || 0);
setTaskSettings(prev => ({
...prev,
evalQuestionTypeRatios: {
...prev.evalQuestionTypeRatios,
multiple_choice: value
}
}));
}}
InputProps={{ inputProps: { min: 0 } }}
/>
{/* 固定短答案 */}
{
const value = Math.max(0, parseInt(e.target.value) || 0);
setTaskSettings(prev => ({
...prev,
evalQuestionTypeRatios: {
...prev.evalQuestionTypeRatios,
short_answer: value
}
}));
}}
InputProps={{ inputProps: { min: 0 } }}
/>
{/* 开放式回答 */}
{
const value = Math.max(0, parseInt(e.target.value) || 0);
setTaskSettings(prev => ({
...prev,
evalQuestionTypeRatios: {
...prev.evalQuestionTypeRatios,
open_ended: value
}
}));
}}
InputProps={{ inputProps: { min: 0 } }}
/>
{t('settings.evalQuestionRatioHelper')}
{t('settings.huggingfaceSettings')}
{t('settings.saveSuccess')}
{error}
{/* 吸底保存按钮 */}
}
onClick={handleSaveTaskSettings}
>
{t('settings.saveTaskConfig')}
);
}