From 1cb66a82db84e33fd23383bf570617a826cd710e Mon Sep 17 00:00:00 2001 From: xiaosheng <73678111+xiaoshengbao@users.noreply.github.com> Date: Tue, 15 Sep 2026 18:45:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=BB=98=E8=AE=A4=E5=BC=80=E5=90=AF?= =?UTF-8?q?=E5=B7=B2=E6=9C=89=E8=B4=A6=E5=8F=B7=E8=87=AA=E5=8A=A8=E5=9B=9E?= =?UTF-8?q?=E7=9C=8B=E5=B9=B6=E4=BF=AE=E5=A4=8D=E5=90=AF=E5=8A=A8=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/components/SettingsDialog.vue | 4 +- frontend/pages/index.vue | 10 ++-- frontend/tests/startup-navigation.test.mjs | 59 ++++++++++++++++++++++ 3 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 frontend/tests/startup-navigation.test.mjs diff --git a/frontend/components/SettingsDialog.vue b/frontend/components/SettingsDialog.vue index 47d76e9e..bc2bd467 100644 --- a/frontend/components/SettingsDialog.vue +++ b/frontend/components/SettingsDialog.vue @@ -781,7 +781,7 @@ const desktopVersionText = computed(() => { return v || '—' }) -const desktopDefaultToChatWhenData = ref(false) +const desktopDefaultToChatWhenData = ref(true) const cdnImageEnabled = ref(false) const cdnImageLoading = ref(false) @@ -2196,7 +2196,7 @@ onMounted(async () => { } } - desktopDefaultToChatWhenData.value = readLocalBoolSetting(DESKTOP_SETTING_DEFAULT_TO_CHAT_KEY, false) + desktopDefaultToChatWhenData.value = readLocalBoolSetting(DESKTOP_SETTING_DEFAULT_TO_CHAT_KEY, true) snsUseCache.value = readLocalBoolSetting(SNS_SETTING_USE_CACHE_KEY, true) void loadCdnImageStatus() diff --git a/frontend/pages/index.vue b/frontend/pages/index.vue index bc16ea6a..95963947 100644 --- a/frontend/pages/index.vue +++ b/frontend/pages/index.vue @@ -141,22 +141,26 @@ import { DESKTOP_SETTING_DEFAULT_TO_CHAT_KEY, readLocalBoolSetting } from '~/lib import { isFirstUseAgreementAccepted } from '~/lib/first-use-agreement' const { listChatAccounts } = useApi() +const router = useRouter() const exportDialogOpen = ref(false) onMounted(async () => { if (!process.client || typeof window === 'undefined') return if (!isFirstUseAgreementAccepted()) return - const enabled = readLocalBoolSetting(DESKTOP_SETTING_DEFAULT_TO_CHAT_KEY, false) + const enabled = readLocalBoolSetting(DESKTOP_SETTING_DEFAULT_TO_CHAT_KEY, true) if (!enabled) return try { const resp = await listChatAccounts() const accounts = resp?.accounts || [] if (accounts.length) { - await navigateTo('/chat', { replace: true }) + // 提前获取路由实例,避免等待账号请求后丢失 Nuxt 上下文。 + await router.replace('/chat') } - } catch {} + } catch (error) { + console.warn('启动时自动进入聊天页失败:', error) + } }) const openExportDialog = () => { diff --git a/frontend/tests/startup-navigation.test.mjs b/frontend/tests/startup-navigation.test.mjs new file mode 100644 index 00000000..3f748616 --- /dev/null +++ b/frontend/tests/startup-navigation.test.mjs @@ -0,0 +1,59 @@ +import assert from 'node:assert/strict' +import { readFileSync } from 'node:fs' +import test from 'node:test' +import vm from 'node:vm' +import { parse } from '@vue/compiler-sfc' + +const source = readFileSync(new URL('../pages/index.vue', import.meta.url), 'utf8') +const script = parse(source).descriptor.scriptSetup.content.replace(/^import .*$/gm, '') +const settings = readFileSync(new URL('../lib/desktop-settings.js', import.meta.url), 'utf8') + .replace(/^export /gm, '') + +const runStartup = async ({ stored = null, accounts = ['ready-account'], accepted = true, fails = false } = {}) => { + let mounted + let contextAvailable = true + const paths = [] + const warnings = [] + const router = { replace: async path => paths.push(path) } + const getRouter = () => { + if (!contextAvailable) throw new Error('Nuxt 上下文不可用') + return router + } + vm.runInNewContext(`${settings}\n${script}`, { + process: { client: true }, window: {}, + localStorage: { getItem: () => stored }, + ref: value => ({ value }), + onMounted: callback => { mounted = callback }, + useRouter: getRouter, + navigateTo: path => getRouter().replace(path), + isFirstUseAgreementAccepted: () => accepted, + console: { warn: (...args) => warnings.push(args) }, + useApi: () => ({ listChatAccounts: async () => { + await Promise.resolve() + // 模拟异步请求结束后,组合式函数不再能获取组件上下文。 + contextAvailable = false + if (fails) throw new Error('账号服务暂时不可用') + return { accounts } + } }), + }) + await mounted() + return { paths, warnings } +} + +test('默认开启时,账号请求结束后仍能跳转到回看页', async () => { + const result = await runStartup() + assert.deepEqual(result.paths, ['/chat']) + assert.equal(result.warnings.length, 0) +}) + +test('手动关闭、没有账号或未同意协议时不自动跳转', async () => { + for (const options of [{ stored: 'false' }, { accounts: [] }, { accepted: false }]) { + assert.deepEqual((await runStartup(options)).paths, []) + } +}) + +test('账号请求失败时留在首页并记录原因', async () => { + const result = await runStartup({ fails: true }) + assert.deepEqual(result.paths, []) + assert.equal(result.warnings.length, 1) +})