'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} {/* 吸底保存按钮 */} ); }