forked from all_user/stat_center
新增广告V2模块,双端下载落地页调整
- 新增 advitise v2: info/location/bind/click-stat/day-click-stat 模型与 对应的 service、api、router、proto 定义 - models/index.go 注册 5 个新模型的索引初始化 - 鉴权白名单: /rsdownload/ 改为 /download/,放行 advitise v2 的 get/click 接口 - statg/config: proxyUrl 增加 fileRes1 - common/genId: lid 生成逻辑补充 - 新增 91fans / huangguo 的 mobileconfig 描述文件 - 新增 deploy/nginx/cpcdownload.mfcg.me.conf 网关配置 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,106 @@
|
|||||||
|
package advitiseV2Api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/stdLog"
|
||||||
|
"stat/common/utils"
|
||||||
|
"stat/service/advitiseV2Ser"
|
||||||
|
"stat/service/opLogSer"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/绑定
|
||||||
|
// @Summary 绑定关系列表
|
||||||
|
// @Router /api/stat/advitise/v2/bind/list [POST]
|
||||||
|
// @Param param body proto.AdvitiseBindListReq true "参数"
|
||||||
|
// @Success 200 {object} proto.AdvitiseBindListResp "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func BindList(ctx *gin.Context) {
|
||||||
|
req := &proto.AdvitiseBindListReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := advitiseV2Ser.BindList(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/绑定
|
||||||
|
// @Summary 新增绑定
|
||||||
|
// @Router /api/stat/advitise/v2/bind/add [POST]
|
||||||
|
// @Param param body proto.AddAdvitiseBindReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func BindAdd(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.AddAdvitiseBindReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.BindAdd(ctx, req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/绑定
|
||||||
|
// @Summary 更新绑定
|
||||||
|
// @Router /api/stat/advitise/v2/bind/update [POST]
|
||||||
|
// @Param param body proto.UpdateAdvitiseBindReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func BindUpdate(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.UpdateAdvitiseBindReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.BindUpdate(ctx, req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/绑定
|
||||||
|
// @Summary 删除绑定
|
||||||
|
// @Router /api/stat/advitise/v2/bind/del [POST]
|
||||||
|
// @Param param body proto.DelAdvitiseBindReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func BindDel(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.DelAdvitiseBindReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.BindDel(ctx, req.Id); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package advitiseV2Api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/stdLog"
|
||||||
|
"stat/service/advitiseV2Ser"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/外部
|
||||||
|
// @Summary 拉广告列表(客户端)
|
||||||
|
// @Description 按 (appId, locationId?) 返回可展示广告;结构对齐老 /ads/get(advertiseList);每条 item 多带 bindId 供点击回传
|
||||||
|
// @Router /api/stat/advitise/v2/get [POST]
|
||||||
|
// @Param param body proto.GetAdvitiseV2Req true "参数"
|
||||||
|
// @Success 200 {object} proto.AdvertiseRes "成功"
|
||||||
|
func GetAdvitises(ctx *gin.Context) {
|
||||||
|
req := &proto.GetAdvitiseV2Req{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := advitiseV2Ser.GetAdvitises(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 对齐老 GetAds 直接 ctx.JSON(200, data) 的行为
|
||||||
|
ctx.JSON(200, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/外部
|
||||||
|
// @Summary 广告点击(客户端)
|
||||||
|
// @Description 根据 GetAds 返回的 bindId 上报点击,服务端反查 (广告, 位置) 并沿用老统计逻辑(redis 时段 hash + doc 累计)
|
||||||
|
// @Router /api/stat/advitise/v2/click [POST]
|
||||||
|
// @Param param body proto.ClickAdvitiseV2Req true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
func ClickAdvitise(ctx *gin.Context) {
|
||||||
|
req := &proto.ClickAdvitiseV2Req{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.ClickAdvitise(ctx, req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package advitiseV2Api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/stdLog"
|
||||||
|
"stat/common/utils"
|
||||||
|
"stat/service/advitiseV2Ser"
|
||||||
|
"stat/service/opLogSer"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/素材
|
||||||
|
// @Summary 素材列表
|
||||||
|
// @Router /api/stat/advitise/v2/info/list [POST]
|
||||||
|
// @Param param body proto.AdvitiseInfoListReq true "参数"
|
||||||
|
// @Success 200 {object} proto.AdvitiseInfoListResp "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func InfoList(ctx *gin.Context) {
|
||||||
|
req := &proto.AdvitiseInfoListReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := advitiseV2Ser.InfoList(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/素材
|
||||||
|
// @Summary 新增素材
|
||||||
|
// @Router /api/stat/advitise/v2/info/add [POST]
|
||||||
|
// @Param param body proto.AddAdvitiseInfoReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func InfoAdd(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.AddAdvitiseInfoReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.InfoAdd(ctx, req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/素材
|
||||||
|
// @Summary 更新素材
|
||||||
|
// @Router /api/stat/advitise/v2/info/update [POST]
|
||||||
|
// @Param param body proto.UpdateAdvitiseInfoReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func InfoUpdate(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.UpdateAdvitiseInfoReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.InfoUpdate(ctx, req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/素材
|
||||||
|
// @Summary 删除素材
|
||||||
|
// @Router /api/stat/advitise/v2/info/del [POST]
|
||||||
|
// @Param param body proto.DelAdvitiseInfoReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func InfoDel(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.DelAdvitiseInfoReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.InfoDel(ctx, req.Id); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package advitiseV2Api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/stdLog"
|
||||||
|
"stat/common/utils"
|
||||||
|
"stat/service/advitiseV2Ser"
|
||||||
|
"stat/service/opLogSer"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/位置
|
||||||
|
// @Summary 广告位列表
|
||||||
|
// @Router /api/stat/advitise/v2/location/list [POST]
|
||||||
|
// @Param param body proto.AdvitiseLocationListReq true "参数"
|
||||||
|
// @Success 200 {object} proto.AdvitiseLocationListResp "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func LocationList(ctx *gin.Context) {
|
||||||
|
req := &proto.AdvitiseLocationListReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := advitiseV2Ser.LocationList(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/位置
|
||||||
|
// @Summary 新增广告位
|
||||||
|
// @Router /api/stat/advitise/v2/location/add [POST]
|
||||||
|
// @Param param body proto.AddAdvitiseLocationReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func LocationAdd(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.AddAdvitiseLocationReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.LocationAdd(ctx, req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/位置
|
||||||
|
// @Summary 更新广告位
|
||||||
|
// @Router /api/stat/advitise/v2/location/update [POST]
|
||||||
|
// @Param param body proto.UpdateAdvitiseLocationReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func LocationUpdate(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.UpdateAdvitiseLocationReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.LocationUpdate(ctx, req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/位置
|
||||||
|
// @Summary 删除广告位
|
||||||
|
// @Router /api/stat/advitise/v2/location/del [POST]
|
||||||
|
// @Param param body proto.DelAdvitiseLocationReq true "参数"
|
||||||
|
// @Success 200 {string} string "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func LocationDel(ctx *gin.Context) {
|
||||||
|
account, err := utils.GetAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.NoToken, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req := &proto.DelAdvitiseLocationReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := advitiseV2Ser.LocationDel(ctx, req.Id); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opLogSer.AddOpLog(ctx, account, true, req)
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, "")
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package advitiseV2Api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/stdLog"
|
||||||
|
"stat/service/advitiseV2Ser"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/统计
|
||||||
|
// @Summary 广告每日点击列表(汇总)
|
||||||
|
// @Router /api/stat/advitise/v2/day/click/list [POST]
|
||||||
|
// @Param param body proto.AdvitiseDayClickListReq true "参数"
|
||||||
|
// @Success 200 {object} proto.AdvitiseDayClickListResp "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func DayClickList(ctx *gin.Context) {
|
||||||
|
req := &proto.AdvitiseDayClickListReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := advitiseV2Ser.DayClickList(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/统计
|
||||||
|
// @Summary 广告点击详情(细维度)
|
||||||
|
// @Router /api/stat/advitise/v2/day/click/info [POST]
|
||||||
|
// @Param param body proto.AdvitiseClickListReq true "参数"
|
||||||
|
// @Success 200 {object} proto.AdvitiseClickListResp "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func DayClickInfo(ctx *gin.Context) {
|
||||||
|
req := &proto.AdvitiseClickListReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := advitiseV2Ser.ClickList(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/统计
|
||||||
|
// @Summary 广告细维度点击列表(广告位查看统计入口)
|
||||||
|
// @Router /api/stat/advitise/v2/click/list [POST]
|
||||||
|
// @Param param body proto.AdvitiseClickListReq true "参数"
|
||||||
|
// @Success 200 {object} proto.AdvitiseClickListResp "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func ClickList(ctx *gin.Context) {
|
||||||
|
// 与 DayClickInfo 语义一致,复用同一入口
|
||||||
|
DayClickInfo(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags 广告管理V2/统计
|
||||||
|
// @Summary 按时间范围汇总广告点击量(每广告一行)
|
||||||
|
// @Router /api/stat/advitise/v2/day/click/summary [POST]
|
||||||
|
// @Param param body proto.AdvitiseClickSummaryReq true "参数"
|
||||||
|
// @Success 200 {object} proto.AdvitiseClickSummaryResp "成功"
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
func ClickSummary(ctx *gin.Context) {
|
||||||
|
req := &proto.AdvitiseClickSummaryReq{}
|
||||||
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := advitiseV2Ser.ClickSummary(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stdLog.ServerJSON(ctx, stdLog.Success, resp)
|
||||||
|
}
|
||||||
+2
-1
@@ -25,9 +25,10 @@ func FileUpload(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 上传到桶2
|
// 上传到桶2
|
||||||
data, err := file.PutObject(ctx, statg.Conf.ProxyUrl.FileRes, &file.FileObject{
|
data, err := file.PutObject(ctx, statg.Conf.ProxyUrl.FileRes1, &file.FileObject{
|
||||||
File: f,
|
File: f,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
stdLog.ServerJSON(ctx, stdLog.Failure, err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-12
@@ -107,21 +107,23 @@ type AdvertiseRes struct {
|
|||||||
|
|
||||||
// 外部广告信息
|
// 外部广告信息
|
||||||
type AdvertiseInfo struct {
|
type AdvertiseInfo struct {
|
||||||
Id int64 `json:"id"` // 广告id
|
Id int64 `json:"id"` // 广告id(V2 = advitiseId)
|
||||||
Title string `json:"title"` // 广告标题
|
Title string `json:"title"` // 广告标题
|
||||||
CoverImg string `json:"coverImg"` // 封面
|
CoverImg string `json:"coverImg"` // 封面
|
||||||
LocId int32 `json:"locId"` // 位置id
|
LocId int32 `json:"locId"` // 位置id
|
||||||
JumpType advertiseMod.JumpType `json:"jumpType"` // 跳转方式 0:外部浏览器跳转 1:内部浏览器跳转 2:app内部跳转
|
JumpType advertiseMod.JumpType `json:"jumpType"` // 跳转方式 0:外部浏览器跳转 1:内部浏览器跳转 2:app内部跳转
|
||||||
Link string `json:"link"` // 链接地址
|
Link string `json:"link"` // 链接地址
|
||||||
Sort int64 `json:"sort"` // 排序
|
Sort int64 `json:"sort"` // 排序
|
||||||
Tags string `json:"tags"` // 标签
|
Tags string `json:"tags"` // 标签
|
||||||
Remark string `json:"remark"` // 备注描述
|
Remark string `json:"remark"` // 备注描述
|
||||||
AmbientColor string `json:"ambientColor"` // 氛围色(逼哩漫画)
|
AmbientColor string `json:"ambientColor"` // 氛围色(逼哩漫画)
|
||||||
Type int // 0:系统 1:渠道
|
Type int // 0:系统 1:渠道
|
||||||
|
BindId int64 `json:"bindId,omitempty"` // V2 点击回传凭证(老接口不填,omitempty 隐藏)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 广告点击请求
|
// 广告点击请求
|
||||||
type AdsClickReq struct {
|
type AdsClickReq struct {
|
||||||
Id *int64 `from:"id" json:"id" binding:"required"` // 广告id
|
Id *int64 `from:"id" json:"id" binding:"required"` // 广告id(客户端上报,可能已过期)
|
||||||
AppId *int32 `from:"appId" json:"appId" binding:"required"` // 应用id
|
AppId *int32 `from:"appId" json:"appId" binding:"required"` // 应用id
|
||||||
|
LocId *int32 `from:"locId" json:"locId"` // 位置id(可选;传入后,Id 失效时会按 AppId+LocId 定位最新广告)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,232 @@
|
|||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/models/advitiseBindMod"
|
||||||
|
"stat/models/advitiseInfoMod"
|
||||||
|
"stat/models/advitiseLocationMod"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ============ 广告素材(Info) ============
|
||||||
|
|
||||||
|
type AdvitiseInfoListReq struct {
|
||||||
|
Title string `json:"title" form:"title"`
|
||||||
|
Remark string `json:"remark" form:"remark"`
|
||||||
|
Status *bool `json:"status" form:"status"`
|
||||||
|
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required,gte=1"`
|
||||||
|
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required,gte=1,lte=500"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseInfoListResp struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
List advitiseInfoMod.AdvitiseInfoList `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddAdvitiseInfoReq struct {
|
||||||
|
Title string `json:"title" binding:"required"`
|
||||||
|
FullScreenImgs []string `json:"fullScreenImgs"`
|
||||||
|
Banner720300Imgs []string `json:"banner720300Imgs"`
|
||||||
|
Banner720150Imgs []string `json:"banner720150Imgs"`
|
||||||
|
Banner750700Imgs []string `json:"banner750700Imgs"`
|
||||||
|
Banner800450Imgs []string `json:"banner800450Imgs"`
|
||||||
|
PopUps600800Imgs []string `json:"popUps600800Imgs"`
|
||||||
|
PopUps512512Imgs []string `json:"popUps512512Imgs"`
|
||||||
|
SmallCubeImgs []string `json:"smallCubeImgs"`
|
||||||
|
VerticalCubeImgs []string `json:"verticalCubeImgs"`
|
||||||
|
RandomNames []string `json:"randomNames"`
|
||||||
|
Link string `json:"link"`
|
||||||
|
Status bool `json:"status"`
|
||||||
|
StartTime time.Time `json:"startTime"`
|
||||||
|
EndTime time.Time `json:"endTime"`
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateAdvitiseInfoReq struct {
|
||||||
|
Id int64 `json:"id" binding:"required"`
|
||||||
|
Title *string `json:"title"`
|
||||||
|
FullScreenImgs *[]string `json:"fullScreenImgs"`
|
||||||
|
Banner720300Imgs *[]string `json:"banner720300Imgs"`
|
||||||
|
Banner720150Imgs *[]string `json:"banner720150Imgs"`
|
||||||
|
Banner750700Imgs *[]string `json:"banner750700Imgs"`
|
||||||
|
Banner800450Imgs *[]string `json:"banner800450Imgs"`
|
||||||
|
PopUps600800Imgs *[]string `json:"popUps600800Imgs"`
|
||||||
|
PopUps512512Imgs *[]string `json:"popUps512512Imgs"`
|
||||||
|
SmallCubeImgs *[]string `json:"smallCubeImgs"`
|
||||||
|
VerticalCubeImgs *[]string `json:"verticalCubeImgs"`
|
||||||
|
RandomNames *[]string `json:"randomNames"`
|
||||||
|
Link *string `json:"link"`
|
||||||
|
Status *bool `json:"status"`
|
||||||
|
StartTime *time.Time `json:"startTime"`
|
||||||
|
EndTime *time.Time `json:"endTime"`
|
||||||
|
Remark *string `json:"remark"`
|
||||||
|
Desc *string `json:"desc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DelAdvitiseInfoReq struct {
|
||||||
|
Id int64 `json:"id" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ 广告位(Location) ============
|
||||||
|
|
||||||
|
type AdvitiseLocationListReq struct {
|
||||||
|
AppId *int32 `json:"appId" form:"appId"`
|
||||||
|
LocId *int32 `json:"locId" form:"locId"`
|
||||||
|
Name string `json:"name" form:"name"`
|
||||||
|
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required,gte=1"`
|
||||||
|
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required,gte=1,lte=500"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseLocationListResp struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
List advitiseLocationMod.AdvitiseLocationList `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddAdvitiseLocationReq struct {
|
||||||
|
AppId int32 `json:"appId" binding:"required"`
|
||||||
|
LocId int32 `json:"locId" binding:"required"`
|
||||||
|
Name string `json:"name" binding:"required"`
|
||||||
|
AdvitiseSize advitiseLocationMod.AdvitiseSizeType `json:"advitiseSize"`
|
||||||
|
ImgSizeDesc string `json:"imgSizeDesc"`
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateAdvitiseLocationReq struct {
|
||||||
|
Id int64 `json:"id" binding:"required"`
|
||||||
|
AppId *int32 `json:"appId"`
|
||||||
|
LocId *int32 `json:"locId"`
|
||||||
|
Name *string `json:"name"`
|
||||||
|
AdvitiseSize *advitiseLocationMod.AdvitiseSizeType `json:"advitiseSize"`
|
||||||
|
ImgSizeDesc *string `json:"imgSizeDesc"`
|
||||||
|
Remark *string `json:"remark"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DelAdvitiseLocationReq struct {
|
||||||
|
Id int64 `json:"id" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ 广告绑定(Bind) ============
|
||||||
|
|
||||||
|
type AdvitiseBindListReq struct {
|
||||||
|
AppId *int32 `json:"appId" form:"appId"`
|
||||||
|
AdvitiseId *int64 `json:"advitiseId" form:"advitiseId"`
|
||||||
|
LocationId *int32 `json:"locationId" form:"locationId"`
|
||||||
|
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required,gte=1"`
|
||||||
|
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required,gte=1,lte=500"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseBindListResp struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
List advitiseBindMod.AdvitiseBindList `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddAdvitiseBindReq struct {
|
||||||
|
AppId int32 `json:"appId" binding:"required"`
|
||||||
|
AdvitiseId int64 `json:"advitiseId" binding:"required"`
|
||||||
|
LocationId []int32 `json:"locationId" binding:"required"`
|
||||||
|
Sort int64 `json:"sort"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateAdvitiseBindReq struct {
|
||||||
|
Id int64 `json:"id" binding:"required"`
|
||||||
|
AppId *int32 `json:"appId"`
|
||||||
|
AdvitiseId *int64 `json:"advitiseId"`
|
||||||
|
LocationId *[]int32 `json:"locationId"`
|
||||||
|
Sort *int64 `json:"sort"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DelAdvitiseBindReq struct {
|
||||||
|
Id int64 `json:"id" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ 外部获取广告 / 点击 ============
|
||||||
|
|
||||||
|
// GetAdvitiseV2Req 客户端拉广告列表
|
||||||
|
type GetAdvitiseV2Req struct {
|
||||||
|
AppId int32 `json:"appId" binding:"required"`
|
||||||
|
LocationId *int32 `json:"locationId"` // 可选,指定位置
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应结构直接复用老 proto.AdvertiseRes (advertiseList) — V2 客户端从 item.bindId 拿点击回传凭证
|
||||||
|
|
||||||
|
// ClickAdvitiseV2Req 客户端点击回传
|
||||||
|
// LocationId 必须传:细维度统计表(advitise_click_stat)按 (appId, advitiseId, locationId, day) 聚合
|
||||||
|
type ClickAdvitiseV2Req struct {
|
||||||
|
Id int64 `from:"id" json:"id" binding:"required"` // 广告id
|
||||||
|
// LocationId int32 `json:"locationId" binding:"required"` // 客户端展示时选中的位置
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ 统计管理 ============
|
||||||
|
|
||||||
|
// AdvitiseDayClickListReq 每日点击列表(汇总,来自 advitise_day_click_stat)
|
||||||
|
type AdvitiseDayClickListReq struct {
|
||||||
|
Id *int64 `json:"id" form:"id"` // 广告id(advitiseId)
|
||||||
|
StatStartDate string `json:"statStartDate" form:"statStartDate"` // yyyy-MM-dd HH:mm:ss
|
||||||
|
StatEndDate string `json:"statEndDate" form:"statEndDate"`
|
||||||
|
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required,gte=1"`
|
||||||
|
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required,gte=1,lte=500"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseDayClickItem struct {
|
||||||
|
AdsId int64 `json:"adsId"` // 广告id (advitiseId)
|
||||||
|
AdsName string `json:"adsName"` // 广告标题
|
||||||
|
Clicks int64 `json:"clicks"`
|
||||||
|
StatDate string `json:"statDate"` // yyyy-MM-dd
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseDayClickListResp struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
List []*AdvitiseDayClickItem `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdvitiseClickListReq 细维度列表(来自 advitise_click_stat)
|
||||||
|
type AdvitiseClickListReq struct {
|
||||||
|
AdsId *int64 `json:"adsId" form:"adsId"` // 广告id(advitiseId)
|
||||||
|
AppId *int32 `json:"appId" form:"appId"`
|
||||||
|
LocationId *int32 `json:"locationId" form:"locationId"`
|
||||||
|
StatStartDate string `json:"statStartDate" form:"statStartDate"`
|
||||||
|
StatEndDate string `json:"statEndDate" form:"statEndDate"`
|
||||||
|
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required,gte=1"`
|
||||||
|
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required,gte=1,lte=500"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseClickItem struct {
|
||||||
|
AppId int32 `json:"appId"`
|
||||||
|
AppName string `json:"appName"`
|
||||||
|
AdsId int64 `json:"adsId"`
|
||||||
|
AdsName string `json:"adsName"`
|
||||||
|
LocationId int32 `json:"locationId"`
|
||||||
|
LocationName string `json:"locationName"`
|
||||||
|
Clicks int64 `json:"clicks"`
|
||||||
|
StatDate string `json:"statDate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseClickListResp struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
List []*AdvitiseClickItem `json:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdvitiseClickSummaryReq 按时间范围汇总广告点击量,每个广告一行
|
||||||
|
// StatStartDate/StatEndDate 至少填一个;可选 id/appId/locationId 缩窄范围
|
||||||
|
type AdvitiseClickSummaryReq struct {
|
||||||
|
Id *int64 `json:"id" form:"id"`
|
||||||
|
AppId *int32 `json:"appId" form:"appId"`
|
||||||
|
LocationId *int32 `json:"locationId" form:"locationId"`
|
||||||
|
StatStartDate string `json:"statStartDate" form:"statStartDate"`
|
||||||
|
StatEndDate string `json:"statEndDate" form:"statEndDate"`
|
||||||
|
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required,gte=1"`
|
||||||
|
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required,gte=1,lte=500"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseClickSummaryItem struct {
|
||||||
|
AdsId int64 `json:"adsId"`
|
||||||
|
AdsName string `json:"adsName"`
|
||||||
|
TotalClicks int64 `json:"totalClicks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseClickSummaryResp struct {
|
||||||
|
Total int64 `json:"total"` // 匹配到的广告数
|
||||||
|
GrandTotal int64 `json:"grandTotal"` // 时间范围内所有点击总量
|
||||||
|
List []*AdvitiseClickSummaryItem `json:"list"`
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
// @Success 200 {file} file "ios返回mobileconfig文件"
|
// @Success 200 {file} file "ios返回mobileconfig文件"
|
||||||
// @Success 302 {string} string "android跳转下载地址"
|
// @Success 302 {string} string "android跳转下载地址"
|
||||||
// @Failure 400 {string} string "失败"
|
// @Failure 400 {string} string "失败"
|
||||||
// @Router /rsdownload/{appId}/{channel} [get]
|
// @Router /download/{appId}/{channel} [get]
|
||||||
func CpcDownload(ctx *gin.Context) {
|
func CpcDownload(ctx *gin.Context) {
|
||||||
// 第一个参数 appId
|
// 第一个参数 appId
|
||||||
appId, err := strconv.Atoi(ctx.Param("appId"))
|
appId, err := strconv.Atoi(ctx.Param("appId"))
|
||||||
|
|||||||
+31
-1
@@ -20,7 +20,10 @@ var audioBook *lid.Lid // 有声小说自增器
|
|||||||
var landpageConfig *lid.Lid // 落地页配置id
|
var landpageConfig *lid.Lid // 落地页配置id
|
||||||
var appCategory *lid.Lid //
|
var appCategory *lid.Lid //
|
||||||
var appLocLid *lid.Lid // 应用中心位置id自增器
|
var appLocLid *lid.Lid // 应用中心位置id自增器
|
||||||
var cpcDownloadCfgLid *lid.Lid // CPC下载配置id自增器
|
var cpcDownloadCfgLid *lid.Lid // CPC下载配置id自增器
|
||||||
|
var advitiseInfoLid *lid.Lid // 广告素材(V2) id自增器
|
||||||
|
var advitiseLocationLid *lid.Lid // 广告位(V2) id自增器
|
||||||
|
var advitiseBindLid *lid.Lid // 广告绑定(V2) id自增器
|
||||||
|
|
||||||
func Start() {
|
func Start() {
|
||||||
var err error
|
var err error
|
||||||
@@ -104,6 +107,21 @@ func Start() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
advitiseInfoLid, err = lid.NewLid(collection, "advitise_info_id", 100)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
advitiseLocationLid, err = lid.NewLid(collection, "advitise_location_id", 100)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
advitiseBindLid, err = lid.NewLid(collection, "advitise_bind_id", 100)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNextRoleId() int64 {
|
func GetNextRoleId() int64 {
|
||||||
@@ -169,3 +187,15 @@ func GetNextAppLocId() int64 {
|
|||||||
func GetCpcDownloadCfgId() int64 {
|
func GetCpcDownloadCfgId() int64 {
|
||||||
return cpcDownloadCfgLid.Get()
|
return cpcDownloadCfgLid.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAdvitiseInfoId() int64 {
|
||||||
|
return advitiseInfoLid.Get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAdvitiseLocationId() int64 {
|
||||||
|
return advitiseLocationLid.Get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAdvitiseBindId() int64 {
|
||||||
|
return advitiseBindLid.Get()
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,58 @@
|
|||||||
|
# /etc/nginx/conf.d/cpcdownload.mfcg.me.conf
|
||||||
|
#
|
||||||
|
# cpcdownload.mfcg.me -> stat_center Go 服务 (127.0.0.1:8089)
|
||||||
|
# 用途:
|
||||||
|
# - GET /download/{appId}/{channel} 双端下载落地页(ios 返回 mobileconfig / android 302 跳转)
|
||||||
|
# - POST /api/stat/cpc/download/{list,add,update,del} 后台 CPC 下载配置管理
|
||||||
|
#
|
||||||
|
# 部署:
|
||||||
|
# scp deploy/nginx/cpcdownload.mfcg.me.conf root@<gateway>:/etc/nginx/conf.d/
|
||||||
|
# ssh root@<gateway> 'nginx -t && nginx -s reload'
|
||||||
|
|
||||||
|
# HTTP -> HTTPS
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name cpcdownload.mfcg.me;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
server_name cpcdownload.mfcg.me;
|
||||||
|
|
||||||
|
# 证书路径按你机器上的实际位置调整(沿用同 mfcg.me 通配证书即可)
|
||||||
|
ssl_certificate /etc/nginx/ssl/mfcg.me/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/mfcg.me/privkey.pem;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
ssl_session_timeout 10m;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/cpcdownload.mfcg.me.access.log;
|
||||||
|
error_log /var/log/nginx/cpcdownload.mfcg.me.error.log;
|
||||||
|
|
||||||
|
# mobileconfig 大小通常很小,这里放宽到 8M 兜底
|
||||||
|
client_max_body_size 8m;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:8089;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
|
||||||
|
# 透传真实 IP(后端 ctx.ClientIP() 依赖此头取 IP 入库 landingpage_cpc)
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# mobileconfig 是二进制,保持原样;不做缓冲以便 302 立即下发
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_request_buffering off;
|
||||||
|
|
||||||
|
proxy_connect_timeout 5s;
|
||||||
|
proxy_send_timeout 30s;
|
||||||
|
proxy_read_timeout 30s;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -86,7 +86,9 @@ var (
|
|||||||
"/api/stat/daily-stat/hour",
|
"/api/stat/daily-stat/hour",
|
||||||
"/api/stat/daily-stat/rank",
|
"/api/stat/daily-stat/rank",
|
||||||
"/api/stat/daily-stat/total",
|
"/api/stat/daily-stat/total",
|
||||||
"/rsdownload/",
|
"/download/",
|
||||||
|
"/api/stat/advitise/v2/get",
|
||||||
|
"/api/stat/advitise/v2/click",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,30 @@ func FindAdsById(ctx context.Context, id int64) (data Advertise, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindLatestAdsByAppAndLoc 取该应用/位置当前生效的最新一条广告(用于点击回退到最新广告)
|
||||||
|
// locId <= 0 表示不按位置过滤,只在应用维度取最新
|
||||||
|
func FindLatestAdsByAppAndLoc(ctx context.Context, appId, locId int32) (data Advertise, err error) {
|
||||||
|
now := time.Now()
|
||||||
|
filter := bson.M{
|
||||||
|
"appId": appId,
|
||||||
|
"isActive": true,
|
||||||
|
"startTime": bson.M{"$lte": now},
|
||||||
|
"endTime": bson.M{"$gte": now},
|
||||||
|
}
|
||||||
|
if locId > 0 {
|
||||||
|
filter["locId"] = locId
|
||||||
|
}
|
||||||
|
opts := options.FindOne().SetSort(bson.D{
|
||||||
|
{Key: "sort", Value: 1},
|
||||||
|
{Key: "createAt", Value: -1},
|
||||||
|
})
|
||||||
|
if err = db.FindOne(ctx, &data, filter, opts); err != nil {
|
||||||
|
log.Error("advertise FindLatestAdsByAppAndLoc FindOne err", log.E(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 增加广告点击量
|
// 增加广告点击量
|
||||||
func IncAdsClickCount(ctx context.Context, id int64) (err error) {
|
func IncAdsClickCount(ctx context.Context, id int64) (err error) {
|
||||||
filter := bson.M{"_id": id}
|
filter := bson.M{"_id": id}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package advitiseBindMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"stat/common/log"
|
||||||
|
"stat/common/mongos"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(ctx context.Context) {
|
||||||
|
db = mongos.New(mongos.MgoManager, TN.AdvitiseBind)
|
||||||
|
indexes := []mongo.IndexModel{
|
||||||
|
{Keys: bson.D{
|
||||||
|
{Key: FN.AdvitiseBind.AppId, Value: 1},
|
||||||
|
{Key: FN.AdvitiseBind.LocationId, Value: 1},
|
||||||
|
}},
|
||||||
|
{Keys: bson.D{{Key: FN.AdvitiseBind.AdvitiseId, Value: 1}}},
|
||||||
|
{Keys: bson.D{{Key: FN.AdvitiseBind.CreatedAt, Value: -1}}},
|
||||||
|
}
|
||||||
|
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||||
|
panic(fmt.Sprintf("(advitiseBindMod:Init) CreateIndex failed: %+v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InsertOneAdvitiseBind(ctx context.Context, doc *AdvitiseBind) error {
|
||||||
|
if _, err := db.InsertOne(ctx, doc); err != nil {
|
||||||
|
log.Warn("advitiseBindMod InsertOne failed", log.E(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindOneAdvitiseBind(ctx context.Context, filter bson.M) (*AdvitiseBind, error) {
|
||||||
|
var doc AdvitiseBind
|
||||||
|
if err := db.FindOne(ctx, &doc, filter); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &doc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DelOneAdvitiseBind(ctx context.Context, filter bson.M) (int64, error) {
|
||||||
|
count, err := db.DeleteOne(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("advitiseBindMod DeleteOne failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateOneAdvitiseBind(ctx context.Context, filter bson.M, update bson.M) error {
|
||||||
|
if _, err := db.UpdateOne(ctx, filter, update); err != nil {
|
||||||
|
log.Warn("advitiseBindMod UpdateOne failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CountAdvitiseBinds(ctx context.Context, filter bson.M) (int64, error) {
|
||||||
|
count, err := db.Count(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("advitiseBindMod Count failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindManyAdvitiseBinds(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (AdvitiseBindList, error) {
|
||||||
|
list := make(AdvitiseBindList, 0)
|
||||||
|
if err := db.Find(ctx, &list, filter, opts...); err != nil {
|
||||||
|
log.Warn("advitiseBindMod Find failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package advitiseBindMod
|
||||||
|
|
||||||
|
type TagAdvitiseBind struct {
|
||||||
|
Id string
|
||||||
|
AppId string
|
||||||
|
AdvitiseId string
|
||||||
|
LocationId string
|
||||||
|
Sort string
|
||||||
|
CreatedAt string
|
||||||
|
UpdatedAt string
|
||||||
|
}
|
||||||
|
|
||||||
|
var FN struct {
|
||||||
|
AdvitiseBind TagAdvitiseBind
|
||||||
|
}
|
||||||
|
|
||||||
|
var TN struct {
|
||||||
|
AdvitiseBind string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
FN.AdvitiseBind.Id = "_id"
|
||||||
|
FN.AdvitiseBind.AppId = "appId"
|
||||||
|
FN.AdvitiseBind.AdvitiseId = "advitiseId"
|
||||||
|
FN.AdvitiseBind.LocationId = "locationId"
|
||||||
|
FN.AdvitiseBind.Sort = "sort"
|
||||||
|
FN.AdvitiseBind.CreatedAt = "createdAt"
|
||||||
|
FN.AdvitiseBind.UpdatedAt = "updatedAt"
|
||||||
|
TN.AdvitiseBind = "advitise_bind"
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package advitiseBindMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/common/mongos"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var db *mongos.MongoTool
|
||||||
|
|
||||||
|
// AdvitiseBind 广告投放绑定(V2):把一个 AdvitiseInfo 绑到指定 (appId, locationId[]) 上
|
||||||
|
// @table:advitise_bind
|
||||||
|
type AdvitiseBind struct {
|
||||||
|
Id int64 `json:"id" bson:"_id"`
|
||||||
|
AppId int32 `json:"appId" bson:"appId"` // 产品id
|
||||||
|
AdvitiseId int64 `json:"advitiseId" bson:"advitiseId"` // 广告id -> advitiseInfoMod
|
||||||
|
LocationId []int32 `json:"locationId" bson:"locationId"` // 位置id列表(可多)
|
||||||
|
Sort int64 `json:"sort" bson:"sort"` // 排序值,优先级
|
||||||
|
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseBindList []*AdvitiseBind
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package advitiseClickStatMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"stat/common/log"
|
||||||
|
"stat/common/mongos"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(ctx context.Context) {
|
||||||
|
db = mongos.New(mongos.MgoManager, TN.AdvitiseClickStat)
|
||||||
|
indexes := []mongo.IndexModel{
|
||||||
|
{
|
||||||
|
Keys: bson.D{
|
||||||
|
{Key: FN.AdvitiseClickStat.AppId, Value: 1},
|
||||||
|
{Key: FN.AdvitiseClickStat.AdvitiseId, Value: 1},
|
||||||
|
{Key: FN.AdvitiseClickStat.LocationId, Value: 1},
|
||||||
|
{Key: FN.AdvitiseClickStat.StatDate, Value: -1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Keys: bson.D{
|
||||||
|
{Key: FN.AdvitiseClickStat.AdvitiseId, Value: 1},
|
||||||
|
{Key: FN.AdvitiseClickStat.StatDate, Value: -1},
|
||||||
|
}},
|
||||||
|
{Keys: bson.D{
|
||||||
|
{Key: FN.AdvitiseClickStat.StatDate, Value: -1},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||||
|
panic(fmt.Sprintf("(advitiseClickStatMod:Init) CreateIndex failed: %+v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertOrUpdate 按 (appId, advitiseId, locationId, statDate) upsert +1
|
||||||
|
// 对齐 media/biadsclickmod.InsertOrUpdateBIAdsClickModel
|
||||||
|
func InsertOrUpdate(ctx context.Context, appId int32, advitiseId int64, locationId int32, statDate time.Time) error {
|
||||||
|
filter := bson.M{
|
||||||
|
FN.AdvitiseClickStat.AppId: appId,
|
||||||
|
FN.AdvitiseClickStat.AdvitiseId: advitiseId,
|
||||||
|
FN.AdvitiseClickStat.LocationId: locationId,
|
||||||
|
FN.AdvitiseClickStat.StatDate: statDate,
|
||||||
|
}
|
||||||
|
update := bson.M{
|
||||||
|
"$inc": bson.M{FN.AdvitiseClickStat.Clicks: 1},
|
||||||
|
"$setOnInsert": bson.M{
|
||||||
|
FN.AdvitiseClickStat.CreatedAt: time.Now(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if _, err := db.UpsertOneEx(ctx, filter, update); err != nil {
|
||||||
|
log.Warn("advitiseClickStatMod InsertOrUpdate upsert failed",
|
||||||
|
log.E(err), log.Any("filter", filter))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindMany(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (AdvitiseClickStatList, error) {
|
||||||
|
list := make(AdvitiseClickStatList, 0)
|
||||||
|
if err := db.Find(ctx, &list, filter, opts...); err != nil {
|
||||||
|
log.Warn("advitiseClickStatMod Find failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Count(ctx context.Context, filter bson.M) (int64, error) {
|
||||||
|
c, err := db.Count(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("advitiseClickStatMod Count failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregate 通用聚合(留给上层写 pipeline)
|
||||||
|
func Aggregate(ctx context.Context, bind interface{}, pipeline []bson.M) error {
|
||||||
|
return db.Aggregate(ctx, bind, pipeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAppClicks 按 appId + statDate 汇总点击(对齐 media/biadsclickmod.GetAppClicks)
|
||||||
|
func GetAppClicks(ctx context.Context, appId int32, statDate time.Time) (int64, error) {
|
||||||
|
list, err := FindMany(ctx, bson.M{
|
||||||
|
FN.AdvitiseClickStat.AppId: appId,
|
||||||
|
FN.AdvitiseClickStat.StatDate: statDate,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
total := int64(0)
|
||||||
|
for _, i := range list {
|
||||||
|
total += i.Clicks
|
||||||
|
}
|
||||||
|
return total, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package advitiseClickStatMod
|
||||||
|
|
||||||
|
type TagAdvitiseClickStat struct {
|
||||||
|
Id string
|
||||||
|
AppId string
|
||||||
|
AdvitiseId string
|
||||||
|
LocationId string
|
||||||
|
Clicks string
|
||||||
|
StatDate string
|
||||||
|
CreatedAt string
|
||||||
|
}
|
||||||
|
|
||||||
|
var FN struct {
|
||||||
|
AdvitiseClickStat TagAdvitiseClickStat
|
||||||
|
}
|
||||||
|
|
||||||
|
var TN struct {
|
||||||
|
AdvitiseClickStat string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
FN.AdvitiseClickStat.Id = "_id"
|
||||||
|
FN.AdvitiseClickStat.AppId = "appId"
|
||||||
|
FN.AdvitiseClickStat.AdvitiseId = "advitiseId"
|
||||||
|
FN.AdvitiseClickStat.LocationId = "locationId"
|
||||||
|
FN.AdvitiseClickStat.Clicks = "clicks"
|
||||||
|
FN.AdvitiseClickStat.StatDate = "statDate"
|
||||||
|
FN.AdvitiseClickStat.CreatedAt = "createdAt"
|
||||||
|
TN.AdvitiseClickStat = "advitise_click_stat"
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package advitiseClickStatMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/common/mongos"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
var db *mongos.MongoTool
|
||||||
|
|
||||||
|
// AdvitiseClickStat 广告点击天粒度细维度统计(对齐 media/biadsclickmod)
|
||||||
|
// 键: (appId, advitiseId, locationId, statDate)
|
||||||
|
// @table:advitise_click_stat
|
||||||
|
type AdvitiseClickStat struct {
|
||||||
|
Id primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||||
|
AppId int32 `json:"appId" bson:"appId"`
|
||||||
|
AdvitiseId int64 `json:"advitiseId" bson:"advitiseId"`
|
||||||
|
LocationId int32 `json:"locationId" bson:"locationId"`
|
||||||
|
Clicks int64 `json:"clicks" bson:"clicks"`
|
||||||
|
StatDate time.Time `json:"statDate" bson:"statDate"`
|
||||||
|
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseClickStatList []*AdvitiseClickStat
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package advitiseDayClickStatMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"stat/common/log"
|
||||||
|
"stat/common/mongos"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(ctx context.Context) {
|
||||||
|
db = mongos.New(mongos.MgoManager, TN.AdvitiseDayClickStat)
|
||||||
|
indexes := []mongo.IndexModel{
|
||||||
|
{Keys: bson.D{
|
||||||
|
{Key: FN.AdvitiseDayClickStat.AdvitiseId, Value: 1},
|
||||||
|
{Key: FN.AdvitiseDayClickStat.StatDate, Value: -1},
|
||||||
|
}},
|
||||||
|
{Keys: bson.D{
|
||||||
|
{Key: FN.AdvitiseDayClickStat.StatDate, Value: -1},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||||
|
panic(fmt.Sprintf("(advitiseDayClickStatMod:Init) CreateIndex failed: %+v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertOrUpdate 按 (advitiseId, statDate) upsert +1
|
||||||
|
// 对齐 media/adsdayclickstatmod.InsertOrUpdateAdsDayClickStatModel
|
||||||
|
func InsertOrUpdate(ctx context.Context, advitiseId int64, statDate time.Time) error {
|
||||||
|
filter := bson.M{
|
||||||
|
FN.AdvitiseDayClickStat.AdvitiseId: advitiseId,
|
||||||
|
FN.AdvitiseDayClickStat.StatDate: statDate,
|
||||||
|
}
|
||||||
|
update := bson.M{
|
||||||
|
"$inc": bson.M{FN.AdvitiseDayClickStat.Clicks: 1},
|
||||||
|
"$setOnInsert": bson.M{
|
||||||
|
FN.AdvitiseDayClickStat.CreatedAt: time.Now(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if _, err := db.UpsertOneEx(ctx, filter, update); err != nil {
|
||||||
|
log.Warn("advitiseDayClickStatMod InsertOrUpdate upsert failed",
|
||||||
|
log.E(err), log.Any("filter", filter))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindMany(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (AdvitiseDayClickStatList, error) {
|
||||||
|
list := make(AdvitiseDayClickStatList, 0)
|
||||||
|
if err := db.Find(ctx, &list, filter, opts...); err != nil {
|
||||||
|
log.Warn("advitiseDayClickStatMod Find failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Count(ctx context.Context, filter bson.M) (int64, error) {
|
||||||
|
c, err := db.Count(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("advitiseDayClickStatMod Count failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package advitiseDayClickStatMod
|
||||||
|
|
||||||
|
type TagAdvitiseDayClickStat struct {
|
||||||
|
Id string
|
||||||
|
AdvitiseId string
|
||||||
|
Clicks string
|
||||||
|
StatDate string
|
||||||
|
CreatedAt string
|
||||||
|
}
|
||||||
|
|
||||||
|
var FN struct {
|
||||||
|
AdvitiseDayClickStat TagAdvitiseDayClickStat
|
||||||
|
}
|
||||||
|
|
||||||
|
var TN struct {
|
||||||
|
AdvitiseDayClickStat string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
FN.AdvitiseDayClickStat.Id = "_id"
|
||||||
|
FN.AdvitiseDayClickStat.AdvitiseId = "advitiseId"
|
||||||
|
FN.AdvitiseDayClickStat.Clicks = "clicks"
|
||||||
|
FN.AdvitiseDayClickStat.StatDate = "statDate"
|
||||||
|
FN.AdvitiseDayClickStat.CreatedAt = "createdAt"
|
||||||
|
TN.AdvitiseDayClickStat = "advitise_day_click_stat"
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package advitiseDayClickStatMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/common/mongos"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
var db *mongos.MongoTool
|
||||||
|
|
||||||
|
// AdvitiseDayClickStat 广告点击天粒度汇总(不含位置维度,对齐 media/adsdayclickstatmod)
|
||||||
|
// 键: (advitiseId, statDate)
|
||||||
|
// @table:advitise_day_click_stat
|
||||||
|
type AdvitiseDayClickStat struct {
|
||||||
|
Id primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||||
|
AdvitiseId int64 `json:"advitiseId" bson:"advitiseId"`
|
||||||
|
Clicks int64 `json:"clicks" bson:"clicks"`
|
||||||
|
StatDate time.Time `json:"statDate" bson:"statDate"`
|
||||||
|
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseDayClickStatList []*AdvitiseDayClickStat
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package advitiseInfoMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"stat/common/log"
|
||||||
|
"stat/common/mongos"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(ctx context.Context) {
|
||||||
|
db = mongos.New(mongos.MgoManager, TN.AdvitiseInfo)
|
||||||
|
indexes := []mongo.IndexModel{
|
||||||
|
{Keys: bson.D{
|
||||||
|
{Key: FN.AdvitiseInfo.StartTime, Value: 1},
|
||||||
|
{Key: FN.AdvitiseInfo.EndTime, Value: 1},
|
||||||
|
{Key: FN.AdvitiseInfo.Status, Value: 1},
|
||||||
|
}},
|
||||||
|
{Keys: bson.D{{Key: FN.AdvitiseInfo.CreatedAt, Value: -1}}},
|
||||||
|
}
|
||||||
|
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||||
|
panic(fmt.Sprintf("(advitiseInfoMod:Init) CreateIndex failed: %+v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InsertOneAdvitiseInfo(ctx context.Context, doc *AdvitiseInfo) error {
|
||||||
|
if _, err := db.InsertOne(ctx, doc); err != nil {
|
||||||
|
log.Warn("advitiseInfoMod InsertOne failed", log.E(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindOneAdvitiseInfo(ctx context.Context, filter bson.M) (*AdvitiseInfo, error) {
|
||||||
|
var doc AdvitiseInfo
|
||||||
|
if err := db.FindOne(ctx, &doc, filter); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &doc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DelOneAdvitiseInfo(ctx context.Context, filter bson.M) (int64, error) {
|
||||||
|
count, err := db.DeleteOne(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("advitiseInfoMod DeleteOne failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateOneAdvitiseInfo(ctx context.Context, filter bson.M, update bson.M) error {
|
||||||
|
if _, err := db.UpdateOne(ctx, filter, update); err != nil {
|
||||||
|
log.Warn("advitiseInfoMod UpdateOne failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CountAdvitiseInfos(ctx context.Context, filter bson.M) (int64, error) {
|
||||||
|
count, err := db.Count(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("advitiseInfoMod Count failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindManyAdvitiseInfos(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (AdvitiseInfoList, error) {
|
||||||
|
list := make(AdvitiseInfoList, 0)
|
||||||
|
if err := db.Find(ctx, &list, filter, opts...); err != nil {
|
||||||
|
log.Warn("advitiseInfoMod Find failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package advitiseInfoMod
|
||||||
|
|
||||||
|
type TagAdvitiseInfo struct {
|
||||||
|
Id string
|
||||||
|
Title string
|
||||||
|
FullScreenImgs string
|
||||||
|
Banner720300Imgs string
|
||||||
|
Banner720150Imgs string
|
||||||
|
Banner750700Imgs string
|
||||||
|
Banner800450Imgs string
|
||||||
|
PopUps600800Imgs string
|
||||||
|
PopUps512512Imgs string
|
||||||
|
SmallCubeImgs string
|
||||||
|
VerticalCubeImgs string
|
||||||
|
RandomNames string
|
||||||
|
Link string
|
||||||
|
Status string
|
||||||
|
StartTime string
|
||||||
|
EndTime string
|
||||||
|
Remark string
|
||||||
|
Desc string
|
||||||
|
CreatedAt string
|
||||||
|
UpdatedAt string
|
||||||
|
}
|
||||||
|
|
||||||
|
var FN struct {
|
||||||
|
AdvitiseInfo TagAdvitiseInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
var TN struct {
|
||||||
|
AdvitiseInfo string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
FN.AdvitiseInfo.Id = "_id"
|
||||||
|
FN.AdvitiseInfo.Title = "title"
|
||||||
|
FN.AdvitiseInfo.FullScreenImgs = "fullScreenImgs"
|
||||||
|
FN.AdvitiseInfo.Banner720300Imgs = "banner720300Imgs"
|
||||||
|
FN.AdvitiseInfo.Banner720150Imgs = "banner720150Imgs"
|
||||||
|
FN.AdvitiseInfo.Banner750700Imgs = "banner750700Imgs"
|
||||||
|
FN.AdvitiseInfo.Banner800450Imgs = "banner800450Imgs"
|
||||||
|
FN.AdvitiseInfo.PopUps600800Imgs = "popUps600800Imgs"
|
||||||
|
FN.AdvitiseInfo.PopUps512512Imgs = "popUps512512Imgs"
|
||||||
|
FN.AdvitiseInfo.SmallCubeImgs = "smallCubeImgs"
|
||||||
|
FN.AdvitiseInfo.VerticalCubeImgs = "verticalCubeImgs"
|
||||||
|
FN.AdvitiseInfo.RandomNames = "randomNames"
|
||||||
|
FN.AdvitiseInfo.Link = "link"
|
||||||
|
FN.AdvitiseInfo.Status = "status"
|
||||||
|
FN.AdvitiseInfo.StartTime = "startTime"
|
||||||
|
FN.AdvitiseInfo.EndTime = "endTime"
|
||||||
|
FN.AdvitiseInfo.Remark = "remark"
|
||||||
|
FN.AdvitiseInfo.Desc = "desc"
|
||||||
|
FN.AdvitiseInfo.CreatedAt = "createdAt"
|
||||||
|
FN.AdvitiseInfo.UpdatedAt = "updatedAt"
|
||||||
|
TN.AdvitiseInfo = "advitise_info"
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package advitiseInfoMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/common/mongos"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var db *mongos.MongoTool
|
||||||
|
|
||||||
|
// AdvitiseInfo 广告素材(V2):素材本身与位置/绑定解耦,可复用到多个 app 的多个位置
|
||||||
|
// @table:advitise_info
|
||||||
|
type AdvitiseInfo struct {
|
||||||
|
Id int64 `json:"id" bson:"_id"`
|
||||||
|
Title string `json:"title" bson:"title"` // 广告标题
|
||||||
|
FullScreenImgs []string `json:"fullScreenImgs" bson:"fullScreenImgs"` // 全屏封面
|
||||||
|
Banner720300Imgs []string `json:"banner720300Imgs" bson:"banner720300Imgs"` // Banner720*300 封面
|
||||||
|
Banner720150Imgs []string `json:"banner720150Imgs" bson:"banner720150Imgs"` // Banner720*150 封面
|
||||||
|
Banner750700Imgs []string `json:"banner750700Imgs" bson:"banner750700Imgs"` // Banner750*700 封面
|
||||||
|
Banner800450Imgs []string `json:"banner800450Imgs" bson:"banner800450Imgs"` // Banner800*450 封面
|
||||||
|
PopUps600800Imgs []string `json:"popUps600800Imgs" bson:"popUps600800Imgs"` // 弹窗 600*800 封面
|
||||||
|
PopUps512512Imgs []string `json:"popUps512512Imgs" bson:"popUps512512Imgs"` // 弹窗 512*512 封面
|
||||||
|
SmallCubeImgs []string `json:"smallCubeImgs" bson:"smallCubeImgs"` // 小方块封面
|
||||||
|
VerticalCubeImgs []string `json:"verticalCubeImgs" bson:"verticalCubeImgs"` // 竖方块封面
|
||||||
|
RandomNames []string `json:"randomNames" bson:"randomNames"` // 随机名称
|
||||||
|
Link string `json:"link" bson:"link"` // 跳转链接
|
||||||
|
Status bool `json:"status" bson:"status"` // 是否激活
|
||||||
|
StartTime time.Time `json:"startTime" bson:"startTime"` // 开始时间
|
||||||
|
EndTime time.Time `json:"endTime" bson:"endTime"` // 结束时间
|
||||||
|
Remark string `json:"remark" bson:"remark"` // 备注
|
||||||
|
Desc string `json:"desc" bson:"desc"` // 描述
|
||||||
|
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseInfoList []*AdvitiseInfo
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package advitiseLocationMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"stat/common/log"
|
||||||
|
"stat/common/mongos"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(ctx context.Context) {
|
||||||
|
db = mongos.New(mongos.MgoManager, TN.AdvitiseLocation)
|
||||||
|
indexes := []mongo.IndexModel{
|
||||||
|
{
|
||||||
|
Keys: bson.D{
|
||||||
|
{Key: FN.AdvitiseLocation.AppId, Value: 1},
|
||||||
|
{Key: FN.AdvitiseLocation.LocId, Value: 1},
|
||||||
|
},
|
||||||
|
Options: options.Index().SetUnique(true),
|
||||||
|
},
|
||||||
|
{Keys: bson.D{{Key: FN.AdvitiseLocation.CreatedAt, Value: -1}}},
|
||||||
|
}
|
||||||
|
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||||
|
panic(fmt.Sprintf("(advitiseLocationMod:Init) CreateIndex failed: %+v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InsertOneAdvitiseLocation(ctx context.Context, doc *AdvitiseLocation) error {
|
||||||
|
if _, err := db.InsertOne(ctx, doc); err != nil {
|
||||||
|
log.Warn("advitiseLocationMod InsertOne failed", log.E(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindOneAdvitiseLocation(ctx context.Context, filter bson.M) (*AdvitiseLocation, error) {
|
||||||
|
var doc AdvitiseLocation
|
||||||
|
if err := db.FindOne(ctx, &doc, filter); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &doc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DelOneAdvitiseLocation(ctx context.Context, filter bson.M) (int64, error) {
|
||||||
|
count, err := db.DeleteOne(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("advitiseLocationMod DeleteOne failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateOneAdvitiseLocation(ctx context.Context, filter bson.M, update bson.M) error {
|
||||||
|
if _, err := db.UpdateOne(ctx, filter, update); err != nil {
|
||||||
|
log.Warn("advitiseLocationMod UpdateOne failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CountAdvitiseLocations(ctx context.Context, filter bson.M) (int64, error) {
|
||||||
|
count, err := db.Count(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("advitiseLocationMod Count failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindManyAdvitiseLocations(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (AdvitiseLocationList, error) {
|
||||||
|
list := make(AdvitiseLocationList, 0)
|
||||||
|
if err := db.Find(ctx, &list, filter, opts...); err != nil {
|
||||||
|
log.Warn("advitiseLocationMod Find failed", log.E(err), log.Any("filter", filter))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package advitiseLocationMod
|
||||||
|
|
||||||
|
type TagAdvitiseLocation struct {
|
||||||
|
Id string
|
||||||
|
AppId string
|
||||||
|
LocId string
|
||||||
|
Name string
|
||||||
|
AdvitiseSize string
|
||||||
|
ImgSizeDesc string
|
||||||
|
Remark string
|
||||||
|
CreatedAt string
|
||||||
|
UpdatedAt string
|
||||||
|
}
|
||||||
|
|
||||||
|
var FN struct {
|
||||||
|
AdvitiseLocation TagAdvitiseLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
var TN struct {
|
||||||
|
AdvitiseLocation string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
FN.AdvitiseLocation.Id = "_id"
|
||||||
|
FN.AdvitiseLocation.AppId = "appId"
|
||||||
|
FN.AdvitiseLocation.LocId = "locId"
|
||||||
|
FN.AdvitiseLocation.Name = "name"
|
||||||
|
FN.AdvitiseLocation.AdvitiseSize = "advitiseSize"
|
||||||
|
FN.AdvitiseLocation.ImgSizeDesc = "imgSizeDesc"
|
||||||
|
FN.AdvitiseLocation.Remark = "remark"
|
||||||
|
FN.AdvitiseLocation.CreatedAt = "createdAt"
|
||||||
|
FN.AdvitiseLocation.UpdatedAt = "updatedAt"
|
||||||
|
TN.AdvitiseLocation = "advitise_location"
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package advitiseLocationMod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/common/mongos"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var db *mongos.MongoTool
|
||||||
|
|
||||||
|
type AdvitiseSizeType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AdvitiseSizeFullScreen AdvitiseSizeType = "全屏" // 全屏
|
||||||
|
AdvitiseSizeBanner720300 AdvitiseSizeType = "banner720*300" // Banner720*300
|
||||||
|
AdvitiseSizeBanner720150 AdvitiseSizeType = "banner720*150" // Banner720*150
|
||||||
|
AdvitiseSizeBanner750700 AdvitiseSizeType = "banner750*700" // Banner750*700
|
||||||
|
AdvitiseSizeBanner800450 AdvitiseSizeType = "banner800*450" // Banner800*450
|
||||||
|
AdvitiseSizePopUps600800 AdvitiseSizeType = "弹窗600*800" // 弹窗 600*800
|
||||||
|
AdvitiseSizePopUps512512 AdvitiseSizeType = "弹窗512*512" // 弹窗 512*512
|
||||||
|
AdvitiseSizeSmallCube AdvitiseSizeType = "小方块" // 小方块
|
||||||
|
AdvitiseSizeVerticalCube AdvitiseSizeType = "竖方块" // 竖方块
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdvitiseLocation 广告位(V2):按 (appId, locId) 唯一
|
||||||
|
// @table:advitise_location
|
||||||
|
type AdvitiseLocation struct {
|
||||||
|
Id int64 `json:"id" bson:"_id"`
|
||||||
|
AppId int32 `json:"appId" bson:"appId"` // 应用id
|
||||||
|
LocId int32 `json:"locId" bson:"locId"` // 位置id,外部使用
|
||||||
|
Name string `json:"name" bson:"name"` // 位置名称
|
||||||
|
AdvitiseSize AdvitiseSizeType `json:"advitiseSize" bson:"advitiseSize"` // 尺寸类型
|
||||||
|
ImgSizeDesc string `json:"imgSizeDesc" bson:"imgSizeDesc"` // 图片描述
|
||||||
|
Remark string `json:"remark" bson:"remark"` // 备注
|
||||||
|
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdvitiseLocationList []*AdvitiseLocation
|
||||||
@@ -9,6 +9,11 @@ import (
|
|||||||
"stat/models/advertiseLocMod"
|
"stat/models/advertiseLocMod"
|
||||||
"stat/models/advertiseMod"
|
"stat/models/advertiseMod"
|
||||||
"stat/models/advertisestat"
|
"stat/models/advertisestat"
|
||||||
|
"stat/models/advitiseBindMod"
|
||||||
|
"stat/models/advitiseClickStatMod"
|
||||||
|
"stat/models/advitiseDayClickStatMod"
|
||||||
|
"stat/models/advitiseInfoMod"
|
||||||
|
"stat/models/advitiseLocationMod"
|
||||||
"stat/models/announInfoMod"
|
"stat/models/announInfoMod"
|
||||||
"stat/models/appInfoMod"
|
"stat/models/appInfoMod"
|
||||||
"stat/models/appcategory"
|
"stat/models/appcategory"
|
||||||
@@ -109,4 +114,9 @@ func InitIndex() {
|
|||||||
applicationLocMod.Init(ctx)
|
applicationLocMod.Init(ctx)
|
||||||
channelpackage.Init(ctx)
|
channelpackage.Init(ctx)
|
||||||
cpcDownloadCfg.Init(ctx)
|
cpcDownloadCfg.Init(ctx)
|
||||||
|
advitiseInfoMod.Init(ctx)
|
||||||
|
advitiseLocationMod.Init(ctx)
|
||||||
|
advitiseBindMod.Init(ctx)
|
||||||
|
advitiseClickStatMod.Init(ctx)
|
||||||
|
advitiseDayClickStatMod.Init(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"stat/api/advitiseV2Api"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func advitiseV2Router(router *gin.RouterGroup) {
|
||||||
|
v2 := router.Group("/advitise/v2")
|
||||||
|
{
|
||||||
|
info := v2.Group("/info")
|
||||||
|
info.POST("/list", advitiseV2Api.InfoList)
|
||||||
|
info.POST("/add", advitiseV2Api.InfoAdd)
|
||||||
|
info.POST("/update", advitiseV2Api.InfoUpdate)
|
||||||
|
info.POST("/del", advitiseV2Api.InfoDel)
|
||||||
|
|
||||||
|
loc := v2.Group("/location")
|
||||||
|
loc.POST("/list", advitiseV2Api.LocationList)
|
||||||
|
loc.POST("/add", advitiseV2Api.LocationAdd)
|
||||||
|
loc.POST("/update", advitiseV2Api.LocationUpdate)
|
||||||
|
loc.POST("/del", advitiseV2Api.LocationDel)
|
||||||
|
|
||||||
|
bind := v2.Group("/bind")
|
||||||
|
bind.POST("/list", advitiseV2Api.BindList)
|
||||||
|
bind.POST("/add", advitiseV2Api.BindAdd)
|
||||||
|
bind.POST("/update", advitiseV2Api.BindUpdate)
|
||||||
|
bind.POST("/del", advitiseV2Api.BindDel)
|
||||||
|
|
||||||
|
// 外部无鉴权接口(需与白名单一致)
|
||||||
|
v2.POST("/get", advitiseV2Api.GetAdvitises)
|
||||||
|
v2.POST("/click", advitiseV2Api.ClickAdvitise)
|
||||||
|
|
||||||
|
// 统计管理(后台)
|
||||||
|
v2.POST("/day/click/list", advitiseV2Api.DayClickList)
|
||||||
|
v2.POST("/day/click/info", advitiseV2Api.DayClickInfo)
|
||||||
|
v2.POST("/click/list", advitiseV2Api.ClickList)
|
||||||
|
v2.POST("/day/click/summary", advitiseV2Api.ClickSummary)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -103,10 +103,11 @@ func registerRouter(router *gin.Engine) {
|
|||||||
applicationRouter(rootRouter) // 配置app应用
|
applicationRouter(rootRouter) // 配置app应用
|
||||||
appcategoryRouter(rootRouter) // app分类
|
appcategoryRouter(rootRouter) // app分类
|
||||||
userInviteRouter(rootRouter) // 兼容
|
userInviteRouter(rootRouter) // 兼容
|
||||||
|
advitiseV2Router(rootRouter) // 广告管理V2(素材/位置/绑定)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 双端下载落地页(无需登陆鉴权)
|
// 双端下载落地页(无需登陆鉴权)
|
||||||
router.GET("/rsdownload/:appId/:channel", versionApi.CpcDownload)
|
router.GET("/download/:appId/:channel", versionApi.CpcDownload)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setGinSwagger(router *gin.Engine) {
|
func setGinSwagger(router *gin.Engine) {
|
||||||
|
|||||||
@@ -280,19 +280,27 @@ func GetAdvertise(ctx context.Context, param proto.AdvertiseReq) (code stdLog.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 增加广告点击次数
|
// 增加广告点击次数
|
||||||
|
// 兼容策略:先按 param.Id 精确查;如果广告已过期/删除或不属于该 AppId,回退到 (AppId, LocId) 上的最新一条广告
|
||||||
|
// LocId 未传时,回退查询只按 AppId 定位;仍找不到才返回 AdvertiseInvalid
|
||||||
func IncAdsClickCount(ctx context.Context, param proto.AdsClickReq) (code stdLog.CodeType, data interface{}, err error) {
|
func IncAdsClickCount(ctx context.Context, param proto.AdsClickReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||||
// 获取广告信息
|
// 先按 Id 查
|
||||||
adsInfo, err := advertiseMod.FindAdsById(ctx, *param.Id)
|
adsInfo, findErr := advertiseMod.FindAdsById(ctx, *param.Id)
|
||||||
if err != nil || adsInfo.Id == 0 {
|
needFallback := findErr != nil || adsInfo.Id == 0 || adsInfo.AppId != *param.AppId
|
||||||
code = stdLog.AdvertiseInvalid
|
if needFallback {
|
||||||
return
|
var locId int32
|
||||||
|
if param.LocId != nil {
|
||||||
|
locId = *param.LocId
|
||||||
|
}
|
||||||
|
latest, latestErr := advertiseMod.FindLatestAdsByAppAndLoc(ctx, *param.AppId, locId)
|
||||||
|
if latestErr != nil || latest.Id == 0 {
|
||||||
|
code = stdLog.AdvertiseInvalid
|
||||||
|
err = latestErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
adsInfo = latest
|
||||||
}
|
}
|
||||||
|
|
||||||
if adsInfo.AppId != *param.AppId {
|
// save to redis(用真正命中的广告 Id 统计)
|
||||||
code = stdLog.AppInfoError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// save to redis
|
|
||||||
now := time.Now().Local()
|
now := time.Now().Local()
|
||||||
set := redis.GetAdvertiseClickDayHash(now)
|
set := redis.GetAdvertiseClickDayHash(now)
|
||||||
name := redis.GetAdvertiseClickHourName(adsInfo.AppId, adsInfo.Id, now.Hour())
|
name := redis.GetAdvertiseClickHourName(adsInfo.AppId, adsInfo.Id, now.Hour())
|
||||||
@@ -301,7 +309,7 @@ func IncAdsClickCount(ctx context.Context, param proto.AdsClickReq) (code stdLog
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// update click+1 to db
|
// update click+1 to db
|
||||||
if err = advertiseMod.IncAdsClickCount(ctx, *param.Id); err != nil {
|
if err = advertiseMod.IncAdsClickCount(ctx, adsInfo.Id); err != nil {
|
||||||
code = stdLog.Failure
|
code = stdLog.Failure
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package advitiseV2Ser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/genId"
|
||||||
|
"stat/models/advitiseBindMod"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BindList(ctx context.Context, req *proto.AdvitiseBindListReq) (*proto.AdvitiseBindListResp, error) {
|
||||||
|
resp := &proto.AdvitiseBindListResp{
|
||||||
|
Total: 0,
|
||||||
|
List: make(advitiseBindMod.AdvitiseBindList, 0),
|
||||||
|
}
|
||||||
|
filter := bson.M{}
|
||||||
|
if req.AppId != nil {
|
||||||
|
filter[advitiseBindMod.FN.AdvitiseBind.AppId] = *req.AppId
|
||||||
|
}
|
||||||
|
if req.AdvitiseId != nil {
|
||||||
|
filter[advitiseBindMod.FN.AdvitiseBind.AdvitiseId] = *req.AdvitiseId
|
||||||
|
}
|
||||||
|
if req.LocationId != nil {
|
||||||
|
filter[advitiseBindMod.FN.AdvitiseBind.LocationId] = *req.LocationId
|
||||||
|
}
|
||||||
|
total, err := advitiseBindMod.CountAdvitiseBinds(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
opt := &options.FindOptions{}
|
||||||
|
opt.SetSort(bson.D{
|
||||||
|
{Key: advitiseBindMod.FN.AdvitiseBind.Sort, Value: -1},
|
||||||
|
{Key: advitiseBindMod.FN.AdvitiseBind.CreatedAt, Value: -1},
|
||||||
|
})
|
||||||
|
opt.SetSkip((req.PageNum - 1) * req.PageSize)
|
||||||
|
opt.SetLimit(req.PageSize)
|
||||||
|
list, err := advitiseBindMod.FindManyAdvitiseBinds(ctx, filter, opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp.Total = total
|
||||||
|
resp.List = list
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BindAdd(ctx context.Context, req *proto.AddAdvitiseBindReq) error {
|
||||||
|
now := time.Now()
|
||||||
|
locs := req.LocationId
|
||||||
|
if locs == nil {
|
||||||
|
locs = []int32{}
|
||||||
|
}
|
||||||
|
doc := &advitiseBindMod.AdvitiseBind{
|
||||||
|
Id: genId.GetAdvitiseBindId(),
|
||||||
|
AppId: req.AppId,
|
||||||
|
AdvitiseId: req.AdvitiseId,
|
||||||
|
LocationId: locs,
|
||||||
|
Sort: req.Sort,
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
return advitiseBindMod.InsertOneAdvitiseBind(ctx, doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BindUpdate(ctx context.Context, req *proto.UpdateAdvitiseBindReq) error {
|
||||||
|
set := bson.M{
|
||||||
|
advitiseBindMod.FN.AdvitiseBind.UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
if req.AppId != nil {
|
||||||
|
set[advitiseBindMod.FN.AdvitiseBind.AppId] = *req.AppId
|
||||||
|
}
|
||||||
|
if req.AdvitiseId != nil {
|
||||||
|
set[advitiseBindMod.FN.AdvitiseBind.AdvitiseId] = *req.AdvitiseId
|
||||||
|
}
|
||||||
|
if req.LocationId != nil {
|
||||||
|
set[advitiseBindMod.FN.AdvitiseBind.LocationId] = *req.LocationId
|
||||||
|
}
|
||||||
|
if req.Sort != nil {
|
||||||
|
set[advitiseBindMod.FN.AdvitiseBind.Sort] = *req.Sort
|
||||||
|
}
|
||||||
|
return advitiseBindMod.UpdateOneAdvitiseBind(ctx,
|
||||||
|
bson.M{advitiseBindMod.FN.AdvitiseBind.Id: req.Id},
|
||||||
|
bson.M{"$set": set},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BindDel(ctx context.Context, id int64) error {
|
||||||
|
_, err := advitiseBindMod.DelOneAdvitiseBind(ctx, bson.M{advitiseBindMod.FN.AdvitiseBind.Id: id})
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
package advitiseV2Ser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/log"
|
||||||
|
"stat/models/advitiseBindMod"
|
||||||
|
"stat/models/advitiseClickStatMod"
|
||||||
|
"stat/models/advitiseDayClickStatMod"
|
||||||
|
"stat/models/advitiseInfoMod"
|
||||||
|
"stat/models/advitiseLocationMod"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
// idScale 把 (bindId, locId) 编码进单个 int64 id 的乘数
|
||||||
|
// 约束:locId < idScale。int64 上限允许 bindId 最大约 9.2e13,远超实际 LID 生成量
|
||||||
|
const idScale = int64(100000)
|
||||||
|
|
||||||
|
// GetAdvitises 外部拉广告:响应结构与老 GetAdvertise (proto.AdvertiseRes) 一致
|
||||||
|
// - 每条广告绑定一个 (bindId, locId) 组合
|
||||||
|
// - CoverImg 依据 location.AdvitiseSize 选 info 里对应尺寸组的第一张
|
||||||
|
// - 返回的 id = bindId*idScale + locId,client 点击时原样回传,后端解码定位 (bind, locId)
|
||||||
|
// - BindId 也单独返回,给愿意用二维接口的 client 用
|
||||||
|
func GetAdvitises(ctx context.Context, req *proto.GetAdvitiseV2Req) (*proto.AdvertiseRes, error) {
|
||||||
|
resp := &proto.AdvertiseRes{AdvertiseList: make([]*proto.AdvertiseInfo, 0)}
|
||||||
|
|
||||||
|
// 1) 拉 bind
|
||||||
|
filter := bson.M{advitiseBindMod.FN.AdvitiseBind.AppId: req.AppId}
|
||||||
|
if req.LocationId != nil {
|
||||||
|
filter[advitiseBindMod.FN.AdvitiseBind.LocationId] = *req.LocationId
|
||||||
|
}
|
||||||
|
opt := &options.FindOptions{}
|
||||||
|
opt.SetSort(bson.D{
|
||||||
|
{Key: advitiseBindMod.FN.AdvitiseBind.Sort, Value: -1},
|
||||||
|
{Key: advitiseBindMod.FN.AdvitiseBind.CreatedAt, Value: -1},
|
||||||
|
})
|
||||||
|
binds, err := advitiseBindMod.FindManyAdvitiseBinds(ctx, filter, opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(binds) == 0 {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) 批量拉当前生效 info
|
||||||
|
advitiseIds := uniqInt64(func() []int64 {
|
||||||
|
out := make([]int64, 0, len(binds))
|
||||||
|
for _, b := range binds {
|
||||||
|
out = append(out, b.AdvitiseId)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}())
|
||||||
|
now := time.Now()
|
||||||
|
infos, err := advitiseInfoMod.FindManyAdvitiseInfos(ctx, bson.M{
|
||||||
|
advitiseInfoMod.FN.AdvitiseInfo.Id: bson.M{"$in": advitiseIds},
|
||||||
|
advitiseInfoMod.FN.AdvitiseInfo.Status: true,
|
||||||
|
advitiseInfoMod.FN.AdvitiseInfo.StartTime: bson.M{"$lte": now},
|
||||||
|
advitiseInfoMod.FN.AdvitiseInfo.EndTime: bson.M{"$gte": now},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
infoMap := make(map[int64]*advitiseInfoMod.AdvitiseInfo, len(infos))
|
||||||
|
for _, info := range infos {
|
||||||
|
infoMap[info.Id] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) 批量拉 location(用于 CoverImg 尺寸匹配)
|
||||||
|
locIdsAll := uniqInt32(func() []int32 {
|
||||||
|
out := make([]int32, 0)
|
||||||
|
for _, b := range binds {
|
||||||
|
out = append(out, b.LocationId...)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}())
|
||||||
|
locMap := make(map[int32]*advitiseLocationMod.AdvitiseLocation)
|
||||||
|
if len(locIdsAll) > 0 {
|
||||||
|
locs, lerr := advitiseLocationMod.FindManyAdvitiseLocations(ctx, bson.M{
|
||||||
|
advitiseLocationMod.FN.AdvitiseLocation.AppId: req.AppId,
|
||||||
|
advitiseLocationMod.FN.AdvitiseLocation.LocId: bson.M{"$in": locIdsAll},
|
||||||
|
})
|
||||||
|
if lerr == nil {
|
||||||
|
for _, l := range locs {
|
||||||
|
locMap[l.LocId] = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) 展开 bind × location 为 item
|
||||||
|
for _, b := range binds {
|
||||||
|
info, ok := infoMap[b.AdvitiseId]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, locId := range b.LocationId {
|
||||||
|
if req.LocationId != nil && locId != *req.LocationId {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var size advitiseLocationMod.AdvitiseSizeType
|
||||||
|
if loc, ok := locMap[locId]; ok && loc != nil {
|
||||||
|
size = loc.AdvitiseSize
|
||||||
|
}
|
||||||
|
resp.AdvertiseList = append(resp.AdvertiseList, &proto.AdvertiseInfo{
|
||||||
|
Id: b.Id*idScale + int64(locId),
|
||||||
|
Title: info.Title,
|
||||||
|
CoverImg: pickCoverImg(info, size),
|
||||||
|
LocId: locId,
|
||||||
|
JumpType: 0, // V2 素材未维护跳转类型,默认外部浏览器
|
||||||
|
Link: info.Link,
|
||||||
|
Sort: b.Sort,
|
||||||
|
Type: 0,
|
||||||
|
Tags: "",
|
||||||
|
Remark: info.Remark,
|
||||||
|
AmbientColor: "",
|
||||||
|
BindId: b.Id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// pickCoverImg 按位置尺寸选一张封面;取不到就用任一非空数组的第一张兜底
|
||||||
|
func pickCoverImg(info *advitiseInfoMod.AdvitiseInfo, size advitiseLocationMod.AdvitiseSizeType) string {
|
||||||
|
var arr []string
|
||||||
|
switch size {
|
||||||
|
case advitiseLocationMod.AdvitiseSizeFullScreen:
|
||||||
|
arr = info.FullScreenImgs
|
||||||
|
case advitiseLocationMod.AdvitiseSizeBanner720300:
|
||||||
|
arr = info.Banner720300Imgs
|
||||||
|
case advitiseLocationMod.AdvitiseSizeBanner720150:
|
||||||
|
arr = info.Banner720150Imgs
|
||||||
|
case advitiseLocationMod.AdvitiseSizeBanner750700:
|
||||||
|
arr = info.Banner750700Imgs
|
||||||
|
case advitiseLocationMod.AdvitiseSizeBanner800450:
|
||||||
|
arr = info.Banner800450Imgs
|
||||||
|
case advitiseLocationMod.AdvitiseSizePopUps600800:
|
||||||
|
arr = info.PopUps600800Imgs
|
||||||
|
case advitiseLocationMod.AdvitiseSizePopUps512512:
|
||||||
|
arr = info.PopUps512512Imgs
|
||||||
|
case advitiseLocationMod.AdvitiseSizeSmallCube:
|
||||||
|
arr = info.SmallCubeImgs
|
||||||
|
case advitiseLocationMod.AdvitiseSizeVerticalCube:
|
||||||
|
arr = info.VerticalCubeImgs
|
||||||
|
}
|
||||||
|
if len(arr) > 0 {
|
||||||
|
return arr[0]
|
||||||
|
}
|
||||||
|
// 兜底:任一非空数组的第一张
|
||||||
|
for _, cand := range [][]string{
|
||||||
|
info.FullScreenImgs, info.Banner720300Imgs, info.Banner720150Imgs,
|
||||||
|
info.Banner750700Imgs, info.Banner800450Imgs,
|
||||||
|
info.PopUps600800Imgs, info.PopUps512512Imgs,
|
||||||
|
info.SmallCubeImgs, info.VerticalCubeImgs,
|
||||||
|
} {
|
||||||
|
if len(cand) > 0 {
|
||||||
|
return cand[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func uniqInt64(in []int64) []int64 {
|
||||||
|
seen := make(map[int64]struct{}, len(in))
|
||||||
|
out := make([]int64, 0, len(in))
|
||||||
|
for _, v := range in {
|
||||||
|
if _, ok := seen[v]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[v] = struct{}{}
|
||||||
|
out = append(out, v)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func uniqInt32(in []int32) []int32 {
|
||||||
|
seen := make(map[int32]struct{}, len(in))
|
||||||
|
out := make([]int32, 0, len(in))
|
||||||
|
for _, v := range in {
|
||||||
|
if _, ok := seen[v]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[v] = struct{}{}
|
||||||
|
out = append(out, v)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClickAdvitise 点击回传:media 逻辑
|
||||||
|
// 1. advitise_click_stat upsert +1 (appId, advitiseId, locationId, day)
|
||||||
|
// 2. advitise_day_click_stat upsert +1 (advitiseId, day)
|
||||||
|
func ClickAdvitise(ctx context.Context, req *proto.ClickAdvitiseV2Req) error {
|
||||||
|
bindId := req.Id / idScale
|
||||||
|
location := int32(req.Id % idScale)
|
||||||
|
bind, err := advitiseBindMod.FindOneAdvitiseBind(ctx, bson.M{advitiseBindMod.FN.AdvitiseBind.Id: bindId})
|
||||||
|
if err != nil || bind == nil {
|
||||||
|
return errors.New("bind not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
day := time.Now().Truncate(24 * time.Hour)
|
||||||
|
|
||||||
|
if err := advitiseClickStatMod.InsertOrUpdate(ctx, bind.AppId, bind.AdvitiseId, location, day); err != nil {
|
||||||
|
log.Warn("v2 click: fine stat upsert failed", log.E(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := advitiseDayClickStatMod.InsertOrUpdate(ctx, bind.AdvitiseId, day); err != nil {
|
||||||
|
// 汇总表失败不阻断细维度已成功的记录
|
||||||
|
log.Warn("v2 click: day rollup upsert failed", log.E(err))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package advitiseV2Ser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/genId"
|
||||||
|
"stat/models/advitiseInfoMod"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InfoList(ctx context.Context, req *proto.AdvitiseInfoListReq) (*proto.AdvitiseInfoListResp, error) {
|
||||||
|
resp := &proto.AdvitiseInfoListResp{
|
||||||
|
Total: 0,
|
||||||
|
List: make(advitiseInfoMod.AdvitiseInfoList, 0),
|
||||||
|
}
|
||||||
|
filter := bson.M{}
|
||||||
|
if req.Title != "" {
|
||||||
|
filter[advitiseInfoMod.FN.AdvitiseInfo.Title] = bson.M{"$regex": req.Title, "$options": "i"}
|
||||||
|
}
|
||||||
|
if req.Remark != "" {
|
||||||
|
filter[advitiseInfoMod.FN.AdvitiseInfo.Remark] = bson.M{"$regex": req.Remark, "$options": "i"}
|
||||||
|
}
|
||||||
|
if req.Status != nil {
|
||||||
|
filter[advitiseInfoMod.FN.AdvitiseInfo.Status] = *req.Status
|
||||||
|
}
|
||||||
|
total, err := advitiseInfoMod.CountAdvitiseInfos(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
opt := &options.FindOptions{}
|
||||||
|
opt.SetSort(bson.D{{Key: advitiseInfoMod.FN.AdvitiseInfo.CreatedAt, Value: -1}})
|
||||||
|
opt.SetSkip((req.PageNum - 1) * req.PageSize)
|
||||||
|
opt.SetLimit(req.PageSize)
|
||||||
|
list, err := advitiseInfoMod.FindManyAdvitiseInfos(ctx, filter, opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp.Total = total
|
||||||
|
resp.List = list
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func InfoAdd(ctx context.Context, req *proto.AddAdvitiseInfoReq) error {
|
||||||
|
now := time.Now()
|
||||||
|
doc := &advitiseInfoMod.AdvitiseInfo{
|
||||||
|
Id: genId.GetAdvitiseInfoId(),
|
||||||
|
Title: req.Title,
|
||||||
|
FullScreenImgs: emptyIfNil(req.FullScreenImgs),
|
||||||
|
Banner720300Imgs: emptyIfNil(req.Banner720300Imgs),
|
||||||
|
Banner720150Imgs: emptyIfNil(req.Banner720150Imgs),
|
||||||
|
Banner750700Imgs: emptyIfNil(req.Banner750700Imgs),
|
||||||
|
Banner800450Imgs: emptyIfNil(req.Banner800450Imgs),
|
||||||
|
PopUps600800Imgs: emptyIfNil(req.PopUps600800Imgs),
|
||||||
|
PopUps512512Imgs: emptyIfNil(req.PopUps512512Imgs),
|
||||||
|
SmallCubeImgs: emptyIfNil(req.SmallCubeImgs),
|
||||||
|
VerticalCubeImgs: emptyIfNil(req.VerticalCubeImgs),
|
||||||
|
RandomNames: emptyIfNil(req.RandomNames),
|
||||||
|
Link: req.Link,
|
||||||
|
Status: req.Status,
|
||||||
|
StartTime: req.StartTime,
|
||||||
|
EndTime: req.EndTime,
|
||||||
|
Remark: req.Remark,
|
||||||
|
Desc: req.Desc,
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
return advitiseInfoMod.InsertOneAdvitiseInfo(ctx, doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func InfoUpdate(ctx context.Context, req *proto.UpdateAdvitiseInfoReq) error {
|
||||||
|
set := bson.M{
|
||||||
|
advitiseInfoMod.FN.AdvitiseInfo.UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
if req.Title != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Title] = *req.Title
|
||||||
|
}
|
||||||
|
if req.FullScreenImgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.FullScreenImgs] = *req.FullScreenImgs
|
||||||
|
}
|
||||||
|
if req.Banner720300Imgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Banner720300Imgs] = *req.Banner720300Imgs
|
||||||
|
}
|
||||||
|
if req.Banner720150Imgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Banner720150Imgs] = *req.Banner720150Imgs
|
||||||
|
}
|
||||||
|
if req.Banner750700Imgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Banner750700Imgs] = *req.Banner750700Imgs
|
||||||
|
}
|
||||||
|
if req.Banner800450Imgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Banner800450Imgs] = *req.Banner800450Imgs
|
||||||
|
}
|
||||||
|
if req.PopUps600800Imgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.PopUps600800Imgs] = *req.PopUps600800Imgs
|
||||||
|
}
|
||||||
|
if req.PopUps512512Imgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.PopUps512512Imgs] = *req.PopUps512512Imgs
|
||||||
|
}
|
||||||
|
if req.SmallCubeImgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.SmallCubeImgs] = *req.SmallCubeImgs
|
||||||
|
}
|
||||||
|
if req.VerticalCubeImgs != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.VerticalCubeImgs] = *req.VerticalCubeImgs
|
||||||
|
}
|
||||||
|
if req.RandomNames != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.RandomNames] = *req.RandomNames
|
||||||
|
}
|
||||||
|
if req.Link != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Link] = *req.Link
|
||||||
|
}
|
||||||
|
if req.Status != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Status] = *req.Status
|
||||||
|
}
|
||||||
|
if req.StartTime != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.StartTime] = *req.StartTime
|
||||||
|
}
|
||||||
|
if req.EndTime != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.EndTime] = *req.EndTime
|
||||||
|
}
|
||||||
|
if req.Remark != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Remark] = *req.Remark
|
||||||
|
}
|
||||||
|
if req.Desc != nil {
|
||||||
|
set[advitiseInfoMod.FN.AdvitiseInfo.Desc] = *req.Desc
|
||||||
|
}
|
||||||
|
return advitiseInfoMod.UpdateOneAdvitiseInfo(ctx,
|
||||||
|
bson.M{advitiseInfoMod.FN.AdvitiseInfo.Id: req.Id},
|
||||||
|
bson.M{"$set": set},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func InfoDel(ctx context.Context, id int64) error {
|
||||||
|
_, err := advitiseInfoMod.DelOneAdvitiseInfo(ctx, bson.M{advitiseInfoMod.FN.AdvitiseInfo.Id: id})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func emptyIfNil(s []string) []string {
|
||||||
|
if s == nil {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package advitiseV2Ser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/common/genId"
|
||||||
|
"stat/models/advitiseLocationMod"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LocationList(ctx context.Context, req *proto.AdvitiseLocationListReq) (*proto.AdvitiseLocationListResp, error) {
|
||||||
|
resp := &proto.AdvitiseLocationListResp{
|
||||||
|
Total: 0,
|
||||||
|
List: make(advitiseLocationMod.AdvitiseLocationList, 0),
|
||||||
|
}
|
||||||
|
filter := bson.M{}
|
||||||
|
if req.AppId != nil {
|
||||||
|
filter[advitiseLocationMod.FN.AdvitiseLocation.AppId] = *req.AppId
|
||||||
|
}
|
||||||
|
if req.LocId != nil {
|
||||||
|
filter[advitiseLocationMod.FN.AdvitiseLocation.LocId] = *req.LocId
|
||||||
|
}
|
||||||
|
if req.Name != "" {
|
||||||
|
filter[advitiseLocationMod.FN.AdvitiseLocation.Name] = bson.M{"$regex": req.Name, "$options": "i"}
|
||||||
|
}
|
||||||
|
total, err := advitiseLocationMod.CountAdvitiseLocations(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
opt := &options.FindOptions{}
|
||||||
|
opt.SetSort(bson.D{{Key: advitiseLocationMod.FN.AdvitiseLocation.CreatedAt, Value: -1}})
|
||||||
|
opt.SetSkip((req.PageNum - 1) * req.PageSize)
|
||||||
|
opt.SetLimit(req.PageSize)
|
||||||
|
list, err := advitiseLocationMod.FindManyAdvitiseLocations(ctx, filter, opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp.Total = total
|
||||||
|
resp.List = list
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LocationAdd(ctx context.Context, req *proto.AddAdvitiseLocationReq) error {
|
||||||
|
now := time.Now()
|
||||||
|
doc := &advitiseLocationMod.AdvitiseLocation{
|
||||||
|
Id: genId.GetAdvitiseLocationId(),
|
||||||
|
AppId: req.AppId,
|
||||||
|
LocId: req.LocId,
|
||||||
|
Name: req.Name,
|
||||||
|
AdvitiseSize: req.AdvitiseSize,
|
||||||
|
ImgSizeDesc: req.ImgSizeDesc,
|
||||||
|
Remark: req.Remark,
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
return advitiseLocationMod.InsertOneAdvitiseLocation(ctx, doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LocationUpdate(ctx context.Context, req *proto.UpdateAdvitiseLocationReq) error {
|
||||||
|
set := bson.M{
|
||||||
|
advitiseLocationMod.FN.AdvitiseLocation.UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
if req.AppId != nil {
|
||||||
|
set[advitiseLocationMod.FN.AdvitiseLocation.AppId] = *req.AppId
|
||||||
|
}
|
||||||
|
if req.LocId != nil {
|
||||||
|
set[advitiseLocationMod.FN.AdvitiseLocation.LocId] = *req.LocId
|
||||||
|
}
|
||||||
|
if req.Name != nil {
|
||||||
|
set[advitiseLocationMod.FN.AdvitiseLocation.Name] = *req.Name
|
||||||
|
}
|
||||||
|
if req.AdvitiseSize != nil {
|
||||||
|
set[advitiseLocationMod.FN.AdvitiseLocation.AdvitiseSize] = *req.AdvitiseSize
|
||||||
|
}
|
||||||
|
if req.ImgSizeDesc != nil {
|
||||||
|
set[advitiseLocationMod.FN.AdvitiseLocation.ImgSizeDesc] = *req.ImgSizeDesc
|
||||||
|
}
|
||||||
|
if req.Remark != nil {
|
||||||
|
set[advitiseLocationMod.FN.AdvitiseLocation.Remark] = *req.Remark
|
||||||
|
}
|
||||||
|
return advitiseLocationMod.UpdateOneAdvitiseLocation(ctx,
|
||||||
|
bson.M{advitiseLocationMod.FN.AdvitiseLocation.Id: req.Id},
|
||||||
|
bson.M{"$set": set},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LocationDel(ctx context.Context, id int64) error {
|
||||||
|
_, err := advitiseLocationMod.DelOneAdvitiseLocation(ctx, bson.M{advitiseLocationMod.FN.AdvitiseLocation.Id: id})
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
package advitiseV2Ser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"stat/api/proto"
|
||||||
|
"stat/models/advitiseClickStatMod"
|
||||||
|
"stat/models/advitiseDayClickStatMod"
|
||||||
|
"stat/models/advitiseInfoMod"
|
||||||
|
"stat/models/advitiseLocationMod"
|
||||||
|
"stat/models/appInfoMod"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
const statDateLayout = "2006-01-02"
|
||||||
|
|
||||||
|
func parseDateRange(startS, endS string) (start, end time.Time, ok bool) {
|
||||||
|
// 允许两种格式:yyyy-MM-dd 和 yyyy-MM-dd HH:mm:ss
|
||||||
|
tryLayouts := []string{"2006-01-02 15:04:05", "2006-01-02"}
|
||||||
|
if startS != "" {
|
||||||
|
for _, l := range tryLayouts {
|
||||||
|
if t, err := time.ParseInLocation(l, startS, time.Local); err == nil {
|
||||||
|
start = t.Truncate(24 * time.Hour)
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if endS != "" {
|
||||||
|
for _, l := range tryLayouts {
|
||||||
|
if t, err := time.ParseInLocation(l, endS, time.Local); err == nil {
|
||||||
|
end = t.Truncate(24 * time.Hour)
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DayClickList 广告每日点击汇总列表(advitise_day_click_stat)
|
||||||
|
func DayClickList(ctx context.Context, req *proto.AdvitiseDayClickListReq) (*proto.AdvitiseDayClickListResp, error) {
|
||||||
|
resp := &proto.AdvitiseDayClickListResp{List: make([]*proto.AdvitiseDayClickItem, 0)}
|
||||||
|
filter := bson.M{}
|
||||||
|
if req.Id != nil {
|
||||||
|
filter[advitiseDayClickStatMod.FN.AdvitiseDayClickStat.AdvitiseId] = *req.Id
|
||||||
|
}
|
||||||
|
start, end, _ := parseDateRange(req.StatStartDate, req.StatEndDate)
|
||||||
|
dateFilter := bson.M{}
|
||||||
|
if !start.IsZero() {
|
||||||
|
dateFilter["$gte"] = start
|
||||||
|
}
|
||||||
|
if !end.IsZero() {
|
||||||
|
dateFilter["$lte"] = end
|
||||||
|
}
|
||||||
|
if len(dateFilter) > 0 {
|
||||||
|
filter[advitiseDayClickStatMod.FN.AdvitiseDayClickStat.StatDate] = dateFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
total, err := advitiseDayClickStatMod.Count(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
opt := &options.FindOptions{}
|
||||||
|
opt.SetSort(bson.D{{Key: advitiseDayClickStatMod.FN.AdvitiseDayClickStat.StatDate, Value: -1}})
|
||||||
|
opt.SetSkip((req.PageNum - 1) * req.PageSize)
|
||||||
|
opt.SetLimit(req.PageSize)
|
||||||
|
list, err := advitiseDayClickStatMod.FindMany(ctx, filter, opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 批量拉广告标题
|
||||||
|
advIds := make([]int64, 0, len(list))
|
||||||
|
for _, r := range list {
|
||||||
|
advIds = append(advIds, r.AdvitiseId)
|
||||||
|
}
|
||||||
|
nameMap := loadInfoNames(ctx, advIds)
|
||||||
|
|
||||||
|
for _, r := range list {
|
||||||
|
resp.List = append(resp.List, &proto.AdvitiseDayClickItem{
|
||||||
|
AdsId: r.AdvitiseId,
|
||||||
|
AdsName: nameMap[r.AdvitiseId],
|
||||||
|
Clicks: r.Clicks,
|
||||||
|
StatDate: r.StatDate.Format(statDateLayout),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
resp.Total = total
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClickList 广告细维度点击列表(advitise_click_stat)。既用于「每日点击详情」也用于「广告位查看统计」入口
|
||||||
|
func ClickList(ctx context.Context, req *proto.AdvitiseClickListReq) (*proto.AdvitiseClickListResp, error) {
|
||||||
|
resp := &proto.AdvitiseClickListResp{List: make([]*proto.AdvitiseClickItem, 0)}
|
||||||
|
filter := bson.M{}
|
||||||
|
if req.AdsId != nil {
|
||||||
|
filter[advitiseClickStatMod.FN.AdvitiseClickStat.AdvitiseId] = *req.AdsId
|
||||||
|
}
|
||||||
|
if req.AppId != nil {
|
||||||
|
filter[advitiseClickStatMod.FN.AdvitiseClickStat.AppId] = *req.AppId
|
||||||
|
}
|
||||||
|
if req.LocationId != nil {
|
||||||
|
filter[advitiseClickStatMod.FN.AdvitiseClickStat.LocationId] = *req.LocationId
|
||||||
|
}
|
||||||
|
start, end, _ := parseDateRange(req.StatStartDate, req.StatEndDate)
|
||||||
|
dateFilter := bson.M{}
|
||||||
|
if !start.IsZero() {
|
||||||
|
dateFilter["$gte"] = start
|
||||||
|
}
|
||||||
|
if !end.IsZero() {
|
||||||
|
dateFilter["$lte"] = end
|
||||||
|
}
|
||||||
|
if len(dateFilter) > 0 {
|
||||||
|
filter[advitiseClickStatMod.FN.AdvitiseClickStat.StatDate] = dateFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
total, err := advitiseClickStatMod.Count(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
opt := &options.FindOptions{}
|
||||||
|
opt.SetSort(bson.D{{Key: advitiseClickStatMod.FN.AdvitiseClickStat.StatDate, Value: -1}})
|
||||||
|
opt.SetSkip((req.PageNum - 1) * req.PageSize)
|
||||||
|
opt.SetLimit(req.PageSize)
|
||||||
|
list, err := advitiseClickStatMod.FindMany(ctx, filter, opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量映射名字
|
||||||
|
advIds := make([]int64, 0)
|
||||||
|
appIds := make(map[int32]bool)
|
||||||
|
locIds := make(map[int32]bool)
|
||||||
|
for _, r := range list {
|
||||||
|
advIds = append(advIds, r.AdvitiseId)
|
||||||
|
appIds[r.AppId] = true
|
||||||
|
locIds[r.LocationId] = true
|
||||||
|
}
|
||||||
|
advNameMap := loadInfoNames(ctx, advIds)
|
||||||
|
appNameMap, _ := appInfoMod.GetAllAppIdNameMap(ctx)
|
||||||
|
// 位置名字 — 用 (appId, locId) 组合查
|
||||||
|
type locKey struct {
|
||||||
|
appId int32
|
||||||
|
locId int32
|
||||||
|
}
|
||||||
|
locNameMap := make(map[locKey]string)
|
||||||
|
if len(locIds) > 0 {
|
||||||
|
locIdsSlice := make([]int32, 0, len(locIds))
|
||||||
|
for id := range locIds {
|
||||||
|
locIdsSlice = append(locIdsSlice, id)
|
||||||
|
}
|
||||||
|
appIdsSlice := make([]int32, 0, len(appIds))
|
||||||
|
for id := range appIds {
|
||||||
|
appIdsSlice = append(appIdsSlice, id)
|
||||||
|
}
|
||||||
|
locs, lerr := advitiseLocationMod.FindManyAdvitiseLocations(ctx, bson.M{
|
||||||
|
advitiseLocationMod.FN.AdvitiseLocation.AppId: bson.M{"$in": appIdsSlice},
|
||||||
|
advitiseLocationMod.FN.AdvitiseLocation.LocId: bson.M{"$in": locIdsSlice},
|
||||||
|
})
|
||||||
|
if lerr == nil {
|
||||||
|
for _, l := range locs {
|
||||||
|
locNameMap[locKey{appId: l.AppId, locId: l.LocId}] = l.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range list {
|
||||||
|
resp.List = append(resp.List, &proto.AdvitiseClickItem{
|
||||||
|
AppId: r.AppId,
|
||||||
|
AppName: appNameMap[r.AppId],
|
||||||
|
AdsId: r.AdvitiseId,
|
||||||
|
AdsName: advNameMap[r.AdvitiseId],
|
||||||
|
LocationId: r.LocationId,
|
||||||
|
LocationName: locNameMap[locKey{appId: r.AppId, locId: r.LocationId}],
|
||||||
|
Clicks: r.Clicks,
|
||||||
|
StatDate: r.StatDate.Format(statDateLayout),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
resp.Total = total
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClickSummary 按时间范围汇总广告点击量,分页按 clicks desc
|
||||||
|
// aggregate pipeline: $match → $group by advitiseId → $sort clicks desc → $facet(list, total, grandTotal)
|
||||||
|
func ClickSummary(ctx context.Context, req *proto.AdvitiseClickSummaryReq) (*proto.AdvitiseClickSummaryResp, error) {
|
||||||
|
resp := &proto.AdvitiseClickSummaryResp{List: make([]*proto.AdvitiseClickSummaryItem, 0)}
|
||||||
|
|
||||||
|
match := bson.M{}
|
||||||
|
if req.Id != nil {
|
||||||
|
match[advitiseClickStatMod.FN.AdvitiseClickStat.AdvitiseId] = *req.Id
|
||||||
|
}
|
||||||
|
if req.AppId != nil {
|
||||||
|
match[advitiseClickStatMod.FN.AdvitiseClickStat.AppId] = *req.AppId
|
||||||
|
}
|
||||||
|
if req.LocationId != nil {
|
||||||
|
match[advitiseClickStatMod.FN.AdvitiseClickStat.LocationId] = *req.LocationId
|
||||||
|
}
|
||||||
|
start, end, _ := parseDateRange(req.StatStartDate, req.StatEndDate)
|
||||||
|
dateFilter := bson.M{}
|
||||||
|
if !start.IsZero() {
|
||||||
|
dateFilter["$gte"] = start
|
||||||
|
}
|
||||||
|
if !end.IsZero() {
|
||||||
|
dateFilter["$lte"] = end
|
||||||
|
}
|
||||||
|
if len(dateFilter) > 0 {
|
||||||
|
match[advitiseClickStatMod.FN.AdvitiseClickStat.StatDate] = dateFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline := []bson.M{
|
||||||
|
{"$match": match},
|
||||||
|
{"$group": bson.M{
|
||||||
|
"_id": "$" + advitiseClickStatMod.FN.AdvitiseClickStat.AdvitiseId,
|
||||||
|
"totalClicks": bson.M{"$sum": "$" + advitiseClickStatMod.FN.AdvitiseClickStat.Clicks},
|
||||||
|
}},
|
||||||
|
{"$facet": bson.M{
|
||||||
|
"list": []bson.M{
|
||||||
|
{"$sort": bson.M{"totalClicks": -1}},
|
||||||
|
{"$skip": (req.PageNum - 1) * req.PageSize},
|
||||||
|
{"$limit": req.PageSize},
|
||||||
|
},
|
||||||
|
"total": []bson.M{{"$count": "count"}},
|
||||||
|
"grandTotal": []bson.M{{"$group": bson.M{"_id": nil, "sum": bson.M{"$sum": "$totalClicks"}}}},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
type facetRow struct {
|
||||||
|
List []struct {
|
||||||
|
Id int64 `bson:"_id"`
|
||||||
|
TotalClicks int64 `bson:"totalClicks"`
|
||||||
|
} `bson:"list"`
|
||||||
|
Total []struct {
|
||||||
|
Count int64 `bson:"count"`
|
||||||
|
} `bson:"total"`
|
||||||
|
GrandTotal []struct {
|
||||||
|
Sum int64 `bson:"sum"`
|
||||||
|
} `bson:"grandTotal"`
|
||||||
|
}
|
||||||
|
rows := make([]facetRow, 0, 1)
|
||||||
|
if err := advitiseClickStatMod.Aggregate(ctx, &rows, pipeline); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var facet facetRow
|
||||||
|
if len(rows) > 0 {
|
||||||
|
facet = rows[0]
|
||||||
|
}
|
||||||
|
if len(facet.Total) > 0 {
|
||||||
|
resp.Total = facet.Total[0].Count
|
||||||
|
}
|
||||||
|
if len(facet.GrandTotal) > 0 {
|
||||||
|
resp.GrandTotal = facet.GrandTotal[0].Sum
|
||||||
|
}
|
||||||
|
|
||||||
|
advIds := make([]int64, 0, len(facet.List))
|
||||||
|
for _, r := range facet.List {
|
||||||
|
advIds = append(advIds, r.Id)
|
||||||
|
}
|
||||||
|
nameMap := loadInfoNames(ctx, advIds)
|
||||||
|
for _, r := range facet.List {
|
||||||
|
resp.List = append(resp.List, &proto.AdvitiseClickSummaryItem{
|
||||||
|
AdsId: r.Id,
|
||||||
|
AdsName: nameMap[r.Id],
|
||||||
|
TotalClicks: r.TotalClicks,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadInfoNames(ctx context.Context, advIds []int64) map[int64]string {
|
||||||
|
m := make(map[int64]string)
|
||||||
|
if len(advIds) == 0 {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
infos, err := advitiseInfoMod.FindManyAdvitiseInfos(ctx, bson.M{
|
||||||
|
advitiseInfoMod.FN.AdvitiseInfo.Id: bson.M{"$in": advIds},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
for _, info := range infos {
|
||||||
|
m[info.Id] = info.Title
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
+3
-2
@@ -51,8 +51,9 @@ type GlobalConfig struct {
|
|||||||
ManhuaPackageUrl string `json:"manhuaPackageUrl"`
|
ManhuaPackageUrl string `json:"manhuaPackageUrl"`
|
||||||
} `json:"url"`
|
} `json:"url"`
|
||||||
ProxyUrl struct {
|
ProxyUrl struct {
|
||||||
File string `json:"file"`
|
File string `json:"file"`
|
||||||
FileRes string `json:"fileRes"`
|
FileRes string `json:"fileRes"`
|
||||||
|
FileRes1 string `json:"fileRes1"`
|
||||||
} `json:"proxyUrl"`
|
} `json:"proxyUrl"`
|
||||||
KafkaServer bool `json:"kafkaServer"`
|
KafkaServer bool `json:"kafkaServer"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
|
|||||||
Reference in New Issue
Block a user