first commit
This commit is contained in:
171
controllers/com_controller.go
Normal file
171
controllers/com_controller.go
Normal file
@@ -0,0 +1,171 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"Quincy_admin/config"
|
||||
"Quincy_admin/schemas"
|
||||
"Quincy_admin/services"
|
||||
"Quincy_admin/utils"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type CommonController struct {
|
||||
service *services.CommonService
|
||||
config *config.Config
|
||||
}
|
||||
|
||||
func NewCommonController(service *services.CommonService) *CommonController {
|
||||
return &CommonController{service: service, config: config.LoadConfig()}
|
||||
}
|
||||
|
||||
// GetLoginLogList 获取系统登录日志
|
||||
// @Summary 系统登录日志
|
||||
// @Description 系统登录日志
|
||||
// @Tags 系统管理
|
||||
// @Produce json
|
||||
// @Param role body schemas.LoginLogListRequest true "req"
|
||||
// @Success 200 {object} utils.Response{data=schemas.LoginLog}
|
||||
// @Failure 500 {object} utils.Response
|
||||
// @Router /system/log/login/list [post]
|
||||
// @Security ApiKeyAuth
|
||||
func (c *CommonController) GetLoginLogList(ctx *gin.Context) {
|
||||
var req schemas.LoginLogListRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
utils.Error(ctx, http.StatusBadRequest, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if req.PageIndex <= 0 || req.PageSize <= 0 || req.PageSize > 100 {
|
||||
utils.Error(ctx, http.StatusBadRequest, "分页参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
items, total, err := c.service.GetLoginLogList(&req)
|
||||
if err != nil {
|
||||
fmt.Println("获取用户列表时出错:", err)
|
||||
utils.Error(ctx, http.StatusInternalServerError, "获取日志列表失败")
|
||||
return
|
||||
}
|
||||
|
||||
response := schemas.LoginLogListResponse{
|
||||
Item: items,
|
||||
Total: total,
|
||||
PageIndex: req.PageIndex,
|
||||
PageSize: req.PageSize,
|
||||
}
|
||||
|
||||
utils.Success(ctx, response)
|
||||
}
|
||||
|
||||
// DownloadLogFile 下载日志文件
|
||||
// @Summary 下载日志文件
|
||||
// @Description 下载指定的日志文件内容
|
||||
// @Tags 系统管理
|
||||
// @Produce application/octet-stream
|
||||
// @Param filename query string true "日志文件名"
|
||||
// @Success 200 {file} file "日志文件内容"
|
||||
// @Failure 400 {object} utils.Response
|
||||
// @Failure 404 {object} utils.Response
|
||||
// @Failure 500 {object} utils.Response
|
||||
// @Router /system/log/download [get]
|
||||
// @Security ApiKeyAuth
|
||||
// DownloadLogFile 下载日志文件
|
||||
func (c *CommonController) DownloadLogFile(ctx *gin.Context) {
|
||||
filename := ctx.Query("filename")
|
||||
if filename == "" {
|
||||
utils.Error(ctx, http.StatusBadRequest, "参数 filename 不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
// 验证文件名安全性
|
||||
if strings.Contains(filename, "..") || strings.Contains(filename, "/") || strings.Contains(filename, "\\") {
|
||||
utils.Error(ctx, http.StatusBadRequest, "无效的文件名")
|
||||
return
|
||||
}
|
||||
|
||||
// 使用 filepath.Join 处理跨平台路径分隔符
|
||||
filePath := filepath.Join(c.config.Log.Path, filename)
|
||||
|
||||
// 检查文件是否存在
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
utils.Error(ctx, http.StatusNotFound, "日志文件不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 对文件名进行编码以支持中文
|
||||
encodedFilename := url.QueryEscape(filename)
|
||||
|
||||
// 设置响应头
|
||||
ctx.Header("Content-Description", "File Transfer")
|
||||
ctx.Header("Content-Transfer-Encoding", "binary")
|
||||
ctx.Header("Content-Disposition", "attachment; filename*=UTF-8''"+encodedFilename)
|
||||
ctx.Header("Content-Type", "application/octet-stream")
|
||||
|
||||
// 返回文件内容
|
||||
ctx.File(filePath)
|
||||
}
|
||||
|
||||
// ViewLogFile 查看日志文件内容
|
||||
// @Summary 查看日志文件内容
|
||||
// @Description 返回指定日志文件的内容
|
||||
// @Tags 系统管理
|
||||
// @Produce json
|
||||
// @Param filename query string true "日志文件名"
|
||||
// @Param lines query int false "返回行数,默认100行"
|
||||
// @Success 200 {object} utils.Response{data=string}
|
||||
// @Failure 400 {object} utils.Response
|
||||
// @Failure 404 {object} utils.Response
|
||||
// @Failure 500 {object} utils.Response
|
||||
// @Router /system/log/view [get]
|
||||
// @Security ApiKeyAuth
|
||||
// ViewLogFile 查看日志文件内容
|
||||
func (c *CommonController) ViewLogFile(ctx *gin.Context) {
|
||||
filename := ctx.Query("filename")
|
||||
if filename == "" {
|
||||
utils.Error(ctx, http.StatusBadRequest, "参数 filename 不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
linesStr := ctx.Query("lines")
|
||||
lines := 100 // 默认返回100行
|
||||
if linesStr != "" {
|
||||
var err error
|
||||
lines, err = strconv.Atoi(linesStr)
|
||||
if err != nil || lines <= 0 {
|
||||
utils.Error(ctx, http.StatusBadRequest, "参数 lines 必须是正整数")
|
||||
return
|
||||
}
|
||||
if lines > 1000 {
|
||||
lines = 1000 // 限制最大行数
|
||||
}
|
||||
}
|
||||
|
||||
// 验证文件名安全性
|
||||
if strings.Contains(filename, "..") || strings.Contains(filename, "/") || strings.Contains(filename, "\\") {
|
||||
utils.Error(ctx, http.StatusBadRequest, "无效的文件名")
|
||||
return
|
||||
}
|
||||
|
||||
// 使用配置文件中的日志目录
|
||||
f := c.config.Log.Path + "/" + filename
|
||||
|
||||
// 读取文件内容
|
||||
content, err := c.service.ReadLastLines(f, lines)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
utils.Error(ctx, http.StatusNotFound, "日志文件不存在")
|
||||
} else {
|
||||
utils.Error(ctx, http.StatusInternalServerError, "读取日志文件失败: "+err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
utils.Success(ctx, content)
|
||||
}
|
||||
Reference in New Issue
Block a user