后台布局
This commit is contained in:
@@ -323,6 +323,7 @@ const topPostsOption = computed(() => ({
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
inverse: true,
|
||||
data: stats.value.topPosts?.map((i: any) => i.title.length > 10 ? i.title.substring(0, 10) + '...' : i.title) || [],
|
||||
axisLabel: { color: '#ccc' }
|
||||
},
|
||||
|
||||
@@ -1,10 +1,42 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
// "log"
|
||||
"time"
|
||||
|
||||
"github.com/niangaodev/art-code/config"
|
||||
"github.com/niangaodev/art-code/models"
|
||||
)
|
||||
|
||||
// Helper to parse date strings flexibly
|
||||
func parseDateString(dateStr string, isEnd bool) string {
|
||||
if dateStr == "" {
|
||||
return ""
|
||||
}
|
||||
// Try parsing with time first
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04", dateStr, time.Local)
|
||||
if err == nil {
|
||||
if isEnd {
|
||||
// If it's end time, go to end of that minute
|
||||
return t.Format("2006-01-02 15:04") + ":59"
|
||||
}
|
||||
return t.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
// Try parsing just date
|
||||
t, err = time.ParseInLocation("2006-01-02", dateStr, time.Local)
|
||||
if err == nil {
|
||||
if isEnd {
|
||||
// If it's end date, go to end of day
|
||||
return t.Format("2006-01-02") + " 23:59:59"
|
||||
}
|
||||
return t.Format("2006-01-02") + " 00:00:00"
|
||||
}
|
||||
|
||||
// Return original if parsing fails (fallback)
|
||||
return dateStr
|
||||
}
|
||||
|
||||
// CreateAccessLog 创建访问日志
|
||||
func CreateAccessLog(log *models.AccessLog) error {
|
||||
query := `INSERT INTO access_logs (ip, user_agent, path, method, status_code, response_time, region) VALUES (?, ?, ?, ?, ?, ?, ?)`
|
||||
@@ -23,25 +55,25 @@ type UVTrendData struct {
|
||||
// GetDailyUV 获取UV趋势
|
||||
func GetDailyUV(startDate, endDate string) ([]UVTrendData, error) {
|
||||
query := `
|
||||
SELECT DATE_FORMAT(created_at, '%Y-%m-%d') as date, COUNT(DISTINCT ip) as count
|
||||
FROM access_logs
|
||||
SELECT DATE_FORMAT(access_time, '%Y-%m-%d') as date, COUNT(DISTINCT user_ip) as count
|
||||
FROM user_access_logs
|
||||
WHERE 1=1
|
||||
`
|
||||
args := []interface{}{}
|
||||
|
||||
if startDate != "" {
|
||||
query += " AND created_at >= ?"
|
||||
args = append(args, startDate)
|
||||
formattedStart := parseDateString(startDate, false)
|
||||
query += " AND access_time >= ?"
|
||||
args = append(args, formattedStart)
|
||||
} else {
|
||||
// 默认最近7天
|
||||
query += " AND created_at >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)"
|
||||
query += " AND access_time >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)"
|
||||
}
|
||||
|
||||
if endDate != "" {
|
||||
query += " AND created_at <= ?"
|
||||
// End date usually needs to cover the whole day, so append time or next day
|
||||
// For simplicity assuming YYYY-MM-DD format, we might want <= YYYY-MM-DD 23:59:59
|
||||
args = append(args, endDate+" 23:59:59")
|
||||
formattedEnd := parseDateString(endDate, true)
|
||||
query += " AND access_time <= ?"
|
||||
args = append(args, formattedEnd)
|
||||
}
|
||||
|
||||
query += `
|
||||
@@ -74,29 +106,29 @@ func GetUserRegions(startDate, endDate string) ([]struct {
|
||||
Region string
|
||||
Count int
|
||||
}, error) {
|
||||
// 简单的截取省份逻辑,实际可能需要更复杂的解析,这里假设region格式为 国家|区域|省份|城市|ISP
|
||||
// 我们可以取省份 (第3部分)
|
||||
query := `
|
||||
SELECT
|
||||
SUBSTRING_INDEX(SUBSTRING_INDEX(region, '|', 3), '|', -1) as province,
|
||||
COUNT(DISTINCT ip) as count
|
||||
FROM access_logs
|
||||
WHERE region != 'Internal' AND region != 'Unknown' AND region IS NOT NULL
|
||||
COALESCE(NULLIF(user_location, ''), 'Unknown') as region,
|
||||
COUNT(DISTINCT user_ip) as count
|
||||
FROM user_access_logs
|
||||
WHERE 1=1
|
||||
`
|
||||
args := []interface{}{}
|
||||
|
||||
if startDate != "" {
|
||||
query += " AND created_at >= ?"
|
||||
args = append(args, startDate)
|
||||
formattedStart := parseDateString(startDate, false)
|
||||
query += " AND access_time >= ?"
|
||||
args = append(args, formattedStart)
|
||||
}
|
||||
|
||||
if endDate != "" {
|
||||
query += " AND created_at <= ?"
|
||||
args = append(args, endDate+" 23:59:59")
|
||||
formattedEnd := parseDateString(endDate, true)
|
||||
query += " AND access_time <= ?"
|
||||
args = append(args, formattedEnd)
|
||||
}
|
||||
|
||||
query += `
|
||||
GROUP BY province
|
||||
GROUP BY region
|
||||
ORDER BY count DESC
|
||||
LIMIT 20
|
||||
`
|
||||
@@ -119,10 +151,7 @@ func GetUserRegions(startDate, endDate string) ([]struct {
|
||||
if err := rows.Scan(&r.Region, &r.Count); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 过滤掉无效数据
|
||||
if r.Region != "" && r.Region != "0" {
|
||||
results = append(results, r)
|
||||
}
|
||||
results = append(results, r)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,39 @@ package repositories
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/niangaodev/art-code/config"
|
||||
"github.com/niangaodev/art-code/models"
|
||||
)
|
||||
|
||||
// Helper to parse date strings flexibly (duplicated to avoid circular dependency if moved to utils, or just keep simple)
|
||||
// Ideally this should be in a utils package, but for now we'll keep it local to avoid refactoring everything
|
||||
func parsePostDateString(dateStr string, isEnd bool) string {
|
||||
if dateStr == "" {
|
||||
return ""
|
||||
}
|
||||
// Try parsing with time first
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04", dateStr, time.Local)
|
||||
if err == nil {
|
||||
if isEnd {
|
||||
return t.Format("2006-01-02 15:04") + ":59"
|
||||
}
|
||||
return t.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
// Try parsing just date
|
||||
t, err = time.ParseInLocation("2006-01-02", dateStr, time.Local)
|
||||
if err == nil {
|
||||
if isEnd {
|
||||
return t.Format("2006-01-02") + " 23:59:59"
|
||||
}
|
||||
return t.Format("2006-01-02") + " 00:00:00"
|
||||
}
|
||||
|
||||
return dateStr
|
||||
}
|
||||
|
||||
// GetPosts 获取所有博客文章(支持搜索)
|
||||
func GetPosts(keyword string) ([]models.Post, error) {
|
||||
var rows *sql.Rows
|
||||
@@ -405,16 +433,18 @@ func GetNewPostsTrend(startDate, endDate string) ([]TrendData, error) {
|
||||
args := []interface{}{dateFormat}
|
||||
|
||||
if startDate != "" {
|
||||
formattedStart := parsePostDateString(startDate, false)
|
||||
query += " AND created_at >= ?"
|
||||
args = append(args, startDate)
|
||||
args = append(args, formattedStart)
|
||||
} else {
|
||||
// 默认最近7天
|
||||
query += " AND created_at >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)"
|
||||
}
|
||||
|
||||
if endDate != "" {
|
||||
formattedEnd := parsePostDateString(endDate, true)
|
||||
query += " AND created_at <= ?"
|
||||
args = append(args, endDate+" 23:59:59")
|
||||
args = append(args, formattedEnd)
|
||||
}
|
||||
|
||||
query += `
|
||||
|
||||
Reference in New Issue
Block a user