package service import ( "cidservice/dao" "cidservice/model/dto" "cidservice/model/entity" "context" "time" "github.com/gogf/gf/v2/util/gconv" ) var Advertisement = new(advertisement) type advertisement struct{} // Add 添加广告 func (s *advertisement) Add(ctx context.Context, req *dto.AddAdvertisementReq) (res *dto.AddAdvertisementRes, err error) { advertisement := &entity.Advertisement{} if err = gconv.Struct(req, advertisement); err != nil { return } // 设置基础字段 now := time.Now() advertisement.CreatedAt = now advertisement.UpdatedAt = now advertisement.IsDeleted = false // 设置初始状态 advertisement.Status = "待审核" // 初始化统计字段 advertisement.Impressions = 0 advertisement.Clicks = 0 advertisement.Conversions = 0 advertisement.Cost = 0 if err = dao.Advertisement.Insert(ctx, advertisement); err != nil { return } res = &dto.AddAdvertisementRes{Id: advertisement.Id.Hex()} return } // Update 更新广告 func (s *advertisement) Update(ctx context.Context, req *dto.UpdateAdvertisementReq) (err error) { // 更新修改时间(不需要设置,DAO层会处理) return dao.Advertisement.Update(ctx, req) } // UpdateStatus 更新广告状态 func (s *advertisement) UpdateStatus(ctx context.Context, req *dto.UpdateAdStatusReq) (err error) { return dao.Advertisement.UpdateStatus(ctx, req.Id, req.Status) } // Audit 审核广告 func (s *advertisement) Audit(ctx context.Context, req *dto.AuditAdvertisementReq) (err error) { return dao.Advertisement.Audit(ctx, req.Id, req.AuditStatus, req.AuditReason) } // GetOne 获取广告详情 func (s *advertisement) GetOne(ctx context.Context, req *dto.GetAdvertisementReq) (res *dto.GetAdvertisementRes, err error) { advertisement, err := dao.Advertisement.GetOne(ctx, req.Id) if err != nil { return } res = &dto.GetAdvertisementRes{ Advertisement: advertisement, } return } // List 获取广告列表 func (s *advertisement) List(ctx context.Context, req *dto.ListAdvertisementReq) (res *dto.ListAdvertisementRes, err error) { list, total, err := dao.Advertisement.List(ctx, req) if err != nil { return } res = &dto.ListAdvertisementRes{ List: list, Total: int(total), } return } // UpdateAdStatistics 更新广告统计 func (s *advertisement) UpdateAdStatistics(ctx context.Context, id string, impressions, clicks, conversions int64, cost int64) (err error) { // 获取广告信息 ad, err := dao.Advertisement.GetOne(ctx, id) if err != nil { return } // 计算统计数据 totalImpressions := ad.Impressions + impressions totalClicks := ad.Clicks + clicks totalConversions := ad.Conversions + conversions totalCost := ad.Cost + cost // 计算比率 ctr := 0.0 if totalImpressions > 0 { ctr = float64(totalClicks) / float64(totalImpressions) } cvr := 0.0 if totalClicks > 0 { cvr = float64(totalConversions) / float64(totalClicks) } cpm := int64(0) if totalImpressions > 0 { cpm = totalCost * 1000 / totalImpressions } cpc := int64(0) if totalClicks > 0 { cpc = totalCost / totalClicks } // 构建更新数据 stats := map[string]interface{}{ "impressions": totalImpressions, "clicks": totalClicks, "conversions": totalConversions, "cost": totalCost, "updatedAt": time.Now(), } // 更新广告统计 err = dao.Advertisement.UpdateStatistics(ctx, id, stats) if err != nil { return } // 插入统计记录 today := time.Now() todayStart := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location()).Unix() statistics := &entity.AdStatistics{ StatType: "advertisement", StatDimension: "day", TargetId: id, TargetName: ad.Title, StatDate: todayStart, Impressions: impressions, Clicks: clicks, Conversions: conversions, Cost: cost, CTR: ctr, CVR: cvr, CPM: cpm, CPC: cpc, // CreatedAt、UpdatedAt、IsDeleted字段是嵌入字段,无需单独设置 } err = dao.AdStatistics.Upsert(ctx, statistics) return }