405 lines
11 KiB
Go
405 lines
11 KiB
Go
|
|
package service
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"dianshang/internal/model"
|
|||
|
|
"time"
|
|||
|
|
|
|||
|
|
"gorm.io/gorm"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// LogService 日志服务
|
|||
|
|
type LogService struct {
|
|||
|
|
db *gorm.DB
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NewLogService 创建日志服务
|
|||
|
|
func NewLogService(db *gorm.DB) *LogService {
|
|||
|
|
return &LogService{
|
|||
|
|
db: db,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateLoginLog 创建登录日志
|
|||
|
|
func (s *LogService) CreateLoginLog(userID uint, ip, userAgent string, status int, remark string) error {
|
|||
|
|
log := &model.UserLoginLog{
|
|||
|
|
UserID: userID,
|
|||
|
|
LoginIP: ip,
|
|||
|
|
UserAgent: userAgent,
|
|||
|
|
LoginTime: time.Now(),
|
|||
|
|
Status: status,
|
|||
|
|
Remark: remark,
|
|||
|
|
}
|
|||
|
|
return s.db.Create(log).Error
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetUserLoginLogs 获取用户登录日志
|
|||
|
|
func (s *LogService) GetUserLoginLogs(userID uint, page, pageSize int) ([]model.UserLoginLog, map[string]interface{}, error) {
|
|||
|
|
var logs []model.UserLoginLog
|
|||
|
|
var total int64
|
|||
|
|
|
|||
|
|
query := s.db.Model(&model.UserLoginLog{}).Where("user_id = ?", userID)
|
|||
|
|
|
|||
|
|
// 获取总数
|
|||
|
|
err := query.Count(&total).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 分页查询
|
|||
|
|
offset := (page - 1) * pageSize
|
|||
|
|
err = query.Offset(offset).Limit(pageSize).Order("login_time DESC").Find(&logs).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建分页信息
|
|||
|
|
pagination := map[string]interface{}{
|
|||
|
|
"total": total,
|
|||
|
|
"page": page,
|
|||
|
|
"page_size": pageSize,
|
|||
|
|
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return logs, pagination, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetLoginLogList 获取登录日志列表(管理后台)
|
|||
|
|
func (s *LogService) GetLoginLogList(page, pageSize int, conditions map[string]interface{}) ([]model.UserLoginLog, map[string]interface{}, error) {
|
|||
|
|
var logs []model.UserLoginLog
|
|||
|
|
var total int64
|
|||
|
|
|
|||
|
|
query := s.db.Model(&model.UserLoginLog{}).Preload("User")
|
|||
|
|
|
|||
|
|
// 应用查询条件
|
|||
|
|
if userID, ok := conditions["user_id"]; ok && userID != "" {
|
|||
|
|
query = query.Where("user_id = ?", userID)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ip, ok := conditions["ip"]; ok && ip != "" {
|
|||
|
|
query = query.Where("login_ip LIKE ?", "%"+ip.(string)+"%")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if status, ok := conditions["status"]; ok && status != "" {
|
|||
|
|
query = query.Where("status = ?", status)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if startDate, ok := conditions["start_date"]; ok && startDate != "" {
|
|||
|
|
query = query.Where("login_time >= ?", startDate)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if endDate, ok := conditions["end_date"]; ok && endDate != "" {
|
|||
|
|
query = query.Where("login_time <= ?", endDate)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取总数
|
|||
|
|
err := query.Count(&total).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 分页查询
|
|||
|
|
offset := (page - 1) * pageSize
|
|||
|
|
err = query.Offset(offset).Limit(pageSize).Order("login_time DESC").Find(&logs).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建分页信息
|
|||
|
|
pagination := map[string]interface{}{
|
|||
|
|
"total": total,
|
|||
|
|
"page": page,
|
|||
|
|
"page_size": pageSize,
|
|||
|
|
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return logs, pagination, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateOperationLog 创建操作日志
|
|||
|
|
func (s *LogService) CreateOperationLog(userID uint, module, action, description, ip, userAgent, requestData string) error {
|
|||
|
|
log := &model.UserOperationLog{
|
|||
|
|
UserID: userID,
|
|||
|
|
Module: module,
|
|||
|
|
Action: action,
|
|||
|
|
Description: description,
|
|||
|
|
IP: ip,
|
|||
|
|
UserAgent: userAgent,
|
|||
|
|
RequestData: requestData,
|
|||
|
|
CreatedAt: time.Now(),
|
|||
|
|
}
|
|||
|
|
return s.db.Create(log).Error
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetUserOperationLogs 获取用户操作日志
|
|||
|
|
func (s *LogService) GetUserOperationLogs(userID uint, page, pageSize int) ([]model.UserOperationLog, map[string]interface{}, error) {
|
|||
|
|
var logs []model.UserOperationLog
|
|||
|
|
var total int64
|
|||
|
|
|
|||
|
|
query := s.db.Model(&model.UserOperationLog{}).Where("user_id = ?", userID)
|
|||
|
|
|
|||
|
|
// 获取总数
|
|||
|
|
err := query.Count(&total).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 分页查询
|
|||
|
|
offset := (page - 1) * pageSize
|
|||
|
|
err = query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&logs).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建分页信息
|
|||
|
|
pagination := map[string]interface{}{
|
|||
|
|
"total": total,
|
|||
|
|
"page": page,
|
|||
|
|
"page_size": pageSize,
|
|||
|
|
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return logs, pagination, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetOperationLogList 获取操作日志列表(管理后台)
|
|||
|
|
func (s *LogService) GetOperationLogList(page, pageSize int, conditions map[string]interface{}) ([]model.UserOperationLog, map[string]interface{}, error) {
|
|||
|
|
var logs []model.UserOperationLog
|
|||
|
|
var total int64
|
|||
|
|
|
|||
|
|
query := s.db.Model(&model.UserOperationLog{}).Preload("User")
|
|||
|
|
|
|||
|
|
// 应用查询条件
|
|||
|
|
if userID, ok := conditions["user_id"]; ok && userID != "" {
|
|||
|
|
query = query.Where("user_id = ?", userID)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if module, ok := conditions["module"]; ok && module != "" {
|
|||
|
|
query = query.Where("module = ?", module)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if action, ok := conditions["action"]; ok && action != "" {
|
|||
|
|
query = query.Where("action = ?", action)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ip, ok := conditions["ip"]; ok && ip != "" {
|
|||
|
|
query = query.Where("ip LIKE ?", "%"+ip.(string)+"%")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if startDate, ok := conditions["start_date"]; ok && startDate != "" {
|
|||
|
|
query = query.Where("created_at >= ?", startDate)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if endDate, ok := conditions["end_date"]; ok && endDate != "" {
|
|||
|
|
query = query.Where("created_at <= ?", endDate)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取总数
|
|||
|
|
err := query.Count(&total).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 分页查询
|
|||
|
|
offset := (page - 1) * pageSize
|
|||
|
|
err = query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&logs).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建分页信息
|
|||
|
|
pagination := map[string]interface{}{
|
|||
|
|
"total": total,
|
|||
|
|
"page": page,
|
|||
|
|
"page_size": pageSize,
|
|||
|
|
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return logs, pagination, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetLoginStatistics 获取登录统计
|
|||
|
|
func (s *LogService) GetLoginStatistics(startDate, endDate string) (map[string]interface{}, error) {
|
|||
|
|
result := make(map[string]interface{})
|
|||
|
|
|
|||
|
|
// 总登录次数
|
|||
|
|
var totalLogins int64
|
|||
|
|
query := s.db.Model(&model.UserLoginLog{})
|
|||
|
|
if startDate != "" && endDate != "" {
|
|||
|
|
query = query.Where("DATE(login_time) BETWEEN ? AND ?", startDate, endDate)
|
|||
|
|
}
|
|||
|
|
query.Count(&totalLogins)
|
|||
|
|
result["total_logins"] = totalLogins
|
|||
|
|
|
|||
|
|
// 成功登录次数
|
|||
|
|
var successLogins int64
|
|||
|
|
query = s.db.Model(&model.UserLoginLog{}).Where("status = 1")
|
|||
|
|
if startDate != "" && endDate != "" {
|
|||
|
|
query = query.Where("DATE(login_time) BETWEEN ? AND ?", startDate, endDate)
|
|||
|
|
}
|
|||
|
|
query.Count(&successLogins)
|
|||
|
|
result["success_logins"] = successLogins
|
|||
|
|
|
|||
|
|
// 失败登录次数
|
|||
|
|
var failedLogins int64
|
|||
|
|
query = s.db.Model(&model.UserLoginLog{}).Where("status = 0")
|
|||
|
|
if startDate != "" && endDate != "" {
|
|||
|
|
query = query.Where("DATE(login_time) BETWEEN ? AND ?", startDate, endDate)
|
|||
|
|
}
|
|||
|
|
query.Count(&failedLogins)
|
|||
|
|
result["failed_logins"] = failedLogins
|
|||
|
|
|
|||
|
|
// 独立用户数
|
|||
|
|
var uniqueUsers int64
|
|||
|
|
query = s.db.Model(&model.UserLoginLog{}).Distinct("user_id")
|
|||
|
|
if startDate != "" && endDate != "" {
|
|||
|
|
query = query.Where("DATE(login_time) BETWEEN ? AND ?", startDate, endDate)
|
|||
|
|
}
|
|||
|
|
query.Count(&uniqueUsers)
|
|||
|
|
result["unique_users"] = uniqueUsers
|
|||
|
|
|
|||
|
|
return result, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetOperationStatistics 获取操作统计
|
|||
|
|
func (s *LogService) GetOperationStatistics(startDate, endDate string) (map[string]interface{}, error) {
|
|||
|
|
result := make(map[string]interface{})
|
|||
|
|
|
|||
|
|
// 总操作次数
|
|||
|
|
var totalOperations int64
|
|||
|
|
query := s.db.Model(&model.UserOperationLog{})
|
|||
|
|
if startDate != "" && endDate != "" {
|
|||
|
|
query = query.Where("DATE(created_at) BETWEEN ? AND ?", startDate, endDate)
|
|||
|
|
}
|
|||
|
|
query.Count(&totalOperations)
|
|||
|
|
result["total_operations"] = totalOperations
|
|||
|
|
|
|||
|
|
// 按模块统计
|
|||
|
|
var moduleStats []struct {
|
|||
|
|
Module string `json:"module"`
|
|||
|
|
Count int64 `json:"count"`
|
|||
|
|
}
|
|||
|
|
query = s.db.Model(&model.UserOperationLog{}).Select("module, COUNT(*) as count").Group("module")
|
|||
|
|
if startDate != "" && endDate != "" {
|
|||
|
|
query = query.Where("DATE(created_at) BETWEEN ? AND ?", startDate, endDate)
|
|||
|
|
}
|
|||
|
|
query.Scan(&moduleStats)
|
|||
|
|
result["module_stats"] = moduleStats
|
|||
|
|
|
|||
|
|
// 按操作统计
|
|||
|
|
var actionStats []struct {
|
|||
|
|
Action string `json:"action"`
|
|||
|
|
Count int64 `json:"count"`
|
|||
|
|
}
|
|||
|
|
query = s.db.Model(&model.UserOperationLog{}).Select("action, COUNT(*) as count").Group("action")
|
|||
|
|
if startDate != "" && endDate != "" {
|
|||
|
|
query = query.Where("DATE(created_at) BETWEEN ? AND ?", startDate, endDate)
|
|||
|
|
}
|
|||
|
|
query.Scan(&actionStats)
|
|||
|
|
result["action_stats"] = actionStats
|
|||
|
|
|
|||
|
|
return result, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CleanOldLogs 清理旧日志
|
|||
|
|
func (s *LogService) CleanOldLogs(days int) error {
|
|||
|
|
cutoffDate := time.Now().AddDate(0, 0, -days)
|
|||
|
|
|
|||
|
|
// 清理登录日志
|
|||
|
|
if err := s.db.Where("login_time < ?", cutoffDate).Delete(&model.UserLoginLog{}).Error; err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清理操作日志
|
|||
|
|
if err := s.db.Where("created_at < ?", cutoffDate).Delete(&model.UserOperationLog{}).Error; err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetLoginLogByID 根据ID获取登录日志
|
|||
|
|
func (s *LogService) GetLoginLogByID(id uint) (*model.UserLoginLog, error) {
|
|||
|
|
var log model.UserLoginLog
|
|||
|
|
err := s.db.Preload("User").First(&log, id).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return &log, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetTodayLoginCount 获取今日登录次数
|
|||
|
|
func (s *LogService) GetTodayLoginCount() (int64, error) {
|
|||
|
|
var count int64
|
|||
|
|
today := time.Now().Format("2006-01-02")
|
|||
|
|
err := s.db.Model(&model.UserLoginLog{}).Where("DATE(login_time) = ?", today).Count(&count).Error
|
|||
|
|
return count, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetTodayOperationCount 获取今日操作次数
|
|||
|
|
func (s *LogService) GetTodayOperationCount() (int64, error) {
|
|||
|
|
var count int64
|
|||
|
|
today := time.Now().Format("2006-01-02")
|
|||
|
|
err := s.db.Model(&model.UserOperationLog{}).Where("DATE(created_at) = ?", today).Count(&count).Error
|
|||
|
|
return count, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetOnlineUserCount 获取在线用户数(最近30分钟有登录记录的用户)
|
|||
|
|
func (s *LogService) GetOnlineUserCount() (int64, error) {
|
|||
|
|
var count int64
|
|||
|
|
thirtyMinutesAgo := time.Now().Add(-30 * time.Minute)
|
|||
|
|
err := s.db.Model(&model.UserLoginLog{}).
|
|||
|
|
Where("login_time >= ? AND status = 1", thirtyMinutesAgo).
|
|||
|
|
Distinct("user_id").
|
|||
|
|
Count(&count).Error
|
|||
|
|
return count, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetLoginTrend 获取登录趋势
|
|||
|
|
func (s *LogService) GetLoginTrend(days int) ([]map[string]interface{}, error) {
|
|||
|
|
var results []map[string]interface{}
|
|||
|
|
|
|||
|
|
for i := days - 1; i >= 0; i-- {
|
|||
|
|
date := time.Now().AddDate(0, 0, -i).Format("2006-01-02")
|
|||
|
|
var count int64
|
|||
|
|
s.db.Model(&model.UserLoginLog{}).
|
|||
|
|
Where("DATE(login_time) = ?", date).
|
|||
|
|
Count(&count)
|
|||
|
|
|
|||
|
|
results = append(results, map[string]interface{}{
|
|||
|
|
"date": date,
|
|||
|
|
"count": count,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return results, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetOperationTrend 获取操作趋势
|
|||
|
|
func (s *LogService) GetOperationTrend(days int) ([]map[string]interface{}, error) {
|
|||
|
|
var results []map[string]interface{}
|
|||
|
|
|
|||
|
|
for i := days - 1; i >= 0; i-- {
|
|||
|
|
date := time.Now().AddDate(0, 0, -i).Format("2006-01-02")
|
|||
|
|
var count int64
|
|||
|
|
s.db.Model(&model.UserOperationLog{}).
|
|||
|
|
Where("DATE(created_at) = ?", date).
|
|||
|
|
Count(&count)
|
|||
|
|
|
|||
|
|
results = append(results, map[string]interface{}{
|
|||
|
|
"date": date,
|
|||
|
|
"count": count,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return results, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetOperationLogByID 根据ID获取操作日志
|
|||
|
|
func (s *LogService) GetOperationLogByID(id uint) (*model.UserOperationLog, error) {
|
|||
|
|
var log model.UserOperationLog
|
|||
|
|
err := s.db.Preload("User").First(&log, id).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
return &log, nil
|
|||
|
|
}
|