From 21683cb7908d2e7a391193d3cd3b037fc7cb31ea Mon Sep 17 00:00:00 2001 From: Frost-ZX Date: Sun, 19 Jul 2026 20:00:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E4=BF=A1=E6=81=AF=E5=AF=BC=E5=85=A5=E3=80=81=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/ipc-handlers.js | 8 ++ app/src/main/mqtt-manager.js | 123 +++++++++++++++----- app/src/preload/index.js | 2 + app/src/renderer/src/components/Sidebar.vue | 62 ++++++++++ app/src/renderer/src/stores/mqtt.js | 16 +++ 5 files changed, 182 insertions(+), 29 deletions(-) diff --git a/app/src/main/ipc-handlers.js b/app/src/main/ipc-handlers.js index a738149..f566162 100644 --- a/app/src/main/ipc-handlers.js +++ b/app/src/main/ipc-handlers.js @@ -58,6 +58,14 @@ export function registerIpcHandlers() { return true; }); + ipcMain.handle('mqtt:export-servers', () => { + return mqttManager.exportServers(); + }); + + ipcMain.handle('mqtt:import-servers', (_, serverList) => { + return mqttManager.importServers(serverList); + }); + // ==================== 连接管理 ==================== ipcMain.handle('mqtt:connect', (_, id) => { diff --git a/app/src/main/mqtt-manager.js b/app/src/main/mqtt-manager.js index 7bccea7..cd13303 100644 --- a/app/src/main/mqtt-manager.js +++ b/app/src/main/mqtt-manager.js @@ -164,23 +164,47 @@ class MqttManager { return this.servers.get(id) || null; } + getServerConfigSchema() { + return { + name: (c, e) => c.name ?? e?.name, + host: (c, e) => c.host ?? e?.host, + port: (c, e) => c.port || e?.port || 1883, + protocol: (c, e) => c.protocol || e?.protocol || 'mqtt', + clientId: (c, e) => c.clientId || e?.clientId || 'frost_' + Math.random().toString(36).slice(2, 10), + username: (c, e) => c.username ?? e?.username ?? '', + password: (c, e, opts) => c.password ?? (opts.keepExistingPassword ? e?.password : '') ?? '', + keepAlive: (c, e) => c.keepAlive || e?.keepAlive || 60, + cleanSession: (c) => c.cleanSession !== false, + connectTimeout: (c, e) => c.connectTimeout ?? e?.connectTimeout ?? 10000, + reconnect: (c) => c.reconnect !== false, + reconnectInterval: (c, e) => c.reconnectInterval ?? e?.reconnectInterval ?? 5000, + }; + } + + buildServerFields(config, existing = null, options = {}) { + let schema = this.getServerConfigSchema(); + let fields = {}; + for (let key of Object.keys(schema)) { + fields[key] = schema[key](config, existing, options); + } + return fields; + } + + buildTopic(t) { + return { + id: t.id || 'topic_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6), + topic: t.topic, + qos: t.qos ?? 1, + subscribed: false, + }; + } + addServer(config) { let id = 'srv_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6); let server = { id, - name: config.name, - host: config.host, - port: config.port || 1883, - protocol: config.protocol || 'mqtt', - clientId: config.clientId || 'frost_' + Math.random().toString(36).slice(2, 10), - username: config.username || '', - password: config.password || '', - keepAlive: config.keepAlive || 60, - cleanSession: config.cleanSession !== false, - connectTimeout: config.connectTimeout ?? 10000, - reconnect: config.reconnect !== false, - reconnectInterval: config.reconnectInterval ?? 5000, + ...this.buildServerFields(config), status: 'disconnected', topics: [], }; @@ -202,23 +226,7 @@ class MqttManager { return null; } - Object.assign(server, { - name: config.name, - host: config.host, - port: config.port || 1883, - protocol: config.protocol || 'mqtt', - clientId: config.clientId || server.clientId, - username: config.username || '', - keepAlive: config.keepAlive || 60, - cleanSession: config.cleanSession !== false, - connectTimeout: config.connectTimeout ?? server.connectTimeout ?? 10000, - reconnect: config.reconnect !== false, - reconnectInterval: config.reconnectInterval ?? server.reconnectInterval ?? 5000, - }); - - if (config.password) { - server.password = config.password; - } + Object.assign(server, this.buildServerFields(config, server, { keepExistingPassword: true })); this.saveData(); @@ -235,6 +243,63 @@ class MqttManager { this.saveData(); } + exportServers() { + let schemaKeys = Object.keys(this.getServerConfigSchema()); + return Array.from(this.servers.values()).map((s) => { + let exported = {}; + for (let key of schemaKeys) { + exported[key] = s[key]; + } + exported.topics = (s.topics || []).map((t) => this.buildTopicExport(t)); + return exported; + }); + } + + buildTopicExport(t) { + return { + id: t.id, + topic: t.topic, + qos: t.qos, + }; + } + + importServers(serverList) { + if (!Array.isArray(serverList)) { + throw new Error('导入格式错误:必须是服务器配置数组'); + } + + // 断开所有现有连接 + this.clients.forEach((client, id) => { + this.disconnect(id); + }); + this.clients.clear(); + + this.servers.clear(); + this.messages.clear(); + this.publishHistory.clear(); + + serverList.forEach((config) => { + if (!config.name || !config.host) { + return; + } + + let id = 'srv_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6); + let server = { + id, + ...this.buildServerFields(config), + status: 'disconnected', + topics: (config.topics || []).map((t) => this.buildTopic(t)), + }; + + this.servers.set(id, server); + this.messages.set(id, []); + this.publishHistory.set(id, []); + }); + + this.saveData(); + return this.getServers(); + } + // ==================== 连接管理 ==================== connect(id) { diff --git a/app/src/preload/index.js b/app/src/preload/index.js index fa50a05..a5f4c43 100644 --- a/app/src/preload/index.js +++ b/app/src/preload/index.js @@ -9,6 +9,8 @@ const api = { addServer: (config) => ipcRenderer.invoke('mqtt:add-server', config), updateServer: (id, config) => ipcRenderer.invoke('mqtt:update-server', id, config), deleteServer: (id) => ipcRenderer.invoke('mqtt:delete-server', id), + exportServers: () => ipcRenderer.invoke('mqtt:export-servers'), + importServers: (serverList) => ipcRenderer.invoke('mqtt:import-servers', serverList), // 连接管理 connect: (id) => ipcRenderer.invoke('mqtt:connect', id), diff --git a/app/src/renderer/src/components/Sidebar.vue b/app/src/renderer/src/components/Sidebar.vue index 4bd54cd..9601b99 100644 --- a/app/src/renderer/src/components/Sidebar.vue +++ b/app/src/renderer/src/components/Sidebar.vue @@ -1,4 +1,5 @@