feat: 添加精确的账户费用计算和时区支持

- 实现基于模型使用量的精确每日费用计算
- 添加 dateHelper 工具支持时区转换
- 移除未使用的 webhook 配置代码
- 清理环境变量和配置文件中的 webhook 相关设置
- 优化前端费用显示,使用后端精确计算的数据
- 添加 DEBUG_HTTP_TRAFFIC 调试选项支持

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
shaw
2025-09-01 11:29:16 +08:00
parent 246bdc928a
commit 5cfa3cc72f
16 changed files with 476 additions and 151 deletions

View File

@@ -15,6 +15,7 @@ const {
} = require('../utils/tokenRefreshLogger')
const tokenRefreshService = require('./tokenRefreshService')
const LRUCache = require('../utils/lruCache')
const { formatDateWithTimezone, getISOStringWithTimezone } = require('../utils/dateHelper')
class ClaudeAccountService {
constructor() {
@@ -1121,8 +1122,8 @@ class ClaudeAccountService {
platform: 'claude-oauth',
status: 'error',
errorCode: 'CLAUDE_OAUTH_RATE_LIMITED',
reason: `Account rate limited (429 error). ${rateLimitResetTimestamp ? `Reset at: ${new Date(rateLimitResetTimestamp * 1000).toISOString()}` : 'Estimated reset in 1-5 hours'}`,
timestamp: new Date().toISOString()
reason: `Account rate limited (429 error). ${rateLimitResetTimestamp ? `Reset at: ${formatDateWithTimezone(rateLimitResetTimestamp)}` : 'Estimated reset in 1-5 hours'}`,
timestamp: getISOStringWithTimezone(new Date())
})
} catch (webhookError) {
logger.error('Failed to send rate limit webhook notification:', webhookError)
@@ -1322,7 +1323,7 @@ class ClaudeAccountService {
status: 'resumed',
errorCode: 'CLAUDE_5H_LIMIT_RESUMED',
reason: '进入新的5小时窗口已自动恢复调度',
timestamp: new Date().toISOString()
timestamp: getISOStringWithTimezone(new Date())
})
} catch (webhookError) {
logger.error('Failed to send webhook notification:', webhookError)
@@ -1985,7 +1986,7 @@ class ClaudeAccountService {
status: 'warning',
errorCode: 'CLAUDE_5H_LIMIT_WARNING',
reason: '5小时使用量接近限制已自动停止调度',
timestamp: new Date().toISOString()
timestamp: getISOStringWithTimezone(new Date())
})
} catch (webhookError) {
logger.error('Failed to send webhook notification:', webhookError)