feat: 平台卡片「关联N个资产」点击跳转资产页并按平台筛选(后端/api/assets新增provider参数,资产页可清除筛选标签)
This commit is contained in:
@@ -17,6 +17,7 @@ const store = reactive({
|
||||
search: '',
|
||||
filterType: '',
|
||||
filterStatus: '',
|
||||
filterProvider: '', // 按平台筛选(slug),从平台页「关联 N 个资产」跳转而来
|
||||
assetTab: '', // 资产页 TAB:'' 全部 / vps / domain / cloudflare / subscription(付费资产) / ai_agent
|
||||
monitorTab: '', // 监控中心 TAB:同上
|
||||
dark: localStorage.getItem('vps_dark') === '1',
|
||||
@@ -76,6 +77,7 @@ async function loadAssets() {
|
||||
const params = new URLSearchParams();
|
||||
if (store.filterType) params.set('asset_type', store.filterType);
|
||||
if (store.filterStatus) params.set('status', store.filterStatus);
|
||||
if (store.filterProvider) params.set('provider', store.filterProvider);
|
||||
if (store.search) params.set('q', store.search);
|
||||
params.set('sort', 'expiry_date'); params.set('order', 'asc');
|
||||
store.assets = await Api.get('/assets?' + params.toString());
|
||||
@@ -197,6 +199,19 @@ async function deleteAccount(a) {
|
||||
catch (e) { store.error = e.message; }
|
||||
}
|
||||
|
||||
/* ---------------- 平台页跳转:按平台查看资产 ---------------- */
|
||||
function openAssetsByProvider(p) {
|
||||
store.filterProvider = p.slug;
|
||||
store.assetTab = '';
|
||||
store.filterType = '';
|
||||
if (window.location.hash !== '#assets') window.location.hash = '#assets';
|
||||
loadAssets();
|
||||
}
|
||||
function clearProviderFilter() {
|
||||
store.filterProvider = '';
|
||||
loadAssets();
|
||||
}
|
||||
|
||||
/* ---------------- 服务器监控 ---------------- */
|
||||
async function viewServer(a) {
|
||||
try {
|
||||
|
||||
@@ -14,6 +14,14 @@ const AssetsView = {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 平台筛选标签(从平台页跳转而来,点 ✕ 取消) -->
|
||||
<div v-if="store.filterProvider" class="flex items-center">
|
||||
<span class="inline-flex items-center gap-1 text-xs px-2.5 py-1 rounded-full bg-blue-500/10 text-blue-600 dark:text-blue-400">
|
||||
🏢 平台:{{ providerName(store.filterProvider) }}
|
||||
<button @click="clearProvider" class="font-bold hover:opacity-70" title="取消平台筛选">✕</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 通用列表(全部 / VPS) -->
|
||||
<template v-if="store.assetTab==='' || store.assetTab==='vps'">
|
||||
<div class="flex flex-wrap gap-2 items-center">
|
||||
@@ -116,6 +124,11 @@ const AssetsView = {
|
||||
// 专有视图需要全量数据;若此前按类型过滤过则清空重载
|
||||
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 {
|
||||
@@ -132,6 +145,6 @@ const AssetsView = {
|
||||
await loadAssets();
|
||||
} catch (e) { alert('同步失败:' + e.message); }
|
||||
}
|
||||
return { store, Fmt, tabs, tabView, list, switchTab, reload: loadAssets, edit: openAssetEdit, del: deleteAsset, viewServer, refreshBalance, syncAllAI };
|
||||
return { store, Fmt, tabs, tabView, list, switchTab, providerName, reload: loadAssets, clearProvider: clearProviderFilter, edit: openAssetEdit, del: deleteAsset, viewServer, refreshBalance, syncAllAI };
|
||||
},
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ const ProvidersView = {
|
||||
<div v-if="p.sdk_type">API 对接: {{ p.sdk_type }}</div>
|
||||
<div v-if="p.console_url"><a :href="p.console_url" target="_blank" class="text-blue-600 dark:text-blue-400 hover:underline">管理面板 ↗</a></div>
|
||||
<div class="flex items-center gap-2 mt-1">
|
||||
<span class="text-slate-500">📎 关联 {{ countOf(p) }} 个资产</span>
|
||||
<button @click="goAssets(p)" :disabled="!countOf(p)" class="text-slate-500 hover:text-blue-600 dark:hover:text-blue-400 disabled:hover:text-slate-500" :title="countOf(p) ? '查看该平台下的资产' : ''">📎 关联 {{ countOf(p) }} 个资产</button>
|
||||
<button @click="openAccounts(p)" class="text-slate-500 hover:text-blue-600 dark:hover:text-blue-400">👤 账号 {{ accountsCountOf(p) }}</button>
|
||||
<span v-if="p.has_api_config" class="text-emerald-600 dark:text-emerald-400">已配置 API</span>
|
||||
<span v-else class="text-slate-400">未配置 API</span>
|
||||
@@ -118,6 +118,6 @@ const ProvidersView = {
|
||||
} catch (e) { results[p.id] = { ok: false, text: '✗ ' + e.message }; }
|
||||
finally { syncing[p.id] = false; }
|
||||
}
|
||||
return { store, Fmt, testing, syncing, results, countOf, accountsCountOf, serviceList, showAll, toggleShowAll, visibleProviders, hiddenCount, isSupported, canSync, fmtTime, test, sync, seed: seedProviders, create: openProviderCreate, edit: openProviderEdit, del: deleteProvider, openAccounts: (p) => openAccountsView(p.slug), manageAccounts: () => openAccountsView(null) };
|
||||
return { store, Fmt, testing, syncing, results, countOf, accountsCountOf, serviceList, showAll, toggleShowAll, visibleProviders, hiddenCount, isSupported, canSync, fmtTime, test, sync, seed: seedProviders, create: openProviderCreate, edit: openProviderEdit, del: deleteProvider, openAccounts: (p) => openAccountsView(p.slug), manageAccounts: () => openAccountsView(null), goAssets: openAssetsByProvider };
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user