新增访客黑名单:支持拉黑 IP/设备并管理列表

工作台可按 IP 或设备拉黑并填写释放时间与原因;侧栏黑名单页查看与解除;进线自动拦截。
This commit is contained in:
yml2213
2026-07-19 00:43:55 +08:00
parent ada7533ffa
commit 1f92c35963
11 changed files with 838 additions and 5 deletions
+17
View File
@@ -22,6 +22,8 @@ func NewWidgetHandler() *WidgetHandler { return &WidgetHandler{} }
type WidgetInitReq struct {
ChannelKey string `json:"channel_key" form:"channel_key"`
VisitorName string `json:"visitor_name"`
// DeviceID 访客端持久设备指纹(localStorage),用于设备级拉黑
DeviceID string `json:"device_id" form:"device_id"`
// 宿主页信息(由 widget.js / 前端上报)
PageURL string `json:"page_url" form:"page_url"`
PageTitle string `json:"page_title" form:"page_title"`
@@ -120,6 +122,20 @@ func (h *WidgetHandler) Init(c *gin.Context) {
}
visitorIP, visitorRegion, userAgent, _ := captureVisitorMeta(c)
deviceKey := normalizeDeviceKey(req.DeviceID, userAgent)
// 黑名单拦截(IP / 设备)
if blocked, blKind, blReason := checkVisitorBlacklist(channel.TenantID, visitorIP, deviceKey); blocked {
kindLabel := "IP"
if blKind == "device" {
kindLabel = "设备"
}
msg := "您暂时无法使用在线客服"
if strings.TrimSpace(blReason) != "" {
msg = msg + "" + kindLabel + "限制)"
}
c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": msg})
return
}
pageURL := sanitizePageURL(req.PageURL)
if pageURL == "" {
// query 兜底
@@ -144,6 +160,7 @@ func (h *WidgetHandler) Init(c *gin.Context) {
VisitorIP: visitorIP,
VisitorRegion: visitorRegion,
UserAgent: userAgent,
DeviceKey: deviceKey,
LandingURL: pageURL,
LandingTitle: pageTitle,
Referrer: referrer,