diff --git a/packages/napcat-onebot/network/plugin-manger.ts b/packages/napcat-onebot/network/plugin-manger.ts index 42a889e9..fa5e3350 100644 --- a/packages/napcat-onebot/network/plugin-manger.ts +++ b/packages/napcat-onebot/network/plugin-manger.ts @@ -316,6 +316,11 @@ export class OB11PluginMangerAdapter extends IOB11NetworkAdapter i entry = newEntry; } + if (!entry.enable) { + this.logger.log(`[PluginManager] Skipping loading disabled plugin: ${pluginId}`); + return false; + } + return await this.loadPlugin(entry); } diff --git a/packages/napcat-onebot/network/plugin/loader.ts b/packages/napcat-onebot/network/plugin/loader.ts index 7c4b23c5..85ab8030 100644 --- a/packages/napcat-onebot/network/plugin/loader.ts +++ b/packages/napcat-onebot/network/plugin/loader.ts @@ -123,8 +123,8 @@ export class PluginLoader { const entryFile = this.findEntryFile(pluginDir, packageJson); const entryPath = entryFile ? path.join(pluginDir, entryFile) : undefined; - // 获取启用状态(默认启用) - const enable = statusConfig[pluginId] !== false; + // 获取启用状态(默认禁用,内置插件除外) + const enable = statusConfig[pluginId] ?? (pluginId === 'napcat-plugin-builtin'); // 创建插件条目 const entry: PluginEntry = { @@ -159,7 +159,7 @@ export class PluginLoader { id: dirname, // 使用目录名作为 ID fileId: dirname, pluginPath: path.join(this.pluginPath, dirname), - enable: statusConfig[dirname] !== false, + enable: statusConfig[dirname] ?? (dirname === 'napcat-plugin-builtin'), loaded: false, runtime: { status: 'error', diff --git a/packages/napcat-onebot/network/plugin/manager.ts b/packages/napcat-onebot/network/plugin/manager.ts index 9fd3ddd6..b9b38fce 100644 --- a/packages/napcat-onebot/network/plugin/manager.ts +++ b/packages/napcat-onebot/network/plugin/manager.ts @@ -285,6 +285,11 @@ export class OB11PluginManager extends IOB11NetworkAdapter impleme entry = newEntry; } + if (!entry.enable) { + this.logger.log(`[PluginManager] Skipping loading disabled plugin: ${pluginId}`); + return false; + } + return await this.loadPlugin(entry); } diff --git a/packages/napcat-webui-backend/src/api/UpdateNapCat.ts b/packages/napcat-webui-backend/src/api/UpdateNapCat.ts index 43126080..274d4fc5 100644 --- a/packages/napcat-webui-backend/src/api/UpdateNapCat.ts +++ b/packages/napcat-webui-backend/src/api/UpdateNapCat.ts @@ -340,7 +340,7 @@ export async function applyPendingUpdates (webUiPathWrapper: NapCatPathWrapper, const configPath = path.join(webUiPathWrapper.configPath, 'napcat-update.json'); if (!fs.existsSync(configPath)) { - logger.log('[NapCat Update] No pending updates found'); + //logger.log('[NapCat Update] No pending updates found'); return; } diff --git a/packages/napcat-webui-frontend/src/components/display_card/plugin_store_card.tsx b/packages/napcat-webui-frontend/src/components/display_card/plugin_store_card.tsx index 6aaa6682..0ea60016 100644 --- a/packages/napcat-webui-frontend/src/components/display_card/plugin_store_card.tsx +++ b/packages/napcat-webui-frontend/src/components/display_card/plugin_store_card.tsx @@ -43,7 +43,7 @@ const PluginStoreCard: React.FC = ({ return { text: '更新', icon: , - color: 'success' as const, + color: 'default' as const, }; default: return { diff --git a/packages/napcat-webui-frontend/src/components/system_info.tsx b/packages/napcat-webui-frontend/src/components/system_info.tsx index bfe509fc..ea79b3b6 100644 --- a/packages/napcat-webui-frontend/src/components/system_info.tsx +++ b/packages/napcat-webui-frontend/src/components/system_info.tsx @@ -260,14 +260,14 @@ const NewVersionTip = (props: NewVersionTipProps) => {
- {updateStatus === 'updating' ? : 'New'} + {updateStatus === 'updating' ? : 'New'}
diff --git a/packages/napcat-webui-frontend/src/pages/dashboard/network.tsx b/packages/napcat-webui-frontend/src/pages/dashboard/network.tsx index f6d93253..dc25a78c 100644 --- a/packages/napcat-webui-frontend/src/pages/dashboard/network.tsx +++ b/packages/napcat-webui-frontend/src/pages/dashboard/network.tsx @@ -2,9 +2,10 @@ import { Button } from '@heroui/button'; import { useDisclosure } from '@heroui/modal'; import { Tab, Tabs } from '@heroui/tabs'; import clsx from 'clsx'; -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import toast from 'react-hot-toast'; import { IoMdRefresh } from 'react-icons/io'; +import { FiDownload, FiUpload } from 'react-icons/fi'; import AddButton from '@/components/button/add_button'; import HTTPClientDisplayCard from '@/components/display_card/http_client'; @@ -55,7 +56,9 @@ export default function NetworkPage () { deleteNetworkConfig, enableNetworkConfig, enableDebugNetworkConfig, + updateSingleConfig, } = useConfig(); + const fileInputRef = useRef(null); const [activeField, setActiveField] = useState('httpServers'); const [activeName, setActiveName] = useState(''); @@ -99,6 +102,45 @@ export default function NetworkPage () { onOpen(); }; + // 导出网络配置 + const handleExport = () => { + const blob = new Blob([JSON.stringify(config.network, null, 2)], { type: 'application/json' }); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.download = `network-config-${Date.now()}.json`; + link.click(); + URL.revokeObjectURL(link.href); + toast.success('导出成功'); + }; + + // 导入网络配置 + const handleFileChange = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + e.target.value = ''; + + try { + const data = JSON.parse(await file.text()) as OneBotConfig['network']; + const keys: (keyof OneBotConfig['network'])[] = ['httpServers', 'httpClients', 'httpSseServers', 'websocketServers', 'websocketClients']; + if (keys.some(k => !Array.isArray(data[k]))) throw new Error('配置格式错误'); + + dialog.confirm({ + title: '导入配置', + content: '确定导入?这将覆盖现有网络配置。', + onConfirm: async () => { + try { + await updateSingleConfig('network', data); + toast.success('导入成功'); + } catch (err) { + toast.error(`导入失败: ${(err as Error).message}`); + } + }, + }); + } catch (err) { + toast.error(`解析失败: ${(err as Error).message}`); + } + }; + const onDelete = async ( field: keyof OneBotConfig['network'], name: string @@ -373,6 +415,21 @@ export default function NetworkPage () {
+ + +