Initial commit

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-23 11:07:42 +08:00
co-authored by Claude Opus 5.5
commit 7974a42301
633 changed files with 120248 additions and 0 deletions
+182
View File
@@ -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
}
+42
View File
@@ -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"
}
+27
View File
@@ -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
+182
View File
@@ -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
}
+42
View File
@@ -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"
}
+27
View File
@@ -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
+102
View File
@@ -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
}
+30
View File
@@ -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"
}
+17
View File
@@ -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
+9
View File
@@ -0,0 +1,9 @@
package cfg
import (
"videoweb/pub/mongos"
)
var (
sysCfgColl *mongos.Collection
)
+55
View File
@@ -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
}
+88
View File
@@ -0,0 +1,88 @@
package cfg
type TagSysCfg struct {
AppAddr string
OfficialAppAddr 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
CustomerServiceHost string
WeiChart string
DHNewUrlAddr1 string
DHNewUrlAddr2 string
DHNewUrlAddr3 string
DHForeverUrlAddr string
DHTitle string
DHKeyworld string
DHDescription string
DHSiteName string
ChannelCode string
EnableH265 string
}
var FN struct {
SysCfg TagSysCfg
}
var TN struct {
SysCfg string
}
func init() {
FN.SysCfg.AppAddr = "appAddr"
FN.SysCfg.OfficialAppAddr = "officialAppAddr"
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.CustomerServiceHost = "customerServiceHost"
FN.SysCfg.WeiChart = "weiChart"
FN.SysCfg.DHNewUrlAddr1 = "dHNewUrlAddr1"
FN.SysCfg.DHNewUrlAddr2 = "dHNewUrlAddr2"
FN.SysCfg.DHNewUrlAddr3 = "dHNewUrlAddr3"
FN.SysCfg.DHForeverUrlAddr = "dHForeverUrlAddr"
FN.SysCfg.DHTitle = "dhTitle"
FN.SysCfg.DHKeyworld = "dhKeyworld"
FN.SysCfg.DHDescription = "dhDescription"
FN.SysCfg.DHSiteName = "dhSiteName"
FN.SysCfg.ChannelCode = "channelCode"
FN.SysCfg.EnableH265 = "enableH265"
TN.SysCfg = "sys_cfg"
}
+58
View File
@@ -0,0 +1,58 @@
package cfg
// @table:sys_cfg
type SysCfg struct {
Id int64 `json:"id" bson:"_id"`
UnencryptedCdn string `json:"unencryptedCdn" bson:"unencryptedCdn"` // 不加密资源使用的cdn
SitemapDefaultImages []string `json:"sitemapDefaultImages" bson:"sitemapDefaultImages"` // Sitemap里面默认封面图
ImgAppCdn string `json:"imgAppCdn" bson:"imgAppCdn"` // 图片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使用)
ImgAppUsCdn string `json:"imgAppUsCdn" bson:"imgAppUsCdn"` // 图片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
CustomerServiceHost string `json:"customerServiceHost" bson:"customerServiceHost"` // 在线客服
//网站管理
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下载地址(落地页)
OfficialAppAddr string `json:"officialAppAddr" bson:"officialAppAddr"` //官网app地址
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"` // 所有使用中的域名
AdvitiesTopicNum int64 `json:"advitiesTopicNum" bson:"advitiesTopicNum"` // 广告间隔
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网站名称
ActressBackGround string `json:"actressBackGround" bson:"actressBackGround"` // 女优通用背景图
ChannelCode string `json:"channelCode" bson:"channelCode"` // 渠道码
EnableH265 bool `json:"enableH265" bson:"enableH265"` // 是否允许客户端使用 H265 地址播放
}
+40
View File
@@ -0,0 +1,40 @@
package cointransmod
type TagCoinTrans struct {
Id string
UserId string
UserName string
FlowDir string
TranType string
Amount string
BalanceBefore string
BalanceAfter string
OrderNo string
RelatedId string
Remark string
CreatedAt string
}
var FN struct {
CoinTrans TagCoinTrans
}
var TN struct {
CoinTrans string
}
func init() {
FN.CoinTrans.Id = "_id"
FN.CoinTrans.UserId = "userId"
FN.CoinTrans.UserName = "userName"
FN.CoinTrans.FlowDir = "flowDir"
FN.CoinTrans.TranType = "tranType"
FN.CoinTrans.Amount = "amount"
FN.CoinTrans.BalanceBefore = "balanceBefore"
FN.CoinTrans.BalanceAfter = "balanceAfter"
FN.CoinTrans.OrderNo = "orderNo"
FN.CoinTrans.RelatedId = "relatedId"
FN.CoinTrans.Remark = "remark"
FN.CoinTrans.CreatedAt = "createdAt"
TN.CoinTrans = "coin_trans"
}
+80
View File
@@ -0,0 +1,80 @@
package cointransmod
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 coll *mongos.Collection
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.CoinTrans)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
// 按用户+时间倒序查流水(最常用)
{Keys: bson.D{
{Key: FN.CoinTrans.UserId, Value: 1},
{Key: FN.CoinTrans.CreatedAt, Value: -1},
}},
// 按交易类型筛选
{Keys: bson.D{{Key: FN.CoinTrans.TranType, Value: 1}}},
// 按订单号查(幂等校验)
{Keys: bson.D{{Key: FN.CoinTrans.OrderNo, Value: 1}}},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(cointransmod:initIndex) Create Index failed! err:%+v:", err))
}
}
// InsertOneCoinTrans 写入一条流水记录
func InsertOneCoinTrans(ctx context.Context, doc *CoinTrans) *srvdef.SrvErr {
if _, err := coll.InsertOne(ctx, doc); err != nil {
log.Error("cointransmod:InsertOneCoinTrans failed", log.Any("doc", doc), log.E(err))
return srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return nil
}
// FindManyCoinTrans 分页查询流水列表
func FindManyCoinTrans(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (CoinTransList, *srvdef.SrvErr) {
var data CoinTransList
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
log.Warn("cointransmod:FindManyCoinTrans failed", log.E(err), log.Any("filter", filter))
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return data, nil
}
// CountCoinTrans 统计流水条数
func CountCoinTrans(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
count, err := coll.Count(ctx, filter)
if err != nil {
log.Warn("cointransmod:CountCoinTrans failed", log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return count, nil
}
// StatSyncConsumeList 按 ID 游标增量拉取金币消费流水(统计中心)
func StatSyncConsumeList(ctx context.Context, startId int64, size int64) (CoinTransList, error) {
opt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.D{{Key: FN.CoinTrans.Id, Value: 1}})
filter := bson.M{
FN.CoinTrans.Id: bson.M{"$gt": startId},
FN.CoinTrans.FlowDir: FlowOut,
}
list := CoinTransList{}
if err := coll.Find(ctx, &list, filter, opt); err != nil {
return nil, err
}
return list, nil
}
+62
View File
@@ -0,0 +1,62 @@
package cointransmod
import "time"
// FlowDir 收支方向
type FlowDir int8
const (
FlowIn FlowDir = 1 // 收入(充值、赠送)
FlowOut FlowDir = -1 // 支出(消费、解锁)
)
func (f FlowDir) Desc() string {
if f == FlowIn {
return "收入"
}
return "支出"
}
// TranType 交易类型
type TranType int32
const (
TranTypeCoinRecharge TranType = 1 // 金币充值(购买金币)
TranTypeVipGiftCoin TranType = 2 // 购买会员赠送金币
TranTypeDarkAlley TranType = 3 // 历史遗留交易类型(已下线)
TranTypeVideoUnlock TranType = 4 // 视频解锁
TranTypeAdminAdjust TranType = 5 // 管理员手动调整
)
var TranTypeNameMap = map[TranType]string{
TranTypeCoinRecharge: "金币充值",
TranTypeVipGiftCoin: "会员赠送",
TranTypeDarkAlley: "历史交易",
TranTypeVideoUnlock: "视频解锁",
TranTypeAdminAdjust: "管理员调整",
}
func (t TranType) Desc() string {
if name, ok := TranTypeNameMap[t]; ok {
return name
}
return "未知"
}
// @table: coin_trans
type CoinTrans struct {
Id int64 `json:"id" bson:"_id"` // 唯一ID
UserId int64 `json:"userId" bson:"userId"` // 用户ID
UserName string `json:"userName" bson:"userName"` // 用户昵称(快照)
FlowDir FlowDir `json:"flowDir" bson:"flowDir"` // 收支方向:1收入 -1支出
TranType TranType `json:"tranType" bson:"tranType"` // 交易类型
Amount int64 `json:"amount" bson:"amount"` // 本次交易金币数(正整数)
BalanceBefore int64 `json:"balanceBefore" bson:"balanceBefore"` // 交易前余额
BalanceAfter int64 `json:"balanceAfter" bson:"balanceAfter"` // 交易后余额
OrderNo string `json:"orderNo" bson:"orderNo"` // 关联订单号(可为空)
RelatedId int64 `json:"relatedId" bson:"relatedId"` // 关联内容ID(视频等,可为空)
Remark string `json:"remark" bson:"remark"` // 备注描述
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 交易时间
}
type CoinTransList []*CoinTrans
+90
View File
@@ -0,0 +1,90 @@
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"
)
var coll *mongos.Collection
// Init 初始化 comment_like 集合和常用查询索引
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.CommentLike)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.CommentLike.UserId, Value: 1},
{Key: FN.CommentLike.CommentId, Value: 1},
},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{
{Key: FN.CommentLike.CommentId, Value: 1},
{Key: FN.CommentLike.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.CommentLike.ObjectType, Value: 1},
{Key: FN.CommentLike.ObjectId, Value: 1},
{Key: FN.CommentLike.CreatedAt, Value: -1},
},
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(commentlikemod:initIndex) 创建索引失败 err:%+v:", err))
}
}
// InsertOneCommentLike 插入一条评论点赞关系
func InsertOneCommentLike(ctx context.Context, doc *CommentLike) (bool, *srvdef.SrvErr) {
if doc.Id == 0 {
doc.Id = mongos.Lid.CommentLike.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) {
return false, nil
}
log.Warn("插入评论点赞关系失败", log.Any("doc", doc), log.E(err))
return false, srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return true, nil
}
// DeleteOneCommentLike 删除一条评论点赞关系
func DeleteOneCommentLike(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
count, err := coll.DeleteOne(ctx, filter)
if err != nil {
log.Warn("删除评论点赞关系失败", log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
}
return count, nil
}
// FindManyCommentLike 按条件查询评论点赞关系
func FindManyCommentLike(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (CommentLikeList, *srvdef.SrvErr) {
data := make(CommentLikeList, 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, "", "")
}
return data, nil
}
+32
View File
@@ -0,0 +1,32 @@
package commentlikemod
// TagCommentLike 保存 comment_like 集合字段名
type TagCommentLike struct {
Id string
UserId string
CommentId string
ObjectId string
ObjectType string
CreatedAt string
UpdatedAt string
}
var FN struct {
CommentLike TagCommentLike
}
var TN struct {
CommentLike string
}
func init() {
FN.CommentLike.Id = "_id"
FN.CommentLike.UserId = "userId"
FN.CommentLike.CommentId = "commentId"
FN.CommentLike.ObjectId = "objectId"
FN.CommentLike.ObjectType = "objectType"
FN.CommentLike.CreatedAt = "createdAt"
FN.CommentLike.UpdatedAt = "updatedAt"
TN.CommentLike = "comment_like"
}
+19
View File
@@ -0,0 +1,19 @@
package commentlikemod
import "time"
// CommentLike @table: comment_like
//
// CommentLike 评论点赞关系模型
type CommentLike struct {
Id int64 `json:"id" bson:"_id,omitempty"` // 点赞记录ID
UserId int64 `json:"userId" bson:"userId"` // 用户ID
CommentId int64 `json:"commentId" bson:"commentId"` // 评论ID
ObjectId int64 `json:"objectId" bson:"objectId"` // 评论对象ID
ObjectType int64 `json:"objectType" bson:"objectType"` // 评论对象类型 10-短剧 11-短剧剧集
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
}
// CommentLikeList 评论点赞关系列表
type CommentLikeList []*CommentLike
+226
View File
@@ -0,0 +1,226 @@
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.ParentsId, Value: 1},
{Key: FN.Comment.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.Comment.UserId, Value: 1},
{Key: FN.Comment.ObjectType, 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.ParentsId, Value: 1},
{Key: FN.Comment.CountLike, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.Comment.ParentsId, Value: 1},
{Key: FN.Comment.Level, Value: 1},
{Key: FN.Comment.ReviewStatus, Value: 1},
{Key: FN.Comment.CreatedAt, Value: 1},
{Key: FN.Comment.Id, 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
}
// 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
}
+54
View File
@@ -0,0 +1,54 @@
package commentmod
type TagComment struct {
CreatedAt string
Id string
Level string
ObjectId string
ParentsId string
ReplyCommentId string
ReplyUserName string
Text string
TopRank string
UpdatedAt string
UserId string
UserName string
UserAvatar 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.ReplyCommentId = "replyCommentId"
FN.Comment.ReplyUserName = "replyUserName"
FN.Comment.Text = "text"
FN.Comment.TopRank = "topRank"
FN.Comment.UpdatedAt = "updatedAt"
FN.Comment.UserId = "userId"
FN.Comment.UserName = "userName"
FN.Comment.UserAvatar = "userAvatar"
FN.Comment.ReviewStatus = "reviewStatus"
FN.Comment.Ip = "ip"
FN.Comment.CommentCount = "commentCount"
FN.Comment.CountLike = "countLike"
FN.Comment.ObjectName = "objectName"
FN.Comment.ObjectType = "objectType"
TN.Comment = "_comment"
}
+31
View File
@@ -0,0 +1,31 @@
package commentmod
import (
"time"
)
// 评论管理
// @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 int64 `json:"objectType" bson:"objectType"` // 对象类型
ObjectName string `json:"objectName" bson:"objectName"` // 对象名
UserId int64 `json:"userId" bson:"userId"` // 评论用户ID
UserName string `json:"userName" bson:"userName"` // 用户名称
UserAvatar string `json:"userAvatar" bson:"userAvatar"` // 评论用户头像
Level int64 `json:"level" bson:"level"` // 评论级别,1-一级评论 2-二级评论
ParentsId int64 `json:"parentsId" bson:"parentsId"` // 上级评论ID,一级评论为0
ReplyCommentId int64 `json:"replyCommentId" bson:"replyCommentId"` // 被回复评论ID,一级评论为0
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
+100
View File
@@ -0,0 +1,100 @@
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 coll *mongos.Collection
// Init 初始化 contactus 集合和常用查询索引
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.ContactUs)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.ContactUs.UserId, Value: 1},
{Key: FN.ContactUs.CreatedAt, Value: -1},
{Key: FN.ContactUs.Id, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.ContactUs.Status, Value: 1},
{Key: FN.ContactUs.CreatedAt, Value: -1},
{Key: FN.ContactUs.Id, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.ContactUs.QuestionType, Value: 1},
{Key: FN.ContactUs.CreatedAt, Value: -1},
{Key: FN.ContactUs.Id, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.ContactUs.CreatedAt, Value: -1},
{Key: FN.ContactUs.Id, Value: -1},
},
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(contactusmod:initIndex) Create Index failed! err:%+v:", err))
}
}
// InsertOneContactUs 插入一条联系我们数据
//
// 当 doc.Id 为空时,会使用 mongos.Lid.ContactUs 自动生成自增ID
func InsertOneContactUs(ctx context.Context, doc *ContactUs) *srvdef.SrvErr {
if doc.Id == 0 {
doc.Id = mongos.Lid.ContactUs.Get()
}
if _, err := coll.InsertOne(ctx, doc); err != nil {
log.Warn("联系我们记录写入失败", log.Any("doc", doc), log.E(err))
return srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return nil
}
// FindManyContactUs 按条件查询多条联系我们数据
func FindManyContactUs(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (ContactUsList, *srvdef.SrvErr) {
var data ContactUsList
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, "", "")
}
return data, nil
}
// CountContactUs 统计满足条件的联系我们数量
func CountContactUs(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
}
// UpdateManyContactUsWithResult 批量更新联系我们数据,并返回命中数量和修改数量
func UpdateManyContactUsWithResult(ctx context.Context, filter bson.M, update bson.M) (matchedCount int64, modifiedCount int64, serr *srvdef.SrvErr) {
result, err := coll.UpdateMany(ctx, filter, update)
if err != nil {
log.Warn("联系我们批量更新失败", log.E(err), log.Any("filter", filter))
return 0, 0, srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
return result.MatchedCount, result.ModifiedCount, nil
}
+40
View File
@@ -0,0 +1,40 @@
package contactusmod
// TagContactUs 保存contactus集合字段名
type TagContactUs struct {
Id string
UserId string
Email string
QuestionType string
Title string
Content string
Attachments string
Status string
Remark string
CreatedAt string
UpdatedAt string
}
var FN struct {
ContactUs TagContactUs
}
var TN struct {
ContactUs string
}
func init() {
FN.ContactUs.Id = "_id"
FN.ContactUs.UserId = "userId"
FN.ContactUs.Email = "email"
FN.ContactUs.QuestionType = "questionType"
FN.ContactUs.Title = "title"
FN.ContactUs.Content = "content"
FN.ContactUs.Attachments = "attachments"
FN.ContactUs.Status = "status"
FN.ContactUs.Remark = "remark"
FN.ContactUs.CreatedAt = "createdAt"
FN.ContactUs.UpdatedAt = "updatedAt"
TN.ContactUs = "contactus"
}
+34
View File
@@ -0,0 +1,34 @@
package contactusmod
import "time"
// ContactUs @table: contactus
//
// ContactUs 联系我们集合模型
type ContactUs struct {
// ID
Id int64 `json:"id" bson:"_id,omitempty"`
// 用户ID
UserId int64 `json:"userId" bson:"userId"`
// 邮箱
Email string `json:"email" bson:"email"`
// 问题类型,1-订单问题、2-账号问题、3-功能问题、4-体验问题、5-其他
QuestionType int32 `json:"questionType" bson:"questionType"`
// 标题
Title string `json:"title" bson:"title"`
// 内容
Content string `json:"content" bson:"content"`
// 附件地址,可存放多张图片或文件地址
Attachments []string `json:"attachments" bson:"attachments"`
// 处理状态,0-待处理、1-已处理
Status int32 `json:"status" bson:"status"`
// 处理备注
Remark string `json:"remark" bson:"remark,omitempty"`
// 创建时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
// 更新时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
}
// ContactUsList 联系我们列表
type ContactUsList []*ContactUs
+102
View File
@@ -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
}
+30
View File
@@ -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"
}
+21
View File
@@ -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
+58
View File
@@ -0,0 +1,58 @@
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 = "webhgdj_video_index_v3"
playletIndex = "webhgdj_playlet_index_v1"
)
func GetVideoIndex() string {
return videoIndex
}
func GetPlayletIndex() string {
return playletIndex
}
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
}
+277
View File
@@ -0,0 +1,277 @@
package esmod
import (
"context"
"fmt"
"videoweb/pub/common/log"
"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
}
initPlayletIndex(playletIndex)
}
// 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 {
log.Warn("初始化视频ES索引失败,跳过索引创建", log.Any("索引", esIndex), log.E(err))
}
}
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.OperateType: esmanager.M{
"type": "integer",
},
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.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.PlayName: esmanager.M{
"type": "text",
"analyzer": esmanager.AnalyzerIkMaxWord,
"search_analyzer": esmanager.AnalyzerIkSmart,
},
FN.ESPlaylet.Description: esmanager.M{
"type": "keyword",
"index": false,
},
FN.ESPlaylet.Slug: esmanager.M{
"type": "keyword",
},
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.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",
},
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,
},
},
},
},
},
}
if err := esmanager.Instance.InitIndices(esIndex, setting); err != nil {
log.Warn("初始化短剧ES索引失败,跳过索引创建", log.Any("索引", esIndex), log.E(err))
}
}
+144
View File
@@ -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
}
+295
View File
@@ -0,0 +1,295 @@
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
OperateType string
ShowOnBanner string
Banner string
OnlineAt string
ThemeIds string
ThemeNames string
Title string
PlayName string
Description string
Slug string
Desc string
Anchor string
Cover string
TagIds string
TagNames string
TotalEpisode string
UpdateStatus string
CountBrowse string
HeatValue string
CountCollect string
CountLike string
UpdatedAt string
CreatedAt string
SeoInfo string
}
type TagESActress struct {
Id string
Alias string
Avatar string
Meas string
Office string
DebutDate string
BornDate string
Region string
Score string
Works 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
}
type TagESPost struct {
Id string
CreateId string
Title string
Cover string
Thumb string
TagIds string
Kind string
Nodes string
VideoId string
Status string
Remark string
Rank string
AddedTime string
Real struct {
WatchTimes string
ShowTimes string
Comments string
WeekWatchs string
MonthWatchs string
TodayWatchs string
}
CreatedAt string
UpdatedAt string
Keyworlds string
FirstTag string
Desc string
IsHot string
Sort string
}
var FN struct {
ESRecord TagESRecord
ESVideo TagESVideo
ESPlaylet TagESPlaylet
ESActress TagESActress
ESPost TagESPost
}
var TN struct {
ESRecord string
ESVideo string
ESPlaylet string
ESActress string
ESPost 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",
OperateType: "operateType",
ShowOnBanner: "showOnBanner",
Banner: "banner",
OnlineAt: "onlineAt",
ThemeIds: "themeIds",
ThemeNames: "themeNames",
Title: "title",
PlayName: "playName",
Description: "description",
Slug: "slug",
Desc: "desc",
Anchor: "anchor",
Cover: "cover",
TagIds: "tagIds",
TagNames: "tagNames",
TotalEpisode: "totalEpisode",
UpdateStatus: "updateStatus",
CountBrowse: "countBrowse",
HeatValue: "heatValue",
CountCollect: "countCollect",
CountLike: "countLike",
UpdatedAt: "updatedAt",
CreatedAt: "createdAt",
SeoInfo: "seoInfo",
}
FN.ESActress = TagESActress{
Id: "_id",
Alias: "alias",
Avatar: "avatar",
Meas: "meas",
Office: "office",
DebutDate: "debutDate",
BornDate: "bornDate",
Region: "region",
Score: "score",
Works: "works",
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",
}
FN.ESPost = TagESPost{
Id: "_id",
CreateId: "createId",
Title: "title",
Cover: "cover",
Thumb: "thumb",
TagIds: "tagIds",
Kind: "kind",
Nodes: "nodes",
VideoId: "videoId",
Status: "status",
Remark: "remark",
Rank: "rank",
AddedTime: "addedTime",
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"},
CreatedAt: "createdAt",
UpdatedAt: "updatedAt",
Keyworlds: "keyworlds",
FirstTag: "firstTag",
Desc: "desc",
IsHot: "isHot",
Sort: "sort",
}
TN.ESRecord = "es_record"
TN.ESVideo = "es_video"
TN.ESPlaylet = "es_playlet"
TN.ESActress = "es_actress"
TN.ESPost = "es_post"
}
+134
View File
@@ -0,0 +1,134 @@
//go:generate gen_bson_tag -m esmod
//esmod essearch数据结构定义
package esmod
import (
"time"
"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 videoinformationmod.InformationSatus `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"` // 视频
CategoryIds []int64 `json:"categoryIds" bson:"categoryIds"` // 分类Id
Tags []int64 `json:"tags" bson:"tags"` // 标签
Real videoinformationmod.Flow `json:"real" bson:"real"` // 真实流量
VideoCount int64 `json:"videoCount" bson:"videoCount"` // 合集视频数量
}
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"` // 是否爆剧(true-是,false-否)
IsRecommend bool `json:"isRecommend" bson:"isRecommend"` // 是否推荐 true-推荐,false-不推荐
OperateType playletmod.OperateType `json:"operateType" bson:"operateType"` // 运营类型 1-短剧 2-漫剧
ShowOnBanner bool `json:"showOnBanner" bson:"showOnBanner"` // 是否显示在首页banner
Banner string `json:"banner" bson:"banner"` // banner图
OnlineAt time.Time `json:"onlineAt" bson:"onlineAt"` // 上架时间
ThemeIds []int64 `json:"themeIds" bson:"themeIds"` // 题材ID集合
ThemeNames []string `json:"themeNames" bson:"themeNames"` // 题材名称集合
Title string `json:"title" bson:"title"` // 标题
PlayName string `json:"playName" bson:"playName"` // 剧名
Description string `json:"description" bson:"description"` // SEO Description
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"` // 封面
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"` // 展示点赞数
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
}
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"`
}
+47
View File
@@ -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))
}
}
+130
View File
@@ -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
}
+31
View File
@@ -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"
}
+32
View File
@@ -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"` // 修改时间
}
+53
View File
@@ -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
}
+93
View File
@@ -0,0 +1,93 @@
package feedbackmod
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 coll *mongos.Collection
// Init 初始化 feedback 集合和常用查询索引
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.Feedback)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.Feedback.UserId, Value: 1},
{Key: FN.Feedback.CreatedAt, Value: -1},
{Key: FN.Feedback.Id, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.Feedback.Status, Value: 1},
{Key: FN.Feedback.CreatedAt, Value: -1},
{Key: FN.Feedback.Id, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.Feedback.CreatedAt, Value: -1},
{Key: FN.Feedback.Id, Value: -1},
},
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(feedbackmod:initIndex) Create Index failed! err:%+v:", err))
}
}
// InsertOneFeedback 插入一条用户意见反馈数据
//
// 当 doc.Id 为空时,会使用 mongos.Lid.Feedback 自动生成自增ID
func InsertOneFeedback(ctx context.Context, doc *Feedback) *srvdef.SrvErr {
if doc.Id == 0 {
doc.Id = mongos.Lid.Feedback.Get()
}
if _, err := coll.InsertOne(ctx, doc); err != nil {
log.Warn("用户意见反馈写入失败", log.Any("doc", doc), log.E(err))
return srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return nil
}
// FindManyFeedback 按条件查询多条用户意见反馈数据
func FindManyFeedback(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (FeedbackList, *srvdef.SrvErr) {
var data FeedbackList
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, "", "")
}
return data, nil
}
// CountFeedback 统计满足条件的用户意见反馈数量
func CountFeedback(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
}
// UpdateManyFeedbackWithResult 批量更新用户意见反馈数据,并返回命中数量和修改数量
func UpdateManyFeedbackWithResult(ctx context.Context, filter bson.M, update bson.M) (matchedCount int64, modifiedCount int64, serr *srvdef.SrvErr) {
result, err := coll.UpdateMany(ctx, filter, update)
if err != nil {
log.Warn("用户意见反馈批量更新失败", log.E(err), log.Any("filter", filter))
return 0, 0, srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
return result.MatchedCount, result.ModifiedCount, nil
}
+38
View File
@@ -0,0 +1,38 @@
package feedbackmod
// TagFeedback 保存feedback集合字段名
type TagFeedback struct {
Id string
UserId string
FeedbackType string
Content string
Screenshots string
Contact string
Status string
Remark string
CreatedAt string
UpdatedAt string
}
var FN struct {
Feedback TagFeedback
}
var TN struct {
Feedback string
}
func init() {
FN.Feedback.Id = "_id"
FN.Feedback.UserId = "userId"
FN.Feedback.FeedbackType = "feedbackType"
FN.Feedback.Content = "content"
FN.Feedback.Screenshots = "screenshots"
FN.Feedback.Contact = "contact"
FN.Feedback.Status = "status"
FN.Feedback.Remark = "remark"
FN.Feedback.CreatedAt = "createdAt"
FN.Feedback.UpdatedAt = "updatedAt"
TN.Feedback = "feedback"
}
+32
View File
@@ -0,0 +1,32 @@
package feedbackmod
import "time"
// Feedback @table: feedback
//
// Feedback 用户意见反馈集合模型
type Feedback struct {
// ID
Id int64 `json:"id" bson:"_id,omitempty"`
// 用户ID
UserId int64 `json:"userId" bson:"userId"`
// 问题类型,1-功能建议、2-播放问题、3-账号问题、4-其他
FeedbackType int32 `json:"feedbackType" bson:"feedbackType"`
// 描述内容
Content string `json:"content" bson:"content"`
// 问题截图,可存放多张图片地址
Screenshots []string `json:"screenshots" bson:"screenshots"`
// 联系方式,可为空
Contact string `json:"contact" bson:"contact,omitempty"`
// 处理状态,0-待处理、1-已处理
Status int32 `json:"status" bson:"status"`
// 处理备注
Remark string `json:"remark" bson:"remark,omitempty"`
// 创建时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
// 更新时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
}
// FeedbackList 用户意见反馈列表
type FeedbackList []*Feedback
+135
View File
@@ -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
}
+41
View File
@@ -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"
}
+24
View File
@@ -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
+105
View File
@@ -0,0 +1,105 @@
package hotsearchmod
import (
"context"
"fmt"
"strings"
"time"
"unicode"
"unicode/utf8"
"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.HotSearch)
indexes := []mongo.IndexModel{
{
Keys: bson.D{{Key: FN.HotSearch.Keyword, Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{
{Key: FN.HotSearch.Count, Value: -1},
{Key: FN.HotSearch.UpdatedAt, Value: -1},
},
},
}
if _, err := db.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(hotsearchmod:Init) Create HotSearch Index failed! err:%+v:", err))
}
}
// NormalizeKeyword 去掉首尾空白、压缩中间空格,并限制长度。
func NormalizeKeyword(raw string) string {
raw = strings.TrimSpace(raw)
if raw == "" {
return ""
}
fields := strings.FieldsFunc(raw, unicode.IsSpace)
raw = strings.Join(fields, " ")
if utf8.RuneCountInString(raw) > MaxKeywordRunes {
raw = string([]rune(raw)[:MaxKeywordRunes])
}
return raw
}
// IncrByKeyword 按搜索词累加次数,不存在则插入。
func IncrByKeyword(ctx context.Context, keyword string) *srvdef.SrvErr {
keyword = NormalizeKeyword(keyword)
if keyword == "" {
return nil
}
now := time.Now()
filter := bson.M{FN.HotSearch.Keyword: keyword}
update := bson.M{
"$inc": bson.M{FN.HotSearch.Count: 1},
"$set": bson.M{FN.HotSearch.UpdatedAt: now},
"$setOnInsert": bson.M{
FN.HotSearch.Id: mongos.Lid.HotSearch.Get(),
FN.HotSearch.Keyword: keyword,
FN.HotSearch.CreatedAt: now,
},
}
if _, err := db.UpsertOne(ctx, filter, update); err != nil {
if _, retryErr := db.UpdateOne(ctx, filter, bson.M{
"$inc": bson.M{FN.HotSearch.Count: 1},
"$set": bson.M{FN.HotSearch.UpdatedAt: now},
}); retryErr != nil {
log.Warn("hotsearchmod:IncrByKeyword failed", log.E(err), log.E(retryErr), log.Any("keyword", keyword))
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
}
return nil
}
func FindTopHotSearch(ctx context.Context, limit int64) (HotSearchList, *srvdef.SrvErr) {
if limit <= 0 {
limit = TopLimit
}
opts := options.Find().
SetSort(bson.D{
{Key: FN.HotSearch.Count, Value: -1},
{Key: FN.HotSearch.UpdatedAt, Value: -1},
{Key: FN.HotSearch.Id, Value: -1},
}).
SetLimit(limit).
SetProjection(bson.D{
{Key: FN.HotSearch.Id, Value: 1},
{Key: FN.HotSearch.Keyword, Value: 1},
{Key: FN.HotSearch.Count, Value: 1},
})
data := make(HotSearchList, 0)
if err := db.Find(ctx, &data, bson.M{}, opts); err != nil {
log.Warn("hotsearchmod:FindTopHotSearch db.Find failed", log.E(err))
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return data, nil
}
+31
View File
@@ -0,0 +1,31 @@
package hotsearchmod
import "testing"
func TestNormalizeKeyword(t *testing.T) {
tests := []struct {
name string
raw string
want string
}{
{name: "空串", raw: " ", want: ""},
{name: "压缩空白", raw: " 霸道 总裁\t ", want: "霸道 总裁"},
{name: "截断长度", raw: stringsRepeat("测", 60), want: stringsRepeat("测", MaxKeywordRunes)},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NormalizeKeyword(tt.raw); got != tt.want {
t.Fatalf("NormalizeKeyword() = %q, want %q", got, tt.want)
}
})
}
}
func stringsRepeat(s string, n int) string {
out := make([]rune, 0, n)
r := []rune(s)[0]
for i := 0; i < n; i++ {
out = append(out, r)
}
return string(out)
}
+26
View File
@@ -0,0 +1,26 @@
package hotsearchmod
type TagHotSearch struct {
Id string
Keyword string
Count string
CreatedAt string
UpdatedAt string
}
var FN struct {
HotSearch TagHotSearch
}
var TN struct {
HotSearch string
}
func init() {
FN.HotSearch.Id = "_id"
FN.HotSearch.Keyword = "keyword"
FN.HotSearch.Count = "count"
FN.HotSearch.CreatedAt = "createdAt"
FN.HotSearch.UpdatedAt = "updatedAt"
TN.HotSearch = "hot_search"
}
+20
View File
@@ -0,0 +1,20 @@
package hotsearchmod
import "time"
const (
MaxKeywordRunes = 50
TopLimit = 10
)
// HotSearch 热搜词
// @table:hot_search
type HotSearch struct {
Id int64 `json:"id" bson:"_id,omitempty"`
Keyword string `json:"keyword" bson:"keyword"` // 搜索词
Count int64 `json:"count" bson:"count"` // 搜索次数
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 首次记录时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 最近搜索时间
}
type HotSearchList []*HotSearch
+109
View File
@@ -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
}
+26
View File
@@ -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"
}
+18
View File
@@ -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
+59
View File
@@ -0,0 +1,59 @@
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)
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)
}
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
}
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
}
+25
View File
@@ -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"
}
+12
View File
@@ -0,0 +1,12 @@
package ipdailystatmod
import "time"
// IpDailyStat 每日访客 IP 去重统计。
// @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
}
+66
View File
@@ -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"
}
+37
View File
@@ -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"`
}
+99
View File
@@ -0,0 +1,99 @@
package models
import (
"context"
"videoweb/pub/common/log"
"videoweb/pub/models/announcementmod"
"videoweb/pub/models/cfg"
"videoweb/pub/models/cointransmod"
"videoweb/pub/models/commentlikemod"
"videoweb/pub/models/commentmod"
"videoweb/pub/models/contactusmod"
"videoweb/pub/models/detailnavmod"
"videoweb/pub/models/esmod"
"videoweb/pub/models/eventmod"
"videoweb/pub/models/feedbackmod"
"videoweb/pub/models/homebannermod"
"videoweb/pub/models/hotsearchmod"
"videoweb/pub/models/ipblackmod"
"videoweb/pub/models/ipdailystatmod"
"videoweb/pub/models/m3u8requestlogmod"
"videoweb/pub/models/mwacc"
"videoweb/pub/models/oplog"
"videoweb/pub/models/playletcategorymod"
"videoweb/pub/models/playletchaptercollectmod"
"videoweb/pub/models/playletchapterlikemod"
"videoweb/pub/models/playletchaptermod"
"videoweb/pub/models/playletchapterunlockmod"
"videoweb/pub/models/playletcollectmod"
"videoweb/pub/models/playletlikemod"
"videoweb/pub/models/playletmod"
"videoweb/pub/models/playlettagmod"
"videoweb/pub/models/playletthememod"
"videoweb/pub/models/playletwatchhistorymod"
"videoweb/pub/models/playletwatchprogressmod"
"videoweb/pub/models/rechargepackagemod"
"videoweb/pub/models/richtextcontentmod"
"videoweb/pub/models/syncfilemod"
"videoweb/pub/models/translationcategorymod"
"videoweb/pub/models/translationmod"
"videoweb/pub/models/userlogin"
"videoweb/pub/models/usermod"
"videoweb/pub/models/uservisitlog"
"videoweb/pub/models/videocategorymod"
"videoweb/pub/models/videocreatermod"
"videoweb/pub/models/videoinformationmod"
"videoweb/pub/models/videotagmod"
"videoweb/pub/models/videotopicmod"
"videoweb/pub/models/vipordermod"
)
func Init() {
log.Info("models init start..")
ctx := context.Background()
cfg.Init(ctx)
mwacc.Init(ctx)
oplog.Init(ctx)
m3u8requestlogmod.Init(ctx)
syncfilemod.Init(ctx)
richtextcontentmod.Init(ctx)
announcementmod.Init(ctx)
hotsearchmod.Init(ctx)
homebannermod.Init(ctx)
commentmod.Init(ctx)
commentlikemod.Init(ctx)
ipblackmod.Init(ctx)
ipdailystatmod.Init(ctx)
esmod.Init(ctx)
detailnavmod.Init(ctx)
eventmod.Init(ctx)
translationcategorymod.Init(ctx)
translationmod.Init(ctx)
playletcategorymod.Init(ctx)
playletthememod.Init(ctx)
playlettagmod.Init(ctx)
playletmod.Init(ctx)
playletchaptermod.Init(ctx)
playletchapterlikemod.Init(ctx)
playletchaptercollectmod.Init(ctx)
playletchapterunlockmod.Init(ctx)
playletlikemod.Init(ctx)
playletcollectmod.Init(ctx)
playletwatchhistorymod.Init(ctx)
playletwatchprogressmod.Init(ctx)
feedbackmod.Init(ctx)
videocategorymod.Init(ctx)
videocreatermod.Init(ctx)
videotagmod.Init(ctx)
videoinformationmod.Init(ctx)
videotopicmod.Init(ctx)
rechargepackagemod.Init(ctx)
cointransmod.Init(ctx)
contactusmod.Init(ctx)
vipordermod.Init(ctx)
usermod.Init(ctx)
userlogin.Init(ctx)
uservisitlog.Init(ctx)
log.Info("models init end")
}
+170
View File
@@ -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
}
+13
View File
@@ -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"`
}
+66
View File
@@ -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))
}
}
+61
View File
@@ -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
}
+130
View File
@@ -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
}
+158
View File
@@ -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
}
+88
View File
@@ -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"
}
+84
View File
@@ -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
}
+78
View File
@@ -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"` // 更新时间
}
+53
View File
@@ -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"` // 角色名称
}
+9
View File
@@ -0,0 +1,9 @@
package oplog
import (
"videoweb/pub/mongos"
)
var (
opLogColl *mongos.Collection
)
+175
View File
@@ -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
}
+34
View File
@@ -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"
}
+22
View File
@@ -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
+126
View File
@@ -0,0 +1,126 @@
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.Slug, 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
}
+46
View File
@@ -0,0 +1,46 @@
package playletcategorymod
// TagPlayletCategory 保存 playlet_category 集合字段名。
type TagPlayletCategory struct {
Id string
Name string
Slug string
Desc 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.Desc = "desc"
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"
}
+26
View File
@@ -0,0 +1,26 @@
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
Desc string `json:"desc" bson:"desc"` // 描述
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,115 @@
package playletchaptercollectmod
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_chapter_collect 集合和常用查询索引
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.PlayletChapterCollect)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.PlayletChapterCollect.UserId, Value: 1},
{Key: FN.PlayletChapterCollect.ChapterId, Value: 1},
},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{
{Key: FN.PlayletChapterCollect.ChapterId, Value: 1},
{Key: FN.PlayletChapterCollect.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.PlayletChapterCollect.PlayletId, Value: 1},
{Key: FN.PlayletChapterCollect.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.PlayletChapterCollect.UserId, Value: 1},
{Key: FN.PlayletChapterCollect.CreatedAt, Value: -1},
},
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(playletchaptercollectmod:initIndex) 创建索引失败 err:%+v:", err))
}
}
// InsertOnePlayletChapterCollect 插入一条短剧剧集收藏关系
func InsertOnePlayletChapterCollect(ctx context.Context, doc *PlayletChapterCollect) (bool, *srvdef.SrvErr) {
if doc.Id == 0 {
doc.Id = mongos.Lid.PlayletChapterCollect.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) {
return false, nil
}
log.Warn("插入短剧剧集收藏关系失败", log.Any("doc", doc), log.E(err))
return false, srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return true, nil
}
// DeleteOnePlayletChapterCollect 删除一条短剧剧集收藏关系
func DeleteOnePlayletChapterCollect(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
count, err := coll.DeleteOne(ctx, filter)
if err != nil {
log.Warn("删除短剧剧集收藏关系失败", log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
}
return count, nil
}
// DeleteManyPlayletChapterCollect 按条件批量删除短剧剧集收藏关系
func DeleteManyPlayletChapterCollect(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
}
// FindManyPlayletChapterCollect 按条件查询短剧剧集收藏关系
func FindManyPlayletChapterCollect(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletChapterCollectList, *srvdef.SrvErr) {
data := make(PlayletChapterCollectList, 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, "", "")
}
return data, nil
}
// CountPlayletChapterCollect 统计满足条件的短剧剧集收藏关系数量
func CountPlayletChapterCollect(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
}
@@ -0,0 +1,30 @@
package playletchaptercollectmod
// TagPlayletChapterCollect 保存 playlet_chapter_collect 集合字段名
type TagPlayletChapterCollect struct {
Id string
UserId string
PlayletId string
ChapterId string
CreatedAt string
UpdatedAt string
}
var FN struct {
PlayletChapterCollect TagPlayletChapterCollect
}
var TN struct {
PlayletChapterCollect string
}
func init() {
FN.PlayletChapterCollect.Id = "_id"
FN.PlayletChapterCollect.UserId = "userId"
FN.PlayletChapterCollect.PlayletId = "playletId"
FN.PlayletChapterCollect.ChapterId = "chapterId"
FN.PlayletChapterCollect.CreatedAt = "createdAt"
FN.PlayletChapterCollect.UpdatedAt = "updatedAt"
TN.PlayletChapterCollect = "playlet_chapter_collect"
}
@@ -0,0 +1,18 @@
package playletchaptercollectmod
import "time"
// PlayletChapterCollect @table: playlet_chapter_collect
//
// PlayletChapterCollect 短剧剧集收藏关系模型
type PlayletChapterCollect struct {
Id int64 `json:"id" bson:"_id,omitempty"` // 收藏记录ID
UserId int64 `json:"userId" bson:"userId"` // 用户ID
PlayletId int64 `json:"playletId" bson:"playletId"` // 短剧ID
ChapterId int64 `json:"chapterId" bson:"chapterId"` // 短剧剧集ID
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
}
// PlayletChapterCollectList 短剧剧集收藏关系列表
type PlayletChapterCollectList []*PlayletChapterCollect
+105
View File
@@ -0,0 +1,105 @@
package playletchapterlikemod
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_chapter_like 集合和常用查询索引
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.PlayletChapterLike)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.PlayletChapterLike.UserId, Value: 1},
{Key: FN.PlayletChapterLike.ChapterId, Value: 1},
},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{
{Key: FN.PlayletChapterLike.ChapterId, Value: 1},
{Key: FN.PlayletChapterLike.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.PlayletChapterLike.PlayletId, Value: 1},
{Key: FN.PlayletChapterLike.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.PlayletChapterLike.UserId, Value: 1},
{Key: FN.PlayletChapterLike.CreatedAt, Value: -1},
},
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(playletchapterlikemod:initIndex) 创建索引失败 err:%+v:", err))
}
}
// InsertOnePlayletChapterLike 插入一条短剧剧集点赞关系
func InsertOnePlayletChapterLike(ctx context.Context, doc *PlayletChapterLike) (bool, *srvdef.SrvErr) {
if doc.Id == 0 {
doc.Id = mongos.Lid.PlayletChapterLike.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) {
return false, nil
}
log.Warn("插入短剧剧集点赞关系失败", log.Any("doc", doc), log.E(err))
return false, srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return true, nil
}
// DeleteOnePlayletChapterLike 删除一条短剧剧集点赞关系
func DeleteOnePlayletChapterLike(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
count, err := coll.DeleteOne(ctx, filter)
if err != nil {
log.Warn("删除短剧剧集点赞关系失败", log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
}
return count, nil
}
// DeleteManyPlayletChapterLike 按条件批量删除短剧剧集点赞关系
func DeleteManyPlayletChapterLike(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
}
// FindManyPlayletChapterLike 按条件查询短剧剧集点赞关系
func FindManyPlayletChapterLike(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletChapterLikeList, *srvdef.SrvErr) {
data := make(PlayletChapterLikeList, 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, "", "")
}
return data, nil
}
+30
View File
@@ -0,0 +1,30 @@
package playletchapterlikemod
// TagPlayletChapterLike 保存 playlet_chapter_like 集合字段名
type TagPlayletChapterLike struct {
Id string
UserId string
PlayletId string
ChapterId string
CreatedAt string
UpdatedAt string
}
var FN struct {
PlayletChapterLike TagPlayletChapterLike
}
var TN struct {
PlayletChapterLike string
}
func init() {
FN.PlayletChapterLike.Id = "_id"
FN.PlayletChapterLike.UserId = "userId"
FN.PlayletChapterLike.PlayletId = "playletId"
FN.PlayletChapterLike.ChapterId = "chapterId"
FN.PlayletChapterLike.CreatedAt = "createdAt"
FN.PlayletChapterLike.UpdatedAt = "updatedAt"
TN.PlayletChapterLike = "playlet_chapter_like"
}
+18
View File
@@ -0,0 +1,18 @@
package playletchapterlikemod
import "time"
// PlayletChapterLike @table: playlet_chapter_like
//
// PlayletChapterLike 短剧剧集点赞关系模型
type PlayletChapterLike struct {
Id int64 `json:"id" bson:"_id,omitempty"` // 点赞记录ID
UserId int64 `json:"userId" bson:"userId"` // 用户ID
PlayletId int64 `json:"playletId" bson:"playletId"` // 短剧ID
ChapterId int64 `json:"chapterId" bson:"chapterId"` // 短剧剧集ID
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
}
// PlayletChapterLikeList 短剧剧集点赞关系列表
type PlayletChapterLikeList []*PlayletChapterLike
+247
View File
@@ -0,0 +1,247 @@
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
const duplicatePlayletChapterMsg = "短剧剧集已存在"
// Init 初始化 playlet_chapter 集合和常用查询索引
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.PlayletChapter)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
commonIndexes := []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.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, commonIndexes); err != nil {
panic(fmt.Sprintf("(playletchaptermod:initIndex) Create Index failed! err:%+v:", err))
}
uniqueIndexes := []mongo.IndexModel{
{
// 反向键序避免和线上已有 playletId_1_currentEpisode_1 普通索引冲突,同时兜住同一短剧同一集数的并发重复写入。
Keys: bson.D{
{Key: FN.PlayletChapter.CurrentEpisode, Value: 1},
{Key: FN.PlayletChapter.PlayletId, Value: 1},
},
Options: options.Index().
SetName("uniq_playlet_chapter_episode").
SetUnique(true),
},
{
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},
}),
},
}
for _, index := range uniqueIndexes {
if _, err := coll.CreateIndex(ctx, []mongo.IndexModel{index}); err != nil {
if isPlayletChapterDuplicateIndexErr(err) {
log.Warn("短剧章节唯一索引创建失败,请先清理历史重复章节数据", log.E(err), log.Any("index", index.Keys))
continue
}
panic(fmt.Sprintf("(playletchaptermod:initIndex) Create Unique Index failed! err:%+v:", err))
}
}
}
// isPlayletChapterDuplicateIndexErr 判断唯一索引创建时是否命中历史重复数据。
func isPlayletChapterDuplicateIndexErr(err error) bool {
if err == nil {
return false
}
return mongo.IsDuplicateKeyError(err) || strings.Contains(err.Error(), "E11000 duplicate key error")
}
// 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 {
if mongo.IsDuplicateKeyError(err) {
return duplicatePlayletChapterErr()
}
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 {
if mongo.IsDuplicateKeyError(err) {
return duplicatePlayletChapterErr()
}
log.Warn("playletchaptermod:InsertManyPlayletChapter failed", log.Any("count", len(data)), log.E(err))
return srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return nil
}
// duplicatePlayletChapterErr 返回章节唯一约束冲突的统一业务错误。
func duplicatePlayletChapterErr() *srvdef.SrvErr {
return srvdef.New(srvdef.ErrDbInputExist, duplicatePlayletChapterMsg, duplicatePlayletChapterMsg)
}
// 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 {
if mongo.IsDuplicateKeyError(err) {
return duplicatePlayletChapterErr()
}
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
}
// UpdateManyPlayletChapter 批量更新章节数据
func UpdateManyPlayletChapter(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
result, err := coll.UpdateMany(ctx, filter, update)
if err != nil {
if mongo.IsDuplicateKeyError(err) {
return duplicatePlayletChapterErr()
}
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
}
+72
View File
@@ -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"
}
+59
View File
@@ -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
+34
View File
@@ -0,0 +1,34 @@
package playletchapterunlockmod
// TagPlayletChapterUnlock 保存 playlet_chapter_unlock 集合字段名。
type TagPlayletChapterUnlock struct {
Id string
UserId string
PlayletId string
ChapterId string
Coins string
OrderNo string
CreatedAt string
UpdatedAt string
}
var FN struct {
PlayletChapterUnlock TagPlayletChapterUnlock
}
var TN struct {
PlayletChapterUnlock string
}
func init() {
FN.PlayletChapterUnlock.Id = "_id"
FN.PlayletChapterUnlock.UserId = "userId"
FN.PlayletChapterUnlock.PlayletId = "playletId"
FN.PlayletChapterUnlock.ChapterId = "chapterId"
FN.PlayletChapterUnlock.Coins = "coins"
FN.PlayletChapterUnlock.OrderNo = "orderNo"
FN.PlayletChapterUnlock.CreatedAt = "createdAt"
FN.PlayletChapterUnlock.UpdatedAt = "updatedAt"
TN.PlayletChapterUnlock = "playlet_chapter_unlock"
}
@@ -0,0 +1,19 @@
package playletchapterunlockmod
import "time"
// PlayletChapterUnlock @table: playlet_chapter_unlock
//
// PlayletChapterUnlock 记录用户已用金币解锁的短剧剧集;一条记录代表该用户永久可观看该剧集。
type PlayletChapterUnlock struct {
Id int64 `json:"id" bson:"_id,omitempty"` // 解锁记录ID
UserId int64 `json:"userId" bson:"userId"` // 用户ID
PlayletId int64 `json:"playletId" bson:"playletId"` // 短剧ID
ChapterId int64 `json:"chapterId" bson:"chapterId"` // 短剧剧集ID
Coins int64 `json:"coins" bson:"coins"` // 解锁消耗金币
OrderNo string `json:"orderNo" bson:"orderNo"` // 解锁流水号
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
}
type PlayletChapterUnlockList []*PlayletChapterUnlock
@@ -0,0 +1,107 @@
package playletchapterunlockmod
import (
"context"
"fmt"
"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/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var coll *mongos.Collection
// Init 初始化 playlet_chapter_unlock 集合和索引。
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.PlayletChapterUnlock)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.PlayletChapterUnlock.UserId, Value: 1},
{Key: FN.PlayletChapterUnlock.ChapterId, Value: 1},
},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{
{Key: FN.PlayletChapterUnlock.UserId, Value: 1},
{Key: FN.PlayletChapterUnlock.PlayletId, Value: 1},
},
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(playletchapterunlockmod:initIndex) 创建索引失败 err:%+v:", err))
}
}
// InsertOnePlayletChapterUnlock 插入解锁记录。
//
// 返回 inserted=false 表示该用户已经解锁过该剧集;调用方应将其视为幂等成功,不可继续扣费。
func InsertOnePlayletChapterUnlock(ctx context.Context, doc *PlayletChapterUnlock) (bool, *srvdef.SrvErr) {
if doc.Id == 0 {
doc.Id = mongos.Lid.PlayletChapterUnlock.Get()
}
now := utils.Now()
if doc.CreatedAt.IsZero() {
doc.CreatedAt = now
}
doc.UpdatedAt = now
if _, err := coll.InsertOne(ctx, doc); err != nil {
if mongo.IsDuplicateKeyError(err) {
return false, nil
}
log.Warn("插入短剧剧集解锁记录失败", log.Any("doc", doc), log.E(err))
return false, srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return true, nil
}
// ExistsPlayletChapterUnlock 判断用户是否已解锁指定剧集。
func ExistsPlayletChapterUnlock(ctx context.Context, userId int64, chapterId int64) (bool, *srvdef.SrvErr) {
if userId <= 0 || chapterId <= 0 {
return false, nil
}
var doc PlayletChapterUnlock
err := coll.FindOneEx(ctx, &doc, bson.M{
FN.PlayletChapterUnlock.UserId: userId,
FN.PlayletChapterUnlock.ChapterId: chapterId,
}, options.FindOne().SetProjection(bson.D{
{Key: FN.PlayletChapterUnlock.Id, Value: 1},
}))
if err != nil {
if err == mongo.ErrNoDocuments {
return false, nil
}
log.Warn("查询短剧剧集解锁记录失败", log.E(err), log.Any("userId", userId), log.Any("chapterId", chapterId))
return false, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return doc.Id > 0, nil
}
// DeleteManyPlayletChapterUnlock 按条件批量删除剧集解锁记录。
func DeleteManyPlayletChapterUnlock(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
}
// FindManyPlayletChapterUnlock 按条件查询多条剧集解锁记录。
func FindManyPlayletChapterUnlock(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletChapterUnlockList, *srvdef.SrvErr) {
data := make(PlayletChapterUnlockList, 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, "", "")
}
return data, nil
}
+115
View File
@@ -0,0 +1,115 @@
package playletcollectmod
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_collect 集合和常用查询索引
func Init(ctx context.Context) {
coll = mongos.Shop.Coll(TN.PlayletCollect)
initIndex(ctx)
}
func initIndex(ctx context.Context) {
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.PlayletCollect.UserId, Value: 1},
{Key: FN.PlayletCollect.PlayletId, Value: 1},
},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{
{Key: FN.PlayletCollect.PlayletId, Value: 1},
{Key: FN.PlayletCollect.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.PlayletCollect.UserId, Value: 1},
{Key: FN.PlayletCollect.CreatedAt, Value: -1},
{Key: FN.PlayletCollect.Id, Value: -1},
},
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(playletcollectmod:initIndex) 创建索引失败 err:%+v:", err))
}
}
// InsertOnePlayletCollect 插入一条短剧收藏关系
func InsertOnePlayletCollect(ctx context.Context, doc *PlayletCollect) (bool, *srvdef.SrvErr) {
if doc.Id == 0 {
doc.Id = mongos.Lid.PlayletCollect.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) {
return false, nil
}
log.Warn("插入短剧收藏关系失败", log.Any("doc", doc), log.E(err))
return false, srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return true, nil
}
// ExistsPlayletCollect 查询短剧收藏关系是否存在
func ExistsPlayletCollect(ctx context.Context, filter bson.M) (bool, *srvdef.SrvErr) {
var doc PlayletCollect
if err := coll.FindOneEx(ctx, &doc, filter, options.FindOne().SetProjection(bson.D{
{Key: FN.PlayletCollect.Id, Value: 1},
})); err != nil {
if err == mongo.ErrNoDocuments {
return false, nil
}
log.Warn("查询短剧收藏关系失败", log.E(err), log.Any("filter", filter))
return false, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return true, nil
}
// DeleteOnePlayletCollect 删除一条短剧收藏关系
func DeleteOnePlayletCollect(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
count, err := coll.DeleteOne(ctx, filter)
if err != nil {
log.Warn("删除短剧收藏关系失败", log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
}
return count, nil
}
// FindManyPlayletCollect 按条件查询短剧收藏关系列表
func FindManyPlayletCollect(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (PlayletCollectList, *srvdef.SrvErr) {
data := make(PlayletCollectList, 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, "", "")
}
return data, nil
}
// CountPlayletCollect 统计满足条件的短剧收藏关系数量
func CountPlayletCollect(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
}
+28
View File
@@ -0,0 +1,28 @@
package playletcollectmod
// TagPlayletCollect 保存 playlet_collect 集合字段名
type TagPlayletCollect struct {
Id string
UserId string
PlayletId string
CreatedAt string
UpdatedAt string
}
var FN struct {
PlayletCollect TagPlayletCollect
}
var TN struct {
PlayletCollect string
}
func init() {
FN.PlayletCollect.Id = "_id"
FN.PlayletCollect.UserId = "userId"
FN.PlayletCollect.PlayletId = "playletId"
FN.PlayletCollect.CreatedAt = "createdAt"
FN.PlayletCollect.UpdatedAt = "updatedAt"
TN.PlayletCollect = "playlet_collect"
}
+17
View File
@@ -0,0 +1,17 @@
package playletcollectmod
import "time"
// PlayletCollect @table: playlet_collect
//
// PlayletCollect 短剧收藏关系模型
type PlayletCollect struct {
Id int64 `json:"id" bson:"_id,omitempty"` // 收藏记录ID
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"` // 修改时间
}
// PlayletCollectList 短剧收藏关系列表
type PlayletCollectList []*PlayletCollect
+88
View File
@@ -0,0 +1,88 @@
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},
{Key: FN.PlayletLike.CreatedAt, Value: -1},
},
},
}
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(playletlikemod:initIndex) 创建索引失败 err:%+v:", err))
}
}
// InsertOnePlayletLike 插入一条短剧点赞关系
func InsertOnePlayletLike(ctx context.Context, doc *PlayletLike) (bool, *srvdef.SrvErr) {
if doc.Id == 0 {
doc.Id = mongos.Lid.PlayletLike.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) {
return false, nil
}
log.Warn("插入短剧点赞关系失败", log.Any("doc", doc), log.E(err))
return false, srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return true, nil
}
// ExistsPlayletLike 查询短剧点赞关系是否存在
func ExistsPlayletLike(ctx context.Context, filter bson.M) (bool, *srvdef.SrvErr) {
var doc PlayletLike
if err := coll.FindOneEx(ctx, &doc, filter, options.FindOne().SetProjection(bson.D{
{Key: FN.PlayletLike.Id, Value: 1},
})); err != nil {
if err == mongo.ErrNoDocuments {
return false, nil
}
log.Warn("查询短剧点赞关系失败", log.E(err), log.Any("filter", filter))
return false, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return true, nil
}
// DeleteOnePlayletLike 删除一条短剧点赞关系
func DeleteOnePlayletLike(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
count, err := coll.DeleteOne(ctx, filter)
if err != nil {
log.Warn("删除短剧点赞关系失败", log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
}
return count, nil
}
+28
View File
@@ -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"
}
+17
View File
@@ -0,0 +1,17 @@
package playletlikemod
import "time"
// PlayletLike @table: playlet_like
//
// PlayletLike 短剧点赞关系模型
type PlayletLike struct {
Id int64 `json:"id" bson:"_id,omitempty"` // 点赞记录ID
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
+153
View File
@@ -0,0 +1,153 @@
package playletmod
import "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)
}
// ApplyCategoryBinds 写入分类绑定并同步 categoryIds。
func ApplyCategoryBinds(item *Playlet, binds []PlayletCategoryBind) {
if item == nil {
return
}
item.CategoryBinds = NormalizeCategoryBinds(binds)
item.CategoryIds = CategoryIdsFromBinds(item.CategoryBinds)
}
// 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},
}
}
+331
View File
@@ -0,0 +1,331 @@
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.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.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.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},
},
},
{
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.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.Slug, 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},
}),
},
{
Keys: bson.D{
{Key: FN.Playlet.OperateType, Value: 1},
{Key: FN.Playlet.Status, Value: 1},
{Key: FN.Playlet.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.Playlet.ContentType, Value: 1},
{Key: FN.Playlet.CreatedAt, Value: -1},
{Key: FN.Playlet.Id, Value: -1},
},
Options: options.Index().
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
}
// 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
}
// FindManyPlayletByCategoryRank 按指定分类的排序分页查询短剧。
func FindManyPlayletByCategoryRank(ctx context.Context, filter bson.M, categoryId int64, skip, limit int64, sort bson.D, projection bson.D) (PlayletList, *srvdef.SrvErr) {
if skip < 0 {
skip = 0
}
if limit <= 0 {
limit = 10
}
if sort == nil {
sort = CategoryRankSort()
}
pipeline := []bson.M{
{"$match": filter},
{"$addFields": CategoryRankAddFields(categoryId)},
{"$sort": sort},
{"$skip": skip},
{"$limit": limit},
}
pipeline = append(pipeline, bson.M{"$unset": categoryRankField})
if len(projection) > 0 {
proj := bson.M{}
for _, field := range projection {
proj[field.Key] = field.Value
}
pipeline = append(pipeline, bson.M{"$project": proj})
}
list := make(PlayletList, 0)
if err := AggregatePlaylet(ctx, &list, pipeline); err != nil {
return nil, err
}
return list, nil
}
// AggregatePlaylet 聚合查询短剧
func AggregatePlaylet(ctx context.Context, bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
if err := coll.Aggregate(ctx, bind, pipeline); err != nil {
log.Warn("playletmod:AggregatePlaylet failed", log.E(err), log.Any("pipeline", pipeline))
return srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return nil
}
+120
View File
@@ -0,0 +1,120 @@
package playletmod
// TagPlaylet 保存 playlet 集合字段名
type TagPlaylet struct {
Id string
MediaCenterId string
MediaSource string
MediaCreatedAt string
MediaUpdatedAt string
MediaSyncTime string
Status string
IsFeatured string
IsOriginal string
IsRecommend string
ShowOnBanner string
Banner string
ReviewAt string
OnlineAt string
CategoryIds string
CategoryBinds string
ThemeIds string
Title string
PlayName string
Description string
Slug string
Desc string
Anchor string
Cover string
CompressedCover string
Preview string
TagIds string
ContentType string
OperateType string
PayType string
SingleCoins string
TotalEpisode string
UpdateStatus string
TopRank string
RecommendRank string
CountComment string
CountBuy string
CountBrowse string
HeatValue string
CountCollect string
CountLike string
VirtualCountLike string
CountDisLike string
SeoInfo struct {
Description string
Keyworld string
Title 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.MediaSource = "mediaSource"
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.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.PlayName = "playName"
FN.Playlet.Description = "description"
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.ContentType = "contentType"
FN.Playlet.OperateType = "operateType"
FN.Playlet.PayType = "payType"
FN.Playlet.SingleCoins = "singleCoins"
FN.Playlet.TotalEpisode = "totalEpisode"
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.HeatValue = "heatValue"
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.OperatorId = "operatorId"
FN.Playlet.OperatorName = "operatorName"
FN.Playlet.CreatedAt = "createdAt"
FN.Playlet.UpdatedAt = "updatedAt"
TN.Playlet = "playlet"
}
+149
View File
@@ -0,0 +1,149 @@
package playletmod
import (
"strconv"
"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
)
// OperateType 运营类型
type OperateType int32
const (
OperateTypePlaylet OperateType = 1 // 短剧
OperateTypeComic OperateType = 2 // 漫剧
)
// NormalizeOperateType 历史数据未写入时按短剧处理
func NormalizeOperateType(t OperateType) OperateType {
if t == OperateTypeComic {
return OperateTypeComic
}
return OperateTypePlaylet
}
// IsValidOperateType 校验运营类型
func IsValidOperateType(t OperateType) bool {
return t == OperateTypePlaylet || t == OperateTypeComic
}
const (
UpdateStatusSerial = 1 // 连载中
UpdateStatusDone = 2 // 已完结
)
const (
MediaSourceDefault = "" // 普通(嘉华)媒资
MediaSourceHG = "hg" // 黄果媒资
)
// BuildPlayNameDescription 按剧名和连载状态生成 SEO Description。
func BuildPlayNameDescription(desc, playName string, updateStatus int, totalEpisode int64) string {
playName = strings.TrimSpace(playName)
if playName == "" {
return ""
}
desc = strings.TrimSpace(desc)
siteName := pubdef.AppName
if updateStatus == UpdateStatusDone {
return desc + siteName + "提供《" + playName + "》全集在线观看、剧情介绍及完整选集,并持续更新相关热门短剧。"
}
return desc + siteName + "提供《" + playName + "》最新剧集、剧情介绍及在线观看,当前更新至第" + strconv.FormatInt(totalEpisode, 10) + "集,后续内容持续更新。"
}
// Playlet @table: playlet
//
// Playlet 连载短剧集合模型
type Playlet struct {
Id int64 `json:"id" bson:"_id,omitempty"`
MediaCenterId uint `json:"mediaCenterId" bson:"mediaCenterId"` // 媒资中心资源ID
MediaSource string `json:"mediaSource" bson:"mediaSource"` // 媒资来源,空值为普通媒资
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
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 同步
CategoryBinds []PlayletCategoryBind `json:"categoryBinds" bson:"categoryBinds"` // 分类及该分类下的排序
ThemeIds []int64 `json:"themeIds" bson:"themeIds"` // 题材ID集合
Title string `json:"title" bson:"title"` // 标题
PlayName string `json:"playName" bson:"playName"` // 剧名,后台维护
Description string `json:"description" bson:"description"` // SEO Description,按剧名规则自动生成
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
ContentType ContentType `json:"contentType" bson:"contentType"` // 内容类型: 0短剧 1普通短剧/影集 2漫画短剧 3动漫 4漫画
OperateType OperateType `json:"operateType" bson:"operateType"` // 运营类型: 1短剧 2漫剧
PayType PayType `json:"payType" bson:"payType"` // 支付方式 0-免费 1-金币 2-VIP
SingleCoins int64 `json:"singleCoins" bson:"singleCoins"` // 单集金币(支付方式为1-金币时候生效)
TotalEpisode int64 `json:"totalEpisode" bson:"totalEpisode"` // 总集数
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"` // 浏览数
HeatValue int64 `json:"heatValue" bson:"heatValue"` // 热度值
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相关信息
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"` // 修改时间
}
// PlayletList 短剧列表
type PlayletList []*Playlet
// 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)
}
+126
View File
@@ -0,0 +1,126 @@
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.Slug, 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
}
+40
View File
@@ -0,0 +1,40 @@
package playlettagmod
// TagPlayletTag 保存 playlet_tag 集合字段名
type TagPlayletTag struct {
Id string
Name string
Slug 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.Slug = "slug"
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"
}
+23
View File
@@ -0,0 +1,23 @@
package playlettagmod
import (
"time"
"videoweb/pub/pubdef"
)
// PlayletTag @table: playlet_tag
//
// PlayletTag 短剧标签集合模型
type PlayletTag struct {
Id int64 `json:"id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"` // 标签名称
Slug string `json:"slug" bson:"slug"` // slug
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

Some files were not shown because too many files have changed in this diff Show More