/* vps-manager 前端应用入口(Vue 3 组件化 + Hash 路由) */ /* ================= 导航与 Hash 路由 ================= */ const NAVS = [ { key: 'dashboard', label: '总览', icon: '📊' }, { key: 'assets', label: '资产', icon: '📦' }, { key: 'monitor', label: '监控中心', icon: '⏳' }, { key: 'providers', label: '平台', icon: '🏢' }, { key: 'settings', label: '设置', icon: '⚙️' }, ]; const VIEW_MAP = { dashboard: 'dashboard-view', assets: 'assets-view', monitor: 'monitor-view', providers: 'providers-view', settings: 'settings-view', // 服务器监控为隐藏路由(不进导航,从资产页 VPS「监控」进入) servers: 'servers-view', }; const VALID_VIEWS = new Set(Object.keys(VIEW_MAP)); function _viewFromHash() { const h = (window.location.hash || '').replace(/^#\/?/, '').split('?')[0]; return VALID_VIEWS.has(h) ? h : 'dashboard'; } function _applyView(key) { store.view = key; if (key !== 'servers') store.serverMetrics = {}; } function navigate(key) { if (!VALID_VIEWS.has(key)) key = 'dashboard'; if (window.location.hash !== '#' + key) { window.location.hash = '#' + key; } else { _applyView(key); } } function initRouter() { _applyView(_viewFromHash()); window.addEventListener('hashchange', () => { _applyView(_viewFromHash()); }); } /* ================= 根组件 ================= */ const AppRoot = { template: `

{{ currentNav.label }}

⚠️ {{ store.error }}
`, setup() { const appName = Api.CFG.appName; const appVersion = Api.CFG.version || 'dev'; const appCommit = Api.CFG.commit || 'unknown'; const navs = NAVS; const currentNav = Vue.computed(() => navs.find(n => n.key === store.view) || navs[0]); const viewComponent = Vue.computed(() => VIEW_MAP[store.view] || 'dashboard-view'); function go(key) { navigate(key); } function quickAdd() { if (store.view === 'providers') return openProviderCreate(); // 资产页:按当前 TAB 预设类型;监控中心/总览/设置:默认 VPS let preset = 'vps'; if (store.view === 'assets') { const t = store.assetTab; if (t === 'ai_agent') return openAICreate(''); if (t === 'domain' || t === 'cloudflare' || t === 'subscription' || t === 'vps') preset = t === 'subscription' ? 'vps' : t; } openAssetCreate(preset); } function toggleDark() { store.dark = !store.dark; applyDark(); } // 搜索防抖:300ms 内连续输入只触发一次请求 let searchTimer = null; function debouncedReload() { if (searchTimer) clearTimeout(searchTimer); searchTimer = setTimeout(() => { loadAssets(); }, 300); } return { store, appName, appVersion, appCommit, navs, currentNav, viewComponent, go, quickAdd, toggleDark, reload: debouncedReload }; }, }; /* ================= 挂载 ================= */ const app = Vue.createApp(AppRoot); app.component('dashboard-view', DashboardView); app.component('assets-view', AssetsView); app.component('monitor-view', MonitorView); app.component('providers-view', ProvidersView); app.component('servers-view', ServersView); app.component('settings-view', SettingsView); app.component('asset-modal', AssetModal); app.component('provider-modal', ProviderModal); app.component('account-modal', AccountModal); applyDark(); initRouter(); loadAll(); app.mount('#app');