/* 资产视图:TAB 容器(全部/VPS/域名/Cloudflare/订阅/AI账号) * 注意:专有视图(DomainsView 等)在后续脚本才定义,必须在 setup 运行时求值, * 不能在组件定义处直接引用(会因加载顺序抛 ReferenceError)。 */ const AssetsView = { template: `
🏢 平台:{{ providerName(store.filterProvider) }}
`, setup() { // tip 为 TAB 悬浮说明:让用户一眼明白每个分类装的是什么 const tabs = [ { key: '', label: '全部', tip: '所有类型的资产' }, { key: 'vps', label: 'VPS', tip: '云服务器(可查看资源监控)' }, { key: 'domain', label: '域名', tip: '域名与解析' }, { key: 'cloudflare', label: 'Cloudflare', tip: 'Cloudflare 账号下的资源' }, { key: 'subscription', label: '付费资产', tip: '有费用或到期日、需要续费的项目(跨类型汇总)' }, { key: 'ai_agent', label: 'AI账号', tip: 'ChatGPT 等 AI 服务账号与余额' }, ]; const tabView = Vue.computed(() => { const t = store.assetTab; if (t === 'domain') return DomainsView; if (t === 'cloudflare') return CloudflareView; if (t === 'subscription') return SubscriptionsView; if (t === 'ai_agent') return AIAccountsView; return null; }); // 通用列表:全部显示所有,VPS 前端过滤类型 const list = Vue.computed(() => { if (store.assetTab === 'vps') return store.assets.filter(a => a.asset_type === 'vps'); return store.assets; }); function switchTab(k) { store.assetTab = k; // 专有视图需要全量数据;若此前按类型过滤过则清空重载 if (k !== '' && k !== 'vps' && store.filterType) { store.filterType = ''; loadAssets(); } } // 平台筛选标签显示名:filterProvider 存 slug,回退显示原值 function providerName(slug) { const p = store.providers.find(x => x.slug === slug); return p ? p.name : slug; } async function refreshBalance(a) { if (!confirm('刷新「' + a.name + '」的余额?')) return; try { const r = await Api.post('/assets/' + a.id + '/refresh-balance', {}); alert('余额已更新:' + r.balance + ' ' + r.currency); await loadAssets(); } catch (e) { alert('刷新失败:' + e.message); } } async function syncAllAI() { if (!confirm('同步所有 AI 账号的余额?')) return; try { const r = await Api.post('/sync/ai-balances', {}); alert('同步完成:成功 ' + r.success + ',失败 ' + r.failed + (r.errors && r.errors.length ? '\n' + r.errors.join('\n') : '')); await loadAssets(); } catch (e) { alert('同步失败:' + e.message); } } return { store, Fmt, tabs, tabView, list, switchTab, providerName, reload: loadAssets, clearProvider: clearProviderFilter, edit: openAssetEdit, del: deleteAsset, viewServer, refreshBalance, syncAllAI }; }, };