Files
soul-yongping/soul-api/internal/handler/db_ckb_leads.go

207 lines
6.2 KiB
Go
Raw Normal View History

package handler
import (
"net/http"
"strconv"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
)
// DBCKBLeadList GET /api/db/ckb-leads 管理端-CKB线索明细
// mode=submitted: ckb_submit_recordsjoin/match 提交)
// mode=contact: ckb_lead_records链接卡若留资有 phone/wechat
func DBCKBLeadList(c *gin.Context) {
db := database.DB()
mode := c.DefaultQuery("mode", "submitted")
matchType := c.Query("matchType")
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
if mode == "contact" {
// ckb_lead_records链接卡若留资
q := db.Model(&model.CkbLeadRecord{})
var total int64
q.Count(&total)
var records []model.CkbLeadRecord
if err := q.Order("created_at DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&records).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
out := make([]gin.H, 0, len(records))
for _, r := range records {
out = append(out, gin.H{
"id": r.ID,
"userId": r.UserID,
"userNickname": r.Nickname,
"matchType": "lead",
"phone": r.Phone,
"wechatId": r.WechatID,
"name": r.Name,
"createdAt": r.CreatedAt,
})
}
c.JSON(http.StatusOK, gin.H{"success": true, "records": out, "total": total, "page": page, "pageSize": pageSize})
return
}
// mode=submitted: ckb_submit_records
q := db.Model(&model.CkbSubmitRecord{})
if matchType != "" {
// matchType 对应 action: join 时 type 在 params 中match 时 matchType 在 params 中
// 简化:仅按 action 过滤join 时 params 含 type
if matchType == "join" || matchType == "match" {
q = q.Where("action = ?", matchType)
}
}
var total int64
q.Count(&total)
var records []model.CkbSubmitRecord
if err := q.Order("created_at DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&records).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
userIDs := make(map[string]bool)
for _, r := range records {
if r.UserID != "" {
userIDs[r.UserID] = true
}
}
ids := make([]string, 0, len(userIDs))
for id := range userIDs {
ids = append(ids, id)
}
var users []model.User
if len(ids) > 0 {
db.Where("id IN ?", ids).Find(&users)
}
userMap := make(map[string]*model.User)
for i := range users {
userMap[users[i].ID] = &users[i]
}
safeNickname := func(u *model.User) string {
if u == nil || u.Nickname == nil {
return ""
}
return *u.Nickname
}
out := make([]gin.H, 0, len(records))
for _, r := range records {
out = append(out, gin.H{
"id": r.ID,
"userId": r.UserID,
"userNickname": safeNickname(userMap[r.UserID]),
"matchType": r.Action,
"nickname": r.Nickname,
"params": r.Params,
"createdAt": r.CreatedAt,
})
}
c.JSON(http.StatusOK, gin.H{"success": true, "records": out, "total": total, "page": page, "pageSize": pageSize})
}
// CKBPersonLeadStats GET /api/db/ckb-person-leads 每个人物的获客线索统计及明细
func CKBPersonLeadStats(c *gin.Context) {
db := database.DB()
personToken := c.Query("token")
if personToken != "" {
// 返回某人物的线索明细(通过 token → Person.PersonID → CkbLeadRecord.TargetPersonID
var person model.Person
if err := db.Where("token = ?", personToken).First(&person).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "人物不存在"})
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
q := db.Model(&model.CkbLeadRecord{}).Where("target_person_id = ?", person.Token)
var total int64
q.Count(&total)
var records []model.CkbLeadRecord
q.Order("created_at DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&records)
out := make([]gin.H, 0, len(records))
for _, r := range records {
out = append(out, gin.H{
"id": r.ID,
"userId": r.UserID,
"nickname": r.Nickname,
"phone": r.Phone,
"wechatId": r.WechatID,
"name": r.Name,
"source": r.Source,
"createdAt": r.CreatedAt,
})
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"personName": person.Name,
"records": out,
"total": total,
"page": page,
"pageSize": pageSize,
})
return
}
// 无 token 参数:返回所有人物的获客数量汇总
type PersonLeadStat struct {
Token string `gorm:"column:target_person_id" json:"token"`
Total int64 `gorm:"column:total" json:"total"`
}
var stats []PersonLeadStat
db.Raw("SELECT target_person_id, COUNT(*) as total FROM ckb_lead_records WHERE target_person_id != '' GROUP BY target_person_id").Scan(&stats)
// 同时统计全局(无特定人物的)线索
var globalTotal int64
db.Model(&model.CkbLeadRecord{}).Where("target_person_id = '' OR target_person_id IS NULL").Count(&globalTotal)
c.JSON(http.StatusOK, gin.H{
"success": true,
"byPerson": stats,
"globalLeads": globalTotal,
})
}
// CKBPlanStats GET /api/db/ckb-plan-stats 存客宝获客计划统计(基于 ckb_submit_records + ckb_lead_records
func CKBPlanStats(c *gin.Context) {
db := database.DB()
type TypeStat struct {
Action string `gorm:"column:action" json:"matchType"`
Total int64 `gorm:"column:total" json:"total"`
}
var submitStats []TypeStat
db.Raw("SELECT action, COUNT(*) as total FROM ckb_submit_records GROUP BY action").Scan(&submitStats)
var submitTotal int64
db.Model(&model.CkbSubmitRecord{}).Count(&submitTotal)
var leadTotal int64
db.Model(&model.CkbLeadRecord{}).Count(&leadTotal)
withContact := leadTotal // ckb_lead_records 均有 phone 或 wechat
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"ckbTotal": submitTotal + leadTotal,
"withContact": withContact,
"byType": submitStats,
"ckbApiKey": "***",
"ckbApiUrl": "https://ckbapi.quwanzhi.com/v1/api/scenarios",
"docNotes": "",
"docContent": "",
"routes": gin.H{},
},
})
}