feat(admin): 默认过滤实时负载禁用项

实时负载默认仅展示平台和模型均启用的来源,并增加全部状态、仅看禁用筛选及重置行为测试。
This commit is contained in:
2026-08-03 15:43:49 +08:00
parent ad8cdd525b
commit b56769512f
2 changed files with 39 additions and 3 deletions
@@ -37,6 +37,7 @@ describe('filterAndSortRealtimeLoad', () => {
const result = filterAndSortRealtimeLoad(statuses, platforms, {
query: '平台',
platformId: '',
availability: 'enabled',
modelType: '',
runtimeState: '',
sortField: 'load',
@@ -50,6 +51,7 @@ describe('filterAndSortRealtimeLoad', () => {
const queued = filterAndSortRealtimeLoad(statuses, platforms, {
query: '',
platformId: '',
availability: 'enabled',
modelType: 'image_generate',
runtimeState: 'queued',
sortField: 'queued',
@@ -59,6 +61,7 @@ describe('filterAndSortRealtimeLoad', () => {
const attention = filterAndSortRealtimeLoad(statuses, platforms, {
query: '',
platformId: '',
availability: 'all',
modelType: '',
runtimeState: 'attention',
sortField: 'load',
@@ -69,4 +72,19 @@ describe('filterAndSortRealtimeLoad', () => {
expect(attention.map((item) => item.platformModelId)).toEqual(['model-b']);
expect(statuses.map((item) => item.platformModelId)).toEqual(['model-a', 'model-b']);
});
it('hides disabled entries by default and supports all or disabled-only filters', () => {
const base = {
query: '',
platformId: '',
modelType: '',
runtimeState: '',
sortField: 'load' as const,
sortDirection: 'desc' as const,
now: Date.now(),
};
expect(filterAndSortRealtimeLoad(statuses, platforms, { ...base, availability: 'enabled' }).map((item) => item.platformModelId)).toEqual(['model-a']);
expect(filterAndSortRealtimeLoad(statuses, platforms, { ...base, availability: 'all' }).map((item) => item.platformModelId)).toEqual(['model-b', 'model-a']);
expect(filterAndSortRealtimeLoad(statuses, platforms, { ...base, availability: 'disabled' }).map((item) => item.platformModelId)).toEqual(['model-b']);
});
});
+21 -3
View File
@@ -19,6 +19,7 @@ export function RealtimeLoadPanel(props: {
const [restoreSavingId, setRestoreSavingId] = useState<string | null>(null);
const [query, setQuery] = useState('');
const [platformId, setPlatformId] = useState('');
const [availability, setAvailability] = useState<RealtimeLoadAvailability>('enabled');
const [modelType, setModelType] = useState('');
const [runtimeState, setRuntimeState] = useState('');
const [sortField, setSortField] = useState<RealtimeLoadSortField>('load');
@@ -33,21 +34,22 @@ export function RealtimeLoadPanel(props: {
() => filterAndSortRealtimeLoad(props.modelRateLimits, platformMap, {
query,
platformId,
availability,
modelType,
runtimeState,
sortField,
sortDirection,
now,
}),
[modelType, now, platformId, platformMap, props.modelRateLimits, query, runtimeState, sortDirection, sortField],
[availability, modelType, now, platformId, platformMap, props.modelRateLimits, query, runtimeState, sortDirection, sortField],
);
const hasActiveFilters = Boolean(query || platformId || modelType || runtimeState);
const hasActiveFilters = Boolean(query || platformId || modelType || runtimeState || availability !== 'all');
const advancedFilterCount = [
modelType,
runtimeState,
sortDirection === 'desc' ? '' : sortDirection,
].filter(Boolean).length;
const hasActiveSettings = Boolean(query || platformId || advancedFilterCount || sortField !== 'load');
const hasActiveSettings = Boolean(query || platformId || availability !== 'enabled' || advancedFilterCount || sortField !== 'load');
useEffect(() => {
const timer = window.setInterval(() => setNow(Date.now()), 1000);
@@ -112,6 +114,7 @@ export function RealtimeLoadPanel(props: {
function resetFilters() {
setQuery('');
setPlatformId('');
setAvailability('enabled');
setModelType('');
setRuntimeState('');
setSortField('load');
@@ -153,6 +156,15 @@ export function RealtimeLoadPanel(props: {
<option value="rpm">RPM</option>
<option value="priority"></option>
</Select>
<Select
aria-label="启用状态筛选"
value={availability}
onChange={(event) => setAvailability(event.target.value as RealtimeLoadAvailability)}
>
<option value="enabled"></option>
<option value="all"></option>
<option value="disabled"></option>
</Select>
<div className="compactAdminToolbarActions">
<Button type="button" variant="outline" size="sm" onClick={() => setFilterDialogOpen(true)}>
<SlidersHorizontal size={14} />
@@ -422,6 +434,7 @@ export function filterAndSortRealtimeLoad(
options: {
query: string;
platformId: string;
availability: RealtimeLoadAvailability;
modelType: string;
runtimeState: string;
sortField: RealtimeLoadSortField;
@@ -447,6 +460,8 @@ export function filterAndSortRealtimeLoad(
const cooling = cooldownRemainingMs(status.modelCooldownUntil, options.now) > 0 ||
cooldownRemainingMs(status.platformCooldownUntil, options.now) > 0;
const disabled = !status.enabled || status.platformStatus !== 'enabled';
const matchesAvailability = options.availability === 'all' ||
(options.availability === 'disabled' ? disabled : !disabled);
const queuedTasks = admissionQueueDepth(status);
const matchesRuntime = !options.runtimeState ||
(options.runtimeState === 'high' && status.loadRatio >= 0.8) ||
@@ -456,6 +471,7 @@ export function filterAndSortRealtimeLoad(
return (!keyword || text.includes(keyword)) &&
(!options.platformId || status.platformId === options.platformId) &&
(!options.modelType || status.modelType.includes(options.modelType)) &&
matchesAvailability &&
matchesRuntime;
});
const direction = options.sortDirection === 'asc' ? 1 : -1;
@@ -466,6 +482,8 @@ export function filterAndSortRealtimeLoad(
});
}
export type RealtimeLoadAvailability = 'enabled' | 'disabled' | 'all';
function realtimeLoadSortValue(status: ModelRateLimitStatus, field: RealtimeLoadSortField) {
if (field === 'queued') return admissionQueueDepth(status);
if (field === 'concurrent') return status.concurrent.currentValue;