feat(webui): add subscription tier and quota visualization

Backend:
This commit is contained in:
Wha1eChai
2026-01-10 06:04:51 +08:00
parent 369a66e8cf
commit ee6d222e4d
11 changed files with 277 additions and 18 deletions

View File

@@ -163,5 +163,40 @@ window.Components.accountManager = () => ({
} catch (e) {
store.showToast(store.t('reloadFailed') + ': ' + e.message, 'error');
}
},
/**
* Get main model quota for display
* Prioritizes flagship models (Opus > Sonnet > Flash)
* @param {Object} account - Account object with limits
* @returns {Object} { percent: number|null, model: string }
*/
getMainModelQuota(account) {
const limits = account.limits || {};
const modelIds = Object.keys(limits);
if (modelIds.length === 0) {
return { percent: null, model: '-' };
}
// Priority: opus > sonnet > flash > others
const priorityModels = [
modelIds.find(m => m.toLowerCase().includes('opus')),
modelIds.find(m => m.toLowerCase().includes('sonnet')),
modelIds.find(m => m.toLowerCase().includes('flash')),
modelIds[0] // Fallback to first model
];
const selectedModel = priorityModels.find(m => m) || modelIds[0];
const quota = limits[selectedModel];
if (!quota || quota.remainingFraction === null) {
return { percent: null, model: selectedModel };
}
return {
percent: Math.round(quota.remainingFraction * 100),
model: selectedModel
};
}
});

View File

@@ -40,4 +40,18 @@ window.DashboardStats.updateStats = function(component) {
component.stats.total = enabledAccounts.length;
component.stats.active = active;
component.stats.limited = limited;
// Calculate subscription tier distribution
const subscription = { ultra: 0, pro: 0, free: 0 };
enabledAccounts.forEach(acc => {
const tier = acc.subscription?.tier || 'free';
if (tier === 'ultra') {
subscription.ultra++;
} else if (tier === 'pro') {
subscription.pro++;
} else {
subscription.free++;
}
});
component.stats.subscription = subscription;
};