From 78ace41b0eb97b3c1dfd984a6bf6ecd0702fed25 Mon Sep 17 00:00:00 2001
From: 2977094657 <2977094657@qq.com>
Date: Sun, 18 Jan 2026 14:01:09 +0800
Subject: [PATCH] feat(desktop): desktop settings
---
desktop/src/main.cjs | 27 ++++
desktop/src/preload.cjs | 4 +-
frontend/pages/chat/[[username]].vue | 222 ++++++++++++++++++++++++++-
frontend/pages/index.vue | 27 +++-
4 files changed, 274 insertions(+), 6 deletions(-)
diff --git a/desktop/src/main.cjs b/desktop/src/main.cjs
index 8616cf2..753601e 100644
--- a/desktop/src/main.cjs
+++ b/desktop/src/main.cjs
@@ -382,6 +382,33 @@ function registerWindowIpc() {
const win = getWin(event);
return !!win?.isMaximized();
});
+
+ ipcMain.handle("app:getAutoLaunch", () => {
+ try {
+ const settings = app.getLoginItemSettings();
+ return !!(settings?.openAtLogin || settings?.executableWillLaunchAtLogin);
+ } catch (err) {
+ logMain(`[main] getAutoLaunch failed: ${err?.message || err}`);
+ return false;
+ }
+ });
+
+ ipcMain.handle("app:setAutoLaunch", (_event, enabled) => {
+ const on = !!enabled;
+ try {
+ app.setLoginItemSettings({ openAtLogin: on });
+ } catch (err) {
+ logMain(`[main] setAutoLaunch(${on}) failed: ${err?.message || err}`);
+ return false;
+ }
+
+ try {
+ const settings = app.getLoginItemSettings();
+ return !!(settings?.openAtLogin || settings?.executableWillLaunchAtLogin);
+ } catch {
+ return on;
+ }
+ });
}
async function main() {
diff --git a/desktop/src/preload.cjs b/desktop/src/preload.cjs
index bbb8bca..39681c4 100644
--- a/desktop/src/preload.cjs
+++ b/desktop/src/preload.cjs
@@ -5,5 +5,7 @@ contextBridge.exposeInMainWorld("wechatDesktop", {
toggleMaximize: () => ipcRenderer.invoke("window:toggleMaximize"),
close: () => ipcRenderer.invoke("window:close"),
isMaximized: () => ipcRenderer.invoke("window:isMaximized"),
-});
+ getAutoLaunch: () => ipcRenderer.invoke("app:getAutoLaunch"),
+ setAutoLaunch: (enabled) => ipcRenderer.invoke("app:setAutoLaunch", !!enabled),
+});
diff --git a/frontend/pages/chat/[[username]].vue b/frontend/pages/chat/[[username]].vue
index 5182983..07ada82 100644
--- a/frontend/pages/chat/[[username]].vue
+++ b/frontend/pages/chat/[[username]].vue
@@ -25,6 +25,23 @@
+
+
+
@@ -1543,6 +1560,85 @@
+
+
+
+
+
+
+
+
+
+ {{ desktopAutoLaunchError }}
+
+
+
+
+
启动后自动开启实时获取
+
进入聊天页后自动打开“实时开关”(默认关闭)
+
+
+
+
+
+
+
有数据时默认进入聊天页
+
有已解密账号时,打开应用默认跳转到 /chat(默认关闭)
+
+
+
+
+
+
+
+
+
+
+
@@ -1607,6 +1703,103 @@ const selectedContact = ref(null)
// 隐私模式
const privacyMode = ref(false)
+// 桌面端设置(仅 Electron 环境可见)
+const isDesktopEnv = ref(false)
+const desktopSettingsOpen = ref(false)
+
+const DESKTOP_SETTING_AUTO_REALTIME_KEY = 'desktop.settings.autoRealtime'
+const DESKTOP_SETTING_DEFAULT_TO_CHAT_KEY = 'desktop.settings.defaultToChatWhenData'
+
+const desktopAutoRealtime = ref(false)
+const desktopDefaultToChatWhenData = ref(false)
+
+const desktopAutoLaunch = ref(false)
+const desktopAutoLaunchLoading = ref(false)
+const desktopAutoLaunchError = ref('')
+
+const readLocalBool = (key) => {
+ if (!process.client) return false
+ try {
+ return localStorage.getItem(key) === 'true'
+ } catch {
+ return false
+ }
+}
+
+const writeLocalBool = (key, value) => {
+ if (!process.client) return
+ try {
+ localStorage.setItem(key, value ? 'true' : 'false')
+ } catch {}
+}
+
+// 尽量早读本地设置,避免首次加载联系人时拿不到 autoRealtime 选项
+if (process.client) {
+ desktopAutoRealtime.value = readLocalBool(DESKTOP_SETTING_AUTO_REALTIME_KEY)
+ desktopDefaultToChatWhenData.value = readLocalBool(DESKTOP_SETTING_DEFAULT_TO_CHAT_KEY)
+}
+
+const refreshDesktopAutoLaunch = async () => {
+ if (!process.client || typeof window === 'undefined') return
+ if (!window.wechatDesktop?.getAutoLaunch) return
+ desktopAutoLaunchLoading.value = true
+ desktopAutoLaunchError.value = ''
+ try {
+ desktopAutoLaunch.value = !!(await window.wechatDesktop.getAutoLaunch())
+ } catch (e) {
+ desktopAutoLaunchError.value = e?.message || '读取开机自启动状态失败'
+ } finally {
+ desktopAutoLaunchLoading.value = false
+ }
+}
+
+const setDesktopAutoLaunch = async (enabled) => {
+ if (!process.client || typeof window === 'undefined') return
+ if (!window.wechatDesktop?.setAutoLaunch) return
+ desktopAutoLaunchLoading.value = true
+ desktopAutoLaunchError.value = ''
+ try {
+ desktopAutoLaunch.value = !!(await window.wechatDesktop.setAutoLaunch(!!enabled))
+ } catch (e) {
+ desktopAutoLaunchError.value = e?.message || '设置开机自启动失败'
+ await refreshDesktopAutoLaunch()
+ } finally {
+ desktopAutoLaunchLoading.value = false
+ }
+}
+
+const openDesktopSettings = async () => {
+ desktopSettingsOpen.value = true
+ await refreshDesktopAutoLaunch()
+}
+
+const closeDesktopSettings = () => {
+ desktopSettingsOpen.value = false
+}
+
+const onDesktopAutoLaunchToggle = async (ev) => {
+ const checked = !!ev?.target?.checked
+ await setDesktopAutoLaunch(checked)
+}
+
+const onDesktopAutoRealtimeToggle = async (ev) => {
+ const checked = !!ev?.target?.checked
+ desktopAutoRealtime.value = checked
+ writeLocalBool(DESKTOP_SETTING_AUTO_REALTIME_KEY, checked)
+ if (checked) {
+ // 开启后尝试立即启用实时模式(不可用则静默忽略)
+ try {
+ await tryEnableRealtimeAuto()
+ } catch {}
+ }
+}
+
+const onDesktopDefaultToChatToggle = (ev) => {
+ const checked = !!ev?.target?.checked
+ desktopDefaultToChatWhenData.value = checked
+ writeLocalBool(DESKTOP_SETTING_DEFAULT_TO_CHAT_KEY, checked)
+}
+
// 联系人数据
const contacts = ref([])
@@ -3406,6 +3599,9 @@ const applyRouteSelection = async () => {
// 默认选择第一个联系人
onMounted(() => {
+ if (process.client && typeof window !== 'undefined') {
+ isDesktopEnv.value = !!window.wechatDesktop
+ }
loadContacts()
loadSearchHistory()
})
@@ -3436,6 +3632,8 @@ const loadContacts = async () => {
} finally {
isLoadingContacts.value = false
}
+
+ await tryEnableRealtimeAuto()
}
const loadSessionsForSelectedAccount = async () => {
@@ -4546,15 +4744,18 @@ const startRealtimeStream = () => {
}
}
-const toggleRealtime = async () => {
+const toggleRealtime = async (opts = {}) => {
+ const silent = !!opts?.silent
if (!process.client || typeof window === 'undefined') return
if (!selectedAccount.value) return
if (!realtimeEnabled.value) {
await fetchRealtimeStatus()
if (!realtimeAvailable.value) {
- window.alert(realtimeStatusError.value || '实时模式不可用:缺少密钥或 db_storage 路径。')
- return
+ if (!silent) {
+ window.alert(realtimeStatusError.value || '实时模式不可用:缺少密钥或 db_storage 路径。')
+ }
+ return false
}
realtimeEnabled.value = true
startRealtimeStream()
@@ -4562,7 +4763,7 @@ const toggleRealtime = async () => {
if (selectedContact.value?.username) {
await refreshSelectedMessages()
}
- return
+ return true
}
realtimeEnabled.value = false
@@ -4571,6 +4772,19 @@ const toggleRealtime = async () => {
if (selectedContact.value?.username) {
await refreshSelectedMessages()
}
+ return true
+}
+
+const tryEnableRealtimeAuto = async () => {
+ if (!process.client || typeof window === 'undefined') return
+ if (!isDesktopEnv.value) return
+ if (!desktopAutoRealtime.value) return
+ if (realtimeEnabled.value) return
+ if (!selectedAccount.value) return
+
+ try {
+ await toggleRealtime({ silent: true })
+ } catch {}
}
watch(selectedAccount, async () => {
diff --git a/frontend/pages/index.vue b/frontend/pages/index.vue
index 068dd7f..cf06df5 100644
--- a/frontend/pages/index.vue
+++ b/frontend/pages/index.vue
@@ -55,6 +55,31 @@