feat(admin): 独立后台壳、站点分析与聊天监管,公开站拆出主题切换与访问埋点
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
56
backend/handler/telemetry.go
Normal file
56
backend/handler/telemetry.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/freefire/jiang13-bbs/middleware"
|
||||
"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")
|
||||
data, err := h.Analytics.Overview(rangeQ)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取分析数据失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, data)
|
||||
}
|
||||
Reference in New Issue
Block a user