-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ 高级参数设置
+
+
+
+
+
setTempAdvancedParams({
+ ...tempAdvancedParams,
+ max_new_tokens: parseInt(e.target.value) || 2048
+ })}
+ />
+
+ {ADVANCED_PARAMS_INFO.max_new_tokens.description}
+
+
+
+
+
setTempAdvancedParams({
+ ...tempAdvancedParams,
+ temperature: parseFloat(e.target.value) || 0.3
+ })}
+ />
+
+ {ADVANCED_PARAMS_INFO.temperature.description}
+
+
+
+
+
setTempAdvancedParams({
+ ...tempAdvancedParams,
+ top_k: parseInt(e.target.value) || 20
+ })}
+ />
+
+ {ADVANCED_PARAMS_INFO.top_k.description}
+
+
+
+
+
setTempAdvancedParams({
+ ...tempAdvancedParams,
+ top_p: parseFloat(e.target.value) || 0.7
+ })}
+ />
+
+ {ADVANCED_PARAMS_INFO.top_p.description}
+
+
+
+
+
setTempAdvancedParams({
+ ...tempAdvancedParams,
+ repetition_penalty: parseFloat(e.target.value) || 1.05
+ })}
+ />
+
+ {ADVANCED_PARAMS_INFO.repetition_penalty.description}
+
+
+
+
+ {
+ setTempAdvancedParams({
+ max_new_tokens: watch('max_new_tokens'),
+ temperature: watch('temperature'),
+ top_k: watch('top_k'),
+ top_p: watch('top_p'),
+ repetition_penalty: watch('repetition_penalty')
+ })
+ setAdvancedOpen(false)
+ }}
+ >
+ 取消
+
+ {
+ setValue('max_new_tokens', tempAdvancedParams.max_new_tokens)
+ setValue('temperature', tempAdvancedParams.temperature)
+ setValue('top_k', tempAdvancedParams.top_k)
+ setValue('top_p', tempAdvancedParams.top_p)
+ setValue('repetition_penalty', tempAdvancedParams.repetition_penalty)
+ setAdvancedOpen(false)
+ }}
+ >
+ 确定
+
+
+
+
-
- {isLoading ? '创建中...' : '生成语音'}
-
+
+
+
+
+
+ {isLoading ? '创建中...' : '生成语音'}
+
+
+
+ 生成语音
+
+
+
{isPolling &&
}
diff --git a/qwen3-tts-frontend/src/components/tts/VoiceCloneForm.tsx b/qwen3-tts-frontend/src/components/tts/VoiceCloneForm.tsx
index 63bce2d..d783c58 100644
--- a/qwen3-tts-frontend/src/components/tts/VoiceCloneForm.tsx
+++ b/qwen3-tts-frontend/src/components/tts/VoiceCloneForm.tsx
@@ -6,11 +6,13 @@ import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
-import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from '@/components/ui/dialog'
import { Checkbox } from '@/components/ui/checkbox'
import { Label } from '@/components/ui/label'
-import { ChevronDown } from 'lucide-react'
+import { Settings, Globe2, Type, Play, FileText, Mic, Zap, Database } from 'lucide-react'
import { toast } from 'sonner'
+import { IconLabel } from '@/components/IconLabel'
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import { ttsApi, jobApi } from '@/lib/api'
import { useJobPolling } from '@/hooks/useJobPolling'
import { LoadingState } from '@/components/LoadingState'
@@ -41,6 +43,9 @@ function VoiceCloneForm() {
const [languages, setLanguages] = useState
([])
const [isLoading, setIsLoading] = useState(false)
const [advancedOpen, setAdvancedOpen] = useState(false)
+ const [tempAdvancedParams, setTempAdvancedParams] = useState({
+ max_new_tokens: 2048
+ })
const { currentJob, isPolling, isCompleted, startPolling, elapsedTime } = useJobPolling()
@@ -101,9 +106,9 @@ function VoiceCloneForm() {
}, [currentJob?.id, currentJob?.audio_url])
return (
-