Add classification annotations

This commit is contained in:
2025-10-27 23:12:15 +08:00
parent 3990ec01c6
commit 5aacb88c22
44 changed files with 2769 additions and 2241 deletions

View File

@@ -13,9 +13,17 @@ import (
"github.com/sirupsen/logrus"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建基础控制器实例
var apiBaseController = controllers.NewBaseController()
// ============================================================================
// 页面处理器
// ============================================================================
// APIFragmentHandler 接口列表页面片段处理器
func APIFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "apis.html", gin.H{
@@ -23,6 +31,10 @@ func APIFragmentHandler(c *gin.Context) {
})
}
// ============================================================================
// API处理器
// ============================================================================
// APIListHandler 接口列表API处理器
func APIListHandler(c *gin.Context) {
// 获取分页参数
@@ -142,6 +154,10 @@ func APIListHandler(c *gin.Context) {
c.JSON(http.StatusOK, response)
}
// ============================================================================
// 辅助函数
// ============================================================================
// getAPIStatusName 获取API状态名称
func getAPIStatusName(status int) string {
switch status {
@@ -238,7 +254,7 @@ func APIGetTypesHandler(c *gin.Context) {
validTypes := []int{
models.APITypeGetBulletin, models.APITypeGetUpdateUrl, models.APITypeCheckAppVersion, models.APITypeGetCardInfo,
models.APITypeSingleLogin,
models.APITypeUserLogin, models.APITypeUserRegin, models.APITypeUserRecharge, models.APITypeCardRegin,
models.APITypeUserLogin, models.APITypeUserRegin, models.APITypeUserRecharge,
models.APITypeLogOut,
models.APITypeGetExpired, models.APITypeCheckUserStatus, models.APITypeGetAppData, models.APITypeGetVariable,
models.APITypeUpdatePwd, models.APITypeMacChangeBind, models.APITypeIPChangeBind,

View File

@@ -15,8 +15,16 @@ import (
"github.com/sirupsen/logrus"
)
// ============================================================================
// 全局变量
// ============================================================================
var appBaseController = controllers.NewBaseController()
// ============================================================================
// 页面处理器
// ============================================================================
// AppsFragmentHandler 应用列表页面片段处理器
func AppsFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "apps.html", gin.H{
@@ -24,6 +32,10 @@ func AppsFragmentHandler(c *gin.Context) {
})
}
// ============================================================================
// API处理器
// ============================================================================
// AppsListHandler 应用列表API处理器
func AppsListHandler(c *gin.Context) {
// 获取分页参数
@@ -338,28 +350,7 @@ 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.APITypeUserDeductedTime, // 扣除时间
}
defaultAPITypes := models.GetDefaultAPITypes()
// 批量创建默认接口
for _, apiType := range defaultAPITypes {

View File

@@ -16,9 +16,17 @@ import (
"github.com/spf13/viper"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建BaseController实例
var authBaseController = controllers.NewBaseController()
// ============================================================================
// 页面处理器
// ============================================================================
// LoginPageHandler 管理员登录页渲染处理器
// - 如果已登录则重定向到 /admin
// - 否则渲染 web/template/admin/login.html 模板
@@ -63,6 +71,10 @@ func LoginPageHandler(c *gin.Context) {
c.HTML(http.StatusOK, "login.html", data)
}
// ============================================================================
// API处理器
// ============================================================================
// LoginHandler 管理员登录接口
// - 接收JSON: {username, password}
// - 验证用户存在与密码正确性
@@ -74,11 +86,11 @@ func LoginHandler(c *gin.Context) {
Password string `json:"password"`
Captcha string `json:"captcha"`
}
if !authBaseController.BindJSON(c, &body) {
return
}
if !authBaseController.ValidateRequired(c, map[string]interface{}{
"用户名": body.Username,
"密码": body.Password,
@@ -178,7 +190,11 @@ func LogoutHandler(c *gin.Context) {
})
}
// clearInvalidJWTCookie 清理失效的JWT Cookie
// ============================================================================
// 辅助函数
// ============================================================================
// clearInvalidJWTCookie 清理无效的JWT Cookie
// - 统一的Cookie清理函数确保一致性
// - 在JWT校验失败时自动调用提升安全性和用户体验
func clearInvalidJWTCookie(c *gin.Context) {
@@ -192,7 +208,11 @@ func getJWTSecret() []byte {
return []byte(viper.GetString("security.jwt_secret"))
}
// JWTClaims JWT载荷结构
// ============================================================================
// 结构体定义
// ============================================================================
// JWTClaims JWT载荷结构体
type JWTClaims struct {
Username string `json:"username"`
PasswordHash string `json:"password_hash"` // 密码哈希摘要,用于验证密码是否被修改

View File

@@ -15,12 +15,20 @@ import (
"github.com/mojocn/base64Captcha"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建基础控制器实例
var captchaBaseController = controllers.NewBaseController()
// 全局验证码存储器
var store = base64Captcha.DefaultMemStore
// ============================================================================
// 辅助函数
// ============================================================================
// secureRandomInt 生成安全的随机整数,范围 [0, max)
func secureRandomInt(max int) (int, error) {
n, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
@@ -30,6 +38,10 @@ func secureRandomInt(max int) (int, error) {
return int(n.Int64()), nil
}
// ============================================================================
// API处理器
// ============================================================================
// CaptchaHandler 生成验证码图片
// GET /admin/captcha - 返回验证码图片
func CaptchaHandler(c *gin.Context) {
@@ -87,8 +99,6 @@ func CaptchaHandler(c *gin.Context) {
c.Data(http.StatusOK, "image/png", imgData)
}
// VerifyCaptcha 验证验证码
// 这个函数将在登录处理中被调用
// 支持大小写不敏感匹配
@@ -97,7 +107,7 @@ func VerifyCaptcha(c *gin.Context, captchaValue string) bool {
if middleware.ShouldSkipCaptcha(c) {
return true
}
// 从cookie中获取验证码ID
captchaId, err := c.Cookie("captcha_id")
if err != nil {

View File

@@ -12,9 +12,17 @@ import (
"github.com/sirupsen/logrus"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建基础控制器实例
var functionBaseController = controllers.NewBaseController()
// ============================================================================
// 页面处理器
// ============================================================================
// FunctionFragmentHandler 公共函数列表页面片段处理器
func FunctionFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "functions.html", gin.H{
@@ -22,6 +30,10 @@ func FunctionFragmentHandler(c *gin.Context) {
})
}
// ============================================================================
// API处理器
// ============================================================================
// FunctionListHandler 函数列表API处理器
func FunctionListHandler(c *gin.Context) {
// 获取分页参数
@@ -321,4 +333,4 @@ func FunctionsBatchDeleteHandler(c *gin.Context) {
logrus.WithField("function_ids", req.IDs).Info("Successfully batch deleted functions")
functionBaseController.HandleSuccess(c, "批量删除成功", nil)
}
}

View File

@@ -14,9 +14,17 @@ import (
"github.com/spf13/viper"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建基础控制器实例
var handlersBaseController = controllers.NewBaseController()
// ============================================================================
// 辅助函数
// ============================================================================
// formatDBType 格式化数据库类型显示
// 将配置文件中的小写类型转换为友好的显示格式
func formatDBType(dbType string) string {
@@ -34,6 +42,10 @@ func formatDBType(dbType string) string {
}
}
// ============================================================================
// 页面处理器
// ============================================================================
// AdminIndexHandler 后台首页处理器/admin 与 /admin/ 根路径入口
// - 未登录:重定向到 /admin/login
// - 已登录:渲染后台布局页(或重定向到 /admin/layout
@@ -107,6 +119,10 @@ func DashboardFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "dashboard.html", data)
}
// ============================================================================
// API处理器
// ============================================================================
// SystemInfoHandler 系统信息API接口
// - 返回系统运行状态的JSON数据用于前端定时刷新
func SystemInfoHandler(c *gin.Context) {

View File

@@ -1,134 +1,146 @@
package admin
import (
"context"
"fmt"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"net/http"
"networkDev/controllers"
"networkDev/models"
"networkDev/services"
"networkDev/utils"
)
// 创建基础控制器实例
var settingsBaseController = controllers.NewBaseController()
// SettingsFragmentHandler 设置片段渲染
// - 渲染设置表单通过前端JS调用API加载/保存)
func SettingsFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "settings.html", gin.H{})
}
// SettingsQueryHandler 设置查询API
// - 返回所有设置项的 name:value 映射
func SettingsQueryHandler(c *gin.Context) {
db, ok := settingsBaseController.GetDB(c)
if !ok {
return
}
var list []models.Settings
if err := db.Find(&list).Error; err != nil {
settingsBaseController.HandleInternalError(c, "查询失败", err)
return
}
res := map[string]string{}
for _, s := range list {
res[s.Name] = s.Value
}
settingsBaseController.HandleSuccess(c, "ok", res)
}
// SettingsUpdateHandler 更新系统设置处理器
// - 接收JSON格式的设置数据支持两种格式
// 1. 直接字段格式: {"site_title": "值", "site_keywords": "值"}
// 2. 嵌套格式: {"settings": {"site_title": "值", "site_keywords": "值"}}
//
// - 自动创建不存在的设置项
// - 更新已存在的设置项
// - 更新完成后:
// 1. 删除对应的Redis缓存键确保后续读取走数据库并重建缓存
// 2. 刷新SettingsService内存缓存
func SettingsUpdateHandler(c *gin.Context) {
// 先尝试解析为直接字段格式
var directBody map[string]interface{}
if !settingsBaseController.BindJSON(c, &directBody) {
return
}
// 提取设置数据
var settingsData map[string]string
// 检查是否为嵌套格式包含settings字段
if settings, exists := directBody["settings"]; exists {
if settingsMap, ok := settings.(map[string]interface{}); ok {
settingsData = make(map[string]string)
for k, v := range settingsMap {
if str, ok := v.(string); ok {
settingsData[k] = str
}
}
} else {
settingsBaseController.HandleValidationError(c, "settings字段格式错误")
return
}
} else {
// 直接字段格式
settingsData = make(map[string]string)
for k, v := range directBody {
if str, ok := v.(string); ok {
settingsData[k] = str
} else if v != nil {
// 转换其他类型为字符串
settingsData[k] = fmt.Sprintf("%v", v)
}
}
}
if len(settingsData) == 0 {
settingsBaseController.HandleValidationError(c, "无设置项")
return
}
db, ok := settingsBaseController.GetDB(c)
if !ok {
return
}
// 记录需要失效的缓存键统一删除减少与Redis交互次数
keysToDel := make([]string, 0, len(settingsData))
// 批量处理设置项
for k, v := range settingsData {
var s models.Settings
if err := db.Where("name = ?", k).First(&s).Error; err != nil {
// 不存在则创建
s = models.Settings{Name: k, Value: v}
if err := db.Create(&s).Error; err != nil {
logrus.WithError(err).WithField("setting_name", k).Error("创建设置失败")
settingsBaseController.HandleInternalError(c, fmt.Sprintf("保存设置 %s 失败", k), err)
return
}
} else {
// 存在则更新
if err := db.Model(&models.Settings{}).Where("id = ?", s.ID).Update("value", v).Error; err != nil {
logrus.WithError(err).WithField("setting_name", k).Error("更新设置失败")
settingsBaseController.HandleInternalError(c, fmt.Sprintf("更新设置 %s 失败", k), err)
return
}
}
// 收集对应的Redis缓存键与services/query.go中的键命名保持一致
keysToDel = append(keysToDel, fmt.Sprintf("setting:%s", k))
}
// 删除Redis缓存键如果Redis不可用则静默跳过
_ = utils.RedisDel(context.Background(), keysToDel...)
// 刷新内存中的设置缓存,保证后续读取一致
services.GetSettingsService().RefreshCache()
settingsBaseController.HandleSuccess(c, "保存成功", nil)
}
package admin
import (
"context"
"fmt"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"net/http"
"networkDev/controllers"
"networkDev/models"
"networkDev/services"
"networkDev/utils"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建基础控制器实例
var settingsBaseController = controllers.NewBaseController()
// ============================================================================
// 页面处理器
// ============================================================================
// SettingsFragmentHandler 设置片段渲染
// - 渲染设置表单通过前端JS调用API加载/保存)
func SettingsFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "settings.html", gin.H{})
}
// ============================================================================
// API处理器
// ============================================================================
// SettingsQueryHandler 设置查询API
// - 返回所有设置项的 name:value 映射
func SettingsQueryHandler(c *gin.Context) {
db, ok := settingsBaseController.GetDB(c)
if !ok {
return
}
var list []models.Settings
if err := db.Find(&list).Error; err != nil {
settingsBaseController.HandleInternalError(c, "查询失败", err)
return
}
res := map[string]string{}
for _, s := range list {
res[s.Name] = s.Value
}
settingsBaseController.HandleSuccess(c, "ok", res)
}
// SettingsUpdateHandler 更新系统设置处理器
// - 接收JSON格式的设置数据支持两种格式
// 1. 直接字段格式: {"site_title": "值", "site_keywords": "值"}
// 2. 嵌套格式: {"settings": {"site_title": "值", "site_keywords": "值"}}
//
// - 自动创建不存在的设置项
// - 更新已存在的设置项
// - 更新完成后:
// 1. 删除对应的Redis缓存键确保后续读取走数据库并重建缓存
// 2. 刷新SettingsService内存缓存
func SettingsUpdateHandler(c *gin.Context) {
// 先尝试解析为直接字段格式
var directBody map[string]interface{}
if !settingsBaseController.BindJSON(c, &directBody) {
return
}
// 提取设置数据
var settingsData map[string]string
// 检查是否为嵌套格式包含settings字段
if settings, exists := directBody["settings"]; exists {
if settingsMap, ok := settings.(map[string]interface{}); ok {
settingsData = make(map[string]string)
for k, v := range settingsMap {
if str, ok := v.(string); ok {
settingsData[k] = str
}
}
} else {
settingsBaseController.HandleValidationError(c, "settings字段格式错误")
return
}
} else {
// 直接字段格式
settingsData = make(map[string]string)
for k, v := range directBody {
if str, ok := v.(string); ok {
settingsData[k] = str
} else if v != nil {
// 转换其他类型为字符串
settingsData[k] = fmt.Sprintf("%v", v)
}
}
}
if len(settingsData) == 0 {
settingsBaseController.HandleValidationError(c, "无设置项")
return
}
db, ok := settingsBaseController.GetDB(c)
if !ok {
return
}
// 记录需要失效的缓存键统一删除减少与Redis交互次数
keysToDel := make([]string, 0, len(settingsData))
// 批量处理设置项
for k, v := range settingsData {
var s models.Settings
if err := db.Where("name = ?", k).First(&s).Error; err != nil {
// 不存在则创建
s = models.Settings{Name: k, Value: v}
if err := db.Create(&s).Error; err != nil {
logrus.WithError(err).WithField("setting_name", k).Error("创建设置失败")
settingsBaseController.HandleInternalError(c, fmt.Sprintf("保存设置 %s 失败", k), err)
return
}
} else {
// 存在则更新
if err := db.Model(&models.Settings{}).Where("id = ?", s.ID).Update("value", v).Error; err != nil {
logrus.WithError(err).WithField("setting_name", k).Error("更新设置失败")
settingsBaseController.HandleInternalError(c, fmt.Sprintf("更新设置 %s 失败", k), err)
return
}
}
// 收集对应的Redis缓存键与services/query.go中的键命名保持一致
keysToDel = append(keysToDel, fmt.Sprintf("setting:%s", k))
}
// 删除Redis缓存键如果Redis不可用则静默跳过
_ = utils.RedisDel(context.Background(), keysToDel...)
// 刷新内存中的设置缓存,保证后续读取一致
services.GetSettingsService().RefreshCache()
settingsBaseController.HandleSuccess(c, "保存成功", nil)
}

View File

@@ -10,15 +10,27 @@ import (
"github.com/gin-gonic/gin"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建基础控制器实例
var baseController = controllers.NewBaseController()
// ============================================================================
// 页面处理器
// ============================================================================
// UserFragmentHandler 个人资料片段渲染
// - 渲染个人资料与修改密码表单
func UserFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "user.html", gin.H{})
}
// ============================================================================
// API处理器
// ============================================================================
// UserProfileQueryHandler 获取当前登录管理员的用户名
// - 返回 JSON: {username}
// - 直接从JWT获取用户名信息
@@ -51,20 +63,20 @@ func UserPasswordUpdateHandler(c *gin.Context) {
NewPassword string `json:"new_password"`
ConfirmPassword string `json:"confirm_password"`
}
if !baseController.BindJSON(c, &body) {
return
}
// 基础校验
if !baseController.ValidateRequired(c, map[string]interface{}{
"旧密码": body.OldPassword,
"新密码": body.NewPassword,
"旧密码": body.OldPassword,
"新密码": body.NewPassword,
"确认密码": body.ConfirmPassword,
}) {
return
}
if len(body.NewPassword) < 6 {
baseController.HandleValidationError(c, "新密码长度不能少于6位")
return
@@ -253,7 +265,7 @@ func UserProfileUpdateHandler(c *gin.Context) {
// 重新签发JWT并写入Cookie
// 创建虚拟用户对象用于生成JWT令牌
adminUser := models.User{
Username: username, // 使用新的用户名
Username: username, // 使用新的用户名
Password: adminPassword,
PasswordSalt: adminPasswordSalt,
}

View File

@@ -12,9 +12,17 @@ import (
"github.com/sirupsen/logrus"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建基础控制器实例
var variableBaseController = controllers.NewBaseController()
// ============================================================================
// 页面处理器
// ============================================================================
// VariableFragmentHandler 公共变量列表页面片段处理器
func VariableFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "variables.html", gin.H{
@@ -22,6 +30,10 @@ func VariableFragmentHandler(c *gin.Context) {
})
}
// ============================================================================
// API处理器
// ============================================================================
// VariableListHandler 变量列表API处理器
func VariableListHandler(c *gin.Context) {
// 获取分页参数

View File

@@ -10,14 +10,26 @@ import (
"gorm.io/gorm"
)
// ============================================================================
// 结构体定义
// ============================================================================
// BaseController 基础控制器结构体
type BaseController struct{}
// ============================================================================
// 构造函数
// ============================================================================
// NewBaseController 创建基础控制器实例
func NewBaseController() *BaseController {
return &BaseController{}
}
// ============================================================================
// 数据库相关方法
// ============================================================================
// GetDB 获取数据库连接,统一错误处理
func (bc *BaseController) GetDB(c *gin.Context) (*gorm.DB, bool) {
db, err := database.GetDB()
@@ -28,6 +40,10 @@ func (bc *BaseController) GetDB(c *gin.Context) (*gorm.DB, bool) {
return db, true
}
// ============================================================================
// 错误处理方法
// ============================================================================
// HandleDatabaseError 统一处理数据库连接错误
func (bc *BaseController) HandleDatabaseError(c *gin.Context, err error) {
c.JSON(http.StatusInternalServerError, gin.H{
@@ -64,6 +80,10 @@ func (bc *BaseController) HandleInternalError(c *gin.Context, message string, er
})
}
// ============================================================================
// 成功响应方法
// ============================================================================
// HandleSuccess 统一处理成功响应
func (bc *BaseController) HandleSuccess(c *gin.Context, message string, data interface{}) {
c.JSON(http.StatusOK, gin.H{
@@ -82,6 +102,10 @@ func (bc *BaseController) HandleCreated(c *gin.Context, message string, data int
})
}
// ============================================================================
// 辅助方法
// ============================================================================
// ValidateRequired 验证必填字段
func (bc *BaseController) ValidateRequired(c *gin.Context, fields map[string]interface{}) bool {
for fieldName, fieldValue := range fields {

View File

@@ -10,8 +10,16 @@ import (
"gorm.io/gorm"
)
// ============================================================================
// 全局变量
// ============================================================================
var homeBaseController = controllers.NewBaseController()
// ============================================================================
// 辅助函数
// ============================================================================
// getSettingValue 获取配置值,优先从数据库获取,不存在时使用默认值
func getSettingValue(settingName string, defaultValue string, db *gorm.DB) string {
if setting, err := services.FindSettingByName(settingName, db); err == nil {
@@ -20,6 +28,10 @@ func getSettingValue(settingName string, defaultValue string, db *gorm.DB) strin
return defaultValue
}
// ============================================================================
// 页面处理器
// ============================================================================
// RootHandler 主页处理器
func RootHandler(c *gin.Context) {
// 获取数据库连接