Initial commit: web_hghl_server
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
package playletmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"videoweb/pub/common/srvdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
const categoryRankField = "_categoryRank"
|
||||
|
||||
// PlayletCategoryBind 短剧绑定的分类及该分类下的排序
|
||||
type PlayletCategoryBind struct {
|
||||
Id int64 `json:"id" bson:"id"` // 分类ID
|
||||
Rank int64 `json:"rank" bson:"rank"` // 该分类下的排序,越大越靠前
|
||||
}
|
||||
|
||||
// NormalizeCategoryBinds 去重并丢弃无效分类ID,保留首次出现的排序
|
||||
func NormalizeCategoryBinds(binds []PlayletCategoryBind) []PlayletCategoryBind {
|
||||
result := make([]PlayletCategoryBind, 0, len(binds))
|
||||
seen := make(map[int64]struct{}, len(binds))
|
||||
for _, bind := range binds {
|
||||
if bind.Id <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[bind.Id]; ok {
|
||||
continue
|
||||
}
|
||||
seen[bind.Id] = struct{}{}
|
||||
result = append(result, PlayletCategoryBind{Id: bind.Id, Rank: bind.Rank})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CategoryIdsFromBinds 从分类绑定中提取分类ID
|
||||
func CategoryIdsFromBinds(binds []PlayletCategoryBind) []int64 {
|
||||
result := make([]int64, 0, len(binds))
|
||||
for _, bind := range binds {
|
||||
if bind.Id <= 0 {
|
||||
continue
|
||||
}
|
||||
result = append(result, bind.Id)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CategoryBindsFromIds 仅有分类ID时补默认排序0
|
||||
func CategoryBindsFromIds(ids []int64) []PlayletCategoryBind {
|
||||
result := make([]PlayletCategoryBind, 0, len(ids))
|
||||
seen := make(map[int64]struct{}, len(ids))
|
||||
for _, id := range ids {
|
||||
if id <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[id]; ok {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
result = append(result, PlayletCategoryBind{Id: id})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// MergeCategoryBindsByIds 按新分类ID集合保留旧排序,新增分类rank为0
|
||||
func MergeCategoryBindsByIds(exist []PlayletCategoryBind, ids []int64) []PlayletCategoryBind {
|
||||
rankByID := make(map[int64]int64, len(exist))
|
||||
for _, bind := range exist {
|
||||
if bind.Id <= 0 {
|
||||
continue
|
||||
}
|
||||
rankByID[bind.Id] = bind.Rank
|
||||
}
|
||||
result := make([]PlayletCategoryBind, 0, len(ids))
|
||||
seen := make(map[int64]struct{}, len(ids))
|
||||
for _, id := range ids {
|
||||
if id <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[id]; ok {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
result = append(result, PlayletCategoryBind{Id: id, Rank: rankByID[id]})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CategoryRankOf 取指定分类下的排序,未绑定返回0
|
||||
func CategoryRankOf(binds []PlayletCategoryBind, categoryId int64) int64 {
|
||||
if categoryId <= 0 {
|
||||
return 0
|
||||
}
|
||||
for _, bind := range binds {
|
||||
if bind.Id == categoryId {
|
||||
return bind.Rank
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// EffectiveCategoryBinds 历史数据只有categoryIds时补默认绑定,便于编辑回显
|
||||
func EffectiveCategoryBinds(item *Playlet) []PlayletCategoryBind {
|
||||
if item == nil {
|
||||
return make([]PlayletCategoryBind, 0)
|
||||
}
|
||||
if len(item.CategoryBinds) > 0 {
|
||||
return item.CategoryBinds
|
||||
}
|
||||
return CategoryBindsFromIds(item.CategoryIds)
|
||||
}
|
||||
|
||||
// CategoryRankAddFields 聚合取出当前分类的排序字段,供分类列表排序
|
||||
func CategoryRankAddFields(categoryId int64) bson.M {
|
||||
return bson.M{
|
||||
categoryRankField: bson.M{
|
||||
"$let": bson.M{
|
||||
"vars": bson.M{
|
||||
"hit": bson.M{
|
||||
"$first": bson.M{
|
||||
"$filter": bson.M{
|
||||
"input": bson.M{"$ifNull": bson.A{"$categoryBinds", bson.A{}}},
|
||||
"as": "b",
|
||||
"cond": bson.M{"$eq": bson.A{"$$b.id", categoryId}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"in": bson.M{"$ifNull": bson.A{"$$hit.rank", 0}},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// CategoryRankSort 分类短剧排序:当前分类rank降序,再按上架时间和ID
|
||||
func CategoryRankSort() bson.D {
|
||||
return bson.D{
|
||||
{Key: categoryRankField, Value: -1},
|
||||
{Key: "onlineAt", Value: -1},
|
||||
{Key: "_id", Value: -1},
|
||||
}
|
||||
}
|
||||
|
||||
// CategoryRankAdminSort 后台按分类查询时的排序:当前分类rank降序
|
||||
func CategoryRankAdminSort() bson.D {
|
||||
return bson.D{
|
||||
{Key: categoryRankField, Value: -1},
|
||||
{Key: "_id", Value: -1},
|
||||
}
|
||||
}
|
||||
|
||||
// FindManyPlayletByCategoryRank 按指定分类的排序分页查询短剧
|
||||
func FindManyPlayletByCategoryRank(ctx context.Context, filter bson.M, categoryId, skip, limit int64, sort bson.D, projection bson.D) (PlayletList, *srvdef.SrvErr) {
|
||||
pipeline := []bson.M{
|
||||
{"$match": filter},
|
||||
{"$addFields": CategoryRankAddFields(categoryId)},
|
||||
{"$sort": sort},
|
||||
{"$skip": skip},
|
||||
{"$limit": limit},
|
||||
{"$unset": categoryRankField},
|
||||
}
|
||||
if len(projection) > 0 {
|
||||
project := bson.M{}
|
||||
for _, field := range projection {
|
||||
project[field.Key] = field.Value
|
||||
}
|
||||
pipeline = append(pipeline, bson.M{"$project": project})
|
||||
}
|
||||
list := make(PlayletList, 0)
|
||||
if err := AggregatePlaylet(ctx, &list, pipeline); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
package playletmod
|
||||
|
||||
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/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var coll *mongos.Collection
|
||||
|
||||
// Init 初始化 playlet 集合和常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.Playlet)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.ThemeIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.ThemeIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CountCollect, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.ThemeIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.UpdatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.ThemeIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.IsRecommend, Value: 1},
|
||||
{Key: FN.Playlet.RecommendRank, Value: -1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.ThemeIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CountBrowse, Value: -1},
|
||||
{Key: FN.Playlet.UpdatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.CategoryIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.TagIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.UpdatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.TagIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.IsRecommend, Value: 1},
|
||||
{Key: FN.Playlet.RecommendRank, Value: -1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.TagIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CountBrowse, Value: -1},
|
||||
{Key: FN.Playlet.UpdatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.CategoryIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.RecommendRank, Value: -1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.CategoryIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.IsRecommend, Value: 1},
|
||||
{Key: FN.Playlet.RecommendRank, Value: -1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.CategoryIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.UpdatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.CategoryIds, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CountBrowse, Value: -1},
|
||||
{Key: FN.Playlet.UpdatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.IsFeatured, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.ShowOnBanner, Value: 1},
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.TopRank, Value: -1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.IsRecommend, Value: 1},
|
||||
{Key: FN.Playlet.RecommendRank, Value: -1},
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.CreatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CountCollect, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.CountBrowse, Value: -1},
|
||||
{Key: FN.Playlet.UpdatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.HeatValue, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.OnlineAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.Status, Value: 1},
|
||||
{Key: FN.Playlet.UpdatedAt, Value: -1},
|
||||
{Key: FN.Playlet.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Playlet.MediaCenterId, Value: 1},
|
||||
},
|
||||
Options: options.Index().
|
||||
SetUnique(true).
|
||||
SetPartialFilterExpression(bson.M{
|
||||
FN.Playlet.MediaCenterId: bson.M{"$gt": 0},
|
||||
}),
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(playletmod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOnePlaylet 插入一条短剧数据
|
||||
func InsertOnePlaylet(ctx context.Context, doc *Playlet) *srvdef.SrvErr {
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.Playlet.Get()
|
||||
}
|
||||
now := time.Now()
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
doc.UpdatedAt = now
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("playletmod:InsertOnePlaylet failed", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOnePlaylet 删除一条短剧数据
|
||||
func DelOnePlaylet(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletmod:DelOnePlaylet failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOnePlaylet 查询一条短剧数据
|
||||
func FindOnePlaylet(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*Playlet, *srvdef.SrvErr) {
|
||||
var doc Playlet
|
||||
if err := coll.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("playletmod:FindOnePlaylet failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyPlaylet 按条件查询多条短剧数据
|
||||
func FindManyPlaylet(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletList, *srvdef.SrvErr) {
|
||||
data := make(PlayletList, 0)
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("playletmod:FindManyPlaylet failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountPlaylet 统计满足条件的短剧数量
|
||||
func CountPlaylet(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter, opts...)
|
||||
if err != nil {
|
||||
log.Warn("playletmod:CountPlaylet failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// AggregatePlaylet 聚合查询短剧数据
|
||||
func AggregatePlaylet(ctx context.Context, bind interface{}, pipeline []bson.M, opts ...*options.AggregateOptions) *srvdef.SrvErr {
|
||||
if err := coll.Aggregate(ctx, bind, pipeline, opts...); err != nil {
|
||||
log.Warn("playletmod:AggregatePlaylet failed", log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateOnePlaylet 更新一条短剧数据
|
||||
func UpdateOnePlaylet(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("playletmod:UpdateOnePlaylet failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindOneAndUpdatePlaylet 更新一条短剧数据并返回更新后的数据
|
||||
func FindOneAndUpdatePlaylet(ctx context.Context, filter bson.M, update bson.M, opts ...*options.FindOneAndUpdateOptions) (*Playlet, *srvdef.SrvErr) {
|
||||
var doc Playlet
|
||||
if err := coll.FindOneAndUpdate(ctx, &doc, filter, update, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("更新并查询短剧数据失败", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// UpdateManyPlaylet 批量更新短剧数据
|
||||
func UpdateManyPlaylet(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("批量更新短剧数据失败", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount == 0 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BulkWritePlaylet 批量写入短剧更新操作。
|
||||
func BulkWritePlaylet(ctx context.Context, docs []mongo.WriteModel, opts ...*options.BulkWriteOptions) *srvdef.SrvErr {
|
||||
if len(docs) == 0 {
|
||||
return nil
|
||||
}
|
||||
result, err := coll.BulkWrite(ctx, docs, opts...)
|
||||
if err != nil {
|
||||
log.Warn("批量写入短剧数据失败", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount == 0 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package playletmod
|
||||
|
||||
// TagPlaylet 保存 playlet 集合字段名
|
||||
type TagPlaylet struct {
|
||||
Id string
|
||||
MediaCenterId string
|
||||
MediaCreatedAt string
|
||||
MediaUpdatedAt string
|
||||
MediaSyncTime string
|
||||
Status string
|
||||
IsFeatured string
|
||||
IsOriginal string
|
||||
ShowOriginal string
|
||||
MediaBusiness string
|
||||
IsRecommend string
|
||||
ShowOnBanner string
|
||||
Banner string
|
||||
ReviewAt string
|
||||
OnlineAt string
|
||||
CategoryIds string
|
||||
CategoryBinds string
|
||||
ThemeIds string
|
||||
Title string
|
||||
Slug string
|
||||
Desc string
|
||||
Anchor string
|
||||
Cover string
|
||||
CompressedCover string
|
||||
Preview string
|
||||
TagIds string
|
||||
OldTags string
|
||||
ContentType string
|
||||
PayType string
|
||||
SingleCoins string
|
||||
TotalEpisode string
|
||||
FreeEpisodeCount string
|
||||
UpdateStatus string
|
||||
TopRank string
|
||||
RecommendRank string
|
||||
CountComment string
|
||||
CountBuy string
|
||||
CountBrowse string
|
||||
VirtualCountBrowse string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
YearWatchs string
|
||||
WatchUpdatedAt string
|
||||
HeatValue string
|
||||
VirtualHeatValue string
|
||||
CountCollect string
|
||||
CountLike string
|
||||
VirtualCountLike string
|
||||
CountDisLike string
|
||||
SeoInfo struct {
|
||||
Description string
|
||||
Keyworld string
|
||||
Title string
|
||||
}
|
||||
IndexNow string
|
||||
OperatorId string
|
||||
OperatorName string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
Playlet TagPlaylet
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
Playlet string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.Playlet.Id = "_id"
|
||||
FN.Playlet.MediaCenterId = "mediaCenterId"
|
||||
FN.Playlet.MediaCreatedAt = "mediaCreatedAt"
|
||||
FN.Playlet.MediaUpdatedAt = "mediaUpdatedAt"
|
||||
FN.Playlet.MediaSyncTime = "mediaSyncTime"
|
||||
FN.Playlet.Status = "status"
|
||||
FN.Playlet.IsFeatured = "isFeatured"
|
||||
FN.Playlet.IsOriginal = "isOriginal"
|
||||
FN.Playlet.ShowOriginal = "showOriginal"
|
||||
FN.Playlet.MediaBusiness = "mediaBusiness"
|
||||
FN.Playlet.IsRecommend = "isRecommend"
|
||||
FN.Playlet.ShowOnBanner = "showOnBanner"
|
||||
FN.Playlet.Banner = "banner"
|
||||
FN.Playlet.ReviewAt = "reviewAt"
|
||||
FN.Playlet.OnlineAt = "onlineAt"
|
||||
FN.Playlet.CategoryIds = "categoryIds"
|
||||
FN.Playlet.CategoryBinds = "categoryBinds"
|
||||
FN.Playlet.ThemeIds = "themeIds"
|
||||
FN.Playlet.Title = "title"
|
||||
FN.Playlet.Slug = "slug"
|
||||
FN.Playlet.Desc = "desc"
|
||||
FN.Playlet.Anchor = "anchor"
|
||||
FN.Playlet.Cover = "cover"
|
||||
FN.Playlet.CompressedCover = "compressedCover"
|
||||
FN.Playlet.Preview = "preview"
|
||||
FN.Playlet.TagIds = "tagIds"
|
||||
FN.Playlet.OldTags = "oldTags"
|
||||
FN.Playlet.ContentType = "contentType"
|
||||
FN.Playlet.PayType = "payType"
|
||||
FN.Playlet.SingleCoins = "singleCoins"
|
||||
FN.Playlet.TotalEpisode = "totalEpisode"
|
||||
FN.Playlet.FreeEpisodeCount = "freeEpisodeCount"
|
||||
FN.Playlet.UpdateStatus = "updateStatus"
|
||||
FN.Playlet.TopRank = "topRank"
|
||||
FN.Playlet.RecommendRank = "recommendRank"
|
||||
FN.Playlet.CountComment = "countComment"
|
||||
FN.Playlet.CountBuy = "countBuy"
|
||||
FN.Playlet.CountBrowse = "countBrowse"
|
||||
FN.Playlet.VirtualCountBrowse = "virtualCountBrowse"
|
||||
FN.Playlet.WeekWatchs = "weekWatchs"
|
||||
FN.Playlet.MonthWatchs = "monthWatchs"
|
||||
FN.Playlet.YearWatchs = "yearWatchs"
|
||||
FN.Playlet.WatchUpdatedAt = "watchUpdatedAt"
|
||||
FN.Playlet.HeatValue = "heatValue"
|
||||
FN.Playlet.VirtualHeatValue = "virtualHeatValue"
|
||||
FN.Playlet.CountCollect = "countCollect"
|
||||
FN.Playlet.CountLike = "countLike"
|
||||
FN.Playlet.VirtualCountLike = "virtualCountLike"
|
||||
FN.Playlet.CountDisLike = "countDisLike"
|
||||
FN.Playlet.SeoInfo.Description = "seoInfo.webDescription"
|
||||
FN.Playlet.SeoInfo.Keyworld = "seoInfo.webKeyworld"
|
||||
FN.Playlet.SeoInfo.Title = "seoInfo.webTitle"
|
||||
FN.Playlet.IndexNow = "indexNow"
|
||||
FN.Playlet.OperatorId = "operatorId"
|
||||
FN.Playlet.OperatorName = "operatorName"
|
||||
FN.Playlet.CreatedAt = "createdAt"
|
||||
FN.Playlet.UpdatedAt = "updatedAt"
|
||||
|
||||
TN.Playlet = "playlet"
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package playletmod
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
// ContentType 内容类型(与媒资 media_type 对应)
|
||||
type ContentType int32
|
||||
|
||||
const (
|
||||
ContentTypeTheater ContentType = 0 // 短剧(对应 media_type=5)
|
||||
ContentTypeAlbum ContentType = 1 // 普通短剧/影集(对应 media_type=6)
|
||||
ContentTypeComic ContentType = 2 // 漫画短剧(对应 media_type=4)
|
||||
ContentTypeAnime ContentType = 3 // 动漫(对应 media_type=1)
|
||||
ContentTypeManga ContentType = 4 // 漫画(对应 media_type=2)
|
||||
)
|
||||
|
||||
// Status 上架状态
|
||||
type Status int32
|
||||
|
||||
const (
|
||||
StatusDown Status = 0 // 下架
|
||||
StatusUp Status = 1 // 上架
|
||||
)
|
||||
|
||||
// PayType 支付方式(剧级默认,连载上架后新增剧集沿用)
|
||||
type PayType int32
|
||||
|
||||
const (
|
||||
PayTypeFree PayType = 0 // 免费
|
||||
PayTypeCoin PayType = 1 // 金币
|
||||
PayTypeVip PayType = 2 // VIP
|
||||
)
|
||||
|
||||
// Playlet @table: playlet
|
||||
//
|
||||
// Playlet 连载短剧集合模型
|
||||
type Playlet struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
MediaCenterId uint `json:"mediaCenterId" bson:"mediaCenterId"` // 媒资中心资源ID
|
||||
MediaCreatedAt time.Time `json:"mediaCreatedAt" bson:"mediaCreatedAt"` // 媒资中心创建时间
|
||||
MediaUpdatedAt time.Time `json:"mediaUpdatedAt" bson:"mediaUpdatedAt"` // 媒资中心更新时间
|
||||
MediaSyncTime int64 `json:"mediaSyncTime" bson:"mediaSyncTime"` // 媒资中心增量同步时间点
|
||||
Status Status `json:"status" bson:"status"` // 状态: 0下架 1上架
|
||||
IsFeatured bool `json:"isFeatured" bson:"isFeatured"` // 是否爆剧(true-是,false-否)
|
||||
IsOriginal bool `json:"isOriginal" bson:"isOriginal"` // 是否原创:后台新增为true,媒资导入为false
|
||||
ShowOriginal bool `json:"showOriginal" bson:"showOriginal"` // 页面是否展示原创标识
|
||||
MediaBusiness string `json:"mediaBusiness" bson:"mediaBusiness"` // 媒资业务来源,按媒资标题前缀记录,如 CGDJ;空表示未标记
|
||||
IsRecommend bool `json:"isRecommend" bson:"isRecommend"` // 是否推荐 true-推荐,false-不推荐
|
||||
ShowOnBanner bool `json:"showOnBanner" bson:"showOnBanner"` // 是否显示在首页banner
|
||||
Banner string `json:"banner" bson:"banner"` // banner图
|
||||
ReviewAt time.Time `json:"reviewAt" bson:"reviewAt"` // 审核时间
|
||||
OnlineAt time.Time `json:"onlineAt" bson:"onlineAt"` // 上架时间
|
||||
CategoryIds []int64 `json:"categoryIds" bson:"categoryIds"` // 分类ID集合
|
||||
CategoryBinds []PlayletCategoryBind `json:"categoryBinds" bson:"categoryBinds"` // 各分类下的排序
|
||||
ThemeIds []int64 `json:"themeIds" bson:"themeIds"` // 题材ID集合
|
||||
Title string `json:"title" bson:"title"` // 标题
|
||||
Slug string `json:"slug" bson:"slug"` // slug
|
||||
Desc string `json:"desc" bson:"desc"` // 简介
|
||||
Anchor string `json:"anchor" bson:"anchor"` // 作者/演员
|
||||
Cover string `json:"cover" bson:"cover"` // 封面原图
|
||||
CompressedCover string `json:"compressedCover" bson:"compressedCover"` // 压缩封面,压缩成功才有值
|
||||
Preview string `json:"preview" bson:"preview"` // 预告
|
||||
TagIds []int64 `json:"tagIds" bson:"tagIds"` // 标签ID
|
||||
OldTags []string `json:"oldTags" bson:"oldTags"` // 媒资库原标签名称
|
||||
ContentType ContentType `json:"contentType" bson:"contentType"` // 内容类型: 0短剧 1普通短剧/影集 2漫画短剧 3动漫 4漫画
|
||||
PayType PayType `json:"payType" bson:"payType"` // 支付方式 0-免费 1-金币 2-VIP
|
||||
SingleCoins int64 `json:"singleCoins" bson:"singleCoins"` // 单集金币(支付方式为1-金币时候生效)
|
||||
TotalEpisode int64 `json:"totalEpisode" bson:"totalEpisode"` // 总集数
|
||||
FreeEpisodeCount int64 `json:"freeEpisodeCount" bson:"freeEpisodeCount"` // 官网开放集数 1至1000表示开放第1集到第N集 -1表示开放全集 0或字段缺失按2集
|
||||
UpdateStatus int `json:"updateStatus" bson:"updateStatus"` // 更新状态 1-连载中 2-已完结
|
||||
TopRank int64 `json:"topRank" bson:"topRank"` // 置顶排名
|
||||
RecommendRank int64 `json:"recommendRank" bson:"recommendRank"` // 推荐排序
|
||||
CountComment int64 `json:"countComment" bson:"countComment"` // 评论数
|
||||
CountBuy int64 `json:"countBuy" bson:"countBuy"` // 购买数
|
||||
CountBrowse int64 `json:"countBrowse" bson:"countBrowse"` // 浏览数
|
||||
VirtualCountBrowse int64 `json:"virtualCountBrowse" bson:"virtualCountBrowse"` // 后台虚拟观看数
|
||||
WeekWatchs int64 `json:"weekWatchs" bson:"weekWatchs"` // 本周观看次数(北京时间)
|
||||
MonthWatchs int64 `json:"monthWatchs" bson:"monthWatchs"` // 本月观看次数(北京时间)
|
||||
YearWatchs int64 `json:"yearWatchs" bson:"yearWatchs"` // 本年观看次数(北京时间)
|
||||
WatchUpdatedAt time.Time `json:"watchUpdatedAt" bson:"watchUpdatedAt"` // 最近一次观看计数时间
|
||||
HeatValue int64 `json:"heatValue" bson:"heatValue"` // 热度值
|
||||
VirtualHeatValue int64 `json:"virtualHeatValue" bson:"virtualHeatValue"` // 后台虚拟热度值
|
||||
CountCollect int64 `json:"countCollect" bson:"countCollect"` // 收藏数
|
||||
CountLike int64 `json:"countLike" bson:"countLike"` // 喜欢数
|
||||
VirtualCountLike int64 `json:"virtualCountLike" bson:"virtualCountLike"` // 虚拟喜欢数,后台配置
|
||||
CountDisLike int64 `json:"countDisLike" bson:"countDisLike"` // 不喜欢数
|
||||
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
|
||||
IndexNow int64 `json:"indexNow" bson:"indexNow"` // 搜索引擎推送标记 0:待提交 1:已入队/已提交
|
||||
OperatorId int64 `json:"operatorId" bson:"operatorId"` // 最后操作人ID(后台账号)
|
||||
OperatorName string `json:"operatorName" bson:"operatorName"` // 最后操作人名称
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
}
|
||||
|
||||
// EffectiveFreeEpisodeCount 历史短剧未配置时官网默认开放前2集
|
||||
func (p *Playlet) EffectiveFreeEpisodeCount() int64 {
|
||||
if p == nil || p.FreeEpisodeCount == 0 {
|
||||
return 2
|
||||
}
|
||||
return p.FreeEpisodeCount
|
||||
}
|
||||
|
||||
// IsOfficialEpisodeOpen 判断剧集是否在官网开放范围内
|
||||
func (p *Playlet) IsOfficialEpisodeOpen(episode int64) bool {
|
||||
if p == nil || p.Status != StatusUp || episode <= 0 {
|
||||
return false
|
||||
}
|
||||
count := p.EffectiveFreeEpisodeCount()
|
||||
return count == -1 || episode <= count
|
||||
}
|
||||
|
||||
// PlayletList 短剧列表
|
||||
type PlayletList []*Playlet
|
||||
|
||||
// DisplayCountBrowse 返回真实观看数与虚拟观看数之和
|
||||
func (p *Playlet) DisplayCountBrowse() int64 {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return p.CountBrowse + p.VirtualCountBrowse
|
||||
}
|
||||
|
||||
// DisplayHeatValue 返回原热度与虚拟热度之和
|
||||
func (p *Playlet) DisplayHeatValue() int64 {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return p.HeatValue + p.VirtualHeatValue
|
||||
}
|
||||
|
||||
// DisplayCover App 展示用封面:压缩图有值则优先,否则回退原图
|
||||
func (p *Playlet) DisplayCover() string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
if cover := strings.TrimSpace(p.CompressedCover); cover != "" {
|
||||
return cover
|
||||
}
|
||||
return strings.TrimSpace(p.Cover)
|
||||
}
|
||||
Reference in New Issue
Block a user