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) +})