feat(token): add batch API for fetching token keys

Add new endpoint POST /api/token/batch/keys to fetch multiple
token keys in a single request, improving performance when
exporting or copying multiple tokens.

- Backend: Add GetTokenKeysBatch controller and GetTokenKeysByIds model
- Backend: Add route with CriticalRateLimit and DisableCache middleware
- Frontend: Add fetchTokenKeysBatch helper function
- Frontend: Update useTokensData to use batch API for token export
This commit is contained in:
RedwindA
2026-04-06 18:07:27 +08:00
parent eacc245bad
commit 12a48c620e
9 changed files with 60 additions and 6 deletions
+14
View File
@@ -33,6 +33,20 @@ export async function fetchTokenKey(tokenId) {
return data.key;
}
/**
* 批量获取多个令牌的真实 key
* @param {number[]} tokenIds
* @returns {Promise<Record<number, string>>} 返回 {id: key} mapkey 不带 sk- 前缀
*/
export async function fetchTokenKeysBatch(tokenIds) {
const response = await API.post('/api/token/batch/keys', { ids: tokenIds });
const { success, data, message } = response.data || {};
if (!success || !data?.keys) {
throw new Error(message || 'Failed to fetch token keys');
}
return data.keys;
}
/**
* 获取可用的 token keys
* @returns {Promise<string[]>} 返回 active 状态的不带 sk- 前缀的真实 token key 数组
+10 -6
View File
@@ -31,6 +31,7 @@ import { ITEMS_PER_PAGE } from '../../constants';
import { useTableCompactMode } from '../common/useTableCompactMode';
import {
fetchTokenKey as fetchTokenKeyById,
fetchTokenKeysBatch,
getServerAddress,
encodeChannelConnectionString,
} from '../../helpers/token';
@@ -408,14 +409,17 @@ export const useTokensData = (openFluentNotification, openCCSwitchModal) => {
return;
}
try {
const keys = await Promise.all(
selectedKeys.map((token) => fetchTokenKey(token, { suppressError: true })),
);
const ids = selectedKeys.map((token) => token.id);
const keysMap = await fetchTokenKeysBatch(ids);
setResolvedTokenKeys((prev) => ({ ...prev, ...keysMap }));
let content = '';
for (let i = 0; i < selectedKeys.length; i++) {
const fullKey = keys[i];
for (const token of selectedKeys) {
const fullKey = keysMap[token.id];
if (!fullKey) continue;
if (copyType === 'name+key') {
content += `${selectedKeys[i].name} sk-${fullKey}\n`;
content += `${token.name} sk-${fullKey}\n`;
} else {
content += `sk-${fullKey}\n`;
}