@@ -0,0 +1,309 @@
|
||||
package modulesectionmod
|
||||
|
||||
import (
|
||||
"91porn-server/common/log"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"91porn-server/common"
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/stderr"
|
||||
"91porn-server/models"
|
||||
"91porn-server/models/commod"
|
||||
"91porn-server/models/v/moduleconfmod"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
const table = models.Section
|
||||
|
||||
var mdb *db.MongoDB
|
||||
|
||||
func initIndex() {
|
||||
coll := coll(nil)
|
||||
many := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{{Key: "sectionName", Value: 1}, {Key: "subModuleID", Value: 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "subModuleID", Value: 1}, {Key: "status", Value: 1}, {Key: "sort", Value: -1}, {Key: "createdAt", Value: -1},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := coll.CreateIndex(many); err != nil {
|
||||
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
|
||||
}
|
||||
}
|
||||
|
||||
func coll(t *db.MongoTool) *db.MongoTool {
|
||||
if t == nil {
|
||||
return mdb.Coll(table)
|
||||
}
|
||||
return t.Coll(table)
|
||||
}
|
||||
|
||||
func InsertOne(section Section) error {
|
||||
section.CreatedAt = time.Now()
|
||||
section.UpdatedAt = section.CreatedAt
|
||||
ok, err := checkLimit(section.SubModuleID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return stderr.ModuleConfLimitExceed
|
||||
}
|
||||
_, err = coll(nil).InsertOne(section)
|
||||
return err
|
||||
}
|
||||
|
||||
func UpdateOne(set EditSelector) error {
|
||||
subModule, err := moduleconfmod.GetByID(*set.SubModuleID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
total, err := CountBySubModuleID(*set.SubModuleID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (set.Status != nil && *set.Status == 1) && total >= int64(subModule.SectionLimit) {
|
||||
return stderr.ModuleConfLimitExceed
|
||||
}
|
||||
cond := bson.M{"updatedAt": time.Now()}
|
||||
if set.Status != nil {
|
||||
cond["status"] = set.Status
|
||||
}
|
||||
if set.Tags != nil && len(*set.Tags) > 0 {
|
||||
cond["tags"] = set.Tags
|
||||
} else {
|
||||
cond["tags"] = []string{}
|
||||
}
|
||||
if set.TagIds != nil && len(set.TagIds) > 0 {
|
||||
cond["tagIds"] = set.TagIds
|
||||
} else {
|
||||
cond["tagIds"] = []primitive.ObjectID{}
|
||||
}
|
||||
if set.SectionName != nil {
|
||||
cond["sectionName"] = set.SectionName
|
||||
}
|
||||
if set.SubModuleID != nil {
|
||||
cond["subModuleID"] = set.SubModuleID
|
||||
}
|
||||
if set.ShowType != nil {
|
||||
cond["showType"] = set.ShowType
|
||||
}
|
||||
if set.Sort != nil {
|
||||
cond["sort"] = set.Sort
|
||||
}
|
||||
if set.SectionCover != nil {
|
||||
cond["sectionCover"] = set.SectionCover
|
||||
}
|
||||
if set.Hot != nil {
|
||||
cond["hot"] = set.Hot
|
||||
}
|
||||
_, err = coll(nil).UpdateOne(bson.M{"_id": set.ID}, bson.M{"$set": cond})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteOne 删除一条数据,仅作删除标记-deletedAt
|
||||
func DeleteOne(id primitive.ObjectID) error {
|
||||
now := time.Now()
|
||||
status := uint8(0)
|
||||
set := EditSelector{ID: id, DeletedAt: &now, Status: &status}
|
||||
return UpdateOne(set)
|
||||
}
|
||||
|
||||
func DeleteById(id primitive.ObjectID) (err error) {
|
||||
_, err = coll(nil).DeleteOne(bson.M{"_id": id})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DeleteById", table, "DeleteOne", err),
|
||||
log.Any("id", id),
|
||||
)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetBySectionID 根据专题ID获取专题详情
|
||||
func GetBySectionByID(sectionID primitive.ObjectID) (section Section, err error) {
|
||||
err = coll(nil).FindOne(§ion, bson.M{"_id": sectionID})
|
||||
return
|
||||
}
|
||||
|
||||
// GetBySubModuleID 通过亚模块id获取专题列表
|
||||
func GetBySubModuleID(subModuleID primitive.ObjectID, page commod.Page) (section []Section, hasNext bool, err error) {
|
||||
opts := options.FindOptions{}
|
||||
opts.SetSkip(int64(page.Skip())).SetLimit(int64(page.Limit()) + 1).SetSort(bson.D{{"sort", 1}, {"_id", -1}})
|
||||
if err = coll(nil).Find(§ion, bson.M{"subModuleID": subModuleID, "status": 1}, &opts); err != nil {
|
||||
return
|
||||
}
|
||||
if uint64(len(section)) > page.Limit() {
|
||||
hasNext = true
|
||||
section = section[:page.Limit()]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetAllBySubModuleID(subModuleID primitive.ObjectID) (section []Section, err error) {
|
||||
section = make([]Section, 0)
|
||||
op := options.Find().SetSort(bson.D{{"sort", 1}})
|
||||
err = coll(nil).Find(§ion, bson.M{"subModuleID": subModuleID, "status": 1}, op)
|
||||
return
|
||||
}
|
||||
|
||||
func HomePageGetBySubModuleID(subModuleID primitive.ObjectID) (section []Section, err error) {
|
||||
section = make([]Section, 0)
|
||||
op := options.Find().SetSort(bson.D{{"sort", 1}}).SetLimit(50)
|
||||
err = coll(nil).Find(§ion, bson.M{"subModuleID": subModuleID, "status": 1}, op)
|
||||
return
|
||||
}
|
||||
|
||||
func CountBySubModuleID(subModuleID primitive.ObjectID) (int64, error) {
|
||||
return coll(nil).Count(bson.M{"subModuleID": subModuleID, "status": 1})
|
||||
}
|
||||
|
||||
func AllSections() (list []Section, err error) {
|
||||
err = coll(nil).Find(&list, bson.M{"status": 1})
|
||||
return
|
||||
}
|
||||
|
||||
// AllSectionsModule 获取所有激活的专题,以及对应的模块信息
|
||||
func AllSectionsModule() (list []SectionModule, err error) {
|
||||
pipeline := []bson.M{
|
||||
{"$match": bson.M{"status": 1}},
|
||||
{"$lookup": bson.M{
|
||||
"from": models.ModuleConf,
|
||||
"localField": "subModuleID",
|
||||
"foreignField": "_id",
|
||||
"as": "sectionMoudle",
|
||||
}},
|
||||
}
|
||||
err = coll(nil).Aggregate(&list, pipeline)
|
||||
return
|
||||
}
|
||||
|
||||
func GetByIDs(ids []primitive.ObjectID) (list []SectionModule, err error) {
|
||||
pipeline := []bson.M{
|
||||
{"$match": bson.M{"_id": bson.M{"$in": ids}}},
|
||||
{"$lookup": bson.M{
|
||||
"from": models.ModuleConf,
|
||||
"localField": "subModuleID",
|
||||
"foreignField": "_id",
|
||||
"as": "sectionMoudle",
|
||||
}},
|
||||
}
|
||||
err = coll(nil).Aggregate(&list, pipeline)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: 并发不安全
|
||||
func checkLimit(subModuleID primitive.ObjectID) (ok bool, err error) {
|
||||
subModule, err := moduleconfmod.GetByID(subModuleID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err := CountBySubModuleID(subModuleID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return subModule.SectionLimit == 0 || int(total) < subModule.SectionLimit, nil
|
||||
}
|
||||
|
||||
// ListBySubModule returns topic metadata under one module. The hard limit keeps
|
||||
// the merged system/custom topic response bounded even if historical data is malformed.
|
||||
func ListBySubModule(subModuleID primitive.ObjectID, limit int64) ([]Section, error) {
|
||||
if limit <= 0 || limit > 1000 {
|
||||
limit = 1000
|
||||
}
|
||||
var list []Section
|
||||
err := coll(nil).Find(&list, bson.M{
|
||||
"subModuleID": subModuleID,
|
||||
"deletedAt": nil,
|
||||
}, options.Find().SetSort(bson.D{{Key: "sort", Value: -1}, {Key: "updatedAt", Value: -1}}).SetLimit(limit))
|
||||
return list, err
|
||||
}
|
||||
|
||||
// UpdateTopicFields updates a section only when it belongs to the expected module.
|
||||
func UpdateTopicFields(t *db.MongoTool, id, subModuleID primitive.ObjectID, fields bson.M) (int64, error) {
|
||||
fields["updatedAt"] = time.Now()
|
||||
result, err := coll(t).UpdateOne(bson.M{
|
||||
"_id": id, "subModuleID": subModuleID, "deletedAt": nil,
|
||||
}, bson.M{"$set": fields})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.MatchedCount, nil
|
||||
}
|
||||
|
||||
func DeleteTopic(t *db.MongoTool, id, subModuleID primitive.ObjectID) (int64, error) {
|
||||
result, err := coll(t).DeleteOne(bson.M{"_id": id, "subModuleID": subModuleID})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.DeletedCount, nil
|
||||
}
|
||||
|
||||
// Search 根据条件检索section
|
||||
func Search(q QuerySelector, p commod.Page) (list []Section, hasNext bool, total int64, err error) {
|
||||
skip := int64(p.Skip())
|
||||
limit := int64(p.Limit() + 1)
|
||||
opts := options.FindOptions{
|
||||
Skip: &skip,
|
||||
Limit: &limit,
|
||||
Sort: append(p.GetSort(), bson.E{Key: "createdAt", Value: -1}),
|
||||
}
|
||||
filter, err := common.ToBsonM(q)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if q.SectionName != nil {
|
||||
filter["sectionName"] = primitive.Regex{
|
||||
Pattern: *q.SectionName,
|
||||
}
|
||||
}
|
||||
if err = coll(nil).Find(&list, filter, &opts); err != nil {
|
||||
return
|
||||
}
|
||||
if total, err = coll(nil).Count(filter); err != nil {
|
||||
return
|
||||
}
|
||||
if uint64(len(list)) > p.Limit() {
|
||||
hasNext = true
|
||||
list = list[:p.Limit()]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetBySectionByIDs 根据专题IDS获取专题详情
|
||||
func GetBySectionByIDs(sectionIds []primitive.ObjectID) (section []Section, err error) {
|
||||
err = coll(nil).Find(§ion, bson.M{"_id": bson.M{"$in": sectionIds}})
|
||||
return
|
||||
}
|
||||
|
||||
// GetBySectionBySids 根据专题IDS获取专题详情
|
||||
func GetBySectionBySids(sIds []primitive.ObjectID) (section []Section, err error) {
|
||||
err = coll(nil).Find(§ion, bson.M{"subModuleID": bson.M{"$in": sIds}, "status": 1})
|
||||
return
|
||||
}
|
||||
|
||||
// GetBySectionID 根据专题ID获取专题详情
|
||||
func GetBySectionID(sectionID primitive.ObjectID) (section Section, err error) {
|
||||
err = coll(nil).FindOne(§ion, bson.M{"_id": sectionID})
|
||||
return
|
||||
}
|
||||
|
||||
// QueryAllList 分页查询文档
|
||||
func QueryAllList(filter primitive.M, opts ...*options.FindOptions) (out []*Section, err error) {
|
||||
if err = coll(nil).Find(&out, filter, opts...); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "QueryAllList", table, "Find", err),
|
||||
log.Any("filter", filter),
|
||||
log.Any("opts", opts),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package modulesectionmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/models/v/moduleconfmod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
const (
|
||||
OneLargeAndFourSmall = 101 // 101 一大四小(横-长视频)
|
||||
FourGrid = 102 // 102 四宫格(横-长视频/ACG)
|
||||
SixGrid = 103 // 103 六宫格(横-长视频)
|
||||
Horizontal15Scroll = 104 // 104 横屏1.5滑动
|
||||
Horizontal25Scroll = 105 // 105 横屏2.5滑动
|
||||
HorizontalList = 106 // 106 横屏列表展示
|
||||
HorizontalSingle = 107 // 107 横屏大图(单个列表展示)
|
||||
VerticalFourGrid = 201 // 四宫格(视频/ACG)
|
||||
VerticalSixGrid = 202 // 六宫格(视频/ACG)
|
||||
VerticalNineGrid = 203 // 九宫格(视频/ACG)
|
||||
Vertical15Scroll = 204 // 竖屏1.5滑动(ACG)
|
||||
Vertical25Scroll = 205 // 竖屏2.5滑动(ACG)
|
||||
GuessYouLike = 301 // 猜你喜欢
|
||||
)
|
||||
|
||||
var ShowTypeHashVale = map[int]int{
|
||||
OneLargeAndFourSmall: 5, // 101 一大四小(横-长视频)
|
||||
FourGrid: 4, // 102 四宫格(横-长视频)
|
||||
SixGrid: 6, // 103 六宫格(横-长视频)
|
||||
Horizontal15Scroll: 12, // 104 横屏1.5滑动
|
||||
Horizontal25Scroll: 12, // 105 横屏2.5滑动
|
||||
HorizontalList: 3, // 106 横屏列表展示
|
||||
HorizontalSingle: 3, // 107 横屏大图(单个列表展示)
|
||||
VerticalFourGrid: 4, // 2 四宫格(竖-短视频)
|
||||
VerticalSixGrid: 6, // 4 六宫格(竖-短视频)
|
||||
VerticalNineGrid: 9, // 5 九宫格(竖-长视频)
|
||||
Vertical15Scroll: 12, // 7 竖屏1.5滑动
|
||||
Vertical25Scroll: 12, // 7 竖屏2.5滑动
|
||||
|
||||
}
|
||||
|
||||
var ACGShowTypeHashVale = map[int]int{
|
||||
VerticalFourGrid: 4, // 2 四宫格(竖-短视频)
|
||||
VerticalSixGrid: 6, // 4 六宫格(竖-短视频)
|
||||
VerticalNineGrid: 9, // 5 九宫格(竖-长视频)
|
||||
Vertical15Scroll: 12, // 7 竖屏1.5滑动
|
||||
Vertical25Scroll: 12, // 7 竖屏2.5滑动
|
||||
}
|
||||
|
||||
// Section 专题配置
|
||||
type Section struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` // ID
|
||||
SectionName string `json:"sectionName" bson:"sectionName" binding:"required"` // 亚模块下的专题名称
|
||||
SectionTitle string `json:"sectionTitle" bson:"sectionTitle"` // 专题的标题
|
||||
SectionCover *string `json:"sectionCover" bson:"sectionCover"` // 亚模块封面
|
||||
SubModuleID primitive.ObjectID `json:"subModuleID" bson:"subModuleID" binding:"required"` // 亚模块id
|
||||
OriginalUserID *uint64 `json:"originalUserID" bson:"originalUserID,omitempty"` // 原创博主用户ID,原创模块需要使用
|
||||
Status *uint8 `json:"status" bson:"status" binding:"required"` // 状态,0-关闭,1-展示
|
||||
Sort *int `json:"sort" bson:"sort" binding:"required"` // 排序
|
||||
Hot bool `json:"hot" bson:"hot"` // 是否显示hot标识
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt,omitempty"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt,omitempty"` // 刷新时间
|
||||
DeletedAt *time.Time `json:"deletedAt" bson:"deletedAt,omitempty"` // 删除时间,不能去除omitempty
|
||||
ShowType int `json:"showType" bson:"showType,omitempty"` // 展示样式
|
||||
Tags *[]string `json:"tags" bson:"tags,omitempty"` // 所属标签
|
||||
TagIds *[]primitive.ObjectID `json:"tagIds" bson:"tagIds,omitempty"` // 所属标签Id
|
||||
}
|
||||
|
||||
func Init() {
|
||||
mdb = db.Init(table)
|
||||
initIndex()
|
||||
}
|
||||
|
||||
type EditSelector struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty" binding:"required"`
|
||||
SectionName *string `json:"sectionName,omitempty" bson:"sectionName,omitempty"`
|
||||
SectionCover *string `json:"sectionCover" bson:"sectionCover,omitempty"`
|
||||
SubModuleID *primitive.ObjectID `json:"subModuleID,omitempty" bson:"subModuleID,omitempty" binding:"required"`
|
||||
Status *uint8 `json:"status,omitempty" bson:"status,omitempty"`
|
||||
Sort *int `json:"sort,omitempty" bson:"sort,omitempty"`
|
||||
Hot *bool `json:"hot" bson:"hot"` // 是否显示hot标识
|
||||
OriginalUserID *uint64 `json:"originalUserID,omitempty" bson:"originalUserID,omitempty"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt"`
|
||||
DeletedAt *time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"`
|
||||
ShowType *int `json:"showType,omitempty" bson:"showType,omitempty"`
|
||||
Tags *[]string `json:"tags" bson:"tags,omitempty"` // 标签
|
||||
TagIds []primitive.ObjectID `json:"tagIds" bson:"tagIds,omitempty"` // 所属标签Id
|
||||
}
|
||||
|
||||
type QuerySelector struct {
|
||||
ID *primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty" form:"id,omitempty" swaggertype:"string"`
|
||||
SectionName *string `json:"sectionName,omitempty" bson:"sectionName,omitempty" form:"sectionName,omitempty"`
|
||||
SubModuleID *primitive.ObjectID `json:"subModuleID,omitempty" bson:"subModuleID,omitempty" form:"subModuleID,omitempty" swaggertype:"string"`
|
||||
Status *uint8 `json:"status,omitempty" bson:"status,omitempty" form:"status,omitempty"`
|
||||
}
|
||||
|
||||
type ListResp struct {
|
||||
Total int64 `json:"total"` // 总数
|
||||
HasNext bool `json:"hasNext"` // 是否还有下一页
|
||||
List []SectionDetail `json:"list"` // 列表
|
||||
}
|
||||
|
||||
type SectionDetail struct {
|
||||
Section
|
||||
ModuleInfo
|
||||
OriginalBloggerInfo
|
||||
}
|
||||
|
||||
type ModuleInfo struct {
|
||||
ModuleName string `json:"moduleName"` // 模块名称
|
||||
SubModuleName string `json:"subModuleName"` // 子模块名称
|
||||
SectionLimit int `json:"sectionLimit"` // 专题数量限制
|
||||
}
|
||||
|
||||
type OriginalBloggerInfo struct {
|
||||
Name string `json:"name"` // 博主姓名
|
||||
Portrait string `json:"portrait"` // 头像
|
||||
OfficialCert bool `json:"officialCert"` // 是否官方认证
|
||||
IsMadou bool `json:"isMadou"` // 是否工作室
|
||||
}
|
||||
|
||||
type SectionModule struct {
|
||||
Section `bson:",inline"`
|
||||
SectionModule []moduleconfmod.ModuleConf `bson:"sectionMoudle"`
|
||||
}
|
||||
|
||||
type ModuleSection struct {
|
||||
moduleconfmod.ModuleConf // 模块,子模块信息
|
||||
Sections []Section `json:"sections"` // 子模块下的所有专题
|
||||
}
|
||||
|
||||
// AllSectionConf 专题配置
|
||||
type AllSectionConf struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"id"` // 文档ID
|
||||
ModuleName string `json:"moduleName" bson:"moduleName" ` // 版块名称
|
||||
AllSection []SectionConf `json:"allSection" bson:"allSection"` // 所有专题
|
||||
}
|
||||
|
||||
type SectionConf struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"id"` // 文档ID
|
||||
SectionName string `json:"sectionName" bson:"sectionName" ` // 专题名称
|
||||
}
|
||||
Reference in New Issue
Block a user