Files
nl-blogs/server/repositories/log_repository.go
李琦 34fe612aab 2
2026-01-20 08:43:35 +08:00

148 lines
3.5 KiB
Go

package repositories
import (
// "log"
"time"
"github.com/niangaodev/art-code/config"
"github.com/niangaodev/art-code/models"
)
// Helper to parse date string to unix timestamp
func parseDateToUnix(dateStr string, isEnd bool) int64 {
if dateStr == "" {
return 0
}
// Try parsing with time first
t, err := time.ParseInLocation("2006-01-02 15:04", dateStr, time.Local)
if err == nil {
if isEnd {
// HH:mm:59
return t.Add(59 * time.Second).Unix()
}
return t.Unix()
}
// Try parsing just date
t, err = time.ParseInLocation("2006-01-02", dateStr, time.Local)
if err == nil {
if isEnd {
// 23:59:59
return t.Add(24*time.Hour - 1*time.Second).Unix()
}
return t.Unix()
}
return 0
}
// CreateAccessLog 创建访问日志
func CreateAccessLog(log *models.AccessLog) error {
return config.DB.Create(log).Error
}
// UVTrendData UV趋势数据
type UVTrendData struct {
Date string `json:"date"`
Count int `json:"value"`
YoY float64 `json:"yoy"`
MoM float64 `json:"mom"`
}
// GetDailyUV 获取UV趋势
func GetDailyUV(startDate, endDate string) ([]UVTrendData, error) {
// 确定日期范围
var startTime, endTime time.Time
if startDate != "" {
startUnix := parseDateToUnix(startDate, false)
startTime = time.Unix(startUnix, 0)
} else {
startTime = time.Now().AddDate(0, 0, -6)
startTime = time.Date(startTime.Year(), startTime.Month(), startTime.Day(), 0, 0, 0, 0, time.Local)
}
if endDate != "" {
endUnix := parseDateToUnix(endDate, true)
endTime = time.Unix(endUnix, 0)
} else {
endTime = time.Now()
endTime = time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 23, 59, 59, 0, time.Local)
}
// 查询数据库
query := config.DB.Model(&models.UserAccessLog{}).
Select("FROM_UNIXTIME(access_time, '%Y-%m-%d') as date, COUNT(DISTINCT user_ip) as count").
Where("access_time >= ?", startTime.Unix()).
Where("access_time <= ?", endTime.Unix())
var results []UVTrendData
err := query.Group("date").
Order("date ASC").
Scan(&results).Error
if err != nil {
return nil, err
}
// 创建日期到数据的映射
resultMap := make(map[string]UVTrendData)
for _, r := range results {
resultMap[r.Date] = r
}
// 生成完整日期列表
var fullResults []UVTrendData
current := time.Date(startTime.Year(), startTime.Month(), startTime.Day(), 0, 0, 0, 0, time.Local)
endDay := time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, time.Local)
for !current.After(endDay) {
dateStr := current.Format("2006-01-02")
if data, exists := resultMap[dateStr]; exists {
data.YoY = 0
data.MoM = 0
fullResults = append(fullResults, data)
} else {
// 填充0值
fullResults = append(fullResults, UVTrendData{
Date: dateStr,
Count: 0,
YoY: 0,
MoM: 0,
})
}
current = current.AddDate(0, 0, 1)
}
return fullResults, nil
}
// GetUserRegions 获取用户地域分布
func GetUserRegions(startDate, endDate string) ([]struct {
Region string
Count int
}, error) {
query := config.DB.Model(&models.UserAccessLog{}).
Select("COALESCE(NULLIF(user_location, ''), 'Unknown') as region, COUNT(DISTINCT user_ip) as count")
if startDate != "" {
startUnix := parseDateToUnix(startDate, false)
query = query.Where("access_time >= ?", startUnix)
}
if endDate != "" {
endUnix := parseDateToUnix(endDate, true)
query = query.Where("access_time <= ?", endUnix)
}
var results []struct {
Region string
Count int
}
err := query.Group("region").
Order("count DESC").
Limit(20).
Scan(&results).Error
return results, err
}