The development mode supports hot reloading of templates

This commit is contained in:
2025-10-26 22:28:50 +08:00
parent a20368a39b
commit edff1bb839
13 changed files with 387 additions and 80 deletions

View File

@@ -274,6 +274,55 @@ func APIGetTypesHandler(c *gin.Context) {
apiBaseController.HandleSuccess(c, "获取接口类型列表成功", apiTypes)
}
// APIUpdateStatusHandler 更新单个接口状态处理器
func APIUpdateStatusHandler(c *gin.Context) {
var req struct {
ID uint `json:"id"`
Status int `json:"status"`
}
if !apiBaseController.BindJSON(c, &req) {
return
}
if req.ID == 0 {
apiBaseController.HandleValidationError(c, "接口ID不能为空")
return
}
if req.Status != 0 && req.Status != 1 {
apiBaseController.HandleValidationError(c, "状态值无效")
return
}
// 获取数据库连接
db, ok := apiBaseController.GetDB(c)
if !ok {
return
}
// 检查接口是否存在
var api models.API
if err := db.Where("id = ?", req.ID).First(&api).Error; err != nil {
apiBaseController.HandleValidationError(c, "接口不存在")
return
}
// 更新状态
if err := db.Model(&api).Update("status", req.Status).Error; err != nil {
logrus.WithError(err).Error("Failed to update API status")
apiBaseController.HandleInternalError(c, "更新状态失败", err)
return
}
statusText := "禁用"
if req.Status == 1 {
statusText = "启用"
}
apiBaseController.HandleSuccess(c, "接口"+statusText+"成功", nil)
}
func APIGenerateKeysHandler(c *gin.Context) {
var req struct {
Side string `json:"side"` // submit | return

View File

@@ -339,25 +339,25 @@ func AppCreateHandler(c *gin.Context) {
// 为应用创建所有默认接口
defaultAPITypes := []int{
models.APITypeGetBulletin, // 获取程序公告
models.APITypeGetUpdateUrl, // 获取更新地址
models.APITypeCheckAppVersion, // 检测最新版本
models.APITypeGetCardInfo, // 获取卡密信息
models.APITypeSingleLogin, // 卡密登录
models.APITypeUserLogin, // 用户登录
models.APITypeUserRegin, // 用户注册
models.APITypeUserRecharge, // 用户充值
models.APITypeCardRegin, // 卡密注册
models.APITypeLogOut, // 退出登录
models.APITypeGetExpired, // 获取到期时间
models.APITypeCheckUserStatus, // 检测账号状态
models.APITypeGetAppData, // 获取程序数据
models.APITypeGetVariable, // 获取变量数据
models.APITypeUpdatePwd, // 修改账号密码
models.APITypeMacChangeBind, // 机器码转绑
models.APITypeIPChangeBind, // IP转绑
models.APITypeDisableUser, // 封停用户
models.APITypeBlackUser, // 添加黑名单
models.APITypeGetBulletin, // 获取程序公告
models.APITypeGetUpdateUrl, // 获取更新地址
models.APITypeCheckAppVersion, // 检测最新版本
models.APITypeGetCardInfo, // 获取卡密信息
models.APITypeSingleLogin, // 卡密登录
models.APITypeUserLogin, // 用户登录
models.APITypeUserRegin, // 用户注册
models.APITypeUserRecharge, // 用户充值
models.APITypeCardRegin, // 卡密注册
models.APITypeLogOut, // 退出登录
models.APITypeGetExpired, // 获取到期时间
models.APITypeCheckUserStatus, // 检测账号状态
models.APITypeGetAppData, // 获取程序数据
models.APITypeGetVariable, // 获取变量数据
models.APITypeUpdatePwd, // 修改账号密码
models.APITypeMacChangeBind, // 机器码转绑
models.APITypeIPChangeBind, // IP转绑
models.APITypeDisableUser, // 封停用户
models.APITypeBlackUser, // 添加黑名单
models.APITypeUserDeductedTime, // 扣除时间
}
@@ -366,7 +366,7 @@ func AppCreateHandler(c *gin.Context) {
api := models.API{
APIType: apiType,
AppUUID: app.UUID,
Status: 1, // 默认
Status: 0, // 默认
SubmitAlgorithm: models.AlgorithmNone, // 默认不加密
ReturnAlgorithm: models.AlgorithmNone, // 默认不加密
}
@@ -928,18 +928,18 @@ func AppGetBindConfigHandler(c *gin.Context) {
"code": 0,
"msg": "获取绑定配置成功",
"data": gin.H{
"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,
"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,
},
})
}
@@ -948,19 +948,19 @@ func AppGetBindConfigHandler(c *gin.Context) {
func AppUpdateBindConfigHandler(c *gin.Context) {
// 解析请求体
var req struct {
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"`
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"`
}
if !appBaseController.BindJSON(c, &req) {
@@ -1005,18 +1005,18 @@ func AppUpdateBindConfigHandler(c *gin.Context) {
// 更新绑定配置
updates := map[string]interface{}{
"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,
"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,
}
if err := db.Model(&app).Updates(updates).Error; err != nil {
@@ -1334,3 +1334,67 @@ func AppsBatchUpdateStatusHandler(c *gin.Context) {
"msg": "批量" + statusText + "成功",
})
}
// 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 + "成功",
})
}

View File

@@ -9,10 +9,10 @@ import (
"github.com/gin-gonic/gin"
"networkDev/controllers"
"networkDev/middleware"
"networkDev/utils"
"github.com/mojocn/base64Captcha"
"github.com/spf13/viper"
)
// 创建基础控制器实例
@@ -94,7 +94,7 @@ func CaptchaHandler(c *gin.Context) {
// 支持大小写不敏感匹配
func VerifyCaptcha(c *gin.Context, captchaValue string) bool {
// 检查是否为开发模式,如果是则跳过验证码验证
if viper.GetBool("server.dev_mode") {
if middleware.ShouldSkipCaptcha(c) {
return true
}

View File

@@ -4,6 +4,7 @@ import (
"net/http"
"networkDev/constants"
"networkDev/controllers"
"networkDev/middleware"
"networkDev/models"
"networkDev/services"
"networkDev/utils"
@@ -97,7 +98,7 @@ func AdminLayoutHandler(c *gin.Context) {
// - 展示系统信息:版本、开发模式、数据库类型、启动时长
func DashboardFragmentHandler(c *gin.Context) {
version := constants.AppVersion
mode := viper.GetBool("server.dev_mode")
mode := middleware.IsDevModeFromContext(c)
dbType := viper.GetString("database.type")
if dbType == "" {
dbType = "sqlite"
@@ -118,7 +119,7 @@ func DashboardFragmentHandler(c *gin.Context) {
// - 返回系统运行状态的JSON数据用于前端定时刷新
func SystemInfoHandler(c *gin.Context) {
version := constants.AppVersion
mode := viper.GetBool("server.dev_mode")
mode := middleware.IsDevModeFromContext(c)
dbType := viper.GetString("database.type")
if dbType == "" {
dbType = "sqlite"