Files
nl-blogs/server/repositories/log_repository.go
2026-01-16 13:01:21 +08:00

160 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 {
now := time.Now().Unix()
query := `INSERT INTO access_logs (ip, user_agent, path, method, status_code, response_time, region, created_at, deleted_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0)`
_, err := config.DB.Exec(query, log.IP, log.UserAgent, log.Path, log.Method, log.StatusCode, log.ResponseTime, log.Region, now)
return err
}
// 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) {
query := `
SELECT FROM_UNIXTIME(access_time, '%Y-%m-%d') as date, COUNT(DISTINCT user_ip) as count
FROM user_access_logs
WHERE 1=1
`
args := []interface{}{}
if startDate != "" {
startUnix := parseDateToUnix(startDate, false)
query += " AND access_time >= ?"
args = append(args, startUnix)
} else {
// 默认最近7天
startUnix := time.Now().AddDate(0, 0, -6).Unix()
query += " AND access_time >= ?"
args = append(args, startUnix)
}
if endDate != "" {
endUnix := parseDateToUnix(endDate, true)
query += " AND access_time <= ?"
args = append(args, endUnix)
}
query += `
GROUP BY date
ORDER BY date ASC
`
rows, err := config.DB.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var results []UVTrendData
for rows.Next() {
var r UVTrendData
if err := rows.Scan(&r.Date, &r.Count); err != nil {
return nil, err
}
// 暂未实现真实的同比环比计算逻辑,设为0
r.YoY = 0
r.MoM = 0
results = append(results, r)
}
return results, nil
}
// GetUserRegions 获取用户地域分布
func GetUserRegions(startDate, endDate string) ([]struct {
Region string
Count int
}, error) {
query := `
SELECT
COALESCE(NULLIF(user_location, ''), 'Unknown') as region,
COUNT(DISTINCT user_ip) as count
FROM user_access_logs
WHERE 1=1
`
args := []interface{}{}
if startDate != "" {
startUnix := parseDateToUnix(startDate, false)
query += " AND access_time >= ?"
args = append(args, startUnix)
}
if endDate != "" {
endUnix := parseDateToUnix(endDate, true)
query += " AND access_time <= ?"
args = append(args, endUnix)
}
query += `
GROUP BY region
ORDER BY count DESC
LIMIT 20
`
rows, err := config.DB.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var results []struct {
Region string
Count int
}
for rows.Next() {
var r struct {
Region string
Count int
}
if err := rows.Scan(&r.Region, &r.Count); err != nil {
return nil, err
}
results = append(results, r)
}
return results, nil
}