feat: 站点访问统计与可配置侧边栏组件
- 新增访问统计:visitstats 服务与查询、visit_capture 中间件、爬虫/来源识别、管理端 analytics 页面 - 新增侧边栏:sidebar 服务与 handler、管理端 sidebar 配置页、前端侧边栏组件 - 新增 widget 嵌入代码生成(widgetCode)与 widgetApi - 遥测逻辑迁移至 handler 层,删除 service/telemetry - env 示例补充 Docker 部署可信代理 IP 说明
This commit is contained in:
46
backend/service/visitstats_test.go
Normal file
46
backend/service/visitstats_test.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/freefire/jiang13-bbs/model"
|
||||
)
|
||||
|
||||
func TestSummarizePageviews(t *testing.T) {
|
||||
day := time.Date(2026, 9, 24, 0, 0, 0, 0, time.Local)
|
||||
at := func(hour int) time.Time { return day.Add(time.Duration(hour) * time.Hour) }
|
||||
|
||||
events := []model.VisitEvent{
|
||||
{Kind: model.VisitKindPageview, CreatedAt: at(9), UserID: 1, VidHash: "aaa"},
|
||||
{Kind: model.VisitKindPageview, CreatedAt: at(9), VidHash: "aaa"}, // 同 vid 同日:去重
|
||||
{Kind: model.VisitKindPageview, CreatedAt: at(10), VidHash: "bbb"},
|
||||
{Kind: model.VisitKindBot, CreatedAt: at(9), VidHash: "aaa"}, // bot 不计
|
||||
{Kind: model.VisitKindProbe, CreatedAt: at(9), VidHash: "bbb"}, // probe 不计
|
||||
}
|
||||
out := summarizePageviews(events)
|
||||
d, ok := out[day]
|
||||
if !ok {
|
||||
t.Fatal("缺少当日聚合")
|
||||
}
|
||||
if d.PV != 3 {
|
||||
t.Errorf("PV = %d, want 3", d.PV)
|
||||
}
|
||||
if d.LoggedInPV != 1 {
|
||||
t.Errorf("LoggedInPV = %d, want 1", d.LoggedInPV)
|
||||
}
|
||||
if len(d.VidHashes) != 2 {
|
||||
t.Errorf("UV 候选 = %d, want 2", len(d.VidHashes))
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashVisitorID(t *testing.T) {
|
||||
a := HashVisitorID(" ABcd1234-0000-0000-0000-000000000000 ")
|
||||
b := HashVisitorID("abcd1234-0000-0000-0000-000000000000")
|
||||
if a != b {
|
||||
t.Error("大小写/空白应归一后哈希一致")
|
||||
}
|
||||
if len(a) != 64 {
|
||||
t.Errorf("哈希长度 = %d, want 64", len(a))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user