/* 应用外壳:左侧菜单 + 顶栏 + 内容区,最后加载并挂载 (ref / computed / createApp 等已在 util.js 里解构到全局) */ const App = { template: `
{{ current.title }}
{{ current.sub }}
↻刷新本页
`, setup() { const pages = window.PAGES; // 分组:按注册顺序把页面归到各自的分组里(总览 / 数据管理 / 统计分析) const groups = []; pages.forEach(p => { const name = p.group || '其他'; let g = groups.find(x => x.name === name); if (!g) { g = { name, items: [] }; groups.push(g); } g.items.push(p); }); const fallback = (pages[0] && pages[0].key) || ''; const currentKey = ref(location.hash.replace(/^#\/?/, '') || fallback); // 刷新本页:改 key 让组件重新挂载,页面自己会重新拉数据 const reloadTick = ref(0); const reload = () => { reloadTick.value++; }; const current = computed(() => pages.find(p => p.key === currentKey.value) || pages[0] || { title: '', sub: '', component: null }); const go = (key) => { if (key === currentKey.value) { reload(); return; } location.hash = '#/' + key; }; // 地址栏直接改 hash / 浏览器前进后退也能切页 const onHash = () => { const k = location.hash.replace(/^#\/?/, ''); if (k && k !== currentKey.value) currentKey.value = k; }; onMounted(() => window.addEventListener('hashchange', onHash)); onUnmounted(() => window.removeEventListener('hashchange', onHash)); // 把地址栏补齐,刷新页面能停在当前页 if (!location.hash) location.hash = '#/' + currentKey.value; // 前后端不同源了,/docs 这种站内相对路径会指到前端服务器上,必须用后端地址 const docsUrl = API_BASE + '/docs'; return { groups, currentKey, current, go, reload, reloadTick, icon, docsUrl }; }, }; const app = createApp(App); // 模板里写错组件名之类的错误,直接在界面上弹出来,比只看控制台快 app.config.errorHandler = (err) => { console.error(err); toastErr(err && err.message ? err.message : '页面出错了,请按 F12 看控制台'); }; app.use(ElementPlus, { locale: ElementPlusLocaleZhCn }); app.mount('#app');