fix(usage): restore request ID column visibility

This commit is contained in:
scp-planet
2026-08-10 10:54:39 +08:00
parent 2d0976ac2c
commit 5350b3d98e
4 changed files with 156 additions and 1 deletions
+11 -1
View File
@@ -625,8 +625,10 @@ const exportToExcel = async () => {
// Column visibility
const ALWAYS_VISIBLE = ['user', 'created_at']
const DEFAULT_HIDDEN_COLUMNS = ['reasoning_effort', 'user_agent']
const DEFAULT_HIDDEN_COLUMNS = ['reasoning_effort', 'request_id', 'user_agent']
const HIDDEN_COLUMNS_KEY = 'usage-hidden-columns'
const HIDDEN_COLUMNS_VERSION_KEY = 'usage-hidden-columns-version'
const HIDDEN_COLUMNS_CURRENT_VERSION = 'request-id-hidden-by-default'
const allColumns = computed(() => [
{ key: 'user', label: t('admin.usage.user'), sortable: false },
@@ -642,6 +644,7 @@ const allColumns = computed(() => [
{ key: 'cost', label: t('usage.cost'), sortable: false },
{ key: 'latency', label: t('usage.latency'), sortable: false },
{ key: 'created_at', label: t('usage.time'), sortable: true },
{ key: 'request_id', label: t('admin.usage.requestId'), sortable: false },
{ key: 'user_agent', label: t('usage.userAgent'), sortable: false },
{ key: 'ip_address', label: t('admin.usage.ipAddress'), sortable: false }
])
@@ -668,6 +671,7 @@ const toggleColumn = (key: string) => {
}
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)
}
@@ -748,10 +752,16 @@ const loadSavedColumns = () => {
(JSON.parse(saved) as string[]).forEach((key) => {
hiddenColumns.add(key)
})
if (localStorage.getItem(HIDDEN_COLUMNS_VERSION_KEY) !== HIDDEN_COLUMNS_CURRENT_VERSION) {
hiddenColumns.add('request_id')
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 {
DEFAULT_HIDDEN_COLUMNS.forEach((key) => {
@@ -32,6 +32,7 @@ const messages: Record<string, string> = {
'admin.dashboard.day': 'Day',
'admin.dashboard.hour': 'Hour',
'admin.usage.failedToLoadUser': 'Failed to load user',
'admin.usage.requestId': 'Request ID',
'usage.requestedModel': 'Requested model',
'usage.sentUpstreamModel': 'Sent upstream model',
'usage.upstreamResponseModel': 'Upstream response model',
@@ -133,6 +134,7 @@ const UsageFiltersStub = defineComponent({
template: '<div><span data-test="user-filter-label">{{ userKeyword }}</span><slot name="after-reset" /></div>',
})
const UsageTableStub = {
props: ['columns'],
emits: ['userClick'],
template: '<div data-test="usage-table"><button class="user-click" @click="$emit(\'userClick\', 2)">user</button></div>',
}
@@ -393,6 +395,70 @@ describe('admin UsageView distribution metric toggles', () => {
})
})
describe('admin UsageView request ID column visibility', () => {
beforeEach(() => {
vi.useFakeTimers()
vi.mocked(localStorage.getItem).mockReset().mockReturnValue(null)
vi.mocked(localStorage.setItem).mockReset()
list.mockReset().mockResolvedValue({ items: [], total: 0, pages: 0 })
getStats.mockReset().mockResolvedValue({
total_requests: 0, total_input_tokens: 0, total_output_tokens: 0,
total_cache_tokens: 0, total_tokens: 0, total_cost: 0, total_actual_cost: 0, average_duration_ms: 0,
})
getSnapshotV2.mockReset().mockResolvedValue({ trend: [], models: [], groups: [] })
getModelStats.mockReset().mockResolvedValue({ models: [] })
})
afterEach(() => {
vi.useRealTimers()
})
it('keeps request ID hidden by default and allows enabling it from column settings', async () => {
const wrapper = mount(UsageView, {
global: {
stubs: {
AppLayout: AppLayoutStub,
UsageStatsCards: true,
UsageFilters: UsageFiltersStub,
UsageTable: UsageTableStub,
UsageExportProgress: true,
UsageCleanupDialog: true,
UserBalanceHistoryModal: true,
AuditLogModal: true,
Pagination: true,
Select: true,
DateRangePicker: true,
Icon: true,
TokenUsageTrend: true,
ModelDistributionChart: true,
GroupDistributionChart: true,
EndpointDistributionChart: true,
UserTokenRanking: true,
},
},
})
await wrapper.vm.$nextTick()
const usageTable = wrapper.findComponent(UsageTableStub)
expect(usageTable.props('columns')).not.toEqual(
expect.arrayContaining([expect.objectContaining({ key: 'request_id' })]),
)
await wrapper.get('button[title="admin.users.columnSettings"]').trigger('click')
const requestIdToggle = wrapper.findAll('button').find((button) => button.text() === 'Request ID')
expect(requestIdToggle).toBeDefined()
await requestIdToggle!.trigger('click')
expect(usageTable.props('columns')).toEqual(
expect.arrayContaining([expect.objectContaining({ key: 'request_id', label: 'Request ID' })]),
)
expect(localStorage.setItem).toHaveBeenCalledWith(
'usage-hidden-columns-version',
'request-id-hidden-by-default',
)
})
})
describe('admin UsageView handleUserClick', () => {
beforeEach(() => {
vi.useFakeTimers()