From 0239603868df97e9a875401ce76cccf0a42ca5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A1=E8=8B=A5?= Date: Sun, 8 Mar 2026 08:51:56 +0800 Subject: [PATCH] =?UTF-8?q?sync:=20soul-api=20=E6=8E=A5=E5=8F=A3=E9=80=BB?= =?UTF-8?q?=E8=BE=91=20|=20=E5=8E=9F=E5=9B=A0:=20=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E9=80=BB=E8=BE=91=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/handler/admin_shensheshou.go | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/soul-api/internal/handler/admin_shensheshou.go b/soul-api/internal/handler/admin_shensheshou.go index 24091e72..efa6c665 100644 --- a/soul-api/internal/handler/admin_shensheshou.go +++ b/soul-api/internal/handler/admin_shensheshou.go @@ -139,6 +139,105 @@ func AdminShensheShouIngest(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "data": result["data"]}) } +// AdminShensheShouEnrich POST /api/admin/shensheshou/enrich — 查询并回填用户基础信息 +func AdminShensheShouEnrich(c *gin.Context) { + if sssAPIKey() == "" { + c.JSON(http.StatusOK, gin.H{"success": false, "error": "神射手 API Key 未配置"}) + return + } + + var body struct { + UserID string `json:"userId" binding:"required"` + Phone string `json:"phone"` + OpenID string `json:"openId"` + WechatID string `json:"wechatId"` + Address string `json:"address"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "参数错误"}) + return + } + + if body.Phone == "" && body.OpenID == "" && body.WechatID == "" { + c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "至少提供手机号、OpenID 或微信号之一"}) + return + } + + // 查询神射手 + queryURL := sssBaseURL() + "?endpoint=user" + if body.Phone != "" { + queryURL += "&phone=" + body.Phone + } + + sssResult, err := sssDoRequest(http.MethodGet, queryURL, nil) + if err != nil { + c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()}) + return + } + + var sssData map[string]interface{} + if d, ok := sssResult["data"].(map[string]interface{}); ok { + sssData = d + } + + // 将神射手数据回填到用户 tags + if sssData != nil { + db := database.DB() + updates := make(map[string]interface{}) + + // 自动合并标签 + if tags, ok := sssData["tags"].([]interface{}); ok && len(tags) > 0 { + tagStrs := make([]string, 0, len(tags)) + for _, t := range tags { + if s, ok := t.(string); ok { + tagStrs = append(tagStrs, s) + } + } + if len(tagStrs) > 0 { + tagsJSON, _ := json.Marshal(tagStrs) + updates["ckb_tags"] = string(tagsJSON) + } + } + + if len(updates) > 0 { + db.Table("users").Where("id = ?", body.UserID).Updates(updates) + } + } + + c.JSON(http.StatusOK, gin.H{"success": true, "data": sssData}) +} + +// AdminShensheShouAutoTag POST /api/admin/shensheshou/auto-tag — 基于行为自动打标(内部调用) +func AdminShensheShouAutoTag(userID string, phone string) { + if sssAPIKey() == "" || phone == "" { + return + } + go func() { + queryURL := sssBaseURL() + "?endpoint=user&phone=" + phone + result, err := sssDoRequest(http.MethodGet, queryURL, nil) + if err != nil || result == nil { + return + } + data, ok := result["data"].(map[string]interface{}) + if !ok { + return + } + tags, ok := data["tags"].([]interface{}) + if !ok || len(tags) == 0 { + return + } + tagStrs := make([]string, 0, len(tags)) + for _, t := range tags { + if s, ok := t.(string); ok { + tagStrs = append(tagStrs, s) + } + } + tagsJSON, _ := json.Marshal(tagStrs) + database.DB().Table("users").Where("id = ?", userID). + Updates(map[string]interface{}{"ckb_tags": string(tagsJSON)}) + }() +} + // AdminShensheShouBatchQuery POST /api/admin/shensheshou/batch — 批量查询 func AdminShensheShouBatchQuery(c *gin.Context) { if sssAPIKey() == "" {