Files
jiang13-bbs/backend/handler/telemetry.go

64 lines
1.8 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 handler
import (
"crypto/rand"
"encoding/hex"
"fmt"
"net/http"
"github.com/freefire/jiang13-bbs/middleware"
"github.com/freefire/jiang13-bbs/model"
"github.com/freefire/jiang13-bbs/service"
"github.com/gin-gonic/gin"
)
const visitorCookie = "j13_vid"
func newVisitorID() string {
var b [16]byte
_, _ = rand.Read(b[:])
// 伪 UUID 形态,满足 ValidVisitorID
return fmt.Sprintf("%s-%s-%s-%s-%s",
hex.EncodeToString(b[0:4]),
hex.EncodeToString(b[4:6]),
hex.EncodeToString(b[6:8]),
hex.EncodeToString(b[8:10]),
hex.EncodeToString(b[10:16]),
)
}
// POST /api/telemetry/pageview — 轻量 PV/UV 埋点(公开,需 CSRF)
func (h *Handlers) TelemetryPageView(c *gin.Context) {
vid, _ := c.Cookie(visitorCookie)
if !service.ValidVisitorID(vid) {
vid = newVisitorID()
secure := c.Request.TLS != nil || c.GetHeader("X-Forwarded-Proto") == "https"
// HttpOnly:仅服务端读 UV,前端埋点不依赖可读 cookie
c.SetCookie(visitorCookie, vid, 365*24*3600, "/", "", secure, true)
}
loggedIn := middleware.CurrentUser(c) != nil
if err := h.Telemetry.RecordPageView(vid, loggedIn); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "记录失败"})
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
}
// GET /api/admin/analytics/overview?range=7d|30d
func (h *Handlers) AdminAnalyticsOverview(c *gin.Context) {
rangeQ := c.DefaultQuery("range", "7d")
actor := middleware.CurrentActor(c)
scoped := actor != nil && actor.Role == model.RoleBoardAdmin
var boardIDs []uint
if scoped {
boardIDs = actor.BoardIDs
}
data, err := h.Analytics.Overview(rangeQ, boardIDs, scoped)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取分析数据失败"})
return
}
c.JSON(http.StatusOK, data)
}