Initial commit

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-11-07 10:47:18 +08:00
co-authored by Claude Opus 4.7
commit 79ac89b458
708 changed files with 151634 additions and 0 deletions
+172
View File
@@ -0,0 +1,172 @@
package playletbackflowstatmod
import (
"context"
"fmt"
"time"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/mongos"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var coll *mongos.Collection
// Init 初始化原创短剧 AI 内容回流日统计表和查询索引。
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.PlayletBackflowDailyStat)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.PlayletBackflowDailyStat.DataDate, Value: 1},
{Key: FN.PlayletBackflowDailyStat.ReportStatus, Value: 1},
{Key: FN.PlayletBackflowDailyStat.Id, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.PlayletBackflowDailyStat.DataDate, Value: 1},
{Key: FN.PlayletBackflowDailyStat.PlayletId, Value: 1},
},
Options: options.Index().SetUnique(true).SetName("uniq_dataDate_playletId"),
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(playletbackflowstatmod:initIndex) Create Index failed! err:%+v:", err))
}
}
// UpsertManyPlayletBackflowDailyStats 批量保存每天原创短剧回流数据快照。
func UpsertManyPlayletBackflowDailyStats(ctx context.Context, docs PlayletBackflowDailyStatList) *srvdef.SrvErr {
if len(docs) == 0 {
return nil
}
now := time.Now()
writes := make([]mongo.WriteModel, 0, len(docs))
for _, doc := range docs {
if doc == nil || doc.DataDate == "" || doc.PlayletId <= 0 {
continue
}
doc.UpdatedAt = now
doc.LastStatAt = now
update := bson.M{
"$set": bson.M{
FN.PlayletBackflowDailyStat.DataDate: doc.DataDate,
FN.PlayletBackflowDailyStat.PlayletId: doc.PlayletId,
FN.PlayletBackflowDailyStat.ChapterId: doc.ChapterId,
FN.PlayletBackflowDailyStat.CurrentEpisode: doc.CurrentEpisode,
FN.PlayletBackflowDailyStat.MediaCenterId: doc.MediaCenterId,
FN.PlayletBackflowDailyStat.MediaContentId: doc.MediaContentId,
FN.PlayletBackflowDailyStat.Title: doc.Title,
FN.PlayletBackflowDailyStat.PublishedData: doc.PublishedData,
FN.PlayletBackflowDailyStat.ScriptName: doc.ScriptName,
FN.PlayletBackflowDailyStat.DramaName: doc.DramaName,
FN.PlayletBackflowDailyStat.DramaNo: doc.DramaNo,
FN.PlayletBackflowDailyStat.VideoURL: doc.VideoURL,
FN.PlayletBackflowDailyStat.PlatformURL: doc.PlatformURL,
FN.PlayletBackflowDailyStat.Views: doc.Views,
FN.PlayletBackflowDailyStat.Clicks: doc.Clicks,
FN.PlayletBackflowDailyStat.Likes: doc.Likes,
FN.PlayletBackflowDailyStat.LikeRate: doc.LikeRate,
FN.PlayletBackflowDailyStat.CompletionRate: doc.CompletionRate,
FN.PlayletBackflowDailyStat.PaidRate: doc.PaidRate,
FN.PlayletBackflowDailyStat.Comments: doc.Comments,
FN.PlayletBackflowDailyStat.Shares: doc.Shares,
FN.PlayletBackflowDailyStat.CompletionRateScope: doc.CompletionRateScope,
FN.PlayletBackflowDailyStat.ReportStatus: doc.ReportStatus,
FN.PlayletBackflowDailyStat.ReportError: "",
FN.PlayletBackflowDailyStat.LastStatAt: doc.LastStatAt,
FN.PlayletBackflowDailyStat.UpdatedAt: doc.UpdatedAt,
},
"$setOnInsert": bson.M{
FN.PlayletBackflowDailyStat.Id: primitive.NewObjectID(),
FN.PlayletBackflowDailyStat.ReportRetryCount: int64(0),
FN.PlayletBackflowDailyStat.CreatedAt: now,
},
}
model := mongo.NewUpdateOneModel().
SetFilter(bson.M{
FN.PlayletBackflowDailyStat.DataDate: doc.DataDate,
FN.PlayletBackflowDailyStat.PlayletId: doc.PlayletId,
}).
SetUpdate(update).
SetUpsert(true)
writes = append(writes, model)
}
if len(writes) == 0 {
return nil
}
if _, err := coll.BulkWrite(ctx, writes, options.BulkWrite().SetOrdered(false)); err != nil {
log.Warn("playletbackflowstatmod:UpsertManyPlayletBackflowDailyStats failed", log.E(err), log.Any("count", len(writes)))
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
return nil
}
// FindManyPlayletBackflowDailyStats 查询原创短剧回流日统计。
func FindManyPlayletBackflowDailyStats(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletBackflowDailyStatList, *srvdef.SrvErr) {
data := make(PlayletBackflowDailyStatList, 0)
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
log.Warn("playletbackflowstatmod:FindManyPlayletBackflowDailyStats failed", log.E(err), log.Any("filter", filter))
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return data, nil
}
// CountPlayletBackflowDailyStats 统计原创短剧回流日统计条数。
func CountPlayletBackflowDailyStats(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
count, err := coll.Count(ctx, filter, opts...)
if err != nil {
log.Warn("playletbackflowstatmod:CountPlayletBackflowDailyStats failed", log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return count, nil
}
// MarkPlayletBackflowDailyStatsReported 把一批统计记录标记为上报成功。
func MarkPlayletBackflowDailyStatsReported(ctx context.Context, ids []primitive.ObjectID, reportAt time.Time) *srvdef.SrvErr {
if len(ids) == 0 {
return nil
}
_, err := coll.UpdateMany(ctx, bson.M{FN.PlayletBackflowDailyStat.Id: bson.M{"$in": ids}}, bson.M{"$set": bson.M{
FN.PlayletBackflowDailyStat.ReportStatus: ReportStatusSuccess,
FN.PlayletBackflowDailyStat.ReportAt: reportAt,
FN.PlayletBackflowDailyStat.ReportError: "",
FN.PlayletBackflowDailyStat.UpdatedAt: time.Now(),
}})
if err != nil {
log.Warn("playletbackflowstatmod:MarkPlayletBackflowDailyStatsReported failed", log.E(err), log.Any("count", len(ids)))
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
return nil
}
// MarkPlayletBackflowDailyStatsFailed 把一批统计记录标记为上报失败。
func MarkPlayletBackflowDailyStatsFailed(ctx context.Context, ids []primitive.ObjectID, reportErr string) *srvdef.SrvErr {
if len(ids) == 0 {
return nil
}
_, err := coll.UpdateMany(ctx, bson.M{FN.PlayletBackflowDailyStat.Id: bson.M{"$in": ids}}, bson.M{
"$set": bson.M{
FN.PlayletBackflowDailyStat.ReportStatus: ReportStatusFailed,
FN.PlayletBackflowDailyStat.ReportError: reportErr,
FN.PlayletBackflowDailyStat.UpdatedAt: time.Now(),
},
"$inc": bson.M{
FN.PlayletBackflowDailyStat.ReportRetryCount: int64(1),
},
})
if err != nil {
log.Warn("playletbackflowstatmod:MarkPlayletBackflowDailyStatsFailed failed", log.E(err), log.Any("count", len(ids)))
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
return nil
}
+78
View File
@@ -0,0 +1,78 @@
package playletbackflowstatmod
// TagPlayletBackflowDailyStat 保存 playlet_backflow_daily_stat 集合字段名。
type TagPlayletBackflowDailyStat struct {
Id string
DataDate string
PlayletId string
ChapterId string
CurrentEpisode string
MediaCenterId string
MediaContentId string
Title string
PublishedData string
ScriptName string
DramaName string
DramaNo string
VideoURL string
PlatformURL string
Views string
Clicks string
Likes string
LikeRate string
CompletionRate string
PaidRate string
Comments string
Shares string
CompletionRateScope string
ReportStatus string
ReportRetryCount string
ReportAt string
ReportError string
LastStatAt string
CreatedAt string
UpdatedAt string
}
var FN struct {
PlayletBackflowDailyStat TagPlayletBackflowDailyStat
}
var TN struct {
PlayletBackflowDailyStat string
}
func init() {
FN.PlayletBackflowDailyStat.Id = "_id"
FN.PlayletBackflowDailyStat.DataDate = "dataDate"
FN.PlayletBackflowDailyStat.PlayletId = "playletId"
FN.PlayletBackflowDailyStat.ChapterId = "chapterId"
FN.PlayletBackflowDailyStat.CurrentEpisode = "currentEpisode"
FN.PlayletBackflowDailyStat.MediaCenterId = "mediaCenterId"
FN.PlayletBackflowDailyStat.MediaContentId = "mediaContentId"
FN.PlayletBackflowDailyStat.Title = "title"
FN.PlayletBackflowDailyStat.PublishedData = "publishedData"
FN.PlayletBackflowDailyStat.ScriptName = "scriptName"
FN.PlayletBackflowDailyStat.DramaName = "dramaName"
FN.PlayletBackflowDailyStat.DramaNo = "dramaNo"
FN.PlayletBackflowDailyStat.VideoURL = "videoUrl"
FN.PlayletBackflowDailyStat.PlatformURL = "platformUrl"
FN.PlayletBackflowDailyStat.Views = "views"
FN.PlayletBackflowDailyStat.Clicks = "clicks"
FN.PlayletBackflowDailyStat.Likes = "likes"
FN.PlayletBackflowDailyStat.LikeRate = "likeRate"
FN.PlayletBackflowDailyStat.CompletionRate = "completionRate"
FN.PlayletBackflowDailyStat.PaidRate = "paidRate"
FN.PlayletBackflowDailyStat.Comments = "comments"
FN.PlayletBackflowDailyStat.Shares = "shares"
FN.PlayletBackflowDailyStat.CompletionRateScope = "completionRateScope"
FN.PlayletBackflowDailyStat.ReportStatus = "reportStatus"
FN.PlayletBackflowDailyStat.ReportRetryCount = "reportRetryCount"
FN.PlayletBackflowDailyStat.ReportAt = "reportAt"
FN.PlayletBackflowDailyStat.ReportError = "reportError"
FN.PlayletBackflowDailyStat.LastStatAt = "lastStatAt"
FN.PlayletBackflowDailyStat.CreatedAt = "createdAt"
FN.PlayletBackflowDailyStat.UpdatedAt = "updatedAt"
TN.PlayletBackflowDailyStat = "playlet_backflow_daily_stat"
}
+55
View File
@@ -0,0 +1,55 @@
package playletbackflowstatmod
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// ReportStatus 是 AI 内容中台数据回流上报状态。
type ReportStatus int64
const (
ReportStatusPending ReportStatus = 0 // 待上报
ReportStatusSuccess ReportStatus = 1 // 上报成功
ReportStatusFailed ReportStatus = 2 // 上报失败
)
// PlayletBackflowDailyStat @table: playlet_backflow_daily_stat
//
// PlayletBackflowDailyStat 保存原创短剧每天回流给 AI 内容中台的数据快照。
type PlayletBackflowDailyStat struct {
Id primitive.ObjectID `json:"id" bson:"_id,omitempty"` // MongoDB ObjectID
DataDate string `json:"dataDate" bson:"dataDate"` // 指标日期,格式 DD/MM/YYYY
PlayletId int64 `json:"playletId" bson:"playletId"` // 业务短剧 ID
ChapterId int64 `json:"chapterId" bson:"chapterId"` // 上报使用的章节 ID
CurrentEpisode int64 `json:"currentEpisode" bson:"currentEpisode"` // 上报使用的章节序号
MediaCenterId int64 `json:"mediaCenterId" bson:"mediaCenterId"` // 媒资库资源 ID
MediaContentId int64 `json:"mediaContentId" bson:"mediaContentId"` // 上报剧集的媒资章节 ID
Title string `json:"title" bson:"title"` // 本地短剧标题
PublishedData string `json:"publishedData" bson:"publishedData"` // 中台字段:视频上线日期
ScriptName string `json:"scriptName" bson:"scriptName"` // 中台字段:剧本名称
DramaName string `json:"dramaName" bson:"dramaName"` // 中台字段:短剧名称
DramaNo string `json:"dramaNo" bson:"dramaNo"` // 中台字段:集数
VideoURL string `json:"videoUrl" bson:"videoUrl"` // 中台字段:成片下载/存储链接
PlatformURL string `json:"platformUrl" bson:"platformUrl"` // 中台字段:产品内播放页链接
Views int64 `json:"views" bson:"views"` // 浏览量
Clicks int64 `json:"clicks" bson:"clicks"` // 播放量
Likes int64 `json:"likes" bson:"likes"` // 点赞量
LikeRate string `json:"likeRate" bson:"likeRate"` // 点赞率
CompletionRate string `json:"completionRate" bson:"completionRate"` // 完播率
PaidRate string `json:"paidRate" bson:"paidRate"` // 付费率
Comments int64 `json:"comments" bson:"comments"` // 评论量
Shares int64 `json:"shares" bson:"shares"` // 分享量
CompletionRateScope string `json:"completionRateScope" bson:"completionRateScope"` // 完播率口径
ReportStatus ReportStatus `json:"reportStatus" bson:"reportStatus"` // 上报状态
ReportRetryCount int64 `json:"reportRetryCount" bson:"reportRetryCount"` // 上报失败次数
ReportAt time.Time `json:"reportAt" bson:"reportAt"` // 最近一次上报成功时间
ReportError string `json:"reportError" bson:"reportError"` // 最近一次上报失败原因
LastStatAt time.Time `json:"lastStatAt" bson:"lastStatAt"` // 最近一次计算时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
}
// PlayletBackflowDailyStatList 是原创短剧日回流统计列表。
type PlayletBackflowDailyStatList []*PlayletBackflowDailyStat