init: web_hgdjc_server

This commit is contained in:
2026-11-07 10:46:18 +08:00
commit b2ff6ac8ff
707 changed files with 147645 additions and 0 deletions
+368
View File
@@ -0,0 +1,368 @@
package srv_homeconfig
import (
"context"
"regexp"
"strings"
"time"
"videoweb/pub/common/playletcache"
"videoweb/pub/common/response"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/homeconfigmod"
"videoweb/pub/pubdef"
"videoweb/pub/seo/sitemapdirty"
"videoweb/web/api/proto"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
const (
defaultHomeConfigPageSize int64 = 10
maxHomeConfigPageSize int64 = 100
)
var homeConfigWebProjection = bson.D{
{Key: homeconfigmod.FN.HomeConfig.Id, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Name, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Slug, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Desc, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Keyword, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Label, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Style, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.CardBackgroundImage, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.TopicIds, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.CategoryId, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.RecommendType, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Type, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Rank, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Limit, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.SortType, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.Status, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.SeoInfo.Title, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.SeoInfo.Description, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.SeoInfo.Keyworld, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.CreatedAt, Value: 1},
{Key: homeconfigmod.FN.HomeConfig.UpdatedAt, Value: 1},
}
// ListHomeConfig 分页查询首页配置列表
func ListHomeConfig(ctx context.Context, req *proto.HomeConfigListReq) (*proto.HomeConfigListPageResp, *srvdef.SrvErr) {
if req == nil {
return nil, srvdef.New(srvdef.ErrParamError, "", "")
}
filter := bson.M{
homeconfigmod.FN.HomeConfig.Type: bson.M{"$in": []int32{homeconfigmod.TypePlaylet, homeconfigmod.TypeTheme}},
}
if req.Id != nil && *req.Id > 0 {
filter[homeconfigmod.FN.HomeConfig.Id] = *req.Id
}
if req.Type != nil {
if !validHomeConfigType(*req.Type) {
return nil, srvdef.New(srvdef.ErrParamError, "类型无效", "")
}
filter[homeconfigmod.FN.HomeConfig.Type] = *req.Type
}
if req.SortType != nil {
if !validHomeConfigSortType(*req.SortType) {
return nil, srvdef.New(srvdef.ErrParamError, "排序字段无效", "")
}
filter[homeconfigmod.FN.HomeConfig.SortType] = *req.SortType
}
if req.Status != nil {
filter[homeconfigmod.FN.HomeConfig.Status] = *req.Status
}
if name := strings.TrimSpace(req.Name); name != "" {
filter[homeconfigmod.FN.HomeConfig.Name] = bson.M{"$regex": regexp.QuoteMeta(name)}
}
if slug := strings.TrimSpace(req.Slug); slug != "" {
filter[homeconfigmod.FN.HomeConfig.Slug] = slug
}
pageNum, pageSize := normalizeHomeConfigPage(req.PageNum, req.PageSize)
totalCount, err := homeconfigmod.CountHomeConfig(ctx, filter)
if err != nil {
return nil, err
}
resp := &proto.HomeConfigListPageResp{
BasePageResp: response.BasePageResp{
TotalCount: totalCount,
PageSize: int(pageSize),
PageNum: int(pageNum),
List: make([]*proto.HomeConfigListResp, 0),
},
}
if totalCount == 0 {
return resp, nil
}
list, err := homeconfigmod.FindManyHomeConfig(ctx, filter, options.Find().
SetProjection(homeConfigWebProjection).
SetSort(bson.D{
{Key: homeconfigmod.FN.HomeConfig.Rank, Value: -1},
{Key: homeconfigmod.FN.HomeConfig.UpdatedAt, Value: -1},
{Key: homeconfigmod.FN.HomeConfig.Id, Value: -1},
}).
SetSkip((pageNum-1)*pageSize).
SetLimit(pageSize))
if err != nil {
return nil, err
}
items := make([]*proto.HomeConfigListResp, 0, len(list))
for _, item := range list {
if item == nil {
continue
}
items = append(items, &proto.HomeConfigListResp{
Id: item.Id,
Name: item.Name,
Slug: item.Slug,
Desc: item.Desc,
Keyword: homeconfigmod.NormalizeKeywords(item.Keyword),
Label: item.Label,
Style: item.Style,
CardBackgroundImage: item.CardBackgroundImage,
TopicIds: item.TopicIds,
CategoryId: item.CategoryId,
RecommendType: item.RecommendType,
Type: item.Type,
Rank: item.Rank,
Limit: item.Limit,
SortType: item.SortType,
Status: item.Status,
SeoInfo: normalizeHomeConfigSeoValue(item.SeoInfo),
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
})
}
resp.List = items
return resp, nil
}
// AddHomeConfig 新增首页配置
func AddHomeConfig(ctx context.Context, req *proto.HomeConfigAddReq) (*proto.HomeConfigAddResp, *srvdef.SrvErr) {
if req == nil {
return nil, srvdef.New(srvdef.ErrParamError, "", "")
}
name := strings.TrimSpace(req.Name)
if name == "" {
return nil, srvdef.New(srvdef.ErrParamError, "名称不能为空", "")
}
if !validHomeConfigType(req.Type) {
return nil, srvdef.New(srvdef.ErrParamError, "类型无效", "")
}
if !validHomeConfigSortType(req.SortType) {
return nil, srvdef.New(srvdef.ErrParamError, "排序字段无效", "")
}
if req.Limit < 0 {
return nil, srvdef.New(srvdef.ErrParamError, "展示数量不能小于0", "")
}
if req.Status == nil {
return nil, srvdef.New(srvdef.ErrParamError, "状态不能为空", "")
}
doc := &homeconfigmod.HomeConfig{
Name: name,
Slug: strings.TrimSpace(req.Slug),
Desc: strings.TrimSpace(req.Desc),
Keyword: homeconfigmod.NormalizeKeywords(req.Keyword),
Label: strings.TrimSpace(req.Label),
Style: strings.ToUpper(strings.TrimSpace(req.Style)),
CardBackgroundImage: strings.TrimSpace(req.CardBackgroundImage),
TopicIds: req.TopicIds,
CategoryId: req.CategoryId,
RecommendType: req.RecommendType,
Type: req.Type,
Rank: req.Rank,
Limit: req.Limit,
SortType: req.SortType,
Status: *req.Status,
SeoInfo: normalizeHomeConfigSeoValue(req.SeoInfo),
}
if err := ensureHomeConfigSlug(ctx, doc, 0); err != nil {
return nil, err
}
if err := validateHomeConfigTopics(ctx, doc); err != nil {
return nil, err
}
if err := homeconfigmod.InsertOneHomeConfig(ctx, doc); err != nil {
return nil, err
}
clearHomeConfigCache()
sitemapdirty.Mark(ctx)
return &proto.HomeConfigAddResp{Id: doc.Id}, nil
}
// UpdateHomeConfig 更新首页配置
func UpdateHomeConfig(ctx context.Context, req *proto.HomeConfigUpdateReq) *srvdef.SrvErr {
if req == nil || req.Id <= 0 {
return srvdef.New(srvdef.ErrParamError, "首页配置 ID无效", "")
}
info, err := homeconfigmod.FindOneHomeConfig(ctx, bson.M{homeconfigmod.FN.HomeConfig.Id: req.Id})
if err != nil {
return err
}
setDoc := bson.M{homeconfigmod.FN.HomeConfig.UpdatedAt: time.Now()}
if req.Name != nil {
name := strings.TrimSpace(*req.Name)
if name == "" {
return srvdef.New(srvdef.ErrParamError, "名称不能为空", "")
}
setDoc[homeconfigmod.FN.HomeConfig.Name] = name
}
if req.Desc != nil {
setDoc[homeconfigmod.FN.HomeConfig.Desc] = strings.TrimSpace(*req.Desc)
}
if req.Keyword != nil {
setDoc[homeconfigmod.FN.HomeConfig.Keyword] = homeconfigmod.NormalizeKeywords(*req.Keyword)
}
if req.Label != nil {
setDoc[homeconfigmod.FN.HomeConfig.Label] = strings.TrimSpace(*req.Label)
}
if req.Style != nil {
setDoc[homeconfigmod.FN.HomeConfig.Style] = strings.ToUpper(strings.TrimSpace(*req.Style))
}
if req.CardBackgroundImage != nil {
setDoc[homeconfigmod.FN.HomeConfig.CardBackgroundImage] = strings.TrimSpace(*req.CardBackgroundImage)
}
if req.TopicIds != nil {
setDoc[homeconfigmod.FN.HomeConfig.TopicIds] = *req.TopicIds
}
if req.CategoryId != nil {
setDoc[homeconfigmod.FN.HomeConfig.CategoryId] = *req.CategoryId
}
if req.RecommendType != nil {
setDoc[homeconfigmod.FN.HomeConfig.RecommendType] = *req.RecommendType
}
if req.Type != nil {
if !validHomeConfigType(*req.Type) {
return srvdef.New(srvdef.ErrParamError, "类型无效", "")
}
setDoc[homeconfigmod.FN.HomeConfig.Type] = *req.Type
}
if req.Rank != nil {
setDoc[homeconfigmod.FN.HomeConfig.Rank] = *req.Rank
}
if req.Limit != nil {
if *req.Limit < 0 {
return srvdef.New(srvdef.ErrParamError, "展示数量不能小于0", "")
}
setDoc[homeconfigmod.FN.HomeConfig.Limit] = *req.Limit
}
if req.SortType != nil {
if !validHomeConfigSortType(*req.SortType) {
return srvdef.New(srvdef.ErrParamError, "排序字段无效", "")
}
setDoc[homeconfigmod.FN.HomeConfig.SortType] = *req.SortType
}
if req.Status != nil {
setDoc[homeconfigmod.FN.HomeConfig.Status] = *req.Status
}
if req.SeoInfo != nil {
setDoc["seoInfo"] = normalizeHomeConfigSeoValue(*req.SeoInfo)
}
if serr := prepareHomeConfigSlugOnUpdate(ctx, req.Id, info, req, setDoc); serr != nil {
return serr
}
merged := *info
if v, ok := setDoc[homeconfigmod.FN.HomeConfig.Type]; ok {
merged.Type = v.(int32)
}
if v, ok := setDoc[homeconfigmod.FN.HomeConfig.Status]; ok {
merged.Status = v.(bool)
}
if v, ok := setDoc[homeconfigmod.FN.HomeConfig.TopicIds]; ok {
merged.TopicIds = v.([]int64)
}
if v, ok := setDoc[homeconfigmod.FN.HomeConfig.Style]; ok {
merged.Style = v.(string)
}
if v, ok := setDoc[homeconfigmod.FN.HomeConfig.CategoryId]; ok {
merged.CategoryId = v.(int64)
}
if v, ok := setDoc[homeconfigmod.FN.HomeConfig.RecommendType]; ok {
merged.RecommendType = v.(int64)
}
if err := validateHomeConfigTopics(ctx, &merged); err != nil {
return err
}
if req.TopicIds != nil {
setDoc[homeconfigmod.FN.HomeConfig.TopicIds] = merged.TopicIds
}
if len(setDoc) <= 1 {
return srvdef.New(srvdef.ErrParamError, "没有可更新字段", "")
}
if err := homeconfigmod.UpdateOneHomeConfig(ctx,
bson.M{homeconfigmod.FN.HomeConfig.Id: req.Id},
bson.M{"$set": setDoc},
); err != nil {
return err
}
clearHomeConfigCache()
sitemapdirty.Mark(ctx)
return nil
}
// DelHomeConfig 删除首页配置
func DelHomeConfig(ctx context.Context, req *proto.HomeConfigDelReq) *srvdef.SrvErr {
if req == nil || req.Id <= 0 {
return srvdef.New(srvdef.ErrParamError, "首页配置 ID无效", "")
}
count, err := homeconfigmod.DelOneHomeConfig(ctx, bson.M{homeconfigmod.FN.HomeConfig.Id: req.Id})
if err != nil {
return err
}
if count == 0 {
return srvdef.New(srvdef.ErrNoData, "", "")
}
clearHomeConfigCache()
sitemapdirty.Mark(ctx)
return nil
}
func validHomeConfigType(typ int32) bool {
return typ == homeconfigmod.TypePlaylet || typ == homeconfigmod.TypeTheme
}
func validHomeConfigSortType(sortType int32) bool {
return sortType == homeconfigmod.SortTypeRecommend ||
sortType == homeconfigmod.SortTypeHot ||
sortType == homeconfigmod.SortTypeLatest ||
sortType == homeconfigmod.SortTypeOnlineAt ||
sortType == homeconfigmod.SortTypeCategory
}
func clearHomeConfigCache() {
playletcache.ClearHomeCache()
}
// normalizeHomeConfigPage 规范分页参数,限制单页数量避免大分页拖慢查询
func normalizeHomeConfigPage(pageNum, pageSize int64) (int64, int64) {
if pageNum <= 0 {
pageNum = 1
}
if pageSize <= 0 {
pageSize = defaultHomeConfigPageSize
}
if pageSize > maxHomeConfigPageSize {
pageSize = maxHomeConfigPageSize
}
return pageNum, pageSize
}
// normalizeHomeConfigSeoValue 规范化 SEO 字段,避免 keywords 为 null
func normalizeHomeConfigSeoValue(seo pubdef.SeoValue) pubdef.SeoValue {
seo.Title = strings.TrimSpace(seo.Title)
seo.Description = strings.TrimSpace(seo.Description)
if seo.Keyworld == nil {
seo.Keyworld = make([]string, 0)
return seo
}
words := make([]string, 0, len(seo.Keyworld))
for _, word := range seo.Keyworld {
word = strings.TrimSpace(word)
if word == "" {
continue
}
words = append(words, word)
}
seo.Keyworld = words
return seo
}
+132
View File
@@ -0,0 +1,132 @@
package srv_homeconfig
import (
"context"
"strings"
"videoweb/pub/common/srvdef"
"videoweb/pub/common/utils"
"videoweb/pub/models/homeconfigmod"
"videoweb/web/api/proto"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
func ensureHomeConfigSlug(ctx context.Context, ac *homeconfigmod.HomeConfig, excludeId int64) *srvdef.SrvErr {
ac.Slug = utils.SanitizeSlug(ac.Slug)
if ac.Slug != "" {
if utils.IsSlugAllDigits(ac.Slug) {
return srvdef.New(srvdef.ErrParamError, "Slug不能全是数字", "Slug不能全是数字")
}
filter := bson.M{homeconfigmod.FN.HomeConfig.Slug: ac.Slug}
if excludeId > 0 {
filter[homeconfigmod.FN.HomeConfig.Id] = bson.M{"$ne": excludeId}
}
exist, _ := homeconfigmod.FindOneHomeConfig(ctx, filter)
if exist != nil {
return srvdef.New(srvdef.ErrDbInputExist, "Slug已存在", "Slug已存在")
}
return nil
}
source := utils.SlugSourceFromKeywordsOrTitle(ac.SeoInfo.Keyworld, ac.Name)
ac.Slug = utils.MakeUniqueSlug(source, func(slug string) bool {
filter := bson.M{homeconfigmod.FN.HomeConfig.Slug: slug}
if excludeId > 0 {
filter[homeconfigmod.FN.HomeConfig.Id] = bson.M{"$ne": excludeId}
}
exist, _ := homeconfigmod.FindOneHomeConfig(ctx, filter)
return exist != nil
})
return nil
}
func prepareHomeConfigSlugOnUpdate(ctx context.Context, id int64, info *homeconfigmod.HomeConfig, req *proto.HomeConfigUpdateReq, setDoc bson.M) *srvdef.SrvErr {
slug := info.Slug
if req.Slug != nil {
slug = utils.SanitizeSlug(*req.Slug)
}
if slug != "" {
if req.Slug != nil {
if utils.IsSlugAllDigits(slug) {
return srvdef.New(srvdef.ErrParamError, "Slug不能全是数字", "Slug不能全是数字")
}
exist, _ := homeconfigmod.FindOneHomeConfig(ctx, bson.M{
homeconfigmod.FN.HomeConfig.Slug: slug,
homeconfigmod.FN.HomeConfig.Id: bson.M{"$ne": id},
})
if exist != nil {
return srvdef.New(srvdef.ErrDbInputExist, "Slug已存在", "Slug已存在")
}
setDoc[homeconfigmod.FN.HomeConfig.Slug] = slug
}
return nil
}
name := info.Name
if req.Name != nil {
name = strings.TrimSpace(*req.Name)
}
keywords := info.SeoInfo.Keyworld
if req.SeoInfo != nil {
keywords = normalizeHomeConfigSeoValue(*req.SeoInfo).Keyworld
}
source := utils.SlugSourceFromKeywordsOrTitle(keywords, name)
setDoc[homeconfigmod.FN.HomeConfig.Slug] = utils.MakeUniqueSlug(source, func(s string) bool {
exist, _ := homeconfigmod.FindOneHomeConfig(ctx, bson.M{
homeconfigmod.FN.HomeConfig.Slug: s,
homeconfigmod.FN.HomeConfig.Id: bson.M{"$ne": id},
})
return exist != nil
})
return nil
}
func emptyHomeConfigSlugFilter() bson.M {
return bson.M{
"$or": []bson.M{
{homeconfigmod.FN.HomeConfig.Slug: ""},
{homeconfigmod.FN.HomeConfig.Slug: bson.M{"$exists": false}},
},
}
}
// SyncEmptySlugs 为首页配置中空 slug 自动生成。
func SyncEmptySlugs(ctx context.Context, maxSize int64) (int64, bool, *srvdef.SrvErr) {
if maxSize <= 0 {
return 0, false, nil
}
list, err := homeconfigmod.FindManyHomeConfig(ctx, emptyHomeConfigSlugFilter(), options.Find().
SetSort(bson.D{{Key: homeconfigmod.FN.HomeConfig.Id, Value: 1}}).
SetLimit(maxSize+1))
if err != nil {
return 0, false, err
}
hasMore := int64(len(list)) > maxSize
if hasMore {
list = list[:maxSize]
}
var updated int64
for _, item := range list {
if item == nil {
continue
}
if serr := ensureHomeConfigSlug(ctx, item, item.Id); serr != nil {
return updated, hasMore, serr
}
if strings.TrimSpace(item.Slug) == "" {
continue
}
if serr := homeconfigmod.UpdateOneHomeConfig(ctx,
bson.M{homeconfigmod.FN.HomeConfig.Id: item.Id},
bson.M{"$set": bson.M{homeconfigmod.FN.HomeConfig.Slug: item.Slug}},
); serr != nil {
return updated, hasMore, serr
}
updated++
}
return updated, hasMore, nil
}
func HasEmptySlug(ctx context.Context) bool {
count, _ := homeconfigmod.CountHomeConfig(ctx, emptyHomeConfigSlugFilter())
return count > 0
}
+142
View File
@@ -0,0 +1,142 @@
package srv_homeconfig
import (
"context"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/homeconfigmod"
"videoweb/pub/models/playletthememod"
"videoweb/web/api/proto"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
// validateHomeConfigTopics 校验题材配置、去重,并阻止启用模块重复占用题材
func validateHomeConfigTopics(ctx context.Context, config *homeconfigmod.HomeConfig) *srvdef.SrvErr {
if config.Style != "" && (len(config.Style) != 1 || config.Style[0] < 'A' || config.Style[0] > 'H') {
return srvdef.New(srvdef.ErrParamError, "样式仅支持 A-H", "")
}
if config.CategoryId < 0 || config.RecommendType < 0 || config.RecommendType > 5 {
return srvdef.New(srvdef.ErrParamError, "推荐配置无效", "")
}
if config.RecommendType == 5 && config.CategoryId == 0 {
return srvdef.New(srvdef.ErrParamError, "按分类推荐时必须填写分类ID", "")
}
if config.Type != homeconfigmod.TypeTheme {
if len(config.TopicIds) != 0 {
return srvdef.New(srvdef.ErrParamError, "短剧模块不能配置题材ID", "")
}
return nil
}
seen := map[int64]bool{}
ids := make([]int64, 0, len(config.TopicIds))
for _, id := range config.TopicIds {
if id <= 0 {
return srvdef.New(srvdef.ErrParamError, "题材ID无效", "")
}
if !seen[id] {
ids = append(ids, id)
seen[id] = true
}
}
config.TopicIds = ids
if !config.Status {
return nil
}
if len(ids) == 0 {
if config.Id == 0 {
return srvdef.New(srvdef.ErrParamError, "启用的题材模块必须配置题材ID", "")
}
return nil // 历史题材配置沿用自动选题材
}
themes, err := playletthememod.FindManyPlayletTheme(ctx, bson.M{playletthememod.FN.PlayletTheme.Id: bson.M{"$in": ids}, playletthememod.FN.PlayletTheme.Status: true})
if err != nil {
return err
}
if len(themes) != len(ids) {
return srvdef.New(srvdef.ErrParamError, "题材不存在或未上架", "")
}
others, err := homeconfigmod.FindManyHomeConfig(ctx, bson.M{homeconfigmod.FN.HomeConfig.Status: true, homeconfigmod.FN.HomeConfig.Type: homeconfigmod.TypeTheme, homeconfigmod.FN.HomeConfig.TopicIds: bson.M{"$in": ids}})
if err != nil {
return err
}
for _, other := range others {
if other != nil && other.Id != config.Id {
return srvdef.New(srvdef.ErrParamError, "题材已被其他启用模块使用", "")
}
}
return nil
}
// ListHomeTopicOptions 分页查询可选的已上架短剧题材,并回显当前配置已选题材
func ListHomeTopicOptions(ctx context.Context, req *proto.HomeTopicOptionsReq) (*proto.HomeTopicOptionsResp, *srvdef.SrvErr) {
if req == nil || req.ConfigId < 0 {
return nil, srvdef.New(srvdef.ErrParamError, "配置ID无效", "")
}
pageNum, pageSize := normalizeHomeConfigPage(req.PageNum, req.PageSize)
resp := &proto.HomeTopicOptionsResp{List: make([]*proto.HomeTopicOption, 0), SelectedList: make([]*proto.HomeTopicOption, 0), PageNum: pageNum, PageSize: pageSize}
var selected []int64
if req.ConfigId > 0 {
current, err := homeconfigmod.FindOneHomeConfig(ctx, bson.M{homeconfigmod.FN.HomeConfig.Id: req.ConfigId})
if err != nil {
return nil, err
}
if current.Type != homeconfigmod.TypeTheme {
return nil, srvdef.New(srvdef.ErrParamError, "当前配置不是题材模块", "")
}
selected = current.TopicIds
}
occupied := map[int64]bool{}
configs, err := homeconfigmod.FindManyHomeConfig(ctx, bson.M{homeconfigmod.FN.HomeConfig.Status: true, homeconfigmod.FN.HomeConfig.Type: homeconfigmod.TypeTheme})
if err != nil {
return nil, err
}
for _, config := range configs {
if config != nil && config.Id != req.ConfigId {
for _, id := range config.TopicIds {
occupied[id] = true
}
}
}
filter := bson.M{playletthememod.FN.PlayletTheme.Status: true}
if len(occupied) > 0 {
ids := make([]int64, 0, len(occupied))
for id := range occupied {
ids = append(ids, id)
}
filter[playletthememod.FN.PlayletTheme.Id] = bson.M{"$nin": ids}
}
resp.TotalCount, err = playletthememod.CountPlayletTheme(ctx, filter)
if err != nil {
return nil, err
}
list, err := playletthememod.FindManyPlayletTheme(ctx, filter, options.Find().SetSort(bson.D{{Key: playletthememod.FN.PlayletTheme.Rank, Value: -1}, {Key: playletthememod.FN.PlayletTheme.Id, Value: -1}}).SetSkip((pageNum-1)*pageSize).SetLimit(pageSize))
if err != nil {
return nil, err
}
for _, item := range list {
if item != nil {
resp.List = append(resp.List, &proto.HomeTopicOption{Id: item.Id, Name: item.Name, Status: item.Status})
}
}
if len(selected) > 0 {
themes, err := playletthememod.FindManyPlayletTheme(ctx, bson.M{playletthememod.FN.PlayletTheme.Id: bson.M{"$in": selected}})
if err != nil {
return nil, err
}
byID := map[int64]*proto.HomeTopicOption{}
for _, item := range themes {
if item != nil {
byID[item.Id] = &proto.HomeTopicOption{Id: item.Id, Name: item.Name, Status: item.Status}
}
}
for _, id := range selected {
if item := byID[id]; item != nil {
resp.SelectedList = append(resp.SelectedList, item)
} else {
resp.SelectedList = append(resp.SelectedList, &proto.HomeTopicOption{Id: id})
}
}
}
return resp, nil
}