Files
WeChatDataAnalysis/frontend/stores/chatAccounts.js
T
Alfred Tang a79ff81be0 fix: resolve chat messages not loading due to Nuxt auto-import bug and WCDB timeout
- Move frontend/utils/ to frontend/lib/ to avoid Nuxt unimport scanner
  incorrectly extracting function parameter names (value, fallback) as
  module-level exports, which injected phantom imports that broke all
  client-side JavaScript execution
- Update all import paths across 13 files from ~/utils/ to ~/lib/
- Add timeout (5s) and negative cache (60s TTL) to WCDB realtime
  ensure_connected() to prevent open_account() from hanging indefinitely
  when the WeChat database is locked
- Reorder selectContact() to fire loadMessages() before navigateTo() so
  the message fetch starts before route navigation triggers Suspense
- Add watch: false to SSR useAsyncData calls to prevent unnecessary
  re-fetching on client-side route changes
2026-03-14 17:17:10 +08:00

112 lines
2.9 KiB
JavaScript

import { defineStore } from 'pinia'
const SELECTED_ACCOUNT_KEY = 'ui.selected_account'
export const useChatAccountsStore = defineStore('chatAccounts', () => {
const accounts = ref([])
const selectedAccount = ref(null)
const loading = ref(false)
const error = ref('')
const loaded = ref(false)
// Capture apiBase during synchronous store setup when Nuxt context is available.
// useApiBase() calls useRuntimeConfig() which requires the Nuxt app context;
// that context can be lost inside deferred async functions (e.g. onMounted callbacks).
const _apiBase = useApiBase()
let loadPromise = null
const readSelectedAccount = () => {
if (!process.client) return null
try {
const raw = localStorage.getItem(SELECTED_ACCOUNT_KEY)
const v = String(raw || '').trim()
return v || null
} catch {
return null
}
}
const writeSelectedAccount = (value) => {
if (!process.client) return
try {
const v = String(value || '').trim()
if (!v) {
localStorage.removeItem(SELECTED_ACCOUNT_KEY)
return
}
localStorage.setItem(SELECTED_ACCOUNT_KEY, v)
} catch {}
}
const setSelectedAccount = (next) => {
selectedAccount.value = next ? String(next) : null
writeSelectedAccount(selectedAccount.value)
}
if (process.client) {
watch(selectedAccount, (next) => {
writeSelectedAccount(next)
})
}
const ensureLoaded = async ({ force = false } = {}) => {
if (!process.client) return
if (loaded.value && !force) return
if (loadPromise && !force) {
await loadPromise
return
}
loadPromise = (async () => {
loading.value = true
error.value = ''
if (!selectedAccount.value) {
const cached = readSelectedAccount()
if (cached) selectedAccount.value = cached
}
try {
const resp = await $fetch('/chat/accounts', { baseURL: _apiBase })
const nextAccounts = Array.isArray(resp?.accounts) ? resp.accounts : []
accounts.value = nextAccounts
const preferred = String(selectedAccount.value || '').trim()
const defaultAccount = String(resp?.default_account || '').trim()
const fallback = defaultAccount || nextAccounts[0] || ''
const nextSelected = preferred && nextAccounts.includes(preferred) ? preferred : (fallback || null)
selectedAccount.value = nextSelected
writeSelectedAccount(nextSelected)
loaded.value = true
} catch (e) {
accounts.value = []
selectedAccount.value = null
writeSelectedAccount(null)
loaded.value = true
error.value = e?.message || '加载账号失败'
} finally {
loading.value = false
}
})()
try {
await loadPromise
} finally {
loadPromise = null
}
}
return {
accounts,
selectedAccount,
loading,
error,
loaded,
ensureLoaded,
setSelectedAccount,
}
})