From b049eaf03c1715f62bcee21203c8f132e325d051 Mon Sep 17 00:00:00 2001 From: gouki Date: Sun, 2 Aug 2026 23:53:18 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20Cloudflare=E8=A7=86=E5=9B=BE=EF=BC=88?= =?UTF-8?q?=E6=8C=89=E8=B4=A6=E5=8F=B7=E5=88=86=E7=BB=84=E5=B1=95=E7=A4=BA?= =?UTF-8?q?zone/worker/r2/tunnel/mail=E5=AD=90=E8=B5=84=E4=BA=A7=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/app.js | 50 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) 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);