// client/src/main.js — 入口 import { createApp } from 'vue'; import { createPinia } from 'pinia'; import App from './App.vue'; import router from './router'; import { useDebugStore } from './stores/debug'; import { usePwaStore } from './stores/pwa'; import { registerSW } from 'virtual:pwa-register'; import './style.css'; const app = createApp(App); app.use(createPinia()); app.use(router); // PWA Service Worker 注册 if ('serviceWorker' in navigator) { const pwa = usePwaStore(); const updateSW = registerSW({ immediate: true, onNeedRefresh() { console.info('[PWA] 新版本可用'); pwa.triggerNeedRefresh(); }, onOfflineReady() { console.info('[PWA] 离线缓存就绪'); pwa.triggerOfflineReady(); }, onRegisterError(err) { console.warn('[PWA] SW 注册失败', err); }, }); pwa.bindRegisterSw(updateSW); // 暴露到 window 方便调试 / 强制更新 window.__pwaUpdate = () => updateSW(true); } // 全局错误捕获 → 调试面板 app.config.errorHandler = (err, instance, info) => { const debug = useDebugStore(); debug.log({ kind: 'vue', title: `[${info}] ${err?.message || err}`, detail: { message: err?.message, stack: err?.stack, info, component: instance?.$options?.name || instance?.$options?.__name || '', }, }); console.error('[vue error]', err, info); }; window.addEventListener('unhandledrejection', (e) => { const debug = useDebugStore(); debug.log({ kind: 'promise', title: `未捕获的 Promise 异常: ${e.reason?.message || e.reason}`, detail: { message: e.reason?.message || String(e.reason), stack: e.reason?.stack, }, }); console.error('[unhandledrejection]', e.reason); }); window.addEventListener('error', (e) => { const debug = useDebugStore(); if (e.error) { debug.log({ kind: 'runtime', title: `全局错误: ${e.message}`, detail: { message: e.message, filename: e.filename, lineno: e.lineno, colno: e.colno, stack: e.error?.stack, }, }); } }); app.mount('#app');