diff --git a/qwen3-tts-backend/core/tts_service.py b/qwen3-tts-backend/core/tts_service.py index b9d28f6..e58c33b 100644 --- a/qwen3-tts-backend/core/tts_service.py +++ b/qwen3-tts-backend/core/tts_service.py @@ -330,15 +330,43 @@ class AliyunTTSBackend(TTSBackend): async def health_check(self) -> dict: try: - import httpx - async with httpx.AsyncClient() as client: - resp = await client.get( - self.http_url.replace('/customization', '/health'), - headers={"Authorization": f"Bearer {self.api_key}"}, - timeout=5 - ) - return {"available": resp.status_code < 500} - except: + from core.config import settings + url = f"{self.ws_url}?model={settings.ALIYUN_MODEL_FLASH}" + headers = {"Authorization": f"Bearer {self.api_key}"} + + async with websockets.connect(url, additional_headers=headers, close_timeout=3) as ws: + await ws.send(json.dumps({ + "type": "session.update", + "session": { + "mode": "server_commit", + "voice": "Cherry", + "language_type": "zh", + "response_format": "pcm", + "sample_rate": 24000 + } + })) + + await ws.send(json.dumps({ + "type": "input_text_buffer.append", + "text": "测试" + })) + + await ws.send(json.dumps({ + "type": "session.finish" + })) + + async for message in ws: + event = json.loads(message) + event_type = event.get('type') + + if event_type == 'error': + return {"available": False} + elif event_type in ['response.audio.delta', 'session.finished']: + return {"available": True} + + return {"available": True} + except Exception as e: + logger.warning(f"Aliyun health check failed: {e}") return {"available": False} @staticmethod diff --git a/qwen3-tts-frontend/src/components/JobDetailDialog.tsx b/qwen3-tts-frontend/src/components/JobDetailDialog.tsx index 39676c2..6d52aae 100644 --- a/qwen3-tts-frontend/src/components/JobDetailDialog.tsx +++ b/qwen3-tts-frontend/src/components/JobDetailDialog.tsx @@ -3,6 +3,7 @@ import type { Job } from '@/types/job' import { Dialog, DialogContent, + DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog' @@ -76,6 +77,7 @@ const JobDetailDialog = memo(({ job, open, onOpenChange }: JobDetailDialogProps) {formatTimestamp(job.created_at)} + 查看任务的详细参数和生成结果 diff --git a/qwen3-tts-frontend/src/components/Navbar.tsx b/qwen3-tts-frontend/src/components/Navbar.tsx index b307fe7..ac691a8 100644 --- a/qwen3-tts-frontend/src/components/Navbar.tsx +++ b/qwen3-tts-frontend/src/components/Navbar.tsx @@ -1,4 +1,4 @@ -import { Menu, LogOut, Users, Settings } from 'lucide-react' +import { Menu, LogOut, Users, Settings, AudioLines } from 'lucide-react' import { Link } from 'react-router-dom' import { Button } from '@/components/ui/button' import { ThemeToggle } from '@/components/ThemeToggle' @@ -25,8 +25,9 @@ export function Navbar({ onToggleSidebar }: NavbarProps) { )}
- -

+ + +

Qwen3-TTS-WebUI

diff --git a/qwen3-tts-frontend/src/components/tts/CustomVoiceForm.tsx b/qwen3-tts-frontend/src/components/tts/CustomVoiceForm.tsx index 1457292..1879856 100644 --- a/qwen3-tts-frontend/src/components/tts/CustomVoiceForm.tsx +++ b/qwen3-tts-frontend/src/components/tts/CustomVoiceForm.tsx @@ -6,7 +6,7 @@ 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 { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from '@/components/ui/dialog' +import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from '@/components/ui/dialog' import { Label } from '@/components/ui/label' import { Globe2, User, Type, Sparkles, Play, Settings } from 'lucide-react' import { toast } from 'sonner' @@ -228,6 +228,7 @@ const CustomVoiceForm = forwardRef((_props, ref) => { 高级参数设置 + 调整生成参数以控制音频质量和生成长度
diff --git a/qwen3-tts-frontend/src/components/tts/VoiceCloneForm.tsx b/qwen3-tts-frontend/src/components/tts/VoiceCloneForm.tsx index ff35b72..e0f421c 100644 --- a/qwen3-tts-frontend/src/components/tts/VoiceCloneForm.tsx +++ b/qwen3-tts-frontend/src/components/tts/VoiceCloneForm.tsx @@ -6,7 +6,7 @@ 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 { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from '@/components/ui/dialog' +import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from '@/components/ui/dialog' import { Checkbox } from '@/components/ui/checkbox' import { Label } from '@/components/ui/label' import { Settings, Globe2, Type, Play, FileText, Mic, ArrowRight, ArrowLeft } from 'lucide-react' @@ -329,6 +329,7 @@ function VoiceCloneForm() { 高级参数设置 + 调整生成参数以控制音频质量和生成长度
diff --git a/qwen3-tts-frontend/src/components/tts/VoiceDesignForm.tsx b/qwen3-tts-frontend/src/components/tts/VoiceDesignForm.tsx index 6e0aa9f..d9f6a9b 100644 --- a/qwen3-tts-frontend/src/components/tts/VoiceDesignForm.tsx +++ b/qwen3-tts-frontend/src/components/tts/VoiceDesignForm.tsx @@ -6,7 +6,7 @@ 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 { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from '@/components/ui/dialog' +import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from '@/components/ui/dialog' import { Label } from '@/components/ui/label' import { Settings, Globe2, Type, Play, Palette } from 'lucide-react' import { toast } from 'sonner' @@ -197,6 +197,7 @@ const VoiceDesignForm = forwardRef((_props, ref) => { 高级参数设置 + 调整生成参数以控制音频质量和生成长度
diff --git a/qwen3-tts-frontend/src/components/users/ChangePasswordDialog.tsx b/qwen3-tts-frontend/src/components/users/ChangePasswordDialog.tsx index fd034dc..33cf9a7 100644 --- a/qwen3-tts-frontend/src/components/users/ChangePasswordDialog.tsx +++ b/qwen3-tts-frontend/src/components/users/ChangePasswordDialog.tsx @@ -73,7 +73,7 @@ export function ChangePasswordDialog({ return ( - + 修改密码 @@ -140,16 +140,17 @@ export function ChangePasswordDialog({ )} /> - + - diff --git a/qwen3-tts-frontend/src/components/users/DeleteUserDialog.tsx b/qwen3-tts-frontend/src/components/users/DeleteUserDialog.tsx index cb33a38..367eb9a 100644 --- a/qwen3-tts-frontend/src/components/users/DeleteUserDialog.tsx +++ b/qwen3-tts-frontend/src/components/users/DeleteUserDialog.tsx @@ -27,7 +27,7 @@ export function DeleteUserDialog({ }: DeleteUserDialogProps) { return ( - + 确认删除用户 @@ -36,9 +36,9 @@ export function DeleteUserDialog({ 此操作不可撤销,该用户的所有数据将被永久删除。 - - 取消 - + + 取消 + {isLoading ? '删除中...' : '确认删除'} diff --git a/qwen3-tts-frontend/src/components/users/UserDialog.tsx b/qwen3-tts-frontend/src/components/users/UserDialog.tsx index 5e18f40..e296397 100644 --- a/qwen3-tts-frontend/src/components/users/UserDialog.tsx +++ b/qwen3-tts-frontend/src/components/users/UserDialog.tsx @@ -5,6 +5,7 @@ import * as z from 'zod' import { Dialog, DialogContent, + DialogDescription, DialogHeader, DialogTitle, DialogFooter, @@ -87,9 +88,12 @@ export function UserDialog({ return ( - + {isEditing ? '编辑用户' : '创建用户'} + + {isEditing ? '修改用户信息和权限设置' : '创建新用户并配置基本信息'} +
@@ -174,16 +178,17 @@ export function UserDialog({ )} /> - + - diff --git a/qwen3-tts-frontend/src/components/users/UserTable.tsx b/qwen3-tts-frontend/src/components/users/UserTable.tsx index b373888..52120d2 100644 --- a/qwen3-tts-frontend/src/components/users/UserTable.tsx +++ b/qwen3-tts-frontend/src/components/users/UserTable.tsx @@ -28,60 +28,115 @@ export function UserTable({ users, isLoading, onEdit, onDelete }: UserTableProps } return ( -
- - - - - - - - - - - - - - {users.map((user) => ( - - - - - - - - - - ))} - -
ID用户名邮箱状态角色创建时间操作
{user.id}{user.username}{user.email} + <> +
+ + + + + + + + + + + + + + {users.map((user) => ( + + + + + + + + + + ))} + +
ID用户名邮箱状态角色创建时间操作
{user.id}{user.username}{user.email} + + {user.is_active ? '活跃' : '停用'} + + + + {user.is_superuser ? '超级管理员' : '普通用户'} + + + {new Date(user.created_at).toLocaleString('zh-CN')} + +
+ + +
+
+
+ +
+ {users.map((user) => ( +
+
+
{user.username}
+
+ + +
+
+ +
+
+ ID: + {user.id} +
+
+ 邮箱: + {user.email} +
+
+ 状态: {user.is_active ? '活跃' : '停用'} -
+ +
+ 角色: {user.is_superuser ? '超级管理员' : '普通用户'} -
- {new Date(user.created_at).toLocaleString('zh-CN')} - -
- - -
-
-
+
+
+ 创建时间: + {new Date(user.created_at).toLocaleString('zh-CN')} +
+
+
+ ))} +
+ ) } diff --git a/qwen3-tts-frontend/src/pages/UserManagement.tsx b/qwen3-tts-frontend/src/pages/UserManagement.tsx index e6e790b..91580a9 100644 --- a/qwen3-tts-frontend/src/pages/UserManagement.tsx +++ b/qwen3-tts-frontend/src/pages/UserManagement.tsx @@ -93,11 +93,11 @@ export default function UserManagement() { return (
-
+
- + 用户管理 -