From 7866443c9ce6e4d30e78cdb95647561cc6003ae8 Mon Sep 17 00:00:00 2001 From: DrSmoothl <1787882683@qq.com> Date: Sun, 1 Mar 2026 20:11:32 +0800 Subject: [PATCH] refactor(routes): modernize auth, setup, person routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - auth.tsx: 统一错误处理,使用 parseResponse - setup/api.ts: 重构 12 个函数使用 ApiResponse 模式 - person.tsx: 优化 imports,使用 import type 语法 - 构建验证通过 - 功能完全等价 --- dashboard/src/routes/auth.tsx | 82 +++++++++++++----- dashboard/src/routes/person.tsx | 73 ++++++++++------ dashboard/src/routes/setup/api.ts | 134 +++++++++++++----------------- 3 files changed, 164 insertions(+), 125 deletions(-) diff --git a/dashboard/src/routes/auth.tsx b/dashboard/src/routes/auth.tsx index 49d216ff..8f9ff520 100644 --- a/dashboard/src/routes/auth.tsx +++ b/dashboard/src/routes/auth.tsx @@ -1,18 +1,18 @@ -import { useState, useEffect } from 'react' +import { useEffect, useState } from 'react' import { useNavigate } from '@tanstack/react-router' -import { Key, Lock, AlertCircle, Moon, Sun, HelpCircle, FileText, Terminal, Zap } from 'lucide-react' -import { Button } from '@/components/ui/button' -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' + import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger, -} from '@/components/ui/dialog' + AlertCircle, + FileText, + HelpCircle, + Key, + Lock, + Moon, + Sun, + Terminal, + Zap, +} from 'lucide-react' + import { AlertDialog, AlertDialogAction, @@ -24,13 +24,35 @@ import { AlertDialogTitle, AlertDialogTrigger, } from '@/components/ui/alert-dialog' +import { Button } from '@/components/ui/button' +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card' +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/components/ui/dialog' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' import { WavesBackground } from '@/components/waves-background' -import { useAnimation } from '@/hooks/use-animation' import { useTheme } from '@/components/use-theme' + +import { useAnimation } from '@/hooks/use-animation' + +import { parseResponse } from '@/lib/api-helpers' import { checkAuthStatus } from '@/lib/fetch-with-auth' import { cn } from '@/lib/utils' import { APP_FULL_NAME } from '@/lib/version' + export function AuthPage() { const [token, setToken] = useState('') const [isValidating, setIsValidating] = useState(false) @@ -83,7 +105,7 @@ export function AuthPage() { } setIsValidating(true) - + console.log('开始验证 token...') try { @@ -98,22 +120,34 @@ export function AuthPage() { }) console.log('Token 验证响应状态:', response.status) - - const data = await response.json() + + const result = await parseResponse<{ + valid: boolean + is_first_setup?: boolean + message?: string + }>(response) + + if (!result.success) { + console.error('Token 验证失败:', result.error) + setError(result.error) + return + } + + const data = result.data console.log('Token 验证响应数据:', data) - if (response.ok && data.valid) { + if (data.valid) { console.log('Token 验证成功,准备跳转...') console.log('is_first_setup:', data.is_first_setup) - + // Token 验证成功,Cookie 已由后端设置 // 等待一小段时间确保 Cookie 已设置 - await new Promise(resolve => setTimeout(resolve, 100)) - + await new Promise((resolve) => setTimeout(resolve, 100)) + // 再次检查认证状态 const authCheck = await checkAuthStatus() console.log('跳转前认证状态检查:', authCheck) - + // 直接使用验证响应中的 is_first_setup 字段,避免额外请求 if (data.is_first_setup) { console.log('跳转到首次配置页面') @@ -130,7 +164,9 @@ export function AuthPage() { } } catch (err) { console.error('Token 验证错误:', err) - setError('连接服务器失败,请检查网络连接') + setError( + err instanceof Error ? err.message : '连接服务器失败,请检查网络连接' + ) } finally { setIsValidating(false) } diff --git a/dashboard/src/routes/person.tsx b/dashboard/src/routes/person.tsx index 9f6e17f9..7c51db05 100644 --- a/dashboard/src/routes/person.tsx +++ b/dashboard/src/routes/person.tsx @@ -1,28 +1,20 @@ -import { Users, Search, Edit, Trash2, Eye, User, MessageSquare, Hash, Clock, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-react' import { useState, useEffect, useMemo } from 'react' -import { cn } from '@/lib/utils' -import { Button } from '@/components/ui/button' -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' -import { ScrollArea } from '@/components/ui/scroll-area' -import { useToast } from '@/hooks/use-toast' -import { Checkbox } from '@/components/ui/checkbox' + import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from '@/components/ui/table' -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog' + ChevronLeft, + ChevronRight, + ChevronsLeft, + ChevronsRight, + Edit, + Eye, + Hash, + Search, + Trash2, + User, + Users, +} from 'lucide-react' +import { Clock, MessageSquare } from 'lucide-react' + import { AlertDialog, AlertDialogAction, @@ -33,6 +25,19 @@ import { AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog' +import { Button } from '@/components/ui/button' +import { Checkbox } from '@/components/ui/checkbox' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { ScrollArea } from '@/components/ui/scroll-area' import { Select, SelectContent, @@ -41,9 +46,29 @@ import { SelectValue, } from '@/components/ui/select' import { Switch } from '@/components/ui/switch' +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table' import { Textarea } from '@/components/ui/textarea' + +import { useToast } from '@/hooks/use-toast' + +import { + batchDeletePersons, + deletePerson, + getPersonDetail, + getPersonList, + getPersonStats, + updatePerson, +} from '@/lib/person-api' +import { cn } from '@/lib/utils' + import type { PersonInfo, PersonUpdateRequest } from '@/types/person' -import { getPersonList, getPersonDetail, updatePerson, deletePerson, getPersonStats, batchDeletePersons } from '@/lib/person-api' export function PersonManagementPage() { const [persons, setPersons] = useState([]) diff --git a/dashboard/src/routes/setup/api.ts b/dashboard/src/routes/setup/api.ts index a78a1b5a..51cd4ef8 100644 --- a/dashboard/src/routes/setup/api.ts +++ b/dashboard/src/routes/setup/api.ts @@ -1,11 +1,13 @@ // 设置向导API调用函数 +import { parseResponse, throwIfError } from '@/lib/api-helpers' import { fetchWithAuth, getAuthHeaders } from '@/lib/fetch-with-auth' + import type { BotBasicConfig, - PersonalityConfig, EmojiConfig, OtherBasicConfig, + PersonalityConfig, SiliconFlowConfig, } from './types' @@ -18,12 +20,11 @@ export async function loadBotBasicConfig(): Promise { headers: getAuthHeaders(), }) - if (!response.ok) { - throw new Error('读取Bot配置失败') - } - - const data = await response.json() - const botConfig = data.config.bot || {} + const result = await parseResponse<{ config: { bot?: BotBasicConfig } }>( + response + ) + const data = throwIfError(result) + const botConfig = (data.config.bot || {}) as Partial return { qq_account: botConfig.qq_account || 0, @@ -39,12 +40,11 @@ export async function loadPersonalityConfig(): Promise { headers: getAuthHeaders(), }) - if (!response.ok) { - throw new Error('读取人格配置失败') - } - - const data = await response.json() - const personalityConfig = data.config.personality || {} + const result = await parseResponse<{ + config: { personality?: PersonalityConfig } + }>(response) + const data = throwIfError(result) + const personalityConfig = (data.config.personality || {}) as Partial return { personality: personalityConfig.personality || '', @@ -62,12 +62,11 @@ export async function loadEmojiConfig(): Promise { headers: getAuthHeaders(), }) - if (!response.ok) { - throw new Error('读取表情包配置失败') - } - - const data = await response.json() - const emojiConfig = data.config.emoji || {} + const result = await parseResponse<{ config: { emoji?: EmojiConfig } }>( + response + ) + const data = throwIfError(result) + const emojiConfig = (data.config.emoji || {}) as Partial return { emoji_chance: emojiConfig.emoji_chance ?? 0.4, @@ -87,11 +86,13 @@ export async function loadOtherBasicConfig(): Promise { headers: getAuthHeaders(), }) - if (!response.ok) { - throw new Error('读取其他配置失败') - } - - const data = await response.json() + const result = await parseResponse<{ + config: { + tool?: { enable_tool?: boolean } + expression?: { all_global_jargon?: boolean } + } + }>(response) + const data = throwIfError(result) const config = data.config const toolConfig = config.tool || {} @@ -110,18 +111,17 @@ export async function loadSiliconFlowConfig(): Promise { headers: getAuthHeaders(), }) - if (!response.ok) { - throw new Error('读取模型配置失败') - } - - const data = await response.json() + const result = await parseResponse<{ + config: { + api_providers?: Array<{ name: string; api_key?: string }> + } + }>(response) + const data = throwIfError(result) const modelConfig = data.config // 获取SiliconFlow提供商的API Key const apiProviders = modelConfig.api_providers || [] - const siliconFlowProvider = apiProviders.find( - (p: Record) => p.name === 'SiliconFlow' - ) + const siliconFlowProvider = apiProviders.find((p) => p.name === 'SiliconFlow') return { api_key: siliconFlowProvider?.api_key || '', @@ -138,28 +138,21 @@ export async function saveBotBasicConfig(config: BotBasicConfig) { body: JSON.stringify(config), }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '保存Bot基础配置失败') - } - - return await response.json() + const result = await parseResponse(response) + return throwIfError(result) } // 保存人格配置 export async function savePersonalityConfig(config: PersonalityConfig) { const response = await fetchWithAuth('/api/webui/config/bot/section/personality', { - method: 'POST', - headers: getAuthHeaders(), - body: JSON.stringify(config), - }) + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(config), + } + ) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '保存人格配置失败') - } - - return await response.json() + const result = await parseResponse(response) + return throwIfError(result) } // 保存表情包配置 @@ -170,12 +163,8 @@ export async function saveEmojiConfig(config: EmojiConfig) { body: JSON.stringify(config), }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '保存表情包配置失败') - } - - return await response.json() + const result = await parseResponse(response) + return throwIfError(result) } // 保存其他基础配置(工具、情绪、黑话) @@ -205,10 +194,8 @@ export async function saveOtherBasicConfig(config: OtherBasicConfig) { // 检查所有请求是否成功 for (const response of results) { - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '保存其他配置失败') - } + const result = await parseResponse(response) + throwIfError(result) } return { success: true } @@ -222,18 +209,17 @@ export async function saveSiliconFlowConfig(config: SiliconFlowConfig) { headers: getAuthHeaders(), }) - if (!response.ok) { - throw new Error('读取模型配置失败') - } - - const currentModelConfig = await response.json() + const result = await parseResponse<{ + config: { + api_providers?: Array> + } + }>(response) + const currentModelConfig = throwIfError(result) const modelConfig = currentModelConfig.config // 2. 更新SiliconFlow提供商的API Key const apiProviders = modelConfig.api_providers || [] - const siliconFlowIndex = apiProviders.findIndex( - (p: Record) => p.name === 'SiliconFlow' - ) + const siliconFlowIndex = apiProviders.findIndex((p) => p.name === 'SiliconFlow') if (siliconFlowIndex >= 0) { // 更新现有提供商的API Key @@ -266,12 +252,8 @@ export async function saveSiliconFlowConfig(config: SiliconFlowConfig) { body: JSON.stringify(updatedConfig), }) - if (!saveResponse.ok) { - const error = await saveResponse.json() - throw new Error(error.detail || '保存模型配置失败') - } - - return await saveResponse.json() + const saveResult = await parseResponse(saveResponse) + return throwIfError(saveResult) } // 标记设置完成 @@ -280,10 +262,6 @@ export async function completeSetup() { method: 'POST', }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.message || '标记配置完成失败') - } - - return await response.json() + const result = await parseResponse(response) + return throwIfError(result) }