Files
gpustack-ui/src/pages/usage/services/use-query-breakdown-list.ts
T
Yuxing Deng 38107a67fe refactor(usage): switch breakdown dimension from model to route
Align with gpustack backend commits 7b57cd3b (add route dimension to
usage breakdown) and 51fd25c8 (use model_route_id as models_called):

* group_by, filters, and BreakdownItem now use the `route` dimension;
  `models` filter cascader is replaced with a flat `routes` selector
  (routes have no provider/cluster grouping).
* Tab / group_by option / column header keep the user-facing "模型 / Model"
  wording — only the underlying data dimension changed.
* Drop cluster_name / provider_type columns from the breakdown table;
  drop api_keys_used column per design.
* Fix pre-existing excel export bug in use-export-table — string
  dataIndex was lodash-joined char-by-char ("input_tokens" →
  "i_n_p_u_t..."), array dataIndex was used as a flat key against nested
  rows. Rebuilt around buildSheetMeta that emits a stable field key plus
  a formatMap using _.get(row, path) for nested values. Sheet name kept
  as `models` to match the visible column label.
2026-05-19 16:50:42 +08:00

94 lines
2.4 KiB
TypeScript

import {
apiKeysTableDataAtom,
modelsTableDataAtom,
usersTableDataAtom
} from '@/atoms/usage';
import { useQueryDataList } from '@/hooks/use-query-data-list';
import { useSetAtom } from 'jotai';
import React from 'react';
import { queryUsageBreakdownList } from '../apis';
import { FilterOptionType, BreakdownItem as ListItem } from '../config/types';
export const useQueryBreakdownList = (options?: {
getLabel?: (item: ListItem) => string;
getValue?: (item: ListItem) => any;
key: 'modelsTableData' | 'usersTableData' | 'apiKeysTableData' | string;
}) => {
const setApiKeysTableData = useSetAtom(apiKeysTableDataAtom);
const setModelsTableData = useSetAtom(modelsTableDataAtom);
const setUsersTableData = useSetAtom(usersTableDataAtom);
const { key = 'usageBreakdownList' } = options || {};
const [dataSource, setDataSource] = React.useState<{
loadend: boolean;
dataList: ListItem[];
total: number;
}>({
total: 0,
loadend: false,
dataList: []
});
const { dataList, loading, fetchData, cancelRequest } = useQueryDataList<
ListItem,
Global.SearchParams & {
filters: {
routes?: FilterOptionType[];
users?: FilterOptionType[];
api_keys?: FilterOptionType[];
};
},
Global.PageResponse<ListItem>
>({
key: key,
responseType: 'object',
fetchList: queryUsageBreakdownList
});
const fetchListData = async (
params: Global.SearchParams & {
filters: {
routes?: FilterOptionType[];
users?: FilterOptionType[];
api_keys?: FilterOptionType[];
};
}
) => {
const res = await fetchData(params);
setDataSource({
dataList: res.items || [],
loadend: true,
total: res.pagination?.total || 0
});
if (key === 'apiKeysTableData') {
setApiKeysTableData({
dataList: res.items || [],
loadend: true,
total: res.pagination?.total || 0
});
}
if (key === 'modelsTableData') {
setModelsTableData({
dataList: res.items || [],
loadend: true,
total: res.pagination?.total || 0
});
}
if (key === 'usersTableData') {
setUsersTableData({
dataList: res.items || [],
loadend: true,
total: res.pagination?.total || 0
});
}
};
return {
dataList,
dataSource,
loading,
fetchData: fetchListData,
cancelRequest
};
};
export default useQueryBreakdownList;