Files
verify/backend/internal/router/admin/agent_apps.go
T

881 lines
24 KiB
Go

package admin
import (
"fmt"
"log"
"time"
"verification-platform-backend/internal/database"
"verification-platform-backend/internal/model"
"verification-platform-backend/pkg/response"
"github.com/gin-gonic/gin"
)
func SetupAgentAppRoutes(r *gin.RouterGroup) {
agentApps := r.Group("/agent-apps")
{
agentApps.GET("", handleGetAgentApps)
agentApps.GET("/requests", handleGetAgentRequests)
agentApps.POST("/authorize", handleDirectAuthorize)
agentApps.POST("/invite", handleInviteAgent)
agentApps.PUT("/requests/:id/approve", handleApproveRequest)
agentApps.PUT("/requests/:id/reject", handleRejectRequest)
agentApps.GET("/:id", handleGetAgentAppDetail)
agentApps.PUT("/:id", handleUpdateAgentApp)
agentApps.PUT("/:id/card-types", handleUpdateAgentCardTypes)
agentApps.DELETE("/:id", handleRemoveAgentApp)
}
}
func SetupAgentAppRoutesWithoutPackage(r *gin.RouterGroup) {
agentApps := r.Group("/agent-apps")
{
agentApps.GET("/my-requests", handleGetMyRequests)
agentApps.POST("/request", handleRequestAuthorization)
agentApps.DELETE("/requests/:id", handleCancelRequest)
}
}
func checkAgentPermission(userID uint) bool {
var user model.User
if err := database.DB.First(&user, userID).Error; err != nil {
return false
}
if user.CurrentPackageID == nil {
return false
}
var userPackage model.UserPackage
if err := database.DB.Where("user_id = ? AND package_id = ? AND status = ?",
userID, user.CurrentPackageID, "active").First(&userPackage).Error; err != nil {
return false
}
if userPackage.ExpiredAt != nil && userPackage.ExpiredAt.Before(time.Now()) {
return false
}
var permission model.PackagePermission
if err := database.DB.Where("package_id = ?", user.CurrentPackageID).First(&permission).Error; err != nil {
return false
}
return permission.AllowAgent
}
func handleGetAgentApps(c *gin.Context) {
userID := c.GetUint("user_id")
var currentUser model.User
if err := database.DB.First(&currentUser, userID).Error; err != nil {
response.Error(c, 500, "获取用户信息失败")
return
}
var authorizations []model.AgentApplication
if currentUser.Role == "admin" {
if err := database.DB.Where("admin_id = ?", userID).
Preload("CardTypes.CardType").
Preload("Agent").
Preload("Application").
Order("created_at DESC").
Find(&authorizations).Error; err != nil {
response.Error(c, 500, "获取授权列表失败")
return
}
} else {
if err := database.DB.Where("admin_id = ?", userID).
Preload("CardTypes.CardType").
Preload("Agent").
Preload("Application").
Order("created_at DESC").
Find(&authorizations).Error; err != nil {
response.Error(c, 500, "获取授权列表失败")
return
}
}
type CardTypeResponse struct {
ID uint `json:"id"`
CardTypeID uint `json:"card_type_id"`
Name string `json:"name"`
BillingType string `json:"billing_type"`
CanGenerate bool `json:"can_generate"`
Price float64 `json:"price"`
OriginPrice float64 `json:"origin_price"`
}
type AgentAppResponse struct {
ID uint `json:"id"`
AgentID uint `json:"agent_id"`
AgentName string `json:"agent_name"`
AgentEmail string `json:"agent_email"`
ApplicationID uint `json:"application_id"`
AppName string `json:"app_name"`
Discount float64 `json:"discount"`
Status string `json:"status"`
Balance float64 `json:"balance"`
CardTypes []CardTypeResponse `json:"card_types"`
CreatedAt string `json:"created_at"`
}
var result []AgentAppResponse
for _, aa := range authorizations {
agentName := ""
agentEmail := ""
var agentBalance float64
if aa.Agent.ID != 0 {
agentName = aa.Agent.Username
if aa.Agent.Email != nil {
agentEmail = *aa.Agent.Email
}
agentBalance = aa.Agent.Balance
}
appName := ""
if aa.Application.ID != 0 {
appName = aa.Application.Name
}
var cardTypes []CardTypeResponse
for _, ct := range aa.CardTypes {
cardTypes = append(cardTypes, CardTypeResponse{
ID: ct.ID,
CardTypeID: ct.CardTypeID,
Name: ct.CardType.Name,
BillingType: ct.CardType.RechargeType,
CanGenerate: ct.CanGenerate,
Price: ct.Price,
OriginPrice: ct.CardType.Price,
})
}
result = append(result, AgentAppResponse{
ID: aa.ID,
AgentID: aa.AgentID,
AgentName: agentName,
AgentEmail: agentEmail,
ApplicationID: aa.ApplicationID,
AppName: appName,
Discount: aa.Discount,
Status: aa.Status,
Balance: agentBalance,
CardTypes: cardTypes,
CreatedAt: aa.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
response.Success(c, gin.H{
"agent_apps": result,
"total": len(result),
})
}
func handleGetAgentRequests(c *gin.Context) {
userID := c.GetUint("user_id")
requestType := c.Query("type")
query := database.DB.Where("admin_id = ?", userID)
if requestType == "invite" {
query = query.Where("type = ?", "invite")
} else if requestType == "request" {
query = query.Where("type = ?", "request")
}
var requests []model.AgentApplicationRequest
if err := query.
Preload("Agent").
Preload("Application").
Order("created_at DESC").
Find(&requests).Error; err != nil {
response.Error(c, 500, "获取申请列表失败")
return
}
type RequestResponse struct {
ID uint `json:"id"`
AgentID uint `json:"agent_id"`
AgentName string `json:"agent_name"`
AgentEmail string `json:"agent_email"`
AdminID uint `json:"admin_id"`
ApplicationID uint `json:"application_id"`
AppName string `json:"app_name"`
Type string `json:"type"`
Status string `json:"status"`
Message string `json:"message"`
RejectReason string `json:"reject_reason"`
CreatedAt string `json:"created_at"`
}
var result []RequestResponse
for _, req := range requests {
agentName := ""
agentEmail := ""
if req.Agent.ID != 0 {
agentName = req.Agent.Username
if req.Agent.Email != nil {
agentEmail = *req.Agent.Email
}
}
appName := ""
if req.Application.ID != 0 {
appName = req.Application.Name
}
result = append(result, RequestResponse{
ID: req.ID,
AgentID: req.AgentID,
AgentName: agentName,
AgentEmail: agentEmail,
AdminID: req.AdminID,
ApplicationID: req.ApplicationID,
AppName: appName,
Type: req.Type,
Status: req.Status,
Message: req.Message,
RejectReason: req.RejectReason,
CreatedAt: req.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
response.Success(c, gin.H{
"requests": result,
"total": len(result),
})
}
func handleGetMyRequests(c *gin.Context) {
userID := c.GetUint("user_id")
requestType := c.Query("type")
query := database.DB.Where("agent_id = ?", userID)
if requestType == "invite" {
query = query.Where("type = ?", "invite")
} else if requestType == "request" {
query = query.Where("type = ?", "request")
}
var requests []model.AgentApplicationRequest
if err := query.
Preload("Admin").
Preload("Application").
Order("created_at DESC").
Find(&requests).Error; err != nil {
response.Error(c, 500, "获取申请列表失败")
return
}
type RequestResponse struct {
ID uint `json:"id"`
AgentID uint `json:"agent_id"`
AdminID uint `json:"admin_id"`
AdminName string `json:"admin_name"`
ApplicationID uint `json:"application_id"`
AppName string `json:"app_name"`
Type string `json:"type"`
Status string `json:"status"`
Message string `json:"message"`
RejectReason string `json:"reject_reason"`
CreatedAt string `json:"created_at"`
}
var result []RequestResponse
for _, req := range requests {
AdminName := ""
if req.Admin.ID != 0 {
AdminName = req.Admin.Username
}
appName := ""
if req.Application.ID != 0 {
appName = req.Application.Name
}
result = append(result, RequestResponse{
ID: req.ID,
AgentID: req.AgentID,
AdminID: req.AdminID,
AdminName: AdminName,
ApplicationID: req.ApplicationID,
AppName: appName,
Type: req.Type,
Status: req.Status,
Message: req.Message,
RejectReason: req.RejectReason,
CreatedAt: req.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
response.Success(c, gin.H{
"requests": result,
"total": len(result),
})
}
func handleInviteAgent(c *gin.Context) {
userID := c.GetUint("user_id")
if !checkAgentPermission(userID) {
response.Error(c, 403, "您的套餐不支持代理功能,请升级套餐")
return
}
var req struct {
AgentID uint `json:"agent_id"`
ApplicationID uint `json:"application_id"`
Message string `json:"message"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
var agent model.User
if err := database.DB.First(&agent, req.AgentID).Error; err != nil {
response.Error(c, 404, "开发者不存在")
return
}
if agent.Role != "agent" {
response.Error(c, 400, "该用户不是代理商")
return
}
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", req.ApplicationID, userID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var existing model.AgentApplication
if err := database.DB.Where("agent_id = ? AND application_id = ?", req.AgentID, req.ApplicationID).First(&existing).Error; err == nil {
response.Error(c, 400, "该开发者已获得此应用的授权")
return
}
request := model.AgentApplicationRequest{
AgentID: req.AgentID,
AdminID: userID,
ApplicationID: req.ApplicationID,
Type: "invite",
Status: "pending",
Message: req.Message,
}
if err := database.DB.Create(&request).Error; err != nil {
fmt.Printf("创建邀请错误: %v\n", err)
response.Error(c, 500, "创建邀请失败")
return
}
response.Success(c, gin.H{
"id": request.ID,
"agent_id": request.AgentID,
"agent_name": agent.Username,
"app_id": request.ApplicationID,
"app_name": app.Name,
"type": request.Type,
"status": request.Status,
})
}
func handleRequestAuthorization(c *gin.Context) {
userID := c.GetUint("user_id")
var req struct {
AdminID uint `json:"admin_id"`
ApplicationID uint `json:"application_id"`
Message string `json:"message"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, 400, "参数错误")
return
}
var Admin model.User
if err := database.DB.First(&Admin, req.AdminID).Error; err != nil {
response.Error(c, 404, "开发者不存在")
return
}
if Admin.Role != "admin" {
response.Error(c, 400, "该用户不是管理员")
return
}
var app model.Application
if err := database.DB.Where("id = ? AND user_id = ?", req.ApplicationID, req.AdminID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
var existing model.AgentApplication
if err := database.DB.Where("agent_id = ? AND application_id = ?", userID, req.ApplicationID).First(&existing).Error; err == nil {
response.Error(c, 400, "您已获得此应用的授权")
return
}
var existingRequest model.AgentApplicationRequest
if err := database.DB.Where("agent_id = ? AND admin_id = ? AND application_id = ? AND status = ?",
userID, req.AdminID, req.ApplicationID, "pending").First(&existingRequest).Error; err == nil {
response.Error(c, 400, "您已有待处理的申请")
return
}
request := model.AgentApplicationRequest{
AgentID: userID,
AdminID: req.AdminID,
ApplicationID: req.ApplicationID,
Type: "request",
Status: "pending",
Message: req.Message,
}
if err := database.DB.Create(&request).Error; err != nil {
fmt.Printf("创建申请错误: %v\n", err)
response.Error(c, 500, "创建申请失败")
return
}
response.Success(c, gin.H{
"id": request.ID,
"admin_id": request.AdminID,
"admin_name": Admin.Username,
"app_id": request.ApplicationID,
"app_name": app.Name,
"type": request.Type,
"status": request.Status,
})
}
func handleApproveRequest(c *gin.Context) {
userID := c.GetUint("user_id")
requestID := c.Param("id")
if !checkAgentPermission(userID) {
response.Error(c, 403, "您的套餐不支持代理功能,请升级套餐")
return
}
var req model.AgentApplicationRequest
if err := database.DB.Where("id = ? AND admin_id = ?", requestID, userID).First(&req).Error; err != nil {
response.Error(c, 404, "申请不存在")
return
}
if req.Status != "pending" {
response.Error(c, 400, "该申请已处理")
return
}
tx := database.DB.Begin()
agentApp := model.AgentApplication{
AgentID: req.AgentID,
ApplicationID: req.ApplicationID,
AdminID: userID,
Discount: 1.0,
Status: "active",
IsReceived: true,
}
if err := tx.Create(&agentApp).Error; err != nil {
tx.Rollback()
fmt.Printf("创建授权错误: %v\n", err)
response.Error(c, 500, "创建授权失败")
return
}
var cardTypes []model.CardType
database.DB.Where("application_id = ? OR application_id IS NULL", req.ApplicationID).Find(&cardTypes)
for _, ct := range cardTypes {
agentCardType := model.AgentApplicationCardType{
AgentApplicationID: agentApp.ID,
CardTypeID: ct.ID,
CanGenerate: false,
}
tx.Create(&agentCardType)
}
req.Status = "approved"
if err := tx.Save(&req).Error; err != nil {
tx.Rollback()
response.Error(c, 500, "更新申请状态失败")
return
}
tx.Commit()
response.Success(c, gin.H{
"id": agentApp.ID,
"status": "approved",
})
}
func handleRejectRequest(c *gin.Context) {
userID := c.GetUint("user_id")
requestID := c.Param("id")
var reqBody struct {
RejectReason string `json:"reject_reason"`
}
if err := c.ShouldBindJSON(&reqBody); err != nil {
response.Error(c, 400, "参数错误")
return
}
var req model.AgentApplicationRequest
if err := database.DB.Where("id = ? AND admin_id = ?", requestID, userID).First(&req).Error; err != nil {
response.Error(c, 404, "申请不存在")
return
}
if req.Status != "pending" {
response.Error(c, 400, "该申请已处理")
return
}
req.Status = "rejected"
req.RejectReason = reqBody.RejectReason
if err := database.DB.Save(&req).Error; err != nil {
response.Error(c, 500, "更新申请状态失败")
return
}
response.Success(c, gin.H{
"id": req.ID,
"status": "rejected",
})
}
func handleGetAgentAppDetail(c *gin.Context) {
userID := c.GetUint("user_id")
agentAppID := c.Param("id")
var agentApp model.AgentApplication
if err := database.DB.Where("id = ? AND admin_id = ?", agentAppID, userID).
Preload("CardTypes.CardType").
First(&agentApp).Error; err != nil {
response.Error(c, 404, "授权记录不存在")
return
}
var agent model.User
if err := database.DB.Where("id = ?", agentApp.AgentID).First(&agent).Error; err != nil {
log.Printf("[ERROR] Failed to query agent: %v\n", err)
}
var application model.Application
if err := database.DB.Where("id = ?", agentApp.ApplicationID).First(&application).Error; err != nil {
log.Printf("[ERROR] Failed to query application: %v\n", err)
}
type CardTypeResponse struct {
CardTypeID uint `json:"card_type_id"`
Name string `json:"name"`
BillingType string `json:"billing_type"`
Price float64 `json:"price"`
OriginPrice float64 `json:"origin_price"`
CanGenerate bool `json:"can_generate"`
}
type AgentAppDetailResponse struct {
ID uint `json:"id"`
AgentID uint `json:"agent_id"`
AgentName string `json:"agent_name"`
AgentEmail string `json:"agent_email"`
ApplicationID uint `json:"application_id"`
AppName string `json:"app_name"`
Discount float64 `json:"discount"`
Status string `json:"status"`
Balance float64 `json:"balance"`
CardTypes []CardTypeResponse `json:"card_types"`
CreatedAt string `json:"created_at"`
}
var cardTypes []CardTypeResponse
for _, ct := range agentApp.CardTypes {
cardTypes = append(cardTypes, CardTypeResponse{
CardTypeID: ct.CardTypeID,
Name: ct.CardType.Name,
BillingType: ct.CardType.RechargeType,
Price: ct.Price,
OriginPrice: ct.CardType.Price,
CanGenerate: ct.CanGenerate,
})
}
result := AgentAppDetailResponse{
ID: agentApp.ID,
AgentID: agentApp.AgentID,
AgentName: agent.Username,
ApplicationID: agentApp.ApplicationID,
AppName: application.Name,
Discount: agentApp.Discount,
Status: agentApp.Status,
Balance: agent.Balance,
CardTypes: cardTypes,
CreatedAt: agentApp.CreatedAt.Format("2006-01-02 15:04:05"),
}
if agent.Email != nil {
result.AgentEmail = *agent.Email
}
response.Success(c, gin.H{
"agent_app": result,
})
}
func handleUpdateAgentApp(c *gin.Context) {
userID := c.GetUint("user_id")
agentAppID := c.Param("id")
var reqBody struct {
Discount *float64 `json:"discount"`
Status *string `json:"status"`
}
if err := c.ShouldBindJSON(&reqBody); err != nil {
response.Error(c, 400, "参数错误")
return
}
var agentApp model.AgentApplication
if err := database.DB.Where("id = ? AND admin_id = ?", agentAppID, userID).First(&agentApp).Error; err != nil {
response.Error(c, 404, "授权记录不存在")
return
}
updates := make(map[string]interface{})
if reqBody.Discount != nil {
updates["discount"] = *reqBody.Discount
}
if reqBody.Status != nil {
updates["status"] = *reqBody.Status
}
if len(updates) > 0 {
if err := database.DB.Model(&agentApp).Updates(updates).Error; err != nil {
response.Error(c, 500, "更新失败")
return
}
}
response.Success(c, gin.H{
"id": agentApp.ID,
})
}
func handleUpdateAgentCardTypes(c *gin.Context) {
userID := c.GetUint("user_id")
agentAppID := c.Param("id")
var reqBody struct {
CardTypes []struct {
CardTypeID uint `json:"card_type_id"`
CanGenerate bool `json:"can_generate"`
Price float64 `json:"price"`
} `json:"card_types"`
}
if err := c.ShouldBindJSON(&reqBody); err != nil {
response.Error(c, 400, "参数错误")
return
}
var agentApp model.AgentApplication
if err := database.DB.Where("id = ? AND admin_id = ?", agentAppID, userID).First(&agentApp).Error; err != nil {
response.Error(c, 404, "授权记录不存在")
return
}
tx := database.DB.Begin()
if err := tx.Where("agent_application_id = ?", agentAppID).Delete(&model.AgentApplicationCardType{}).Error; err != nil {
tx.Rollback()
response.Error(c, 500, "清除旧权限失败")
return
}
for _, ct := range reqBody.CardTypes {
agentCardType := model.AgentApplicationCardType{
AgentApplicationID: agentApp.ID,
CardTypeID: ct.CardTypeID,
CanGenerate: ct.CanGenerate,
Price: ct.Price,
}
if err := tx.Create(&agentCardType).Error; err != nil {
tx.Rollback()
response.Error(c, 500, "创建权限失败")
return
}
}
tx.Commit()
response.Success(c, gin.H{
"id": agentApp.ID,
})
}
func handleRemoveAgentApp(c *gin.Context) {
userID := c.GetUint("user_id")
agentAppID := c.Param("id")
var agentApp model.AgentApplication
if err := database.DB.Where("id = ? AND admin_id = ?", agentAppID, userID).First(&agentApp).Error; err != nil {
response.Error(c, 404, "授权记录不存在")
return
}
if err := database.DB.Delete(&agentApp).Error; err != nil {
response.Error(c, 500, "删除失败")
return
}
response.Success(c, gin.H{
"id": agentApp.ID,
})
}
func handleCancelRequest(c *gin.Context) {
userID := c.GetUint("user_id")
requestID := c.Param("id")
var req model.AgentApplicationRequest
if err := database.DB.Where("id = ? AND agent_id = ? AND status = ?", requestID, userID, "pending").First(&req).Error; err != nil {
response.Error(c, 404, "申请不存在或已处理")
return
}
if err := database.DB.Delete(&req).Error; err != nil {
response.Error(c, 500, "取消失败")
return
}
response.Success(c, gin.H{
"id": req.ID,
})
}
func handleDirectAuthorize(c *gin.Context) {
userID := c.GetUint("user_id")
var reqBody struct {
AgentID uint `json:"agent_id" binding:"required"`
ApplicationID uint `json:"application_id" binding:"required"`
Discount float64 `json:"discount"`
CardTypes []struct {
CardTypeID uint `json:"card_type_id" binding:"required"`
CanGenerate bool `json:"can_generate"`
Price float64 `json:"price"`
} `json:"card_types"`
}
if err := c.ShouldBindJSON(&reqBody); err != nil {
response.Error(c, 400, "参数错误")
return
}
if reqBody.Discount <= 0 || reqBody.Discount > 1 {
reqBody.Discount = 1.0
}
var agent model.User
if err := database.DB.Where("id = ? AND role = ?", reqBody.AgentID, "agent").First(&agent).Error; err != nil {
response.Error(c, 404, "代理不存在")
return
}
if agent.ParentAgentID != nil && *agent.ParentAgentID != userID {
var currentUser model.User
if err := database.DB.First(&currentUser, userID).Error; err != nil {
response.Error(c, 403, "无权授权该代理")
return
}
if currentUser.Role != "admin" {
response.Error(c, 403, "只能授权自己的下级代理")
return
}
}
var app model.Application
if err := database.DB.Where("id = ?", reqBody.ApplicationID).First(&app).Error; err != nil {
response.Error(c, 404, "应用不存在")
return
}
if app.UserID != userID {
var currentUser model.User
if err := database.DB.First(&currentUser, userID).Error; err != nil {
response.Error(c, 403, "无权授权该应用")
return
}
if currentUser.Role != "admin" {
response.Error(c, 403, "只能授权自己的应用")
return
}
}
var existing model.AgentApplication
if err := database.DB.Where("agent_id = ? AND application_id = ?", reqBody.AgentID, reqBody.ApplicationID).First(&existing).Error; err == nil {
response.Error(c, 400, "该代理已获得此应用的授权")
return
}
tx := database.DB.Begin()
agentApp := model.AgentApplication{
AgentID: reqBody.AgentID,
ApplicationID: reqBody.ApplicationID,
AdminID: userID,
Discount: reqBody.Discount,
Status: "active",
IsReceived: true,
}
if err := tx.Create(&agentApp).Error; err != nil {
tx.Rollback()
response.Error(c, 500, "创建授权失败")
return
}
if len(reqBody.CardTypes) > 0 {
for _, ct := range reqBody.CardTypes {
agentCardType := model.AgentApplicationCardType{
AgentApplicationID: agentApp.ID,
CardTypeID: ct.CardTypeID,
CanGenerate: ct.CanGenerate,
Price: ct.Price,
}
if err := tx.Create(&agentCardType).Error; err != nil {
tx.Rollback()
response.Error(c, 500, "创建卡密权限失败")
return
}
}
} else {
var cardTypes []model.CardType
database.DB.Where("application_id = ?", reqBody.ApplicationID).Find(&cardTypes)
for _, ct := range cardTypes {
agentCardType := model.AgentApplicationCardType{
AgentApplicationID: agentApp.ID,
CardTypeID: ct.ID,
CanGenerate: false,
Price: ct.Price,
}
if err := tx.Create(&agentCardType).Error; err != nil {
tx.Rollback()
response.Error(c, 500, "创建卡密权限失败")
return
}
}
}
tx.Commit()
response.Success(c, gin.H{
"id": agentApp.ID,
"agent_id": agentApp.AgentID,
"agent_name": agent.Username,
"app_id": agentApp.ApplicationID,
"app_name": app.Name,
"discount": agentApp.Discount,
"status": agentApp.Status,
})
}