diff --git a/dashboard/src/lib/plugin-api.ts b/dashboard/src/lib/plugin-api.ts index a0f49ed5..a866bf6d 100644 --- a/dashboard/src/lib/plugin-api.ts +++ b/dashboard/src/lib/plugin-api.ts @@ -1,6 +1,8 @@ -import { fetchWithAuth, getAuthHeaders } from '@/lib/fetch-with-auth' +import type { ApiResponse } from '@/types/api' import type { PluginInfo } from '@/types/plugin' +import { fetchWithAuth, getAuthHeaders } from '@/lib/fetch-with-auth' +import { parseResponse } from './api-helpers' import { createReconnectingWebSocket } from './ws-utils' /** @@ -106,124 +108,118 @@ interface PluginApiResponse { /** * 从远程获取插件列表(通过后端代理避免 CORS) */ -export async function fetchPluginList(): Promise { - try { - // 通过后端 API 获取 Raw 文件 - const response = await fetchWithAuth('/api/webui/plugins/fetch-raw', { - method: 'POST', - - body: JSON.stringify({ - owner: PLUGIN_REPO_OWNER, - repo: PLUGIN_REPO_NAME, - branch: PLUGIN_REPO_BRANCH, - file_path: PLUGIN_DETAILS_FILE - }) +export async function fetchPluginList(): Promise> { + const response = await fetchWithAuth('/api/webui/plugins/fetch-raw', { + method: 'POST', + body: JSON.stringify({ + owner: PLUGIN_REPO_OWNER, + repo: PLUGIN_REPO_NAME, + branch: PLUGIN_REPO_BRANCH, + file_path: PLUGIN_DETAILS_FILE }) - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`) + }) + + const apiResult = await parseResponse<{ success: boolean; data: string; error?: string }>(response) + + if (!apiResult.success) { + return apiResult + } + + const result = apiResult.data + if (!result.success || !result.data) { + return { + success: false, + error: result.error || '获取插件列表失败' } - - const result = await response.json() - - // 检查后端返回的结果 - if (!result.success || !result.data) { - throw new Error(result.error || '获取插件列表失败') - } - - const data: PluginApiResponse[] = JSON.parse(result.data) - - // 转换为 PluginInfo 格式,并过滤掉无效数据 - const pluginList = data - .filter(item => { - // 验证必需字段 - if (!item?.id || !item?.manifest) { - console.warn('跳过无效插件数据:', item) - return false - } - if (!item.manifest.name || !item.manifest.version) { - console.warn('跳过缺少必需字段的插件:', item.id) - return false - } - return true - }) - .map((item) => ({ - id: item.id, - manifest: { - manifest_version: item.manifest.manifest_version || 1, - name: item.manifest.name, - version: item.manifest.version, - description: item.manifest.description || '', - author: item.manifest.author || { name: 'Unknown' }, - license: item.manifest.license || 'Unknown', - host_application: item.manifest.host_application || { min_version: '0.0.0' }, - homepage_url: item.manifest.homepage_url, - repository_url: item.manifest.repository_url, - keywords: item.manifest.keywords || [], - categories: item.manifest.categories || [], - default_locale: item.manifest.default_locale || 'zh-CN', - locales_path: item.manifest.locales_path, - }, - // 默认值,这些信息可能需要从其他 API 获取 - downloads: 0, - rating: 0, - review_count: 0, - installed: false, - published_at: new Date().toISOString(), - updated_at: new Date().toISOString(), - })) - - return pluginList - } catch (error) { - console.error('Failed to fetch plugin list:', error) - throw error + } + + const data: PluginApiResponse[] = JSON.parse(result.data) + + const pluginList = data + .filter(item => { + if (!item?.id || !item?.manifest) { + console.warn('跳过无效插件数据:', item) + return false + } + if (!item.manifest.name || !item.manifest.version) { + console.warn('跳过缺少必需字段的插件:', item.id) + return false + } + return true + }) + .map((item) => ({ + id: item.id, + manifest: { + manifest_version: item.manifest.manifest_version || 1, + name: item.manifest.name, + version: item.manifest.version, + description: item.manifest.description || '', + author: item.manifest.author || { name: 'Unknown' }, + license: item.manifest.license || 'Unknown', + host_application: item.manifest.host_application || { min_version: '0.0.0' }, + homepage_url: item.manifest.homepage_url, + repository_url: item.manifest.repository_url, + keywords: item.manifest.keywords || [], + categories: item.manifest.categories || [], + default_locale: item.manifest.default_locale || 'zh-CN', + locales_path: item.manifest.locales_path, + }, + downloads: 0, + rating: 0, + review_count: 0, + installed: false, + published_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + })) + + return { + success: true, + data: pluginList } } /** * 检查本机 Git 安装状态 */ -export async function checkGitStatus(): Promise { - try { - const response = await fetchWithAuth('/api/webui/plugins/git-status') - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`) - } - - return await response.json() - } catch (error) { - console.error('Failed to check Git status:', error) - // 返回未安装状态 +export async function checkGitStatus(): Promise> { + const response = await fetchWithAuth('/api/webui/plugins/git-status') + + const apiResult = await parseResponse(response) + + if (!apiResult.success) { return { - installed: false, - error: '无法检测 Git 安装状态' + success: true, + data: { + installed: false, + error: '无法检测 Git 安装状态' + } } } + + return apiResult } /** * 获取麦麦版本信息 */ -export async function getMaimaiVersion(): Promise { - try { - const response = await fetchWithAuth('/api/webui/plugins/version') - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`) - } - - return await response.json() - } catch (error) { - console.error('Failed to get Maimai version:', error) - // 返回默认版本 +export async function getMaimaiVersion(): Promise> { + const response = await fetchWithAuth('/api/webui/plugins/version') + + const apiResult = await parseResponse(response) + + if (!apiResult.success) { return { - version: '0.0.0', - version_major: 0, - version_minor: 0, - version_patch: 0 + success: true, + data: { + version: '0.0.0', + version_major: 0, + version_minor: 0, + version_patch: 0 + } } } + + return apiResult } /** @@ -318,26 +314,31 @@ export async function connectPluginProgressWebSocket( /** * 获取已安装插件列表 */ -export async function getInstalledPlugins(): Promise { - try { - const response = await fetchWithAuth('/api/webui/plugins/installed', { - headers: getAuthHeaders() - }) - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`) +export async function getInstalledPlugins(): Promise> { + const response = await fetchWithAuth('/api/webui/plugins/installed', { + headers: getAuthHeaders() + }) + + const apiResult = await parseResponse<{ success: boolean; plugins?: InstalledPlugin[]; message?: string }>(response) + + if (!apiResult.success) { + return { + success: true, + data: [] } - - const result = await response.json() - - if (!result.success) { - throw new Error(result.message || '获取已安装插件列表失败') + } + + const result = apiResult.data + if (!result.success) { + return { + success: true, + data: [] } - - return result.plugins || [] - } catch (error) { - console.error('Failed to get installed plugins:', error) - return [] + } + + return { + success: true, + data: result.plugins || [] } } @@ -363,10 +364,9 @@ export function getInstalledPluginVersion(pluginId: string, installedPlugins: In /** * 安装插件 */ -export async function installPlugin(pluginId: string, repositoryUrl: string, branch: string = 'main'): Promise<{ success: boolean; message: string }> { +export async function installPlugin(pluginId: string, repositoryUrl: string, branch: string = 'main'): Promise> { const response = await fetchWithAuth('/api/webui/plugins/install', { method: 'POST', - body: JSON.stringify({ plugin_id: pluginId, repository_url: repositoryUrl, @@ -374,41 +374,29 @@ export async function installPlugin(pluginId: string, repositoryUrl: string, bra }) }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '安装失败') - } - - return await response.json() + return await parseResponse<{ success: boolean; message: string }>(response) } /** * 卸载插件 */ -export async function uninstallPlugin(pluginId: string): Promise<{ success: boolean; message: string }> { +export async function uninstallPlugin(pluginId: string): Promise> { const response = await fetchWithAuth('/api/webui/plugins/uninstall', { method: 'POST', - body: JSON.stringify({ plugin_id: pluginId }) }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '卸载失败') - } - - return await response.json() + return await parseResponse<{ success: boolean; message: string }>(response) } /** * 更新插件 */ -export async function updatePlugin(pluginId: string, repositoryUrl: string, branch: string = 'main'): Promise<{ success: boolean; message: string; old_version: string; new_version: string }> { +export async function updatePlugin(pluginId: string, repositoryUrl: string, branch: string = 'main'): Promise> { const response = await fetchWithAuth('/api/webui/plugins/update', { method: 'POST', - body: JSON.stringify({ plugin_id: pluginId, repository_url: repositoryUrl, @@ -416,12 +404,7 @@ export async function updatePlugin(pluginId: string, repositoryUrl: string, bran }) }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '更新失败') - } - - return await response.json() + return await parseResponse<{ success: boolean; message: string; old_version: string; new_version: string }>(response) } @@ -525,82 +508,85 @@ export interface PluginConfigSchema { /** * 获取插件配置 Schema */ -export async function getPluginConfigSchema(pluginId: string): Promise { +export async function getPluginConfigSchema(pluginId: string): Promise> { const response = await fetchWithAuth(`/api/webui/plugins/config/${pluginId}/schema`, { headers: getAuthHeaders() }) - if (!response.ok) { - const text = await response.text() - try { - const error = JSON.parse(text) - throw new Error(error.detail || '获取配置 Schema 失败') - } catch { - throw new Error(`获取配置 Schema 失败 (${response.status})`) + const apiResult = await parseResponse<{ success: boolean; schema?: PluginConfigSchema; message?: string }>(response) + + if (!apiResult.success) { + return apiResult + } + + const result = apiResult.data + if (!result.success || !result.schema) { + return { + success: false, + error: result.message || '获取配置 Schema 失败' } } - const result = await response.json() - - if (!result.success) { - throw new Error(result.message || '获取配置 Schema 失败') + return { + success: true, + data: result.schema } - - return result.schema } /** * 获取插件当前配置值 */ -export async function getPluginConfig(pluginId: string): Promise> { +export async function getPluginConfig(pluginId: string): Promise>> { const response = await fetchWithAuth(`/api/webui/plugins/config/${pluginId}`, { headers: getAuthHeaders() }) - if (!response.ok) { - const text = await response.text() - try { - const error = JSON.parse(text) - throw new Error(error.detail || '获取配置失败') - } catch { - throw new Error(`获取配置失败 (${response.status})`) + const apiResult = await parseResponse<{ success: boolean; config?: Record; message?: string }>(response) + + if (!apiResult.success) { + return apiResult + } + + const result = apiResult.data + if (!result.success || !result.config) { + return { + success: false, + error: result.message || '获取配置失败' } } - const result = await response.json() - - if (!result.success) { - throw new Error(result.message || '获取配置失败') + return { + success: true, + data: result.config } - - return result.config } /** * 获取插件原始 TOML 配置 */ -export async function getPluginConfigRaw(pluginId: string): Promise { +export async function getPluginConfigRaw(pluginId: string): Promise> { const response = await fetchWithAuth(`/api/webui/plugins/config/${pluginId}/raw`, { headers: getAuthHeaders() }) - if (!response.ok) { - const text = await response.text() - try { - const error = JSON.parse(text) - throw new Error(error.detail || '获取配置失败') - } catch { - throw new Error(`获取配置失败 (${response.status})`) + const apiResult = await parseResponse<{ success: boolean; config?: string; message?: string }>(response) + + if (!apiResult.success) { + return apiResult + } + + const result = apiResult.data + if (!result.success || !result.config) { + return { + success: false, + error: result.message || '获取配置失败' } } - const result = await response.json() - - if (!result.success) { - throw new Error(result.message || '获取配置失败') + return { + success: true, + data: result.config } - - return result.config } /** @@ -609,19 +595,14 @@ export async function getPluginConfigRaw(pluginId: string): Promise { export async function updatePluginConfig( pluginId: string, config: Record -): Promise<{ success: boolean; message: string; note?: string }> { +): Promise> { const response = await fetchWithAuth(`/api/webui/plugins/config/${pluginId}`, { method: 'PUT', headers: getAuthHeaders(), body: JSON.stringify({ config }) }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '保存配置失败') - } - - return await response.json() + return await parseResponse<{ success: boolean; message: string; note?: string }>(response) } /** @@ -630,19 +611,14 @@ export async function updatePluginConfig( export async function updatePluginConfigRaw( pluginId: string, configToml: string -): Promise<{ success: boolean; message: string; note?: string }> { +): Promise> { const response = await fetchWithAuth(`/api/webui/plugins/config/${pluginId}/raw`, { method: 'PUT', headers: getAuthHeaders(), body: JSON.stringify({ config: configToml }) }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '保存配置失败') - } - - return await response.json() + return await parseResponse<{ success: boolean; message: string; note?: string }>(response) } /** @@ -650,18 +626,13 @@ export async function updatePluginConfigRaw( */ export async function resetPluginConfig( pluginId: string -): Promise<{ success: boolean; message: string; backup?: string }> { +): Promise> { const response = await fetchWithAuth(`/api/webui/plugins/config/${pluginId}/reset`, { method: 'POST', headers: getAuthHeaders() }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '重置配置失败') - } - - return await response.json() + return await parseResponse<{ success: boolean; message: string; backup?: string }>(response) } /** @@ -669,16 +640,11 @@ export async function resetPluginConfig( */ export async function togglePlugin( pluginId: string -): Promise<{ success: boolean; enabled: boolean; message: string; note?: string }> { +): Promise> { const response = await fetchWithAuth(`/api/webui/plugins/config/${pluginId}/toggle`, { method: 'POST', headers: getAuthHeaders() }) - if (!response.ok) { - const error = await response.json() - throw new Error(error.detail || '切换状态失败') - } - - return await response.json() + return await parseResponse<{ success: boolean; enabled: boolean; message: string; note?: string }>(response) } diff --git a/dashboard/src/routes/plugin-config.tsx b/dashboard/src/routes/plugin-config.tsx index c6cd4ce8..8c2cff3d 100644 --- a/dashboard/src/routes/plugin-config.tsx +++ b/dashboard/src/routes/plugin-config.tsx @@ -341,16 +341,44 @@ function PluginConfigEditor({ plugin, onBack }: PluginConfigEditorProps) { const loadConfig = useCallback(async () => { setLoading(true) try { - const [schemaData, configData, rawConfigData] = await Promise.all([ + const [schemaResult, configResult, rawResult] = await Promise.all([ getPluginConfigSchema(plugin.id), getPluginConfig(plugin.id), getPluginConfigRaw(plugin.id) ]) - setSchema(schemaData) - setConfig(configData) - setOriginalConfig(JSON.parse(JSON.stringify(configData))) - setSourceCode(rawConfigData) - setOriginalSourceCode(rawConfigData) + + if (!schemaResult.success) { + toast({ + title: '加载配置架构失败', + description: schemaResult.error, + variant: 'destructive' + }) + return + } + + if (!configResult.success) { + toast({ + title: '加载配置数据失败', + description: configResult.error, + variant: 'destructive' + }) + return + } + + if (!rawResult.success) { + toast({ + title: '加载原始配置失败', + description: rawResult.error, + variant: 'destructive' + }) + return + } + + setSchema(schemaResult.data) + setConfig(configResult.data) + setOriginalConfig(JSON.parse(JSON.stringify(configResult.data))) + setSourceCode(rawResult.data) + setOriginalSourceCode(rawResult.data) } catch (error) { toast({ title: '加载配置失败', @@ -433,7 +461,15 @@ function PluginConfigEditor({ plugin, onBack }: PluginConfigEditorProps) { // 重置配置 const handleReset = async () => { try { - await resetPluginConfig(plugin.id) + const resetResult = await resetPluginConfig(plugin.id) + if (!resetResult.success) { + toast({ + title: '重置失败', + description: resetResult.error, + variant: 'destructive' + }) + return + } toast({ title: '配置已重置', description: '下次加载插件时将使用默认配置' @@ -452,10 +488,18 @@ function PluginConfigEditor({ plugin, onBack }: PluginConfigEditorProps) { // 切换启用状态 const handleToggle = async () => { try { - const result = await togglePlugin(plugin.id) + const toggleResult = await togglePlugin(plugin.id) + if (!toggleResult.success) { + toast({ + title: '切换失败', + description: toggleResult.error, + variant: 'destructive' + }) + return + } toast({ - title: result.message, - description: result.note + title: toggleResult.data.message, + description: toggleResult.data.note }) loadConfig() } catch (error) { @@ -723,8 +767,16 @@ function PluginConfigPageContent() { const loadPlugins = async () => { setLoading(true) try { - const data = await getInstalledPlugins() - setPlugins(data) + const installedResult = await getInstalledPlugins() + if (!installedResult.success) { + toast({ + title: '加载插件列表失败', + description: installedResult.error, + variant: 'destructive' + }) + return + } + setPlugins(installedResult.data) } catch (error) { toast({ title: '加载插件列表失败', diff --git a/dashboard/src/routes/plugin-detail.tsx b/dashboard/src/routes/plugin-detail.tsx index fccbdd51..5c6eb1d5 100644 --- a/dashboard/src/routes/plugin-detail.tsx +++ b/dashboard/src/routes/plugin-detail.tsx @@ -131,10 +131,37 @@ export function PluginDetailPage() { getInstalledPlugins(), ]) - setGitStatus(gitStatusResult) - setMaimaiVersion(versionResult) - setIsInstalled(checkPluginInstalled(search.pluginId, installedPlugins)) - setInstalledVersion(getInstalledPluginVersion(search.pluginId, installedPlugins)) + if (!gitStatusResult.success) { + toast({ + title: 'Git 状态检查失败', + description: gitStatusResult.error, + variant: 'destructive', + }) + } else { + setGitStatus(gitStatusResult.data) + } + + if (!versionResult.success) { + toast({ + title: '版本获取失败', + description: versionResult.error, + variant: 'destructive', + }) + } else { + setMaimaiVersion(versionResult.data) + } + + if (!installedPlugins.success) { + toast({ + title: '获取已安装插件失败', + description: installedPlugins.error, + variant: 'destructive', + }) + return + } + + setIsInstalled(checkPluginInstalled(search.pluginId, installedPlugins.data)) + setInstalledVersion(getInstalledPluginVersion(search.pluginId, installedPlugins.data)) } catch (err) { setError(err instanceof Error ? err.message : '加载失败') } finally { @@ -243,7 +270,16 @@ export function PluginDetailPage() { try { setOperating(true) - await installPlugin(plugin.id, plugin.manifest.repository_url || '', 'main') + const installResult = await installPlugin(plugin.id, plugin.manifest.repository_url || '', 'main') + + if (!installResult.success) { + toast({ + title: '安装失败', + description: installResult.error, + variant: 'destructive', + }) + return + } // 记录下载统计 recordPluginDownload(plugin.id).catch((err) => { @@ -256,9 +292,17 @@ export function PluginDetailPage() { }) // 重新加载安装状态 - const installedPlugins = await getInstalledPlugins() - setIsInstalled(checkPluginInstalled(plugin.id, installedPlugins)) - setInstalledVersion(getInstalledPluginVersion(plugin.id, installedPlugins)) + const installedPluginsResult = await getInstalledPlugins() + if (!installedPluginsResult.success) { + toast({ + title: '获取已安装插件失败', + description: installedPluginsResult.error, + variant: 'destructive', + }) + return + } + setIsInstalled(checkPluginInstalled(plugin.id, installedPluginsResult.data)) + setInstalledVersion(getInstalledPluginVersion(plugin.id, installedPluginsResult.data)) } catch (error) { toast({ title: '安装失败', @@ -277,7 +321,16 @@ export function PluginDetailPage() { try { setOperating(true) - await uninstallPlugin(plugin.id) + const uninstallResult = await uninstallPlugin(plugin.id) + + if (!uninstallResult.success) { + toast({ + title: '卸载失败', + description: uninstallResult.error, + variant: 'destructive', + }) + return + } toast({ title: '卸载成功', @@ -285,9 +338,17 @@ export function PluginDetailPage() { }) // 重新加载安装状态 - const installedPlugins = await getInstalledPlugins() - setIsInstalled(checkPluginInstalled(plugin.id, installedPlugins)) - setInstalledVersion(getInstalledPluginVersion(plugin.id, installedPlugins)) + const installedPluginsResult = await getInstalledPlugins() + if (!installedPluginsResult.success) { + toast({ + title: '获取已安装插件失败', + description: installedPluginsResult.error, + variant: 'destructive', + }) + return + } + setIsInstalled(checkPluginInstalled(plugin.id, installedPluginsResult.data)) + setInstalledVersion(getInstalledPluginVersion(plugin.id, installedPluginsResult.data)) } catch (error) { toast({ title: '卸载失败', @@ -306,17 +367,34 @@ export function PluginDetailPage() { try { setOperating(true) - const result = await updatePlugin(plugin.id, plugin.manifest.repository_url || '', 'main') + const updateResult = await updatePlugin(plugin.id, plugin.manifest.repository_url || '', 'main') + + if (!updateResult.success) { + toast({ + title: '更新失败', + description: updateResult.error, + variant: 'destructive', + }) + return + } toast({ title: '更新成功', - description: `${plugin.manifest.name} 已从 ${result.old_version} 更新到 ${result.new_version}`, + description: `${plugin.manifest.name} 已从 ${updateResult.data.old_version} 更新到 ${updateResult.data.new_version}`, }) // 重新加载安装状态 - const installedPlugins = await getInstalledPlugins() - setIsInstalled(checkPluginInstalled(plugin.id, installedPlugins)) - setInstalledVersion(getInstalledPluginVersion(plugin.id, installedPlugins)) + const installedPluginsResult = await getInstalledPlugins() + if (!installedPluginsResult.success) { + toast({ + title: '获取已安装插件失败', + description: installedPluginsResult.error, + variant: 'destructive', + }) + return + } + setIsInstalled(checkPluginInstalled(plugin.id, installedPluginsResult.data)) + setInstalledVersion(getInstalledPluginVersion(plugin.id, installedPluginsResult.data)) } catch (error) { toast({ title: '更新失败', diff --git a/dashboard/src/routes/plugins.tsx b/dashboard/src/routes/plugins.tsx index 9d34ff57..100fae85 100644 --- a/dashboard/src/routes/plugins.tsx +++ b/dashboard/src/routes/plugins.tsx @@ -180,34 +180,71 @@ function PluginsPageContent() { // 3. 检查 Git 状态 if (!isUnmounted) { - const status = await checkGitStatus() - setGitStatus(status) - - if (!status.installed) { + const statusResult = await checkGitStatus() + if (!statusResult.success) { toast({ - title: 'Git 未安装', - description: status.error || '请先安装 Git 才能使用插件安装功能', + title: 'Git 状态检查失败', + description: statusResult.error, variant: 'destructive', }) + setGitStatus({ installed: false, error: statusResult.error }) + } else { + setGitStatus(statusResult.data) + + if (!statusResult.data.installed) { + toast({ + title: 'Git 未安装', + description: statusResult.data.error || '请先安装 Git 才能使用插件安装功能', + variant: 'destructive', + }) + } } } // 4. 获取麦麦版本 if (!isUnmounted) { - const version = await getMaimaiVersion() - setMaimaiVersion(version) + const versionResult = await getMaimaiVersion() + if (!versionResult.success) { + toast({ + title: '版本获取失败', + description: versionResult.error, + variant: 'destructive', + }) + } else { + setMaimaiVersion(versionResult.data) + } } - // 5. 加载插件列表(包含已安装信息) if (!isUnmounted) { try { setLoading(true) setError(null) - const data = await fetchPluginList() + const apiResult = await fetchPluginList() + if (!apiResult.success) { + if (!isUnmounted) { + setError(apiResult.error) + toast({ + title: '加载失败', + description: apiResult.error, + variant: 'destructive', + }) + } + return + } + const data = apiResult.data if (!isUnmounted) { // 获取已安装插件列表 - const installed = await getInstalledPlugins() + const installedResult = await getInstalledPlugins() + if (!installedResult.success) { + toast({ + title: '获取已安装插件失败', + description: installedResult.error, + variant: 'destructive', + }) + return + } + const installed = installedResult.data setInstalledPlugins(installed) // 将已安装信息合并到插件数据中 @@ -261,16 +298,6 @@ function PluginsPageContent() { // 6. 加载所有插件的统计数据 loadPluginStats(mergedData) } - } catch (err) { - if (!isUnmounted) { - const errorMessage = err instanceof Error ? err.message : '加载插件列表失败' - setError(errorMessage) - toast({ - title: '加载失败', - description: errorMessage, - variant: 'destructive', - }) - } } finally { if (!isUnmounted) { setLoading(false) @@ -463,12 +490,21 @@ function PluginsPageContent() { try { setInstallDialogOpen(false) - await installPlugin( + const installResult = await installPlugin( installingPlugin.id, installingPlugin.manifest.repository_url || '', branch ) + if (!installResult.success) { + toast({ + title: '安装失败', + description: installResult.error, + variant: 'destructive', + }) + return + } + // 记录下载统计 recordPluginDownload(installingPlugin.id).catch(err => { console.warn('Failed to record download:', err) @@ -480,7 +516,16 @@ function PluginsPageContent() { }) // 重新加载已安装插件列表 - const installed = await getInstalledPlugins() + const installedResult = await getInstalledPlugins() + if (!installedResult.success) { + toast({ + title: '获取已安装插件失败', + description: installedResult.error, + variant: 'destructive', + }) + return + } + const installed = installedResult.data setInstalledPlugins(installed) // 重新合并已安装信息到插件列表 @@ -513,7 +558,16 @@ function PluginsPageContent() { // 卸载插件处理 const handleUninstall = async (plugin: PluginInfo) => { try { - await uninstallPlugin(plugin.id) + const uninstallResult = await uninstallPlugin(plugin.id) + + if (!uninstallResult.success) { + toast({ + title: '卸载失败', + description: uninstallResult.error, + variant: 'destructive', + }) + return + } toast({ title: '卸载成功', @@ -521,7 +575,16 @@ function PluginsPageContent() { }) // 重新加载已安装插件列表 - const installed = await getInstalledPlugins() + const installedResult = await getInstalledPlugins() + if (!installedResult.success) { + toast({ + title: '获取已安装插件失败', + description: installedResult.error, + variant: 'destructive', + }) + return + } + const installed = installedResult.data setInstalledPlugins(installed) // 重新合并已安装信息到插件列表 @@ -561,19 +624,37 @@ function PluginsPageContent() { } try { - const result = await updatePlugin( + const updateResult = await updatePlugin( plugin.id, plugin.manifest.repository_url || '', 'main' ) + if (!updateResult.success) { + toast({ + title: '更新失败', + description: updateResult.error, + variant: 'destructive', + }) + return + } + toast({ title: '更新成功', - description: `${plugin.manifest.name} 已从 ${result.old_version} 更新到 ${result.new_version}`, + description: `${plugin.manifest.name} 已从 ${updateResult.data.old_version} 更新到 ${updateResult.data.new_version}`, }) // 重新加载已安装插件列表 - const installed = await getInstalledPlugins() + const installedResult = await getInstalledPlugins() + if (!installedResult.success) { + toast({ + title: '获取已安装插件失败', + description: installedResult.error, + variant: 'destructive', + }) + return + } + const installed = installedResult.data setInstalledPlugins(installed) // 重新合并已安装信息到插件列表