feat(admin): 默认过滤实时负载禁用项
实时负载默认仅展示平台和模型均启用的来源,并增加全部状态、仅看禁用筛选及重置行为测试。
This commit is contained in:
@@ -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']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user