diff --git a/controllers/admin/api.go b/controllers/admin/api.go index 62c6d73..09c88e3 100644 --- a/controllers/admin/api.go +++ b/controllers/admin/api.go @@ -1,11 +1,12 @@ package admin import ( - "encoding/hex" - "net/http" "NetworkAuth/controllers" "NetworkAuth/models" + "NetworkAuth/services" "NetworkAuth/utils/encrypt" + "encoding/hex" + "net/http" "strconv" "strings" @@ -38,14 +39,7 @@ func APIFragmentHandler(c *gin.Context) { // APIListHandler 接口列表API处理器 func APIListHandler(c *gin.Context) { // 获取分页参数 - page, _ := strconv.Atoi(c.Query("page")) - if page <= 0 { - page = 1 - } - limit, _ := strconv.Atoi(c.Query("limit")) - if limit <= 0 { - limit = 10 - } + page, limit := apiBaseController.GetPaginationParams(c) // 获取应用UUID参数(用于按应用筛选接口) appUUID := strings.TrimSpace(c.Query("app_uuid")) @@ -76,18 +70,9 @@ func APIListHandler(c *gin.Context) { query = query.Where("api_type = ?", apiType) } - // 获取总数 - var total int64 - if err := query.Count(&total).Error; err != nil { - logrus.WithError(err).Error("Failed to count APIs") - apiBaseController.HandleInternalError(c, "获取接口总数失败", err) - return - } - - // 获取分页数据 - var apis []models.API - offset := (page - 1) * limit - if err := query.Offset(offset).Limit(limit).Order("created_at DESC").Find(&apis).Error; err != nil { + // 泛型分页查询 + apis, total, err := services.Paginate[models.API](query, page, limit, "created_at DESC") + if err != nil { logrus.WithError(err).Error("Failed to fetch APIs") apiBaseController.HandleInternalError(c, "获取接口列表失败", err) return diff --git a/controllers/admin/app.go b/controllers/admin/app.go index ca915d4..3427501 100644 --- a/controllers/admin/app.go +++ b/controllers/admin/app.go @@ -8,7 +8,6 @@ import ( "encoding/base64" "encoding/hex" "net/http" - "strconv" "strings" "github.com/gin-gonic/gin" @@ -40,14 +39,7 @@ func AppsFragmentHandler(c *gin.Context) { // AppsListHandler 应用列表API处理器 func AppsListHandler(c *gin.Context) { // 获取分页参数 - page, _ := strconv.Atoi(c.Query("page")) - if page <= 0 { - page = 1 - } - limit, _ := strconv.Atoi(c.Query("limit")) - if limit <= 0 { - limit = 10 - } + page, limit := appBaseController.GetPaginationParams(c) // 获取搜索参数 search := strings.TrimSpace(c.Query("search")) @@ -58,9 +50,6 @@ func AppsListHandler(c *gin.Context) { return } - var apps []models.App - var total int64 - query := db.Model(&models.App{}) // 如果有搜索条件 @@ -69,16 +58,9 @@ func AppsListHandler(c *gin.Context) { query = query.Where("name = ? OR uuid = ?", search, search) } - // 获取总数 - if err := query.Count(&total).Error; err != nil { - logrus.WithError(err).Error("Failed to count apps") - appBaseController.HandleInternalError(c, "获取应用总数失败", err) - return - } - - // 分页查询 - offset := (page - 1) * limit - if err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&apps).Error; err != nil { + // 泛型分页查询 + apps, total, err := services.Paginate[models.App](query, page, limit, "created_at DESC") + if err != nil { logrus.WithError(err).Error("Failed to query apps") appBaseController.HandleInternalError(c, "查询应用列表失败", err) return diff --git a/controllers/admin/dashboard.go b/controllers/admin/dashboard.go index e9bf60d..a542e7e 100644 --- a/controllers/admin/dashboard.go +++ b/controllers/admin/dashboard.go @@ -9,7 +9,6 @@ import ( "NetworkAuth/utils" "NetworkAuth/utils/timeutil" "net/http" - "strconv" "github.com/gin-gonic/gin" "github.com/spf13/viper" @@ -199,17 +198,7 @@ func DashboardLoginLogsHandler(c *gin.Context) { } // 获取分页参数 - pageStr := c.DefaultQuery("page", "1") - limitStr := c.DefaultQuery("limit", "10") - page, _ := strconv.Atoi(pageStr) - limit, _ := strconv.Atoi(limitStr) - if page < 1 { - page = 1 - } - if limit < 1 || limit > 100 { - limit = 10 - } - offset := (page - 1) * limit + page, limit := handlersBaseController.GetPaginationParams(c) // 获取当前管理员信息(可能是 username 或 admin_username,具体取决于认证中间件设置的 key) username := c.GetString("admin_username") @@ -217,7 +206,7 @@ func DashboardLoginLogsHandler(c *gin.Context) { // 尝试获取其他可能的键名 username = c.GetString("username") } - + var total int64 query := db.Model(&models.LoginLog{}).Where("type = ?", "admin") @@ -226,14 +215,9 @@ func DashboardLoginLogsHandler(c *gin.Context) { query = query.Where("username = ?", username) } - if err := query.Count(&total).Error; err != nil { - handlersBaseController.HandleInternalError(c, "获取登录日志总数失败", err) - return - } - - var logs []models.LoginLog - if err := query.Order("created_at desc").Offset(offset).Limit(limit).Find(&logs).Error; err != nil { - handlersBaseController.HandleInternalError(c, "获取登录日志列表失败", err) + logs, total, err := services.Paginate[models.LoginLog](query, page, limit, "created_at desc") + if err != nil { + handlersBaseController.HandleInternalError(c, "获取登录日志失败", err) return } @@ -243,4 +227,3 @@ func DashboardLoginLogsHandler(c *gin.Context) { } handlersBaseController.HandleSuccess(c, "获取登录日志成功", data) } - diff --git a/controllers/admin/function.go b/controllers/admin/function.go index a5db9f6..88517ab 100644 --- a/controllers/admin/function.go +++ b/controllers/admin/function.go @@ -38,18 +38,7 @@ func FunctionFragmentHandler(c *gin.Context) { // FunctionListHandler 函数列表API处理器 func FunctionListHandler(c *gin.Context) { // 获取分页参数 - page, _ := strconv.Atoi(c.Query("page")) - if page <= 0 { - page = 1 - } - limit, _ := strconv.Atoi(c.Query("limit")) - // 兼容前端使用的page_size参数 - if limit <= 0 { - limit, _ = strconv.Atoi(c.Query("page_size")) - } - if limit <= 0 { - limit = 10 - } + page, limit := functionBaseController.GetPaginationParams(c) // 获取搜索关键词参数(支持编号、别名、代码的综合搜索) search := strings.TrimSpace(c.Query("search")) @@ -83,18 +72,9 @@ func FunctionListHandler(c *gin.Context) { query = query.Where("app_uuid = ?", appUUID) } - // 获取总数 - var total int64 - if err := query.Count(&total).Error; err != nil { - logrus.WithError(err).Error("Failed to count functions") - functionBaseController.HandleInternalError(c, "查询函数总数失败", err) - return - } - - // 获取分页数据 - var functions []models.Function - offset := (page - 1) * limit - if err := query.Offset(offset).Limit(limit).Order("created_at DESC").Find(&functions).Error; err != nil { + // 泛型分页查询 + functions, total, err := services.Paginate[models.Function](query, page, limit, "created_at DESC") + if err != nil { logrus.WithError(err).Error("Failed to fetch functions") functionBaseController.HandleInternalError(c, "查询函数列表失败", err) return @@ -128,14 +108,13 @@ func FunctionListHandler(c *gin.Context) { }) } - response := gin.H{ + // 返回结果 (LayUI table format) + c.JSON(http.StatusOK, gin.H{ "code": 0, - "msg": "success", + "msg": "", "count": total, "data": responseData, - } - - c.JSON(http.StatusOK, response) + }) } // FunctionCreateHandler 新增函数API处理器 diff --git a/controllers/admin/login_log.go b/controllers/admin/login_log.go index 36b8f60..cc00382 100644 --- a/controllers/admin/login_log.go +++ b/controllers/admin/login_log.go @@ -3,6 +3,7 @@ package admin import ( "NetworkAuth/controllers" "NetworkAuth/models" + "NetworkAuth/services" "net/http" "strconv" "strings" @@ -58,14 +59,7 @@ func LoginLogsFragmentHandler(c *gin.Context) { // LoginLogsListHandler 登录日志列表API处理器 func LoginLogsListHandler(c *gin.Context) { // 获取分页参数 - page, _ := strconv.Atoi(c.Query("page")) - if page <= 0 { - page = 1 - } - limit, _ := strconv.Atoi(c.Query("limit")) - if limit <= 0 { - limit = 10 - } + page, limit := loginLogBaseController.GetPaginationParams(c) // 构建查询 db, ok := loginLogBaseController.GetDB(c) @@ -73,9 +67,6 @@ func LoginLogsListHandler(c *gin.Context) { return } - var logs []models.LoginLog - var total int64 - // 兼容旧数据(Type为空)和新数据(Type=admin) query := db.Model(&models.LoginLog{}).Where("type = ? OR type = ? OR type IS NULL", "admin", "") @@ -97,21 +88,11 @@ func LoginLogsListHandler(c *gin.Context) { } // 筛选条件:时间范围 - startTime := strings.TrimSpace(c.Query("start_time")) - endTime := strings.TrimSpace(c.Query("end_time")) - if startTime != "" && endTime != "" { - query = query.Where("created_at BETWEEN ? AND ?", startTime, endTime) - } + query = loginLogBaseController.ApplyTimeRangeQuery(c, query, "created_at") - // 统计总数 - if err := query.Count(&total).Error; err != nil { - loginLogBaseController.HandleInternalError(c, "获取日志总数失败", err) - return - } - - // 查询数据(时间倒序,从新到旧) - offset := (page - 1) * limit - if err := query.Order("created_at DESC").Limit(limit).Offset(offset).Find(&logs).Error; err != nil { + // 泛型分页查询 + logs, total, err := services.Paginate[models.LoginLog](query, page, limit, "created_at DESC") + if err != nil { loginLogBaseController.HandleInternalError(c, "获取日志列表失败", err) return } diff --git a/controllers/admin/operation_log.go b/controllers/admin/operation_log.go index 9b8917b..d0709bd 100644 --- a/controllers/admin/operation_log.go +++ b/controllers/admin/operation_log.go @@ -3,8 +3,8 @@ package admin import ( "NetworkAuth/controllers" "NetworkAuth/models" + "NetworkAuth/services" "net/http" - "strconv" "strings" "time" @@ -37,30 +37,18 @@ func LogsFragmentHandler(c *gin.Context) { // LogsListHandler 日志列表API处理器 func LogsListHandler(c *gin.Context) { // 获取分页参数 - page, _ := strconv.Atoi(c.Query("page")) - if page <= 0 { - page = 1 - } - limit, _ := strconv.Atoi(c.Query("limit")) - if limit <= 0 { - limit = 10 - } + page, limit := logBaseController.GetPaginationParams(c) // 获取搜索参数 - startTimeStr := strings.TrimSpace(c.Query("start_time")) - endTimeStr := strings.TrimSpace(c.Query("end_time")) operationType := strings.TrimSpace(c.Query("operation_type")) operator := strings.TrimSpace(c.Query("operator")) - // 构建查询 + // 获取数据库连接 db, ok := logBaseController.GetDB(c) if !ok { return } - var logs []models.OperationLog - var total int64 - query := db.Model(&models.OperationLog{}) // 筛选条件 @@ -71,39 +59,13 @@ func LogsListHandler(c *gin.Context) { // 支持按 UUID 或 用户名 筛选 query = query.Where("operator_uuid = ? OR operator = ?", operator, operator) } - if startTimeStr != "" { - if t, err := time.ParseInLocation("2006-01-02", startTimeStr, time.Local); err == nil { - query = query.Where("created_at >= ?", t) - } else if t, err := time.ParseInLocation("2006-01-02 15:04:05", startTimeStr, time.Local); err == nil { - query = query.Where("created_at >= ?", t) - } else { - query = query.Where("created_at >= ?", startTimeStr) - } - } - if endTimeStr != "" { - if t, err := time.ParseInLocation("2006-01-02", endTimeStr, time.Local); err == nil { - t = t.Add(24*time.Hour - time.Nanosecond) - query = query.Where("created_at <= ?", t) - } else if t, err := time.ParseInLocation("2006-01-02 15:04:05", endTimeStr, time.Local); err == nil { - query = query.Where("created_at <= ?", t) - } else { - if len(endTimeStr) == 10 { // yyyy-MM-dd - endTimeStr += " 23:59:59" - } - query = query.Where("created_at <= ?", endTimeStr) - } - } - // 获取总数 - if err := query.Count(&total).Error; err != nil { - logrus.WithError(err).Error("获取日志总数失败") - logBaseController.HandleInternalError(c, "获取日志总数失败", err) - return - } + // 筛选条件:时间范围 + query = logBaseController.ApplyTimeRangeQuery(c, query, "created_at") - // 分页查询(时间倒序,从新到旧) - offset := (page - 1) * limit - if err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&logs).Error; err != nil { + // 泛型分页查询 + logs, total, err := services.Paginate[models.OperationLog](query, page, limit, "created_at DESC") + if err != nil { logrus.WithError(err).Error("查询日志列表失败") logBaseController.HandleInternalError(c, "查询日志列表失败", err) return diff --git a/controllers/admin/variable.go b/controllers/admin/variable.go index f0d99af..209a6c8 100644 --- a/controllers/admin/variable.go +++ b/controllers/admin/variable.go @@ -38,18 +38,7 @@ func VariableFragmentHandler(c *gin.Context) { // VariableListHandler 变量列表API处理器 func VariableListHandler(c *gin.Context) { // 获取分页参数 - page, _ := strconv.Atoi(c.Query("page")) - if page <= 0 { - page = 1 - } - limit, _ := strconv.Atoi(c.Query("limit")) - // 兼容前端使用的page_size参数 - if limit <= 0 { - limit, _ = strconv.Atoi(c.Query("page_size")) - } - if limit <= 0 { - limit = 10 - } + page, limit := variableBaseController.GetPaginationParams(c) // 获取搜索关键词参数(支持编号、别名、数据的综合搜索) search := strings.TrimSpace(c.Query("search")) @@ -83,18 +72,9 @@ func VariableListHandler(c *gin.Context) { query = query.Where("app_uuid = ?", appUUID) } - // 获取总数 - var total int64 - if err := query.Count(&total).Error; err != nil { - logrus.WithError(err).Error("Failed to count variables") - variableBaseController.HandleInternalError(c, "查询变量总数失败", err) - return - } - - // 获取分页数据 - var variables []models.Variable - offset := (page - 1) * limit - if err := query.Offset(offset).Limit(limit).Order("created_at DESC").Find(&variables).Error; err != nil { + // 泛型分页查询 + variables, total, err := services.Paginate[models.Variable](query, page, limit, "created_at DESC") + if err != nil { logrus.WithError(err).Error("Failed to fetch variables") variableBaseController.HandleInternalError(c, "查询变量列表失败", err) return diff --git a/controllers/base.go b/controllers/base.go index c6bc2f0..b400739 100644 --- a/controllers/base.go +++ b/controllers/base.go @@ -3,6 +3,8 @@ package controllers import ( "net/http" "strconv" + "strings" + "time" "NetworkAuth/database" @@ -128,7 +130,7 @@ func (bc *BaseController) ValidateRequired(c *gin.Context, fields map[string]int // GetPaginationParams 获取分页参数 func (bc *BaseController) GetPaginationParams(c *gin.Context) (int, int) { page := 1 - pageSize := 10 + limit := 10 if p := c.Query("page"); p != "" { if pageInt, err := strconv.Atoi(p); err == nil && pageInt > 0 { @@ -136,13 +138,18 @@ func (bc *BaseController) GetPaginationParams(c *gin.Context) (int, int) { } } - if ps := c.Query("page_size"); ps != "" { - if pageSizeInt, err := strconv.Atoi(ps); err == nil && pageSizeInt > 0 && pageSizeInt <= 100 { - pageSize = pageSizeInt + // 兼容 layui 的 limit 和 其他的 page_size + if l := c.Query("limit"); l != "" { + if limitInt, err := strconv.Atoi(l); err == nil && limitInt > 0 { + limit = limitInt + } + } else if ps := c.Query("page_size"); ps != "" { + if pageSizeInt, err := strconv.Atoi(ps); err == nil && pageSizeInt > 0 { + limit = pageSizeInt } } - return page, pageSize + return page, limit } // CalculateOffset 计算数据库查询偏移量 @@ -150,6 +157,53 @@ func (bc *BaseController) CalculateOffset(page, pageSize int) int { return (page - 1) * pageSize } +// ApplyTimeRangeQuery 应用通用时间范围查询 +func (bc *BaseController) ApplyTimeRangeQuery(c *gin.Context, query *gorm.DB, field string) *gorm.DB { + // 获取可能的时间参数名 + startTimes := []string{"start_time", "login_start_time", "operation_start_time"} + endTimes := []string{"end_time", "login_end_time", "operation_end_time"} + + var startTimeStr, endTimeStr string + for _, k := range startTimes { + if v := strings.TrimSpace(c.Query(k)); v != "" { + startTimeStr = v + break + } + } + for _, k := range endTimes { + if v := strings.TrimSpace(c.Query(k)); v != "" { + endTimeStr = v + break + } + } + + if startTimeStr != "" { + if t, err := time.ParseInLocation("2006-01-02", startTimeStr, time.Local); err == nil { + query = query.Where(field+" >= ?", t) + } else if t, err := time.ParseInLocation("2006-01-02 15:04:05", startTimeStr, time.Local); err == nil { + query = query.Where(field+" >= ?", t) + } else { + query = query.Where(field+" >= ?", startTimeStr) + } + } + + if endTimeStr != "" { + if t, err := time.ParseInLocation("2006-01-02", endTimeStr, time.Local); err == nil { + t = t.Add(24*time.Hour - time.Nanosecond) + query = query.Where(field+" <= ?", t) + } else if t, err := time.ParseInLocation("2006-01-02 15:04:05", endTimeStr, time.Local); err == nil { + query = query.Where(field+" <= ?", t) + } else { + if len(endTimeStr) == 10 { // yyyy-MM-dd + endTimeStr += " 23:59:59" + } + query = query.Where(field+" <= ?", endTimeStr) + } + } + + return query +} + // BindJSON 绑定JSON数据并处理错误 func (bc *BaseController) BindJSON(c *gin.Context, obj interface{}) bool { if err := c.ShouldBindJSON(obj); err != nil { diff --git a/services/query.go b/services/query.go index b74d304..a956bd6 100644 --- a/services/query.go +++ b/services/query.go @@ -107,3 +107,36 @@ func CheckEntityExists(model interface{}, condition string, db *gorm.DB, args .. err := db.Model(model).Where(condition, args...).Count(&count).Error return count > 0, err } + +// ============================================================================ +// 泛型查询函数 +// ============================================================================ + +// Paginate 泛型分页查询 +// query: 带条件的数据库查询对象 +// page: 当前页码 +// limit: 每页数量 +// order: 排序规则 (例如 "created_at DESC") +// 返回: 数据列表, 总数, 错误 +func Paginate[T any](query *gorm.DB, page, limit int, order string) ([]T, int64, error) { + var list []T + var total int64 + + // 获取总数 + if err := query.Count(&total).Error; err != nil { + return nil, 0, err + } + + // 排序 + if order != "" { + query = query.Order(order) + } + + // 分页查询 + offset := (page - 1) * limit + if err := query.Offset(offset).Limit(limit).Find(&list).Error; err != nil { + return nil, 0, err + } + + return list, total, nil +}