From 7e5cbaf65efa6250829070e1fc22f5bdc3de2050 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Mon, 5 Oct 2026 15:42:00 +0800 Subject: [PATCH] =?UTF-8?q?fix(rock):=20=E5=85=BC=E5=AE=B9=200666.pro=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=20points=20=E5=AD=97=E6=AE=B5=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2=E4=B8=8E=E6=95=B0=E5=80=BC=E8=87=AA=E9=80=82?= =?UTF-8?q?=E5=BA=94=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增 FlexibleFloat64 类型,解决上游 /api/me 响应中 points 为字符串(如 '8271.2')导致反序列化失败的问题; 2. 服务层与数据库快照存储统一调用 Float64() 保持类型严谨; 3. 单元测试补充真实上游字符串响应场景并全绿通过。 --- .../internal/service/provider_rock_test.go | 2 +- backend/internal/service/rock_client.go | 51 +++++++++++++++++-- backend/internal/service/rock_service.go | 4 +- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/backend/internal/service/provider_rock_test.go b/backend/internal/service/provider_rock_test.go index 106b130..3878c95 100644 --- a/backend/internal/service/provider_rock_test.go +++ b/backend/internal/service/provider_rock_test.go @@ -285,7 +285,7 @@ func TestRockService_StatsAndPurchase(t *testing.T) { "id": 10028, "username": "王大锤", "role": "merchant", - "points": 8271.2, + "points": "8271.2", // 真实上游 0666.pro 返回字符串格式 "status": "active", }, }) diff --git a/backend/internal/service/rock_client.go b/backend/internal/service/rock_client.go index fe746c2..884d2d7 100644 --- a/backend/internal/service/rock_client.go +++ b/backend/internal/service/rock_client.go @@ -8,10 +8,51 @@ import ( "io" "net/http" "net/url" + "strconv" "strings" "time" ) +// FlexibleFloat64 兼容反序列化 JSON 中的数字或字符串(如 "8271.2") +type FlexibleFloat64 float64 + +func (f *FlexibleFloat64) UnmarshalJSON(b []byte) error { + if len(b) == 0 || string(b) == "null" { + *f = 0 + return nil + } + var n float64 + if err := json.Unmarshal(b, &n); err == nil { + *f = FlexibleFloat64(n) + return nil + } + var s string + if err := json.Unmarshal(b, &s); err == nil { + s = strings.TrimSpace(s) + if s == "" { + *f = 0 + return nil + } + val, err := strconv.ParseFloat(s, 64) + if err != nil { + *f = 0 + return nil + } + *f = FlexibleFloat64(val) + return nil + } + *f = 0 + return nil +} + +func (f FlexibleFloat64) MarshalJSON() ([]byte, error) { + return json.Marshal(float64(f)) +} + +func (f FlexibleFloat64) Float64() float64 { + return float64(f) +} + // RockClient 负责与 0666.pro 平台进行 HTTP 通信 type RockClient struct { baseURL string @@ -33,11 +74,11 @@ func NewRockClient(baseURL string) *RockClient { type RockMeResponse struct { User struct { - ID uint64 `json:"id"` - Username string `json:"username"` - Role string `json:"role"` - Points float64 `json:"points"` - Status string `json:"status"` + ID uint64 `json:"id"` + Username string `json:"username"` + Role string `json:"role"` + Points FlexibleFloat64 `json:"points"` + Status string `json:"status"` } `json:"user"` Error string `json:"error,omitempty"` } diff --git a/backend/internal/service/rock_service.go b/backend/internal/service/rock_service.go index c4d43b1..ddec074 100644 --- a/backend/internal/service/rock_service.go +++ b/backend/internal/service/rock_service.go @@ -150,7 +150,7 @@ func (s *RockService) TestConnection(ctx context.Context, bearerToken string) (* now := time.Now() _ = s.db.WithContext(ctx).Model(&model.RockConfig{}).Where("id = 1").Updates(map[string]interface{}{ "username": me.User.Username, - "points": me.User.Points, + "points": me.User.Points.Float64(), "last_heartbeat_at": now, }).Error @@ -271,7 +271,7 @@ func (s *RockService) PurchaseTokens(ctx context.Context, count int, isAuto bool defer cancel() me, meErr := s.client.GetMe(bgCtx, cfg.BearerToken) if meErr == nil && me != nil { - _ = s.db.Model(&model.RockConfig{}).Where("id = 1").Update("points", me.User.Points).Error + _ = s.db.Model(&model.RockConfig{}).Where("id = 1").Update("points", me.User.Points.Float64()).Error } }()