From cd9d31f5f2b3c462d7ebdea443a85f3d816fd3b9 Mon Sep 17 00:00:00 2001 From: shaw Date: Sun, 28 Dec 2025 11:22:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DNeedsRefresh=20bug?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E5=88=B7=E6=96=B0=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + backend/internal/service/account.go | 4 ++++ .../internal/service/token_refresh_service.go | 15 +++++++++++---- backend/internal/service/token_refresher.go | 18 ++++++------------ frontend/vite.config.d.ts | 2 -- 5 files changed, 22 insertions(+), 18 deletions(-) delete mode 100644 frontend/vite.config.d.ts diff --git a/.gitignore b/.gitignore index 5e9296f9..3a41cb76 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ frontend/node_modules/ frontend/dist/ *.local *.tsbuildinfo +vite.config.d.ts # 日志 npm-debug.log* diff --git a/backend/internal/service/account.go b/backend/internal/service/account.go index f740cb90..5bcd98f5 100644 --- a/backend/internal/service/account.go +++ b/backend/internal/service/account.go @@ -1,6 +1,7 @@ package service import ( + "encoding/json" "strconv" "time" ) @@ -94,6 +95,9 @@ func (a *Account) GetCredential(key string) string { switch val := v.(type) { case string: return val + case json.Number: + // GORM datatypes.JSONMap 使用 UseNumber() 解析,数字类型为 json.Number + return val.String() case float64: // JSON 解析后数字默认为 float64 return strconv.FormatInt(int64(val), 10) diff --git a/backend/internal/service/token_refresh_service.go b/backend/internal/service/token_refresh_service.go index 5420dd3e..23126bfb 100644 --- a/backend/internal/service/token_refresh_service.go +++ b/backend/internal/service/token_refresh_service.go @@ -106,6 +106,9 @@ func (s *TokenRefreshService) processRefresh() { return } + totalAccounts := len(accounts) + oauthAccounts := 0 // 可刷新的OAuth账号数 + needsRefresh := 0 // 需要刷新的账号数 refreshed, failed := 0, 0 for i := range accounts { @@ -117,11 +120,15 @@ func (s *TokenRefreshService) processRefresh() { continue } + oauthAccounts++ + // 检查是否需要刷新 if !refresher.NeedsRefresh(account, refreshWindow) { - continue + break // 不需要刷新,跳过 } + needsRefresh++ + // 执行刷新 if err := s.refreshWithRetry(ctx, account, refresher); err != nil { log.Printf("[TokenRefresh] Account %d (%s) failed: %v", account.ID, account.Name, err) @@ -136,9 +143,9 @@ func (s *TokenRefreshService) processRefresh() { } } - if refreshed > 0 || failed > 0 { - log.Printf("[TokenRefresh] Cycle complete: %d refreshed, %d failed", refreshed, failed) - } + // 始终打印周期日志,便于跟踪服务运行状态 + log.Printf("[TokenRefresh] Cycle complete: total=%d, oauth=%d, needs_refresh=%d, refreshed=%d, failed=%d", + totalAccounts, oauthAccounts, needsRefresh, refreshed, failed) } // listActiveAccounts 获取所有active状态的账号 diff --git a/backend/internal/service/token_refresher.go b/backend/internal/service/token_refresher.go index a43a525e..2ae3c822 100644 --- a/backend/internal/service/token_refresher.go +++ b/backend/internal/service/token_refresher.go @@ -43,19 +43,13 @@ func (r *ClaudeTokenRefresher) CanRefresh(account *Account) bool { // NeedsRefresh 检查token是否需要刷新 // 基于 expires_at 字段判断是否在刷新窗口内 func (r *ClaudeTokenRefresher) NeedsRefresh(account *Account, refreshWindow time.Duration) bool { - var expiresAt int64 + s := account.GetCredential("expires_at") + if s == "" { + return false + } - // 方式1: 通过 GetCredential 获取(处理字符串和部分数字类型) - if s := account.GetCredential("expires_at"); s != "" { - v, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return false - } - expiresAt = v - } else if v, ok := account.Credentials["expires_at"].(float64); ok { - // 方式2: 直接获取 float64(处理某些 JSON 解码器将数字解析为 float64 的情况) - expiresAt = int64(v) - } else { + expiresAt, err := strconv.ParseInt(s, 10, 64) + if err != nil { return false } diff --git a/frontend/vite.config.d.ts b/frontend/vite.config.d.ts deleted file mode 100644 index 135c1dc0..00000000 --- a/frontend/vite.config.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare const _default: import('vite').UserConfig -export default _default