From 739d0ee61e9ed8c381a8f282760ad10e9ae6135b Mon Sep 17 00:00:00 2001 From: shaw Date: Fri, 26 Dec 2025 21:22:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20admin=20handlers=20=E6=B7=BB=E5=8A=A0=20?= =?UTF-8?q?DTO=20=E8=BD=AC=E6=8D=A2=E4=BF=AE=E5=A4=8D=20JSON=20=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 PR #36 合并后部分 admin handler 直接返回 service 层对象导致 JSON 字段名为 PascalCase 而非期望的 snake_case 问题。 修复内容: - account_handler: Refresh 接口添加 dto.AccountFromService - openai_oauth_handler: RefreshAccountToken/CreateAccountFromOAuth 添加 dto 转换 - subscription_handler: BulkAssign 添加 dto.BulkAssignResultFromService - usage_handler: List 接口添加 dto.UsageLogFromService 转换 - 新增 dto.BulkAssignResult 类型和对应的 mapper 函数 --- .../internal/handler/admin/account_handler.go | 2 +- .../handler/admin/openai_oauth_handler.go | 5 +-- .../internal/handler/admin/proxy_handler.go | 31 ++++++++++++++----- .../internal/handler/admin/redeem_handler.go | 17 +++++++--- .../handler/admin/subscription_handler.go | 2 +- .../internal/handler/admin/usage_handler.go | 7 ++++- .../internal/handler/admin/user_handler.go | 21 +++++++++---- backend/internal/handler/dto/mappers.go | 16 ++++++++++ backend/internal/handler/dto/types.go | 7 +++++ 9 files changed, 86 insertions(+), 22 deletions(-) diff --git a/backend/internal/handler/admin/account_handler.go b/backend/internal/handler/admin/account_handler.go index 0522bc3c..af7f8eff 100644 --- a/backend/internal/handler/admin/account_handler.go +++ b/backend/internal/handler/admin/account_handler.go @@ -376,7 +376,7 @@ func (h *AccountHandler) Refresh(c *gin.Context) { return } - response.Success(c, updatedAccount) + response.Success(c, dto.AccountFromService(updatedAccount)) } // GetStats handles getting account statistics diff --git a/backend/internal/handler/admin/openai_oauth_handler.go b/backend/internal/handler/admin/openai_oauth_handler.go index 60285fe3..ed86fea9 100644 --- a/backend/internal/handler/admin/openai_oauth_handler.go +++ b/backend/internal/handler/admin/openai_oauth_handler.go @@ -3,6 +3,7 @@ package admin import ( "strconv" + "github.com/Wei-Shaw/sub2api/internal/handler/dto" "github.com/Wei-Shaw/sub2api/internal/pkg/response" "github.com/Wei-Shaw/sub2api/internal/service" @@ -163,7 +164,7 @@ func (h *OpenAIOAuthHandler) RefreshAccountToken(c *gin.Context) { return } - response.Success(c, updatedAccount) + response.Success(c, dto.AccountFromService(updatedAccount)) } // CreateAccountFromOAuth creates a new OpenAI OAuth account from token info @@ -224,5 +225,5 @@ func (h *OpenAIOAuthHandler) CreateAccountFromOAuth(c *gin.Context) { return } - response.Success(c, account) + response.Success(c, dto.AccountFromService(account)) } diff --git a/backend/internal/handler/admin/proxy_handler.go b/backend/internal/handler/admin/proxy_handler.go index 99937fb9..0480b312 100644 --- a/backend/internal/handler/admin/proxy_handler.go +++ b/backend/internal/handler/admin/proxy_handler.go @@ -4,6 +4,7 @@ import ( "strconv" "strings" + "github.com/Wei-Shaw/sub2api/internal/handler/dto" "github.com/Wei-Shaw/sub2api/internal/pkg/response" "github.com/Wei-Shaw/sub2api/internal/service" @@ -57,7 +58,11 @@ func (h *ProxyHandler) List(c *gin.Context) { return } - response.Paginated(c, proxies, total, page, pageSize) + out := make([]dto.Proxy, 0, len(proxies)) + for i := range proxies { + out = append(out, *dto.ProxyFromService(&proxies[i])) + } + response.Paginated(c, out, total, page, pageSize) } // GetAll handles getting all active proxies without pagination @@ -72,7 +77,11 @@ func (h *ProxyHandler) GetAll(c *gin.Context) { response.ErrorFrom(c, err) return } - response.Success(c, proxies) + out := make([]dto.ProxyWithAccountCount, 0, len(proxies)) + for i := range proxies { + out = append(out, *dto.ProxyWithAccountCountFromService(&proxies[i])) + } + response.Success(c, out) return } @@ -82,7 +91,11 @@ func (h *ProxyHandler) GetAll(c *gin.Context) { return } - response.Success(c, proxies) + out := make([]dto.Proxy, 0, len(proxies)) + for i := range proxies { + out = append(out, *dto.ProxyFromService(&proxies[i])) + } + response.Success(c, out) } // GetByID handles getting a proxy by ID @@ -100,7 +113,7 @@ func (h *ProxyHandler) GetByID(c *gin.Context) { return } - response.Success(c, proxy) + response.Success(c, dto.ProxyFromService(proxy)) } // Create handles creating a new proxy @@ -125,7 +138,7 @@ func (h *ProxyHandler) Create(c *gin.Context) { return } - response.Success(c, proxy) + response.Success(c, dto.ProxyFromService(proxy)) } // Update handles updating a proxy @@ -157,7 +170,7 @@ func (h *ProxyHandler) Update(c *gin.Context) { return } - response.Success(c, proxy) + response.Success(c, dto.ProxyFromService(proxy)) } // Delete handles deleting a proxy @@ -233,7 +246,11 @@ func (h *ProxyHandler) GetProxyAccounts(c *gin.Context) { return } - response.Paginated(c, accounts, total, page, pageSize) + out := make([]dto.Account, 0, len(accounts)) + for i := range accounts { + out = append(out, *dto.AccountFromService(&accounts[i])) + } + response.Paginated(c, out, total, page, pageSize) } // BatchCreateProxyItem represents a single proxy in batch create request diff --git a/backend/internal/handler/admin/redeem_handler.go b/backend/internal/handler/admin/redeem_handler.go index 98a4c242..4e8e48e6 100644 --- a/backend/internal/handler/admin/redeem_handler.go +++ b/backend/internal/handler/admin/redeem_handler.go @@ -6,6 +6,7 @@ import ( "fmt" "strconv" + "github.com/Wei-Shaw/sub2api/internal/handler/dto" "github.com/Wei-Shaw/sub2api/internal/pkg/response" "github.com/Wei-Shaw/sub2api/internal/service" @@ -47,7 +48,11 @@ func (h *RedeemHandler) List(c *gin.Context) { return } - response.Paginated(c, codes, total, page, pageSize) + out := make([]dto.RedeemCode, 0, len(codes)) + for i := range codes { + out = append(out, *dto.RedeemCodeFromService(&codes[i])) + } + response.Paginated(c, out, total, page, pageSize) } // GetByID handles getting a redeem code by ID @@ -65,7 +70,7 @@ func (h *RedeemHandler) GetByID(c *gin.Context) { return } - response.Success(c, code) + response.Success(c, dto.RedeemCodeFromService(code)) } // Generate handles generating new redeem codes @@ -89,7 +94,11 @@ func (h *RedeemHandler) Generate(c *gin.Context) { return } - response.Success(c, codes) + out := make([]dto.RedeemCode, 0, len(codes)) + for i := range codes { + out = append(out, *dto.RedeemCodeFromService(&codes[i])) + } + response.Success(c, out) } // Delete handles deleting a redeem code @@ -148,7 +157,7 @@ func (h *RedeemHandler) Expire(c *gin.Context) { return } - response.Success(c, code) + response.Success(c, dto.RedeemCodeFromService(code)) } // GetStats handles getting redeem code statistics diff --git a/backend/internal/handler/admin/subscription_handler.go b/backend/internal/handler/admin/subscription_handler.go index c929b75f..ca69eb05 100644 --- a/backend/internal/handler/admin/subscription_handler.go +++ b/backend/internal/handler/admin/subscription_handler.go @@ -177,7 +177,7 @@ func (h *SubscriptionHandler) BulkAssign(c *gin.Context) { return } - response.Success(c, result) + response.Success(c, dto.BulkAssignResultFromService(result)) } // Extend handles extending a subscription diff --git a/backend/internal/handler/admin/usage_handler.go b/backend/internal/handler/admin/usage_handler.go index 6c230c56..fc9a944c 100644 --- a/backend/internal/handler/admin/usage_handler.go +++ b/backend/internal/handler/admin/usage_handler.go @@ -4,6 +4,7 @@ import ( "strconv" "time" + "github.com/Wei-Shaw/sub2api/internal/handler/dto" "github.com/Wei-Shaw/sub2api/internal/pkg/pagination" "github.com/Wei-Shaw/sub2api/internal/pkg/response" "github.com/Wei-Shaw/sub2api/internal/pkg/timezone" @@ -94,7 +95,11 @@ func (h *UsageHandler) List(c *gin.Context) { return } - response.Paginated(c, records, result.Total, page, pageSize) + out := make([]dto.UsageLog, 0, len(records)) + for i := range records { + out = append(out, *dto.UsageLogFromService(&records[i])) + } + response.Paginated(c, out, result.Total, page, pageSize) } // Stats handles getting usage statistics with filters diff --git a/backend/internal/handler/admin/user_handler.go b/backend/internal/handler/admin/user_handler.go index b8842ae0..681b59ea 100644 --- a/backend/internal/handler/admin/user_handler.go +++ b/backend/internal/handler/admin/user_handler.go @@ -3,6 +3,7 @@ package admin import ( "strconv" + "github.com/Wei-Shaw/sub2api/internal/handler/dto" "github.com/Wei-Shaw/sub2api/internal/pkg/response" "github.com/Wei-Shaw/sub2api/internal/service" @@ -68,7 +69,11 @@ func (h *UserHandler) List(c *gin.Context) { return } - response.Paginated(c, users, total, page, pageSize) + out := make([]dto.User, 0, len(users)) + for i := range users { + out = append(out, *dto.UserFromService(&users[i])) + } + response.Paginated(c, out, total, page, pageSize) } // GetByID handles getting a user by ID @@ -86,7 +91,7 @@ func (h *UserHandler) GetByID(c *gin.Context) { return } - response.Success(c, user) + response.Success(c, dto.UserFromService(user)) } // Create handles creating a new user @@ -113,7 +118,7 @@ func (h *UserHandler) Create(c *gin.Context) { return } - response.Success(c, user) + response.Success(c, dto.UserFromService(user)) } // Update handles updating a user @@ -148,7 +153,7 @@ func (h *UserHandler) Update(c *gin.Context) { return } - response.Success(c, user) + response.Success(c, dto.UserFromService(user)) } // Delete handles deleting a user @@ -190,7 +195,7 @@ func (h *UserHandler) UpdateBalance(c *gin.Context) { return } - response.Success(c, user) + response.Success(c, dto.UserFromService(user)) } // GetUserAPIKeys handles getting user's API keys @@ -210,7 +215,11 @@ func (h *UserHandler) GetUserAPIKeys(c *gin.Context) { return } - response.Paginated(c, keys, total, page, pageSize) + out := make([]dto.ApiKey, 0, len(keys)) + for i := range keys { + out = append(out, *dto.ApiKeyFromService(&keys[i])) + } + response.Paginated(c, out, total, page, pageSize) } // GetUserUsage handles getting user's usage statistics diff --git a/backend/internal/handler/dto/mappers.go b/backend/internal/handler/dto/mappers.go index 7cdfa203..a3d71c6b 100644 --- a/backend/internal/handler/dto/mappers.go +++ b/backend/internal/handler/dto/mappers.go @@ -292,3 +292,19 @@ func UserSubscriptionFromService(sub *service.UserSubscription) *UserSubscriptio AssignedByUser: UserFromServiceShallow(sub.AssignedByUser), } } + +func BulkAssignResultFromService(r *service.BulkAssignResult) *BulkAssignResult { + if r == nil { + return nil + } + subs := make([]UserSubscription, 0, len(r.Subscriptions)) + for i := range r.Subscriptions { + subs = append(subs, *UserSubscriptionFromService(&r.Subscriptions[i])) + } + return &BulkAssignResult{ + SuccessCount: r.SuccessCount, + FailedCount: r.FailedCount, + Subscriptions: subs, + Errors: r.Errors, + } +} diff --git a/backend/internal/handler/dto/types.go b/backend/internal/handler/dto/types.go index 2b59e38d..24d78e98 100644 --- a/backend/internal/handler/dto/types.go +++ b/backend/internal/handler/dto/types.go @@ -210,3 +210,10 @@ type UserSubscription struct { Group *Group `json:"group,omitempty"` AssignedByUser *User `json:"assigned_by_user,omitempty"` } + +type BulkAssignResult struct { + SuccessCount int `json:"success_count"` + FailedCount int `json:"failed_count"` + Subscriptions []UserSubscription `json:"subscriptions"` + Errors []string `json:"errors"` +}