forked from all_user/stat_center
- 新增 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>
320 lines
8.0 KiB
Go
320 lines
8.0 KiB
Go
package advertiseSer
|
|
|
|
import (
|
|
"context"
|
|
"stat/api/proto"
|
|
"stat/common/genId"
|
|
"stat/common/log"
|
|
"stat/common/redis"
|
|
"stat/common/stdLog"
|
|
"stat/common/utils"
|
|
"stat/models/advertiseLocMod"
|
|
"stat/models/advertiseMod"
|
|
"stat/models/appInfoMod"
|
|
"strings"
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
)
|
|
|
|
// 获取广告列表
|
|
func ListAds(ctx context.Context, param proto.ListAdsReq) (code stdLog.CodeType, data interface{}, err error) {
|
|
resp := proto.ListAdsRes{
|
|
Total: 0,
|
|
List: make([]proto.AdsInfo, 0),
|
|
}
|
|
|
|
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
|
|
|
// 获取广告位置信息
|
|
total, adsList, err := advertiseMod.FindAdvertiseList(ctx, param.AppId, param.IsActive,
|
|
param.LocId, skip, limit, param.Link, param.Title, param.DaoLiangTitle)
|
|
if err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
resp.Total = total
|
|
|
|
// 获取app信息
|
|
appIds := make([]int32, 0)
|
|
for _, v := range adsList {
|
|
appIds = append(appIds, v.AppId)
|
|
}
|
|
appList, err := appInfoMod.GetAppInfosByAppIds(ctx, appIds)
|
|
if err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
appMap := make(map[int32]appInfoMod.AppInfo)
|
|
for _, v := range appList {
|
|
appMap[v.AppId] = v
|
|
}
|
|
|
|
for _, v := range adsList {
|
|
appName := ""
|
|
if appInfo, ok := appMap[v.AppId]; ok {
|
|
appName = appInfo.Name
|
|
}
|
|
|
|
// 获取位置信息
|
|
adsLocInfo, err := advertiseLocMod.FindLocationByAppIdAndLocId(ctx, v.AppId, v.LocId)
|
|
if err != nil {
|
|
code = stdLog.Failure
|
|
return code, data, err
|
|
}
|
|
str := make([]string, 0)
|
|
if v.Tags != "" {
|
|
split := strings.Split(strings.TrimSpace(v.Tags), ",")
|
|
for _, s := range split {
|
|
str = append(str, s)
|
|
}
|
|
}
|
|
tmp := proto.AdsInfo{
|
|
Id: v.Id,
|
|
AppId: v.AppId,
|
|
AppName: appName,
|
|
Title: v.Title,
|
|
DaoLiangTitle: v.DaoLiangTitle,
|
|
Tags: str,
|
|
CoverImg: v.CoverImg,
|
|
VisibleChannels: v.VisibleChannels,
|
|
LocId: v.LocId,
|
|
LocName: adsLocInfo.Name,
|
|
ImgSizeDesc: adsLocInfo.ImgSizeDesc,
|
|
Links: make([]proto.LinkInfo, 0),
|
|
Sort: v.Sort,
|
|
IsActive: v.IsActive,
|
|
StartTime: v.StartTime,
|
|
EndTime: v.EndTime,
|
|
Remark: v.Remark,
|
|
ClickCount: v.ClickCount,
|
|
AmbientColor: v.AmbientColor,
|
|
CreatedAt: v.CreatedAt,
|
|
UpdatedAt: v.UpdatedAt,
|
|
}
|
|
|
|
for _, v := range v.Links {
|
|
tmp.Links = append(tmp.Links, proto.LinkInfo{
|
|
Link: v.Link,
|
|
Foreign: v.Foreign,
|
|
Weight: v.Weight,
|
|
})
|
|
}
|
|
|
|
resp.List = append(resp.List, tmp)
|
|
}
|
|
|
|
code = stdLog.Success
|
|
data = resp
|
|
return
|
|
}
|
|
|
|
// 新增广告
|
|
func AddAds(ctx context.Context, param proto.AddAdsReq, account string) (code stdLog.CodeType, data interface{}, err error) {
|
|
adsId := genId.GetNextAdsId()
|
|
now := time.Now()
|
|
|
|
doc := advertiseMod.Advertise{
|
|
Id: adsId,
|
|
AppId: param.AppId,
|
|
Title: param.Title,
|
|
Tags: param.Tags,
|
|
CoverImg: param.CoverImg,
|
|
LocId: param.LocId,
|
|
Sort: param.Sort,
|
|
IsActive: param.IsActive,
|
|
StartTime: param.StartTime,
|
|
EndTime: param.EndTime,
|
|
Remark: param.Remark,
|
|
AmbientColor: param.AmbientColor,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
for _, v := range param.Links {
|
|
doc.Links = append(doc.Links, advertiseMod.LinkInfo{
|
|
Link: v.Link,
|
|
Foreign: v.Foreign,
|
|
Weight: v.Weight,
|
|
})
|
|
}
|
|
|
|
if err = advertiseMod.AddAdvertise(ctx, &doc); err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
newInfo, _ := advertiseMod.FindOneAdvertise(ctx, bson.M{"_id": adsId})
|
|
if newInfo != nil {
|
|
CheckChange(ctx, nil, newInfo, account)
|
|
}
|
|
|
|
code = stdLog.Success
|
|
return
|
|
}
|
|
|
|
// 修改广告位置
|
|
func UpdateAds(ctx context.Context, param proto.UpdateAdsReq, account string) (code stdLog.CodeType, data interface{}, err error) {
|
|
now := time.Now()
|
|
|
|
doc := advertiseMod.UpdateAds{
|
|
AppId: param.AppId,
|
|
Title: param.Title,
|
|
DaoLiangTitle: param.DaoLiangTitle,
|
|
Tags: param.Tags,
|
|
CoverImg: param.CoverImg,
|
|
Location: param.Location,
|
|
JumpType: param.JumpType,
|
|
Sort: param.Sort,
|
|
IsActive: param.IsActive,
|
|
StartTime: param.StartTime,
|
|
EndTime: param.EndTime,
|
|
Remark: param.Remark,
|
|
AmbientColor: param.AmbientColor,
|
|
UpdatedAt: &now,
|
|
}
|
|
if *param.Links != nil {
|
|
links := make([]advertiseMod.LinkInfo, 0)
|
|
for _, v := range *param.Links {
|
|
links = append(links, advertiseMod.LinkInfo{
|
|
Link: v.Link,
|
|
Foreign: v.Foreign,
|
|
Weight: v.Weight,
|
|
})
|
|
}
|
|
doc.Links = &links
|
|
}
|
|
|
|
if param.VisibleChannels != nil {
|
|
channels := make([]string, 0)
|
|
if len(*param.VisibleChannels) > 0 {
|
|
ch := strings.Split(*param.VisibleChannels, ",")
|
|
channels = append(channels, ch...)
|
|
}
|
|
|
|
doc.VisibleChannels = &channels
|
|
}
|
|
if doc.Location != nil {
|
|
locId := int32(*doc.Location)
|
|
doc.LocId = &locId
|
|
}
|
|
oldInfo, err := advertiseMod.FindOneAdvertise(ctx, bson.M{"_id": *param.Id})
|
|
if err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
if err = advertiseMod.UpdateAdvertise(ctx, *param.Id, doc); err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
newInfo, err := advertiseMod.FindOneAdvertise(ctx, bson.M{"_id": *param.Id})
|
|
if err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
CheckChange(ctx, oldInfo, newInfo, account)
|
|
|
|
code = stdLog.Success
|
|
return
|
|
}
|
|
|
|
// 删除广告
|
|
func DelAds(ctx context.Context, param proto.DelAdsReq, account string) (code stdLog.CodeType, data interface{}, err error) {
|
|
|
|
oldInfo, err := advertiseMod.FindOneAdvertise(ctx, bson.M{"_id": *param.Id})
|
|
if err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
if err = advertiseMod.DelAdvertise(ctx, *param.Id); err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
CheckChange(ctx, oldInfo, nil, account)
|
|
|
|
code = stdLog.Success
|
|
return
|
|
}
|
|
|
|
// 外部获取广告
|
|
func GetAdvertise(ctx context.Context, param proto.AdvertiseReq) (code stdLog.CodeType, resp *proto.AdvertiseRes, err error) {
|
|
resp = &proto.AdvertiseRes{AdvertiseList: make([]*proto.AdvertiseInfo, 0)}
|
|
log.Info("GetAdvertise", log.Any("param", param))
|
|
|
|
adsList, err := advertiseMod.FindAdsByAppAndLocation(ctx, param.AppId, param.LocId)
|
|
if err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
log.Info("GetAdvertise", log.Any("param", param), log.Any("adsList", len(adsList)))
|
|
|
|
// 遍历广告,处理系统广告
|
|
for _, v := range adsList {
|
|
adsInfo := &proto.AdvertiseInfo{
|
|
Id: v.Id,
|
|
Title: v.Title,
|
|
CoverImg: v.CoverImg,
|
|
LocId: v.LocId,
|
|
JumpType: v.JumpType,
|
|
Sort: v.Sort,
|
|
Type: 0,
|
|
Tags: v.Tags,
|
|
Remark: v.Remark,
|
|
AmbientColor: v.AmbientColor,
|
|
}
|
|
if len(v.Links) >= 1 {
|
|
adsInfo.Link = v.Links[0].Link
|
|
}
|
|
resp.AdvertiseList = append(resp.AdvertiseList, adsInfo)
|
|
}
|
|
code = stdLog.Success
|
|
err = nil
|
|
return
|
|
}
|
|
|
|
// 增加广告点击次数
|
|
// 兼容策略:先按 param.Id 精确查;如果广告已过期/删除或不属于该 AppId,回退到 (AppId, LocId) 上的最新一条广告
|
|
// LocId 未传时,回退查询只按 AppId 定位;仍找不到才返回 AdvertiseInvalid
|
|
func IncAdsClickCount(ctx context.Context, param proto.AdsClickReq) (code stdLog.CodeType, data interface{}, err error) {
|
|
// 先按 Id 查
|
|
adsInfo, findErr := advertiseMod.FindAdsById(ctx, *param.Id)
|
|
needFallback := findErr != nil || adsInfo.Id == 0 || adsInfo.AppId != *param.AppId
|
|
if needFallback {
|
|
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
|
|
}
|
|
|
|
// save to redis(用真正命中的广告 Id 统计)
|
|
now := time.Now().Local()
|
|
set := redis.GetAdvertiseClickDayHash(now)
|
|
name := redis.GetAdvertiseClickHourName(adsInfo.AppId, adsInfo.Id, now.Hour())
|
|
if _, err = set.IncInt(name, 1); err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
// update click+1 to db
|
|
if err = advertiseMod.IncAdsClickCount(ctx, adsInfo.Id); err != nil {
|
|
code = stdLog.Failure
|
|
return
|
|
}
|
|
|
|
code = stdLog.Success
|
|
return
|
|
}
|