From db9a036b2c2539138f85d1df1d0c40fca310d179 Mon Sep 17 00:00:00 2001 From: shirainbown Date: Fri, 19 Jun 2026 19:11:42 +0800 Subject: [PATCH] fix: operation logs page display and API pagination - Fix frontend Logs.vue to use correct field names (entity_type, entity_name, old_value, new_value) - Add user and source_ip columns to logs table - Add details column showing old_value -> new_value transitions - Fix backend logs API to support pagination (page, page_size, search) - Add search support across all log fields (action, entity_type, entity_name, username, values) - Return proper {list, total, page, page_size} response format --- server/handlers/logs.go | 50 +++++++++++++++++++++++++++++++++++++++-- web/src/views/Logs.vue | 18 ++++++++++----- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/server/handlers/logs.go b/server/handlers/logs.go index a59bc42..91aec79 100644 --- a/server/handlers/logs.go +++ b/server/handlers/logs.go @@ -3,6 +3,7 @@ package handlers import ( "database/sql" "net/http" + "strconv" "github.com/gin-gonic/gin" "lan-manager/server/db" @@ -18,17 +19,55 @@ func NewLogHandler() *LogHandler { func (h *LogHandler) List(c *gin.Context) { action := c.Query("action") date := c.Query("date") + search := c.Query("search") + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) + if page < 1 { + page = 1 + } + if pageSize < 1 || pageSize > 100 { + pageSize = 20 + } + offset := (page - 1) * pageSize + + // Build count query + countQuery := `SELECT COUNT(*) FROM operation_logs WHERE 1=1` + countArgs := []interface{}{} + + // Build data query query := `SELECT id, action, entity_type, entity_id, entity_name, old_value, new_value, source_ip, username, created_at FROM operation_logs WHERE 1=1` args := []interface{}{} + if action != "" { + countQuery += ` AND action = ?` query += ` AND action = ?` + countArgs = append(countArgs, action) args = append(args, action) } if date != "" { + countQuery += ` AND DATE(created_at) = ?` query += ` AND DATE(created_at) = ?` + countArgs = append(countArgs, date) args = append(args, date) } - query += ` ORDER BY created_at DESC LIMIT 1000` + if search != "" { + searchPattern := "%" + search + "%" + countQuery += ` AND (action LIKE ? OR entity_type LIKE ? OR entity_name LIKE ? OR username LIKE ? OR old_value LIKE ? OR new_value LIKE ?)` + query += ` AND (action LIKE ? OR entity_type LIKE ? OR entity_name LIKE ? OR username LIKE ? OR old_value LIKE ? OR new_value LIKE ?)` + countArgs = append(countArgs, searchPattern, searchPattern, searchPattern, searchPattern, searchPattern, searchPattern) + args = append(args, searchPattern, searchPattern, searchPattern, searchPattern, searchPattern, searchPattern) + } + + // Get total count + var total int + if err := db.DB.QueryRow(countQuery, countArgs...).Scan(&total); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + // Get data with pagination + query += ` ORDER BY created_at DESC LIMIT ? OFFSET ?` + args = append(args, pageSize, offset) rows, err := db.DB.Query(query, args...) if err != nil { @@ -36,6 +75,7 @@ func (h *LogHandler) List(c *gin.Context) { return } defer rows.Close() + logs := []models.OperationLog{} for rows.Next() { var l models.OperationLog @@ -47,5 +87,11 @@ func (h *LogHandler) List(c *gin.Context) { logs = append(logs, l) } } - c.JSON(http.StatusOK, logs) + + c.JSON(http.StatusOK, gin.H{ + "list": logs, + "total": total, + "page": page, + "page_size": pageSize, + }) } diff --git a/web/src/views/Logs.vue b/web/src/views/Logs.vue index 5a5a2df..4c4a5a8 100644 --- a/web/src/views/Logs.vue +++ b/web/src/views/Logs.vue @@ -29,18 +29,26 @@ - + - + - + + + + +