diff --git a/static/js/app.js b/static/js/app.js
index 12b4181..9c883bc 100644
--- a/static/js/app.js
+++ b/static/js/app.js
@@ -416,6 +416,52 @@ const SubscriptionsView = {
},
};
+const SUB_TYPE_LABELS = { zone: '解析', worker: 'Worker', r2: 'R2', tunnel: 'Tunnel', mail: 'Mail', dns_record: 'DNS记录', other: '其他' };
+
+const CloudflareView = {
+ template: `
+
+
+ 暂无 Cloudflare 子资产(新增资产时选 Cloudflare 类型即可)
+
+
+
+
☁️ {{ g.account || '未指定账号' }}
+
{{ g.items.length }} 个子资产
+
+
+
+
+ {{ SUB_TYPE_LABELS[a.cloudflare_detail.sub_type] || a.cloudflare_detail.sub_type }}
+ {{ a.cloudflare_detail.sub_name || a.cloudflare_detail.zone_name || a.name }}
+ @{{ a.cloudflare_detail.zone_name }}
+
+
+ {{ a.cloudflare_detail.status }}
+
+
+
+
+
+
`,
+ setup() {
+ const groups = computed(() => {
+ const cfAssets = store.assets.filter(a => a.asset_type === 'cloudflare' && a.cloudflare_detail);
+ const map = {};
+ for (const a of cfAssets) {
+ const acc = a.cloudflare_detail.account_email || '';
+ if (!map[acc]) map[acc] = { account: a.cloudflare_detail.account_email, items: [] };
+ map[acc].items.push(a);
+ }
+ return Object.values(map);
+ });
+ function subTypeBadge(t) {
+ return { zone: 'bg-blue-500/10 text-blue-600 dark:text-blue-400', worker: 'bg-orange-500/10 text-orange-600 dark:text-orange-400', r2: 'bg-purple-500/10 text-purple-600 dark:text-purple-400', tunnel: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400', mail: 'bg-pink-500/10 text-pink-600 dark:text-pink-400', dns_record: 'bg-slate-500/10 text-slate-600', other: 'bg-slate-500/10 text-slate-500' }[t] || 'bg-slate-500/10 text-slate-500';
+ }
+ return { store, groups, subTypeBadge, SUB_TYPE_LABELS, edit: openAssetEdit };
+ },
+};
+
const ProvidersView = {
template: `
@@ -979,12 +1025,13 @@ const AppRoot = {
{ key: 'assets', label: '资产', icon: '📦' },
{ key: 'servers', label: '服务器', icon: '🖥️' },
{ key: 'domains', label: '域名', icon: '🌐' },
+ { key: 'cloudflare', label: 'Cloudflare', icon: '☁️' },
{ key: 'subscriptions', label: '订阅', icon: '💳' },
{ key: 'ai', label: 'AI账号', icon: '🤖' },
{ key: 'providers', label: '平台', icon: '🏢' },
{ key: 'settings', label: '设置', icon: '⚙️' },
];
- const viewMap = { dashboard: 'dashboard-view', assets: 'assets-view', servers: 'servers-view', domains: 'domains-view', subscriptions: 'subscriptions-view', ai: 'ai-view', providers: 'providers-view', settings: 'settings-view' };
+ const viewMap = { dashboard: 'dashboard-view', assets: 'assets-view', servers: 'servers-view', domains: 'domains-view', cloudflare: 'cloudflare-view', subscriptions: 'subscriptions-view', ai: 'ai-view', providers: 'providers-view', settings: 'settings-view' };
const currentNav = computed(() => navs.find(n => n.key === store.view) || navs[0]);
const viewComponent = computed(() => viewMap[store.view] || 'dashboard-view');
function go(key) { store.view = key; if (key !== 'servers') store.serverMetrics = {}; if (key === 'ai') { store.filterType = ''; store.filterStatus = ''; store.search = ''; loadAssets(); } }
@@ -1006,6 +1053,7 @@ app.component('assets-view', AssetsView);
app.component('providers-view', ProvidersView);
app.component('servers-view', ServersView);
app.component('domains-view', DomainsView);
+app.component('cloudflare-view', CloudflareView);
app.component('subscriptions-view', SubscriptionsView);
app.component('ai-view', AIAccountsView);
app.component('settings-view', SettingsView);