mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-03-30 00:33:35 +00:00
fix: 修复速率限制的使用次数显示问题
This commit is contained in:
@@ -1031,7 +1031,11 @@ router.post('/api-keys/batch-stats', authenticateAdmin, async (req, res) => {
|
||||
dailyCost: 0,
|
||||
weeklyOpusCost: 0,
|
||||
currentWindowCost: 0,
|
||||
currentWindowRequests: 0,
|
||||
currentWindowTokens: 0,
|
||||
windowRemainingSeconds: null,
|
||||
windowStartTime: null,
|
||||
windowEndTime: null,
|
||||
allTimeCost: 0,
|
||||
error: error.message
|
||||
}
|
||||
@@ -1110,8 +1114,10 @@ async function calculateKeyStats(keyId, timeRange, startDate, endDate) {
|
||||
|
||||
// 获取实时限制数据(窗口数据不受时间范围筛选影响,始终获取当前窗口状态)
|
||||
let dailyCost = 0
|
||||
let weeklyOpusCost = 0 // 字段名沿用 weeklyOpusCost*,语义为“Claude 周费用”
|
||||
let weeklyOpusCost = 0 // 字段名沿用 weeklyOpusCost*,语义为"Claude 周费用"
|
||||
let currentWindowCost = 0
|
||||
let currentWindowRequests = 0 // 当前窗口请求次数
|
||||
let currentWindowTokens = 0 // 当前窗口 Token 使用量
|
||||
let windowRemainingSeconds = null
|
||||
let windowStartTime = null
|
||||
let windowEndTime = null
|
||||
@@ -1141,6 +1147,38 @@ async function calculateKeyStats(keyId, timeRange, startDate, endDate) {
|
||||
weeklyOpusCost = await redis.getWeeklyOpusCost(keyId)
|
||||
}
|
||||
|
||||
// 只在启用了窗口限制时查询窗口数据(移到早期返回之前,确保窗口数据始终被获取)
|
||||
if (rateLimitWindow > 0) {
|
||||
const requestCountKey = `rate_limit:requests:${keyId}`
|
||||
const tokenCountKey = `rate_limit:tokens:${keyId}`
|
||||
const costCountKey = `rate_limit:cost:${keyId}`
|
||||
const windowStartKey = `rate_limit:window_start:${keyId}`
|
||||
|
||||
currentWindowRequests = parseInt((await client.get(requestCountKey)) || '0')
|
||||
currentWindowTokens = parseInt((await client.get(tokenCountKey)) || '0')
|
||||
currentWindowCost = parseFloat((await client.get(costCountKey)) || '0')
|
||||
|
||||
// 获取窗口开始时间和计算剩余时间
|
||||
const windowStart = await client.get(windowStartKey)
|
||||
if (windowStart) {
|
||||
const now = Date.now()
|
||||
windowStartTime = parseInt(windowStart)
|
||||
const windowDuration = rateLimitWindow * 60 * 1000 // 转换为毫秒
|
||||
windowEndTime = windowStartTime + windowDuration
|
||||
|
||||
// 如果窗口还有效
|
||||
if (now < windowEndTime) {
|
||||
windowRemainingSeconds = Math.max(0, Math.floor((windowEndTime - now) / 1000))
|
||||
} else {
|
||||
// 窗口已过期
|
||||
windowRemainingSeconds = 0
|
||||
currentWindowRequests = 0
|
||||
currentWindowTokens = 0
|
||||
currentWindowCost = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 🔧 FIX: 对于 "全部时间" 时间范围,直接使用 allTimeCost
|
||||
// 因为 usage:*:model:daily:* 键有 30 天 TTL,旧数据已经过期
|
||||
if (timeRange === 'all' && allTimeCost > 0) {
|
||||
@@ -1159,38 +1197,14 @@ async function calculateKeyStats(keyId, timeRange, startDate, endDate) {
|
||||
dailyCost,
|
||||
weeklyOpusCost,
|
||||
currentWindowCost,
|
||||
currentWindowRequests,
|
||||
currentWindowTokens,
|
||||
windowRemainingSeconds,
|
||||
windowStartTime,
|
||||
windowEndTime,
|
||||
allTimeCost
|
||||
}
|
||||
}
|
||||
|
||||
// 只在启用了窗口限制时查询窗口数据
|
||||
if (rateLimitWindow > 0) {
|
||||
const costCountKey = `rate_limit:cost:${keyId}`
|
||||
const windowStartKey = `rate_limit:window_start:${keyId}`
|
||||
|
||||
currentWindowCost = parseFloat((await client.get(costCountKey)) || '0')
|
||||
|
||||
// 获取窗口开始时间和计算剩余时间
|
||||
const windowStart = await client.get(windowStartKey)
|
||||
if (windowStart) {
|
||||
const now = Date.now()
|
||||
windowStartTime = parseInt(windowStart)
|
||||
const windowDuration = rateLimitWindow * 60 * 1000 // 转换为毫秒
|
||||
windowEndTime = windowStartTime + windowDuration
|
||||
|
||||
// 如果窗口还有效
|
||||
if (now < windowEndTime) {
|
||||
windowRemainingSeconds = Math.max(0, Math.floor((windowEndTime - now) / 1000))
|
||||
} else {
|
||||
// 窗口已过期
|
||||
windowRemainingSeconds = 0
|
||||
currentWindowCost = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(`⚠️ 获取实时限制数据失败 (key: ${keyId}):`, error.message)
|
||||
}
|
||||
@@ -1210,6 +1224,8 @@ async function calculateKeyStats(keyId, timeRange, startDate, endDate) {
|
||||
dailyCost,
|
||||
weeklyOpusCost,
|
||||
currentWindowCost,
|
||||
currentWindowRequests,
|
||||
currentWindowTokens,
|
||||
windowRemainingSeconds,
|
||||
windowStartTime,
|
||||
windowEndTime,
|
||||
@@ -1329,6 +1345,8 @@ async function calculateKeyStats(keyId, timeRange, startDate, endDate) {
|
||||
dailyCost,
|
||||
weeklyOpusCost,
|
||||
currentWindowCost,
|
||||
currentWindowRequests,
|
||||
currentWindowTokens,
|
||||
windowRemainingSeconds,
|
||||
windowStartTime,
|
||||
windowEndTime,
|
||||
|
||||
@@ -4263,6 +4263,8 @@ const showUsageDetails = (apiKey) => {
|
||||
dailyCost: cachedStats?.dailyCost ?? apiKey.dailyCost ?? 0,
|
||||
weeklyOpusCost: cachedStats?.weeklyOpusCost ?? apiKey.weeklyOpusCost ?? 0,
|
||||
currentWindowCost: cachedStats?.currentWindowCost ?? apiKey.currentWindowCost ?? 0,
|
||||
currentWindowRequests: cachedStats?.currentWindowRequests ?? apiKey.currentWindowRequests ?? 0,
|
||||
currentWindowTokens: cachedStats?.currentWindowTokens ?? apiKey.currentWindowTokens ?? 0,
|
||||
windowRemainingSeconds: cachedStats?.windowRemainingSeconds ?? apiKey.windowRemainingSeconds,
|
||||
windowStartTime: cachedStats?.windowStartTime ?? apiKey.windowStartTime ?? null,
|
||||
windowEndTime: cachedStats?.windowEndTime ?? apiKey.windowEndTime ?? null,
|
||||
|
||||
Reference in New Issue
Block a user