diff --git a/app/src/main/ipc-handlers.js b/app/src/main/ipc-handlers.js index 8a06c3b..2390727 100644 --- a/app/src/main/ipc-handlers.js +++ b/app/src/main/ipc-handlers.js @@ -77,6 +77,17 @@ export function registerIpcHandlers() { return mqttManager.importServers(serverList); }); + // ==================== 快速发送 ==================== + + ipcMain.handle('mqtt:get-quick-send-list', () => { + return mqttManager.getQuickSendList(); + }); + + ipcMain.handle('mqtt:save-quick-send-list', (_, list) => { + mqttManager.saveQuickSendList(list); + return true; + }); + // ==================== 连接管理 ==================== ipcMain.handle('mqtt:connect', (_, id) => { diff --git a/app/src/main/mqtt-manager.js b/app/src/main/mqtt-manager.js index 3709ec0..5ce2814 100644 --- a/app/src/main/mqtt-manager.js +++ b/app/src/main/mqtt-manager.js @@ -35,6 +35,7 @@ class MqttManager { this.listeners = new Set(); // IPC callback functions this.msgIdCounter = 0; // 用于生成唯一消息 id this.dataPath = join(app.getPath('userData'), 'frost-mqtt-data.json'); + this.quickSendList = []; this.loadData(); } @@ -101,6 +102,12 @@ class MqttManager { }); } + if (Array.isArray(data.quickSendList)) { + this.quickSendList = data.quickSendList.filter((item) => { + return item && typeof item.id === 'string' && typeof item.topic === 'string'; + }); + } + } else { this.initDefaultServers(); } @@ -124,6 +131,7 @@ class MqttManager { })), messages: Object.fromEntries(this.messages), publishHistory: Object.fromEntries(this.publishHistory), + quickSendList: this.quickSendList, }; writeFileSync(this.dataPath, JSON.stringify(data, null, 2), 'utf-8'); @@ -409,6 +417,30 @@ class MqttManager { return this.getServers(); } + // ==================== 快速发送 ==================== + + /** + * 获取快速发送列表 + * @returns {QuickSendItem[]} 快速发送项数组 + */ + getQuickSendList() { + return this.quickSendList; + } + + /** + * 保存快速发送列表 + * @param {QuickSendItem[]} list - 快速发送项数组 + */ + saveQuickSendList(list) { + if (!Array.isArray(list)) { + return; + } + this.quickSendList = list.filter((item) => { + return item && typeof item.id === 'string' && typeof item.topic === 'string'; + }); + this.saveData(); + } + // ==================== 连接管理 ==================== /** diff --git a/app/src/preload/index.js b/app/src/preload/index.js index 74bc7ac..713c12e 100644 --- a/app/src/preload/index.js +++ b/app/src/preload/index.js @@ -15,6 +15,10 @@ const api = { exportServers: () => ipcRenderer.invoke('mqtt:export-servers'), importServers: (serverList) => ipcRenderer.invoke('mqtt:import-servers', serverList), + // 快速发送 + getQuickSendList: () => ipcRenderer.invoke('mqtt:get-quick-send-list'), + saveQuickSendList: (list) => ipcRenderer.invoke('mqtt:save-quick-send-list', list), + // 连接管理 connect: (id) => ipcRenderer.invoke('mqtt:connect', id), disconnect: (id) => ipcRenderer.invoke('mqtt:disconnect', id), diff --git a/app/src/renderer/src/views/QuickSend.vue b/app/src/renderer/src/views/QuickSend.vue index 2b80bef..df9c0b6 100644 --- a/app/src/renderer/src/views/QuickSend.vue +++ b/app/src/renderer/src/views/QuickSend.vue @@ -8,8 +8,8 @@ const store = useMqttStore(); const msg = useMessage(); const dialog = useDialog(); -// localStorage 持久化 key -const storageKey = 'mqtt-client.quick-send-list'; +// 旧版 localStorage key,用于数据迁移 +const oldStorageKey = 'mqtt-client.quick-send-list'; /** * @typedef {Object} QuickSendItem @@ -24,6 +24,9 @@ const storageKey = 'mqtt-client.quick-send-list'; /** @type {import('vue').Ref} */ const quickList = ref([]); +// 列表是否已从本地文件加载完成 +const quickListLoaded = ref(false); + // 表单弹窗显隐 const showModal = ref(false); const isEdit = ref(false); @@ -35,26 +38,33 @@ const formPayload = ref(''); const formQos = ref(1); const formRetain = ref(false); -// 从 localStorage 恢复列表 -try { - - let saved = JSON.parse(localStorage.getItem(storageKey) || '[]'); - - if (Array.isArray(saved)) { - quickList.value = saved.filter((item) => { - return item && typeof item.id === 'string' && typeof item.topic === 'string'; - }); +// 从旧版 localStorage 迁移数据 +function migrateFromLocalStorage() { + try { + let saved = JSON.parse(localStorage.getItem(oldStorageKey) || '[]'); + if (Array.isArray(saved) && saved.length > 0) { + quickList.value = saved.filter((item) => { + return item && typeof item.id === 'string' && typeof item.topic === 'string'; + }); + window.api.saveQuickSendList(JSON.parse(JSON.stringify(quickList.value))); + } + } catch { + // 忽略旧数据解析错误 + } finally { + localStorage.removeItem(oldStorageKey); } - -} catch { - localStorage.removeItem(storageKey); } -// 列表变化时持久化 +// 列表变化时持久化到本地文件 watch( quickList, () => { - localStorage.setItem(storageKey, JSON.stringify(quickList.value)); + if (!quickListLoaded.value) { + return; + } + window.api.saveQuickSendList(JSON.parse(JSON.stringify(quickList.value))).catch((e) => { + console.error('保存快速发送列表失败:', e); + }); }, { deep: true } ); @@ -461,7 +471,23 @@ function updateColumnCount(width) { } } -onMounted(() => { +onMounted(async () => { + try { + let list = await window.api.getQuickSendList(); + if (Array.isArray(list)) { + quickList.value = list.filter((item) => { + return item && typeof item.id === 'string' && typeof item.topic === 'string'; + }); + } + if (quickList.value.length === 0) { + migrateFromLocalStorage(); + } + } catch (e) { + console.error('加载快速发送列表失败:', e); + } finally { + quickListLoaded.value = true; + } + resizeObserver = new ResizeObserver((entries) => { for (let entry of entries) { updateColumnCount(entry.contentRect.width);