2025-10-24 00:09:45 +08:00
|
|
|
|
package admin
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2026-03-18 21:51:17 +08:00
|
|
|
|
"NetworkAuth/controllers"
|
|
|
|
|
|
"NetworkAuth/models"
|
2026-03-19 05:11:44 +08:00
|
|
|
|
"NetworkAuth/services"
|
2025-10-24 00:09:45 +08:00
|
|
|
|
"crypto/rand"
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"encoding/base64"
|
2025-10-24 00:09:45 +08:00
|
|
|
|
"encoding/hex"
|
|
|
|
|
|
"net/http"
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"github.com/gin-gonic/gin"
|
2025-10-24 00:09:45 +08:00
|
|
|
|
"github.com/google/uuid"
|
|
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-27 23:12:15 +08:00
|
|
|
|
// ============================================================================
|
|
|
|
|
|
// 全局变量
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
var appBaseController = controllers.NewBaseController()
|
|
|
|
|
|
|
2025-10-27 23:12:15 +08:00
|
|
|
|
// ============================================================================
|
|
|
|
|
|
// API处理器
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
2025-10-24 00:09:45 +08:00
|
|
|
|
// AppsListHandler 应用列表API处理器
|
2025-10-26 14:48:02 +08:00
|
|
|
|
func AppsListHandler(c *gin.Context) {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
// 获取分页参数
|
2026-03-19 19:17:37 +08:00
|
|
|
|
page, limit := appBaseController.GetPaginationParams(c)
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取搜索参数
|
2025-10-26 14:48:02 +08:00
|
|
|
|
search := strings.TrimSpace(c.Query("search"))
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 构建查询
|
2025-10-26 14:48:02 +08:00
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
query := db.Model(&models.App{})
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有搜索条件
|
|
|
|
|
|
if search != "" {
|
2026-03-18 01:08:15 +08:00
|
|
|
|
// 优化:使用精确匹配提升查询性能
|
|
|
|
|
|
query = query.Where("name = ? OR uuid = ?", search, search)
|
2025-10-24 00:09:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-19 19:17:37 +08:00
|
|
|
|
// 泛型分页查询
|
|
|
|
|
|
apps, total, err := services.Paginate[models.App](query, page, limit, "created_at DESC")
|
|
|
|
|
|
if err != nil {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to query apps")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
appBaseController.HandleInternalError(c, "查询应用列表失败", err)
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 返回结果
|
2025-10-26 14:48:02 +08:00
|
|
|
|
response := gin.H{
|
2025-10-24 00:09:45 +08:00
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "success",
|
|
|
|
|
|
"count": total,
|
|
|
|
|
|
"data": apps,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, response)
|
2025-10-24 00:09:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-25 01:43:03 +08:00
|
|
|
|
// AppGetAppDataHandler 获取应用数据处理器
|
2025-10-26 14:48:02 +08:00
|
|
|
|
func AppGetAppDataHandler(c *gin.Context) {
|
2025-10-25 01:43:03 +08:00
|
|
|
|
// 获取UUID参数
|
2025-10-26 14:48:02 +08:00
|
|
|
|
uuid := c.Query("uuid")
|
2025-10-25 01:43:03 +08:00
|
|
|
|
if uuid == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取数据库连接
|
2025-10-26 14:48:02 +08:00
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", uuid).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解码base64应用数据内容
|
|
|
|
|
|
var appData string
|
|
|
|
|
|
if app.AppData != "" {
|
|
|
|
|
|
decodedBytes, err := base64.StdEncoding.DecodeString(app.AppData)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to decode app data")
|
|
|
|
|
|
// 如果解码失败,返回空字符串
|
|
|
|
|
|
appData = ""
|
|
|
|
|
|
} else {
|
|
|
|
|
|
appData = string(decodedBytes)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "获取成功",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"data": gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"app_data": appData,
|
|
|
|
|
|
},
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppGetAnnouncementHandler 获取公告处理器
|
|
|
|
|
|
func AppGetAnnouncementHandler(c *gin.Context) {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
// 获取UUID参数
|
2025-10-26 14:48:02 +08:00
|
|
|
|
uuid := c.Query("uuid")
|
2025-10-24 01:48:54 +08:00
|
|
|
|
if uuid == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取数据库连接
|
2025-10-26 14:48:02 +08:00
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", uuid).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解码base64公告内容
|
|
|
|
|
|
var announcement string
|
|
|
|
|
|
if app.Announcement != "" {
|
|
|
|
|
|
decodedBytes, err := base64.StdEncoding.DecodeString(app.Announcement)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to decode announcement")
|
|
|
|
|
|
// 如果解码失败,返回空字符串
|
|
|
|
|
|
announcement = ""
|
|
|
|
|
|
} else {
|
|
|
|
|
|
announcement = string(decodedBytes)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "获取成功",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"data": gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"announcement": announcement,
|
|
|
|
|
|
},
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppResetSecretHandler 重置应用密钥处理器
|
|
|
|
|
|
func AppResetSecretHandler(c *gin.Context) {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
var req struct {
|
|
|
|
|
|
UUID string `json:"uuid"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 验证必填字段
|
|
|
|
|
|
if strings.TrimSpace(req.UUID) == "" {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", req.UUID).First(&app).Error; err != nil {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
|
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成新的密钥
|
2025-10-26 14:48:02 +08:00
|
|
|
|
bytes := make([]byte, 16) // 16字节 = 32位16进制字符
|
|
|
|
|
|
rand.Read(bytes)
|
2025-10-24 01:48:54 +08:00
|
|
|
|
newSecret := strings.ToUpper(hex.EncodeToString(bytes))
|
|
|
|
|
|
|
|
|
|
|
|
// 更新密钥
|
|
|
|
|
|
if err := db.Model(&app).Update("secret", newSecret).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to update app secret")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "重置密钥失败",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-18 21:51:17 +08:00
|
|
|
|
logrus.WithField("app_uuid", app.UUID).Debug("Successfully reset app secret")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 0,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "重置成功",
|
|
|
|
|
|
"data": gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"secret": newSecret,
|
|
|
|
|
|
},
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-24 00:09:45 +08:00
|
|
|
|
// AppCreateHandler 创建应用API处理器
|
2025-10-26 14:48:02 +08:00
|
|
|
|
func AppCreateHandler(c *gin.Context) {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
var req struct {
|
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
|
Version string `json:"version"`
|
|
|
|
|
|
Status int `json:"status"`
|
|
|
|
|
|
DownloadType int `json:"download_type"`
|
|
|
|
|
|
ForceUpdate int `json:"force_update"`
|
|
|
|
|
|
DownloadURL string `json:"download_url"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证必填字段
|
|
|
|
|
|
if strings.TrimSpace(req.Name) == "" {
|
|
|
|
|
|
logrus.Error("App name is empty")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用名称不能为空",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置默认值
|
|
|
|
|
|
if req.Version == "" {
|
|
|
|
|
|
req.Version = "1.0.0"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
|
|
"name": req.Name,
|
|
|
|
|
|
"version": req.Version,
|
|
|
|
|
|
"status": req.Status,
|
|
|
|
|
|
"download_type": req.DownloadType,
|
|
|
|
|
|
"download_url": req.DownloadURL,
|
|
|
|
|
|
"force_update": req.ForceUpdate,
|
2026-03-18 21:51:17 +08:00
|
|
|
|
}).Debug("Received app create request")
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 创建应用
|
|
|
|
|
|
app := models.App{
|
|
|
|
|
|
Name: strings.TrimSpace(req.Name),
|
|
|
|
|
|
Version: req.Version,
|
|
|
|
|
|
Status: req.Status,
|
|
|
|
|
|
DownloadType: req.DownloadType,
|
|
|
|
|
|
DownloadURL: strings.TrimSpace(req.DownloadURL),
|
|
|
|
|
|
ForceUpdate: req.ForceUpdate,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 确保UUID和Secret被设置(虽然BeforeCreate钩子应该处理这些,但为了保险起见)
|
|
|
|
|
|
if app.UUID == "" {
|
2025-10-24 01:54:45 +08:00
|
|
|
|
app.UUID = strings.ToUpper(uuid.New().String())
|
2025-10-24 00:09:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
if app.Secret == "" {
|
|
|
|
|
|
// 生成32位大写16进制随机字符
|
|
|
|
|
|
bytes := make([]byte, 16) // 16字节 = 32位16进制字符
|
|
|
|
|
|
rand.Read(bytes)
|
|
|
|
|
|
app.Secret = strings.ToUpper(hex.EncodeToString(bytes))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-25 01:43:03 +08:00
|
|
|
|
// 开始事务
|
|
|
|
|
|
tx := db.Begin()
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if tx.Error != nil {
|
|
|
|
|
|
logrus.WithError(tx.Error).Error("Failed to begin transaction")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "开始事务失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-10-25 01:43:03 +08:00
|
|
|
|
defer func() {
|
|
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
}
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
// 创建应用
|
|
|
|
|
|
if err := tx.Create(&app).Error; err != nil {
|
|
|
|
|
|
tx.Rollback()
|
2025-10-24 00:09:45 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to create app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2026-03-18 21:51:17 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "创建应用失败: " + err.Error(),
|
|
|
|
|
|
"error": err.Error(),
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-25 01:43:03 +08:00
|
|
|
|
// 为应用创建所有默认接口
|
2025-10-27 23:12:15 +08:00
|
|
|
|
defaultAPITypes := models.GetDefaultAPITypes()
|
2025-10-25 01:43:03 +08:00
|
|
|
|
|
|
|
|
|
|
// 批量创建默认接口
|
|
|
|
|
|
for _, apiType := range defaultAPITypes {
|
|
|
|
|
|
api := models.API{
|
|
|
|
|
|
APIType: apiType,
|
|
|
|
|
|
AppUUID: app.UUID,
|
2025-10-26 22:28:50 +08:00
|
|
|
|
Status: 0, // 默认禁用
|
2025-10-25 01:43:03 +08:00
|
|
|
|
SubmitAlgorithm: models.AlgorithmNone, // 默认不加密
|
|
|
|
|
|
ReturnAlgorithm: models.AlgorithmNone, // 默认不加密
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := tx.Create(&api).Error; err != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
logrus.WithError(err).WithField("api_type", apiType).Error("Failed to create default API")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "创建默认接口失败",
|
|
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提交事务
|
2026-03-28 23:30:02 +08:00
|
|
|
|
|
2025-10-25 01:43:03 +08:00
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to commit transaction")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "提交事务失败",
|
|
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-19 05:11:44 +08:00
|
|
|
|
// 记录操作日志
|
|
|
|
|
|
operator := c.GetString("admin_username")
|
|
|
|
|
|
if operator == "" {
|
|
|
|
|
|
operator = "unknown"
|
|
|
|
|
|
}
|
|
|
|
|
|
operatorUUID := c.GetString("admin_uuid")
|
|
|
|
|
|
|
|
|
|
|
|
services.RecordOperationLog(
|
|
|
|
|
|
"创建应用",
|
|
|
|
|
|
operator,
|
|
|
|
|
|
operatorUUID,
|
|
|
|
|
|
"创建了应用: "+app.Name,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-03-18 21:51:17 +08:00
|
|
|
|
logrus.WithField("app_uuid", app.UUID).Debug("Successfully created app with default APIs")
|
2025-10-25 01:43:03 +08:00
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-24 00:09:45 +08:00
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "创建成功",
|
|
|
|
|
|
"data": app,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// AppUpdateHandler 更新应用API处理器
|
2025-10-26 14:48:02 +08:00
|
|
|
|
func AppUpdateHandler(c *gin.Context) {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
var req struct {
|
|
|
|
|
|
ID uint `json:"id"`
|
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
|
Version string `json:"version"`
|
|
|
|
|
|
Status int `json:"status"`
|
|
|
|
|
|
DownloadType int `json:"download_type"`
|
|
|
|
|
|
DownloadURL string `json:"download_url"`
|
|
|
|
|
|
ForceUpdate int `json:"force_update"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证必填字段
|
|
|
|
|
|
if req.ID == 0 {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用ID不能为空",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-10-26 14:48:02 +08:00
|
|
|
|
|
2025-10-24 00:09:45 +08:00
|
|
|
|
if strings.TrimSpace(req.Name) == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用名称不能为空",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.First(&app, req.ID).Error; err != nil {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
|
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 更新应用信息
|
2025-10-24 00:09:45 +08:00
|
|
|
|
app.Name = strings.TrimSpace(req.Name)
|
|
|
|
|
|
app.Version = req.Version
|
|
|
|
|
|
app.Status = req.Status
|
|
|
|
|
|
app.DownloadType = req.DownloadType
|
|
|
|
|
|
app.DownloadURL = strings.TrimSpace(req.DownloadURL)
|
|
|
|
|
|
app.ForceUpdate = req.ForceUpdate
|
|
|
|
|
|
|
|
|
|
|
|
if err := db.Save(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to update app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "更新应用失败",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-18 21:51:17 +08:00
|
|
|
|
logrus.WithField("app_id", app.ID).Debug("Successfully updated app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-24 00:09:45 +08:00
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "更新成功",
|
|
|
|
|
|
"data": app,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppDeleteHandler 删除应用处理器
|
|
|
|
|
|
func AppDeleteHandler(c *gin.Context) {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
var req struct {
|
|
|
|
|
|
ID uint `json:"id"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 验证必填字段
|
2025-10-24 00:09:45 +08:00
|
|
|
|
if req.ID == 0 {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用ID不能为空",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 查找应用
|
2025-10-25 01:43:03 +08:00
|
|
|
|
var app models.App
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if err := db.First(&app, req.ID).Error; err != nil {
|
2025-10-25 01:43:03 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 开始事务
|
|
|
|
|
|
tx := db.Begin()
|
|
|
|
|
|
if tx.Error != nil {
|
|
|
|
|
|
logrus.WithError(tx.Error).Error("Failed to begin transaction")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "开始事务失败",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-25 01:43:03 +08:00
|
|
|
|
defer func() {
|
|
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
}
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 删除相关的API记录
|
|
|
|
|
|
if err := tx.Where("app_uuid = ?", app.UUID).Delete(&models.API{}).Error; err != nil {
|
2025-10-25 01:43:03 +08:00
|
|
|
|
tx.Rollback()
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to delete related APIs")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "删除相关接口失败",
|
|
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-04 20:50:45 +08:00
|
|
|
|
// 检查是否有关联的变量
|
|
|
|
|
|
var varCount int64
|
|
|
|
|
|
if err := tx.Model(&models.Variable{}).Where("app_uuid = ?", app.UUID).Count(&varCount).Error; err != nil {
|
2026-03-28 23:30:02 +08:00
|
|
|
|
tx.Rollback()
|
2026-04-04 20:50:45 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to count related variables")
|
2026-03-28 23:30:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
2026-04-04 20:50:45 +08:00
|
|
|
|
"msg": "检查关联变量失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if varCount > 0 {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "该应用下存在关联变量,禁止删除",
|
2026-03-28 23:30:02 +08:00
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-04 20:50:45 +08:00
|
|
|
|
// 检查是否有关联的函数
|
|
|
|
|
|
var funcCount int64
|
|
|
|
|
|
if err := tx.Model(&models.Function{}).Where("app_uuid = ?", app.UUID).Count(&funcCount).Error; err != nil {
|
2026-03-28 23:30:02 +08:00
|
|
|
|
tx.Rollback()
|
2026-04-04 20:50:45 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to count related functions")
|
2026-03-28 23:30:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
2026-04-04 20:50:45 +08:00
|
|
|
|
"msg": "检查关联函数失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if funcCount > 0 {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "该应用下存在关联函数,禁止删除",
|
2026-03-28 23:30:02 +08:00
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 删除应用
|
|
|
|
|
|
if err := tx.Delete(&app).Error; err != nil {
|
2025-10-25 01:43:03 +08:00
|
|
|
|
tx.Rollback()
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Failed to delete app")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "删除应用失败",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-25 01:43:03 +08:00
|
|
|
|
// 提交事务
|
|
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to commit transaction")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "提交事务失败",
|
|
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-19 05:11:44 +08:00
|
|
|
|
// 记录操作日志
|
|
|
|
|
|
operator := c.GetString("admin_username")
|
|
|
|
|
|
if operator == "" {
|
|
|
|
|
|
operator = "unknown"
|
|
|
|
|
|
}
|
|
|
|
|
|
operatorUUID := c.GetString("admin_uuid")
|
|
|
|
|
|
|
|
|
|
|
|
services.RecordOperationLog(
|
|
|
|
|
|
"删除应用",
|
|
|
|
|
|
operator,
|
|
|
|
|
|
operatorUUID,
|
|
|
|
|
|
"删除了应用: "+app.Name,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-25 01:43:03 +08:00
|
|
|
|
logrus.WithFields(logrus.Fields{
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"app_id": app.ID,
|
|
|
|
|
|
"app_uuid": app.UUID,
|
2026-04-04 20:50:45 +08:00
|
|
|
|
}).Debug("Successfully deleted app and related APIs")
|
2025-10-24 00:09:45 +08:00
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-24 00:09:45 +08:00
|
|
|
|
"code": 0,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "删除成功",
|
|
|
|
|
|
})
|
2025-10-24 00:09:45 +08:00
|
|
|
|
}
|
2025-10-24 01:48:54 +08:00
|
|
|
|
|
2025-10-25 01:43:03 +08:00
|
|
|
|
// AppUpdateAppDataHandler 更新应用数据处理器
|
2025-10-26 14:48:02 +08:00
|
|
|
|
func AppUpdateAppDataHandler(c *gin.Context) {
|
2025-10-25 01:43:03 +08:00
|
|
|
|
// 解析请求体
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
UUID string `json:"uuid"`
|
|
|
|
|
|
AppData string `json:"app_data"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID
|
|
|
|
|
|
if req.UUID == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID格式
|
|
|
|
|
|
if _, err := uuid.Parse(req.UUID); err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Invalid UUID format")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "无效的UUID格式",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取数据库连接
|
2025-10-26 14:48:02 +08:00
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", req.UUID).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 对应用数据内容进行base64编码
|
|
|
|
|
|
encodedAppData := base64.StdEncoding.EncodeToString([]byte(req.AppData))
|
|
|
|
|
|
|
|
|
|
|
|
// 更新应用的数据内容
|
|
|
|
|
|
if err := db.Model(&app).Update("app_data", encodedAppData).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to update app data")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "更新应用数据失败",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
|
|
"app_uuid": req.UUID,
|
|
|
|
|
|
"app_name": app.Name,
|
2026-03-18 21:51:17 +08:00
|
|
|
|
}).Debug("App data updated successfully")
|
2025-10-25 01:43:03 +08:00
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-25 01:43:03 +08:00
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "应用数据更新成功",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-25 01:43:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-24 01:48:54 +08:00
|
|
|
|
// AppUpdateAnnouncementHandler 更新应用程序公告处理器
|
2025-10-26 14:48:02 +08:00
|
|
|
|
func AppUpdateAnnouncementHandler(c *gin.Context) {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
// 解析请求体
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
UUID string `json:"uuid"`
|
|
|
|
|
|
Announcement string `json:"announcement"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID
|
|
|
|
|
|
if req.UUID == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID格式
|
|
|
|
|
|
if _, err := uuid.Parse(req.UUID); err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Invalid UUID format")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "无效的UUID格式",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取数据库连接
|
2025-10-26 14:48:02 +08:00
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", req.UUID).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 对公告内容进行base64编码
|
|
|
|
|
|
encodedAnnouncement := base64.StdEncoding.EncodeToString([]byte(req.Announcement))
|
|
|
|
|
|
|
|
|
|
|
|
// 更新应用的公告内容
|
|
|
|
|
|
if err := db.Model(&app).Update("announcement", encodedAnnouncement).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to update app announcement")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "更新程序公告失败",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
|
|
"app_uuid": req.UUID,
|
|
|
|
|
|
"app_name": app.Name,
|
2026-03-18 21:51:17 +08:00
|
|
|
|
}).Debug("App announcement updated successfully")
|
2025-10-24 01:48:54 +08:00
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-24 01:48:54 +08:00
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "程序公告更新成功",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppGetMultiConfigHandler 获取应用多开配置处理器
|
|
|
|
|
|
func AppGetMultiConfigHandler(c *gin.Context) {
|
|
|
|
|
|
appUUID := c.Query("uuid")
|
2025-10-24 01:48:54 +08:00
|
|
|
|
if appUUID == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID格式
|
|
|
|
|
|
if _, err := uuid.Parse(appUUID); err != nil {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Invalid UUID format")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "无效的UUID格式",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 查找应用
|
2025-10-24 01:48:54 +08:00
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", appUUID).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "获取多开配置成功",
|
|
|
|
|
|
"data": gin.H{
|
|
|
|
|
|
"login_type": app.LoginType,
|
|
|
|
|
|
"multi_open_scope": app.MultiOpenScope,
|
|
|
|
|
|
"clean_interval": app.CleanInterval,
|
|
|
|
|
|
"check_interval": app.CheckInterval,
|
|
|
|
|
|
"multi_open_count": app.MultiOpenCount,
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppUpdateMultiConfigHandler 更新应用多开配置处理器
|
|
|
|
|
|
func AppUpdateMultiConfigHandler(c *gin.Context) {
|
|
|
|
|
|
// 解析请求体
|
2025-10-24 01:48:54 +08:00
|
|
|
|
var req struct {
|
2025-10-24 08:50:45 +08:00
|
|
|
|
UUID string `json:"uuid"`
|
|
|
|
|
|
LoginType int `json:"login_type"`
|
|
|
|
|
|
MultiOpenScope int `json:"multi_open_scope"`
|
|
|
|
|
|
CleanInterval int `json:"clean_interval"`
|
|
|
|
|
|
CheckInterval int `json:"check_interval"`
|
|
|
|
|
|
MultiOpenCount int `json:"multi_open_count"`
|
2025-10-24 01:48:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 验证UUID
|
|
|
|
|
|
if req.UUID == "" {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID格式
|
2025-10-24 01:48:54 +08:00
|
|
|
|
if _, err := uuid.Parse(req.UUID); err != nil {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Invalid UUID format")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "无效的UUID格式",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证参数范围
|
|
|
|
|
|
if req.LoginType < 0 || req.LoginType > 1 {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "登录方式参数无效",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if req.MultiOpenScope < 0 || req.MultiOpenScope > 2 {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "多开范围参数无效",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if req.CleanInterval < 1 {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "清理间隔必须大于0",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if req.CheckInterval < 1 {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "校验间隔必须大于0",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if req.MultiOpenCount < 1 {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "多开数量必须大于0",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", req.UUID).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新多开配置
|
|
|
|
|
|
updates := map[string]interface{}{
|
|
|
|
|
|
"login_type": req.LoginType,
|
|
|
|
|
|
"multi_open_scope": req.MultiOpenScope,
|
|
|
|
|
|
"clean_interval": req.CleanInterval,
|
|
|
|
|
|
"check_interval": req.CheckInterval,
|
|
|
|
|
|
"multi_open_count": req.MultiOpenCount,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := db.Model(&app).Updates(updates).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to update app multi config")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "更新多开配置失败",
|
|
|
|
|
|
})
|
2025-10-24 01:48:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
|
|
"app_uuid": req.UUID,
|
|
|
|
|
|
"app_name": app.Name,
|
2026-03-18 21:51:17 +08:00
|
|
|
|
}).Debug("App multi config updated successfully")
|
2025-10-24 05:09:22 +08:00
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "多开配置更新成功",
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-10-24 05:09:22 +08:00
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppGetBindConfigHandler 获取应用绑定配置处理器
|
|
|
|
|
|
func AppGetBindConfigHandler(c *gin.Context) {
|
|
|
|
|
|
appUUID := c.Query("uuid")
|
2025-10-24 05:09:22 +08:00
|
|
|
|
if appUUID == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 05:09:22 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "应用UUID不能为空",
|
|
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID格式
|
|
|
|
|
|
if _, err := uuid.Parse(appUUID); err != nil {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Invalid UUID format")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 05:09:22 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "无效的UUID格式",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 查找应用
|
2025-10-24 05:09:22 +08:00
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", appUUID).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
2025-10-24 05:09:22 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "获取绑定配置成功",
|
|
|
|
|
|
"data": gin.H{
|
2025-10-26 22:28:50 +08:00
|
|
|
|
"machine_verify": app.MachineVerify,
|
|
|
|
|
|
"machine_rebind_enabled": app.MachineRebindEnabled,
|
|
|
|
|
|
"machine_rebind_limit": app.MachineRebindLimit,
|
|
|
|
|
|
"machine_free_count": app.MachineFreeCount,
|
|
|
|
|
|
"machine_rebind_count": app.MachineRebindCount,
|
|
|
|
|
|
"machine_rebind_deduct": app.MachineRebindDeduct,
|
|
|
|
|
|
"ip_verify": app.IPVerify,
|
|
|
|
|
|
"ip_rebind_enabled": app.IPRebindEnabled,
|
|
|
|
|
|
"ip_rebind_limit": app.IPRebindLimit,
|
|
|
|
|
|
"ip_free_count": app.IPFreeCount,
|
|
|
|
|
|
"ip_rebind_count": app.IPRebindCount,
|
|
|
|
|
|
"ip_rebind_deduct": app.IPRebindDeduct,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
},
|
|
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppUpdateBindConfigHandler 更新应用绑定配置处理器
|
|
|
|
|
|
func AppUpdateBindConfigHandler(c *gin.Context) {
|
|
|
|
|
|
// 解析请求体
|
|
|
|
|
|
var req struct {
|
2025-10-26 22:28:50 +08:00
|
|
|
|
UUID string `json:"uuid"`
|
|
|
|
|
|
MachineVerify int `json:"machine_verify"`
|
|
|
|
|
|
MachineRebindEnabled int `json:"machine_rebind_enabled"`
|
|
|
|
|
|
MachineRebindLimit int `json:"machine_rebind_limit"`
|
|
|
|
|
|
MachineFreeCount int `json:"machine_free_count"`
|
|
|
|
|
|
MachineRebindCount int `json:"machine_rebind_count"`
|
|
|
|
|
|
MachineRebindDeduct int `json:"machine_rebind_deduct"`
|
|
|
|
|
|
IPVerify int `json:"ip_verify"`
|
|
|
|
|
|
IPRebindEnabled int `json:"ip_rebind_enabled"`
|
|
|
|
|
|
IPRebindLimit int `json:"ip_rebind_limit"`
|
|
|
|
|
|
IPFreeCount int `json:"ip_free_count"`
|
|
|
|
|
|
IPRebindCount int `json:"ip_rebind_count"`
|
|
|
|
|
|
IPRebindDeduct int `json:"ip_rebind_deduct"`
|
2025-10-24 05:09:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID
|
|
|
|
|
|
if req.UUID == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 05:09:22 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 验证UUID格式
|
2025-10-24 05:09:22 +08:00
|
|
|
|
if _, err := uuid.Parse(req.UUID); err != nil {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Invalid UUID format")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 05:09:22 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "无效的UUID格式",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", req.UUID).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
2025-10-24 05:09:22 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新绑定配置
|
|
|
|
|
|
updates := map[string]interface{}{
|
2025-10-26 22:28:50 +08:00
|
|
|
|
"machine_verify": req.MachineVerify,
|
|
|
|
|
|
"machine_rebind_enabled": req.MachineRebindEnabled,
|
|
|
|
|
|
"machine_rebind_limit": req.MachineRebindLimit,
|
|
|
|
|
|
"machine_free_count": req.MachineFreeCount,
|
|
|
|
|
|
"machine_rebind_count": req.MachineRebindCount,
|
|
|
|
|
|
"machine_rebind_deduct": req.MachineRebindDeduct,
|
|
|
|
|
|
"ip_verify": req.IPVerify,
|
|
|
|
|
|
"ip_rebind_enabled": req.IPRebindEnabled,
|
|
|
|
|
|
"ip_rebind_limit": req.IPRebindLimit,
|
|
|
|
|
|
"ip_free_count": req.IPFreeCount,
|
|
|
|
|
|
"ip_rebind_count": req.IPRebindCount,
|
|
|
|
|
|
"ip_rebind_deduct": req.IPRebindDeduct,
|
2025-10-24 05:09:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := db.Model(&app).Updates(updates).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to update app bind config")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2025-10-24 05:09:22 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "更新绑定配置失败",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
|
|
"app_uuid": req.UUID,
|
|
|
|
|
|
"app_name": app.Name,
|
2026-03-18 21:51:17 +08:00
|
|
|
|
}).Debug("App bind config updated successfully")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2025-10-24 05:09:22 +08:00
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "绑定配置更新成功",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 05:09:22 +08:00
|
|
|
|
}
|
2025-10-24 08:25:16 +08:00
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppGetRegisterConfigHandler 获取应用注册配置处理器
|
|
|
|
|
|
func AppGetRegisterConfigHandler(c *gin.Context) {
|
|
|
|
|
|
appUUID := c.Query("uuid")
|
2025-10-24 08:25:16 +08:00
|
|
|
|
if appUUID == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "应用UUID不能为空",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID格式
|
|
|
|
|
|
if _, err := uuid.Parse(appUUID); err != nil {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Invalid UUID format")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "无效的UUID格式",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 查找应用
|
2025-10-24 08:25:16 +08:00
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", appUUID).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "获取注册配置成功",
|
|
|
|
|
|
"data": gin.H{
|
|
|
|
|
|
"register_enabled": app.RegisterEnabled,
|
|
|
|
|
|
"register_limit_enabled": app.RegisterLimitEnabled,
|
|
|
|
|
|
"register_limit_time": app.RegisterLimitTime,
|
|
|
|
|
|
"register_count": app.RegisterCount,
|
|
|
|
|
|
"trial_enabled": app.TrialEnabled,
|
|
|
|
|
|
"trial_limit_time": app.TrialLimitTime,
|
|
|
|
|
|
"trial_duration": app.TrialDuration,
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// AppUpdateRegisterConfigHandler 更新应用注册配置处理器
|
|
|
|
|
|
func AppUpdateRegisterConfigHandler(c *gin.Context) {
|
|
|
|
|
|
// 解析请求体
|
2025-10-24 08:25:16 +08:00
|
|
|
|
var req struct {
|
|
|
|
|
|
UUID string `json:"uuid"`
|
|
|
|
|
|
RegisterEnabled int `json:"register_enabled"`
|
|
|
|
|
|
RegisterLimitEnabled int `json:"register_limit_enabled"`
|
|
|
|
|
|
RegisterLimitTime int `json:"register_limit_time"`
|
|
|
|
|
|
RegisterCount int `json:"register_count"`
|
|
|
|
|
|
TrialEnabled int `json:"trial_enabled"`
|
|
|
|
|
|
TrialLimitTime int `json:"trial_limit_time"`
|
|
|
|
|
|
TrialDuration int `json:"trial_duration"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证UUID
|
|
|
|
|
|
if req.UUID == "" {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用UUID不能为空",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 验证UUID格式
|
2025-10-24 08:25:16 +08:00
|
|
|
|
if _, err := uuid.Parse(req.UUID); err != nil {
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithError(err).Error("Invalid UUID format")
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "无效的UUID格式",
|
2025-10-26 14:48:02 +08:00
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 查找应用
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("uuid = ?", req.UUID).First(&app).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find app")
|
|
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "应用不存在",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 更新注册配置
|
|
|
|
|
|
updates := map[string]interface{}{
|
|
|
|
|
|
"register_enabled": req.RegisterEnabled,
|
|
|
|
|
|
"register_limit_enabled": req.RegisterLimitEnabled,
|
|
|
|
|
|
"register_limit_time": req.RegisterLimitTime,
|
|
|
|
|
|
"register_count": req.RegisterCount,
|
|
|
|
|
|
"trial_enabled": req.TrialEnabled,
|
|
|
|
|
|
"trial_limit_time": req.TrialLimitTime,
|
|
|
|
|
|
"trial_duration": req.TrialDuration,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := db.Model(&app).Updates(updates).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to update app register config")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "更新注册配置失败",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
|
|
"app_uuid": req.UUID,
|
|
|
|
|
|
"app_name": app.Name,
|
2026-03-18 21:51:17 +08:00
|
|
|
|
}).Debug("App register config updated successfully")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "注册配置更新成功",
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// AppsBatchDeleteHandler 批量删除应用处理器
|
|
|
|
|
|
func AppsBatchDeleteHandler(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
IDs []uint `json:"ids"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if len(req.IDs) == 0 {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "请选择要删除的应用",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 开始事务
|
|
|
|
|
|
tx := db.Begin()
|
|
|
|
|
|
if tx.Error != nil {
|
|
|
|
|
|
logrus.WithError(tx.Error).Error("Failed to begin transaction")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "开始事务失败",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
defer func() {
|
|
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
}
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
// 首先获取要删除的应用的UUID列表
|
|
|
|
|
|
var apps []models.App
|
|
|
|
|
|
if err := tx.Where("id IN ?", req.IDs).Find(&apps).Error; err != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to find apps")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "查找应用失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提取UUID列表
|
|
|
|
|
|
var appUUIDs []string
|
|
|
|
|
|
for _, app := range apps {
|
|
|
|
|
|
appUUIDs = append(appUUIDs, app.UUID)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 删除这些应用的所有相关接口
|
|
|
|
|
|
if len(appUUIDs) > 0 {
|
2026-04-04 20:50:45 +08:00
|
|
|
|
// 检查是否有关联的变量
|
|
|
|
|
|
var varCount int64
|
|
|
|
|
|
if err := tx.Model(&models.Variable{}).Where("app_uuid IN ?", appUUIDs).Count(&varCount).Error; err != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to count related variables")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "检查关联变量失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if varCount > 0 {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "所选应用中存在关联变量,禁止删除",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否有关联的函数
|
|
|
|
|
|
var funcCount int64
|
|
|
|
|
|
if err := tx.Model(&models.Function{}).Where("app_uuid IN ?", appUUIDs).Count(&funcCount).Error; err != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to count related functions")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "检查关联函数失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if funcCount > 0 {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "所选应用中存在关联函数,禁止删除",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if err := tx.Where("app_uuid IN ?", appUUIDs).Delete(&models.API{}).Error; err != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to delete related APIs")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "删除相关接口失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
2025-10-24 08:25:16 +08:00
|
|
|
|
}
|
2025-10-26 14:48:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 批量删除应用
|
|
|
|
|
|
if err := tx.Delete(&models.App{}, req.IDs).Error; err != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to batch delete apps")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "批量删除失败",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 提交事务
|
|
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to commit transaction")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "提交事务失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
|
|
"app_ids": req.IDs,
|
|
|
|
|
|
"app_uuids": appUUIDs,
|
2026-03-18 21:51:17 +08:00
|
|
|
|
}).Debug("Successfully batch deleted apps and related APIs")
|
2025-10-26 14:48:02 +08:00
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "批量删除成功",
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// AppsBatchUpdateStatusHandler 批量更新应用状态处理器
|
|
|
|
|
|
func AppsBatchUpdateStatusHandler(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
IDs []uint `json:"ids"`
|
|
|
|
|
|
Status int `json:"status"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if len(req.IDs) == 0 {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "请选择要更新的应用",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
if req.Status != 0 && req.Status != 1 {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "状态值无效",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
2025-10-24 08:25:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
// 批量更新状态
|
|
|
|
|
|
if err := db.Model(&models.App{}).Where("id IN ?", req.IDs).Update("status", req.Status).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to batch update app status")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
2025-10-24 08:25:16 +08:00
|
|
|
|
"code": 1,
|
2025-10-26 14:48:02 +08:00
|
|
|
|
"msg": "批量更新状态失败",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
statusText := "禁用"
|
|
|
|
|
|
if req.Status == 1 {
|
|
|
|
|
|
statusText = "启用"
|
2025-10-24 08:25:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-26 14:48:02 +08:00
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "批量" + statusText + "成功",
|
|
|
|
|
|
})
|
2025-10-24 08:25:16 +08:00
|
|
|
|
}
|
2025-10-26 22:28:50 +08:00
|
|
|
|
|
|
|
|
|
|
// AppUpdateStatusHandler 更新单个应用状态处理器
|
|
|
|
|
|
func AppUpdateStatusHandler(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
ID uint `json:"id"`
|
|
|
|
|
|
Status int `json:"status"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if !appBaseController.BindJSON(c, &req) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if req.ID == 0 {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用ID不能为空",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if req.Status != 0 && req.Status != 1 {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "状态值无效",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查应用是否存在
|
|
|
|
|
|
var app models.App
|
|
|
|
|
|
if err := db.Where("id = ?", req.ID).First(&app).Error; err != nil {
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "应用不存在",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态
|
|
|
|
|
|
if err := db.Model(&app).Update("status", req.Status).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to update app status")
|
|
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
|
|
"code": 1,
|
|
|
|
|
|
"msg": "更新状态失败",
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
statusText := "禁用"
|
|
|
|
|
|
if req.Status == 1 {
|
|
|
|
|
|
statusText = "启用"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "应用" + statusText + "成功",
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-10-27 21:06:41 +08:00
|
|
|
|
|
|
|
|
|
|
// AppsSimpleListHandler 简化应用列表API处理器(用于下拉框选择等场景)
|
|
|
|
|
|
func AppsSimpleListHandler(c *gin.Context) {
|
|
|
|
|
|
// 获取数据库连接
|
|
|
|
|
|
db, ok := appBaseController.GetDB(c)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查询所有启用的应用,只获取必要字段
|
|
|
|
|
|
var apps []struct {
|
|
|
|
|
|
ID uint `json:"id"`
|
|
|
|
|
|
UUID string `json:"uuid"`
|
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := db.Model(&models.App{}).
|
|
|
|
|
|
Select("id, uuid, name").
|
|
|
|
|
|
Where("status = ?", 1). // 只获取启用的应用
|
|
|
|
|
|
Order("name ASC").
|
|
|
|
|
|
Find(&apps).Error; err != nil {
|
|
|
|
|
|
logrus.WithError(err).Error("Failed to query simple apps list")
|
|
|
|
|
|
appBaseController.HandleInternalError(c, "获取应用列表失败", err)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 返回结果
|
|
|
|
|
|
response := gin.H{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"msg": "success",
|
|
|
|
|
|
"data": apps,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
|
|
|
|
}
|