package handler import ( "fmt" "net/http" "gpt-plus/internal/db" "gpt-plus/internal/service" "github.com/gin-gonic/gin" ) func RegisterAccountRoutes(api *gin.RouterGroup) { api.GET("/accounts", ListAccounts) api.GET("/accounts/:id", GetAccount) api.POST("/accounts/check", CheckAccounts) api.POST("/accounts/:id/check", CheckSingleAccount) api.POST("/accounts/test-model", TestModel) api.PUT("/accounts/:id/note", UpdateAccountNote) api.POST("/accounts/export", ExportAccounts) api.POST("/accounts/:id/transfer-to-cpa", TransferToCPA) } func ListAccounts(c *gin.Context) { d := db.GetDB() query := d.Model(&db.Account{}).Order("created_at DESC") plan := c.Query("plan") if plan != "" && plan != "all" { query = query.Where("plan = ?", plan) } // "all" or empty: show everything if status := c.Query("status"); status != "" { query = query.Where("status = ?", status) } if search := c.Query("search"); search != "" { query = query.Where("email LIKE ?", "%"+search+"%") } p := db.PaginationParams{Page: intQuery(c, "page", 1), Size: intQuery(c, "size", 20)} var accounts []db.Account result, err := db.Paginate(query, p, &accounts) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } for i := range accounts { if accounts[i].Plan == "team_owner" { d.Where("parent_id = ?", accounts[i].ID).Find(&accounts[i].SubAccounts) } if accounts[i].Plan == "team_member" && accounts[i].ParentID != nil { var parent db.Account if d.First(&parent, *accounts[i].ParentID).Error == nil { accounts[i].Parent = &parent } } } result.Items = accounts c.JSON(http.StatusOK, result) } func GetAccount(c *gin.Context) { var account db.Account d := db.GetDB() if err := d.First(&account, c.Param("id")).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "账号不存在"}) return } if account.Plan == "team_owner" { d.Where("parent_id = ?", account.ID).Find(&account.SubAccounts) } c.JSON(http.StatusOK, account) } func CheckAccounts(c *gin.Context) { var req struct { IDs []uint `json:"ids" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } results := service.CheckAccountStatuses(db.GetDB(), req.IDs) c.JSON(http.StatusOK, gin.H{"message": "状态检查完成", "results": results}) } func CheckSingleAccount(c *gin.Context) { id := c.Param("id") var uid uint if _, err := fmt.Sscanf(id, "%d", &uid); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 ID"}) return } results := service.CheckAccountStatuses(db.GetDB(), []uint{uid}) if len(results) > 0 { c.JSON(http.StatusOK, results[0]) } else { c.JSON(http.StatusNotFound, gin.H{"error": "账号不存在"}) } } func TestModel(c *gin.Context) { var req struct { ID uint `json:"id" binding:"required"` Model string `json:"model"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } result := service.TestModelAvailability(db.GetDB(), req.ID, req.Model) c.JSON(http.StatusOK, result) } func UpdateAccountNote(c *gin.Context) { var req struct { Note string `json:"note"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := db.GetDB().Model(&db.Account{}).Where("id = ?", c.Param("id")).Update("note", req.Note).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "备注已更新"}) } func TransferToCPA(c *gin.Context) { id := c.Param("id") var uid uint if _, err := fmt.Sscanf(id, "%d", &uid); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 ID"}) return } result := service.TransferAccountToCPA(db.GetDB(), uid) if result.OK { c.JSON(http.StatusOK, result) } else { c.JSON(http.StatusInternalServerError, result) } } func ExportAccounts(c *gin.Context) { var req struct { IDs []uint `json:"ids" binding:"required"` Note string `json:"note"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } data, filename, err := service.ExportAccounts(db.GetDB(), req.IDs, req.Note) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.Header("Content-Disposition", "attachment; filename=\""+filename+"\"") if len(req.IDs) > 1 { c.Data(http.StatusOK, "application/zip", data) } else { c.Data(http.StatusOK, "application/json", data) } }