2026-07-03 16:01:08 +08:00
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"seeyon-filesystem/config"
|
|
|
|
|
"seeyon-filesystem/dto"
|
|
|
|
|
"seeyon-filesystem/model"
|
2026-07-18 10:52:32 +08:00
|
|
|
"seeyon-filesystem/utils"
|
2026-07-03 16:01:08 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// LogService 日志服务
|
|
|
|
|
type LogService struct{}
|
|
|
|
|
|
|
|
|
|
func NewLogService() *LogService {
|
|
|
|
|
return &LogService{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Record 记录操作日志
|
|
|
|
|
func (s *LogService) Record(userID uint64, username, action, resource, detail, ip, ua string, status int) {
|
|
|
|
|
log := &model.OperationLog{
|
2026-07-18 10:52:32 +08:00
|
|
|
ID: utils.GenID(),
|
2026-07-03 16:01:08 +08:00
|
|
|
UserID: userID,
|
|
|
|
|
Username: username,
|
|
|
|
|
Action: action,
|
|
|
|
|
Resource: resource,
|
|
|
|
|
Detail: detail,
|
|
|
|
|
IP: ip,
|
|
|
|
|
UserAgent: ua,
|
|
|
|
|
Status: status,
|
|
|
|
|
}
|
|
|
|
|
config.DB.Create(log)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// List 查询日志列表
|
|
|
|
|
func (s *LogService) List(page, size int, action, resource, keyword string, userID uint64) ([]dto.OperationLogVO, int64, error) {
|
|
|
|
|
query := config.DB.Model(&model.OperationLog{})
|
|
|
|
|
|
|
|
|
|
if action != "" {
|
|
|
|
|
query = query.Where("action = ?", action)
|
|
|
|
|
}
|
|
|
|
|
if resource != "" {
|
|
|
|
|
query = query.Where("resource = ?", resource)
|
|
|
|
|
}
|
|
|
|
|
if userID > 0 {
|
|
|
|
|
query = query.Where("user_id = ?", userID)
|
|
|
|
|
}
|
|
|
|
|
if keyword != "" {
|
|
|
|
|
query = query.Where("detail LIKE ? OR username LIKE ? OR ip LIKE ?",
|
|
|
|
|
"%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var total int64
|
|
|
|
|
query.Count(&total)
|
|
|
|
|
|
|
|
|
|
var logs []model.OperationLog
|
|
|
|
|
query.Order("created_at DESC").Offset((page - 1) * size).Limit(size).Find(&logs)
|
|
|
|
|
|
|
|
|
|
vos := make([]dto.OperationLogVO, 0, len(logs))
|
|
|
|
|
for _, l := range logs {
|
|
|
|
|
vos = append(vos, dto.OperationLogVO{
|
|
|
|
|
ID: l.ID,
|
|
|
|
|
UserID: l.UserID,
|
|
|
|
|
Username: l.Username,
|
|
|
|
|
Action: l.Action,
|
|
|
|
|
Resource: l.Resource,
|
|
|
|
|
Detail: l.Detail,
|
|
|
|
|
IP: l.IP,
|
|
|
|
|
Status: l.Status,
|
|
|
|
|
CreatedAt: l.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return vos, total, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetStats 获取日志统计
|
|
|
|
|
func (s *LogService) GetStats() (map[string]interface{}, error) {
|
|
|
|
|
var total int64
|
|
|
|
|
var today int64
|
|
|
|
|
var failed int64
|
|
|
|
|
|
|
|
|
|
config.DB.Model(&model.OperationLog{}).Count(&total)
|
|
|
|
|
config.DB.Model(&model.OperationLog{}).Where("DATE(created_at) = CURDATE()").Count(&today)
|
|
|
|
|
config.DB.Model(&model.OperationLog{}).Where("status = 0").Count(&failed)
|
|
|
|
|
|
|
|
|
|
// 按操作类型统计
|
|
|
|
|
type ActionCount struct {
|
|
|
|
|
Action string `json:"action"`
|
|
|
|
|
Count int64 `json:"count"`
|
|
|
|
|
}
|
|
|
|
|
var actionCounts []ActionCount
|
|
|
|
|
config.DB.Model(&model.OperationLog{}).
|
|
|
|
|
Select("action, COUNT(*) as count").
|
|
|
|
|
Group("action").
|
|
|
|
|
Order("count DESC").
|
|
|
|
|
Limit(10).
|
|
|
|
|
Find(&actionCounts)
|
|
|
|
|
|
|
|
|
|
return map[string]interface{}{
|
|
|
|
|
"total": total,
|
|
|
|
|
"today": today,
|
|
|
|
|
"failed": failed,
|
|
|
|
|
"action_counts": actionCounts,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CleanOld 清理N天前的日志
|
|
|
|
|
func (s *LogService) CleanOld(days int) (int64, error) {
|
|
|
|
|
result := config.DB.Where("created_at < DATE_SUB(NOW(), INTERVAL ? DAY)", days).Delete(&model.OperationLog{})
|
|
|
|
|
return result.RowsAffected, result.Error
|
|
|
|
|
}
|