Merge pull request #3811 from jianjianai/hotfix/admin-scheduler-score-opt-in

fix(admin): 管理员账号列表默认关闭调度权值计算以降低负载
This commit is contained in:
Wesley Liddick
2026-07-08 10:22:10 +08:00
committed by GitHub
6 changed files with 111 additions and 6 deletions
+2
View File
@@ -41,6 +41,7 @@ export async function list(
search?: string
privacy_mode?: string
lite?: string
include_scheduler_score?: string
sort_by?: string
sort_order?: 'asc' | 'desc'
},
@@ -76,6 +77,7 @@ export async function listWithEtag(
search?: string
privacy_mode?: string
lite?: string
include_scheduler_score?: string
sort_by?: string
sort_order?: 'asc' | 'desc'
},
+33 -1
View File
@@ -547,8 +547,11 @@ const exportingData = ref(false)
const showAccountToolsDropdown = ref(false)
const accountToolsDropdownRef = ref<HTMLElement | null>(null)
const hiddenColumns = reactive<Set<string>>(new Set())
const DEFAULT_HIDDEN_COLUMNS = ['today_stats', 'proxy', 'notes', 'priority', 'rate_multiplier']
const DEFAULT_HIDDEN_COLUMNS = ['today_stats', 'proxy', 'notes', 'priority', 'scheduler_score', 'rate_multiplier']
const HIDDEN_COLUMNS_KEY = 'account-hidden-columns'
// One-time migration: hide scheduler score for existing admins too, because showing it opt-ins to heavy backend scoring.
const HIDDEN_COLUMNS_VERSION_KEY = 'account-hidden-columns-version'
const HIDDEN_COLUMNS_CURRENT_VERSION = 'scheduler-score-hidden-by-default'
// Sorting settings
const ACCOUNT_SORT_STORAGE_KEY = 'account-table-sort'
@@ -704,10 +707,17 @@ const loadSavedColumns = () => {
parsed.forEach(key => {
hiddenColumns.add(key)
})
// Older saved column layouts may have scheduler_score visible; migrate them to the new safe default once.
if (localStorage.getItem(HIDDEN_COLUMNS_VERSION_KEY) !== HIDDEN_COLUMNS_CURRENT_VERSION) {
hiddenColumns.add('scheduler_score')
localStorage.setItem(HIDDEN_COLUMNS_KEY, JSON.stringify([...hiddenColumns]))
localStorage.setItem(HIDDEN_COLUMNS_VERSION_KEY, HIDDEN_COLUMNS_CURRENT_VERSION)
}
} else {
DEFAULT_HIDDEN_COLUMNS.forEach(key => {
hiddenColumns.add(key)
})
localStorage.setItem(HIDDEN_COLUMNS_VERSION_KEY, HIDDEN_COLUMNS_CURRENT_VERSION)
}
} catch (e) {
console.error('Failed to load saved columns:', e)
@@ -720,6 +730,7 @@ const loadSavedColumns = () => {
const saveColumnsToStorage = () => {
try {
localStorage.setItem(HIDDEN_COLUMNS_KEY, JSON.stringify([...hiddenColumns]))
localStorage.setItem(HIDDEN_COLUMNS_VERSION_KEY, HIDDEN_COLUMNS_CURRENT_VERSION)
} catch (e) {
console.error('Failed to save columns:', e)
}
@@ -792,9 +803,22 @@ const toggleColumn = (key: string) => {
console.error('Failed to load account today stats after showing column:', error)
})
}
if (key === 'scheduler_score') {
// The server only returns scheduler scores when this column is visible, so reload the current page immediately.
syncAccountListDerivedParams()
load().catch((error) => {
console.error('Failed to reload accounts after toggling scheduler score column:', error)
})
}
}
const isColumnVisible = (key: string) => !hiddenColumns.has(key)
const shouldIncludeSchedulerScore = () => isColumnVisible('scheduler_score')
const syncAccountListDerivedParams = () => {
// Keep every load path, including auto-refresh and sorting, aligned with the current column visibility.
const requestParams = params as any
requestParams.include_scheduler_score = shouldIncludeSchedulerScore() ? '1' : '0'
}
const {
items: accounts,
@@ -815,6 +839,7 @@ const {
privacy_mode: '',
group: '',
search: '',
include_scheduler_score: shouldIncludeSchedulerScore() ? '1' : '0',
sort_by: sortState.sort_by,
sort_order: sortState.sort_order
}
@@ -859,6 +884,7 @@ const isFirstLoad = ref(true)
const load = async () => {
const requestParams = params as any
syncAccountListDerivedParams()
hasPendingListSync.value = false
resetAutoRefreshCache()
pendingTodayStatsRefresh.value = false
@@ -874,6 +900,7 @@ const load = async () => {
}
const reload = async () => {
syncAccountListDerivedParams()
hasPendingListSync.value = false
resetAutoRefreshCache()
pendingTodayStatsRefresh.value = false
@@ -882,6 +909,7 @@ const reload = async () => {
}
const debouncedReload = () => {
syncAccountListDerivedParams()
hasPendingListSync.value = false
resetAutoRefreshCache()
pendingTodayStatsRefresh.value = true
@@ -889,6 +917,7 @@ const debouncedReload = () => {
}
const handlePageChange = (page: number) => {
syncAccountListDerivedParams()
hasPendingListSync.value = false
resetAutoRefreshCache()
pendingTodayStatsRefresh.value = true
@@ -896,6 +925,7 @@ const handlePageChange = (page: number) => {
}
const handlePageSizeChange = (size: number) => {
syncAccountListDerivedParams()
hasPendingListSync.value = false
resetAutoRefreshCache()
pendingTodayStatsRefresh.value = true
@@ -908,6 +938,7 @@ const handleSort = (key: string, order: AccountSortOrder) => {
const requestParams = params as any
requestParams.sort_by = key
requestParams.sort_order = order
syncAccountListDerivedParams()
pagination.page = 1
hasPendingListSync.value = false
resetAutoRefreshCache()
@@ -1007,6 +1038,7 @@ const mergeAccountsIncrementally = (nextRows: Account[]) => {
const refreshAccountsIncrementally = async () => {
if (autoRefreshFetching.value) return
syncAccountListDerivedParams()
autoRefreshFetching.value = true
try {
const result = await adminAPI.accounts.listWithEtag(
@@ -196,6 +196,10 @@ describe('admin AccountsView scheduler score column', () => {
const wrapper = mountView()
await flushPromises()
expect(listAccounts.mock.calls[0]?.[2]).toEqual(expect.objectContaining({
include_scheduler_score: '0'
}))
const ungroupedCell = wrapper.find('[data-test="scheduler-score-1"]')
expect(ungroupedCell.exists()).toBe(true)
expect(ungroupedCell.text()).toContain('1.234567')
@@ -213,6 +217,30 @@ describe('admin AccountsView scheduler score column', () => {
expect(groupedCell.text()).toContain('2')
})
it('keeps scheduler score hidden for old saved column settings until the admin opts in again', async () => {
localStorage.setItem('account-hidden-columns', JSON.stringify(['today_stats']))
mountView()
await flushPromises()
expect(listAccounts.mock.calls[0]?.[2]).toEqual(expect.objectContaining({
include_scheduler_score: '0'
}))
expect(JSON.parse(localStorage.getItem('account-hidden-columns') || '[]')).toContain('scheduler_score')
})
it('requests scheduler scores when the migrated column settings explicitly show the column', async () => {
localStorage.setItem('account-hidden-columns', JSON.stringify(['today_stats']))
localStorage.setItem('account-hidden-columns-version', 'scheduler-score-hidden-by-default')
mountView()
await flushPromises()
expect(listAccounts.mock.calls[0]?.[2]).toEqual(expect.objectContaining({
include_scheduler_score: '1'
}))
})
it('still shows a dash when no scheduler score is available', async () => {
const wrapper = mountView()
await flushPromises()