Initial commit: web_hghl_server
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
package actress
|
||||
|
||||
import (
|
||||
"context"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"fmt"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// 表名
|
||||
var db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
// 获取数据库表
|
||||
db = mongos.Shop.Coll(TN.Actress)
|
||||
// 获取数据库表
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Alias, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.Alias, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.Rank, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.UpdatedAt, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.Works, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.Works, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.HotValue, Value: -1},
|
||||
{Key: FN.Actress.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.Real.WeekWatchs, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.Real.MonthWatchs, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Actress.Status, Value: 1},
|
||||
{Key: FN.Actress.Real.WatchTimes, Value: 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(channelmod:initActressIndex) Create Actress Index failed! err:%+v:", err))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// InsertOneActress 插入一个导航分类
|
||||
func InsertOneActress(ctx context.Context, qa *Actress) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, qa); err != nil {
|
||||
log.Warn("Actressmod:InsertOneActress db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneActress 删除一个导航分类
|
||||
func DelOneActress(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("Actressmod:DelOneActress db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneActress 查找一个导航分类
|
||||
func FindOneActress(ctx context.Context, filter bson.M) (
|
||||
*Actress, *srvdef.SrvErr) {
|
||||
var Actress Actress
|
||||
if err := db.FindOneEx(ctx, &Actress, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("Actressmod:FindOneActress db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &Actress, nil
|
||||
}
|
||||
|
||||
func FindManyActresss(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (ActressList, *srvdef.SrvErr) {
|
||||
data := make(ActressList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); nil != err {
|
||||
log.Warn("faq:FindManyActresss", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQuery.Code, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountActresss 统计导航分类数量
|
||||
func CountActresss(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("faqmod:CountActresss db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneActress 更新一个导航分类
|
||||
func UpdateOneActress(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("post:UpdateOneActress db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("post:UpdateOneActress db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func UpdateManyActress(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
_, err := db.UpdateMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("post:UpdateManyActress db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package actress
|
||||
|
||||
type TagActress struct {
|
||||
Meas struct {
|
||||
Gender string // Type: int , Desc: 性别 0:女 1:男 2:其他
|
||||
Height string // Type: int , Desc: 身高 厘米
|
||||
Weight string // Type: int , Desc: 体重 公斤
|
||||
Bust string // Type: int , Desc: 胸围 英寸
|
||||
Waist string // Type: int , Desc: 腰围 英寸
|
||||
Hip string // Type: int , Desc: 臀围 英寸
|
||||
Cup string // Type: int , Desc: 罩杯(A:1-G:9)1表示A,2表示B,3表示C,4表示D,5表示E,6表示F,7表示G,8表示H,9表示I
|
||||
Len string // Type: int , Desc: 长度 毫米(前端可以显示为厘米,如45毫米,显示为14.5厘米,返回后端时,乘以10,保留整数,返回145)
|
||||
Dia string // Type: int , Desc: 直径 毫米(前端可以显示为厘米,如45毫米,显示为4.5厘米,返回后端时,乘以10,保留整数,返回45)
|
||||
Blood string // Type: string , Desc: 血型
|
||||
}
|
||||
Id string
|
||||
Alias string
|
||||
Slug string
|
||||
Avatar string
|
||||
Cover string
|
||||
Desc string
|
||||
TranslationCategoryId string
|
||||
Office string
|
||||
DebutDate string
|
||||
BornDate string
|
||||
Region string
|
||||
Score string
|
||||
Rank string
|
||||
HotValue string
|
||||
Status string
|
||||
Works string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
RealUpdateAt string
|
||||
SeoInfo string
|
||||
IndexNow string
|
||||
Real struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
Likes string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
Actress TagActress
|
||||
}
|
||||
var TN struct {
|
||||
Actress string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.Actress.Id = "_id"
|
||||
FN.Actress.UpdatedAt = "updatedAt"
|
||||
FN.Actress.Works = "works"
|
||||
FN.Actress.Status = "status"
|
||||
FN.Actress.Rank = "rank"
|
||||
FN.Actress.HotValue = "hotValue"
|
||||
FN.Actress.Score = "score"
|
||||
FN.Actress.Region = "region"
|
||||
FN.Actress.BornDate = "bornDate"
|
||||
FN.Actress.DebutDate = "debutDate"
|
||||
FN.Actress.Office = "office"
|
||||
FN.Actress.Meas.Gender = "meas.gender"
|
||||
FN.Actress.Meas.Height = "meas.height"
|
||||
FN.Actress.Meas.Weight = "meas.weight"
|
||||
FN.Actress.Meas.Bust = "meas.bust"
|
||||
FN.Actress.Meas.Waist = "meas.waist"
|
||||
FN.Actress.Meas.Hip = "meas.hip"
|
||||
FN.Actress.Meas.Cup = "meas.cup"
|
||||
FN.Actress.Meas.Len = "meas.len"
|
||||
FN.Actress.Meas.Dia = "meas.dia"
|
||||
FN.Actress.Meas.Blood = "meas.blood"
|
||||
FN.Actress.Desc = "desc"
|
||||
FN.Actress.Cover = "cover"
|
||||
FN.Actress.Avatar = "avatar"
|
||||
FN.Actress.Alias = "alias"
|
||||
FN.Actress.Slug = "slug"
|
||||
FN.Actress.CreatedAt = "createdAt"
|
||||
FN.Actress.UpdatedAt = "updatedAt"
|
||||
FN.Actress.TranslationCategoryId = "translationCategoryId"
|
||||
FN.Actress.Real.WatchTimes = "watchTimes"
|
||||
FN.Actress.Real.ShowTimes = "showTimes"
|
||||
FN.Actress.Real.Comments = "comments"
|
||||
FN.Actress.Real.Likes = "likes"
|
||||
FN.Actress.Real.WeekWatchs = "weekWatchs"
|
||||
FN.Actress.Real.MonthWatchs = "monthWatchs"
|
||||
FN.Actress.Real.TodayWatchs = "todayWatchs"
|
||||
FN.Actress.SeoInfo = "seoInfo"
|
||||
FN.Actress.IndexNow = "indexNow"
|
||||
FN.Actress.RealUpdateAt = "realUpdateAt"
|
||||
TN.Actress = "actress"
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// @title:女优管理
|
||||
package actress
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
type Meas struct {
|
||||
Gender int `bson:"gender" json:"gender"` // 性别 0:女 1:男 2:其他
|
||||
Height int `bson:"height" json:"height"` // 身高 厘米
|
||||
Weight int `bson:"weight" json:"weight"` // 体重 公斤
|
||||
Bust int `bson:"bust" json:"bust"` // 胸围 英寸
|
||||
Waist int `bson:"waist" json:"waist"` // 腰围 英寸
|
||||
Hip int `bson:"hip" json:"hip"` // 臀围 英寸
|
||||
Cup int `bson:"cup" json:"cup"` // 罩杯(A:1-G:9)1表示A,2表示B,3表示C,4表示D,5表示E,6表示F,7表示G,8表示H,9表示I
|
||||
Len int `bson:"len" json:"len"` // 长度 毫米(前端可以显示为厘米,如145毫米,显示为14.5厘米,返回后端时,乘以10,保留整数,返回145)
|
||||
Dia int `bson:"dia" json:"dia"` // 直径 毫米(前端可以显示为厘米,如45毫米,显示为4.5厘米,返回后端时,乘以10,保留整数,返回45)
|
||||
Blood string `json:"blood" bson:"blood"` // 血型
|
||||
}
|
||||
|
||||
func calculateCup(bust int, waist int) int {
|
||||
// 计算胸围和腰围的差值
|
||||
difference := bust - waist
|
||||
// 根据差值大致判断罩杯
|
||||
switch {
|
||||
case difference < 5:
|
||||
return 1 // A杯
|
||||
case difference < 7:
|
||||
return 2 // B杯
|
||||
case difference < 9:
|
||||
return 3 // C杯
|
||||
case difference < 11:
|
||||
return 4 // D杯
|
||||
case difference < 13:
|
||||
return 5 // E杯
|
||||
case difference < 15:
|
||||
return 6 // F杯
|
||||
case difference < 17:
|
||||
return 7 // G杯
|
||||
case difference < 19:
|
||||
return 8 // H杯
|
||||
case difference < 21:
|
||||
return 9 // I杯
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Meas) Parse(text string) {
|
||||
text = strings.ReplaceAll(text, "长度", "尺寸")
|
||||
text = strings.ReplaceAll(text, "長度", "尺寸")
|
||||
text = strings.ReplaceAll(text, "厘米", "cm")
|
||||
text = strings.ReplaceAll(text, "公分", "cm")
|
||||
text = strings.ReplaceAll(text, "公斤", "kg")
|
||||
text = strings.ReplaceAll(text, "體", "体")
|
||||
text = strings.ReplaceAll(text, "圍", "围")
|
||||
text = strings.ReplaceAll(text, "徑", "径")
|
||||
// 将字母转换为对应的数字
|
||||
cupMap := map[string]int{
|
||||
"A": 1, "B": 2, "C": 3, "D": 4,
|
||||
"E": 5, "F": 6, "G": 7, "H": 8, "I": 9,
|
||||
"a": 1, "b": 2, "c": 3, "d": 4,
|
||||
"e": 5, "f": 6, "g": 7, "h": 8, "i": 9,
|
||||
}
|
||||
// 身高提取cm
|
||||
heightReg := regexp.MustCompile(`(?i)身高\s*(\d+)cm`)
|
||||
if matches := heightReg.FindStringSubmatch(text); len(matches) > 1 {
|
||||
m.Height, _ = strconv.Atoi(matches[1])
|
||||
}
|
||||
// 体重提取kg
|
||||
weightReg := regexp.MustCompile(`(?i)体重\s*(\d+)kg`)
|
||||
if matches := weightReg.FindStringSubmatch(text); len(matches) > 1 {
|
||||
m.Weight, _ = strconv.Atoi(matches[1])
|
||||
}
|
||||
// 体重提取斤
|
||||
weightReg = regexp.MustCompile(`(?i)体重\s*(\d+)斤`)
|
||||
if matches := weightReg.FindStringSubmatch(text); len(matches) > 1 {
|
||||
m.Weight, _ = strconv.Atoi(matches[1])
|
||||
m.Weight = m.Weight / 2
|
||||
}
|
||||
// 胸围提取
|
||||
bustReg := regexp.MustCompile(`胸围\s*(\d+)`)
|
||||
if matches := bustReg.FindStringSubmatch(text); len(matches) > 1 {
|
||||
m.Bust, _ = strconv.Atoi(matches[1])
|
||||
}
|
||||
// 三围单个数值提取
|
||||
bustReg = regexp.MustCompile(`三围\s*(\d+)`)
|
||||
if matches := bustReg.FindStringSubmatch(text); len(matches) > 1 {
|
||||
m.Bust, _ = strconv.Atoi(matches[1])
|
||||
}
|
||||
// 罩杯提取
|
||||
cupReg := regexp.MustCompile(`(?i)(\d+)([A-Z])`)
|
||||
if matches := cupReg.FindStringSubmatch(text); len(matches) > 2 {
|
||||
m.Cup = cupMap[matches[2]]
|
||||
}
|
||||
// 长度提取cm,支持浮点数
|
||||
lengthReg := regexp.MustCompile(`(?i)尺寸\s*(\d+\.?\d*)cm`)
|
||||
if matches := lengthReg.FindStringSubmatch(text); len(matches) > 1 {
|
||||
value, _ := strconv.ParseFloat(matches[1], 64)
|
||||
m.Len = int(value * 10) // 转换为mm
|
||||
}
|
||||
// 直径提取cm,支持浮点数
|
||||
diaReg := regexp.MustCompile(`(?i)直径\s*(\d+\.?\d*)cm`)
|
||||
if matches := diaReg.FindStringSubmatch(text); len(matches) > 1 {
|
||||
value, _ := strconv.ParseFloat(matches[1], 64)
|
||||
m.Len = int(value * 10) // 转换为mm
|
||||
}
|
||||
// 提取三围和罩杯
|
||||
threeSizeReg := regexp.MustCompile(`(?i)三围\s*(\d+)([A-Z])/(\d+)/(\d+)`)
|
||||
if matches := threeSizeReg.FindStringSubmatch(text); len(matches) > 1 {
|
||||
m.Bust, _ = strconv.Atoi(matches[1])
|
||||
m.Cup = cupMap[matches[2]]
|
||||
m.Waist, _ = strconv.Atoi(matches[3])
|
||||
m.Hip, _ = strconv.Atoi(matches[4])
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Meas) convertCupToString(cup int) string {
|
||||
if cup <= 0 {
|
||||
cup = calculateCup(m.Bust, m.Waist)
|
||||
}
|
||||
if cup >= 1 && cup <= 9 {
|
||||
letter := rune('A' + cup - 1)
|
||||
return string(letter)
|
||||
} else {
|
||||
if m.Gender == 1 {
|
||||
return "" // 男性默认返回空字符串
|
||||
}
|
||||
return "B" // 非男性默认返回B杯
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Meas) Measurements() string {
|
||||
//三围 格式为 35D-24-34 // 胸围(罩杯)-腰围-臀围
|
||||
return fmt.Sprintf("%d%s-%d-%d", m.Bust, m.convertCupToString(m.Cup), m.Waist, m.Hip)
|
||||
}
|
||||
|
||||
// @title:女优
|
||||
// @table:actress
|
||||
type Actress struct {
|
||||
Id int64 `json:"id" bson:"_id"` // Id
|
||||
Alias string `bson:"alias" json:"alias"` // 别名
|
||||
Slug string `json:"slug" bson:"slug"` // slug
|
||||
Avatar string `bson:"avatar" json:"avatar"` // 头像
|
||||
Cover string `bson:"cover" json:"cover"` // 封面大图
|
||||
Desc string `bson:"desc" json:"desc"` // 详细描述
|
||||
TranslationCategoryId int64 `bson:"translationCategoryId" json:"translationCategoryId"` // 关联导航分类id
|
||||
Meas Meas `bson:"meas" json:"meas"` // 三围
|
||||
Office string `json:"office" bson:"office"` // 事务所
|
||||
DebutDate time.Time `bson:"debutDate" json:"debutDate" ` // 出道日期
|
||||
BornDate time.Time `bson:"bornDate" json:"bornDate"` // 出生日期
|
||||
Region string `json:"region" bson:"region"` // 地区/国家
|
||||
Score string `json:"score" bson:"score"` // 评分
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序
|
||||
HotValue int64 `json:"hotValue" bson:"hotValue"` // 热度值
|
||||
Status bool `json:"status" bson:"status"` // 是否启用
|
||||
Works int64 `json:"works" bson:"works"` // 作品数
|
||||
Real pubdef.Flow `json:"real" bson:"real"` // 真实流量
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
RealUpdateAt time.Time `json:"realUpdateAt" bson:"realUpdateAt"` // 播放相关数据更新时间
|
||||
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
|
||||
IndexNow int64 `json:"indexNow" bson:"indexNow"` // 是否需要提交 0:代表提交 1:表示已提交 运营通过接口可以修改
|
||||
|
||||
}
|
||||
|
||||
type ActressList []*Actress
|
||||
@@ -0,0 +1,182 @@
|
||||
package analyticsdailystat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
// 获取数据库表
|
||||
db = mongos.Shop.Coll(TN.AnalyticsDailyInfo)
|
||||
// 获取数据库表
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.AnalyticsDailyInfo.AppId, Value: 1},
|
||||
{Key: FN.AnalyticsDailyInfo.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.AnalyticsDailyInfo.SumDate, Value: 1},
|
||||
{Key: FN.AnalyticsDailyInfo.AppId, Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.AnalyticsDailyInfo.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(AnalyticsDailyInfo:initAnalyticsDailyInfoIndex) Create AnalyticsDailyInfo Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOneAnalyticsDailyInfo 插入一个评论
|
||||
func InsertOneAnalyticsDailyInfo(ctx context.Context, AnalyticsDailyInfo *AnalyticsDailyInfo) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, AnalyticsDailyInfo); err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:InsertOneAnalyticsDailyInfo db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneAnalyticsDailyInfo 删除一个评论
|
||||
func DelOneAnalyticsDailyInfo(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:DelOneAnalyticsDailyInfo db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// DelManyAnalyticsDailyInfo 删除一个评论评论
|
||||
func DelManyAnalyticsDailyInfo(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteMany(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:DelOneAnalyticsDailyInfo db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneAnalyticsDailyInfo 查找一个评论
|
||||
func FindOneAnalyticsDailyInfo(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (
|
||||
*AnalyticsDailyInfo, *srvdef.SrvErr) {
|
||||
var AnalyticsDailyInfo AnalyticsDailyInfo
|
||||
if err := db.FindOneEx(
|
||||
ctx, &AnalyticsDailyInfo, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Info("AnalyticsDailyInfo:FindOneAnalyticsDailyInfo db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &AnalyticsDailyInfo, nil
|
||||
}
|
||||
|
||||
// CountAnalyticsDailyInfos 统计评论视频评论数量
|
||||
func CountAnalyticsDailyInfos(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:CountAnalyticsDailyInfos db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneAnalyticsDailyInfo 更新一个评论
|
||||
func UpdateOneAnalyticsDailyInfo(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:UpdateOneAnalyticsDailyInfo db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("AnalyticsDailyInfo:UpdateOneAnalyticsDailyInfo db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateManyAnalyticsDailyInfo 更新一批评论
|
||||
func UpdateManyAnalyticsDailyInfo(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateMMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:UpdateManyAnalyticsDailyInfo db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount <= 0 {
|
||||
log.Warn("AnalyticsDailyInfo:UpdateManyAnalyticsDailyInfo db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
//return srvdef.New(srvdef.ErrAnalyticsDailyInfoNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyAnalyticsDailyInfo 查找一批评论
|
||||
func FindManyAnalyticsDailyInfo(ctx context.Context, filter bson.M,
|
||||
opts ...*options.FindOptions) (AnalyticsDailyInfoList, *srvdef.SrvErr) {
|
||||
data := make(AnalyticsDailyInfoList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:FindManyAnalyticsDailyInfo db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// InsertManyAnalyticsDailyInfo 插入一批用户
|
||||
func InsertManyAnalyticsDailyInfo(ctx context.Context, histrory *AnalyticsDailyInfoList) *srvdef.SrvErr {
|
||||
if _, err := db.InsertMany(ctx, histrory); err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:InsertManyAnalyticsDailyInfo db.InsertMany failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AggregateAnalyticsDailyInfo 聚合查找一批数据
|
||||
func AggregateAnalyticsDailyInfo(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := db.Aggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:AggregateAnalyticsDailyInfo db.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectAggregateAnalyticsDailyInfo 聚合查找一批数据
|
||||
func ObjectAggregateAnalyticsDailyInfo(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := db.ObjectAggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("AnalyticsDailyInfo:AggregateAnalyticsDailyInfo db.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
package analyticsdailystat
|
||||
|
||||
type TagAnalyticsDailyInfo struct {
|
||||
AppId string
|
||||
AppName string
|
||||
CreatedAt string
|
||||
Id string
|
||||
LeadAmount string
|
||||
LeadNewCount string
|
||||
SumDate string
|
||||
UpdatedAt string
|
||||
YestodayActiveUsers string
|
||||
YestodayNewUsers string
|
||||
YestodayPV string
|
||||
YestodaySessions string
|
||||
YestodayUV string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
AnalyticsDailyInfo TagAnalyticsDailyInfo
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
AnalyticsDailyInfo string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.AnalyticsDailyInfo.AppId = "appId"
|
||||
FN.AnalyticsDailyInfo.AppName = "appName"
|
||||
FN.AnalyticsDailyInfo.CreatedAt = "createdAt"
|
||||
FN.AnalyticsDailyInfo.Id = "_id"
|
||||
FN.AnalyticsDailyInfo.LeadAmount = "leadAmount"
|
||||
FN.AnalyticsDailyInfo.LeadNewCount = "leadNewCount"
|
||||
FN.AnalyticsDailyInfo.SumDate = "sumDate"
|
||||
FN.AnalyticsDailyInfo.UpdatedAt = "updatedAt"
|
||||
FN.AnalyticsDailyInfo.YestodayActiveUsers = "yestodayActiveUsers"
|
||||
FN.AnalyticsDailyInfo.YestodayNewUsers = "yestodayNewUsers"
|
||||
FN.AnalyticsDailyInfo.YestodayPV = "yestodayPV"
|
||||
FN.AnalyticsDailyInfo.YestodaySessions = "yestodaySessions"
|
||||
FN.AnalyticsDailyInfo.YestodayUV = "yestodayUV"
|
||||
TN.AnalyticsDailyInfo = "analytics_daily_info"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package analyticsdailystat
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 数据统计
|
||||
// @table:analytics_daily_info
|
||||
type AnalyticsDailyInfo struct {
|
||||
Id primitive.ObjectID `bson:"_id,omitempty"`
|
||||
SumDate time.Time `json:"sumDate" bson:"sumDate"` // 时间半小时
|
||||
AppId int64 `json:"appId" bson:"appId"` // appId
|
||||
AppName string `json:"appName" bson:"appName"` // APP名称
|
||||
YestodayPV int64 `json:"yestodayPV" bson:"yestodayPV"` // 页面浏览量 (PV)
|
||||
YestodayUV int64 `json:"yestodayUV" bson:"yestodayUV"` // 独立用户数 (UV)
|
||||
YestodayActiveUsers int64 `json:"yestodayActiveUsers" bson:"yestodayActiveUsers"` // 活跃用户数
|
||||
YestodaySessions int64 `json:"yestodaySessions" bson:"yestodaySessions"` // 会话数
|
||||
YestodayNewUsers int64 `json:"yestodayNewUsers" bson:"yestodayNewUsers"` // 新增数量
|
||||
LeadNewCount float64 `json:"leadNewCount" bson:"leadNewCount"` // 日导量新增
|
||||
LeadAmount float64 `json:"leadAmount" bson:"leadAmount"` // 日导量充值
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type AnalyticsDailyInfoList []*AnalyticsDailyInfo
|
||||
@@ -0,0 +1,182 @@
|
||||
package analyticsstat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
// 获取数据库表
|
||||
db = mongos.Shop.Coll(TN.AnalyticsInfo)
|
||||
// 获取数据库表
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.AnalyticsInfo.AppId, Value: 1},
|
||||
{Key: FN.AnalyticsInfo.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.AnalyticsInfo.SumDate, Value: 1},
|
||||
{Key: FN.AnalyticsInfo.AppId, Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.AnalyticsInfo.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(AnalyticsInfo:initAnalyticsInfoIndex) Create AnalyticsInfo Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOneAnalyticsInfo 插入一个评论
|
||||
func InsertOneAnalyticsInfo(ctx context.Context, AnalyticsInfo *AnalyticsInfo) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, AnalyticsInfo); err != nil {
|
||||
log.Warn("AnalyticsInfo:InsertOneAnalyticsInfo db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneAnalyticsInfo 删除一个评论
|
||||
func DelOneAnalyticsInfo(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsInfo:DelOneAnalyticsInfo db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// DelManyAnalyticsInfo 删除一个评论评论
|
||||
func DelManyAnalyticsInfo(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteMany(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsInfo:DelOneAnalyticsInfo db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneAnalyticsInfo 查找一个评论
|
||||
func FindOneAnalyticsInfo(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (
|
||||
*AnalyticsInfo, *srvdef.SrvErr) {
|
||||
var AnalyticsInfo AnalyticsInfo
|
||||
if err := db.FindOneEx(
|
||||
ctx, &AnalyticsInfo, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Info("AnalyticsInfo:FindOneAnalyticsInfo db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &AnalyticsInfo, nil
|
||||
}
|
||||
|
||||
// CountAnalyticsInfos 统计评论视频评论数量
|
||||
func CountAnalyticsInfos(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsInfo:CountAnalyticsInfos db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneAnalyticsInfo 更新一个评论
|
||||
func UpdateOneAnalyticsInfo(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsInfo:UpdateOneAnalyticsInfo db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("AnalyticsInfo:UpdateOneAnalyticsInfo db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateManyAnalyticsInfo 更新一批评论
|
||||
func UpdateManyAnalyticsInfo(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateMMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("AnalyticsInfo:UpdateManyAnalyticsInfo db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount <= 0 {
|
||||
log.Warn("AnalyticsInfo:UpdateManyAnalyticsInfo db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
//return srvdef.New(srvdef.ErrAnalyticsInfoNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyAnalyticsInfo 查找一批评论
|
||||
func FindManyAnalyticsInfo(ctx context.Context, filter bson.M,
|
||||
opts ...*options.FindOptions) (AnalyticsInfoList, *srvdef.SrvErr) {
|
||||
data := make(AnalyticsInfoList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("AnalyticsInfo:FindManyAnalyticsInfo db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// InsertManyAnalyticsInfo 插入一批用户
|
||||
func InsertManyAnalyticsInfo(ctx context.Context, histrory *AnalyticsInfoList) *srvdef.SrvErr {
|
||||
if _, err := db.InsertMany(ctx, histrory); err != nil {
|
||||
log.Warn("AnalyticsInfo:InsertManyAnalyticsInfo db.InsertMany failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AggregateAnalyticsInfo 聚合查找一批数据
|
||||
func AggregateAnalyticsInfo(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := db.Aggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("AnalyticsInfo:AggregateAnalyticsInfo db.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectAggregateAnalyticsInfo 聚合查找一批数据
|
||||
func ObjectAggregateAnalyticsInfo(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := db.ObjectAggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("AnalyticsInfo:AggregateAnalyticsInfo db.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
package analyticsstat
|
||||
|
||||
type TagAnalyticsInfo struct {
|
||||
ActiveUsers string
|
||||
AppId string
|
||||
AppName string
|
||||
CreatedAt string
|
||||
DaySumDate string
|
||||
Id string
|
||||
SumDate string
|
||||
UpdatedAt string
|
||||
YestodayActiveUsers string
|
||||
YestodayNewUsers string
|
||||
YestodayPV string
|
||||
YestodaySessions string
|
||||
YestodayUV string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
AnalyticsInfo TagAnalyticsInfo
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
AnalyticsInfo string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.AnalyticsInfo.ActiveUsers = "activeUsers"
|
||||
FN.AnalyticsInfo.AppId = "appId"
|
||||
FN.AnalyticsInfo.AppName = "appName"
|
||||
FN.AnalyticsInfo.CreatedAt = "createdAt"
|
||||
FN.AnalyticsInfo.DaySumDate = "daySumDate"
|
||||
FN.AnalyticsInfo.Id = "_id"
|
||||
FN.AnalyticsInfo.SumDate = "sumDate"
|
||||
FN.AnalyticsInfo.UpdatedAt = "updatedAt"
|
||||
FN.AnalyticsInfo.YestodayActiveUsers = "yestodayActiveUsers"
|
||||
FN.AnalyticsInfo.YestodayNewUsers = "yestodayNewUsers"
|
||||
FN.AnalyticsInfo.YestodayPV = "yestodayPV"
|
||||
FN.AnalyticsInfo.YestodaySessions = "yestodaySessions"
|
||||
FN.AnalyticsInfo.YestodayUV = "yestodayUV"
|
||||
TN.AnalyticsInfo = "analytics_info"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package analyticsstat
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 数据统计
|
||||
// @table:analytics_info
|
||||
type AnalyticsInfo struct {
|
||||
Id primitive.ObjectID `bson:"_id,omitempty"`
|
||||
SumDate time.Time `json:"sumDate" bson:"sumDate"` // 时间半小时
|
||||
DaySumDate time.Time `json:"daySumDate" bson:"daySumDate"` // 当天
|
||||
AppId int64 `json:"appId" bson:"appId"` // appId
|
||||
AppName string `json:"appName" bson:"appName"` // APP名称
|
||||
ActiveUsers int64 `json:"activeUsers" bson:"activeUsers"` // 最近半小时活跃数
|
||||
YestodayPV int64 `json:"yestodayPV" bson:"yestodayPV"` // 页面浏览量 (PV)
|
||||
YestodayUV int64 `json:"yestodayUV" bson:"yestodayUV"` // 独立用户数 (UV)
|
||||
YestodayActiveUsers int64 `json:"yestodayActiveUsers" bson:"yestodayActiveUsers"` // 活跃用户数
|
||||
YestodaySessions int64 `json:"yestodaySessions" bson:"yestodaySessions"` // 会话数
|
||||
YestodayNewUsers int64 `json:"yestodayNewUsers" bson:"yestodayNewUsers"` // 新增数量
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type AnalyticsInfoList []*AnalyticsInfo
|
||||
@@ -0,0 +1,102 @@
|
||||
package announcementmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
db = mongos.Shop.Coll(TN.Announcement)
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Announcement.Status, Value: 1},
|
||||
{Key: FN.Announcement.Sort, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Announcement.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(announcementmod:Init) Create Announcement Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
func InsertOneAnnouncement(ctx context.Context, doc *Announcement) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("announcementmod:InsertOneAnnouncement db.InsertOne failed",
|
||||
log.E(err), log.Any("doc", doc))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DelOneAnnouncement(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("announcementmod:DelOneAnnouncement db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func FindOneAnnouncement(ctx context.Context, filter bson.M) (*Announcement, *srvdef.SrvErr) {
|
||||
var doc Announcement
|
||||
if err := db.FindOneEx(ctx, &doc, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("announcementmod:FindOneAnnouncement db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrAnnouncementNotExsit, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
func FindManyAnnouncement(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (AnnouncementList, *srvdef.SrvErr) {
|
||||
data := make(AnnouncementList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("announcementmod:FindManyAnnouncement db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func CountAnnouncement(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("announcementmod:CountAnnouncement db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func UpdateOneAnnouncement(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("announcementmod:UpdateOneAnnouncement db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("announcementmod:UpdateOneAnnouncement not matched",
|
||||
log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrAnnouncementNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package announcementmod
|
||||
|
||||
type TagAnnouncement struct {
|
||||
Id string
|
||||
Title string
|
||||
Content string
|
||||
Sort string
|
||||
Status string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
Announcement TagAnnouncement
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
Announcement string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.Announcement.Id = "_id"
|
||||
FN.Announcement.Title = "title"
|
||||
FN.Announcement.Content = "content"
|
||||
FN.Announcement.Sort = "sort"
|
||||
FN.Announcement.Status = "status"
|
||||
FN.Announcement.CreatedAt = "createdAt"
|
||||
FN.Announcement.UpdatedAt = "updatedAt"
|
||||
TN.Announcement = "announcement"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package announcementmod
|
||||
|
||||
import "time"
|
||||
|
||||
// Announcement 公告
|
||||
// @table:announcement
|
||||
type Announcement struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
Title string `json:"title" bson:"title"` // 标题
|
||||
Content string `json:"content" bson:"content"` // 内容
|
||||
Sort int64 `json:"sort" bson:"sort"` // 排序,越大越靠前
|
||||
Status bool `json:"status" bson:"status"` // 是否启用
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
}
|
||||
|
||||
type AnnouncementList []*Announcement
|
||||
@@ -0,0 +1,42 @@
|
||||
package cfg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
var appKeyCache struct {
|
||||
sync.RWMutex
|
||||
value string
|
||||
ready bool
|
||||
}
|
||||
|
||||
// CacheAppKey 把系统配置里的 appKey 放进内存,供媒资写接口读取。
|
||||
func CacheAppKey(appKey string) {
|
||||
appKeyCache.Lock()
|
||||
appKeyCache.value = strings.TrimSpace(appKey)
|
||||
appKeyCache.ready = true
|
||||
appKeyCache.Unlock()
|
||||
}
|
||||
|
||||
// CachedAppKey 返回已缓存的 appKey。缓存未建立时读取 sys_cfg 并写入缓存。
|
||||
func CachedAppKey(ctx context.Context) string {
|
||||
appKeyCache.RLock()
|
||||
if appKeyCache.ready {
|
||||
value := appKeyCache.value
|
||||
appKeyCache.RUnlock()
|
||||
return value
|
||||
}
|
||||
appKeyCache.RUnlock()
|
||||
|
||||
sysCfg, serr := FindOneSysCfg(ctx, bson.M{FN.SysCfg.Id: 1})
|
||||
if serr != nil || sysCfg == nil {
|
||||
return ""
|
||||
}
|
||||
value := strings.TrimSpace(sysCfg.AppKey)
|
||||
CacheAppKey(value)
|
||||
return value
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cfg
|
||||
|
||||
import (
|
||||
"videoweb/pub/mongos"
|
||||
)
|
||||
|
||||
var (
|
||||
sysCfgColl *mongos.Collection
|
||||
)
|
||||
@@ -0,0 +1,55 @@
|
||||
package cfg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
// Init 初始化数据
|
||||
func Init(ctx context.Context) {
|
||||
sysCfgColl = mongos.Shop.Coll(TN.SysCfg)
|
||||
}
|
||||
|
||||
// FindOneSysCfg 查找一个系统配置
|
||||
func FindOneSysCfg(ctx context.Context, filter bson.M) (
|
||||
*SysCfg, *srvdef.SrvErr) {
|
||||
var sysCfg SysCfg
|
||||
if err := sysCfgColl.FindOneEx(
|
||||
ctx, &sysCfg, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Info("cfg:FindOneSysCfg db.FindOneEx failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return &sysCfg, nil
|
||||
}
|
||||
|
||||
// UpdateOneSysCfg 更新一个系统配置
|
||||
func UpdateOneSysCfg(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := sysCfgColl.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("cfg:UpdateOneSysCfg db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteOneSysCfg(ctx context.Context, filter bson.M) *srvdef.SrvErr {
|
||||
_, err := sysCfgColl.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("cfg:DeleteOneSysCfg db.DeleteOne failed", log.Any("filter", filter), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Executable
+88
@@ -0,0 +1,88 @@
|
||||
package cfg
|
||||
|
||||
type TagSysCfg struct {
|
||||
AppAddr string
|
||||
DownloadVideoUrl string
|
||||
ForeverUrlAddr string
|
||||
GitAddr string
|
||||
GmailAddr string
|
||||
Id string
|
||||
ImgAppCdn string
|
||||
ImgWebCdn string
|
||||
MediaAppCdn string
|
||||
MediaWebCdn string
|
||||
NewUrlAddr string
|
||||
NewUrlAddr1 string
|
||||
NewUrlAddr2 string
|
||||
QQ string
|
||||
Telegram string
|
||||
TelegramAdd string
|
||||
TgGroup string
|
||||
TranslationAddr string
|
||||
TwitterAddr string
|
||||
WatermarkImage string
|
||||
WatermarkMedia string
|
||||
WatermarkMediaTop string
|
||||
WatermarkMediaTopRight string
|
||||
WatermarkMediaBottomLeft string
|
||||
WeiChart string
|
||||
DHNewUrlAddr1 string
|
||||
DHNewUrlAddr2 string
|
||||
DHNewUrlAddr3 string
|
||||
DHForeverUrlAddr string
|
||||
UnencryptedCdn string
|
||||
SitemapDefaultImages string
|
||||
Version string
|
||||
ChannelCode string
|
||||
EnableH265 string
|
||||
M3U8DayRateLimitMax string
|
||||
AppKey string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
SysCfg TagSysCfg
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
SysCfg string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.SysCfg.AppAddr = "appAddr"
|
||||
FN.SysCfg.DownloadVideoUrl = "downloadVideoUrl"
|
||||
FN.SysCfg.ForeverUrlAddr = "foreverUrlAddr"
|
||||
FN.SysCfg.GitAddr = "gitAddr"
|
||||
FN.SysCfg.GmailAddr = "gmailAddr"
|
||||
FN.SysCfg.Id = "_id"
|
||||
FN.SysCfg.ImgAppCdn = "imgAppCdn"
|
||||
FN.SysCfg.ImgWebCdn = "imgWebCdn"
|
||||
FN.SysCfg.MediaAppCdn = "mediaAppCdn"
|
||||
FN.SysCfg.MediaWebCdn = "mediaWebCdn"
|
||||
FN.SysCfg.NewUrlAddr = "newUrlAddr"
|
||||
FN.SysCfg.NewUrlAddr1 = "newUrlAddr1"
|
||||
FN.SysCfg.NewUrlAddr2 = "newUrlAddr2"
|
||||
FN.SysCfg.QQ = "qq"
|
||||
FN.SysCfg.Telegram = "telegram"
|
||||
FN.SysCfg.TelegramAdd = "telegramAdd"
|
||||
FN.SysCfg.TgGroup = "tgGroup"
|
||||
FN.SysCfg.TranslationAddr = "translationAddr"
|
||||
FN.SysCfg.TwitterAddr = "twitterAddr"
|
||||
FN.SysCfg.WatermarkImage = "watermarkImage"
|
||||
FN.SysCfg.WatermarkMedia = "watermarkMedia"
|
||||
FN.SysCfg.WatermarkMediaTop = "watermarkMediaTop"
|
||||
FN.SysCfg.WatermarkMediaTopRight = "watermarkMediaTopRight"
|
||||
FN.SysCfg.WatermarkMediaBottomLeft = "watermarkMediaBottomLeft"
|
||||
FN.SysCfg.WeiChart = "weiChart"
|
||||
FN.SysCfg.DHNewUrlAddr1 = "dHNewUrlAddr1"
|
||||
FN.SysCfg.DHNewUrlAddr2 = "dHNewUrlAddr2"
|
||||
FN.SysCfg.DHNewUrlAddr3 = "dHNewUrlAddr3"
|
||||
FN.SysCfg.DHForeverUrlAddr = "dHForeverUrlAddr"
|
||||
FN.SysCfg.UnencryptedCdn = "unencryptedCdn"
|
||||
FN.SysCfg.SitemapDefaultImages = "sitemapDefaultImages"
|
||||
FN.SysCfg.Version = "version"
|
||||
FN.SysCfg.ChannelCode = "channelCode"
|
||||
FN.SysCfg.EnableH265 = "enableH265"
|
||||
FN.SysCfg.M3U8DayRateLimitMax = "m3u8DayRateLimitMax"
|
||||
FN.SysCfg.AppKey = "appKey"
|
||||
TN.SysCfg = "sys_cfg"
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package cfg
|
||||
|
||||
import "strings"
|
||||
|
||||
// @table:sys_cfg
|
||||
type SysCfg struct {
|
||||
Id int64 `json:"id" bson:"_id"`
|
||||
Version int64 `json:"version" bson:"version"` // 版本号,用于更新乐观锁
|
||||
UnencryptedCdn string `json:"unencryptedCdn" bson:"unencryptedCdn"` // 不加密资源使用的cdn
|
||||
SitemapDefaultImages []string `json:"sitemapDefaultImages" bson:"sitemapDefaultImages"` // Sitemap里面默认封面图
|
||||
ImgAppCdn string `json:"imgAppCdn" bson:"imgAppCdn"` // 图片CDN(app使用)
|
||||
ImgAppUsCdn string `json:"imgAppUsCdn" bson:"imgAppUsCdn"` // 图片CDN(海外app使用)
|
||||
ImgWebCdn string `json:"imgWebCdn" bson:"imgWebCdn"` // 图片CDN(web使用)
|
||||
MediaWebCdn string `json:"mediaWebCdn" bson:"mediaWebCdn"` // 视频CDN(web使用)
|
||||
MediaAppCdn string `json:"mediaAppCdn" bson:"mediaAppCdn"` // 视频CDN(app使用)
|
||||
MediaAppUsCdn string `json:"mediaAppUsCdn" bson:"mediaAppUsCdn"` // 视频CDN(海外app使用)
|
||||
WatermarkImage string `json:"watermarkImage" bson:"watermarkImage"` // 图片水印文件
|
||||
WatermarkMedia string `json:"watermarkMedia" bson:"watermarkMedia"` // 视频水印文件(底部右边)
|
||||
WatermarkMediaTop string `json:"watermarkMediaTop" bson:"watermarkMediaTop"` // 视频水印文件(顶部左边)
|
||||
WatermarkMediaTopRight string `json:"watermarkMediaTopRight" bson:"watermarkMediaTopRight"` // 视频水印文件(顶部右边)
|
||||
WatermarkMediaBottomLeft string `json:"watermarkMediaBottomLeft" bson:"watermarkMediaBottomLeft"` // 视频水印文件(底部左边)
|
||||
Mp4Addr string `json:"mp4Addr" bson:"mp4Addr"` // mp4地址(web使用)
|
||||
PdfAddr string `json:"pdfAddr" bson:"pdfAddr"` // 回家的路PDF
|
||||
//网站管理
|
||||
NewUrlAddr string `json:"newUrlAddr" bson:"newUrlAddr"` //最新地址
|
||||
NewUrlAddr1 string `json:"newUrlAddr1" bson:"newUrlAddr1"` //最新地址(备用地址1)
|
||||
NewUrlAddr2 string `json:"newUrlAddr2" bson:"newUrlAddr2"` //最新地址(备用地址2)
|
||||
ForeverUrlAddr string `json:"foreverUrlAddr" bson:"foreverUrlAddr"` //永久地址
|
||||
GmailAddr string `json:"gmailAddr" bson:"gmailAddr"` //邮箱地址
|
||||
AppAddr string `json:"appAddr" bson:"appAddr"` //APP下载地址(落地页)
|
||||
DownloadVideoUrl string `json:"downloadVideoUrl" bson:"downloadVideoUrl"` // 下载视频URL
|
||||
WeiChart string `json:"weiChart" bson:"weiChart"` //微信群
|
||||
QQ string `json:"qq" bson:"qq"` //qq群
|
||||
TgGroup string `json:"tgGroup" bson:"tgGroup"` //tg群
|
||||
PotaoGroup string `json:"potaoGroup" bson:"potaoGroup"` //土豆群
|
||||
GitAddr string `json:"gitAddr" bson:"gitAddr"` //git地址
|
||||
TwitterAddr string `json:"twitterAddr" bson:"twitterAddr"` //推特地址
|
||||
Telegram string `json:"telegram" bson:"telegram"` //商务tg
|
||||
TelegramAdd string `json:"telegramAdd" bson:"telegramAdd"` //加入我们tg
|
||||
TranslationAddr string `json:"translationAddr" bson:"translationAddr"` //应用导航
|
||||
//SEO
|
||||
WebTitle string `json:"webTitle" bson:"webTitle"` // 网站SEO标题
|
||||
WebKeyworld []string `json:"webKeyworld" bson:"webKeyworld"` // 网站SEO关键字
|
||||
WebDescription string `json:"webDescription" bson:"webDescription"` // 网站SEO描述
|
||||
WebSiteName string `json:"webSiteName" bson:"webSiteName"` // 网站SEO网站名称
|
||||
WebAddr string `json:"webAddr" bson:"webAddr"` // 网站SEO网站地址
|
||||
DHNewUrlAddr1 string `json:"dhNewUrlAddr1" bson:"dhNewUrlAddr1"` // 导航页-线路1
|
||||
DHNewUrlAddr2 string `json:"dhNewUrlAddr2" bson:"dhNewUrlAddr2"` // 导航页-线路2
|
||||
DHNewUrlAddr3 string `json:"dhNewUrlAddr3" bson:"dhNewUrlAddr3"` // 导航页-线路3
|
||||
FreeVPN string `json:"freeVPN" bson:"freeVPN"` // 免费vpn链接
|
||||
UseAddress []string `json:"useAddress" bson:"useAddress"` // 所有使用中的域名
|
||||
DHTitle string `json:"dhTitle" bson:"dhTitle"` // 导航SEO标题
|
||||
DHKeyworld []string `json:"dhKeyworld" bson:"dhKeyworld"` // 导航SEO关键字
|
||||
DHDescription string `json:"dhDescription" bson:"dhDescription"` // 导航SEO描述
|
||||
DHSiteName string `json:"dhSiteName" bson:"dhSiteName"` // 导航SEO网站名称
|
||||
ChannelCode string `json:"channelCode" bson:"channelCode"` // 渠道码
|
||||
EnableH265 bool `json:"enableH265" bson:"enableH265"` // 是否允许客户端使用 H265 地址播放
|
||||
M3U8DayRateLimitMax int64 `json:"m3u8DayRateLimitMax" bson:"m3u8DayRateLimitMax"` // 每 IP 每天最多不同正片数,<=0 使用默认 80
|
||||
AppKey string `json:"appKey" bson:"appKey"` // 媒资库 appKey,调用 media 写接口时传入
|
||||
}
|
||||
|
||||
// SEOBaseURL 返回与页面 canonical 一致的 SEO 主域。
|
||||
// 永久域名未配置时回退到 WebAddr,避免生成空地址。
|
||||
func (c *SysCfg) SEOBaseURL() string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
base := strings.TrimSpace(c.ForeverUrlAddr)
|
||||
if base == "" {
|
||||
base = strings.TrimSpace(c.WebAddr)
|
||||
}
|
||||
return strings.TrimRight(base, "/")
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package commentlikemod
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
const collectionName = "comment_like"
|
||||
|
||||
const CollectionName = collectionName
|
||||
|
||||
type CommentLike struct {
|
||||
UserId int64 `bson:"userId"`
|
||||
CommentId int64 `bson:"commentId"`
|
||||
CreatedAt time.Time `bson:"createdAt"`
|
||||
}
|
||||
|
||||
var coll *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(collectionName)
|
||||
indexes := []mongo.IndexModel{
|
||||
{Keys: bson.D{{Key: "userId", Value: 1}, {Key: "commentId", Value: 1}}, Options: options.Index().SetUnique(true)},
|
||||
{Keys: bson.D{{Key: "commentId", Value: 1}}},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("commentlikemod.Init CreateIndex failed: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
// Add 新增点赞关系,重复点赞不改变状态
|
||||
func Add(ctx context.Context, userId, commentId int64) (bool, *srvdef.SrvErr) {
|
||||
_, err := coll.InsertOne(ctx, &CommentLike{UserId: userId, CommentId: commentId, CreatedAt: time.Now()})
|
||||
if mongo.IsDuplicateKeyError(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
log.Warn("commentlikemod.Add", log.E(err))
|
||||
return false, srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Remove 删除点赞关系,重复取消不改变状态
|
||||
func Remove(ctx context.Context, userId, commentId int64) (bool, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteOne(ctx, bson.M{"userId": userId, "commentId": commentId})
|
||||
if err != nil {
|
||||
log.Warn("commentlikemod.Remove", log.E(err))
|
||||
return false, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// FindByUserAndComments 批量查询当前用户的评论点赞关系
|
||||
func FindByUserAndComments(ctx context.Context, userId int64, commentIds []int64) ([]CommentLike, *srvdef.SrvErr) {
|
||||
result := make([]CommentLike, 0)
|
||||
if userId <= 0 || len(commentIds) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
err := coll.Find(ctx, &result, bson.M{"userId": userId, "commentId": bson.M{"$in": commentIds}})
|
||||
if err != nil {
|
||||
log.Warn("commentlikemod.FindByUserAndComments", log.E(err))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DeleteByCommentIds 清理已删除评论的点赞关系
|
||||
func DeleteByCommentIds(ctx context.Context, commentIds []int64) *srvdef.SrvErr {
|
||||
if len(commentIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := coll.DeleteMany(ctx, bson.M{"commentId": bson.M{"$in": commentIds}})
|
||||
if err != nil {
|
||||
log.Warn("commentlikemod.DeleteByCommentIds", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
package commentmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
// 获取数据库表
|
||||
db = mongos.Shop.Coll(TN.Comment)
|
||||
// 获取数据库表
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Comment.ObjectId, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Comment.Id, Value: 1},
|
||||
{Key: FN.Comment.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Comment.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Comment.ObjectId, Value: 1},
|
||||
{Key: FN.Comment.ReviewStatus, Value: 1},
|
||||
{Key: FN.Comment.Level, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Comment.ObjectId, Value: 1},
|
||||
{Key: FN.Comment.ObjectType, Value: 1},
|
||||
{Key: FN.Comment.ReviewStatus, Value: 1},
|
||||
{Key: FN.Comment.Level, Value: 1},
|
||||
{Key: FN.Comment.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Comment.ObjectId, Value: 1},
|
||||
{Key: FN.Comment.ObjectType, Value: 1},
|
||||
{Key: FN.Comment.ReviewStatus, Value: 1},
|
||||
{Key: FN.Comment.Level, Value: 1},
|
||||
{Key: FN.Comment.CountLike, Value: -1},
|
||||
{Key: FN.Comment.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Comment.ParentsId, Value: 1},
|
||||
{Key: FN.Comment.ReviewStatus, Value: 1},
|
||||
{Key: FN.Comment.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Comment.TopRank, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(comment:initCommentIndex) Create Comment Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOneComment 插入一个评论
|
||||
func InsertOneComment(ctx context.Context, Comment *CommentModel) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, Comment); err != nil {
|
||||
log.Warn("comment:InsertOneComment db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneComment 删除一个评论
|
||||
func DelOneComment(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("comment:DelOneComment db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// DelManyComment 删除一个评论评论
|
||||
func DelManyComment(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteMany(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("comment:DelOneComment db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneComment 查找一个评论
|
||||
func FindOneComment(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (
|
||||
*CommentModel, *srvdef.SrvErr) {
|
||||
var Comment CommentModel
|
||||
if err := db.FindOneEx(
|
||||
ctx, &Comment, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Info("comment:FindOneComment db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &Comment, nil
|
||||
}
|
||||
|
||||
// CountComments 统计评论视频评论数量
|
||||
func CountComments(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("comment:CountComments db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneComment 更新一个评论
|
||||
func UpdateOneComment(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("comment:UpdateOneComment db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("comment:UpdateOneComment db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChangeLikeCount 原子更新已审核评论的点赞数并返回最新值
|
||||
func ChangeLikeCount(ctx context.Context, commentId, delta int64) (int64, *srvdef.SrvErr) {
|
||||
filter := bson.M{FN.Comment.Id: commentId, FN.Comment.ReviewStatus: 1}
|
||||
if delta < 0 {
|
||||
filter[FN.Comment.CountLike] = bson.M{"$gt": 0}
|
||||
}
|
||||
var comment CommentModel
|
||||
err := db.FindOneAndUpdate(ctx, &comment, filter,
|
||||
bson.M{"$inc": bson.M{FN.Comment.CountLike: delta}},
|
||||
options.FindOneAndUpdate().SetReturnDocument(options.After))
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return 0, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
if err != nil {
|
||||
log.Warn("commentmod.ChangeLikeCount", log.E(err))
|
||||
return 0, srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return comment.CountLike, nil
|
||||
}
|
||||
|
||||
// UpdateManyComment 更新一批评论
|
||||
func UpdateManyComment(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateMMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("comment:UpdateManyComment db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount <= 0 {
|
||||
log.Warn("comment:UpdateManyComment db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
//return srvdef.New(srvdef.ErrCommentNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyComment 查找一批评论
|
||||
func FindManyComment(ctx context.Context, filter bson.M,
|
||||
opts ...*options.FindOptions) (CommentModelList, *srvdef.SrvErr) {
|
||||
data := make(CommentModelList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("comment:FindManyComment db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// InsertManyComment 插入一批用户
|
||||
func InsertManyComment(ctx context.Context, histrory *CommentModelList) *srvdef.SrvErr {
|
||||
if _, err := db.InsertMany(ctx, histrory); err != nil {
|
||||
log.Warn("comment:InsertManyComment db.InsertMany failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AggregateComment 聚合查找一批数据
|
||||
func AggregateComment(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := db.Aggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("comment:AggregateComment db.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectAggregateComment 聚合查找一批数据
|
||||
func ObjectAggregateComment(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := db.ObjectAggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("comment:AggregateComment db.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
package commentmod
|
||||
|
||||
type TagComment struct {
|
||||
CreatedAt string
|
||||
Id string
|
||||
Level string
|
||||
ObjectId string
|
||||
ParentsId string
|
||||
ReplyUserName string
|
||||
Text string
|
||||
TopRank string
|
||||
UpdatedAt string
|
||||
UserName string
|
||||
UserId string
|
||||
Avatar string
|
||||
ReviewStatus string
|
||||
CommentCount string
|
||||
CountLike string
|
||||
Ip string
|
||||
ObjectName string
|
||||
ObjectType string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
Comment TagComment
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
Comment string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.Comment.CreatedAt = "createdAt"
|
||||
FN.Comment.Id = "_id"
|
||||
FN.Comment.Level = "level"
|
||||
FN.Comment.ObjectId = "objectId"
|
||||
FN.Comment.ParentsId = "parentsId"
|
||||
FN.Comment.ReplyUserName = "replyUserName"
|
||||
FN.Comment.Text = "text"
|
||||
FN.Comment.TopRank = "topRank"
|
||||
FN.Comment.UpdatedAt = "updatedAt"
|
||||
FN.Comment.UserName = "userName"
|
||||
FN.Comment.ReviewStatus = "reviewStatus"
|
||||
FN.Comment.Ip = "ip"
|
||||
FN.Comment.CommentCount = "commentCount"
|
||||
FN.Comment.CountLike = "countLike"
|
||||
FN.Comment.ObjectName = "objectName"
|
||||
FN.Comment.ObjectType = "objectType"
|
||||
FN.Comment.UserId = "userId"
|
||||
FN.Comment.Avatar = "avatar"
|
||||
TN.Comment = "_comment"
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package commentmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
// 评论管理
|
||||
// @table:_comment
|
||||
type CommentModel struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"` // 评论ID
|
||||
Ip string `json:"ip" bson:"ip"` // 评论IP
|
||||
ObjectId int64 `json:"objectId" bson:"objectId"` // 对象ID
|
||||
ObjectType pubdef.CommentObjectType `json:"objectType" bson:"objectType"` // 对象类型 0=视频 4=短剧
|
||||
ObjectName string `json:"objectName" bson:"objectName"` // 对象类型名称 视频/短剧
|
||||
UserName string `json:"userName" bson:"userName"` // 用户名称
|
||||
UserId int64 `json:"userId" bson:"userId"` // 用户ID
|
||||
Avatar string `json:"avatar" bson:"avatar"` // 用户头像
|
||||
Level int64 `json:"level" bson:"level"` // 评论级别
|
||||
ParentsId int64 `json:"parentsId" bson:"parentsId"` // 上级评论ID
|
||||
ReplyUserName string `json:"replyUserName" bson:"replyUserName"` // 回复名称
|
||||
Text string `json:"text" bson:"text"` // 评论内容
|
||||
CommentCount int64 `json:"commentCount" bson:"commentCount"` // 该评论回复数量
|
||||
CountLike int64 `json:"countLike" bson:"countLike"` // 点赞数
|
||||
ReviewStatus int `json:"reviewStatus" bson:"reviewStatus"` // 审核状态 0 未审核 1审核成功 2 审核失败
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
CreatedAt time.Time `bson:"createdAt" json:"createdAt"` // 创建时间
|
||||
TopRank int64 `json:"topRank" bson:"topRank"` // 置顶排序
|
||||
}
|
||||
|
||||
type CommentModelList []*CommentModel
|
||||
@@ -0,0 +1,189 @@
|
||||
package contactusmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
// 获取数据库表
|
||||
db = mongos.Shop.Coll(TN.ContactUsModel)
|
||||
// 获取数据库表
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContactUsModel.Status, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContactUsModel.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContactUsModel.Name, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContactUsModel.Email, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContactUsModel.Ip, Value: 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(ContactUsModel:initContactUsModelIndex) Create ContactUsModel Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOneContactUsModel 插入一个评论
|
||||
func InsertOneContactUsModel(ctx context.Context, ContactUsModel *ContactUsModel) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, ContactUsModel); err != nil {
|
||||
log.Warn("ContactUsModel:InsertOneContactUsModel db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneContactUsModel 删除一个评论
|
||||
func DelOneContactUsModel(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("ContactUsModel:DelOneContactUsModel db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// DelManyContactUsModel 删除一个评论评论
|
||||
func DelManyContactUsModel(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteMany(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("ContactUsModel:DelOneContactUsModel db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneContactUsModel 查找一个评论
|
||||
func FindOneContactUsModel(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (
|
||||
*ContactUsModel, *srvdef.SrvErr) {
|
||||
var ContactUsModel ContactUsModel
|
||||
if err := db.FindOneEx(
|
||||
ctx, &ContactUsModel, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Info("ContactUsModel:FindOneContactUsModel db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &ContactUsModel, nil
|
||||
}
|
||||
|
||||
// CountContactUsModels 统计评论视频评论数量
|
||||
func CountContactUsModels(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("ContactUsModel:CountContactUsModels db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneContactUsModel 更新一个评论
|
||||
func UpdateOneContactUsModel(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("ContactUsModel:UpdateOneContactUsModel db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("ContactUsModel:UpdateOneContactUsModel db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateManyContactUsModel 更新一批评论
|
||||
func UpdateManyContactUsModel(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateMMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("ContactUsModel:UpdateManyContactUsModel db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount <= 0 {
|
||||
log.Warn("ContactUsModel:UpdateManyContactUsModel db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
//return srvdef.New(srvdef.ErrContactUsModelNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyContactUsModel 查找一批评论
|
||||
func FindManyContactUsModel(ctx context.Context, filter bson.M,
|
||||
opts ...*options.FindOptions) (ContactUsModelList, *srvdef.SrvErr) {
|
||||
data := make(ContactUsModelList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("ContactUsModel:FindManyContactUsModel db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// InsertManyContactUsModel 插入一批用户
|
||||
func InsertManyContactUsModel(ctx context.Context, histrory *ContactUsModelList) *srvdef.SrvErr {
|
||||
if _, err := db.InsertMany(ctx, histrory); err != nil {
|
||||
log.Warn("ContactUsModel:InsertManyContactUsModel db.InsertMany failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AggregateContactUsModel 聚合查找一批数据
|
||||
func AggregateContactUsModel(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := db.Aggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("ContactUsModel:AggregateContactUsModel db.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectAggregateContactUsModel 聚合查找一批数据
|
||||
func ObjectAggregateContactUsModel(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := db.ObjectAggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("ContactUsModel:AggregateContactUsModel db.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
package contactusmod
|
||||
|
||||
type TagContactUsModel struct {
|
||||
Id string
|
||||
Ip string
|
||||
Name string
|
||||
Email string
|
||||
CategoryName string
|
||||
Content string
|
||||
Status string
|
||||
UpdatedAt string
|
||||
CreatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
ContactUsModel TagContactUsModel
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
ContactUsModel string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.ContactUsModel.Id = "_id"
|
||||
FN.ContactUsModel.Ip = "ip"
|
||||
FN.ContactUsModel.Name = "name"
|
||||
FN.ContactUsModel.Email = "email"
|
||||
FN.ContactUsModel.CategoryName = "categoryName"
|
||||
FN.ContactUsModel.Content = "content"
|
||||
FN.ContactUsModel.Status = "status"
|
||||
FN.ContactUsModel.UpdatedAt = "updatedAt"
|
||||
FN.ContactUsModel.CreatedAt = "createdAt"
|
||||
TN.ContactUsModel = "contact_us"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package contactusmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ContactUsModel 联系我们
|
||||
// @table:contact_us
|
||||
type ContactUsModel struct {
|
||||
Id primitive.ObjectID `json:"id" bson:"_id,omitempty"` // ID
|
||||
Ip string `json:"ip" bson:"ip"` // 评论IP
|
||||
Name string `json:"name" bson:"name"` // 名字
|
||||
Email string `json:"email" bson:"email"` // 邮件
|
||||
CategoryName string `json:"categoryName" bson:"categoryName"` // 主旨分类
|
||||
Content string `json:"content" bson:"content"` // 内容
|
||||
Status int64 `json:"status" bson:"status"` // 状态 0=初始 1=已回复 2=不予处理 3=已完结
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
CreatedAt time.Time `bson:"createdAt" json:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type ContactUsModelList []*ContactUsModel
|
||||
@@ -0,0 +1,206 @@
|
||||
package contenttagmod
|
||||
|
||||
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 初始化 content_tag 集合和常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.ContentTag)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContentTag.Name, Value: 1},
|
||||
},
|
||||
Options: options.Index().
|
||||
SetUnique(true).
|
||||
SetName("uniq_content_tag_name").
|
||||
SetPartialFilterExpression(bson.M{FN.ContentTag.Name: bson.M{"$type": "string", "$gt": ""}}),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContentTag.Types, Value: 1},
|
||||
{Key: FN.ContentTag.Status, Value: 1},
|
||||
{Key: FN.ContentTag.Rank, Value: -1},
|
||||
{Key: FN.ContentTag.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContentTag.Status, Value: 1},
|
||||
{Key: FN.ContentTag.Rank, Value: -1},
|
||||
{Key: FN.ContentTag.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContentTag.VideoCount, Value: -1},
|
||||
{Key: FN.ContentTag.Rank, Value: -1},
|
||||
{Key: FN.ContentTag.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ContentTag.PlayletCount, Value: -1},
|
||||
{Key: FN.ContentTag.Rank, Value: -1},
|
||||
{Key: FN.ContentTag.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(contenttagmod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOneContentTag 插入一条统一标签数据
|
||||
func InsertOneContentTag(ctx context.Context, doc *ContentTag) *srvdef.SrvErr {
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.ContentTag.Get()
|
||||
}
|
||||
now := time.Now()
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
doc.UpdatedAt = now
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
if mongo.IsDuplicateKeyError(err) {
|
||||
log.Warn("contenttagmod:InsertOneContentTag duplicate key", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInputExist, "标签名称已存在", "")
|
||||
}
|
||||
log.Warn("contenttagmod:InsertOneContentTag failed", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneContentTag 删除一条统一标签数据
|
||||
func DelOneContentTag(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("contenttagmod:DelOneContentTag failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneContentTag 查询一条统一标签数据
|
||||
func FindOneContentTag(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*ContentTag, *srvdef.SrvErr) {
|
||||
var doc ContentTag
|
||||
if err := coll.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("contenttagmod:FindOneContentTag failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyContentTag 按条件查询多条统一标签数据
|
||||
func FindManyContentTag(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (ContentTagList, *srvdef.SrvErr) {
|
||||
data := make(ContentTagList, 0)
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("contenttagmod:FindManyContentTag failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// AggregateContentTag 聚合查询统一标签数据
|
||||
func AggregateContentTag(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("contenttagmod:AggregateContentTag 聚合查询统一标签失败", log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMapTags 按标签ID批量查询统一标签映射
|
||||
func GetMapTags(ctx context.Context, ids []int64) (ContentTagMap, *srvdef.SrvErr) {
|
||||
result := make(ContentTagMap)
|
||||
if len(ids) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
list, err := FindManyContentTag(ctx, bson.M{
|
||||
FN.ContentTag.Id: bson.M{"$in": ids},
|
||||
}, options.Find().SetProjection(bson.M{
|
||||
FN.ContentTag.Id: 1,
|
||||
FN.ContentTag.Name: 1,
|
||||
FN.ContentTag.Slug: 1,
|
||||
FN.ContentTag.Types: 1,
|
||||
FN.ContentTag.Status: 1,
|
||||
"seoInfo": 1,
|
||||
FN.ContentTag.Rank: 1,
|
||||
}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, item := range list {
|
||||
if item != nil {
|
||||
result[item.Id] = item
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CountContentTag 统计满足条件的统一标签数量
|
||||
func CountContentTag(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter, opts...)
|
||||
if err != nil {
|
||||
log.Warn("contenttagmod:CountContentTag failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneContentTag 更新一条统一标签数据
|
||||
func UpdateOneContentTag(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
if mongo.IsDuplicateKeyError(err) {
|
||||
log.Warn("contenttagmod:UpdateOneContentTag duplicate key", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbInputExist, "标签名称已存在", "")
|
||||
}
|
||||
log.Warn("contenttagmod:UpdateOneContentTag failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateManyContentTag 批量更新统一标签数据
|
||||
func UpdateManyContentTag(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
_, err := coll.UpdateMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("contenttagmod:UpdateManyContentTag failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BulkWriteContentTag 批量写入/更新统一标签数据
|
||||
func BulkWriteContentTag(ctx context.Context, docs []mongo.WriteModel, opts ...*options.BulkWriteOptions) (*mongo.BulkWriteResult, *srvdef.SrvErr) {
|
||||
result, err := coll.BulkWrite(ctx, docs, opts...)
|
||||
if err != nil {
|
||||
log.Warn("contenttagmod:BulkWriteContentTag failed", log.E(err))
|
||||
return nil, srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package contenttagmod
|
||||
|
||||
// TagContentTag 保存 content_tag 集合字段名
|
||||
type TagContentTag struct {
|
||||
Id string
|
||||
Name string
|
||||
Slug string
|
||||
Types string
|
||||
Status string
|
||||
Rank string
|
||||
VideoCount string
|
||||
PlayletCount string
|
||||
SeoInfo struct {
|
||||
Description string
|
||||
Keyworld string
|
||||
Title string
|
||||
}
|
||||
CreatedById string
|
||||
CreatedByName string
|
||||
UpdatedByName string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
ContentTag TagContentTag
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
ContentTag string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.ContentTag.Id = "_id"
|
||||
FN.ContentTag.Name = "name"
|
||||
FN.ContentTag.Slug = "slug"
|
||||
FN.ContentTag.Types = "types"
|
||||
FN.ContentTag.Status = "status"
|
||||
FN.ContentTag.Rank = "rank"
|
||||
FN.ContentTag.VideoCount = "videoCount"
|
||||
FN.ContentTag.PlayletCount = "playletCount"
|
||||
FN.ContentTag.SeoInfo.Description = "seoInfo.webDescription"
|
||||
FN.ContentTag.SeoInfo.Keyworld = "seoInfo.webKeyworld"
|
||||
FN.ContentTag.SeoInfo.Title = "seoInfo.webTitle"
|
||||
FN.ContentTag.CreatedById = "createdById"
|
||||
FN.ContentTag.CreatedByName = "createdByName"
|
||||
FN.ContentTag.UpdatedByName = "updatedByName"
|
||||
FN.ContentTag.CreatedAt = "createdAt"
|
||||
FN.ContentTag.UpdatedAt = "updatedAt"
|
||||
TN.ContentTag = "content_tag"
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package contenttagmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
// ContentTagType 统一内容标签支持的内容类型
|
||||
type ContentTagType int32
|
||||
|
||||
const (
|
||||
ContentTagTypeVideo ContentTagType = 1 // 视频
|
||||
ContentTagTypePlaylet ContentTagType = 5 // 短剧
|
||||
)
|
||||
|
||||
// ContentTag @table: content_tag
|
||||
//
|
||||
// ContentTag 内容统一标签集合模型
|
||||
type ContentTag struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"` // ID
|
||||
Name string `json:"name" bson:"name"` // 标签名称
|
||||
Slug string `json:"slug" bson:"slug"` // slug
|
||||
Types []ContentTagType `json:"types" bson:"types"` // 支持类型 1-视频 5-短剧
|
||||
Status bool `json:"status" bson:"status"` // 状态 true-启用 false-停用
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序,越大越靠前
|
||||
VideoCount int64 `json:"videoCount" bson:"videoCount"` // 绑定视频数量
|
||||
PlayletCount int64 `json:"playletCount" bson:"playletCount"` // 绑定短剧数量
|
||||
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
|
||||
CreatedById int64 `json:"createdById" bson:"createdById"` // 创建人ID
|
||||
CreatedByName string `json:"createdByName" bson:"createdByName"` // 创建人名称
|
||||
UpdatedByName string `json:"updatedByName" bson:"updatedByName"` // 修改人名称
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
}
|
||||
|
||||
// ContentTagList 内容统一标签列表
|
||||
type ContentTagList []*ContentTag
|
||||
|
||||
// ContentTagMap 内容统一标签ID映射
|
||||
type ContentTagMap map[int64]*ContentTag
|
||||
@@ -0,0 +1,102 @@
|
||||
package detailnavmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
db = mongos.Shop.Coll(TN.DetailNavModel)
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.DetailNavModel.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(detailnavmod:Init) Create DetailNavModel Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOneDetailNav 插入一条详情页导航
|
||||
func InsertOneDetailNav(ctx context.Context, doc *DetailNavModel) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("detailnavmod:InsertOneDetailNav db.InsertOne failed",
|
||||
log.E(err), log.Any("doc", doc))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneDetailNav 删除一条详情页导航
|
||||
func DelOneDetailNav(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("detailnavmod:DelOneDetailNav db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneDetailNav 查找一条详情页导航
|
||||
func FindOneDetailNav(ctx context.Context, filter bson.M) (*DetailNavModel, *srvdef.SrvErr) {
|
||||
var doc DetailNavModel
|
||||
if err := db.FindOneEx(ctx, &doc, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("detailnavmod:FindOneDetailNav db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyDetailNav 查找多条详情页导航
|
||||
func FindManyDetailNav(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (DetailNavModelList, *srvdef.SrvErr) {
|
||||
data := make(DetailNavModelList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("detailnavmod:FindManyDetailNav db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountDetailNav 统计详情页导航数量
|
||||
func CountDetailNav(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("detailnavmod:CountDetailNav db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneDetailNav 更新一条详情页导航
|
||||
func UpdateOneDetailNav(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("detailnavmod:UpdateOneDetailNav db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("detailnavmod:UpdateOneDetailNav not matched",
|
||||
log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package detailnavmod
|
||||
|
||||
type TagDetailNavModel struct {
|
||||
CreatedAt string
|
||||
ID string
|
||||
Name string
|
||||
Url string
|
||||
Sort string
|
||||
Status string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
DetailNavModel TagDetailNavModel
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
DetailNavModel string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.DetailNavModel.CreatedAt = "createdAt"
|
||||
FN.DetailNavModel.ID = "_id"
|
||||
FN.DetailNavModel.Name = "name"
|
||||
FN.DetailNavModel.Url = "url"
|
||||
FN.DetailNavModel.Sort = "sort"
|
||||
FN.DetailNavModel.Status = "status"
|
||||
FN.DetailNavModel.UpdatedAt = "updatedAt"
|
||||
TN.DetailNavModel = "detail_nav"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package detailnavmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 详情页导航配置
|
||||
// @table:detail_nav
|
||||
type DetailNavModel struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
Name string `json:"name" bson:"name"` // 导航名称
|
||||
Url string `json:"url" bson:"url"` // 导航链接
|
||||
Sort int64 `json:"sort" bson:"sort"` // 排序
|
||||
Status bool `json:"status" bson:"status"` // 是否启用
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
}
|
||||
|
||||
type DetailNavModelList []*DetailNavModel
|
||||
@@ -0,0 +1,105 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/esmanager"
|
||||
)
|
||||
|
||||
// SearchActress 根据关键字搜索媒体
|
||||
func SearchActress(content string, from int64, size int64, sort string) (int64, []*ESActress, *srvdef.SrvErr) {
|
||||
fields := []string{FN.ESActress.Alias, FN.ESActress.Office, FN.ESActress.Region, FN.ESActress.Desc}
|
||||
must := esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields},
|
||||
},
|
||||
{"term": esmanager.M{FN.ESActress.Status: true}},
|
||||
},
|
||||
},
|
||||
}
|
||||
switch sort {
|
||||
case string(proto.SearchSortTypeHot):
|
||||
must = esmanager.M{
|
||||
"function_score": esmanager.M{
|
||||
"query": esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESActress.Status: true}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"functions": esmanager.A{
|
||||
esmanager.M{
|
||||
"field_value_factor": esmanager.M{
|
||||
"field": FN.ESActress.Real.WatchTimes,
|
||||
"factor": 1.0,
|
||||
"modifier": "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
"score_mode": "sum",
|
||||
"boost_mode": "multiply",
|
||||
},
|
||||
}
|
||||
case string(proto.SearchSortTypeNew):
|
||||
must = esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields},
|
||||
},
|
||||
{"term": esmanager.M{FN.ESActress.Status: true}},
|
||||
},
|
||||
"should": esmanager.A{
|
||||
{"range": esmanager.M{FN.ESActress.CreatedAt: esmanager.M{"gte": "now-30d/d", "boost": 2.0}}}, //7天内提升4倍权重
|
||||
{"range": esmanager.M{FN.ESActress.CreatedAt: esmanager.M{"gte": "now-180d/d", "boost": 1.5}}}, // 30天内提升3倍权重
|
||||
{"range": esmanager.M{FN.ESActress.CreatedAt: esmanager.M{"gte": "now-365d/d", "boost": 1.1}}}, // 90天内提升1.5倍权重
|
||||
},
|
||||
"minimum_should_match": 0, // 允许不匹配任何should条件
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
query := esmanager.M{
|
||||
"query": must,
|
||||
"sort": esmanager.A{
|
||||
esmanager.M{"_score": esmanager.M{"order": "desc"}},
|
||||
},
|
||||
"from": from,
|
||||
"size": size,
|
||||
}
|
||||
|
||||
actressList := &ESActressHits{}
|
||||
err := esmanager.Instance.Search(actressIndex, actressList, query)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf(
|
||||
"(esmod:SearchActress) Search failed! err:%+v:", err)
|
||||
log.Warn(info,
|
||||
log.Any("keywords", content),
|
||||
log.Any("from", from),
|
||||
log.Any("size", size))
|
||||
return 0, nil, srvdef.New(srvdef.ErrElsOperError, "", "")
|
||||
}
|
||||
total := int64(0)
|
||||
rslData := make([]*ESActress, 0)
|
||||
if actressList != nil && actressList.Hits != nil && len(actressList.Hits) > 0 {
|
||||
total = actressList.Total.Value
|
||||
for _, video := range actressList.Hits {
|
||||
rslData = append(rslData, video.Source)
|
||||
}
|
||||
}
|
||||
return total, rslData, nil
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"videoweb/pub/common/srvdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
const (
|
||||
FiveMinuteScale = 5 //对齐时间(分钟)
|
||||
)
|
||||
|
||||
var (
|
||||
videoIndex = "webhjsq_video_index_v1"
|
||||
playletIndex = "webhjsq_playlet_index_v1"
|
||||
actressIndex = "webhjsq_actress_index_v1"
|
||||
)
|
||||
|
||||
func GetVideoIndex() string {
|
||||
return videoIndex
|
||||
}
|
||||
func GetPlayletIndex() string {
|
||||
return playletIndex
|
||||
}
|
||||
func GetActressIndex() string {
|
||||
return actressIndex
|
||||
}
|
||||
|
||||
func GetRecordByESIndex(ctx context.Context, esIndex string) (
|
||||
*ESTimestamp, *srvdef.SrvErr) {
|
||||
|
||||
filter := bson.M{FN.ESRecord.EsIndex: esIndex}
|
||||
esRecord, serr := FindOneESRecord(ctx, filter)
|
||||
if serr != nil {
|
||||
if serr.Code != srvdef.ErrNoData {
|
||||
return nil, serr
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
return &esRecord.Timestamp, nil
|
||||
}
|
||||
|
||||
func SetOneEsRecord(ctx context.Context, esIndex string,
|
||||
timestamp *ESTimestamp) *srvdef.SrvErr {
|
||||
filter := bson.M{FN.ESRecord.EsIndex: esIndex}
|
||||
upsertDoc := bson.M{
|
||||
"$set": bson.M{
|
||||
FN.ESRecord.Timestamp.T: timestamp.T,
|
||||
FN.ESRecord.Timestamp.I: timestamp.I,
|
||||
FN.ESRecord.UpdatedAt: time.Now(),
|
||||
},
|
||||
"$setOnInsert": bson.M{
|
||||
FN.ESRecord.Id: primitive.NewObjectID(),
|
||||
FN.ESRecord.CreatedAt: time.Now(),
|
||||
},
|
||||
}
|
||||
serr := UpsertOneESRecord(ctx, filter, upsertDoc)
|
||||
return serr
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"videoweb/pub/esmanager"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var db *mongos.Collection
|
||||
|
||||
// Init 初始化数据
|
||||
func Init(ctx context.Context) {
|
||||
initDBIndex(ctx)
|
||||
initIndex()
|
||||
return
|
||||
}
|
||||
|
||||
// initIndex 初始化索引
|
||||
func initIndex() {
|
||||
if esmanager.Instance == nil {
|
||||
return
|
||||
}
|
||||
initVideoIndex(videoIndex)
|
||||
initPlayletIndex(playletIndex)
|
||||
initActressIndex(actressIndex)
|
||||
}
|
||||
|
||||
// initDBIndex 初始化数据库索引
|
||||
func initDBIndex(ctx context.Context) {
|
||||
//获取数据库表
|
||||
db = mongos.Shop.Coll(TN.ESRecord)
|
||||
// 获取数据库表
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ESRecord.EsIndex, Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(esmod:initDBIndex) Create es_record Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
func initVideoIndex(esIndex string) {
|
||||
var setting = esmanager.M{
|
||||
"settings": esmanager.M{
|
||||
"number_of_shards": esmanager.NumberOfShards,
|
||||
"number_of_replicas": esmanager.NumberOfReplicas,
|
||||
"analysis": esmanager.M{
|
||||
"analyzer": esmanager.M{
|
||||
"ik": esmanager.M{
|
||||
"tokenizer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mappings": esmanager.M{
|
||||
"properties": esmanager.M{
|
||||
FN.ESVideo.Title: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.MediaType: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESVideo.Remark: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.Desc: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.Keyworlds: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.CreatorName: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.Bango: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.IssuedBrand: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.Status: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
//FN.ESVideo.IsHot: esmanager.M{
|
||||
// "type": "boolean",
|
||||
//},
|
||||
//FN.ESVideo.Sort: esmanager.M{
|
||||
// "type": "integer",
|
||||
//},
|
||||
FN.ESVideo.WatchTimes: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESVideo.ShowTimes: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESVideo.Comments: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESVideo.AddedTime: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
FN.ESVideo.IssuedAt: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
//FN.ESVideo.CreatedAt: esmanager.M{
|
||||
// "type": "date",
|
||||
// "format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
//},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := esmanager.Instance.InitIndices(esIndex, setting); err != nil {
|
||||
panic(fmt.Sprintf("ElasticSearch Index %s initMediaIndex error", esIndex))
|
||||
}
|
||||
}
|
||||
|
||||
func initPlayletIndex(esIndex string) {
|
||||
var setting = esmanager.M{
|
||||
"settings": esmanager.M{
|
||||
"number_of_shards": esmanager.NumberOfShards,
|
||||
"number_of_replicas": esmanager.NumberOfReplicas,
|
||||
"analysis": esmanager.M{
|
||||
"analyzer": esmanager.M{
|
||||
"ik": esmanager.M{
|
||||
"tokenizer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mappings": esmanager.M{
|
||||
"properties": esmanager.M{
|
||||
FN.ESPlaylet.Id: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.Status: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESPlaylet.IsFeatured: esmanager.M{
|
||||
"type": "boolean",
|
||||
},
|
||||
FN.ESPlaylet.IsRecommend: esmanager.M{
|
||||
"type": "boolean",
|
||||
},
|
||||
FN.ESPlaylet.ShowOnBanner: esmanager.M{
|
||||
"type": "boolean",
|
||||
},
|
||||
FN.ESPlaylet.Banner: esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
FN.ESPlaylet.OnlineAt: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
FN.ESPlaylet.CategoryIds: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.CategoryNames: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.ThemeIds: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.ThemeNames: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.Title: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.Desc: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.Anchor: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.Cover: esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
FN.ESPlaylet.TagIds: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.TagNames: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.TotalEpisode: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.UpdateStatus: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESPlaylet.CountBrowse: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.HeatValue: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.CountCollect: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.CountLike: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.SeoInfo: esmanager.M{
|
||||
"properties": esmanager.M{
|
||||
"title": esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
"keyworld": esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
"description": esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
FN.ESPlaylet.UpdatedAt: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
FN.ESPlaylet.CreatedAt: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := esmanager.Instance.InitIndices(esIndex, setting); err != nil {
|
||||
panic(fmt.Sprintf("ElasticSearch Index %s initPlayletIndex error", esIndex))
|
||||
}
|
||||
}
|
||||
|
||||
func initActressIndex(esIndex string) {
|
||||
var setting = esmanager.M{
|
||||
"settings": esmanager.M{
|
||||
"number_of_shards": esmanager.NumberOfShards,
|
||||
"number_of_replicas": esmanager.NumberOfReplicas,
|
||||
"analysis": esmanager.M{
|
||||
"analyzer": esmanager.M{
|
||||
"ik": esmanager.M{
|
||||
"tokenizer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mappings": esmanager.M{
|
||||
"properties": esmanager.M{
|
||||
FN.ESActress.Alias: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESActress.Desc: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESActress.Office: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESActress.Region: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESActress.Rank: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Status: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Works: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.HotValue: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Real.WatchTimes: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Real.WeekWatchs: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Real.MonthWatchs: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.DebutDate: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
FN.ESActress.DebutDate: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := esmanager.Instance.InitIndices(esIndex, setting); err != nil {
|
||||
panic(fmt.Sprintf("ElasticSearch Index %s initMediaIndex error", esIndex))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/esmanager"
|
||||
"videoweb/pub/models/playletmod"
|
||||
)
|
||||
|
||||
// SearchPlaylet 根据关键字搜索短剧
|
||||
func SearchPlaylet(content string, from int64, size int64, sort string) (int64, []*ESPlaylet, *srvdef.SrvErr) {
|
||||
fields := []string{
|
||||
FN.ESPlaylet.Title,
|
||||
FN.ESPlaylet.Desc,
|
||||
FN.ESPlaylet.Anchor,
|
||||
FN.ESPlaylet.CategoryNames,
|
||||
FN.ESPlaylet.ThemeNames,
|
||||
FN.ESPlaylet.TagNames,
|
||||
}
|
||||
must := esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESPlaylet.Status: playletmod.StatusUp}},
|
||||
},
|
||||
},
|
||||
}
|
||||
switch sort {
|
||||
case string(proto.SearchSortTypeHot):
|
||||
must = esmanager.M{
|
||||
"function_score": esmanager.M{
|
||||
"query": esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESPlaylet.Status: playletmod.StatusUp}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"functions": esmanager.A{
|
||||
esmanager.M{
|
||||
"field_value_factor": esmanager.M{
|
||||
"field": FN.ESPlaylet.CountBrowse,
|
||||
"factor": 1.0,
|
||||
"modifier": "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
"score_mode": "sum",
|
||||
"boost_mode": "multiply",
|
||||
},
|
||||
}
|
||||
case string(proto.SearchSortTypeNew):
|
||||
must = esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESPlaylet.Status: playletmod.StatusUp}},
|
||||
},
|
||||
"should": esmanager.A{
|
||||
{"range": esmanager.M{FN.ESPlaylet.OnlineAt: esmanager.M{"gte": "now-30d/d", "boost": 2.0}}},
|
||||
{"range": esmanager.M{FN.ESPlaylet.OnlineAt: esmanager.M{"gte": "now-180d/d", "boost": 1.5}}},
|
||||
{"range": esmanager.M{FN.ESPlaylet.OnlineAt: esmanager.M{"gte": "now-365d/d", "boost": 1.1}}},
|
||||
},
|
||||
"minimum_should_match": 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
query := esmanager.M{
|
||||
"query": must,
|
||||
"sort": esmanager.A{
|
||||
esmanager.M{"_score": esmanager.M{"order": "desc"}},
|
||||
},
|
||||
"from": from,
|
||||
"size": size,
|
||||
"terminate_after": 1000,
|
||||
}
|
||||
|
||||
playletList := &ESPlayletHits{}
|
||||
err := esmanager.Instance.Search(playletIndex, playletList, query)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf("(esmod:SearchPlaylet) Search failed! err:%+v:", err)
|
||||
log.Warn(info, log.Any("keywords", content), log.Any("from", from), log.Any("size", size))
|
||||
return 0, nil, srvdef.New(srvdef.ErrElsOperError, "", "")
|
||||
}
|
||||
total := int64(0)
|
||||
result := make([]*ESPlaylet, 0)
|
||||
if playletList != nil && playletList.Hits != nil && len(playletList.Hits) > 0 {
|
||||
total = playletList.Total.Value
|
||||
for _, item := range playletList.Hits {
|
||||
if item != nil && item.Source != nil {
|
||||
result = append(result, item.Source)
|
||||
}
|
||||
}
|
||||
}
|
||||
return total, result, nil
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"time"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// InsertOneESRecord 插入ES操作记录
|
||||
func InsertOneESRecord(ctx context.Context, esRecord *ESRecord) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, esRecord); err != nil {
|
||||
log.Warn("esmod:InsertOneESRecord db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneESRecord 删除一个ES操作记录
|
||||
func DelOneESRecord(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("esmod:DelOnAppTag db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneESRecord 查找一个ES操作记录
|
||||
func FindOneESRecord(ctx context.Context, filter bson.M) (
|
||||
*ESRecord, *srvdef.SrvErr) {
|
||||
var esRecord ESRecord
|
||||
if err := db.FindOneEx(
|
||||
ctx, &esRecord, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Info("esmod:FindOnESRecord db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &esRecord, nil
|
||||
}
|
||||
|
||||
// CountESRecords 统计ES操作记录
|
||||
func CountESRecords(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("esmod:CountMediaCats db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneESRecord 更新ES操作记录
|
||||
func UpdateOneESRecord(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("esmod:UpdateOnESRecord db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("esmod:UpdateOnESRecord db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrMediaRecordNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpsertOneESRecord 插入或更新一条ES操作记录
|
||||
func UpsertOneESRecord(ctx context.Context,
|
||||
filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
if _, err := db.UpsertOne(ctx, filter, update); err != nil {
|
||||
log.Info("esmod:UpsertOneESRecord db.InsertOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateManyESRecord 更新一批ES操作记录
|
||||
func UpdateManyESRecord(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateMMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("esmod:UpdateManyMediaCat db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount <= 0 {
|
||||
log.Warn("esmod:UpdateManyMediaCat db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
//return srvdef.New(srvdef.ErrMediaTagNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyESRecord 查找一批ES操作记录
|
||||
func FindManyESRecord(ctx context.Context, filter bson.M,
|
||||
opts ...*options.FindOptions) (ESRecordList, *srvdef.SrvErr) {
|
||||
data := make(ESRecordList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("esmod:FindManyESRecord db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func GetRecordTimeByESIndex(ctx context.Context, esIndex string) (*ESRecord, *srvdef.SrvErr) {
|
||||
filter := bson.M{FN.ESRecord.EsIndex: esIndex}
|
||||
esRecord, serr := FindOneESRecord(ctx, filter)
|
||||
if serr != nil {
|
||||
if serr.Code != srvdef.ErrNoData {
|
||||
return nil, serr
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
return esRecord, nil
|
||||
}
|
||||
func SetOneEsRecordTime(ctx context.Context, esIndex string, recordTime time.Time) *srvdef.SrvErr {
|
||||
filter := bson.M{FN.ESRecord.EsIndex: esIndex}
|
||||
upsertDoc := bson.M{
|
||||
"$set": bson.M{
|
||||
FN.ESRecord.RecordTime: recordTime,
|
||||
FN.ESRecord.UpdatedAt: time.Now(),
|
||||
},
|
||||
"$setOnInsert": bson.M{
|
||||
FN.ESRecord.Id: primitive.NewObjectID(),
|
||||
FN.ESRecord.CreatedAt: time.Now(),
|
||||
},
|
||||
}
|
||||
serr := UpsertOneESRecord(ctx, filter, upsertDoc)
|
||||
return serr
|
||||
}
|
||||
Executable
+227
@@ -0,0 +1,227 @@
|
||||
package esmod
|
||||
|
||||
type TagESRecord struct {
|
||||
CreatedAt string
|
||||
EsIndex string
|
||||
Id string
|
||||
RecordTime string
|
||||
Timestamp struct {
|
||||
I string
|
||||
T string
|
||||
}
|
||||
UpdatedAt string
|
||||
}
|
||||
type TagESVideo struct {
|
||||
Id string
|
||||
Title string
|
||||
MediaType string
|
||||
AddedTime string
|
||||
CreatorName string
|
||||
Keyworlds string
|
||||
Desc string
|
||||
Remark string
|
||||
Status string
|
||||
IsHot string
|
||||
Sort string
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
UpdatedAt string
|
||||
CreatedAt string
|
||||
|
||||
Keyworld string
|
||||
CreatorId string
|
||||
FirstTag string
|
||||
SecondTags string
|
||||
CoverImg string
|
||||
Nodes string
|
||||
Video string
|
||||
CategoryIds string
|
||||
Tags string
|
||||
Real struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}
|
||||
IssuedAt string
|
||||
IssuedBrand string
|
||||
Bango string
|
||||
}
|
||||
type TagESPlaylet struct {
|
||||
Id string
|
||||
Status string
|
||||
IsFeatured string
|
||||
IsRecommend string
|
||||
ShowOnBanner string
|
||||
Banner string
|
||||
OnlineAt string
|
||||
CategoryIds string
|
||||
CategoryNames string
|
||||
ThemeIds string
|
||||
ThemeNames string
|
||||
Title string
|
||||
Desc string
|
||||
Anchor string
|
||||
Cover string
|
||||
TagIds string
|
||||
TagNames string
|
||||
TotalEpisode string
|
||||
UpdateStatus string
|
||||
CountBrowse string
|
||||
HeatValue string
|
||||
CountCollect string
|
||||
CountLike string
|
||||
SeoInfo string
|
||||
UpdatedAt string
|
||||
CreatedAt string
|
||||
}
|
||||
type TagESActress struct {
|
||||
Id string
|
||||
Alias string
|
||||
Avatar string
|
||||
Meas string
|
||||
Office string
|
||||
DebutDate string
|
||||
BornDate string
|
||||
Region string
|
||||
Score string
|
||||
Works string
|
||||
HotValue string
|
||||
Real struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}
|
||||
Desc string
|
||||
Status string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
Rank string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
ESRecord TagESRecord
|
||||
ESVideo TagESVideo
|
||||
ESPlaylet TagESPlaylet
|
||||
ESActress TagESActress
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
ESRecord string
|
||||
ESVideo string
|
||||
ESPlaylet string
|
||||
ESActress string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.ESRecord = TagESRecord{
|
||||
CreatedAt: "createdAt",
|
||||
EsIndex: "esIndex",
|
||||
Id: "_id",
|
||||
RecordTime: "recordTime",
|
||||
Timestamp: struct {
|
||||
I string
|
||||
T string
|
||||
}{
|
||||
I: "i",
|
||||
T: "t",
|
||||
},
|
||||
UpdatedAt: "updatedAt",
|
||||
}
|
||||
FN.ESVideo = TagESVideo{
|
||||
Id: "_id",
|
||||
Title: "title",
|
||||
Desc: "desc",
|
||||
Status: "status",
|
||||
AddedTime: "addedTime",
|
||||
MediaType: "mediaType",
|
||||
CreatorName: "creatorName",
|
||||
Keyworlds: "keyworlds",
|
||||
Remark: "remark",
|
||||
IsHot: "isHot",
|
||||
Sort: "sort",
|
||||
UpdatedAt: "updatedAt",
|
||||
CreatedAt: "createdAt",
|
||||
WatchTimes: "watchTimes",
|
||||
ShowTimes: "showTimes",
|
||||
Comments: "comments",
|
||||
IssuedAt: "issuedAt",
|
||||
IssuedBrand: "issuedBrand",
|
||||
Bango: "bango",
|
||||
Real: struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}{WatchTimes: "watchTimes", ShowTimes: "showTimes", Comments: "comments", WeekWatchs: "weekWatchs", MonthWatchs: "monthWatchs", TodayWatchs: "todayWatchs"},
|
||||
}
|
||||
|
||||
FN.ESPlaylet = TagESPlaylet{
|
||||
Id: "id",
|
||||
Status: "status",
|
||||
IsFeatured: "isFeatured",
|
||||
IsRecommend: "isRecommend",
|
||||
ShowOnBanner: "showOnBanner",
|
||||
Banner: "banner",
|
||||
OnlineAt: "onlineAt",
|
||||
CategoryIds: "categoryIds",
|
||||
CategoryNames: "categoryNames",
|
||||
ThemeIds: "themeIds",
|
||||
ThemeNames: "themeNames",
|
||||
Title: "title",
|
||||
Desc: "desc",
|
||||
Anchor: "anchor",
|
||||
Cover: "cover",
|
||||
TagIds: "tagIds",
|
||||
TagNames: "tagNames",
|
||||
TotalEpisode: "totalEpisode",
|
||||
UpdateStatus: "updateStatus",
|
||||
CountBrowse: "countBrowse",
|
||||
HeatValue: "heatValue",
|
||||
CountCollect: "countCollect",
|
||||
CountLike: "countLike",
|
||||
SeoInfo: "seoInfo",
|
||||
UpdatedAt: "updatedAt",
|
||||
CreatedAt: "createdAt",
|
||||
}
|
||||
|
||||
FN.ESActress = TagESActress{
|
||||
Id: "_id",
|
||||
Alias: "alias",
|
||||
Avatar: "avatar",
|
||||
Meas: "meas",
|
||||
Office: "office",
|
||||
DebutDate: "debutDate",
|
||||
BornDate: "bornDate",
|
||||
Region: "region",
|
||||
Score: "score",
|
||||
Works: "works",
|
||||
HotValue: "hotValue",
|
||||
Real: struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}{WatchTimes: "watchTimes", ShowTimes: "showTimes", Comments: "comments", WeekWatchs: "weekWatchs", MonthWatchs: "monthWatchs", TodayWatchs: "todayWatchs"},
|
||||
Desc: "desc",
|
||||
Status: "status",
|
||||
CreatedAt: "createdAt",
|
||||
UpdatedAt: "updatedAt",
|
||||
Rank: "rank",
|
||||
}
|
||||
|
||||
TN.ESRecord = "es_record"
|
||||
TN.ESVideo = "es_video"
|
||||
TN.ESPlaylet = "es_playlet"
|
||||
TN.ESActress = "es_actress"
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
//go:generate gen_bson_tag -m esmod
|
||||
//esmod essearch数据结构定义
|
||||
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
"videoweb/pub/models/actress"
|
||||
"videoweb/pub/models/playletmod"
|
||||
"videoweb/pub/models/videoinformationmod"
|
||||
"videoweb/pub/pubdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type ESTimestamp struct {
|
||||
T uint32 `json:"t" bson:"t"`
|
||||
I uint32 `json:"i" bson:"i"`
|
||||
}
|
||||
|
||||
func (v *ESTimestamp) IsZero() bool {
|
||||
if v == nil {
|
||||
return true
|
||||
}
|
||||
return v.T == 0 && v.I == 0
|
||||
}
|
||||
|
||||
// ESOperator es操作记录
|
||||
// @table:es_record
|
||||
type ESRecord struct {
|
||||
Id primitive.ObjectID `json:"id" bson:"_id"`
|
||||
EsIndex string `json:"esIndex" bson:"esIndex"` //es索引名称
|
||||
Timestamp ESTimestamp `json:"timestamp" bson:"timestamp"` //操作时间
|
||||
RecordTime time.Time `json:"recordTime" bson:"recordTime"` // 操作记录时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //更新时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
|
||||
}
|
||||
|
||||
type ESRecordList []*ESRecord
|
||||
|
||||
// ESVideo es中存储的media数据
|
||||
// @table:es_video
|
||||
type ESVideo struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
Title string `json:"title" bson:"title"` // 帖子标题
|
||||
MediaType videoinformationmod.MediaType `json:"mediaType" bson:"mediaType"` // 资源类型
|
||||
AddedTime time.Time `json:"addedTime" bson:"addedTime"` // 帖子上架时间
|
||||
CreatorName string `json:"creatorName" bson:"creatorName"` // 作者名称
|
||||
Keyworlds string `bson:"keyworlds,omitempty" json:"keyworlds"` // 关键字
|
||||
Desc string `bson:"desc,omitempty" json:"desc"` // 详细描述
|
||||
Remark string `bson:"remark,omitempty" json:"remark"` // 备注
|
||||
Status pubdef.InformationStatus `json:"status" bson:"status"` // 帖子上架状态
|
||||
IsHot bool `json:"isHot" bson:"isHot"` // 是否热门
|
||||
Sort int64 `json:"sort" bson:"sort"` // 排序
|
||||
WatchTimes int64 `json:"watchTimes" bson:"watchTimes"` // 观看次数
|
||||
ShowTimes int64 `json:"showTimes" bson:"showTimes"` // 展示次数
|
||||
Comments int64 `json:"comments" bson:"comments"` // 评论条数
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
Keyworld []string `bson:"keyworld,omitempty" json:"keyworld"` // 关键字
|
||||
CreatorId int64 `json:"creatorId" bson:"creatorId"` // 作者Id
|
||||
FirstTag string `bson:"firstTag,omitempty" json:"firstTag"` // 一级标签
|
||||
SecondTags []string `bson:"secondTags,omitempty" json:"secondTags"` // 二级标签标签
|
||||
CoverImg string `bson:"coverImg,omitempty" json:"coverImg"` // 封面
|
||||
Nodes []videoinformationmod.Node `json:"nodes" bson:"nodes"` // 节点
|
||||
Video videoinformationmod.VideoInfo `json:"video" bson:"video"` // 视频
|
||||
Tags []int64 `json:"tags" bson:"tags"` // 标签
|
||||
Real pubdef.Flow `json:"real" bson:"real"` // 真实流量
|
||||
VideoCount int64 `json:"videoCount" bson:"videoCount"` // 合集视频数量
|
||||
IssuedAt time.Time `json:"issuedAt" bson:"issuedAt"` // 发行时间
|
||||
IssuedBrand string `json:"issuedBrand" bson:"issuedBrand"` // 发行商
|
||||
Bango string `bson:"bango,omitempty" json:"bango"` // 番号,唯一
|
||||
}
|
||||
|
||||
type ESVideoList []*ESVideo
|
||||
type ESTotal struct {
|
||||
Value int64 `json:"value"`
|
||||
}
|
||||
|
||||
type ESVideoSource struct {
|
||||
ID string `json:"_id"`
|
||||
Score float32 `json:"_score"`
|
||||
Source *ESVideo `json:"_source"`
|
||||
}
|
||||
|
||||
// ESVideoHits search media hits
|
||||
type ESVideoHits struct {
|
||||
Total ESTotal `json:"total"`
|
||||
Hits []*ESVideoSource `json:"hits"`
|
||||
}
|
||||
|
||||
// ESPlaylet es中存储的短剧搜索数据
|
||||
// @table:es_playlet
|
||||
type ESPlaylet struct {
|
||||
Id int64 `json:"id" bson:"id"` // 短剧ID
|
||||
Status playletmod.Status `json:"status" bson:"status"` // 状态: 0下架 1上架
|
||||
IsFeatured bool `json:"isFeatured" bson:"isFeatured"` // 是否爆剧
|
||||
IsRecommend bool `json:"isRecommend" bson:"isRecommend"` // 是否推荐
|
||||
ShowOnBanner bool `json:"showOnBanner" bson:"showOnBanner"` // 是否显示在首页banner
|
||||
Banner string `json:"banner" bson:"banner"` // banner图
|
||||
OnlineAt time.Time `json:"onlineAt" bson:"onlineAt"` // 上架时间
|
||||
CategoryIds []int64 `json:"categoryIds" bson:"categoryIds"` // 分类ID集合
|
||||
CategoryNames []string `json:"categoryNames" bson:"categoryNames"` // 分类名称集合
|
||||
ThemeIds []int64 `json:"themeIds" bson:"themeIds"` // 题材ID集合
|
||||
ThemeNames []string `json:"themeNames" bson:"themeNames"` // 题材名称集合
|
||||
Title string `json:"title" bson:"title"` // 剧名
|
||||
Desc string `json:"desc" bson:"desc"` // 简介
|
||||
Anchor string `json:"anchor" bson:"anchor"` // 作者/演员
|
||||
Cover string `json:"cover" bson:"cover"` // 封面
|
||||
TagIds []int64 `json:"tagIds" bson:"tagIds"` // 标签ID集合
|
||||
TagNames []string `json:"tagNames" bson:"tagNames"` // 标签名称集合
|
||||
TotalEpisode int64 `json:"totalEpisode" bson:"totalEpisode"` // 总集数
|
||||
UpdateStatus int `json:"updateStatus" bson:"updateStatus"` // 更新状态 1-连载中 2-已完结
|
||||
CountBrowse int64 `json:"countBrowse" bson:"countBrowse"` // 观看量
|
||||
HeatValue int64 `json:"heatValue" bson:"heatValue"` // 热度值
|
||||
CountCollect int64 `json:"countCollect" bson:"countCollect"` // 收藏数
|
||||
CountLike int64 `json:"countLike" bson:"countLike"` // 展示点赞数
|
||||
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type ESPlayletList []*ESPlaylet
|
||||
|
||||
type ESPlayletSource struct {
|
||||
ID string `json:"_id"`
|
||||
Score float32 `json:"_score"`
|
||||
Source *ESPlaylet `json:"_source"`
|
||||
}
|
||||
|
||||
// ESPlayletHits search playlet hits
|
||||
type ESPlayletHits struct {
|
||||
Total ESTotal `json:"total"`
|
||||
Hits []*ESPlayletSource `json:"hits"`
|
||||
}
|
||||
|
||||
// ESActress es中存储的actress数据
|
||||
// @table:es_actress
|
||||
type ESActress struct {
|
||||
Id int64 `json:"id" bson:"_id"` // Id
|
||||
Alias string `bson:"alias" json:"alias"` // 别名
|
||||
Avatar string `bson:"avatar" json:"avatar"` // 头像
|
||||
Meas actress.Meas `bson:"meas" json:"meas"` // 三围
|
||||
Desc string `bson:"desc" json:"desc"` // 详细描述
|
||||
Office string `json:"office" bson:"office"` // 事务所
|
||||
DebutDate time.Time `bson:"debutDate" json:"debutDate" ` // 出道日期
|
||||
BornDate time.Time `bson:"bornDate" json:"bornDate"` // 出生日期
|
||||
Region string `json:"region" bson:"region"` // 地区/国家
|
||||
Score string `json:"score" bson:"score"` // 评分
|
||||
Works int64 `json:"works" bson:"works"` // 作品数
|
||||
HotValue int64 `json:"hotValue" bson:"hotValue"` // 热度值
|
||||
Real pubdef.Flow `json:"real" bson:"real"` // 真实流量
|
||||
Status bool `json:"status" bson:"status"` // 状态
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
TranslationCategoryId int64 `bson:"translationCategoryId" json:"translationCategoryId"` // 关联导航分类id
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序
|
||||
}
|
||||
|
||||
type ESActressList []*ESActress
|
||||
|
||||
type ESActressSource struct {
|
||||
ID string `json:"_id"`
|
||||
Score float32 `json:"_score"`
|
||||
Source *ESActress `json:"_source"`
|
||||
}
|
||||
|
||||
// ESActressHits search media hits
|
||||
type ESActressHits struct {
|
||||
Total ESTotal `json:"total"`
|
||||
Hits []*ESActressSource `json:"hits"`
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/esmanager"
|
||||
"videoweb/pub/models/videoinformationmod"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
// SearchVideo 根据关键字搜索媒体
|
||||
func SearchVideo(content string, from int64, size int64, sort string, isAv bool) (int64, []*videoinformationmod.VideoInformation, *srvdef.SrvErr) {
|
||||
fields := []string{FN.ESVideo.Title, FN.ESVideo.Bango, FN.ESVideo.IssuedBrand, FN.ESVideo.Keyworlds, FN.ESVideo.Desc}
|
||||
mediaType := videoinformationmod.MediaType_Video
|
||||
if isAv {
|
||||
mediaType = videoinformationmod.MediaType_AV
|
||||
}
|
||||
must := esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields},
|
||||
},
|
||||
{"term": esmanager.M{FN.ESVideo.Status: pubdef.InformationStatusVerifyOK}},
|
||||
{"term": esmanager.M{FN.ESVideo.MediaType: mediaType}},
|
||||
},
|
||||
},
|
||||
}
|
||||
switch sort {
|
||||
case string(proto.SearchSortTypeHot):
|
||||
must = esmanager.M{
|
||||
"function_score": esmanager.M{
|
||||
"query": esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESVideo.Status: pubdef.InformationStatusVerifyOK}},
|
||||
{"term": esmanager.M{FN.ESVideo.MediaType: mediaType}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"functions": esmanager.A{
|
||||
esmanager.M{
|
||||
"field_value_factor": esmanager.M{
|
||||
"field": FN.ESVideo.WatchTimes,
|
||||
"factor": 1.0,
|
||||
"modifier": "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
"score_mode": "sum",
|
||||
"boost_mode": "multiply",
|
||||
},
|
||||
}
|
||||
case string(proto.SearchSortTypeNew):
|
||||
must = esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields},
|
||||
},
|
||||
{"term": esmanager.M{FN.ESVideo.Status: pubdef.InformationStatusVerifyOK}},
|
||||
{"term": esmanager.M{FN.ESVideo.MediaType: mediaType}},
|
||||
},
|
||||
"should": esmanager.A{
|
||||
{"range": esmanager.M{FN.ESVideo.AddedTime: esmanager.M{"gte": "now-30d/d", "boost": 2.0}}}, //7天内提升4倍权重
|
||||
{"range": esmanager.M{FN.ESVideo.AddedTime: esmanager.M{"gte": "now-180d/d", "boost": 1.5}}}, // 30天内提升3倍权重
|
||||
{"range": esmanager.M{FN.ESVideo.AddedTime: esmanager.M{"gte": "now-365d/d", "boost": 1.1}}}, // 90天内提升1.5倍权重
|
||||
},
|
||||
"minimum_should_match": 0, // 允许不匹配任何should条件
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
query := esmanager.M{
|
||||
"query": must,
|
||||
"sort": esmanager.A{
|
||||
esmanager.M{"_score": esmanager.M{"order": "desc"}},
|
||||
},
|
||||
"from": from,
|
||||
"size": size,
|
||||
}
|
||||
|
||||
log.Info("(esmod:SearchVideo) 执行搜索",
|
||||
log.Any("index", videoIndex),
|
||||
log.Any("keywords", content),
|
||||
log.Any("sort", sort),
|
||||
log.Any("from", from),
|
||||
log.Any("size", size))
|
||||
videos := &ESVideoHits{}
|
||||
err := esmanager.Instance.Search(videoIndex, videos, query)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf(
|
||||
"(esmod:SearchVideo) Search failed! err:%+v:", err)
|
||||
log.Warn(info,
|
||||
log.Any("keywords", content),
|
||||
log.Any("from", from),
|
||||
log.Any("size", size))
|
||||
return 0, nil, srvdef.New(srvdef.ErrElsOperError, "", "")
|
||||
}
|
||||
total := int64(0)
|
||||
rslData := make([]*videoinformationmod.VideoInformation, 0)
|
||||
if videos != nil && videos.Hits != nil && len(videos.Hits) > 0 {
|
||||
total = videos.Total.Value
|
||||
for _, video := range videos.Hits {
|
||||
rslData = append(rslData, EsVideoInfoToData(video.Source))
|
||||
}
|
||||
}
|
||||
log.Info("(esmod:SearchVideo) 搜索完成",
|
||||
log.Any("index", videoIndex),
|
||||
log.Any("keywords", content),
|
||||
log.Any("total", total),
|
||||
log.Any("hits", len(rslData)))
|
||||
return total, rslData, nil
|
||||
}
|
||||
|
||||
func EsVideoInfoToData(esInfo *ESVideo) *videoinformationmod.VideoInformation {
|
||||
info := &videoinformationmod.VideoInformation{
|
||||
Id: esInfo.Id,
|
||||
Title: esInfo.Title,
|
||||
MediaType: esInfo.MediaType,
|
||||
AddedTime: esInfo.AddedTime,
|
||||
CreatorId: esInfo.CreatorId,
|
||||
CreatorName: esInfo.CreatorName,
|
||||
Keyworld: esInfo.Keyworld,
|
||||
FirstTag: esInfo.FirstTag,
|
||||
SecondTags: esInfo.SecondTags,
|
||||
CoverImg: esInfo.CoverImg,
|
||||
Desc: esInfo.Desc,
|
||||
Remark: esInfo.Remark,
|
||||
Nodes: esInfo.Nodes,
|
||||
Status: esInfo.Status,
|
||||
Video: esInfo.Video,
|
||||
Tags: esInfo.Tags,
|
||||
IsHot: esInfo.IsHot,
|
||||
Sort: esInfo.Sort,
|
||||
Real: esInfo.Real,
|
||||
VideoCount: esInfo.VideoCount,
|
||||
UpdatedAt: esInfo.UpdatedAt,
|
||||
CreatedAt: esInfo.CreatedAt,
|
||||
}
|
||||
return info
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package eventmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
var db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
db = mongos.Shop.Coll(TN.Event)
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Event.Status, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Event.EventType, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Event.EventId, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Event.Status, Value: 1},
|
||||
{Key: FN.Event.RetryCount, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Event.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(eventmod:Init) Create Event Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package eventmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// InsertOneEvent 插入一个事件
|
||||
func InsertOneEvent(ctx context.Context, event *Event) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, event); err != nil {
|
||||
log.Warn("eventmod:InsertOneEvent db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertManyEvent 批量插入事件
|
||||
func InsertManyEvent(ctx context.Context, events *EventList) *srvdef.SrvErr {
|
||||
if _, err := db.InsertMany(ctx, events); err != nil {
|
||||
log.Warn("eventmod:InsertManyEvent db.InsertMany failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneEvent 删除一个事件
|
||||
func DelOneEvent(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("eventmod:DelOneEvent db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// DelManyEvent 批量删除事件
|
||||
func DelManyEvent(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteMany(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("eventmod:DelManyEvent db.DeleteMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneEvent 查找一个事件
|
||||
func FindOneEvent(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*Event, *srvdef.SrvErr) {
|
||||
var event Event
|
||||
if err := db.FindOneEx(ctx, &event, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("eventmod:FindOneEvent db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &event, nil
|
||||
}
|
||||
|
||||
// FindManyEvent 查找多个事件
|
||||
func FindManyEvent(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (EventList, *srvdef.SrvErr) {
|
||||
data := make(EventList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("eventmod:FindManyEvent db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountEvent 统计事件数量
|
||||
func CountEvent(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("eventmod:CountEvent db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneEvent 更新一个事件
|
||||
func UpdateOneEvent(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("eventmod:UpdateOneEvent db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("eventmod:UpdateOneEvent db.UpdateOne not matched",
|
||||
log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateManyEvent 批量更新事件
|
||||
func UpdateManyEvent(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("eventmod:UpdateManyEvent db.UpdateMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount < 1 {
|
||||
log.Warn("eventmod:UpdateManyEvent db.UpdateMany not matched",
|
||||
log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpsertOneEvent 插入或更新一个事件
|
||||
func UpsertOneEvent(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
opts := options.Update().SetUpsert(true)
|
||||
if _, err := db.UpdateOne(ctx, filter, update, opts); err != nil {
|
||||
log.Warn("eventmod:UpsertOneEvent db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package eventmod
|
||||
|
||||
type TagEvent struct {
|
||||
ID string //
|
||||
CreatedAt string // 创建事件
|
||||
RetryCount string // 重试次数
|
||||
Status string //
|
||||
Data string //
|
||||
EventType string //
|
||||
EventId string //
|
||||
UpdatedAt string // 修改时间
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
Event TagEvent
|
||||
}
|
||||
var TN struct {
|
||||
Event string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.Event.ID = "_id"
|
||||
FN.Event.CreatedAt = "createdAt"
|
||||
FN.Event.RetryCount = "retryCount"
|
||||
FN.Event.Status = "status"
|
||||
FN.Event.Data = "data"
|
||||
FN.Event.EventType = "eventType"
|
||||
FN.Event.EventId = "eventId"
|
||||
FN.Event.UpdatedAt = "updatedAt"
|
||||
TN.Event = "event"
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package eventmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type EventStatus int
|
||||
|
||||
const (
|
||||
Default EventStatus = 0 // 默认状态,等待上报
|
||||
Success EventStatus = 1 // 成功
|
||||
Failure EventStatus = 2 // 失败
|
||||
)
|
||||
|
||||
//go:generate fox mongo --model
|
||||
//go:generate fox mongo --tag
|
||||
//go:generate fox mongo --update
|
||||
|
||||
// @table:event
|
||||
// @title:事件表
|
||||
type Event struct {
|
||||
ID primitive.ObjectID `bson:"_id,omitempty"`
|
||||
EventId string `json:"eventId" bson:"eventId"`
|
||||
EventType string `json:"eventType" bson:"eventType"`
|
||||
Data string `json:"data" bson:"data"`
|
||||
Status EventStatus `json:"status" bson:"status"` //
|
||||
RetryCount int `json:"retryCount" bson:"retryCount"` // 重试次数
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建事件
|
||||
UpdatedAt time.Time `bson:"updatedAt"` // 修改时间
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package eventmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type EventList []*Event
|
||||
type EventUpdate struct {
|
||||
RetryCount *int `json:"retryCount" bson:"retryCount,omitempty"` // 重试次数
|
||||
Status *EventStatus `json:"status" bson:"status,omitempty"` //
|
||||
Data *string `json:"data" bson:"data,omitempty"` //
|
||||
EventType *string `json:"eventType" bson:"eventType,omitempty"` //
|
||||
EventId *string `json:"eventId" bson:"eventId,omitempty"` //
|
||||
UpdatedAt *time.Time `json:"" bson:"updatedAt,omitempty"` // 修改时间
|
||||
}
|
||||
type EventQuery struct {
|
||||
ID *primitive.ObjectID `json:"" bson:"_id,omitempty"` //
|
||||
RetryCount *int `json:"retryCount" bson:"retryCount,omitempty"` // 重试次数
|
||||
Status *EventStatus `json:"status" bson:"status,omitempty"` //
|
||||
Data *string `json:"data" bson:"data,omitempty"` //
|
||||
EventType *string `json:"eventType" bson:"eventType,omitempty"` //
|
||||
EventId *string `json:"eventId" bson:"eventId,omitempty"` //
|
||||
UpdatedAt *time.Time `json:"" bson:"updatedAt,omitempty"` // 修改时间
|
||||
}
|
||||
|
||||
func (query *EventQuery) GetQueryFilter() bson.M {
|
||||
filter := bson.M{}
|
||||
if query.ID != nil {
|
||||
filter[FN.Event.ID] = *query.ID
|
||||
}
|
||||
if query.RetryCount != nil {
|
||||
filter[FN.Event.RetryCount] = *query.RetryCount
|
||||
}
|
||||
if query.Status != nil {
|
||||
filter[FN.Event.Status] = *query.Status
|
||||
}
|
||||
if query.Data != nil {
|
||||
filter[FN.Event.Data] = bson.M{"$regex": primitive.Regex{Pattern: *query.Data, Options: "i"}}
|
||||
}
|
||||
if query.EventType != nil {
|
||||
filter[FN.Event.EventType] = bson.M{"$regex": primitive.Regex{Pattern: *query.EventType, Options: "i"}}
|
||||
}
|
||||
if query.EventId != nil {
|
||||
filter[FN.Event.EventId] = bson.M{"$regex": primitive.Regex{Pattern: *query.EventId, Options: "i"}}
|
||||
}
|
||||
if query.UpdatedAt != nil {
|
||||
filter[FN.Event.UpdatedAt] = *query.UpdatedAt
|
||||
}
|
||||
return filter
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package homebannermod
|
||||
|
||||
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 初始化 home_banner 集合和常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.HomeBanner)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.HomeBanner.Status, Value: 1},
|
||||
{Key: FN.HomeBanner.UpdatedAt, Value: -1},
|
||||
{Key: FN.HomeBanner.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.HomeBanner.Name, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.HomeBanner.CreatedAt, Value: -1},
|
||||
{Key: FN.HomeBanner.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.HomeBanner.Status, Value: 1},
|
||||
{Key: FN.HomeBanner.CreatedAt, Value: -1},
|
||||
{Key: FN.HomeBanner.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.HomeBanner.Status, Value: 1},
|
||||
{Key: FN.HomeBanner.Rank, Value: -1},
|
||||
{Key: FN.HomeBanner.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(homebannermod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOneHomeBanner 插入一条首页 banner 数据
|
||||
func InsertOneHomeBanner(ctx context.Context, doc *HomeBanner) *srvdef.SrvErr {
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.HomeBanner.Get()
|
||||
}
|
||||
now := time.Now()
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
doc.UpdatedAt = now
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("homebannermod:InsertOneHomeBanner failed", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneHomeBanner 删除一条首页 banner 数据
|
||||
func DelOneHomeBanner(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("homebannermod:DelOneHomeBanner failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneHomeBanner 查询一条首页 banner 数据
|
||||
func FindOneHomeBanner(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*HomeBanner, *srvdef.SrvErr) {
|
||||
var doc HomeBanner
|
||||
if err := coll.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("homebannermod:FindOneHomeBanner failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyHomeBanner 按条件查询多条首页 banner 数据
|
||||
func FindManyHomeBanner(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (HomeBannerList, *srvdef.SrvErr) {
|
||||
data := make(HomeBannerList, 0)
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("homebannermod:FindManyHomeBanner failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountHomeBanner 统计满足条件的首页 banner 数量
|
||||
func CountHomeBanner(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter, opts...)
|
||||
if err != nil {
|
||||
log.Warn("homebannermod:CountHomeBanner failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneHomeBanner 更新一条首页 banner 数据
|
||||
func UpdateOneHomeBanner(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("homebannermod:UpdateOneHomeBanner failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package homebannermod
|
||||
|
||||
// TagHomeBanner 保存 home_banner 集合字段名
|
||||
type TagHomeBanner struct {
|
||||
Id string
|
||||
Name string
|
||||
Image string
|
||||
VerticalImage string
|
||||
Url string
|
||||
Rank string
|
||||
Status string
|
||||
CreatedById string
|
||||
CreatedByName string
|
||||
UpdatedByName string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
HomeBanner TagHomeBanner
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
HomeBanner string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.HomeBanner.Id = "_id"
|
||||
FN.HomeBanner.Name = "name"
|
||||
FN.HomeBanner.Image = "image"
|
||||
FN.HomeBanner.VerticalImage = "verticalImage"
|
||||
FN.HomeBanner.Url = "url"
|
||||
FN.HomeBanner.Rank = "rank"
|
||||
FN.HomeBanner.Status = "status"
|
||||
FN.HomeBanner.CreatedById = "createdById"
|
||||
FN.HomeBanner.CreatedByName = "createdByName"
|
||||
FN.HomeBanner.UpdatedByName = "updatedByName"
|
||||
FN.HomeBanner.CreatedAt = "createdAt"
|
||||
FN.HomeBanner.UpdatedAt = "updatedAt"
|
||||
TN.HomeBanner = "home_banner"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package homebannermod
|
||||
|
||||
import "time"
|
||||
|
||||
// HomeBanner @table: home_banner
|
||||
//
|
||||
// HomeBanner 首页 banner 配置集合模型
|
||||
type HomeBanner struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"` // ID
|
||||
Name string `json:"name" bson:"name"` // 名称
|
||||
Image string `json:"image" bson:"image"` // 图片
|
||||
VerticalImage string `json:"verticalImage" bson:"verticalImage"` // 竖版图片
|
||||
Url string `json:"url" bson:"url"` // URL
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序
|
||||
Status bool `json:"status" bson:"status"` // 状态 true-启用 false-停用
|
||||
CreatedById int64 `json:"createdById" bson:"createdById"` // 创建人ID
|
||||
CreatedByName string `json:"createdByName" bson:"createdByName"` // 创建人名称
|
||||
UpdatedByName string `json:"updatedByName" bson:"updatedByName"` // 修改人名称
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
}
|
||||
|
||||
// HomeBannerList 首页 banner 列表
|
||||
type HomeBannerList []*HomeBanner
|
||||
@@ -0,0 +1,101 @@
|
||||
package hotnavmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
db = mongos.Shop.Coll(TN.HotNav)
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.HotNav.Sort, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.HotNav.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(hotnavmod:Init) Create HotNav Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
func InsertOneHotNav(ctx context.Context, doc *HotNav) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("hotnavmod:InsertOneHotNav db.InsertOne failed",
|
||||
log.E(err), log.Any("doc", doc))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DelOneHotNav(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("hotnavmod:DelOneHotNav db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func FindOneHotNav(ctx context.Context, filter bson.M) (*HotNav, *srvdef.SrvErr) {
|
||||
var doc HotNav
|
||||
if err := db.FindOneEx(ctx, &doc, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("hotnavmod:FindOneHotNav db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
func FindManyHotNav(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (HotNavList, *srvdef.SrvErr) {
|
||||
data := make(HotNavList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("hotnavmod:FindManyHotNav db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func CountHotNav(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("hotnavmod:CountHotNav db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func UpdateOneHotNav(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("hotnavmod:UpdateOneHotNav db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("hotnavmod:UpdateOneHotNav not matched",
|
||||
log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package hotnavmod
|
||||
|
||||
type TagHotNav struct {
|
||||
CreatedAt string
|
||||
Icon string
|
||||
Id string
|
||||
Intro string
|
||||
Sort string
|
||||
Status string
|
||||
Title string
|
||||
UpdatedAt string
|
||||
Url string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
HotNav TagHotNav
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
HotNav string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.HotNav.CreatedAt = "createdAt"
|
||||
FN.HotNav.Icon = "icon"
|
||||
FN.HotNav.Id = "_id"
|
||||
FN.HotNav.Intro = "intro"
|
||||
FN.HotNav.Sort = "sort"
|
||||
FN.HotNav.Status = "status"
|
||||
FN.HotNav.Title = "title"
|
||||
FN.HotNav.UpdatedAt = "updatedAt"
|
||||
FN.HotNav.Url = "url"
|
||||
TN.HotNav = "hot_nav"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package hotnavmod
|
||||
|
||||
import "time"
|
||||
|
||||
// HotNav 热门导航配置
|
||||
// @table:hot_nav
|
||||
type HotNav struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"` // ID
|
||||
Title string `json:"title" bson:"title"` // 标题
|
||||
Intro string `json:"intro" bson:"intro"` // 介绍
|
||||
Url string `json:"url" bson:"url"` // 链接
|
||||
Icon string `json:"icon" bson:"icon"` // 图标
|
||||
Sort int64 `json:"sort" bson:"sort"` // 排序
|
||||
Status bool `json:"status" bson:"status"` // 是否启用
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
}
|
||||
|
||||
type HotNavList []*HotNav
|
||||
@@ -0,0 +1,109 @@
|
||||
package ipblackmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
// 获取数据库表
|
||||
db = mongos.Shop.Coll(TN.IPBlackModel)
|
||||
// 初始化索引
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.IPBlackModel.Ip, Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(IPBlackModel:InitIPBlackModel) Create IPBlackModel Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// CountIPBlackModel 统计活动数量
|
||||
func CountIPBlackModel(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("IPBlackModelmod:CountIPBlackModel db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// InsertOneIPBlackModel 插入一条活动
|
||||
func InsertOneIPBlackModel(ctx context.Context, IPBlackModel *IPBlackModel) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, IPBlackModel); err != nil {
|
||||
log.Info("IPBlackModelmod:InsertOneIPBlackModel db.InsertOne failed",
|
||||
log.E(err), log.Any("IPBlackModel", IPBlackModel))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneIPBlackModel 删除一个活动
|
||||
func DelOneIPBlackModel(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("IPBlackModelmod:DelOneIPBlackModel db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneIPBlackModel 更新一个IPBlackModel
|
||||
func UpdateOneIPBlackModel(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("IPBlackModelmod:UpdateOneIPBlackModel db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("IPBlackModelmod:UpdateOneIPBlackModel db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ObjectNotExist, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyIPBlackModel 查找一批活动数据
|
||||
func FindManyIPBlackModel(ctx context.Context, filter bson.M,
|
||||
opts ...*options.FindOptions) (IPBlackModelList, *srvdef.SrvErr) {
|
||||
data := make(IPBlackModelList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("IPBlackModelmod:FindManyAcivities db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// FindOneIPBlackModel 查找一个媒体
|
||||
func FindOneIPBlackModel(ctx context.Context, filter bson.M) (
|
||||
*IPBlackModel, *srvdef.SrvErr) {
|
||||
var IPBlackModel IPBlackModel
|
||||
if err := db.FindOneEx(ctx, &IPBlackModel, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("IPBlackModel:FindOneIPBlackModel db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ObjectDayStatDoesNotExist, "", "")
|
||||
}
|
||||
return &IPBlackModel, nil
|
||||
}
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
package ipblackmod
|
||||
|
||||
type TagIPBlackModel struct {
|
||||
CreatedAt string
|
||||
ID string
|
||||
Ip string
|
||||
Desc string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
IPBlackModel TagIPBlackModel
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
IPBlackModel string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.IPBlackModel.CreatedAt = "createdAt"
|
||||
FN.IPBlackModel.ID = "_id"
|
||||
FN.IPBlackModel.Ip = "ip"
|
||||
FN.IPBlackModel.UpdatedAt = "updatedAt"
|
||||
FN.IPBlackModel.Desc = "desc"
|
||||
TN.IPBlackModel = "ip_black"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package ipblackmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 资源同步
|
||||
// @table:ip_black
|
||||
type IPBlackModel struct {
|
||||
ID primitive.ObjectID `bson:"_id,omitempty"`
|
||||
Ip string `json:"ip" bson:"ip"`
|
||||
Desc string `json:"desc" bson:"desc"` // 备注
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
}
|
||||
type IPBlackModelList []*IPBlackModel
|
||||
@@ -0,0 +1,62 @@
|
||||
package ipdailystatmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
db = mongos.Shop.Coll(TN.IpDailyStat)
|
||||
|
||||
// 唯一索引:(appId, date)
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.IpDailyStat.AppId, Value: 1},
|
||||
{Key: FN.IpDailyStat.Date, Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
}
|
||||
_, _ = db.CreateIndex(ctx, indexes)
|
||||
}
|
||||
|
||||
// UpsertCount 写入或更新指定 appId 当天的 IP 去重数
|
||||
func UpsertCount(ctx context.Context, appId int64, date string, count int64) error {
|
||||
filter := bson.M{
|
||||
FN.IpDailyStat.AppId: appId,
|
||||
FN.IpDailyStat.Date: date,
|
||||
}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
FN.IpDailyStat.Count: count,
|
||||
FN.IpDailyStat.UpdatedAt: time.Now(),
|
||||
},
|
||||
}
|
||||
_, err := db.UpsertOne(ctx, filter, update)
|
||||
return err
|
||||
}
|
||||
|
||||
// FindCount 查询指定 appId 在某天的 IP 去重数,未找到返回 0
|
||||
func FindCount(ctx context.Context, appId int64, date string) (int64, error) {
|
||||
filter := bson.M{
|
||||
FN.IpDailyStat.AppId: appId,
|
||||
FN.IpDailyStat.Date: date,
|
||||
}
|
||||
var stat IpDailyStat
|
||||
err := db.FindOneEx(ctx, &stat, filter)
|
||||
if err != nil {
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return 0, nil
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
return stat.Count, nil
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package ipdailystatmod
|
||||
|
||||
type tagIpDailyStat struct {
|
||||
AppId string
|
||||
Date string
|
||||
Count string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
IpDailyStat tagIpDailyStat
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
IpDailyStat string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.IpDailyStat.AppId = "appId"
|
||||
FN.IpDailyStat.Date = "date"
|
||||
FN.IpDailyStat.Count = "count"
|
||||
FN.IpDailyStat.UpdatedAt = "updatedAt"
|
||||
|
||||
TN.IpDailyStat = "ip_daily_stat"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package ipdailystatmod
|
||||
|
||||
import "time"
|
||||
|
||||
// IpDailyStat 每日访客 IP 去重统计
|
||||
// app 端写入,web 端读取,通过共享 MongoDB 跨进程共享数据。
|
||||
// @table:ip_daily_stat
|
||||
type IpDailyStat struct {
|
||||
AppId int64 `bson:"appId"` // 站点 ID
|
||||
Date string `bson:"date"` // 日期,格式 "20060102"
|
||||
Count int64 `bson:"count"` // 当日去重 IP 数
|
||||
UpdatedAt time.Time `bson:"updatedAt"` // 最后同步时间
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package m3u8requestlogmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
var db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
db = mongos.Shop.Coll(TN.M3U8RequestLog)
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.M3U8RequestLog.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.M3U8RequestLog.VideoId, Value: 1},
|
||||
{Key: FN.M3U8RequestLog.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.M3U8RequestLog.M3U8Path, Value: 1},
|
||||
{Key: FN.M3U8RequestLog.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.M3U8RequestLog.ClientIP, Value: 1},
|
||||
{Key: FN.M3U8RequestLog.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.M3U8RequestLog.Host, Value: 1},
|
||||
{Key: FN.M3U8RequestLog.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.M3U8RequestLog.Status, Value: 1},
|
||||
{Key: FN.M3U8RequestLog.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.M3U8RequestLog.TokenOK, Value: 1},
|
||||
{Key: FN.M3U8RequestLog.PathOK, Value: 1},
|
||||
{Key: FN.M3U8RequestLog.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(m3u8requestlogmod:Init) Create M3U8RequestLog Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
func InsertOneM3U8RequestLog(ctx context.Context, doc *M3U8RequestLog) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("m3u8requestlogmod:InsertOneM3U8RequestLog db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package m3u8requestlogmod
|
||||
|
||||
type TagM3U8RequestLog struct {
|
||||
CDNDomain string
|
||||
CFConnectingIP string
|
||||
ClientIP string
|
||||
CostMs string
|
||||
CreatedAt string
|
||||
Error string
|
||||
Headers string
|
||||
Host string
|
||||
Id string
|
||||
IsOverseas string
|
||||
M3U8Path string
|
||||
PathOK string
|
||||
Query string
|
||||
RawQuery string
|
||||
Referer string
|
||||
RemoteAddr string
|
||||
RequestURI string
|
||||
Status string
|
||||
T string
|
||||
Token string
|
||||
TokenOK string
|
||||
UserAgent string
|
||||
VideoId string
|
||||
XForwardedFor string
|
||||
XRealIP string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
M3U8RequestLog TagM3U8RequestLog
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
M3U8RequestLog string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.M3U8RequestLog.CDNDomain = "cdnDomain"
|
||||
FN.M3U8RequestLog.CFConnectingIP = "cfConnectingIP"
|
||||
FN.M3U8RequestLog.ClientIP = "clientIP"
|
||||
FN.M3U8RequestLog.CostMs = "costMs"
|
||||
FN.M3U8RequestLog.CreatedAt = "createdAt"
|
||||
FN.M3U8RequestLog.Error = "error"
|
||||
FN.M3U8RequestLog.Headers = "headers"
|
||||
FN.M3U8RequestLog.Host = "host"
|
||||
FN.M3U8RequestLog.Id = "_id"
|
||||
FN.M3U8RequestLog.IsOverseas = "isOverseas"
|
||||
FN.M3U8RequestLog.M3U8Path = "m3u8Path"
|
||||
FN.M3U8RequestLog.PathOK = "pathOK"
|
||||
FN.M3U8RequestLog.Query = "query"
|
||||
FN.M3U8RequestLog.RawQuery = "rawQuery"
|
||||
FN.M3U8RequestLog.Referer = "referer"
|
||||
FN.M3U8RequestLog.RemoteAddr = "remoteAddr"
|
||||
FN.M3U8RequestLog.RequestURI = "requestURI"
|
||||
FN.M3U8RequestLog.Status = "status"
|
||||
FN.M3U8RequestLog.T = "t"
|
||||
FN.M3U8RequestLog.Token = "token"
|
||||
FN.M3U8RequestLog.TokenOK = "tokenOK"
|
||||
FN.M3U8RequestLog.UserAgent = "userAgent"
|
||||
FN.M3U8RequestLog.VideoId = "videoId"
|
||||
FN.M3U8RequestLog.XForwardedFor = "xForwardedFor"
|
||||
FN.M3U8RequestLog.XRealIP = "xRealIP"
|
||||
TN.M3U8RequestLog = "m3u8_request_log"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package m3u8requestlogmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// M3U8RequestLog records every HLS playlist request for hotlink analysis.
|
||||
// @table:m3u8_request_log
|
||||
type M3U8RequestLog struct {
|
||||
ID primitive.ObjectID `bson:"_id,omitempty"`
|
||||
CreatedAt time.Time `bson:"createdAt"`
|
||||
Host string `bson:"host"`
|
||||
RequestURI string `bson:"requestURI"`
|
||||
M3U8Path string `bson:"m3u8Path"`
|
||||
RawQuery string `bson:"rawQuery"`
|
||||
Query map[string][]string `bson:"query"`
|
||||
Headers map[string][]string `bson:"headers"`
|
||||
VideoId int64 `bson:"videoId"`
|
||||
T int64 `bson:"t"`
|
||||
Token string `bson:"token"`
|
||||
ClientIP string `bson:"clientIP"`
|
||||
RemoteAddr string `bson:"remoteAddr"`
|
||||
XForwardedFor string `bson:"xForwardedFor"`
|
||||
XRealIP string `bson:"xRealIP"`
|
||||
CFConnectingIP string `bson:"cfConnectingIP"`
|
||||
UserAgent string `bson:"userAgent"`
|
||||
Referer string `bson:"referer"`
|
||||
IsOverseas bool `bson:"isOverseas"`
|
||||
CDNDomain string `bson:"cdnDomain"`
|
||||
TokenOK bool `bson:"tokenOK"`
|
||||
PathOK bool `bson:"pathOK"`
|
||||
Status string `bson:"status"`
|
||||
Error string `bson:"error"`
|
||||
CostMs int64 `bson:"costMs"`
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/models/actress"
|
||||
"videoweb/pub/models/announcementmod"
|
||||
"videoweb/pub/models/cfg"
|
||||
"videoweb/pub/models/commentlikemod"
|
||||
"videoweb/pub/models/commentmod"
|
||||
"videoweb/pub/models/contactusmod"
|
||||
"videoweb/pub/models/contenttagmod"
|
||||
"videoweb/pub/models/detailnavmod"
|
||||
"videoweb/pub/models/esmod"
|
||||
"videoweb/pub/models/eventmod"
|
||||
"videoweb/pub/models/homebannermod"
|
||||
"videoweb/pub/models/hotnavmod"
|
||||
"videoweb/pub/models/ipblackmod"
|
||||
"videoweb/pub/models/ipdailystatmod"
|
||||
"videoweb/pub/models/m3u8requestlogmod"
|
||||
"videoweb/pub/models/mwacc"
|
||||
"videoweb/pub/models/oplog"
|
||||
"videoweb/pub/models/playletbackflowstatmod"
|
||||
"videoweb/pub/models/playletcategorymod"
|
||||
"videoweb/pub/models/playletchaptermod"
|
||||
"videoweb/pub/models/playletfavoritemod"
|
||||
"videoweb/pub/models/playlethomeconfigmod"
|
||||
"videoweb/pub/models/playletlikemod"
|
||||
"videoweb/pub/models/playletmod"
|
||||
"videoweb/pub/models/playlettagmod"
|
||||
"videoweb/pub/models/playletthememod"
|
||||
"videoweb/pub/models/questionnairemod"
|
||||
"videoweb/pub/models/richtextcontentmod"
|
||||
"videoweb/pub/models/seopushmod"
|
||||
"videoweb/pub/models/syncfilemod"
|
||||
"videoweb/pub/models/translationcategorymod"
|
||||
"videoweb/pub/models/translationmod"
|
||||
"videoweb/pub/models/userlogin"
|
||||
"videoweb/pub/models/usermod"
|
||||
"videoweb/pub/models/videocategorymod"
|
||||
"videoweb/pub/models/videocollectionmediamod"
|
||||
"videoweb/pub/models/videocreatermod"
|
||||
"videoweb/pub/models/videofavoritemod"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"videoweb/pub/models/videoinformationmod"
|
||||
"videoweb/pub/models/videolikemod"
|
||||
"videoweb/pub/models/videotagmod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func Init() {
|
||||
log.Info("models init start..")
|
||||
ctx := context.Background()
|
||||
cfg.Init(ctx)
|
||||
mwacc.Init(ctx)
|
||||
oplog.Init(ctx)
|
||||
m3u8requestlogmod.Init(ctx)
|
||||
|
||||
videocategorymod.Init(ctx)
|
||||
videoinformationmod.Init(ctx)
|
||||
videofavoritemod.Init(ctx)
|
||||
videolikemod.Init(ctx)
|
||||
videotagmod.Init(ctx)
|
||||
|
||||
translationcategorymod.Init(ctx)
|
||||
translationmod.Init(ctx)
|
||||
contenttagmod.Init(ctx)
|
||||
playletcategorymod.Init(ctx)
|
||||
playlethomeconfigmod.Init(ctx)
|
||||
playlettagmod.Init(ctx)
|
||||
playletthememod.Init(ctx)
|
||||
playletmod.Init(ctx)
|
||||
playletbackflowstatmod.Init(ctx)
|
||||
playletchaptermod.Init(ctx)
|
||||
playletlikemod.Init(ctx)
|
||||
playletfavoritemod.Init(ctx)
|
||||
initWatchHistory(ctx)
|
||||
videocategorymod.Init(ctx)
|
||||
videocreatermod.Init(ctx)
|
||||
videotagmod.Init(ctx)
|
||||
videoinformationmod.Init(ctx)
|
||||
videocreatermod.Init(ctx)
|
||||
syncfilemod.Init(ctx)
|
||||
seopushmod.Init(ctx)
|
||||
richtextcontentmod.Init(ctx)
|
||||
announcementmod.Init(ctx)
|
||||
commentmod.Init(ctx)
|
||||
commentlikemod.Init(ctx)
|
||||
videocollectionmediamod.Init(ctx)
|
||||
ipblackmod.Init(ctx)
|
||||
esmod.Init(ctx)
|
||||
actress.Init(ctx)
|
||||
contactusmod.Init(ctx)
|
||||
detailnavmod.Init(ctx)
|
||||
hotnavmod.Init(ctx)
|
||||
homebannermod.Init(ctx)
|
||||
eventmod.Init(ctx)
|
||||
usermod.Init(ctx)
|
||||
userlogin.Init(ctx)
|
||||
questionnairemod.Init(ctx)
|
||||
ipdailystatmod.Init(ctx)
|
||||
log.Info("models init end")
|
||||
}
|
||||
|
||||
const (
|
||||
WatchHistoryTypePlaylet int64 = 1
|
||||
WatchHistoryTypeVideo int64 = 2
|
||||
WatchHistoryRetentionDays = 60
|
||||
watchHistoryCollectionName = "watch_history"
|
||||
WatchHistoryCollectionName = watchHistoryCollectionName
|
||||
WatchHistoryUserID = "userId"
|
||||
WatchHistoryDataType = "dataType"
|
||||
WatchHistoryContentID = "contentId"
|
||||
WatchHistoryChapterID = "chapterId"
|
||||
WatchHistoryEpisode = "episode"
|
||||
WatchHistoryCreatedAt = "createdAt"
|
||||
WatchHistoryUpdatedAt = "updatedAt"
|
||||
)
|
||||
|
||||
// WatchHistory 保存当前用户最近观看的内容
|
||||
type WatchHistory struct {
|
||||
UserID int64 `bson:"userId"`
|
||||
DataType int64 `bson:"dataType"`
|
||||
ContentID int64 `bson:"contentId"`
|
||||
ChapterID int64 `bson:"chapterId"`
|
||||
Episode int64 `bson:"episode"`
|
||||
CreatedAt time.Time `bson:"createdAt"`
|
||||
UpdatedAt time.Time `bson:"updatedAt"`
|
||||
}
|
||||
|
||||
var watchHistoryColl *mongos.Collection
|
||||
|
||||
// initWatchHistory 初始化观看历史及 60 天 TTL 索引
|
||||
func initWatchHistory(ctx context.Context) {
|
||||
watchHistoryColl = mongos.Shop.Coll(watchHistoryCollectionName)
|
||||
indexes := []mongo.IndexModel{
|
||||
{Keys: bson.D{{Key: WatchHistoryUserID, Value: 1}, {Key: WatchHistoryDataType, Value: 1}, {Key: WatchHistoryContentID, Value: 1}}, Options: options.Index().SetUnique(true)},
|
||||
{Keys: bson.D{{Key: WatchHistoryUserID, Value: 1}, {Key: WatchHistoryDataType, Value: 1}, {Key: WatchHistoryUpdatedAt, Value: -1}, {Key: "_id", Value: -1}}},
|
||||
{Keys: bson.D{{Key: WatchHistoryUpdatedAt, Value: 1}}, Options: options.Index().SetExpireAfterSeconds(WatchHistoryRetentionDays * 24 * 60 * 60)},
|
||||
}
|
||||
if _, err := watchHistoryColl.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(models:initWatchHistory) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// TouchWatchHistory 从已验证的播放清单刷新历史
|
||||
func TouchWatchHistory(ctx context.Context, item WatchHistory) *srvdef.SrvErr {
|
||||
filter := bson.M{WatchHistoryUserID: item.UserID, WatchHistoryDataType: item.DataType, WatchHistoryContentID: item.ContentID}
|
||||
if item.DataType == WatchHistoryTypePlaylet {
|
||||
sameChapter := bson.M{WatchHistoryUserID: item.UserID, WatchHistoryDataType: item.DataType, WatchHistoryContentID: item.ContentID, WatchHistoryChapterID: item.ChapterID}
|
||||
result, err := watchHistoryColl.UpdateOne(ctx, sameChapter, bson.M{"$set": bson.M{WatchHistoryUpdatedAt: item.UpdatedAt, WatchHistoryEpisode: item.Episode}})
|
||||
if err != nil {
|
||||
log.Warn("TouchWatchHistory failed", log.Any("filter", sameChapter), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount > 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
update := bson.M{
|
||||
"$set": bson.M{WatchHistoryChapterID: item.ChapterID, WatchHistoryEpisode: item.Episode, WatchHistoryUpdatedAt: item.UpdatedAt},
|
||||
"$setOnInsert": bson.M{WatchHistoryUserID: item.UserID, WatchHistoryDataType: item.DataType, WatchHistoryContentID: item.ContentID, WatchHistoryCreatedAt: item.CreatedAt},
|
||||
}
|
||||
if _, err := watchHistoryColl.UpdateOne(ctx, filter, update, options.Update().SetUpsert(true)); err != nil {
|
||||
if mongo.IsDuplicateKeyError(err) {
|
||||
_, err = watchHistoryColl.UpdateOne(ctx, filter, bson.M{"$set": update["$set"]})
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
log.Warn("TouchWatchHistory failed", log.Any("filter", filter), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AggregateWatchHistory 聚合查询观看历史
|
||||
func AggregateWatchHistory(ctx context.Context, bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := watchHistoryColl.Aggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("AggregateWatchHistory failed", log.Any("pipeline", pipeline), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteWatchHistory 删除当前用户指定类型的观看历史
|
||||
func DeleteWatchHistory(ctx context.Context, userID, dataType int64) (int64, *srvdef.SrvErr) {
|
||||
filter := bson.M{WatchHistoryUserID: userID, WatchHistoryDataType: dataType}
|
||||
count, err := watchHistoryColl.DeleteMany(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("DeleteWatchHistory failed", log.Any("filter", filter), log.E(err))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package mwacc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"videoweb/pub/common/errors"
|
||||
sErr "videoweb/pub/common/errors"
|
||||
"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/options"
|
||||
)
|
||||
|
||||
// 过滤查询数量
|
||||
func AccCountByFilter(ctx context.Context, filters primitive.M, opts ...*options.CountOptions) (c int64, err error) {
|
||||
c, err = mwAccColl.Count(ctx, filters)
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤查询账号
|
||||
func FindOneAccByFilter(ctx context.Context, filters primitive.M, opts ...*options.FindOneOptions) (*MwAcc, error) {
|
||||
var res MwAcc
|
||||
err := mwAccColl.FindOne(ctx, &res, filters, opts...)
|
||||
if err != nil {
|
||||
log.Error("mwacc FindOneAccByFilter err", log.Any("filters", filters), log.E(err))
|
||||
}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// 过滤更新
|
||||
func UpOneAccByFilter(ctx context.Context, query primitive.M, update primitive.M) (err error) {
|
||||
_, err = mwAccColl.UpdateOne(ctx, query, primitive.M{"$set": update})
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤删除角色
|
||||
func DelAccByFilter(ctx context.Context, filters primitive.M) (err error) {
|
||||
_, err = mwAccColl.DeleteOne(ctx, filters)
|
||||
if err != nil {
|
||||
log.Error("mwacc DelAccByFilter err", log.Any("filters", filters), log.E(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// // 更新最后登录时间
|
||||
// func UpAccLastTimeById(ctx context.Context, id int64) (*mongo.UpdateResult, error) {
|
||||
// ret, err := mwAccColl.UpdateOne(ctx, primitive.M{FN.MwAcc.Id: id}, primitive.M{"$set": primitive.M{FN.MwAcc.LastTime: time.Now()}})
|
||||
// if err != nil {
|
||||
// log.Error("mvacc UpLastTimeById err", log.Any(FN.MwAcc.Id, id), log.E(err))
|
||||
// }
|
||||
// return ret, err
|
||||
// }
|
||||
|
||||
// 绑定二维码
|
||||
func BindAccQurl(ctx context.Context, acc string) (ok bool, err error) {
|
||||
|
||||
res, dataErr := FindOneAccByFilter(ctx, primitive.M{
|
||||
FN.MwAcc.Acc: acc,
|
||||
})
|
||||
|
||||
if dataErr != nil || res.Id == 0 {
|
||||
err = sErr.MakeWithMsg(sErr.Logo, "用户不存在!")
|
||||
return false, err
|
||||
}
|
||||
|
||||
if res.IsEnb == false {
|
||||
err = sErr.MakeWithMsg(sErr.UserPermission, "用户被禁用!")
|
||||
return false, err
|
||||
}
|
||||
err = UpOneAccByFilter(ctx, primitive.M{
|
||||
FN.MwAcc.Acc: acc,
|
||||
}, primitive.M{
|
||||
FN.MwAcc.IsBase32: true,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
// 插入角色
|
||||
func AccAdd(ctx context.Context, insertReq *AccInsertDoc) (id int64, ok bool, err error) {
|
||||
|
||||
insertReq.Id = int64(mongos.Lid.MwAcc.Get())
|
||||
insertReq.CreatedAt = time.Now()
|
||||
|
||||
_, err = mwAccColl.InsertOne(ctx, insertReq)
|
||||
if err != nil {
|
||||
log.ZapLog.Error(fmt.Sprintf("InsertRole mongo error %v", err))
|
||||
err = errors.MakeWithErr(errors.DBInsert, err)
|
||||
return 0, false, err
|
||||
}
|
||||
return insertReq.Id, true, nil
|
||||
}
|
||||
|
||||
// 获取角色列表
|
||||
func GetAccList(ctx context.Context, search primitive.M, sort []primitive.M) (
|
||||
total int64, data []*AccGetListRec, err error) {
|
||||
|
||||
var countPipe []primitive.M
|
||||
countPipe = append(countPipe, search, bson.M{"$count": "total"})
|
||||
var aggCount AggStatCount
|
||||
err = mwAccColl.ObjectAggregate(ctx, &aggCount, countPipe)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
total = aggCount.Total
|
||||
|
||||
var pip []primitive.M
|
||||
pip = append(pip, search)
|
||||
pip = append(pip, sort...)
|
||||
pip = append(pip,
|
||||
primitive.M{
|
||||
"$lookup": primitive.M{
|
||||
"localField": FN.MwAcc.RoleId,
|
||||
"from": TN.MwRole,
|
||||
"foreignField": FN.MwRole.Id,
|
||||
"as": "roles",
|
||||
},
|
||||
},
|
||||
primitive.M{"$unwind": primitive.M{
|
||||
"path": "$roles",
|
||||
"preserveNullAndEmptyArrays": true,
|
||||
},
|
||||
},
|
||||
primitive.M{
|
||||
"$project": primitive.M{
|
||||
FN.MwAcc.Id: 1,
|
||||
FN.MwAcc.UserName: 1,
|
||||
FN.MwAcc.Acc: 1,
|
||||
FN.MwAcc.Pwd: 1,
|
||||
FN.MwAcc.Email: 1,
|
||||
FN.MwAcc.RoleId: 1,
|
||||
FN.MwAcc.RoleName: "$roles.name",
|
||||
FN.MwAcc.Base32: 1,
|
||||
FN.MwAcc.IsBase32: 1,
|
||||
// mwacc.FN.MwAcc.LastTime: 1,
|
||||
FN.MwAcc.IsEnb: 1,
|
||||
FN.MwAcc.Feedback: 1,
|
||||
FN.MwAcc.CreatedAt: 1,
|
||||
FN.MwAcc.UpdatedAt: 1,
|
||||
FN.MwAcc.LimitIP: 1,
|
||||
},
|
||||
})
|
||||
|
||||
err = mwAccColl.Aggregate(ctx, &data, pip)
|
||||
if err != nil {
|
||||
err = errors.MakeWithErr(errors.DBQuery, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤查询账号
|
||||
func FindManyAccByFilter(ctx context.Context, filters primitive.M, opts ...*options.FindOptions) ([]*MwAcc, *srvdef.SrvErr) {
|
||||
var res []*MwAcc
|
||||
err := mwAccColl.Find(ctx, &res, filters, opts...)
|
||||
if err != nil {
|
||||
log.Error("mwacc FindOneAccByFilter err", log.Any("filters", filters), log.E(err))
|
||||
return res, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
log.Info("success")
|
||||
|
||||
return res, nil
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package mwacc
|
||||
|
||||
import "videoweb/pub/mongos"
|
||||
|
||||
var (
|
||||
mwAccColl *mongos.Collection = nil
|
||||
mwRoleColl *mongos.Collection = nil
|
||||
mwAccTokenColl *mongos.Collection = nil
|
||||
)
|
||||
|
||||
type AggStatCount struct {
|
||||
Total int64 `bson:"total"`
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package mwacc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
// Init 初始化数据
|
||||
func Init(ctx context.Context) {
|
||||
mwAccColl = mongos.Shop.Coll(TN.MwAcc)
|
||||
mwRoleColl = mongos.Shop.Coll(TN.MwRole)
|
||||
mwAccTokenColl = mongos.Shop.Coll(TN.MwAccToken)
|
||||
initIndex(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// initIndex 初始化索引
|
||||
func initIndex(ctx context.Context) {
|
||||
initAccIndex(ctx)
|
||||
initRoleIndex(ctx)
|
||||
initAccTokenIndex(ctx)
|
||||
}
|
||||
|
||||
func initAccIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{FN.MwAcc.Id, 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := mwAccColl.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(mwacc:initAccIndex) Create mwacc Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
func initRoleIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{FN.MwRole.Id, 1},
|
||||
},
|
||||
// Options: options.Index().SetUnique(true),
|
||||
},
|
||||
}
|
||||
if _, err := mwRoleColl.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(mwacc:initRoleIndex) Create mwacc Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
func initAccTokenIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{FN.MwAccToken.Id, 1},
|
||||
},
|
||||
// Options: options.Index().SetUnique(true),
|
||||
},
|
||||
}
|
||||
if _, err := mwAccTokenColl.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(mwacc:initAccTokenIndex) Create mwacc Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package mwacc
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"videoweb/pub/pubdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
func MakeSearch(keyWords string, status int64, page pubdef.Page) (searchs bson.M) {
|
||||
var search []bson.M
|
||||
if len(keyWords) > 0 {
|
||||
userId, _ := strconv.ParseInt(keyWords, 10, 64)
|
||||
search = append(search, bson.M{FN.MwAcc.Id: userId})
|
||||
search = append(search, bson.M{FN.MwAcc.UserName: bson.M{"$regex": keyWords}})
|
||||
search = append(search, bson.M{FN.MwAcc.Acc: bson.M{"$regex": keyWords}})
|
||||
search = append(search, bson.M{FN.MwAcc.Email: bson.M{"$regex": keyWords}})
|
||||
}
|
||||
|
||||
match := bson.M{}
|
||||
if len(search) > 0 {
|
||||
match["$or"] = search
|
||||
}
|
||||
|
||||
if status > 0 {
|
||||
if status == 1 {
|
||||
match[FN.MwAcc.IsEnb] = true
|
||||
} else {
|
||||
match[FN.MwAcc.IsEnb] = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
searchs = bson.M{}
|
||||
searchs["$match"] = match
|
||||
return
|
||||
}
|
||||
|
||||
func MakeSort(pageNum int64, pageSize int64) (sort []bson.M) {
|
||||
sort = append(sort, bson.M{
|
||||
"$sort": bson.M{
|
||||
FN.MwAcc.CreatedAt: -1,
|
||||
},
|
||||
})
|
||||
if pageNum <= 0 {
|
||||
pageNum = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
skip := (pageNum - 1) * pageSize
|
||||
sort = append(sort, bson.M{
|
||||
"$skip": skip,
|
||||
})
|
||||
|
||||
sort = append(sort, bson.M{
|
||||
"$limit": pageSize,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// Code generated by gen_bson_tag. DO NOT EDIT.
|
||||
package mwacc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// CreateOneMwAcc 创建一个MwAcc
|
||||
func CreateOneMwAcc(ctx context.Context, data *MwAcc) *srvdef.SrvErr {
|
||||
_, err := mwAccColl.InsertOne(ctx, data)
|
||||
if err != nil {
|
||||
log.Error("mwacc:CreateOneMwAcc db.InsertOne failed",
|
||||
log.Any("doc", data),
|
||||
log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindOneMwAcc 查找一个MwAcc
|
||||
func FindOneMwAcc(ctx context.Context, filter bson.M) (
|
||||
*MwAcc, *srvdef.SrvErr) {
|
||||
var data *MwAcc
|
||||
if err := mwAccColl.FindOneEx(ctx, &data, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("mwacc:FindOneMwAcc mwAccColl.FindOneEx failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// DelOneOneMwAcc 删除一个MwAcc
|
||||
func DelOneOneMwAcc(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := mwAccColl.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("mwacc:DelOneOneMwAcc mwAccColl.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneMwAcc 更新一个MwAcc
|
||||
func UpdateOneMwAcc(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := mwAccColl.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("mwacc:UpdateOneMwAcc mwAccColl.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CountMwAccs 统计MwAcc数量
|
||||
func CountMwAccs(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := mwAccColl.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("mwacc:CountMwAccs mwAccColl.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindManyMwAccs 查找一批MwAcc
|
||||
func FindManyMwAccs(ctx context.Context, filter bson.M,
|
||||
opts ...*options.FindOptions) (MwAccList, *srvdef.SrvErr) {
|
||||
data := make(MwAccList, 0)
|
||||
if err := mwAccColl.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("mwacc:FindManyMwAccs mwAccColl.Find failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// FindManyMwAccsWithBind 用自己定义结构查找一批MwAcc数据
|
||||
func FindManyMwAccsWithBind(ctx context.Context, bind interface{}, filter bson.M,
|
||||
opts ...*options.FindOptions) *srvdef.SrvErr {
|
||||
if err := mwAccColl.Find(ctx, bind, filter, opts...); err != nil {
|
||||
log.Warn("mwacc:FindManyMwAccsWithBind mwAccColl.Find failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AggregateMwAccs 聚合查找一批MwAcc
|
||||
func AggregateMwAccs(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := mwAccColl.Aggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("mwacc:AggregateMwAccs mwAccColl.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectAggregateMwAccs 聚合查找一批MwAcc数据
|
||||
func ObjectAggregateMwAccs(ctx context.Context,
|
||||
bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := mwAccColl.ObjectAggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("mwacc:AggregateMwAccs mwAccColl.Aggregate failed",
|
||||
log.E(err), log.Any("pipeline", pipeline))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectAggregateMwAccs 批量写入或者更新MwAcc数据
|
||||
func BulkWriteMwAccs(ctx context.Context,
|
||||
docs []mongo.WriteModel, opts ...*options.BulkWriteOptions) *srvdef.SrvErr {
|
||||
_, err := mwAccColl.BulkWrite(ctx, docs, opts...)
|
||||
if err != nil {
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package mwacc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"videoweb/pub/common/errors"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/pageopt"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// 角色聚集处理
|
||||
func RoleAggregate(ctx context.Context, filters []primitive.M, opts ...*options.AggregateOptions) (roles []*MwRole, err error) {
|
||||
roles = make([]*MwRole, 0)
|
||||
err = mwRoleColl.Aggregate(ctx, &roles, filters)
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤查询数量
|
||||
func RoleCountByFilter(ctx context.Context, filters primitive.M, opts ...*options.CountOptions) (c int64, err error) {
|
||||
c, err = mwRoleColl.Count(ctx, filters)
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤查询角色
|
||||
func FindOneRoleByFilter(ctx context.Context, filters primitive.M, opts ...*options.FindOneOptions) (*MwRole, *srvdef.SrvErr) {
|
||||
var res MwRole
|
||||
err := mwRoleColl.FindOne(ctx, &res, filters, opts...)
|
||||
if err != nil {
|
||||
log.Error("mwacc FindOneRoleByFilter err", log.Any("filters", filters), log.E(err))
|
||||
return &res, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// 过滤更新
|
||||
func UpOneRoleByFilter(ctx context.Context, query primitive.M, update primitive.M) *srvdef.SrvErr {
|
||||
_, err := mwRoleColl.UpdateOne(ctx, query, update)
|
||||
if err != nil {
|
||||
log.Error("mwacc UpOneRoleByFilter: db.UpdateOne err", log.Any("update", update), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 过滤删除角色
|
||||
func DelRoleByFilter(ctx context.Context, filters primitive.M) *srvdef.SrvErr {
|
||||
_, err := mwRoleColl.DeleteOne(ctx, filters)
|
||||
if err != nil {
|
||||
log.Error("mwacc DelRoleByFilter err", log.Any("filters", filters), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 更新角色权限
|
||||
func UpRoleAuth(ctx context.Context, id int64, keys []string, dataRouter []*Router) (ok bool, err error) {
|
||||
|
||||
_, err = mwRoleColl.UpdateOne(ctx, primitive.M{
|
||||
FN.MwRole.Id: id,
|
||||
}, primitive.M{
|
||||
"$set": primitive.M{
|
||||
FN.MwRole.ApiMenus: keys,
|
||||
FN.MwRole.Router: dataRouter,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Error("mvacc UpRoleAuth err", log.Any(FN.MwRole.Id, id), log.E(err))
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 获取角色列表
|
||||
func GetRoleList(ctx context.Context, skip, limit int64, matchs ...pageopt.Matcher) (data []*RoleGetListRec, err error) {
|
||||
data = make([]*RoleGetListRec, 0)
|
||||
|
||||
err = mwRoleColl.Aggregate(ctx, &data,
|
||||
[]primitive.M{
|
||||
{"$match": pageopt.MergeM(matchs)},
|
||||
{"$sort": primitive.M{FN.MwRole.Id: -1}},
|
||||
{"$skip": skip},
|
||||
{"$limit": limit},
|
||||
{"$lookup": primitive.M{
|
||||
"localField": FN.MwRole.Id,
|
||||
"from": TN.MwAcc,
|
||||
"foreignField": FN.MwAcc.RoleId,
|
||||
"as": "onlyRole",
|
||||
}},
|
||||
{"$project": primitive.M{
|
||||
FN.MwRole.Id: 1,
|
||||
FN.MwRole.Name: 1,
|
||||
FN.MwRole.Desc: 1,
|
||||
FN.MwRole.IsEnb: 1,
|
||||
FN.MwRole.ApiMenus: 1,
|
||||
FN.MwRole.CreatedAt: 1,
|
||||
FN.MwRole.UpdatedAt: 1,
|
||||
"account": primitive.M{
|
||||
"$size": "$onlyRole",
|
||||
},
|
||||
}},
|
||||
})
|
||||
if err != nil && err.Error() != errors.NotFind {
|
||||
log.ZapLog.Error(fmt.Sprintf("mwacc GetRoleList error %v", err))
|
||||
err = errors.MakeWithErr(errors.DBQuery, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 下拉列表
|
||||
func RoleDrop(ctx context.Context) (data []*RoleDropDoc, err error) {
|
||||
|
||||
query := primitive.M{FN.MwRole.IsEnb: true}
|
||||
|
||||
opt := options.Find().SetProjection(primitive.M{
|
||||
FN.MwRole.Id: 1,
|
||||
FN.MwRole.Name: 1,
|
||||
})
|
||||
|
||||
err = mwRoleColl.Find(ctx, &data, query, opt)
|
||||
if err != nil {
|
||||
err = errors.MakeWithErr(errors.DBQuery, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 插入角色
|
||||
func RoleAdd(ctx context.Context, name string, desc string, isEnb bool) (ok bool, err error) {
|
||||
c, err := mwRoleColl.Count(ctx, primitive.M{FN.MwRole.Name: name})
|
||||
if c > 0 {
|
||||
err = errors.MakeWithMsg(errors.DBInsert, "角色名称")
|
||||
return false, err
|
||||
}
|
||||
|
||||
_, err = mwRoleColl.InsertOne(ctx, primitive.M{
|
||||
FN.MwRole.Id: mongos.Lid.MwRole.Get(),
|
||||
FN.MwRole.Name: name,
|
||||
FN.MwRole.Desc: desc,
|
||||
FN.MwRole.IsEnb: isEnb,
|
||||
FN.MwRole.CreatedAt: time.Now(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.ZapLog.Error(fmt.Sprintf("InsertRole mongo error %v", err))
|
||||
err = errors.MakeWithErr(errors.DBInsert, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
Executable
+88
@@ -0,0 +1,88 @@
|
||||
package mwacc
|
||||
|
||||
type TagMwRole struct {
|
||||
ApiMenus string
|
||||
CreatedAt string
|
||||
Desc string
|
||||
Id string
|
||||
IsEnb string
|
||||
Name string
|
||||
Router string
|
||||
UpdatedAt string
|
||||
}
|
||||
type TagMwAcc struct {
|
||||
Acc string
|
||||
Base32 string
|
||||
Code string
|
||||
CreatedAt string
|
||||
Email string
|
||||
Feedback string
|
||||
Id string
|
||||
IsBase32 string
|
||||
IsEnb string
|
||||
LastTime string
|
||||
LimitIP string
|
||||
Pwd string
|
||||
Qurl string
|
||||
RoleId string
|
||||
RoleName string
|
||||
Token string
|
||||
UpdatedAt string
|
||||
UserName string
|
||||
}
|
||||
type TagMwAccToken struct {
|
||||
AccId string
|
||||
CreatedAt string
|
||||
Id string
|
||||
Token string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
MwRole TagMwRole
|
||||
MwAcc TagMwAcc
|
||||
MwAccToken TagMwAccToken
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
MwRole string
|
||||
MwAcc string
|
||||
MwAccToken string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.MwRole.ApiMenus = "apiMenus"
|
||||
FN.MwRole.CreatedAt = "createdAt"
|
||||
FN.MwRole.Desc = "desc"
|
||||
FN.MwRole.Id = "_id"
|
||||
FN.MwRole.IsEnb = "isEnb"
|
||||
FN.MwRole.Name = "name"
|
||||
FN.MwRole.Router = "router"
|
||||
FN.MwRole.UpdatedAt = "updatedAt"
|
||||
FN.MwAcc.Acc = "acc"
|
||||
FN.MwAcc.Base32 = "base32"
|
||||
FN.MwAcc.Code = "code"
|
||||
FN.MwAcc.CreatedAt = "createdAt"
|
||||
FN.MwAcc.Email = "email"
|
||||
FN.MwAcc.Feedback = "feedback"
|
||||
FN.MwAcc.Id = "_id"
|
||||
FN.MwAcc.IsBase32 = "isBase32"
|
||||
FN.MwAcc.IsEnb = "isEnb"
|
||||
FN.MwAcc.LastTime = "lastTime"
|
||||
FN.MwAcc.LimitIP = "limitIP"
|
||||
FN.MwAcc.Pwd = "pwd"
|
||||
FN.MwAcc.Qurl = "qurl"
|
||||
FN.MwAcc.RoleId = "roleId"
|
||||
FN.MwAcc.RoleName = "roleName"
|
||||
FN.MwAcc.Token = "token"
|
||||
FN.MwAcc.UpdatedAt = "updatedAt"
|
||||
FN.MwAcc.UserName = "userName"
|
||||
FN.MwAccToken.AccId = "accId"
|
||||
FN.MwAccToken.CreatedAt = "createdAt"
|
||||
FN.MwAccToken.Id = "_id"
|
||||
FN.MwAccToken.Token = "token"
|
||||
FN.MwAccToken.UpdatedAt = "updatedAt"
|
||||
TN.MwRole = "mw_role"
|
||||
TN.MwAcc = "mw_acc"
|
||||
TN.MwAccToken = "mw_acc_token"
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package mwacc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"videoweb/pub/common/errors"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 过滤更新
|
||||
func UpOneTokenByFilter(ctx context.Context, query primitive.M, update primitive.M) (err error) {
|
||||
_, err = mwAccTokenColl.UpdateOne(ctx, query, primitive.M{"$set": update})
|
||||
return
|
||||
}
|
||||
|
||||
func SaveToken(ctx context.Context, accId int64, token string) (ok bool, err error) {
|
||||
var booToken MwAccToken
|
||||
|
||||
// 查找
|
||||
err = mwAccTokenColl.FindOne(ctx, &booToken, primitive.M{FN.MwAccToken.AccId: accId})
|
||||
|
||||
if booToken.AccId > 0 {
|
||||
// 更新
|
||||
err = UpOneTokenByFilter(ctx, primitive.M{
|
||||
FN.MwAccToken.AccId: accId,
|
||||
}, primitive.M{
|
||||
FN.MwAccToken.Token: token,
|
||||
FN.MwAccToken.UpdatedAt: time.Now(),
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if err != nil || booToken.AccId == 0 {
|
||||
if _, err := mwAccTokenColl.InsertOne(ctx,
|
||||
primitive.M{
|
||||
FN.MwAccToken.Id: mongos.Lid.MwAccToken.Get(),
|
||||
FN.MwAccToken.AccId: accId,
|
||||
FN.MwAccToken.Token: token,
|
||||
FN.MwAccToken.CreatedAt: time.Now(),
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func CheckToken(ctx context.Context, token string) (ok bool, err error) {
|
||||
var booToken MwAccToken
|
||||
Terr := mwAccTokenColl.FindOne(ctx, &booToken, primitive.M{FN.MwAccToken.Token: token})
|
||||
if Terr != nil || booToken.AccId == 0 {
|
||||
err = errors.MakeWithMsg(errors.NoToken, "token 不存在或已过期")
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// // 检测Token
|
||||
// func CheckToken(ctx context.Context, token string) (ok bool, err error) {
|
||||
// var booToken WebToken
|
||||
// Terr := tokenColl.FindOne(ctx, &booToken, primitive.M{"token": token})
|
||||
// if Terr != nil || booToken.Id == 0 {
|
||||
// err = errors.MakeWithMsg(errors.NoToken, "token 不存在或已过期")
|
||||
// return
|
||||
// }
|
||||
// return true, nil
|
||||
// }
|
||||
|
||||
// 删除token
|
||||
func DeleteOneToken(ctx context.Context, filter bson.M) *srvdef.SrvErr {
|
||||
if _, err := mwAccTokenColl.DeleteOne(ctx, filter); err != nil {
|
||||
log.Warn("mwacc:DeleteOneToken db.DeleteOne failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package mwacc
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Meta struct {
|
||||
Title string `bson:"title"`
|
||||
Icon string `bson:"icon"`
|
||||
NoCache bool `bson:"noCache"`
|
||||
}
|
||||
|
||||
type Apiurl struct {
|
||||
Url []string `bson:"url"`
|
||||
Desc string `bson:"desc"`
|
||||
Status bool `bson:"status"`
|
||||
Method []string `bson:"method"`
|
||||
}
|
||||
|
||||
// 编辑返回去的数据
|
||||
type Router struct {
|
||||
Path string `bson:"path"`
|
||||
Component string `bson:"component"`
|
||||
Redirect string `bson:"redirect"`
|
||||
Name string `bson:"name"`
|
||||
IsShow bool `bson:"isShow"`
|
||||
Hidden bool `bson:"hidden"`
|
||||
Meta Meta `bson:"meta"`
|
||||
Children []Router `bson:"children"`
|
||||
ApiUrl []Apiurl `bson:"apiUrl"`
|
||||
}
|
||||
|
||||
// 角色
|
||||
// @table:mw_role
|
||||
type MwRole struct {
|
||||
Id int64 `bson:"_id"`
|
||||
Name string `bson:"name"` // 角色名称
|
||||
Desc string `bson:"desc"` // 描述
|
||||
IsEnb bool `bson:"isEnb"` // 是否启用 false:禁用 true:启用
|
||||
ApiMenus []string `bson:"apiMenus"` // 已有权限的api
|
||||
Router []Router `bson:"router"`
|
||||
CreatedAt time.Time `bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `bson:"updatedAt"` // 更新时间
|
||||
}
|
||||
|
||||
// 账号
|
||||
// @table:mw_acc
|
||||
type MwAcc struct {
|
||||
Id int64 `bson:"_id"` // id
|
||||
UserName string `bson:"userName"` // 用户名
|
||||
Acc string `bson:"acc"` // 账号
|
||||
Pwd string `bson:"pwd"` // 密码
|
||||
Email string `bson:"email"` // 邮箱
|
||||
RoleId int64 `bson:"roleId"` // 角色Id
|
||||
RoleName string `bson:"roleName"` // 角色名
|
||||
Base32 string `bson:"base32"` // 二步签名
|
||||
IsBase32 bool `bson:"isBase32"` // 是否已签名
|
||||
Code string `bson:"code"` // 验证码
|
||||
Qurl []byte `bson:"qurl"` // 二维码链接
|
||||
Token string `bson:"token"` // token
|
||||
LastTime time.Time `bson:"lastTime"` // 登录时间
|
||||
IsEnb bool `bson:"isEnb"` // 使能
|
||||
Feedback string `bson:"feedback"` // 禁用原因
|
||||
CreatedAt time.Time `bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `bson:"updatedAt"` // 更新时间
|
||||
LimitIP []string `bson:"limitIP"` // 限制IP
|
||||
}
|
||||
type MwAccList []*MwAcc
|
||||
|
||||
// 账号Token
|
||||
// @table:mw_acc_token
|
||||
type MwAccToken struct {
|
||||
Id int64 `bson:"_id"` // id
|
||||
AccId int64 `bson:"accId"` // 账号id
|
||||
Token string `bson:"token"` // token
|
||||
CreatedAt time.Time `bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `bson:"updatedAt"` // 更新时间
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package mwacc
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type AccGetListRec struct {
|
||||
Id int64 `bson:"_id"` // id
|
||||
Username string `bson:"username"` // 用户名
|
||||
Acc string `bson:"acc"` // 用户名
|
||||
Pwd string `bson:"pwd"` // 密码
|
||||
Email string `bson:"email"` // 邮箱
|
||||
RoleId int64 `bson:"roleId"` // 角色Id
|
||||
RoleName string `bson:"roleName"` // 角色名
|
||||
// Base32 string `bson:"base32"` // 二步签名
|
||||
IsBase32 bool `bson:"isBase32"` // 是否已签名
|
||||
IsEnb bool `bson:"isEnb"` // 使能
|
||||
Feedback string `bson:"feedback"` // 禁用原因
|
||||
CreatedAt time.Time `bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `bson:"updatedAt"` // 更新时间
|
||||
LimitIP []string `bson:"limitIP"` // 允许访问的IP
|
||||
}
|
||||
|
||||
type RoleGetListRec struct {
|
||||
Id int64 `bson:"_id"` // 角色Id
|
||||
Name string `bson:"name"` // 角色名称
|
||||
Desc string `bson:"desc"` // 描述
|
||||
IsEnb bool `bson:"isEnb"` // 是否启用 false:禁用 true:启用
|
||||
ApiMenus []string `bson:"apiMenus"` // 已有权限的api
|
||||
CreatedAt time.Time `bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `bson:"updatedAt"` // 更新时间
|
||||
AccCount int64 `bson:"accCount"` // 账户数量
|
||||
}
|
||||
|
||||
type AccInsertDoc struct {
|
||||
Id int64 `bson:"_id"` // id
|
||||
UserName string `bson:"userName"` // 用户名
|
||||
Pwd string `bson:"pwd"` // 密码
|
||||
Acc string `bson:"acc"` // 用户名
|
||||
Email string `bson:"email"` // 邮箱
|
||||
RoleId int64 `bson:"roleId"` // 角色Id
|
||||
Base32 string `bson:"base32"` // 二步签名
|
||||
IsBase32 bool `bson:"isBase32"` // 是否已签名
|
||||
IsEnb bool `bson:"isEnb"` // 使能
|
||||
LastTime time.Time `bson:"lastTime"` // 登录时间
|
||||
CreatedAt time.Time `bson:"createdAt"` // 创建时间
|
||||
LimitIP []string `bson:"limitIP"` // 允许访问的IP
|
||||
}
|
||||
|
||||
type RoleDropDoc struct {
|
||||
Id int64 `bson:"_id"` // 角色Id
|
||||
Name string `bson:"name"` // 角色名称
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package oplog
|
||||
|
||||
import (
|
||||
"videoweb/pub/mongos"
|
||||
)
|
||||
|
||||
var (
|
||||
opLogColl *mongos.Collection
|
||||
)
|
||||
@@ -0,0 +1,175 @@
|
||||
package oplog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/common/utils"
|
||||
"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"
|
||||
)
|
||||
|
||||
// Init 初始化数据
|
||||
func Init(ctx context.Context) {
|
||||
opLogColl = mongos.ShopLog.Coll(TN.OpLog)
|
||||
initIndex(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{FN.OpLog.ActId, 1},
|
||||
{FN.OpLog.Action, 1},
|
||||
{FN.OpLog.Path, 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{FN.OpLog.CreatedAt, -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := opLogColl.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(oplog:initIndex) Create adLog Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// 添加日志
|
||||
func AddLog(ctx context.Context, path string, desc string, actId int64, rawData, ip string) (err error) {
|
||||
_, err = opLogColl.InsertOne(ctx, primitive.M{
|
||||
FN.OpLog.Id: mongos.Lid.MwOpLog.Get(),
|
||||
FN.OpLog.Action: desc,
|
||||
FN.OpLog.Path: path,
|
||||
FN.OpLog.ActId: actId,
|
||||
FN.OpLog.RawData: rawData,
|
||||
FN.OpLog.CreatedAt: utils.Now(),
|
||||
FN.OpLog.IP: ip,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
type LogReq struct {
|
||||
PageNum int64 `json:"pageNum"` // 页码
|
||||
PageSize int64 `json:"pageSize"` //
|
||||
Path *string `json:"path"` // 请求接口
|
||||
Action *string `json:"action"` // 操作目的
|
||||
ActId *int64 `json:"actId"` // 操作人Id
|
||||
StartTime *time.Time `json:"startTime"` // 开始时间
|
||||
EndTime *time.Time `json:"endTime"` // 开始时间
|
||||
}
|
||||
|
||||
// 操作日志信息
|
||||
type OpLogInfo struct {
|
||||
Path string `json:"path" bson:"path"` // 请求接口
|
||||
ActId int64 `json:"actId" bson:"actId"` // 操作人Id
|
||||
Action string `json:"action" bson:"action"` // 操作目的
|
||||
Param string `json:"param" bson:"rawData"` // 操作内容
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 操作时间
|
||||
ActName string `json:"actName" bson:"actName"` // 操作人
|
||||
}
|
||||
|
||||
type OpPageRes struct {
|
||||
Total int64 `json:"total" bson:"total"`
|
||||
List []*OpLogInfo `json:"list" bson:"list"`
|
||||
}
|
||||
|
||||
// 获取日志列表
|
||||
func PageLogList(ctx context.Context, req *LogReq) (res *OpPageRes, err error) {
|
||||
filter := bson.M{}
|
||||
if req.Path != nil && *req.Path != "" {
|
||||
filter[FN.OpLog.Path] = bson.M{"$regex": req.Path}
|
||||
}
|
||||
if req.Action != nil && *req.Action != "" {
|
||||
filter[FN.OpLog.Action] = req.Action
|
||||
}
|
||||
if req.ActId != nil && *req.ActId > 0 {
|
||||
filter[FN.OpLog.ActId] = req.ActId
|
||||
}
|
||||
if req.StartTime != nil && req.EndTime != nil {
|
||||
filter[FN.OpLog.CreatedAt] = bson.M{"$gte": req.StartTime, "$lt": req.EndTime}
|
||||
}
|
||||
res = new(OpPageRes)
|
||||
res.Total, err = mongos.ShopLog.Coll(TN.OpLog).Count(ctx, filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sort := bson.M{FN.OpLog.CreatedAt: -1}
|
||||
opt := &options.FindOptions{}
|
||||
opt.SetSort(sort)
|
||||
skip := (req.PageNum - 1) * req.PageSize
|
||||
opt.SetSkip(skip)
|
||||
opt.SetLimit(req.PageSize)
|
||||
list := make(OpLogList, 0)
|
||||
err = mongos.ShopLog.Coll(TN.OpLog).Find(ctx, &list, filter, opt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
actIds := make([]int64, 0)
|
||||
for _, v := range list {
|
||||
actIds = append(actIds, v.ActId)
|
||||
}
|
||||
// err = opLogColl.Aggregate(ctx, &res.List, []bson.M{
|
||||
// {"$match": conf},
|
||||
// {"$sort": bson.M{FN.OpLog.CreatedAt: -1}},
|
||||
// {"$skip": (req.PageNum - 1) * req.PageSize},
|
||||
// {"$limit": req.PageSize},
|
||||
// {"$lookup": bson.M{
|
||||
// "localField": FN.OpLog.ActId,
|
||||
// "from": mwacc.TN.MwAcc,
|
||||
// "foreignField": mwacc.FN.MwAcc.Id,
|
||||
// "as": "admins",
|
||||
// }},
|
||||
// {"$unwind": "$admins"},
|
||||
// {"$project": bson.M{
|
||||
// FN.OpLog.Path: 1,
|
||||
// FN.OpLog.Action: 1,
|
||||
// FN.OpLog.ActId: 1,
|
||||
// FN.OpLog.RawData: 1,
|
||||
// FN.OpLog.CreatedAt: 1,
|
||||
// "actName": "$admins.userName",
|
||||
// }},
|
||||
// })
|
||||
return
|
||||
}
|
||||
|
||||
// CountOpLogs 计算某个查询的数量
|
||||
func CountOpLogs(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
total, err := mongos.ShopLog.Coll(TN.OpLog).Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Info("oplog:CountOpLogs db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// InsertOneUser 插入一个用户
|
||||
func InsertOneUser(ctx context.Context, opLog *OpLog) *srvdef.SrvErr {
|
||||
if _, err := mongos.ShopLog.Coll(TN.OpLog).InsertOne(ctx, opLog); err != nil {
|
||||
log.Warn("oplog:InsertOneUser db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyOpLogs 查找一批数据
|
||||
func FindManyOpLogs(ctx context.Context,
|
||||
filter bson.M, opts ...*options.FindOptions) (
|
||||
OpLogList, *srvdef.SrvErr) {
|
||||
data := make(OpLogList, 0)
|
||||
if err := mongos.ShopLog.Coll(TN.OpLog).Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("oplog:FindManyOpLogs db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
package oplog
|
||||
|
||||
type TagOpLog struct {
|
||||
ActId string
|
||||
Action string
|
||||
CreatedAt string
|
||||
IP string
|
||||
Id string
|
||||
IsWhite string
|
||||
OpType string
|
||||
Path string
|
||||
RawData string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
OpLog TagOpLog
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
OpLog string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.OpLog.ActId = "actId"
|
||||
FN.OpLog.Action = "action"
|
||||
FN.OpLog.CreatedAt = "createdAt"
|
||||
FN.OpLog.IP = "ip"
|
||||
FN.OpLog.Id = "_id"
|
||||
FN.OpLog.IsWhite = "isWhite"
|
||||
FN.OpLog.OpType = "opType"
|
||||
FN.OpLog.Path = "path"
|
||||
FN.OpLog.RawData = "rawData"
|
||||
TN.OpLog = "mw_op_log"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package oplog
|
||||
|
||||
import (
|
||||
"time"
|
||||
"videoweb/pub/common"
|
||||
)
|
||||
|
||||
// 操作日志
|
||||
// @table:mw_op_log
|
||||
type OpLog struct {
|
||||
Id int64 `bson:"_id"` // id
|
||||
Path string `bson:"path"` // 请求接口
|
||||
OpType common.ApiOpType `bson:"opType"` // 操作类型
|
||||
IsWhite bool `bson:"isWhite"` // 是否白名单
|
||||
ActId int64 `bson:"actId"` // 操作人Id
|
||||
Action string `bson:"action"` // 操作目的
|
||||
RawData string `bson:"rawData"` // 原始数据
|
||||
CreatedAt time.Time `bson:"createdAt"` // 操作时间
|
||||
IP string `bson:"ip"` // 操作人IP
|
||||
}
|
||||
|
||||
type OpLogList []*OpLog
|
||||
@@ -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
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,121 @@
|
||||
package playletcategorymod
|
||||
|
||||
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_category 集合和后台常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.PlayletCategory)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletCategory.Status, Value: 1},
|
||||
{Key: FN.PlayletCategory.Rank, Value: -1},
|
||||
{Key: FN.PlayletCategory.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletCategory.Name, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletCategory.CreatedAt, Value: -1},
|
||||
{Key: FN.PlayletCategory.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(playletcategorymod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOnePlayletCategory 插入一条短剧分类数据
|
||||
func InsertOnePlayletCategory(ctx context.Context, doc *PlayletCategory) *srvdef.SrvErr {
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.PlayletCategory.Get()
|
||||
}
|
||||
now := time.Now()
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
doc.UpdatedAt = now
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("playletcategorymod:InsertOnePlayletCategory failed", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOnePlayletCategory 删除一条短剧分类数据
|
||||
func DelOnePlayletCategory(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletcategorymod:DelOnePlayletCategory failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOnePlayletCategory 查询一条短剧分类数据
|
||||
func FindOnePlayletCategory(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*PlayletCategory, *srvdef.SrvErr) {
|
||||
var doc PlayletCategory
|
||||
if err := coll.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("playletcategorymod:FindOnePlayletCategory failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyPlayletCategory 按条件查询多条短剧分类数据
|
||||
func FindManyPlayletCategory(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletCategoryList, *srvdef.SrvErr) {
|
||||
data := make(PlayletCategoryList, 0)
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("playletcategorymod:FindManyPlayletCategory failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountPlayletCategory 统计满足条件的短剧分类数量
|
||||
func CountPlayletCategory(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter, opts...)
|
||||
if err != nil {
|
||||
log.Warn("playletcategorymod:CountPlayletCategory failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOnePlayletCategory 更新一条短剧分类数据
|
||||
func UpdateOnePlayletCategory(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("playletcategorymod:UpdateOnePlayletCategory failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package playletcategorymod
|
||||
|
||||
// TagPlayletCategory 保存 playlet_category 集合字段名
|
||||
type TagPlayletCategory struct {
|
||||
Id string
|
||||
Name string
|
||||
Slug string
|
||||
Icon string
|
||||
Status string
|
||||
Rank string
|
||||
Remark string
|
||||
SeoInfo struct {
|
||||
Description string
|
||||
Keyworld string
|
||||
Title string
|
||||
}
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
PlayletCategory TagPlayletCategory
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
PlayletCategory string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.PlayletCategory.Id = "_id"
|
||||
FN.PlayletCategory.Name = "name"
|
||||
FN.PlayletCategory.Slug = "slug"
|
||||
FN.PlayletCategory.Icon = "icon"
|
||||
FN.PlayletCategory.Status = "status"
|
||||
FN.PlayletCategory.Rank = "rank"
|
||||
FN.PlayletCategory.Remark = "remark"
|
||||
FN.PlayletCategory.SeoInfo.Description = "seoInfo.webDescription"
|
||||
FN.PlayletCategory.SeoInfo.Keyworld = "seoInfo.webKeyworld"
|
||||
FN.PlayletCategory.SeoInfo.Title = "seoInfo.webTitle"
|
||||
FN.PlayletCategory.CreatedAt = "createdAt"
|
||||
FN.PlayletCategory.UpdatedAt = "updatedAt"
|
||||
|
||||
TN.PlayletCategory = "playlet_category"
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package playletcategorymod
|
||||
|
||||
import (
|
||||
"time"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
// PlayletCategory @table: playlet_category
|
||||
//
|
||||
// PlayletCategory 短剧分类集合模型
|
||||
type PlayletCategory struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
Name string `json:"name" bson:"name"` // 分类名称
|
||||
Slug string `json:"slug" bson:"slug"` // slug
|
||||
Icon string `json:"icon" bson:"icon"` // 分类图标
|
||||
Status bool `json:"status" bson:"status"` // 启用状态
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序,越大越靠前
|
||||
Remark string `json:"remark" bson:"remark"` // 备注
|
||||
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
}
|
||||
|
||||
// PlayletCategoryList 短剧分类列表
|
||||
type PlayletCategoryList []*PlayletCategory
|
||||
@@ -0,0 +1,265 @@
|
||||
package playletchaptermod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"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_chapter 集合和常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.PlayletChapter)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletChapter.PlayletId, Value: 1},
|
||||
{Key: FN.PlayletChapter.CurrentEpisode, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletChapter.PlayletId, Value: 1},
|
||||
{Key: FN.PlayletChapter.MediaContentId, Value: 1},
|
||||
},
|
||||
Options: options.Index().
|
||||
SetUnique(true).
|
||||
SetPartialFilterExpression(bson.M{
|
||||
FN.PlayletChapter.MediaContentId: bson.M{"$gt": 0},
|
||||
}),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletChapter.PlayletId, Value: 1},
|
||||
{Key: FN.PlayletChapter.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletChapter.CreatedAt, Value: -1},
|
||||
{Key: FN.PlayletChapter.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletChapter.WatermarkStatus, Value: 1},
|
||||
{Key: FN.PlayletChapter.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletChapter.MediaSourceId, Value: 1},
|
||||
},
|
||||
Options: options.Index().
|
||||
SetPartialFilterExpression(bson.M{
|
||||
FN.PlayletChapter.MediaSourceId: bson.M{"$gt": ""},
|
||||
}),
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(playletchaptermod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOnePlayletChapter 插入一条章节数据
|
||||
func InsertOnePlayletChapter(ctx context.Context, doc *PlayletChapter) *srvdef.SrvErr {
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.PlayletChapter.Get()
|
||||
}
|
||||
now := time.Now()
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
doc.UpdatedAt = now
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("playletchaptermod:InsertOnePlayletChapter failed", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertManyPlayletChapter 批量插入章节数据
|
||||
func InsertManyPlayletChapter(ctx context.Context, docs PlayletChapterList) *srvdef.SrvErr {
|
||||
data := make(PlayletChapterList, 0, len(docs))
|
||||
now := time.Now()
|
||||
for _, doc := range docs {
|
||||
if doc == nil {
|
||||
continue
|
||||
}
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.PlayletChapter.Get()
|
||||
}
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
doc.UpdatedAt = now
|
||||
data = append(data, doc)
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
if _, err := coll.InsertMany(ctx, &data); err != nil {
|
||||
log.Warn("playletchaptermod:InsertManyPlayletChapter failed", log.Any("count", len(data)), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOnePlayletChapter 删除一条章节数据
|
||||
func DelOnePlayletChapter(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletchaptermod:DelOnePlayletChapter failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// DelManyPlayletChapter 按条件批量删除章节数据
|
||||
func DelManyPlayletChapter(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteMany(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletchaptermod:DelManyPlayletChapter failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOnePlayletChapter 查询一条章节数据
|
||||
func FindOnePlayletChapter(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*PlayletChapter, *srvdef.SrvErr) {
|
||||
var doc PlayletChapter
|
||||
if err := coll.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("playletchaptermod:FindOnePlayletChapter failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyPlayletChapter 按条件查询多条章节数据
|
||||
func FindManyPlayletChapter(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletChapterList, *srvdef.SrvErr) {
|
||||
data := make(PlayletChapterList, 0)
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("playletchaptermod:FindManyPlayletChapter failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountPlayletChapter 统计满足条件的章节数量
|
||||
func CountPlayletChapter(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter, opts...)
|
||||
if err != nil {
|
||||
log.Warn("playletchaptermod:CountPlayletChapter failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOnePlayletChapter 更新一条章节数据
|
||||
func UpdateOnePlayletChapter(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("playletchaptermod:UpdateOnePlayletChapter failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsLinkedMedia 是否短剧媒资:显式标记或已挂到剧集
|
||||
func IsLinkedMedia(ctx context.Context, isPlaylet bool, ids ...string) bool {
|
||||
if isPlaylet {
|
||||
return true
|
||||
}
|
||||
return ExistsByMediaIDs(ctx, ids...)
|
||||
}
|
||||
|
||||
// ExistsByMediaIDs 判断媒资 ID 是否属于短剧剧集(mediaSourceId / mediaTaskId)
|
||||
func ExistsByMediaIDs(ctx context.Context, ids ...string) bool {
|
||||
clean := uniqueNonEmptyStrings(ids)
|
||||
if len(clean) == 0 {
|
||||
return false
|
||||
}
|
||||
item, _ := FindOnePlayletChapter(ctx, bson.M{
|
||||
"$or": []bson.M{
|
||||
{FN.PlayletChapter.MediaSourceId: bson.M{"$in": clean}},
|
||||
{FN.PlayletChapter.MediaTaskId: bson.M{"$in": clean}},
|
||||
},
|
||||
}, options.FindOne().SetProjection(bson.M{FN.PlayletChapter.Id: 1}))
|
||||
return item != nil
|
||||
}
|
||||
|
||||
// ListLinkedMediaIDs 返回短剧剧集关联的媒资 ID,用于排除短剧视频
|
||||
func ListLinkedMediaIDs(ctx context.Context) []string {
|
||||
list, err := FindManyPlayletChapter(ctx, bson.M{
|
||||
"$or": []bson.M{
|
||||
{FN.PlayletChapter.MediaSourceId: bson.M{"$gt": ""}},
|
||||
{FN.PlayletChapter.MediaTaskId: bson.M{"$gt": ""}},
|
||||
},
|
||||
}, options.Find().SetProjection(bson.M{
|
||||
FN.PlayletChapter.MediaSourceId: 1,
|
||||
FN.PlayletChapter.MediaTaskId: 1,
|
||||
}))
|
||||
if err != nil || len(list) == 0 {
|
||||
return nil
|
||||
}
|
||||
ids := make([]string, 0, len(list)*2)
|
||||
for _, item := range list {
|
||||
if item == nil {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, item.MediaSourceId, item.MediaTaskId)
|
||||
}
|
||||
return uniqueNonEmptyStrings(ids)
|
||||
}
|
||||
|
||||
func uniqueNonEmptyStrings(ids []string) []string {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
seen := make(map[string]struct{}, len(ids))
|
||||
out := make([]string, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
id = strings.TrimSpace(id)
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[id]; ok {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
out = append(out, id)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// UpdateManyPlayletChapter 批量更新章节数据
|
||||
func UpdateManyPlayletChapter(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
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package playletchaptermod
|
||||
|
||||
// TagPlayletChapter 保存 playlet_chapter 集合字段名
|
||||
type TagPlayletChapter struct {
|
||||
Id string
|
||||
PlayletId string
|
||||
MediaContentId string
|
||||
CurrentEpisode string
|
||||
Title string
|
||||
Md5 string
|
||||
Hash string
|
||||
Height string
|
||||
Width string
|
||||
Ratio string
|
||||
VideoUrl string
|
||||
WatermarkVideoUrl string
|
||||
MediaSize string
|
||||
MediaTime string
|
||||
CountComment string
|
||||
CountBuy string
|
||||
CountBrowse string
|
||||
CountCollect string
|
||||
CountLike string
|
||||
CountDisLike string
|
||||
PayType string
|
||||
SingleCoins string
|
||||
WatermarkStatus string
|
||||
MediaSourceId string
|
||||
MediaTaskId string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
PlayletChapter TagPlayletChapter
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
PlayletChapter string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.PlayletChapter.Id = "_id"
|
||||
FN.PlayletChapter.PlayletId = "playletId"
|
||||
FN.PlayletChapter.MediaContentId = "mediaContentId"
|
||||
FN.PlayletChapter.CurrentEpisode = "currentEpisode"
|
||||
FN.PlayletChapter.Title = "title"
|
||||
FN.PlayletChapter.Md5 = "md5"
|
||||
FN.PlayletChapter.Hash = "hash"
|
||||
FN.PlayletChapter.Height = "height"
|
||||
FN.PlayletChapter.Width = "width"
|
||||
FN.PlayletChapter.Ratio = "ratio"
|
||||
FN.PlayletChapter.VideoUrl = "videoUrl"
|
||||
FN.PlayletChapter.WatermarkVideoUrl = "watermarkVideoUrl"
|
||||
FN.PlayletChapter.MediaSize = "mediaSize"
|
||||
FN.PlayletChapter.MediaTime = "mediaTime"
|
||||
FN.PlayletChapter.CountComment = "countComment"
|
||||
FN.PlayletChapter.CountBuy = "countBuy"
|
||||
FN.PlayletChapter.CountBrowse = "countBrowse"
|
||||
FN.PlayletChapter.CountCollect = "countCollect"
|
||||
FN.PlayletChapter.CountLike = "countLike"
|
||||
FN.PlayletChapter.CountDisLike = "countDisLike"
|
||||
FN.PlayletChapter.PayType = "payType"
|
||||
FN.PlayletChapter.SingleCoins = "singleCoins"
|
||||
FN.PlayletChapter.WatermarkStatus = "watermarkStatus"
|
||||
FN.PlayletChapter.MediaSourceId = "mediaSourceId"
|
||||
FN.PlayletChapter.MediaTaskId = "mediaTaskId"
|
||||
FN.PlayletChapter.CreatedAt = "createdAt"
|
||||
FN.PlayletChapter.UpdatedAt = "updatedAt"
|
||||
|
||||
TN.PlayletChapter = "playlet_chapter"
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package playletchaptermod
|
||||
|
||||
import "time"
|
||||
|
||||
// PayType 支付方式
|
||||
type PayType int32
|
||||
|
||||
const (
|
||||
PayTypeFree PayType = 0 // 免费
|
||||
PayTypeCoin PayType = 1 // 金币
|
||||
PayTypeVip PayType = 2 // VIP
|
||||
)
|
||||
|
||||
// WatermarkStatus 水印状态
|
||||
type WatermarkStatus int32
|
||||
|
||||
const (
|
||||
WatermarkStatusPending WatermarkStatus = 0 // 未处理(待 mediafile/sync)
|
||||
WatermarkStatusRegistered WatermarkStatus = 1 // 已登记(原片已登记,待 task/add)
|
||||
WatermarkStatusProcessing WatermarkStatus = 2 // 处理中(已提交加水印任务,待回写)
|
||||
WatermarkStatusDone WatermarkStatus = 3 // 已完成
|
||||
WatermarkStatusFailed WatermarkStatus = 4 // 处理失败
|
||||
)
|
||||
|
||||
// PlayletChapter @table: playlet_chapter
|
||||
//
|
||||
// PlayletChapter 连载短剧章节集合模型
|
||||
type PlayletChapter struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
PlayletId int64 `json:"playletId" bson:"playletId"` // 短剧ID
|
||||
MediaContentId uint `json:"mediaContentId" bson:"mediaContentId"` // 媒资中心章节ID
|
||||
CurrentEpisode int64 `json:"currentEpisode" bson:"currentEpisode"` // 第几集
|
||||
Title string `json:"title" bson:"title"` // 章节名
|
||||
Md5 string `json:"md5" bson:"md5"` // 媒体md5
|
||||
Hash string `json:"hash" bson:"hash"` // 媒体hash
|
||||
Height int64 `json:"height" bson:"height"` // 高
|
||||
Width int64 `json:"width" bson:"width"` // 宽
|
||||
Ratio float64 `json:"ratio" bson:"ratio"` // 宽高比
|
||||
VideoUrl string `json:"videoUrl" bson:"videoUrl"` // 原片视频地址(加水印后保持不变,方便换水印)
|
||||
WatermarkVideoUrl string `json:"watermarkVideoUrl" bson:"watermarkVideoUrl"` // 加水印后的视频地址
|
||||
MediaSize int64 `json:"mediaSize" bson:"mediaSize"` // 资源大小
|
||||
MediaTime int64 `json:"mediaTime" bson:"mediaTime"` // 影片长度(秒)
|
||||
CountComment int64 `json:"countComment" bson:"countComment"` // 评论数
|
||||
CountBuy int64 `json:"countBuy" bson:"countBuy"` // 购买数
|
||||
CountBrowse int64 `json:"countBrowse" bson:"countBrowse"` // 浏览数
|
||||
CountCollect int64 `json:"countCollect" bson:"countCollect"` // 收藏数
|
||||
CountLike int64 `json:"countLike" bson:"countLike"` // 喜欢数
|
||||
CountDisLike int64 `json:"countDisLike" bson:"countDisLike"` // 不喜欢数
|
||||
PayType PayType `json:"payType" bson:"payType"` // 支付方式 0-免费 1-金币 2-VIP
|
||||
SingleCoins int64 `json:"singleCoins" bson:"singleCoins"` // 单集金币(支付方式为1-金币时候生效)
|
||||
WatermarkStatus WatermarkStatus `json:"watermarkStatus" bson:"watermarkStatus"` // 水印状态 0-未处理 1-已登记 2-处理中 3-已完成 4-处理失败
|
||||
MediaSourceId string `json:"mediaSourceId" bson:"mediaSourceId"` // media切片服原片ID
|
||||
MediaTaskId string `json:"mediaTaskId" bson:"mediaTaskId"` // media切片服水印任务ID
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
}
|
||||
|
||||
// PlayletChapterList 章节列表
|
||||
type PlayletChapterList []*PlayletChapter
|
||||
@@ -0,0 +1,100 @@
|
||||
package playletfavoritemod
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
const CollectionName = "playlet_favorite"
|
||||
|
||||
const (
|
||||
FieldID = "_id"
|
||||
FieldUserID = "userId"
|
||||
FieldPlayletID = "playletId"
|
||||
FieldCreatedAt = "createdAt"
|
||||
FieldUpdatedAt = "updatedAt"
|
||||
)
|
||||
|
||||
type PlayletFavorite struct {
|
||||
ID int64 `bson:"_id,omitempty"`
|
||||
UserID int64 `bson:"userId"`
|
||||
PlayletID int64 `bson:"playletId"`
|
||||
CreatedAt time.Time `bson:"createdAt"`
|
||||
UpdatedAt time.Time `bson:"updatedAt"`
|
||||
}
|
||||
|
||||
var coll *mongos.Collection
|
||||
|
||||
// Init 初始化短剧收藏集合及查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(CollectionName)
|
||||
indexes := []mongo.IndexModel{
|
||||
{Keys: bson.D{{Key: FieldUserID, Value: 1}, {Key: FieldPlayletID, Value: 1}}, Options: options.Index().SetUnique(true)},
|
||||
{Keys: bson.D{{Key: FieldUserID, Value: 1}, {Key: FieldCreatedAt, Value: -1}, {Key: FieldID, Value: -1}}},
|
||||
{Keys: bson.D{{Key: FieldPlayletID, Value: 1}}},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(playletfavoritemod:Init) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// Upsert 按用户和短剧写入收藏关系并返回是否新增
|
||||
func Upsert(ctx context.Context, userID, playletID int64, now time.Time) (bool, *srvdef.SrvErr) {
|
||||
filter := bson.M{FieldUserID: userID, FieldPlayletID: playletID}
|
||||
update := bson.M{"$set": bson.M{FieldUpdatedAt: now}, "$setOnInsert": bson.M{
|
||||
FieldID: mongos.Lid.PlayletFavorite.Get(), FieldUserID: userID, FieldPlayletID: playletID, FieldCreatedAt: now,
|
||||
}}
|
||||
result, err := coll.UpdateOne(ctx, filter, update, options.Update().SetUpsert(true))
|
||||
if err != nil {
|
||||
log.Warn("playletfavoritemod:Upsert failed", log.Any("filter", filter), log.E(err))
|
||||
return false, srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return result.UpsertedCount > 0, nil
|
||||
}
|
||||
|
||||
// Delete 删除收藏关系并返回是否实际删除
|
||||
func Delete(ctx context.Context, filter bson.M) (bool, *srvdef.SrvErr) {
|
||||
deleted, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletfavoritemod:Delete failed", log.Any("filter", filter), log.E(err))
|
||||
return false, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return deleted > 0, nil
|
||||
}
|
||||
|
||||
// Count 统计收藏关系数量
|
||||
func Count(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletfavoritemod:Count failed", log.Any("filter", filter), log.E(err))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindMany 查询收藏关系列表
|
||||
func FindMany(ctx context.Context, filter bson.M, opts ...*options.FindOptions) ([]*PlayletFavorite, *srvdef.SrvErr) {
|
||||
list := make([]*PlayletFavorite, 0)
|
||||
if err := coll.Find(ctx, &list, filter, opts...); err != nil {
|
||||
log.Warn("playletfavoritemod:FindMany failed", log.Any("filter", filter), log.E(err))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// Aggregate 聚合收藏关系和短剧数据
|
||||
func Aggregate(ctx context.Context, bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := coll.Aggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("playletfavoritemod:Aggregate failed", log.Any("pipeline", pipeline), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package playlethomeconfigmod
|
||||
|
||||
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_home_config 集合和常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.PlayletHomeConfig)
|
||||
backfillSlugs(ctx)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
// backfillSlugs 为历史配置生成稳定路径标识
|
||||
func backfillSlugs(ctx context.Context) {
|
||||
var docs PlayletHomeConfigList
|
||||
filter := bson.M{"$or": []bson.M{{FN.PlayletHomeConfig.Slug: bson.M{"$exists": false}}, {FN.PlayletHomeConfig.Slug: nil}, {FN.PlayletHomeConfig.Slug: ""}}}
|
||||
if err := coll.Find(ctx, &docs, filter, options.Find().SetProjection(bson.M{FN.PlayletHomeConfig.Id: 1})); err != nil {
|
||||
panic(fmt.Sprintf("(playlethomeconfigmod:backfillSlugs) Find failed! err:%+v", err))
|
||||
}
|
||||
for _, doc := range docs {
|
||||
if doc == nil {
|
||||
continue
|
||||
}
|
||||
if _, err := coll.UpdateOne(ctx, bson.M{FN.PlayletHomeConfig.Id: doc.Id, "$or": filter["$or"]}, bson.M{"$set": bson.M{FN.PlayletHomeConfig.Slug: fmt.Sprintf("home-config-%d", doc.Id)}}); err != nil {
|
||||
panic(fmt.Sprintf("(playlethomeconfigmod:backfillSlugs) UpdateOne failed! id:%d err:%+v", doc.Id, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletHomeConfig.Enabled, Value: 1},
|
||||
{Key: FN.PlayletHomeConfig.ModuleType, Value: 1},
|
||||
{Key: FN.PlayletHomeConfig.Rank, Value: -1},
|
||||
{Key: FN.PlayletHomeConfig.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletHomeConfig.CreatedAt, Value: -1},
|
||||
{Key: FN.PlayletHomeConfig.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: FN.PlayletHomeConfig.Slug, Value: 1}},
|
||||
Options: options.Index().SetUnique(true).SetName("slug_unique"),
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(playlethomeconfigmod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOnePlayletHomeConfig 插入一条首页配置
|
||||
func InsertOnePlayletHomeConfig(ctx context.Context, doc *PlayletHomeConfig) *srvdef.SrvErr {
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.PlayletHomeConfig.Get()
|
||||
}
|
||||
now := time.Now()
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
normalizePlayletHomeConfig(doc)
|
||||
doc.UpdatedAt = now
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
if mongo.IsDuplicateKeyError(err) {
|
||||
return srvdef.New(srvdef.ErrParamError, "slug已存在", "")
|
||||
}
|
||||
log.Warn("插入首页配置失败", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizePlayletHomeConfig(doc *PlayletHomeConfig) {
|
||||
if doc == nil {
|
||||
return
|
||||
}
|
||||
if doc.ModuleType != ModuleTypeTopic {
|
||||
doc.ModuleType = ModuleTypePlaylet
|
||||
}
|
||||
if doc.DataType != DataTypeVideo {
|
||||
doc.DataType = DataTypeAll
|
||||
}
|
||||
if doc.Limit <= 0 {
|
||||
doc.Limit = DefaultLimit
|
||||
}
|
||||
if doc.Limit > MaxLimit {
|
||||
doc.Limit = MaxLimit
|
||||
}
|
||||
}
|
||||
|
||||
// DelManyPlayletHomeConfig 删除多条首页配置
|
||||
func DelManyPlayletHomeConfig(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteMany(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("删除首页配置失败", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOnePlayletHomeConfig 查询一条首页配置
|
||||
func FindOnePlayletHomeConfig(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*PlayletHomeConfig, *srvdef.SrvErr) {
|
||||
var doc PlayletHomeConfig
|
||||
if err := coll.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("查询首页配置失败", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
normalizePlayletHomeConfig(&doc)
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyPlayletHomeConfig 按条件查询多条首页配置
|
||||
func FindManyPlayletHomeConfig(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletHomeConfigList, *srvdef.SrvErr) {
|
||||
data := make(PlayletHomeConfigList, 0)
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("查询首页配置列表失败", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
for _, item := range data {
|
||||
normalizePlayletHomeConfig(item)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountPlayletHomeConfig 统计满足条件的首页配置数量
|
||||
func CountPlayletHomeConfig(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter, opts...)
|
||||
if err != nil {
|
||||
log.Warn("统计首页配置失败", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOnePlayletHomeConfig 更新一条首页配置
|
||||
func UpdateOnePlayletHomeConfig(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
if mongo.IsDuplicateKeyError(err) {
|
||||
return srvdef.New(srvdef.ErrParamError, "slug已存在", "")
|
||||
}
|
||||
log.Warn("更新首页配置失败", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package playlethomeconfigmod
|
||||
|
||||
// TagPlayletHomeConfig 保存 playlet_home_config 集合字段名
|
||||
type TagPlayletHomeConfig struct {
|
||||
Id string
|
||||
Slug string
|
||||
Title string
|
||||
Desc string
|
||||
Label string
|
||||
Style string
|
||||
CardBackgroundImage string
|
||||
ModuleType string
|
||||
DataType string
|
||||
RecommendType string
|
||||
CategoryId string
|
||||
TopicIds string
|
||||
Rank string
|
||||
Enabled string
|
||||
Limit string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
PlayletHomeConfig TagPlayletHomeConfig
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
PlayletHomeConfig string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.PlayletHomeConfig.Id = "_id"
|
||||
FN.PlayletHomeConfig.Slug = "slug"
|
||||
FN.PlayletHomeConfig.Title = "title"
|
||||
FN.PlayletHomeConfig.Desc = "desc"
|
||||
FN.PlayletHomeConfig.Label = "label"
|
||||
FN.PlayletHomeConfig.Style = "style"
|
||||
FN.PlayletHomeConfig.CardBackgroundImage = "cardBackgroundImage"
|
||||
FN.PlayletHomeConfig.ModuleType = "moduleType"
|
||||
FN.PlayletHomeConfig.DataType = "dataType"
|
||||
FN.PlayletHomeConfig.RecommendType = "recommendType"
|
||||
FN.PlayletHomeConfig.CategoryId = "categoryId"
|
||||
FN.PlayletHomeConfig.TopicIds = "topicIds"
|
||||
FN.PlayletHomeConfig.Rank = "rank"
|
||||
FN.PlayletHomeConfig.Enabled = "enabled"
|
||||
FN.PlayletHomeConfig.Limit = "limit"
|
||||
FN.PlayletHomeConfig.CreatedAt = "createdAt"
|
||||
FN.PlayletHomeConfig.UpdatedAt = "updatedAt"
|
||||
|
||||
TN.PlayletHomeConfig = "playlet_home_config"
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package playlethomeconfigmod
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
RecommendTypeUpdated int64 = 1 // 按更新
|
||||
RecommendTypeLike int64 = 2 // 按点赞
|
||||
RecommendTypeBrowse int64 = 3 // 按观看
|
||||
RecommendTypeHeat int64 = 4 // 按热度
|
||||
RecommendTypeCategory int64 = 5 // 按分类
|
||||
DefaultLimit int64 = 30
|
||||
MaxLimit int64 = 100
|
||||
)
|
||||
|
||||
const (
|
||||
DataTypeAll int64 = 1 // 全部上架短剧
|
||||
DataTypeVideo int64 = 2 // 全部上架视频
|
||||
)
|
||||
|
||||
const (
|
||||
ModuleTypePlaylet int64 = 1 // 列表,具体为短剧或视频由 DataType 决定
|
||||
ModuleTypeTopic int64 = 2 // 专题
|
||||
)
|
||||
|
||||
const (
|
||||
StyleA = "A"
|
||||
StyleB = "B"
|
||||
StyleC = "C"
|
||||
StyleD = "D"
|
||||
StyleE = "E"
|
||||
StyleF = "F"
|
||||
StyleG = "G"
|
||||
StyleH = "H"
|
||||
)
|
||||
|
||||
// PlayletHomeConfig @table: playlet_home_config
|
||||
//
|
||||
// PlayletHomeConfig 短剧首页配置表
|
||||
type PlayletHomeConfig struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
Slug string `json:"slug" bson:"slug"` // 页面路径标识
|
||||
Title string `json:"title" bson:"title"` // 模块标题
|
||||
Desc string `json:"desc" bson:"desc"` // 模块描述
|
||||
Label string `json:"label" bson:"label"` // 样式名称
|
||||
Style string `json:"style" bson:"style"` // 样式 A-H
|
||||
CardBackgroundImage string `json:"cardBackgroundImage" bson:"cardBackgroundImage"` // 卡片背景图
|
||||
ModuleType int64 `json:"moduleType" bson:"moduleType"` // 模块类型 1列表 2专题,短剧或视频由 DataType 决定
|
||||
DataType int64 `json:"dataType" bson:"dataType"` // 数据类型 1全部上架短剧 2全部上架视频
|
||||
RecommendType int64 `json:"recommendType" bson:"recommendType"` // 推荐类型 1按更新 2按点赞 3按观看 4按热度 5按分类
|
||||
CategoryId int64 `json:"categoryId" bson:"categoryId"` // 按分类推荐时使用的分类ID
|
||||
TopicIds []int64 `json:"topicIds" bson:"topicIds"` // 专题模块关联的题材或视频分类ID
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序,越大越靠前
|
||||
Enabled bool `json:"enabled" bson:"enabled"` // 是否启用
|
||||
Limit int64 `json:"limit" bson:"limit"` // 展示条数
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
}
|
||||
|
||||
// PlayletHomeConfigList 首页配置列表
|
||||
type PlayletHomeConfigList []*PlayletHomeConfig
|
||||
@@ -0,0 +1,83 @@
|
||||
package playletlikemod
|
||||
|
||||
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_like 集合和常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.PlayletLike)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{Keys: bson.D{{Key: FN.PlayletLike.UserID, Value: 1}, {Key: FN.PlayletLike.PlayletID, Value: 1}}, Options: options.Index().SetUnique(true)},
|
||||
{Keys: bson.D{{Key: FN.PlayletLike.PlayletID, Value: 1}}},
|
||||
{Keys: bson.D{{Key: FN.PlayletLike.CreatedAt, Value: -1}, {Key: FN.PlayletLike.PlayletID, Value: 1}}},
|
||||
{Keys: bson.D{{Key: FN.PlayletLike.UserID, Value: 1}, {Key: FN.PlayletLike.CreatedAt, Value: -1}, {Key: FN.PlayletLike.Id, Value: -1}}},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(playletlikemod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// UpsertOnePlayletLike 按用户ID和短剧ID写入点赞关系,返回是否新增点赞
|
||||
func UpsertOnePlayletLike(ctx context.Context, userId, playletId int64, now time.Time) (bool, *srvdef.SrvErr) {
|
||||
filter := bson.M{FN.PlayletLike.UserID: userId, FN.PlayletLike.PlayletID: playletId}
|
||||
update := bson.M{
|
||||
"$set": bson.M{FN.PlayletLike.UpdatedAt: now},
|
||||
"$setOnInsert": bson.M{
|
||||
FN.PlayletLike.Id: mongos.Lid.PlayletLike.Get(),
|
||||
FN.PlayletLike.UserID: userId,
|
||||
FN.PlayletLike.PlayletID: playletId,
|
||||
FN.PlayletLike.CreatedAt: now,
|
||||
},
|
||||
}
|
||||
result, err := coll.UpdateOne(ctx, filter, update, options.Update().SetUpsert(true))
|
||||
if err != nil {
|
||||
log.Warn("playletlikemod:UpsertOnePlayletLike db.UpdateOne failed", log.Any("filter", filter), log.E(err))
|
||||
return false, srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return result.UpsertedCount > 0, nil
|
||||
}
|
||||
|
||||
// DeleteOnePlayletLike 删除一条短剧点赞关系,返回是否实际删除
|
||||
func DeleteOnePlayletLike(ctx context.Context, filter bson.M) (bool, *srvdef.SrvErr) {
|
||||
result, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletlikemod:DeleteOnePlayletLike db.DeleteOne failed", log.Any("filter", filter), log.E(err))
|
||||
return false, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return result > 0, nil
|
||||
}
|
||||
|
||||
// CountPlayletLike 统计短剧点赞关系数量
|
||||
func CountPlayletLike(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletlikemod:CountPlayletLike db.Count failed", log.Any("filter", filter), log.E(err))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// AggregatePlayletLike 聚合查询短剧点赞关系
|
||||
func AggregatePlayletLike(ctx context.Context, bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
|
||||
if err := coll.Aggregate(ctx, bind, pipeline); err != nil {
|
||||
log.Warn("playletlikemod:AggregatePlayletLike db.Aggregate failed", log.Any("pipeline", pipeline), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package playletlikemod
|
||||
|
||||
// TagPlayletLike 保存 playlet_like 集合字段名
|
||||
type TagPlayletLike struct {
|
||||
Id string
|
||||
UserID string
|
||||
PlayletID string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
PlayletLike TagPlayletLike
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
PlayletLike string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.PlayletLike.Id = "_id"
|
||||
FN.PlayletLike.UserID = "userId"
|
||||
FN.PlayletLike.PlayletID = "playletId"
|
||||
FN.PlayletLike.CreatedAt = "createdAt"
|
||||
FN.PlayletLike.UpdatedAt = "updatedAt"
|
||||
|
||||
TN.PlayletLike = "playlet_like"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package playletlikemod
|
||||
|
||||
import "time"
|
||||
|
||||
// PlayletLike 短剧点赞关系
|
||||
type PlayletLike struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
UserID int64 `json:"userId" bson:"userId"` // 用户ID
|
||||
PlayletID int64 `json:"playletId" bson:"playletId"` // 短剧ID
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
|
||||
}
|
||||
|
||||
// PlayletLikeList 短剧点赞列表
|
||||
type PlayletLikeList []*PlayletLike
|
||||
@@ -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)
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package playlettagmod
|
||||
|
||||
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_tag 集合和常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.PlayletTag)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletTag.Status, Value: 1},
|
||||
{Key: FN.PlayletTag.Rank, Value: -1},
|
||||
{Key: FN.PlayletTag.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletTag.Name, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletTag.CreatedAt, Value: -1},
|
||||
{Key: FN.PlayletTag.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(playlettagmod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOnePlayletTag 插入一条标签数据
|
||||
func InsertOnePlayletTag(ctx context.Context, doc *PlayletTag) *srvdef.SrvErr {
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.PlayletTag.Get()
|
||||
}
|
||||
now := time.Now()
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
doc.UpdatedAt = now
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("playlettagmod:InsertOnePlayletTag failed", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOnePlayletTag 删除一条标签数据
|
||||
func DelOnePlayletTag(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playlettagmod:DelOnePlayletTag failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOnePlayletTag 查询一条标签数据
|
||||
func FindOnePlayletTag(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*PlayletTag, *srvdef.SrvErr) {
|
||||
var doc PlayletTag
|
||||
if err := coll.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("playlettagmod:FindOnePlayletTag failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyPlayletTag 按条件查询多条标签数据
|
||||
func FindManyPlayletTag(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletTagList, *srvdef.SrvErr) {
|
||||
data := make(PlayletTagList, 0)
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("playlettagmod:FindManyPlayletTag failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountPlayletTag 统计满足条件的标签数量
|
||||
func CountPlayletTag(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter, opts...)
|
||||
if err != nil {
|
||||
log.Warn("playlettagmod:CountPlayletTag failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOnePlayletTag 更新一条标签数据
|
||||
func UpdateOnePlayletTag(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("playlettagmod:UpdateOnePlayletTag failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package playlettagmod
|
||||
|
||||
// TagPlayletTag 保存 playlet_tag 集合字段名
|
||||
type TagPlayletTag struct {
|
||||
Id string
|
||||
Name string
|
||||
Status string
|
||||
Rank string
|
||||
SeoInfo struct {
|
||||
Description string
|
||||
Keyworld string
|
||||
Title string
|
||||
}
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
PlayletTag TagPlayletTag
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
PlayletTag string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.PlayletTag.Id = "_id"
|
||||
FN.PlayletTag.Name = "name"
|
||||
FN.PlayletTag.Status = "status"
|
||||
FN.PlayletTag.Rank = "rank"
|
||||
FN.PlayletTag.SeoInfo.Description = "seoInfo.webDescription"
|
||||
FN.PlayletTag.SeoInfo.Keyworld = "seoInfo.webKeyworld"
|
||||
FN.PlayletTag.SeoInfo.Title = "seoInfo.webTitle"
|
||||
FN.PlayletTag.CreatedAt = "createdAt"
|
||||
FN.PlayletTag.UpdatedAt = "updatedAt"
|
||||
|
||||
TN.PlayletTag = "playlet_tag"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package playlettagmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
// PlayletTag @table: playlet_tag
|
||||
//
|
||||
// PlayletTag 短剧标签集合模型
|
||||
type PlayletTag struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"` // ID
|
||||
Name string `json:"name" bson:"name"` // 标签名称
|
||||
Status bool `json:"status" bson:"status"` // 上架状态
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序,越大越靠前
|
||||
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
}
|
||||
|
||||
// PlayletTagList 标签列表
|
||||
type PlayletTagList []*PlayletTag
|
||||
@@ -0,0 +1,42 @@
|
||||
package playletthememod
|
||||
|
||||
// TagPlayletTheme 保存 playlet_theme 集合字段名
|
||||
type TagPlayletTheme struct {
|
||||
Id string
|
||||
Name string
|
||||
Slug string
|
||||
Icon string
|
||||
Status string
|
||||
Rank string
|
||||
SeoInfo struct {
|
||||
Description string
|
||||
Keyworld string
|
||||
Title string
|
||||
}
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
PlayletTheme TagPlayletTheme
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
PlayletTheme string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.PlayletTheme.Id = "_id"
|
||||
FN.PlayletTheme.Name = "name"
|
||||
FN.PlayletTheme.Slug = "slug"
|
||||
FN.PlayletTheme.Icon = "icon"
|
||||
FN.PlayletTheme.Status = "status"
|
||||
FN.PlayletTheme.Rank = "rank"
|
||||
FN.PlayletTheme.SeoInfo.Description = "seoInfo.webDescription"
|
||||
FN.PlayletTheme.SeoInfo.Keyworld = "seoInfo.webKeyworld"
|
||||
FN.PlayletTheme.SeoInfo.Title = "seoInfo.webTitle"
|
||||
FN.PlayletTheme.CreatedAt = "createdAt"
|
||||
FN.PlayletTheme.UpdatedAt = "updatedAt"
|
||||
|
||||
TN.PlayletTheme = "playlet_theme"
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package playletthememod
|
||||
|
||||
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_theme 集合和常用查询索引
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.PlayletTheme)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletTheme.Status, Value: 1},
|
||||
{Key: FN.PlayletTheme.Rank, Value: -1},
|
||||
{Key: FN.PlayletTheme.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletTheme.Name, Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.PlayletTheme.CreatedAt, Value: -1},
|
||||
{Key: FN.PlayletTheme.Id, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(playletthememod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOnePlayletTheme 插入一条题材数据
|
||||
func InsertOnePlayletTheme(ctx context.Context, doc *PlayletTheme) *srvdef.SrvErr {
|
||||
if doc.Id == 0 {
|
||||
doc.Id = mongos.Lid.PlayletTheme.Get()
|
||||
}
|
||||
now := time.Now()
|
||||
if doc.CreatedAt.IsZero() {
|
||||
doc.CreatedAt = now
|
||||
}
|
||||
doc.UpdatedAt = now
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("playletthememod:InsertOnePlayletTheme failed", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOnePlayletTheme 删除一条题材数据
|
||||
func DelOnePlayletTheme(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("playletthememod:DelOnePlayletTheme failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOnePlayletTheme 查询一条题材数据
|
||||
func FindOnePlayletTheme(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*PlayletTheme, *srvdef.SrvErr) {
|
||||
var doc PlayletTheme
|
||||
if err := coll.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Warn("playletthememod:FindOnePlayletTheme failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindManyPlayletTheme 按条件查询多条题材数据
|
||||
func FindManyPlayletTheme(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletThemeList, *srvdef.SrvErr) {
|
||||
data := make(PlayletThemeList, 0)
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("playletthememod:FindManyPlayletTheme failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountPlayletTheme 统计满足条件的题材数量
|
||||
func CountPlayletTheme(ctx context.Context, filter bson.M, opts ...*options.CountOptions) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter, opts...)
|
||||
if err != nil {
|
||||
log.Warn("playletthememod:CountPlayletTheme failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOnePlayletTheme 更新一条题材数据
|
||||
func UpdateOnePlayletTheme(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := coll.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("playletthememod:UpdateOnePlayletTheme failed", log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
return srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package playletthememod
|
||||
|
||||
import (
|
||||
"time"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
// PlayletTheme @table: playlet_theme
|
||||
//
|
||||
// PlayletTheme 短剧题材集合模型
|
||||
type PlayletTheme struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
Name string `json:"name" bson:"name"` // 题材名称
|
||||
Slug string `json:"slug" bson:"slug"` // slug
|
||||
Icon string `json:"icon" bson:"icon"` // 图标
|
||||
Status bool `json:"status" bson:"status"` // 上架状态
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序,越大越靠前
|
||||
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
|
||||
}
|
||||
|
||||
// PlayletThemeList 题材列表
|
||||
type PlayletThemeList []*PlayletTheme
|
||||
@@ -0,0 +1,88 @@
|
||||
package questionnairemod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"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 db *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
db = mongos.Shop.Coll(TN.Questionnaire)
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Questionnaire.Status, Value: 1},
|
||||
{Key: FN.Questionnaire.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.Questionnaire.CreatedAt, Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(questionnaire:Init) Create Index failed! err:%+v", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOne 插入一条问卷
|
||||
func InsertOne(ctx context.Context, doc *QuestionnaireModel) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, doc); err != nil {
|
||||
log.Warn("questionnairemod:InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindOne 查找一条问卷
|
||||
func FindOne(ctx context.Context, filter bson.M, opts ...*options.FindOneOptions) (*QuestionnaireModel, *srvdef.SrvErr) {
|
||||
var doc QuestionnaireModel
|
||||
if err := db.FindOneEx(ctx, &doc, filter, opts...); err != nil {
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
log.Warn("questionnairemod:FindOne failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
// FindMany 查找多条问卷
|
||||
func FindMany(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (QuestionnaireModelList, *srvdef.SrvErr) {
|
||||
data := make(QuestionnaireModelList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("questionnairemod:FindMany failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// Count 统计问卷数量
|
||||
func Count(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("questionnairemod:Count failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOne 更新一条问卷,返回 MatchedCount
|
||||
func UpdateOne(ctx context.Context, filter bson.M, update bson.M) (int64, *srvdef.SrvErr) {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("questionnairemod:UpdateOne failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return result.MatchedCount, nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user