Files
verify/backend/internal/router/developer/agents.go
T

586 lines
16 KiB
Go

package developer
import (
"fmt"
"verification-platform-backend/internal/database"
"verification-platform-backend/internal/model"
"verification-platform-backend/internal/service"
"verification-platform-backend/pkg/response"
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
)
func SetupAgentsRoutes(r *gin.RouterGroup) {
agents := r.Group("/agents")
{
agents.GET("", handleGetAgents)
agents.GET("/tree", handleGetAgentsTree)
agents.POST("", handleCreateAgent)
agents.GET("/:id", handleGetAgentDetail)
agents.PUT("/:id", handleUpdateAgent)
agents.PUT("/:id/status", handleUpdateAgentStatus)
agents.DELETE("/:id", handleDeleteAgent)
agents.GET("/:id/cards", handleGetAgentCards)
agents.PUT("/:id/cards", handleUpdateAgentCards)
}
}
type AgentTreeNode struct {
ID uint `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Avatar string `json:"avatar"`
Status string `json:"status"`
Role string `json:"role"`
ParentAgentID *uint `json:"parent_agent_id"`
ParentAgentName string `json:"parent_agent_name"`
CreatedAt string `json:"created_at"`
LastLoginAt string `json:"last_login_at"`
Balance float64 `json:"balance"`
Commission float64 `json:"commission"`
CanCreateAgent bool `json:"can_create_agent"`
CardsCount int `json:"cards_count"`
ChildAgentsCount int `json:"child_agents_count"`
Children []AgentTreeNode `json:"children,omitempty"`
}
func handleGetAgents(c *gin.Context) {
var users []model.User
if err := database.DB.Where("role = ?", "agent").
Preload("ParentAgent").
Order("created_at DESC").
Find(&users).Error; err != nil {
response.Error(c, 500, "获取代理列表失败")
return
}
type AgentResponse struct {
ID uint `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Avatar string `json:"avatar"`
Status string `json:"status"`
Role string `json:"role"`
ParentAgentID *uint `json:"parent_agent_id"`
ParentAgentName string `json:"parent_agent_name"`
CreatedAt string `json:"created_at"`
LastLoginAt string `json:"last_login_at"`
Balance float64 `json:"balance"`
Commission float64 `json:"commission"`
CanCreateAgent bool `json:"can_create_agent"`
CardsCount int `json:"cards_count"`
ChildAgentsCount int `json:"child_agents_count"`
}
var result []AgentResponse
for _, user := range users {
var parentAgentName string
if user.ParentAgent != nil {
parentAgentName = user.ParentAgent.Username
}
var childAgentsCount int64
database.DB.Model(&model.User{}).Where("parent_agent_id = ?", user.ID).Count(&childAgentsCount)
var cardsCount int64
database.DB.Model(&model.Card{}).Where("creator_id = ?", user.ID).Count(&cardsCount)
var lastLoginAt string
if user.LastLoginAt != nil {
lastLoginAt = user.LastLoginAt.Format("2006-01-02 15:04:05")
}
email := ""
if user.Email != nil {
email = *user.Email
}
result = append(result, AgentResponse{
ID: user.ID,
Username: user.Username,
Email: email,
Avatar: user.Avatar,
Status: user.Status,
Role: user.Role,
ParentAgentID: user.ParentAgentID,
ParentAgentName: parentAgentName,
CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
LastLoginAt: lastLoginAt,
Balance: user.Balance,
Commission: user.Commission,
CanCreateAgent: user.CanCreateAgent,
CardsCount: int(cardsCount),
ChildAgentsCount: int(childAgentsCount),
})
}
response.Success(c, gin.H{
"agents": result,
"total": len(result),
})
}
func handleGetAgentsTree(c *gin.Context) {
var users []model.User
if err := database.DB.Where("role = ?", "agent").
Preload("ParentAgent").
Order("created_at DESC").
Find(&users).Error; err != nil {
response.Error(c, 500, "获取代理列表失败")
return
}
userMap := make(map[uint]model.User)
for _, user := range users {
userMap[user.ID] = user
}
childrenMap := make(map[uint][]uint)
var rootUsers []uint
for _, user := range users {
if user.ParentAgentID != nil {
childrenMap[*user.ParentAgentID] = append(childrenMap[*user.ParentAgentID], user.ID)
} else {
rootUsers = append(rootUsers, user.ID)
}
}
var buildTree func(userID uint) AgentTreeNode
buildTree = func(userID uint) AgentTreeNode {
user := userMap[userID]
var parentAgentName string
if user.ParentAgent != nil {
parentAgentName = user.ParentAgent.Username
}
var cardsCount int64
database.DB.Model(&model.Card{}).Where("creator_id = ?", user.ID).Count(&cardsCount)
var childAgentsCount int64
database.DB.Model(&model.User{}).Where("parent_agent_id = ?", user.ID).Count(&childAgentsCount)
var lastLoginAt string
if user.LastLoginAt != nil {
lastLoginAt = user.LastLoginAt.Format("2006-01-02 15:04:05")
}
email := ""
if user.Email != nil {
email = *user.Email
}
node := AgentTreeNode{
ID: user.ID,
Username: user.Username,
Email: email,
Avatar: user.Avatar,
Status: user.Status,
Role: user.Role,
ParentAgentID: user.ParentAgentID,
ParentAgentName: parentAgentName,
CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
LastLoginAt: lastLoginAt,
Balance: user.Balance,
Commission: user.Commission,
CanCreateAgent: user.CanCreateAgent,
CardsCount: int(cardsCount),
ChildAgentsCount: int(childAgentsCount),
}
if childIDs, exists := childrenMap[userID]; exists {
for _, childID := range childIDs {
node.Children = append(node.Children, buildTree(childID))
}
}
return node
}
var tree []AgentTreeNode
for _, rootID := range rootUsers {
tree = append(tree, buildTree(rootID))
}
response.Success(c, gin.H{
"tree": tree,
"total": len(users),
})
}
func handleCreateAgent(c *gin.Context) {
var req struct {
Username string `json:"username" binding:"required"`
Email string `json:"email"`
Password string `json:"password" binding:"required"`
ParentAgentID *uint `json:"parent_agent_id"`
Commission float64 `json:"commission"`
CanCreateAgent bool `json:"can_create_agent"`
Balance float64 `json:"balance"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
var existingUser model.User
if err := database.DB.Where("username = ?", req.Username).First(&existingUser).Error; err == nil {
response.Error(c, 400, "用户名已存在")
return
}
if req.Email != "" {
if err := database.DB.Where("email = ?", req.Email).First(&existingUser).Error; err == nil {
response.Error(c, 400, "邮箱已被使用")
return
}
}
if req.ParentAgentID != nil {
var parentAgent model.User
if err := database.DB.Where("id = ? AND role = ?", *req.ParentAgentID, "agent").First(&parentAgent).Error; err != nil {
response.Error(c, 404, "上级代理不存在")
return
}
}
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
response.Error(c, 500, "密码加密失败")
return
}
user := model.User{
Username: req.Username,
Password: string(hashedPassword),
Role: "agent",
Status: "active",
ParentAgentID: req.ParentAgentID,
Commission: req.Commission,
CanCreateAgent: req.CanCreateAgent,
Balance: req.Balance,
}
if req.Email != "" {
user.Email = &req.Email
}
if err := database.DB.Create(&user).Error; err != nil {
response.Error(c, 500, "创建代理失败")
return
}
service.LogOperation(c, "create", "agent", &user.ID, fmt.Sprintf("创建代理: %s", user.Username), nil)
response.Success(c, gin.H{
"id": user.ID,
"username": user.Username,
})
}
func handleGetAgentDetail(c *gin.Context) {
agentID := c.Param("id")
var user model.User
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").
Preload("ParentAgent").
First(&user).Error; err != nil {
response.Error(c, 404, "代理不存在")
return
}
var agentApps []model.AgentApplication
database.DB.Where("agent_id = ?", user.ID).
Preload("Application").
Find(&agentApps)
var childAgents []model.User
database.DB.Where("parent_agent_id = ?", user.ID).Find(&childAgents)
var cards []model.Card
database.DB.Where("creator_id = ?", user.ID).
Preload("Application").
Preload("CardType").
Find(&cards)
type CardResponse struct {
ID uint `json:"id"`
CardKey string `json:"card_key"`
ApplicationID uint `json:"application_id"`
AppName string `json:"app_name"`
CardTypeID uint `json:"card_type_id"`
CardTypeName string `json:"card_type_name"`
Price float64 `json:"price"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
}
var cardsResponse []CardResponse
for _, card := range cards {
appName := ""
if card.Application != nil {
appName = card.Application.Name
}
cardTypeName := ""
if card.CardType.ID != 0 {
cardTypeName = card.CardType.Name
}
cardsResponse = append(cardsResponse, CardResponse{
ID: card.ID,
CardKey: card.CardKey,
ApplicationID: card.ApplicationID,
AppName: appName,
CardTypeID: card.CardTypeID,
CardTypeName: cardTypeName,
Price: card.CardType.Price,
Status: card.Status,
CreatedAt: card.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
var lastLoginAt string
if user.LastLoginAt != nil {
lastLoginAt = user.LastLoginAt.Format("2006-01-02 15:04:05")
}
email := ""
if user.Email != nil {
email = *user.Email
}
var parentAgentName string
if user.ParentAgent != nil {
parentAgentName = user.ParentAgent.Username
}
response.Success(c, gin.H{
"id": user.ID,
"username": user.Username,
"email": email,
"avatar": user.Avatar,
"status": user.Status,
"role": user.Role,
"parent_agent_id": user.ParentAgentID,
"parent_agent_name": parentAgentName,
"commission": user.Commission,
"can_create_agent": user.CanCreateAgent,
"balance": user.Balance,
"created_at": user.CreatedAt.Format("2006-01-02 15:04:05"),
"last_login_at": lastLoginAt,
"cards": cardsResponse,
"cards_count": len(cardsResponse),
"child_agents_count": len(childAgents),
})
}
func handleUpdateAgent(c *gin.Context) {
agentID := c.Param("id")
var user model.User
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
response.Error(c, 404, "代理不存在")
return
}
var req struct {
ParentAgentID *uint `json:"parent_agent_id"`
Commission *float64 `json:"commission"`
Email *string `json:"email"`
Password *string `json:"password"`
CanCreateAgent *bool `json:"can_create_agent"`
Balance *float64 `json:"balance"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
if req.ParentAgentID != nil {
if *req.ParentAgentID == user.ID {
response.Error(c, 400, "不能将自己设为上级代理")
return
}
var parentAgent model.User
if err := database.DB.Where("id = ? AND role = ?", *req.ParentAgentID, "agent").First(&parentAgent).Error; err != nil {
response.Error(c, 404, "上级代理不存在")
return
}
user.ParentAgentID = req.ParentAgentID
}
if req.Email != nil {
user.Email = req.Email
}
if req.Commission != nil {
user.Commission = *req.Commission
}
if req.Password != nil && *req.Password != "" {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(*req.Password), bcrypt.DefaultCost)
if err != nil {
response.Error(c, 500, "密码加密失败")
return
}
user.Password = string(hashedPassword)
}
if req.CanCreateAgent != nil {
user.CanCreateAgent = *req.CanCreateAgent
}
if req.Balance != nil {
user.Balance = *req.Balance
}
if err := database.DB.Save(&user).Error; err != nil {
response.Error(c, 500, "更新失败")
return
}
service.LogOperation(c, "update", "agent", &user.ID, fmt.Sprintf("更新代理: %s", user.Username), nil)
response.Success(c, gin.H{
"id": user.ID,
})
}
func handleUpdateAgentStatus(c *gin.Context) {
agentID := c.Param("id")
var user model.User
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
response.Error(c, 404, "代理不存在")
return
}
var req struct {
Status string `json:"status" binding:"required,oneof=active inactive banned"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
user.Status = req.Status
if err := database.DB.Save(&user).Error; err != nil {
response.Error(c, 500, "更新状态失败")
return
}
service.LogOperation(c, "update_status", "agent", &user.ID, fmt.Sprintf("更新代理状态: %s -> %s", user.Username, user.Status), nil)
response.Success(c, gin.H{
"id": user.ID,
"status": user.Status,
})
}
func handleDeleteAgent(c *gin.Context) {
agentID := c.Param("id")
var user model.User
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
response.Error(c, 404, "代理不存在")
return
}
database.DB.Model(&model.User{}).Where("parent_agent_id = ?", user.ID).Update("parent_agent_id", nil)
if err := database.DB.Delete(&user).Error; err != nil {
response.Error(c, 500, "删除失败")
return
}
service.LogOperation(c, "delete", "agent", &user.ID, fmt.Sprintf("删除代理: %s", user.Username), nil)
response.Success(c, gin.H{
"id": user.ID,
})
}
func handleGetAgentCards(c *gin.Context) {
agentID := c.Param("id")
var user model.User
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
response.Error(c, 404, "代理不存在")
return
}
var cards []model.Card
database.DB.Where("creator_id = ?", user.ID).
Preload("Application").
Preload("CardType").
Order("created_at DESC").
Find(&cards)
type CardResponse struct {
ID uint `json:"id"`
CardKey string `json:"card_key"`
ApplicationID uint `json:"application_id"`
AppName string `json:"app_name"`
CardTypeID uint `json:"card_type_id"`
CardTypeName string `json:"card_type_name"`
Price float64 `json:"price"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
}
var result []CardResponse
for _, card := range cards {
appName := ""
if card.Application != nil {
appName = card.Application.Name
}
cardTypeName := ""
if card.CardType.ID != 0 {
cardTypeName = card.CardType.Name
}
result = append(result, CardResponse{
ID: card.ID,
CardKey: card.CardKey,
ApplicationID: card.ApplicationID,
AppName: appName,
CardTypeID: card.CardTypeID,
CardTypeName: cardTypeName,
Price: card.CardType.Price,
Status: card.Status,
CreatedAt: card.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
response.Success(c, gin.H{
"cards": result,
"total": len(result),
})
}
func handleUpdateAgentCards(c *gin.Context) {
agentID := c.Param("id")
var user model.User
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
response.Error(c, 404, "代理不存在")
return
}
var req struct {
Cards []struct {
CardID uint `json:"card_id"`
Status string `json:"status"`
} `json:"cards"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
for _, cardReq := range req.Cards {
database.DB.Model(&model.Card{}).
Where("id = ? AND creator_id = ?", cardReq.CardID, user.ID).
Update("status", cardReq.Status)
}
response.Success(c, gin.H{
"message": "更新成功",
})
}