diff --git a/backend/internal/handler/admin/admin_service_stub_test.go b/backend/internal/handler/admin/admin_service_stub_test.go index b77a2b7fd8..94627b06e3 100644 --- a/backend/internal/handler/admin/admin_service_stub_test.go +++ b/backend/internal/handler/admin/admin_service_stub_test.go @@ -179,6 +179,10 @@ func (s *stubAdminService) GetGroupRateMultipliers(_ context.Context, _ int64) ( return nil, nil } +func (s *stubAdminService) ClearGroupRateMultipliers(_ context.Context, _ int64) error { + return nil +} + func (s *stubAdminService) ListAccounts(ctx context.Context, page, pageSize int, platform, accountType, status, search string, groupID int64) ([]service.Account, int64, error) { return s.accounts, int64(len(s.accounts)), nil } diff --git a/backend/internal/handler/admin/group_handler.go b/backend/internal/handler/admin/group_handler.go index 34c94f2ae2..ca70aed751 100644 --- a/backend/internal/handler/admin/group_handler.go +++ b/backend/internal/handler/admin/group_handler.go @@ -360,6 +360,23 @@ func (h *GroupHandler) GetGroupRateMultipliers(c *gin.Context) { response.Success(c, entries) } +// ClearGroupRateMultipliers handles clearing all rate multipliers for a group +// DELETE /api/v1/admin/groups/:id/rate-multipliers +func (h *GroupHandler) ClearGroupRateMultipliers(c *gin.Context) { + groupID, err := strconv.ParseInt(c.Param("id"), 10, 64) + if err != nil { + response.BadRequest(c, "Invalid group ID") + return + } + + if err := h.adminService.ClearGroupRateMultipliers(c.Request.Context(), groupID); err != nil { + response.ErrorFrom(c, err) + return + } + + response.Success(c, gin.H{"message": "Rate multipliers cleared successfully"}) +} + // UpdateSortOrderRequest represents the request to update group sort orders type UpdateSortOrderRequest struct { Updates []struct { diff --git a/backend/internal/repository/user_group_rate_repo.go b/backend/internal/repository/user_group_rate_repo.go index b57a3bb99e..b0e3ae8f90 100644 --- a/backend/internal/repository/user_group_rate_repo.go +++ b/backend/internal/repository/user_group_rate_repo.go @@ -98,7 +98,7 @@ func (r *userGroupRateRepository) GetByUserIDs(ctx context.Context, userIDs []in // GetByGroupID 获取指定分组下所有用户的专属倍率 func (r *userGroupRateRepository) GetByGroupID(ctx context.Context, groupID int64) ([]service.UserGroupRateEntry, error) { query := ` - SELECT ugr.user_id, u.email, ugr.rate_multiplier + SELECT ugr.user_id, u.username, u.email, ugr.rate_multiplier FROM user_group_rate_multipliers ugr JOIN users u ON u.id = ugr.user_id WHERE ugr.group_id = $1 @@ -113,7 +113,7 @@ func (r *userGroupRateRepository) GetByGroupID(ctx context.Context, groupID int6 var result []service.UserGroupRateEntry for rows.Next() { var entry service.UserGroupRateEntry - if err := rows.Scan(&entry.UserID, &entry.UserEmail, &entry.RateMultiplier); err != nil { + if err := rows.Scan(&entry.UserID, &entry.UserName, &entry.UserEmail, &entry.RateMultiplier); err != nil { return nil, err } result = append(result, entry) diff --git a/backend/internal/server/routes/admin.go b/backend/internal/server/routes/admin.go index dc5e82691b..7e6ea4ec2b 100644 --- a/backend/internal/server/routes/admin.go +++ b/backend/internal/server/routes/admin.go @@ -229,6 +229,7 @@ func registerGroupRoutes(admin *gin.RouterGroup, h *handler.Handlers) { groups.DELETE("/:id", h.Admin.Group.Delete) groups.GET("/:id/stats", h.Admin.Group.GetStats) groups.GET("/:id/rate-multipliers", h.Admin.Group.GetGroupRateMultipliers) + groups.DELETE("/:id/rate-multipliers", h.Admin.Group.ClearGroupRateMultipliers) groups.GET("/:id/api-keys", h.Admin.Group.GetGroupAPIKeys) } } diff --git a/backend/internal/service/admin_service.go b/backend/internal/service/admin_service.go index f2e7bd9b17..fc9f4836db 100644 --- a/backend/internal/service/admin_service.go +++ b/backend/internal/service/admin_service.go @@ -43,6 +43,7 @@ type AdminService interface { DeleteGroup(ctx context.Context, id int64) error GetGroupAPIKeys(ctx context.Context, groupID int64, page, pageSize int) ([]APIKey, int64, error) GetGroupRateMultipliers(ctx context.Context, groupID int64) ([]UserGroupRateEntry, error) + ClearGroupRateMultipliers(ctx context.Context, groupID int64) error UpdateGroupSortOrders(ctx context.Context, updates []GroupSortOrderUpdate) error // API Key management (admin) @@ -1271,6 +1272,13 @@ func (s *adminServiceImpl) GetGroupRateMultipliers(ctx context.Context, groupID return s.userGroupRateRepo.GetByGroupID(ctx, groupID) } +func (s *adminServiceImpl) ClearGroupRateMultipliers(ctx context.Context, groupID int64) error { + if s.userGroupRateRepo == nil { + return nil + } + return s.userGroupRateRepo.DeleteByGroupID(ctx, groupID) +} + func (s *adminServiceImpl) UpdateGroupSortOrders(ctx context.Context, updates []GroupSortOrderUpdate) error { return s.groupRepo.UpdateSortOrders(ctx, updates) } diff --git a/backend/internal/service/user_group_rate.go b/backend/internal/service/user_group_rate.go index 9908546ebe..9d401ec870 100644 --- a/backend/internal/service/user_group_rate.go +++ b/backend/internal/service/user_group_rate.go @@ -5,6 +5,7 @@ import "context" // UserGroupRateEntry 分组下用户专属倍率条目 type UserGroupRateEntry struct { UserID int64 `json:"user_id"` + UserName string `json:"user_name"` UserEmail string `json:"user_email"` RateMultiplier float64 `json:"rate_multiplier"` } diff --git a/frontend/src/api/admin/groups.ts b/frontend/src/api/admin/groups.ts index 81bf4e55b5..ff3c0c5011 100644 --- a/frontend/src/api/admin/groups.ts +++ b/frontend/src/api/admin/groups.ts @@ -158,6 +158,7 @@ export async function getGroupApiKeys( */ export interface GroupRateMultiplierEntry { user_id: number + user_name: string user_email: string rate_multiplier: number } @@ -188,6 +189,16 @@ export async function updateSortOrder( return data } +/** + * Clear all rate multipliers for a group + * @param id - Group ID + * @returns Success confirmation + */ +export async function clearGroupRateMultipliers(id: number): Promise<{ message: string }> { + const { data } = await apiClient.delete<{ message: string }>(`/admin/groups/${id}/rate-multipliers`) + return data +} + export const groupsAPI = { list, getAll, @@ -200,6 +211,7 @@ export const groupsAPI = { getStats, getGroupApiKeys, getGroupRateMultipliers, + clearGroupRateMultipliers, updateSortOrder } diff --git a/frontend/src/components/admin/group/GroupRateMultipliersModal.vue b/frontend/src/components/admin/group/GroupRateMultipliersModal.vue index 11e551d0ef..8ece0f3085 100644 --- a/frontend/src/components/admin/group/GroupRateMultipliersModal.vue +++ b/frontend/src/components/admin/group/GroupRateMultipliersModal.vue @@ -1,8 +1,8 @@