feat(webui): add hot-reload account management with OAuth support

This commit is contained in:
Wha1eChai
2026-01-08 23:49:12 +08:00
parent dc9bea1100
commit c9c5e7d486
10 changed files with 194 additions and 153 deletions

View File

@@ -28,6 +28,14 @@ window.Components.accountManager = () => ({
async toggleAccount(email, enabled) {
const store = Alpine.store('global');
const password = store.webuiPassword;
// Optimistic update: immediately update UI
const dataStore = Alpine.store('data');
const account = dataStore.accounts.find(a => a.email === email);
if (account) {
account.enabled = enabled;
}
try {
const { response, newPassword } = await window.utils.request(`/api/accounts/${encodeURIComponent(email)}/toggle`, {
method: 'POST',
@@ -40,12 +48,23 @@ window.Components.accountManager = () => ({
if (data.status === 'ok') {
const status = enabled ? store.t('enabledStatus') : store.t('disabledStatus');
store.showToast(store.t('accountToggled', { email, status }), 'success');
Alpine.store('data').fetchData();
// Refresh to confirm server state
await dataStore.fetchData();
} else {
store.showToast(data.error || store.t('toggleFailed'), 'error');
// Rollback optimistic update on error
if (account) {
account.enabled = !enabled;
}
await dataStore.fetchData();
}
} catch (e) {
store.showToast(store.t('toggleFailed') + ': ' + e.message, 'error');
// Rollback optimistic update on error
if (account) {
account.enabled = !enabled;
}
await dataStore.fetchData();
}
},

View File

@@ -495,7 +495,10 @@ window.Components.dashboard = () => ({
const isCore = (id) => /sonnet|opus|pro|flash/i.test(id);
accounts.forEach(acc => {
// Only count enabled accounts in statistics
const enabledAccounts = accounts.filter(acc => acc.enabled !== false);
enabledAccounts.forEach(acc => {
if (acc.status === 'ok') {
const limits = Object.entries(acc.limits || {});
let hasActiveCore = limits.some(([id, l]) => l && l.remainingFraction > 0.05 && isCore(id));
@@ -512,7 +515,10 @@ window.Components.dashboard = () => ({
limited++;
}
});
this.stats.total = accounts.length;
// TOTAL shows only enabled accounts
// Disabled accounts are excluded from all statistics
this.stats.total = enabledAccounts.length;
this.stats.active = active;
this.stats.limited = limited;
},