@@ -0,0 +1,284 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListAlbum(req *AlbumListReq) (int64, []officialwebsitemod.Album, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.Album{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
// resolveAlbumSeoSlug 处理 seoSlug:手填则校验格式并查重(冲突报错);为空则由标题生成雏形并追加后缀去重。
|
||||
func resolveAlbumSeoSlug(provided, title string, excludeID primitive.ObjectID) (string, error) {
|
||||
return ResolveSeoSlug(provided, title, func(slug string) (bool, error) {
|
||||
filter := officialwebsitemod.M{"seoSlug": slug}
|
||||
if !excludeID.IsZero() {
|
||||
filter["_id"] = officialwebsitemod.M{"$ne": excludeID}
|
||||
}
|
||||
n, err := (&officialwebsitemod.Album{}).Count(filter)
|
||||
return n > 0, err
|
||||
})
|
||||
}
|
||||
|
||||
func CreateAlbum(req *ModifyAlbumReq) (officialwebsitemod.Album, error) {
|
||||
data, err := req.toMod()
|
||||
if err != nil {
|
||||
return officialwebsitemod.Album{}, err
|
||||
}
|
||||
if data.SeoSlug, err = resolveAlbumSeoSlug(data.SeoSlug, data.Title, primitive.NilObjectID); err != nil {
|
||||
return officialwebsitemod.Album{}, err
|
||||
}
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.Album{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdateAlbum(req *ModifyAlbumReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Album{}
|
||||
err = mod.FindOne(officialwebsitemod.M{"_id": id})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(mod.ID) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
// 若提交了 seoSlug,先校验/去重(排除自身),回写后由 toM 落库
|
||||
if req.SeoSlug != nil {
|
||||
var slug string
|
||||
if slug, err = resolveAlbumSeoSlug(*req.SeoSlug, mod.Title, id); err != nil {
|
||||
return
|
||||
}
|
||||
*req.SeoSlug = slug
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteAlbum(req *DeleteAlbumReq) (data DeleteAlbumResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Album{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyAlbumReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
HeroID *string `json:"heroID" form:"heroID"`
|
||||
Title *string `json:"title"`
|
||||
SeoSlug *string `json:"seoSlug"`
|
||||
Description *string `json:"description"`
|
||||
Cover *string `json:"cover"`
|
||||
IsHot *bool `json:"isHot"`
|
||||
Tags *[]officialwebsitemod.Tag `json:"tags"`
|
||||
Sort *int64 `json:"sort"`
|
||||
IsActive *bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteAlbumReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeleteAlbumResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyAlbumReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyAlbumReq) toMod() (officialwebsitemod.Album, error) {
|
||||
if req == nil {
|
||||
return officialwebsitemod.Album{}, nil
|
||||
}
|
||||
data := officialwebsitemod.Album{
|
||||
Title: stringOrZero(req.Title),
|
||||
Description: stringOrZero(req.Description),
|
||||
Cover: stringOrZero(req.Cover),
|
||||
IsHot: boolOrZero(req.IsHot),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: int64OrZero(req.Sort),
|
||||
IsActive: boolOrZero(req.IsActive),
|
||||
},
|
||||
}
|
||||
if req.HeroID != nil {
|
||||
if *req.HeroID != "" {
|
||||
heroID, err := primitive.ObjectIDFromHex(*req.HeroID)
|
||||
if err != nil || isNilObjectID(heroID) {
|
||||
return officialwebsitemod.Album{}, stderr.ErrParamError
|
||||
}
|
||||
data.HeroID = heroID
|
||||
}
|
||||
}
|
||||
if req.Tags != nil {
|
||||
data.Tags = *req.Tags
|
||||
}
|
||||
if req.SeoSlug != nil {
|
||||
data.SeoSlug = *req.SeoSlug
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyAlbumReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyAlbumReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.HeroID != nil {
|
||||
if *req.HeroID != "" {
|
||||
heroID, err := primitive.ObjectIDFromHex(*req.HeroID)
|
||||
if err != nil || isNilObjectID(heroID) {
|
||||
return nil, stderr.ErrParamError
|
||||
}
|
||||
set["heroID"] = heroID
|
||||
}
|
||||
}
|
||||
if req.Title != nil {
|
||||
set["title"] = *req.Title
|
||||
}
|
||||
if req.SeoSlug != nil && *req.SeoSlug != "" {
|
||||
set["seoSlug"] = *req.SeoSlug
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.Cover != nil {
|
||||
set["cover"] = *req.Cover
|
||||
}
|
||||
if req.IsHot != nil {
|
||||
set["isHot"] = *req.IsHot
|
||||
}
|
||||
if req.Tags != nil {
|
||||
set["tags"] = *req.Tags
|
||||
}
|
||||
if req.Sort != nil {
|
||||
set["sort"] = *req.Sort
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
set["isActive"] = *req.IsActive
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type AlbumListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
HeroID *string `form:"heroID"`
|
||||
Title *string `form:"title"`
|
||||
Description *string `form:"description"`
|
||||
Cover *string `form:"cover"`
|
||||
IsHot *bool `form:"isHot"`
|
||||
Tags *string `form:"tags"`
|
||||
Sort *int64 `form:"sort"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *AlbumListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := parseObjectIDFilter(filter, "heroID", r.HeroID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Title != nil {
|
||||
filter["title"] = *r.Title
|
||||
}
|
||||
if r.Description != nil {
|
||||
filter["description"] = *r.Description
|
||||
}
|
||||
if r.Cover != nil {
|
||||
filter["cover"] = *r.Cover
|
||||
}
|
||||
if r.IsHot != nil {
|
||||
filter["isHot"] = *r.IsHot
|
||||
}
|
||||
if err := parseJSONFilter(filter, "tags", r.Tags, &[]officialwebsitemod.Tag{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Sort != nil {
|
||||
filter["sort"] = *r.Sort
|
||||
}
|
||||
if r.IsActive != nil {
|
||||
filter["isActive"] = *r.IsActive
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/common/log"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
var seoSlugBackfillCron *cron.Cron
|
||||
|
||||
// StartSeoSlugBackfillCron 启动定时任务:扫描官网各表(Video/Hero/Album/News/Photograph)
|
||||
// 中缺失 seoSlug 的记录,按标题自动生成并回填。
|
||||
// 启动后异步先跑一次(补存量),之后每小时扫一次(兜底导入/批量遗漏的记录)。
|
||||
func StartSeoSlugBackfillCron() {
|
||||
go backfillAllSeoSlug() // 首次异步执行,避免阻塞服务启动
|
||||
seoSlugBackfillCron = cron.New()
|
||||
if _, err := seoSlugBackfillCron.AddFunc("@every 1h", backfillAllSeoSlug); err != nil {
|
||||
log.Error("StartSeoSlugBackfillCron AddFunc fail", log.E(err))
|
||||
return
|
||||
}
|
||||
seoSlugBackfillCron.Start()
|
||||
}
|
||||
|
||||
func backfillAllSeoSlug() {
|
||||
backfillVideoSeoSlug()
|
||||
backfillHeroSeoSlug()
|
||||
backfillAlbumSeoSlug()
|
||||
backfillNewsSeoSlug()
|
||||
backfillPhotographSeoSlug()
|
||||
}
|
||||
|
||||
// seoSlugMissingFilter 匹配 seoSlug 字段缺失或为空的记录。
|
||||
func seoSlugMissingFilter() officialwebsitemod.M {
|
||||
return officialwebsitemod.M{"$or": []officialwebsitemod.M{
|
||||
{"seoSlug": officialwebsitemod.M{"$exists": false}},
|
||||
{"seoSlug": ""},
|
||||
}}
|
||||
}
|
||||
|
||||
// setSeoSlug 回填单条记录的 seoSlug。
|
||||
func setSeoSlug(update func(officialwebsitemod.M, officialwebsitemod.M) (int64, error), id interface{}, slug string) {
|
||||
if _, err := update(officialwebsitemod.M{"_id": id}, officialwebsitemod.M{"$set": officialwebsitemod.M{"seoSlug": slug}}); err != nil {
|
||||
log.Error("backfill seoSlug update fail", log.E(err), log.Any("id", id))
|
||||
}
|
||||
}
|
||||
|
||||
func backfillVideoSeoSlug() {
|
||||
mod := &officialwebsitemod.Video{}
|
||||
list, err := mod.FindMany(seoSlugMissingFilter())
|
||||
if err != nil {
|
||||
log.Error("backfill video seoSlug find fail", log.E(err))
|
||||
return
|
||||
}
|
||||
for i := range list {
|
||||
if list[i].Title == "" {
|
||||
continue
|
||||
}
|
||||
slug, e := resolveVideoSeoSlug("", list[i].Title, list[i].ID)
|
||||
if e != nil || slug == "" {
|
||||
continue
|
||||
}
|
||||
setSeoSlug(mod.Update, list[i].ID, slug)
|
||||
}
|
||||
}
|
||||
|
||||
func backfillHeroSeoSlug() {
|
||||
mod := &officialwebsitemod.Hero{}
|
||||
list, err := mod.FindMany(seoSlugMissingFilter())
|
||||
if err != nil {
|
||||
log.Error("backfill hero seoSlug find fail", log.E(err))
|
||||
return
|
||||
}
|
||||
for i := range list {
|
||||
if list[i].Name == "" {
|
||||
continue
|
||||
}
|
||||
slug, e := resolveHeroSeoSlug("", list[i].Name, list[i].ID)
|
||||
if e != nil || slug == "" {
|
||||
continue
|
||||
}
|
||||
setSeoSlug(mod.Update, list[i].ID, slug)
|
||||
}
|
||||
}
|
||||
|
||||
func backfillAlbumSeoSlug() {
|
||||
mod := &officialwebsitemod.Album{}
|
||||
list, err := mod.FindMany(seoSlugMissingFilter())
|
||||
if err != nil {
|
||||
log.Error("backfill album seoSlug find fail", log.E(err))
|
||||
return
|
||||
}
|
||||
for i := range list {
|
||||
if list[i].Title == "" {
|
||||
continue
|
||||
}
|
||||
slug, e := resolveAlbumSeoSlug("", list[i].Title, list[i].ID)
|
||||
if e != nil || slug == "" {
|
||||
continue
|
||||
}
|
||||
setSeoSlug(mod.Update, list[i].ID, slug)
|
||||
}
|
||||
}
|
||||
|
||||
func backfillNewsSeoSlug() {
|
||||
mod := &officialwebsitemod.News{}
|
||||
list, err := mod.FindMany(seoSlugMissingFilter())
|
||||
if err != nil {
|
||||
log.Error("backfill news seoSlug find fail", log.E(err))
|
||||
return
|
||||
}
|
||||
for i := range list {
|
||||
if list[i].Title == "" {
|
||||
continue
|
||||
}
|
||||
slug, e := resolveNewsSeoSlug("", list[i].Title, list[i].ID)
|
||||
if e != nil || slug == "" {
|
||||
continue
|
||||
}
|
||||
setSeoSlug(mod.Update, list[i].ID, slug)
|
||||
}
|
||||
}
|
||||
|
||||
func backfillPhotographSeoSlug() {
|
||||
mod := &officialwebsitemod.Photograph{}
|
||||
list, err := mod.FindMany(seoSlugMissingFilter())
|
||||
if err != nil {
|
||||
log.Error("backfill photograph seoSlug find fail", log.E(err))
|
||||
return
|
||||
}
|
||||
for i := range list {
|
||||
if list[i].Name == "" {
|
||||
continue
|
||||
}
|
||||
slug, e := resolvePhotographSeoSlug("", list[i].Name, list[i].ID)
|
||||
if e != nil || slug == "" {
|
||||
continue
|
||||
}
|
||||
setSeoSlug(mod.Update, list[i].ID, slug)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,779 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/common"
|
||||
"91porn-server/common/cachev2"
|
||||
"91porn-server/common/constant/redisconst"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func GetBasicData() (data GetBasicDataResp, err error) {
|
||||
mod := &officialwebsitemod.BasicData{}
|
||||
if err = mod.FindOne(); err != nil {
|
||||
return
|
||||
}
|
||||
err = data.transfer(mod)
|
||||
return
|
||||
}
|
||||
|
||||
func CreateBasicData(req *ModifyBasicDataReq) (data officialwebsitemod.BasicData, err error) {
|
||||
data, err = req.toMod()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = data.Create(); err != nil {
|
||||
return officialwebsitemod.BasicData{}, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func UpdateBasicData(req *ModifyBasicDataReq) (resp UpdateBasicDataResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.BasicData{}
|
||||
if err = mod.FindOne(); err != nil {
|
||||
return
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
|
||||
common.Go(func() {
|
||||
// 删除缓存
|
||||
cachev2.Classes().
|
||||
CacheTime(redisconst.OfficialWebsiteBasicDataCacheExpire).
|
||||
AutoListKey(redisconst.OfficialWebsiteBasicDataCacheKey).
|
||||
DeleteCurrent()
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteBasicData(req *DeleteBasicDataReq) (data DeleteBasicDataResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.BasicData{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Query (BasicData) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type GetBasicDataReq struct{}
|
||||
|
||||
type GetBasicDataResp struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
Title string `json:"title" bson:"title"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Banner []GBDBanner `json:"banner" bson:"banner"`
|
||||
HeroBanner []GBDHeroBanner `json:"heroBanner" bson:"heroBanner"`
|
||||
Masterpiece []GBDMasterpiece `json:"masterpiece" bson:"masterpiece"`
|
||||
Business []GBDBusiness `json:"business" bson:"business"`
|
||||
BannersDescription string `json:"bannersDescription" bson:"bannersDescription"`
|
||||
BannersDuration int `json:"bannersDuration" bson:"bannersDuration"`
|
||||
AboutUs GBDAboutUs `json:"aboutUs" bson:"aboutUs"`
|
||||
FAQ []GBDFAQ `json:"faq" bson:"faq"`
|
||||
HomePageCMS []GBDCMSData `json:"homePageCMS" bson:"homePageCMS"`
|
||||
HomePageCMSDescription string `json:"homePageCMSDescription" bson:"homePageCMSDescription"`
|
||||
RecruitCMS []GBDCMSData `json:"recruitCMS" bson:"recruitCMS"`
|
||||
Tags []officialwebsitemod.Tag `json:"tags" bson:"tags"`
|
||||
}
|
||||
|
||||
type GBDBanner struct {
|
||||
Name string `json:"name" bson:"name"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Image string `json:"image" bson:"image"`
|
||||
PhoneImage string `json:"phoneImage" bson:"phoneImage"`
|
||||
Thumbnail string `json:"thumbnail" bson:"thumbnail"`
|
||||
URL string `json:"url" bson:"url"`
|
||||
}
|
||||
|
||||
type GBDHeroBanner struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
HeroID string `json:"heroId" bson:"heroId"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Image string `json:"image" bson:"image"`
|
||||
URL string `json:"url" bson:"url"`
|
||||
Duration int `json:"duration" bson:"duration"`
|
||||
}
|
||||
|
||||
type GBDMasterpiece struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Cover string `json:"cover" bson:"cover"`
|
||||
Type string `json:"type" bson:"type"`
|
||||
}
|
||||
|
||||
type GBDBusiness struct {
|
||||
Name string `json:"name" bson:"name"`
|
||||
EnglishName string `json:"englishName" bson:"englishName"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Cover string `json:"cover" bson:"cover"`
|
||||
Detail []GBDBusinessDetail `json:"detail" bson:"detail"`
|
||||
}
|
||||
|
||||
type GBDBusinessDetail struct {
|
||||
Cover string `json:"cover" bson:"cover"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
}
|
||||
|
||||
type GBDAboutUs struct {
|
||||
Description string `json:"description" bson:"description"`
|
||||
Companies []GBDCompanyInfo `json:"companies" bson:"companies"`
|
||||
Values string `json:"values" bson:"values"`
|
||||
ValuesImg string `json:"valuesImg" bson:"valuesImg"`
|
||||
}
|
||||
|
||||
type GBDCompanyInfo struct {
|
||||
Name string `json:"name" bson:"name"`
|
||||
Address string `json:"address" bson:"address"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Contact []GBDContactInfo `json:"contact" bson:"contact"`
|
||||
}
|
||||
|
||||
type GBDContactInfo struct {
|
||||
Type string `json:"type" bson:"type"`
|
||||
Value string `json:"value" bson:"value"`
|
||||
}
|
||||
|
||||
type GBDFAQ struct {
|
||||
Question string `json:"question" bson:"question"`
|
||||
Answer string `json:"answer" bson:"answer"`
|
||||
}
|
||||
|
||||
type GBDCMSData struct {
|
||||
Description string `json:"description" bson:"description"`
|
||||
Value string `json:"value" bson:"value"`
|
||||
}
|
||||
|
||||
func (data *GetBasicDataResp) transfer(mod *officialwebsitemod.BasicData) error {
|
||||
if mod == nil {
|
||||
return stderr.CodeEmptyData
|
||||
}
|
||||
data.ID = mod.ID
|
||||
data.Title = mod.Title
|
||||
data.Description = mod.Description
|
||||
data.Tags = mod.Tags
|
||||
data.BannersDescription = mod.BannersDescription
|
||||
data.BannersDuration = mod.BannersDuration
|
||||
data.HomePageCMSDescription = mod.HomePageCMSDescription
|
||||
data.AboutUs.Description = mod.AboutUs.Description
|
||||
data.AboutUs.Values = mod.AboutUs.Values
|
||||
data.AboutUs.ValuesImg = mod.AboutUs.ValuesImg
|
||||
|
||||
data.Banner = make([]GBDBanner, 0, len(mod.Banner))
|
||||
for _, v := range mod.Banner {
|
||||
data.Banner = append(data.Banner, GBDBanner{
|
||||
Name: v.Name, Description: v.Description, Image: v.Image, PhoneImage: v.PhoneImage, Thumbnail: v.Thumbnail, URL: v.URL,
|
||||
})
|
||||
}
|
||||
data.HeroBanner = make([]GBDHeroBanner, 0, len(mod.HeroBanner))
|
||||
for _, v := range mod.HeroBanner {
|
||||
data.HeroBanner = append(data.HeroBanner, GBDHeroBanner{
|
||||
ID: v.ID, HeroID: v.HeroID.Hex(), Name: v.Name, Description: v.Description, Image: v.Image, URL: v.URL, Duration: v.Duration,
|
||||
})
|
||||
}
|
||||
data.Masterpiece = make([]GBDMasterpiece, 0, len(mod.Masterpiece))
|
||||
for _, v := range mod.Masterpiece {
|
||||
data.Masterpiece = append(data.Masterpiece, GBDMasterpiece{
|
||||
ID: v.ID, Name: v.Name, Description: v.Description, Cover: v.Cover, Type: v.Type,
|
||||
})
|
||||
}
|
||||
data.Business = make([]GBDBusiness, 0, len(mod.Business))
|
||||
for _, v := range mod.Business {
|
||||
business := GBDBusiness{
|
||||
Name: v.Name, EnglishName: v.EnglishName, Description: v.Description, Cover: v.Cover,
|
||||
Detail: make([]GBDBusinessDetail, 0, len(v.Detail)),
|
||||
}
|
||||
for _, d := range v.Detail {
|
||||
business.Detail = append(business.Detail, GBDBusinessDetail{
|
||||
Cover: d.Cover, Description: d.Description,
|
||||
})
|
||||
}
|
||||
data.Business = append(data.Business, business)
|
||||
}
|
||||
data.AboutUs.Companies = make([]GBDCompanyInfo, 0, len(mod.AboutUs.Companies))
|
||||
for _, v := range mod.AboutUs.Companies {
|
||||
company := GBDCompanyInfo{
|
||||
Name: v.Name, Address: v.Address, Description: v.Description,
|
||||
Contact: make([]GBDContactInfo, 0, len(v.Contact)),
|
||||
}
|
||||
for _, c := range v.Contact {
|
||||
company.Contact = append(company.Contact, GBDContactInfo{Type: c.Type, Value: c.Value})
|
||||
}
|
||||
data.AboutUs.Companies = append(data.AboutUs.Companies, company)
|
||||
}
|
||||
data.FAQ = make([]GBDFAQ, 0, len(mod.FAQ))
|
||||
for _, v := range mod.FAQ {
|
||||
data.FAQ = append(data.FAQ, GBDFAQ{Question: v.Question, Answer: v.Answer})
|
||||
}
|
||||
data.HomePageCMS = make([]GBDCMSData, 0, len(mod.HomePageCMS))
|
||||
for _, v := range mod.HomePageCMS {
|
||||
data.HomePageCMS = append(data.HomePageCMS, GBDCMSData{Description: v.Description, Value: v.Value})
|
||||
}
|
||||
data.RecruitCMS = make([]GBDCMSData, 0, len(mod.RecruitCMS))
|
||||
for _, v := range mod.RecruitCMS {
|
||||
data.RecruitCMS = append(data.RecruitCMS, GBDCMSData{Description: v.Description, Value: v.Value})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyBasicDataReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Title *string `json:"title" bson:"title"`
|
||||
Description *string `json:"description" bson:"description"`
|
||||
Banner *[]ModifyBanner `json:"banner" bson:"banner"`
|
||||
HeroBanner *[]ModifyHeroBanner `json:"heroBanner" bson:"heroBanner"`
|
||||
Masterpiece *[]ModifyMasterpiece `json:"masterpiece" bson:"masterpiece"`
|
||||
Business *[]ModifyBusiness `json:"business" bson:"business"`
|
||||
BannersDescription *string `json:"bannersDescription" bson:"bannersDescription"`
|
||||
BannersDuration *int `json:"bannersDuration" bson:"bannersDuration"`
|
||||
AboutUs *ModifyAboutUs `json:"aboutUs" bson:"aboutUs"`
|
||||
FAQ *[]ModifyFAQ `json:"faq" bson:"faq"`
|
||||
HomePageCMS *[]ModifyCMSData `json:"homePageCMS" bson:"homePageCMS"`
|
||||
HomePageCMSDescription *string `json:"homePageCMSDescription" bson:"homePageCMSDescription"`
|
||||
RecruitCMS *[]ModifyCMSData `json:"recruitCMS" bson:"recruitCMS"`
|
||||
Tags *[]officialwebsitemod.Tag `json:"tags" bson:"tags"`
|
||||
}
|
||||
|
||||
type ModifyBanner struct {
|
||||
Name *string `json:"name" bson:"name"`
|
||||
Description *string `json:"description" bson:"description"`
|
||||
Image *string `json:"image" bson:"image"`
|
||||
PhoneImage *string `json:"phoneImage" bson:"phoneImage"`
|
||||
Thumbnail *string `json:"thumbnail" bson:"thumbnail"`
|
||||
URL *string `json:"url" bson:"url"`
|
||||
}
|
||||
|
||||
type ModifyHeroBanner struct {
|
||||
ID *primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
HeroID *primitive.ObjectID `json:"heroId" bson:"heroId"`
|
||||
Name *string `json:"name" bson:"name"`
|
||||
Description *string `json:"description" bson:"description"`
|
||||
Image *string `json:"image" bson:"image"`
|
||||
URL *string `json:"url" bson:"url"`
|
||||
Duration *int `json:"duration" bson:"duration"`
|
||||
}
|
||||
|
||||
type ModifyMasterpiece struct {
|
||||
ID *primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
Name *string `json:"name" bson:"name"`
|
||||
Description *string `json:"description" bson:"description"`
|
||||
Cover *string `json:"cover" bson:"cover"`
|
||||
Type *string `json:"type" bson:"type"`
|
||||
}
|
||||
|
||||
type ModifyBusiness struct {
|
||||
Name *string `json:"name" bson:"name"`
|
||||
EnglishName *string `json:"englishName" bson:"englishName"`
|
||||
Description *string `json:"description" bson:"description"`
|
||||
Cover *string `json:"cover" bson:"cover"`
|
||||
Detail *[]ModifyBusinessDetail `json:"detail" bson:"detail"`
|
||||
}
|
||||
|
||||
type ModifyBusinessDetail struct {
|
||||
Cover *string `json:"cover" bson:"cover"`
|
||||
Description *string `json:"description" bson:"description"`
|
||||
}
|
||||
|
||||
type ModifyAboutUs struct {
|
||||
Description *string `json:"description" bson:"description"`
|
||||
Companies *[]ModifyCompanyInfo `json:"companies" bson:"companies"`
|
||||
Values *string `json:"values" bson:"values"`
|
||||
ValuesImg *string `json:"valuesImg" bson:"valuesImg"`
|
||||
}
|
||||
|
||||
type ModifyCompanyInfo struct {
|
||||
Name *string `json:"name" bson:"name"`
|
||||
Address *string `json:"address" bson:"address"`
|
||||
Description *string `json:"description" bson:"description"`
|
||||
Contact *[]ModifyContactInfo `json:"contact" bson:"contact"`
|
||||
}
|
||||
|
||||
type ModifyContactInfo struct {
|
||||
Type *string `json:"type" bson:"type"`
|
||||
Value *string `json:"value" bson:"value"`
|
||||
}
|
||||
|
||||
type ModifyFAQ struct {
|
||||
Question *string `json:"question" bson:"question"`
|
||||
Answer *string `json:"answer" bson:"answer"`
|
||||
}
|
||||
|
||||
type ModifyCMSData struct {
|
||||
Description *string `json:"description" bson:"description"`
|
||||
Value *string `json:"value" bson:"value"`
|
||||
}
|
||||
|
||||
type UpdateBasicDataResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteBasicDataReq struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type DeleteBasicDataResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — Modify* → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (v ModifyBanner) toMod() officialwebsitemod.Banner {
|
||||
return officialwebsitemod.Banner{
|
||||
Name: stringOrZero(v.Name), Description: stringOrZero(v.Description),
|
||||
Image: stringOrZero(v.Image), Thumbnail: stringOrZero(v.Thumbnail),
|
||||
PhoneImage: stringOrZero(v.PhoneImage), URL: stringOrZero(v.URL),
|
||||
}
|
||||
}
|
||||
|
||||
func (v ModifyHeroBanner) toMod() officialwebsitemod.HeroBanner {
|
||||
return officialwebsitemod.HeroBanner{
|
||||
HeroID: objectIDOrZero(v.HeroID), Name: stringOrZero(v.Name), Description: stringOrZero(v.Description),
|
||||
Image: stringOrZero(v.Image), URL: stringOrZero(v.URL), Duration: intOrZero(v.Duration),
|
||||
}
|
||||
}
|
||||
|
||||
func (v ModifyMasterpiece) toMod() officialwebsitemod.Masterpiece {
|
||||
return officialwebsitemod.Masterpiece{
|
||||
ID: objectIDOrZero(v.ID), Name: stringOrZero(v.Name), Description: stringOrZero(v.Description),
|
||||
Cover: stringOrZero(v.Cover), Type: stringOrZero(v.Type),
|
||||
}
|
||||
}
|
||||
|
||||
func (v ModifyBusiness) toMod() officialwebsitemod.Business {
|
||||
out := officialwebsitemod.Business{
|
||||
Name: stringOrZero(v.Name), EnglishName: stringOrZero(v.EnglishName),
|
||||
Description: stringOrZero(v.Description), Cover: stringOrZero(v.Cover),
|
||||
}
|
||||
if v.Detail != nil {
|
||||
out.Detail = make([]officialwebsitemod.BusinessDetail, 0, len(*v.Detail))
|
||||
for _, d := range *v.Detail {
|
||||
out.Detail = append(out.Detail, d.toMod())
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyBusinessDetail) toMod() officialwebsitemod.BusinessDetail {
|
||||
return officialwebsitemod.BusinessDetail{
|
||||
Cover: stringOrZero(v.Cover), Description: stringOrZero(v.Description),
|
||||
}
|
||||
}
|
||||
|
||||
func (v ModifyContactInfo) toMod() officialwebsitemod.ContactInfo {
|
||||
return officialwebsitemod.ContactInfo{Type: stringOrZero(v.Type), Value: stringOrZero(v.Value)}
|
||||
}
|
||||
|
||||
func (v ModifyCompanyInfo) toMod() officialwebsitemod.CompanyInfo {
|
||||
out := officialwebsitemod.CompanyInfo{
|
||||
Name: stringOrZero(v.Name), Address: stringOrZero(v.Address), Description: stringOrZero(v.Description),
|
||||
}
|
||||
if v.Contact != nil {
|
||||
out.Contact = make([]officialwebsitemod.ContactInfo, 0, len(*v.Contact))
|
||||
for _, c := range *v.Contact {
|
||||
out.Contact = append(out.Contact, c.toMod())
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v *ModifyAboutUs) toMod() officialwebsitemod.AboutUs {
|
||||
if v == nil {
|
||||
return officialwebsitemod.AboutUs{}
|
||||
}
|
||||
out := officialwebsitemod.AboutUs{
|
||||
Description: stringOrZero(v.Description), Values: stringOrZero(v.Values), ValuesImg: stringOrZero(v.ValuesImg),
|
||||
}
|
||||
if v.Companies != nil {
|
||||
out.Companies = make([]officialwebsitemod.CompanyInfo, 0, len(*v.Companies))
|
||||
for _, c := range *v.Companies {
|
||||
out.Companies = append(out.Companies, c.toMod())
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyFAQ) toMod() officialwebsitemod.FAQ {
|
||||
return officialwebsitemod.FAQ{Question: stringOrZero(v.Question), Answer: stringOrZero(v.Answer)}
|
||||
}
|
||||
|
||||
func (v ModifyCMSData) toMod() officialwebsitemod.CMSData {
|
||||
return officialwebsitemod.CMSData{Description: stringOrZero(v.Description), Value: stringOrZero(v.Value)}
|
||||
}
|
||||
|
||||
// toMod 将请求结构体转换为完整的 BasicData model
|
||||
func (req *ModifyBasicDataReq) toMod() (officialwebsitemod.BasicData, error) {
|
||||
if req == nil {
|
||||
return officialwebsitemod.BasicData{}, stderr.CodeEmptyData
|
||||
}
|
||||
data := officialwebsitemod.BasicData{
|
||||
Title: stringOrZero(req.Title),
|
||||
Description: stringOrZero(req.Description),
|
||||
BannersDescription: stringOrZero(req.BannersDescription),
|
||||
BannersDuration: intOrZero(req.BannersDuration),
|
||||
HomePageCMSDescription: stringOrZero(req.HomePageCMSDescription),
|
||||
}
|
||||
if req.AboutUs != nil {
|
||||
data.AboutUs = req.AboutUs.toMod()
|
||||
}
|
||||
if req.Banner != nil {
|
||||
data.Banner = make([]officialwebsitemod.Banner, 0, len(*req.Banner))
|
||||
for _, b := range *req.Banner {
|
||||
data.Banner = append(data.Banner, b.toMod())
|
||||
}
|
||||
}
|
||||
if req.HeroBanner != nil {
|
||||
data.HeroBanner = make([]officialwebsitemod.HeroBanner, 0, len(*req.HeroBanner))
|
||||
for _, h := range *req.HeroBanner {
|
||||
data.HeroBanner = append(data.HeroBanner, h.toMod())
|
||||
}
|
||||
}
|
||||
if req.Masterpiece != nil {
|
||||
data.Masterpiece = make([]officialwebsitemod.Masterpiece, 0, len(*req.Masterpiece))
|
||||
for _, m := range *req.Masterpiece {
|
||||
data.Masterpiece = append(data.Masterpiece, m.toMod())
|
||||
}
|
||||
}
|
||||
if req.Business != nil {
|
||||
data.Business = make([]officialwebsitemod.Business, 0, len(*req.Business))
|
||||
for _, b := range *req.Business {
|
||||
data.Business = append(data.Business, b.toMod())
|
||||
}
|
||||
}
|
||||
if req.FAQ != nil {
|
||||
data.FAQ = make([]officialwebsitemod.FAQ, 0, len(*req.FAQ))
|
||||
for _, f := range *req.FAQ {
|
||||
data.FAQ = append(data.FAQ, f.toMod())
|
||||
}
|
||||
}
|
||||
if req.HomePageCMS != nil {
|
||||
data.HomePageCMS = make([]officialwebsitemod.CMSData, 0, len(*req.HomePageCMS))
|
||||
for _, h := range *req.HomePageCMS {
|
||||
data.HomePageCMS = append(data.HomePageCMS, h.toMod())
|
||||
}
|
||||
}
|
||||
if req.RecruitCMS != nil {
|
||||
data.RecruitCMS = make([]officialwebsitemod.CMSData, 0, len(*req.RecruitCMS))
|
||||
for _, r := range *req.RecruitCMS {
|
||||
data.RecruitCMS = append(data.RecruitCMS, r.toMod())
|
||||
}
|
||||
}
|
||||
if req.Tags != nil {
|
||||
data.Tags = *req.Tags
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — Modify* → officialwebsitemod.M (Mongo update doc)
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (v ModifyBanner) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.Name != nil {
|
||||
out["name"] = *v.Name
|
||||
}
|
||||
if v.Description != nil {
|
||||
out["description"] = *v.Description
|
||||
}
|
||||
if v.Image != nil {
|
||||
out["image"] = *v.Image
|
||||
}
|
||||
if v.Thumbnail != nil {
|
||||
out["thumbnail"] = *v.Thumbnail
|
||||
}
|
||||
if v.PhoneImage != nil {
|
||||
out["phoneImage"] = *v.PhoneImage
|
||||
}
|
||||
if v.URL != nil {
|
||||
out["url"] = *v.URL
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyHeroBanner) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.ID != nil {
|
||||
out["_id"] = *v.ID
|
||||
}
|
||||
if v.HeroID != nil {
|
||||
out["heroId"] = *v.HeroID
|
||||
}
|
||||
if v.Name != nil {
|
||||
out["name"] = *v.Name
|
||||
}
|
||||
if v.Description != nil {
|
||||
out["description"] = *v.Description
|
||||
}
|
||||
if v.Image != nil {
|
||||
out["image"] = *v.Image
|
||||
}
|
||||
if v.URL != nil {
|
||||
out["url"] = *v.URL
|
||||
}
|
||||
if v.Duration != nil {
|
||||
out["duration"] = *v.Duration
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyMasterpiece) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.ID != nil {
|
||||
out["_id"] = *v.ID
|
||||
}
|
||||
if v.Name != nil {
|
||||
out["name"] = *v.Name
|
||||
}
|
||||
if v.Description != nil {
|
||||
out["description"] = *v.Description
|
||||
}
|
||||
if v.Cover != nil {
|
||||
out["cover"] = *v.Cover
|
||||
}
|
||||
if v.Type != nil {
|
||||
out["type"] = *v.Type
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyBusiness) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.Name != nil {
|
||||
out["name"] = *v.Name
|
||||
}
|
||||
if v.EnglishName != nil {
|
||||
out["englishName"] = *v.EnglishName
|
||||
}
|
||||
if v.Description != nil {
|
||||
out["description"] = *v.Description
|
||||
}
|
||||
if v.Cover != nil {
|
||||
out["cover"] = *v.Cover
|
||||
}
|
||||
if v.Detail != nil {
|
||||
detail := make([]officialwebsitemod.M, 0, len(*v.Detail))
|
||||
for _, d := range *v.Detail {
|
||||
detail = append(detail, d.toM())
|
||||
}
|
||||
out["detail"] = detail
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyBusinessDetail) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.Cover != nil {
|
||||
out["cover"] = *v.Cover
|
||||
}
|
||||
if v.Description != nil {
|
||||
out["description"] = *v.Description
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyContactInfo) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.Type != nil {
|
||||
out["type"] = *v.Type
|
||||
}
|
||||
if v.Value != nil {
|
||||
out["value"] = *v.Value
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyCompanyInfo) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.Name != nil {
|
||||
out["name"] = *v.Name
|
||||
}
|
||||
if v.Address != nil {
|
||||
out["address"] = *v.Address
|
||||
}
|
||||
if v.Description != nil {
|
||||
out["description"] = *v.Description
|
||||
}
|
||||
if v.Contact != nil {
|
||||
contacts := make([]officialwebsitemod.M, 0, len(*v.Contact))
|
||||
for _, c := range *v.Contact {
|
||||
contacts = append(contacts, c.toM())
|
||||
}
|
||||
out["contact"] = contacts
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v *ModifyAboutUs) toM() officialwebsitemod.M {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
out := officialwebsitemod.M{}
|
||||
if v.Description != nil {
|
||||
out["description"] = *v.Description
|
||||
}
|
||||
if v.Values != nil {
|
||||
out["values"] = *v.Values
|
||||
}
|
||||
if v.ValuesImg != nil {
|
||||
out["valuesImg"] = *v.ValuesImg
|
||||
}
|
||||
if v.Companies != nil {
|
||||
companies := make([]officialwebsitemod.M, 0, len(*v.Companies))
|
||||
for _, c := range *v.Companies {
|
||||
companies = append(companies, c.toM())
|
||||
}
|
||||
out["companies"] = companies
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyFAQ) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.Question != nil {
|
||||
out["question"] = *v.Question
|
||||
}
|
||||
if v.Answer != nil {
|
||||
out["answer"] = *v.Answer
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (v ModifyCMSData) toM() officialwebsitemod.M {
|
||||
out := officialwebsitemod.M{}
|
||||
if v.Description != nil {
|
||||
out["description"] = *v.Description
|
||||
}
|
||||
if v.Value != nil {
|
||||
out["value"] = *v.Value
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// toM 将请求中的非 nil 字段构造为 Mongo $set 更新文档
|
||||
func (req *ModifyBasicDataReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.Title != nil {
|
||||
set["title"] = *req.Title
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.BannersDescription != nil {
|
||||
set["bannersDescription"] = *req.BannersDescription
|
||||
}
|
||||
if req.BannersDuration != nil {
|
||||
set["bannersDuration"] = *req.BannersDuration
|
||||
}
|
||||
if req.HomePageCMSDescription != nil {
|
||||
set["homePageCMSDescription"] = *req.HomePageCMSDescription
|
||||
}
|
||||
if req.Banner != nil {
|
||||
banners := make([]officialwebsitemod.M, 0, len(*req.Banner))
|
||||
for _, b := range *req.Banner {
|
||||
banners = append(banners, b.toM())
|
||||
}
|
||||
set["banner"] = banners
|
||||
}
|
||||
if req.HeroBanner != nil {
|
||||
heroBanners := make([]officialwebsitemod.M, 0, len(*req.HeroBanner))
|
||||
for _, h := range *req.HeroBanner {
|
||||
heroBanners = append(heroBanners, h.toM())
|
||||
}
|
||||
set["heroBanner"] = heroBanners
|
||||
}
|
||||
if req.Masterpiece != nil {
|
||||
masterpiece := make([]officialwebsitemod.M, 0, len(*req.Masterpiece))
|
||||
for _, m := range *req.Masterpiece {
|
||||
masterpiece = append(masterpiece, m.toM())
|
||||
}
|
||||
set["masterpiece"] = masterpiece
|
||||
}
|
||||
if req.Business != nil {
|
||||
businesses := make([]officialwebsitemod.M, 0, len(*req.Business))
|
||||
for _, b := range *req.Business {
|
||||
businesses = append(businesses, b.toM())
|
||||
}
|
||||
set["business"] = businesses
|
||||
}
|
||||
if req.AboutUs != nil {
|
||||
aboutUsM := req.AboutUs.toM()
|
||||
if len(aboutUsM) > 0 {
|
||||
set["aboutUs"] = aboutUsM
|
||||
}
|
||||
}
|
||||
if req.FAQ != nil {
|
||||
faqs := make([]officialwebsitemod.M, 0, len(*req.FAQ))
|
||||
for _, f := range *req.FAQ {
|
||||
faqs = append(faqs, f.toM())
|
||||
}
|
||||
set["faq"] = faqs
|
||||
}
|
||||
if req.HomePageCMS != nil {
|
||||
cms := make([]officialwebsitemod.M, 0, len(*req.HomePageCMS))
|
||||
for _, h := range *req.HomePageCMS {
|
||||
cms = append(cms, h.toM())
|
||||
}
|
||||
set["homePageCMS"] = cms
|
||||
}
|
||||
if req.RecruitCMS != nil {
|
||||
rcms := make([]officialwebsitemod.M, 0, len(*req.RecruitCMS))
|
||||
for _, r := range *req.RecruitCMS {
|
||||
rcms = append(rcms, r.toM())
|
||||
}
|
||||
set["recruitCMS"] = rcms
|
||||
}
|
||||
if req.Tags != nil {
|
||||
set["tags"] = *req.Tags
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListBusiness(req *BusinessListReq) (int64, []officialwebsitemod.BusinessData, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.BusinessData{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func CreateBusiness(req *ModifyBusinessReq) (officialwebsitemod.BusinessData, error) {
|
||||
data := req.toMod()
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.BusinessData{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdateBusiness(req *ModifyBusinessReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.BusinessData{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteBusiness(req *DeleteBusinessReq) (data DeleteBusinessResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.BusinessData{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyBusinessReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Title *string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
Type *string `json:"type"`
|
||||
ServiceOverview *string `json:"serviceOverview"`
|
||||
CollaborationProcess *string `json:"collaborationProcess"`
|
||||
CaseStudies *string `json:"caseStudies"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteBusinessReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeleteBusinessResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyBusinessReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyBusinessReq) toMod() officialwebsitemod.BusinessData {
|
||||
if req == nil {
|
||||
return officialwebsitemod.BusinessData{}
|
||||
}
|
||||
return officialwebsitemod.BusinessData{
|
||||
Title: stringOrZero(req.Title),
|
||||
Description: stringOrZero(req.Description),
|
||||
Type: stringOrZero(req.Type),
|
||||
ServiceOverview: stringOrZero(req.ServiceOverview),
|
||||
CollaborationProcess: stringOrZero(req.CollaborationProcess),
|
||||
CaseStudies: stringOrZero(req.CaseStudies),
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyBusinessReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyBusinessReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.Title != nil {
|
||||
set["title"] = *req.Title
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.Type != nil {
|
||||
set["type"] = *req.Type
|
||||
}
|
||||
if req.ServiceOverview != nil {
|
||||
set["serviceOverview"] = *req.ServiceOverview
|
||||
}
|
||||
if req.CollaborationProcess != nil {
|
||||
set["collaborationProcess"] = *req.CollaborationProcess
|
||||
}
|
||||
if req.CaseStudies != nil {
|
||||
set["caseStudies"] = *req.CaseStudies
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type BusinessListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
Title *string `form:"title"`
|
||||
Description *string `form:"description"`
|
||||
Type *string `form:"type"`
|
||||
ServiceOverview *string `form:"serviceOverview"`
|
||||
CollaborationProcess *string `form:"collaborationProcess"`
|
||||
CaseStudies *string `form:"caseStudies"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *BusinessListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Title != nil {
|
||||
filter["title"] = *r.Title
|
||||
}
|
||||
if r.Description != nil {
|
||||
filter["description"] = *r.Description
|
||||
}
|
||||
if r.Type != nil {
|
||||
filter["type"] = *r.Type
|
||||
}
|
||||
if r.ServiceOverview != nil {
|
||||
filter["serviceOverview"] = *r.ServiceOverview
|
||||
}
|
||||
if r.CollaborationProcess != nil {
|
||||
filter["collaborationProcess"] = *r.CollaborationProcess
|
||||
}
|
||||
if r.CaseStudies != nil {
|
||||
filter["caseStudies"] = *r.CaseStudies
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List Helper Types and Functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
// CountResp 通用操作返回
|
||||
type CountResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// PageReq 分页请求
|
||||
type PageReq struct {
|
||||
Page int64 `form:"page"`
|
||||
PageSize int64 `form:"pageSize"`
|
||||
}
|
||||
|
||||
func (r *PageReq) FindOptions() *options.FindOptions {
|
||||
page := r.Page
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
pageSize := r.PageSize
|
||||
if pageSize <= 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
skip := (page - 1) * pageSize
|
||||
return options.Find().SetSkip(skip).SetLimit(pageSize).SetSort(officialwebsitemod.M{"createdAt": -1})
|
||||
}
|
||||
|
||||
func parseObjectIDFilter(filter officialwebsitemod.M, key string, raw *string) error {
|
||||
if raw == nil || *raw == "" {
|
||||
return nil
|
||||
}
|
||||
id, err := primitive.ObjectIDFromHex(*raw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid %s: %w", key, err)
|
||||
}
|
||||
filter[key] = id
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseJSONFilter(filter officialwebsitemod.M, key string, raw *string, out interface{}) error {
|
||||
if raw == nil || *raw == "" {
|
||||
return nil
|
||||
}
|
||||
if err := json.Unmarshal([]byte(*raw), out); err != nil {
|
||||
return fmt.Errorf("invalid %s json: %w", key, err)
|
||||
}
|
||||
v := reflect.ValueOf(out)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
filter[key] = v.Elem().Interface()
|
||||
return nil
|
||||
}
|
||||
filter[key] = out
|
||||
return nil
|
||||
}
|
||||
|
||||
// ─────���───────────────────────────────────
|
||||
// Update Helper Functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func modelToMap(doc interface{}) (officialwebsitemod.M, error) {
|
||||
raw, err := bson.Marshal(doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := officialwebsitemod.M{}
|
||||
if err := bson.Unmarshal(raw, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
delete(data, "_id")
|
||||
delete(data, "createdAt")
|
||||
delete(data, "updatedAt")
|
||||
delete(data, "deletedAt")
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func modelChanged(oldDoc interface{}, newDoc interface{}) (bool, error) {
|
||||
oldMap, err := modelToMap(oldDoc)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
newMap, err := modelToMap(newDoc)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !reflect.DeepEqual(oldMap, newMap), nil
|
||||
}
|
||||
|
||||
func buildModelUpdateDoc(doc interface{}) (officialwebsitemod.M, error) {
|
||||
data, err := modelToMap(doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": data}, nil
|
||||
}
|
||||
|
||||
func buildPointerUpdateDoc(oldDoc interface{}, updateDoc interface{}) (officialwebsitemod.M, error) {
|
||||
oldVal, err := structValueOf(oldDoc, "old doc")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newVal, err := structValueOf(updateDoc, "update doc")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
collectPointerChanges(set, oldVal, newVal)
|
||||
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
func structValueOf(doc interface{}, label string) (reflect.Value, error) {
|
||||
val := reflect.ValueOf(doc)
|
||||
if val.Kind() == reflect.Ptr {
|
||||
if val.IsNil() {
|
||||
return reflect.Value{}, errors.New(label + " is nil")
|
||||
}
|
||||
val = val.Elem()
|
||||
}
|
||||
if val.Kind() != reflect.Struct {
|
||||
return reflect.Value{}, errors.New(label + " must be struct")
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func collectPointerChanges(set officialwebsitemod.M, oldVal reflect.Value, newVal reflect.Value) {
|
||||
newType := newVal.Type()
|
||||
for i := 0; i < newVal.NumField(); i++ {
|
||||
addPointerFieldChange(set, oldVal, newVal.Field(i), newType.Field(i))
|
||||
}
|
||||
}
|
||||
|
||||
func addPointerFieldChange(set officialwebsitemod.M, oldVal reflect.Value, newField reflect.Value, fieldInfo reflect.StructField) {
|
||||
if fieldInfo.Name == "ID" {
|
||||
return
|
||||
}
|
||||
if !newField.IsValid() || newField.Kind() != reflect.Ptr || newField.IsNil() {
|
||||
return
|
||||
}
|
||||
|
||||
oldField := findStructFieldByName(oldVal, fieldInfo.Name)
|
||||
if !oldField.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
newValue := derefValue(newField)
|
||||
oldValue := derefValue(oldField)
|
||||
if !newValue.IsValid() || !oldValue.IsValid() {
|
||||
return
|
||||
}
|
||||
if reflect.DeepEqual(oldValue.Interface(), newValue.Interface()) {
|
||||
return
|
||||
}
|
||||
|
||||
key := bsonFieldName(fieldInfo)
|
||||
if key == "" {
|
||||
return
|
||||
}
|
||||
set[key] = newValue.Interface()
|
||||
}
|
||||
|
||||
func findStructFieldByName(val reflect.Value, name string) reflect.Value {
|
||||
if !val.IsValid() {
|
||||
return reflect.Value{}
|
||||
}
|
||||
if val.Kind() == reflect.Ptr {
|
||||
if val.IsNil() {
|
||||
return reflect.Value{}
|
||||
}
|
||||
val = val.Elem()
|
||||
}
|
||||
if val.Kind() != reflect.Struct {
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
if field := val.FieldByName(name); field.IsValid() {
|
||||
return field
|
||||
}
|
||||
|
||||
valType := val.Type()
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
fieldType := valType.Field(i)
|
||||
if !fieldType.Anonymous {
|
||||
continue
|
||||
}
|
||||
field := findStructFieldByName(val.Field(i), name)
|
||||
if field.IsValid() {
|
||||
return field
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
func derefValue(v reflect.Value) reflect.Value {
|
||||
for v.IsValid() && v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
return reflect.Value{}
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func bsonFieldName(field reflect.StructField) string {
|
||||
if tag := field.Tag.Get("bson"); tag != "" {
|
||||
name := strings.Split(tag, ",")[0]
|
||||
if name != "" && name != "-" {
|
||||
return name
|
||||
}
|
||||
}
|
||||
if tag := field.Tag.Get("json"); tag != "" {
|
||||
name := strings.Split(tag, ",")[0]
|
||||
if name != "" && name != "-" {
|
||||
return name
|
||||
}
|
||||
}
|
||||
return field.Name
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Pointer helpers
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func stringOrZero(v *string) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
func intOrZero(v *int) int {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
func objectIDOrZero(v *primitive.ObjectID) primitive.ObjectID {
|
||||
if v == nil {
|
||||
return primitive.NilObjectID
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
func int64OrZero(v *int64) int64 {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
func boolOrZero(v *bool) bool {
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
func isNilObjectID(id primitive.ObjectID) bool {
|
||||
return id == primitive.NilObjectID
|
||||
}
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListHero(req *HeroListReq) (int64, []officialwebsitemod.Hero, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.Hero{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func CreateHero(req *ModifyHeroReq) (officialwebsitemod.Hero, error) {
|
||||
data := req.toMod()
|
||||
// SEO slug:手填优先(校验唯一),为空则由名称生成雏形并去重
|
||||
var err error
|
||||
if data.SeoSlug, err = resolveHeroSeoSlug(data.SeoSlug, data.Name, primitive.NilObjectID); err != nil {
|
||||
return officialwebsitemod.Hero{}, err
|
||||
}
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.Hero{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// resolveHeroSeoSlug 处理 seoSlug:手填则校验格式并查重(冲突报错);为空则由名称生成雏形并追加后缀去重。
|
||||
func resolveHeroSeoSlug(provided, name string, excludeID primitive.ObjectID) (string, error) {
|
||||
return ResolveSeoSlug(provided, name, func(slug string) (bool, error) {
|
||||
filter := officialwebsitemod.M{"seoSlug": slug}
|
||||
if !excludeID.IsZero() {
|
||||
filter["_id"] = officialwebsitemod.M{"$ne": excludeID}
|
||||
}
|
||||
n, err := (&officialwebsitemod.Hero{}).Count(filter)
|
||||
return n > 0, err
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateHero(req *ModifyHeroReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Hero{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
// 若提交了 seoSlug,先校验/去重(排除自身),回写后由 toM 落库
|
||||
if req.SeoSlug != nil {
|
||||
var slug string
|
||||
if slug, err = resolveHeroSeoSlug(*req.SeoSlug, mod.Name, id); err != nil {
|
||||
return
|
||||
}
|
||||
*req.SeoSlug = slug
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteHero(req *DeleteHeroReq) (data DeleteHeroResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Hero{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyHeroReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Name *string `json:"name"`
|
||||
SeoSlug *string `json:"seoSlug"`
|
||||
Avatar *string `json:"avatar"`
|
||||
Description *string `json:"description"`
|
||||
FansCount *int64 `json:"fansCount"`
|
||||
Height *int64 `json:"height"`
|
||||
Bust *int64 `json:"bust"`
|
||||
Waist *int64 `json:"waist"`
|
||||
Hip *int64 `json:"hip"`
|
||||
Cover *string `json:"cover"`
|
||||
Partners *[]primitive.ObjectID `json:"partners"`
|
||||
Sort *int64 `json:"sort"`
|
||||
IsActive *bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteHeroReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeleteHeroResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyHeroReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyHeroReq) toMod() officialwebsitemod.Hero {
|
||||
if req == nil {
|
||||
return officialwebsitemod.Hero{}
|
||||
}
|
||||
data := officialwebsitemod.Hero{
|
||||
Name: stringOrZero(req.Name),
|
||||
Avatar: stringOrZero(req.Avatar),
|
||||
Description: stringOrZero(req.Description),
|
||||
FansCount: int64OrZero(req.FansCount),
|
||||
Height: int64OrZero(req.Height),
|
||||
Bust: int64OrZero(req.Bust),
|
||||
Waist: int64OrZero(req.Waist),
|
||||
Hip: int64OrZero(req.Hip),
|
||||
Cover: stringOrZero(req.Cover),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: int64OrZero(req.Sort),
|
||||
IsActive: boolOrZero(req.IsActive),
|
||||
},
|
||||
}
|
||||
if req.Partners != nil {
|
||||
data.Partners = *req.Partners
|
||||
}
|
||||
if req.SeoSlug != nil {
|
||||
data.SeoSlug = *req.SeoSlug
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyHeroReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyHeroReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.Name != nil {
|
||||
set["name"] = *req.Name
|
||||
}
|
||||
if req.SeoSlug != nil && *req.SeoSlug != "" {
|
||||
set["seoSlug"] = *req.SeoSlug
|
||||
}
|
||||
if req.Avatar != nil {
|
||||
set["avatar"] = *req.Avatar
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.FansCount != nil {
|
||||
set["fansCount"] = *req.FansCount
|
||||
}
|
||||
if req.Height != nil {
|
||||
set["height"] = *req.Height
|
||||
}
|
||||
if req.Bust != nil {
|
||||
set["bust"] = *req.Bust
|
||||
}
|
||||
if req.Waist != nil {
|
||||
set["waist"] = *req.Waist
|
||||
}
|
||||
if req.Hip != nil {
|
||||
set["hip"] = *req.Hip
|
||||
}
|
||||
if req.Cover != nil {
|
||||
set["cover"] = *req.Cover
|
||||
}
|
||||
if req.Partners != nil {
|
||||
set["partners"] = *req.Partners
|
||||
}
|
||||
if req.Sort != nil {
|
||||
set["sort"] = *req.Sort
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
set["isActive"] = *req.IsActive
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type HeroListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
Name *string `form:"name"`
|
||||
Avatar *string `form:"avatar"`
|
||||
Height *int64 `form:"height"`
|
||||
Bust *int64 `form:"bust"`
|
||||
Waist *int64 `form:"waist"`
|
||||
Hip *int64 `form:"hip"`
|
||||
Description *string `form:"description"`
|
||||
FansCount *int64 `form:"fansCount"`
|
||||
Cover *string `form:"cover"`
|
||||
Partners *string `form:"partners"`
|
||||
Sort *int64 `form:"sort"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *HeroListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Name != nil {
|
||||
filter["name"] = *r.Name
|
||||
}
|
||||
if r.Avatar != nil {
|
||||
filter["avatar"] = *r.Avatar
|
||||
}
|
||||
if r.Height != nil {
|
||||
filter["height"] = *r.Height
|
||||
}
|
||||
if r.Bust != nil {
|
||||
filter["bust"] = *r.Bust
|
||||
}
|
||||
if r.Waist != nil {
|
||||
filter["waist"] = *r.Waist
|
||||
}
|
||||
if r.Hip != nil {
|
||||
filter["hip"] = *r.Hip
|
||||
}
|
||||
if r.Description != nil {
|
||||
filter["description"] = *r.Description
|
||||
}
|
||||
if r.FansCount != nil {
|
||||
filter["fansCount"] = *r.FansCount
|
||||
}
|
||||
if r.Cover != nil {
|
||||
filter["cover"] = *r.Cover
|
||||
}
|
||||
if err := parseJSONFilter(filter, "partners", r.Partners, &[]primitive.ObjectID{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Sort != nil {
|
||||
filter["sort"] = *r.Sort
|
||||
}
|
||||
if r.IsActive != nil {
|
||||
filter["isActive"] = *r.IsActive
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListJobList(req *JobListReq) (int64, []officialwebsitemod.Job, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.Job{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func CreateJobList(req *ModifyJobReq) (officialwebsitemod.Job, error) {
|
||||
data := req.toMod()
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.Job{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdateJobList(req *ModifyJobReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Job{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteJobList(req *DeleteJobReq) (data DeleteJobResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Job{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyJobReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Title *string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
Requirements *string `json:"requirements"`
|
||||
Benefits *string `json:"benefits"`
|
||||
JDUrl *string `json:"jdUrl"`
|
||||
Sort *int64 `json:"sort"`
|
||||
IsActive *bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteJobReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeleteJobResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyJobReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyJobReq) toMod() officialwebsitemod.Job {
|
||||
if req == nil {
|
||||
return officialwebsitemod.Job{}
|
||||
}
|
||||
return officialwebsitemod.Job{
|
||||
Title: stringOrZero(req.Title),
|
||||
Description: stringOrZero(req.Description),
|
||||
Requirements: stringOrZero(req.Requirements),
|
||||
Benefits: stringOrZero(req.Benefits),
|
||||
JDUrl: stringOrZero(req.JDUrl),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: int64OrZero(req.Sort),
|
||||
IsActive: boolOrZero(req.IsActive),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyJobReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyJobReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.Title != nil {
|
||||
set["title"] = *req.Title
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.Requirements != nil {
|
||||
set["requirements"] = *req.Requirements
|
||||
}
|
||||
if req.Benefits != nil {
|
||||
set["benefits"] = *req.Benefits
|
||||
}
|
||||
if req.JDUrl != nil {
|
||||
set["jdUrl"] = *req.JDUrl
|
||||
}
|
||||
if req.Sort != nil {
|
||||
set["sort"] = *req.Sort
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
set["isActive"] = *req.IsActive
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type JobListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
Title *string `form:"title"`
|
||||
Description *string `form:"description"`
|
||||
Requirements *string `form:"requirements"`
|
||||
Benefits *string `form:"benefits"`
|
||||
JDUrl *string `form:"jdUrl"`
|
||||
Sort *int64 `form:"sort"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *JobListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Title != nil {
|
||||
filter["title"] = *r.Title
|
||||
}
|
||||
if r.Description != nil {
|
||||
filter["description"] = *r.Description
|
||||
}
|
||||
if r.Requirements != nil {
|
||||
filter["requirements"] = *r.Requirements
|
||||
}
|
||||
if r.Benefits != nil {
|
||||
filter["benefits"] = *r.Benefits
|
||||
}
|
||||
if r.JDUrl != nil {
|
||||
filter["jdUrl"] = *r.JDUrl
|
||||
}
|
||||
if r.Sort != nil {
|
||||
filter["sort"] = *r.Sort
|
||||
}
|
||||
if r.IsActive != nil {
|
||||
filter["isActive"] = *r.IsActive
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListNews(req *NewsListReq) (int64, []officialwebsitemod.News, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.News{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
// resolveNewsSeoSlug 处理 seoSlug:手填则校验格式并查重(冲突报错);为空则由标题生成雏形并追加后缀去重。
|
||||
func resolveNewsSeoSlug(provided, title string, excludeID primitive.ObjectID) (string, error) {
|
||||
return ResolveSeoSlug(provided, title, func(slug string) (bool, error) {
|
||||
filter := officialwebsitemod.M{"seoSlug": slug}
|
||||
if !excludeID.IsZero() {
|
||||
filter["_id"] = officialwebsitemod.M{"$ne": excludeID}
|
||||
}
|
||||
n, err := (&officialwebsitemod.News{}).Count(filter)
|
||||
return n > 0, err
|
||||
})
|
||||
}
|
||||
|
||||
func CreateNews(req *ModifyNewsReq) (officialwebsitemod.News, error) {
|
||||
data := req.toMod()
|
||||
// SEO slug:手填优先(校验唯一),为空则由标题生成雏形并去重
|
||||
slug, err := resolveNewsSeoSlug(data.SeoSlug, data.Title, primitive.NilObjectID)
|
||||
if err != nil {
|
||||
return officialwebsitemod.News{}, err
|
||||
}
|
||||
data.SeoSlug = slug
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.News{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdateNews(req *ModifyNewsReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.News{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
// 若提交了 seoSlug,先校验/去重(排除自身),回写后由 toM 落库
|
||||
if req.SeoSlug != nil {
|
||||
var slug string
|
||||
if slug, err = resolveNewsSeoSlug(*req.SeoSlug, mod.Title, id); err != nil {
|
||||
return
|
||||
}
|
||||
*req.SeoSlug = slug
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteNews(req *DeleteNewsReq) (data DeleteNewsResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.News{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyNewsReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Title *string `json:"title"`
|
||||
SeoSlug *string `json:"seoSlug"`
|
||||
Description *string `json:"description"`
|
||||
Cover *string `json:"cover"`
|
||||
Url *string `json:"url"`
|
||||
Tags *[]officialwebsitemod.Tag `json:"tags"`
|
||||
Detail *string `json:"detail"`
|
||||
Sort *int64 `json:"sort"`
|
||||
IsActive *bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteNewsReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeleteNewsResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyNewsReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyNewsReq) toMod() officialwebsitemod.News {
|
||||
if req == nil {
|
||||
return officialwebsitemod.News{}
|
||||
}
|
||||
data := officialwebsitemod.News{
|
||||
Title: stringOrZero(req.Title),
|
||||
Description: stringOrZero(req.Description),
|
||||
Cover: stringOrZero(req.Cover),
|
||||
Url: stringOrZero(req.Url),
|
||||
Detail: stringOrZero(req.Detail),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: int64OrZero(req.Sort),
|
||||
IsActive: boolOrZero(req.IsActive),
|
||||
},
|
||||
}
|
||||
if req.Tags != nil {
|
||||
data.Tags = *req.Tags
|
||||
}
|
||||
if req.SeoSlug != nil {
|
||||
data.SeoSlug = *req.SeoSlug
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyNewsReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyNewsReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.Title != nil {
|
||||
set["title"] = *req.Title
|
||||
}
|
||||
if req.SeoSlug != nil && *req.SeoSlug != "" {
|
||||
set["seoSlug"] = *req.SeoSlug
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.Cover != nil {
|
||||
set["cover"] = *req.Cover
|
||||
}
|
||||
if req.Url != nil {
|
||||
set["url"] = *req.Url
|
||||
}
|
||||
if req.Tags != nil {
|
||||
set["tags"] = *req.Tags
|
||||
}
|
||||
if req.Detail != nil {
|
||||
set["detail"] = *req.Detail
|
||||
}
|
||||
if req.Sort != nil {
|
||||
set["sort"] = *req.Sort
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
set["isActive"] = *req.IsActive
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type NewsListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
Title *string `form:"title"`
|
||||
Description *string `form:"description"`
|
||||
Cover *string `form:"cover"`
|
||||
Url *string `form:"url"`
|
||||
Tags *string `form:"tags"`
|
||||
Sort *int64 `form:"sort"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *NewsListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Title != nil {
|
||||
filter["title"] = *r.Title
|
||||
}
|
||||
if r.Description != nil {
|
||||
filter["description"] = *r.Description
|
||||
}
|
||||
if r.Cover != nil {
|
||||
filter["cover"] = *r.Cover
|
||||
}
|
||||
if r.Url != nil {
|
||||
filter["url"] = *r.Url
|
||||
}
|
||||
if err := parseJSONFilter(filter, "tags", r.Tags, &[]officialwebsitemod.Tag{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Sort != nil {
|
||||
filter["sort"] = *r.Sort
|
||||
}
|
||||
if r.IsActive != nil {
|
||||
filter["isActive"] = *r.IsActive
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListPartner(req *PartnerListReq) (int64, []officialwebsitemod.Partner, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.Partner{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func CreatePartner(req *ModifyPartnerReq) (officialwebsitemod.Partner, error) {
|
||||
data := req.toMod()
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.Partner{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdatePartner(req *ModifyPartnerReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Partner{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeletePartner(req *DeletePartnerReq) (data DeletePartnerResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Partner{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyPartnerReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Name *string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
Logo *string `json:"logo"`
|
||||
Url *string `json:"url"`
|
||||
Sort *int64 `json:"sort"`
|
||||
IsActive *bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeletePartnerReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeletePartnerResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyPartnerReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyPartnerReq) toMod() officialwebsitemod.Partner {
|
||||
if req == nil {
|
||||
return officialwebsitemod.Partner{}
|
||||
}
|
||||
return officialwebsitemod.Partner{
|
||||
Name: stringOrZero(req.Name),
|
||||
Description: stringOrZero(req.Description),
|
||||
Logo: stringOrZero(req.Logo),
|
||||
Url: stringOrZero(req.Url),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: int64OrZero(req.Sort),
|
||||
IsActive: boolOrZero(req.IsActive),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyPartnerReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyPartnerReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.Name != nil {
|
||||
set["name"] = *req.Name
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.Logo != nil {
|
||||
set["logo"] = *req.Logo
|
||||
}
|
||||
if req.Url != nil {
|
||||
set["url"] = *req.Url
|
||||
}
|
||||
if req.Sort != nil {
|
||||
set["sort"] = *req.Sort
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
set["isActive"] = *req.IsActive
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type PartnerListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
Name *string `form:"name"`
|
||||
Description *string `form:"description"`
|
||||
Logo *string `form:"logo"`
|
||||
Url *string `form:"url"`
|
||||
Sort *int64 `form:"sort"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *PartnerListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Name != nil {
|
||||
filter["name"] = *r.Name
|
||||
}
|
||||
if r.Description != nil {
|
||||
filter["description"] = *r.Description
|
||||
}
|
||||
if r.Logo != nil {
|
||||
filter["logo"] = *r.Logo
|
||||
}
|
||||
if r.Url != nil {
|
||||
filter["url"] = *r.Url
|
||||
}
|
||||
if r.Sort != nil {
|
||||
filter["sort"] = *r.Sort
|
||||
}
|
||||
if r.IsActive != nil {
|
||||
filter["isActive"] = *r.IsActive
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListPhotograph(req *ListPhotographReq) (int64, []officialwebsitemod.Photograph, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.Photograph{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
// resolvePhotographSeoSlug 处理 seoSlug:手填则校验格式并查重(冲突报错);为空则由标题生成雏形并追加后缀去重。
|
||||
func resolvePhotographSeoSlug(provided, name string, excludeID primitive.ObjectID) (string, error) {
|
||||
return ResolveSeoSlug(provided, name, func(slug string) (bool, error) {
|
||||
filter := officialwebsitemod.M{"seoSlug": slug}
|
||||
if !excludeID.IsZero() {
|
||||
filter["_id"] = officialwebsitemod.M{"$ne": excludeID}
|
||||
}
|
||||
n, err := (&officialwebsitemod.Photograph{}).Count(filter)
|
||||
return n > 0, err
|
||||
})
|
||||
}
|
||||
|
||||
func CreatePhotograph(req *ModifyPhotographReq) (officialwebsitemod.Photograph, error) {
|
||||
data, err := req.toMod()
|
||||
if err != nil {
|
||||
return officialwebsitemod.Photograph{}, err
|
||||
}
|
||||
// SEO slug:手填优先(校验唯一),为空则由标题生成雏形并去重
|
||||
if data.SeoSlug, err = resolvePhotographSeoSlug(data.SeoSlug, data.Name, primitive.NilObjectID); err != nil {
|
||||
return officialwebsitemod.Photograph{}, err
|
||||
}
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.Photograph{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdatePhotograph(req *ModifyPhotographReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Photograph{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(mod.ID) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
// 若提交了 seoSlug,先校验/去重(排除自身),回写后由 toM 落库
|
||||
if req.SeoSlug != nil {
|
||||
var slug string
|
||||
if slug, err = resolvePhotographSeoSlug(*req.SeoSlug, mod.Name, id); err != nil {
|
||||
return
|
||||
}
|
||||
*req.SeoSlug = slug
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeletePhotograph(req *DeletePhotographReq) (data DeletePhotographResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Photograph{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
func BatchUpdatePhotographOwner(req *BatchUpdatePhotographOwnerReq) (data BatchUpdatePhotographOwnerResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
|
||||
// Check owner is exist
|
||||
var ownerID primitive.ObjectID
|
||||
ownerID, err = primitive.ObjectIDFromHex(req.OwnerID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var heroMod = &officialwebsitemod.Hero{}
|
||||
err = heroMod.FindOne(officialwebsitemod.M{"_id": ownerID})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(heroMod.ID) {
|
||||
err = stderr.OfficialWebsiteHeroExist
|
||||
return
|
||||
}
|
||||
|
||||
var photographIDs []primitive.ObjectID
|
||||
for i := range req.PhotographIDs {
|
||||
photographID, parseErr := primitive.ObjectIDFromHex(req.PhotographIDs[i])
|
||||
err = parseErr
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
photographIDs = append(photographIDs, photographID)
|
||||
}
|
||||
var photographMod = &officialwebsitemod.Photograph{}
|
||||
filter := bson.M{"_id": bson.M{"$in": photographIDs}}
|
||||
update := bson.M{"$set": bson.M{"heroId": ownerID}}
|
||||
data.Count, err = photographMod.Update(filter, update)
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Batch (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type BatchUpdatePhotographOwnerReq struct {
|
||||
PhotographIDs []string `json:"photograph_ids"`
|
||||
OwnerID string `json:"owner_id"`
|
||||
}
|
||||
|
||||
type BatchUpdatePhotographOwnerResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyPhotographReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
HeroID *string `json:"heroID"`
|
||||
Name *string `json:"name"`
|
||||
SeoSlug *string `json:"seoSlug"`
|
||||
Description *string `json:"description"`
|
||||
Cover *string `json:"cover"`
|
||||
Photos *[]string `json:"photos"`
|
||||
Tags *[]officialwebsitemod.Tag `json:"tags"`
|
||||
Sort *int64 `json:"sort"`
|
||||
IsActive *bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeletePhotographReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeletePhotographResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyPhotographReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyPhotographReq) toMod() (data officialwebsitemod.Photograph, err error) {
|
||||
if req == nil {
|
||||
return
|
||||
}
|
||||
data = officialwebsitemod.Photograph{
|
||||
Name: stringOrZero(req.Name),
|
||||
Description: stringOrZero(req.Description),
|
||||
Cover: stringOrZero(req.Cover),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: int64OrZero(req.Sort),
|
||||
IsActive: boolOrZero(req.IsActive),
|
||||
},
|
||||
}
|
||||
if req.HeroID != nil {
|
||||
data.HeroID, err = primitive.ObjectIDFromHex(stringOrZero(req.HeroID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if req.Photos != nil {
|
||||
data.Photos = *req.Photos
|
||||
}
|
||||
if req.Tags != nil {
|
||||
data.Tags = *req.Tags
|
||||
}
|
||||
if req.SeoSlug != nil {
|
||||
data.SeoSlug = *req.SeoSlug
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyPhotographReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyPhotographReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.HeroID != nil {
|
||||
if *req.HeroID != "" {
|
||||
heroID, err := primitive.ObjectIDFromHex(*req.HeroID)
|
||||
if err != nil || isNilObjectID(heroID) {
|
||||
return nil, stderr.ErrParamError
|
||||
}
|
||||
set["heroId"] = heroID
|
||||
}
|
||||
}
|
||||
if req.Name != nil {
|
||||
set["name"] = *req.Name
|
||||
}
|
||||
if req.SeoSlug != nil && *req.SeoSlug != "" {
|
||||
set["seoSlug"] = *req.SeoSlug
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.Cover != nil {
|
||||
set["cover"] = *req.Cover
|
||||
}
|
||||
if req.Photos != nil {
|
||||
set["photos"] = *req.Photos
|
||||
}
|
||||
if req.Tags != nil {
|
||||
set["tags"] = *req.Tags
|
||||
}
|
||||
if req.Sort != nil {
|
||||
set["sort"] = *req.Sort
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
set["isActive"] = *req.IsActive
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ListPhotographReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
HeroID *string `form:"heroID"`
|
||||
Name *string `form:"name"`
|
||||
Description *string `form:"description"`
|
||||
Cover *string `form:"cover"`
|
||||
Photos *string `form:"photos"`
|
||||
Sort *int64 `form:"sort"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (l *ListPhotographReq) Query() (filter officialwebsitemod.M, err error) {
|
||||
filter = officialwebsitemod.M{}
|
||||
if err = parseObjectIDFilter(filter, "_id", l.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = parseObjectIDFilter(filter, "heroId", l.HeroID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if l.Name != nil {
|
||||
filter["name"] = *l.Name
|
||||
}
|
||||
if l.Description != nil {
|
||||
filter["description"] = *l.Description
|
||||
}
|
||||
if l.Cover != nil {
|
||||
filter["cover"] = *l.Cover
|
||||
}
|
||||
if err = parseJSONFilter(filter, "photos", l.Photos, &[]string{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if l.Sort != nil {
|
||||
filter["sort"] = *l.Sort
|
||||
}
|
||||
if l.IsActive != nil {
|
||||
filter["isActive"] = *l.IsActive
|
||||
}
|
||||
if l.CreatedAt != nil {
|
||||
filter["createdAt"] = *l.CreatedAt
|
||||
}
|
||||
if l.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *l.UpdatedAt
|
||||
}
|
||||
if l.DeletedAt != nil {
|
||||
filter["deletedAt"] = *l.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListRecruitForm(req *RecruitFormListReq) (int64, []officialwebsitemod.RecruitForm, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.RecruitForm{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func CreateRecruitForm(req *ModifyRecruitFormReq) (officialwebsitemod.RecruitForm, error) {
|
||||
data := req.toMod()
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.RecruitForm{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdateRecruitForm(req *ModifyRecruitFormReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.RecruitForm{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteRecruitForm(req *DeleteRecruitFormReq) (data DeleteRecruitFormResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.RecruitForm{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyRecruitFormReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Name *string `json:"name"`
|
||||
Sex *int `json:"sex"`
|
||||
Age *int `json:"age"`
|
||||
Country *string `json:"country"`
|
||||
Address *string `json:"address"`
|
||||
Contact *[]officialwebsitemod.ContactInfo `json:"contact"`
|
||||
Description *string `json:"description"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteRecruitFormReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeleteRecruitFormResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyRecruitFormReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyRecruitFormReq) toMod() officialwebsitemod.RecruitForm {
|
||||
if req == nil {
|
||||
return officialwebsitemod.RecruitForm{}
|
||||
}
|
||||
data := officialwebsitemod.RecruitForm{
|
||||
Name: stringOrZero(req.Name),
|
||||
Sex: intOrZero(req.Sex),
|
||||
Age: intOrZero(req.Age),
|
||||
Country: stringOrZero(req.Country),
|
||||
Address: stringOrZero(req.Address),
|
||||
Description: stringOrZero(req.Description),
|
||||
}
|
||||
if req.Contact != nil {
|
||||
data.Contact = *req.Contact
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyRecruitFormReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyRecruitFormReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.Name != nil {
|
||||
set["name"] = *req.Name
|
||||
}
|
||||
if req.Sex != nil {
|
||||
set["sex"] = *req.Sex
|
||||
}
|
||||
if req.Age != nil {
|
||||
set["age"] = *req.Age
|
||||
}
|
||||
if req.Country != nil {
|
||||
set["country"] = *req.Country
|
||||
}
|
||||
if req.Address != nil {
|
||||
set["address"] = *req.Address
|
||||
}
|
||||
if req.Contact != nil {
|
||||
set["contact"] = *req.Contact
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type RecruitFormListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
Name *string `form:"name"`
|
||||
Sex *int `form:"sex"`
|
||||
Age *int `form:"age"`
|
||||
Country *string `form:"country"`
|
||||
Address *string `form:"address"`
|
||||
Contact *string `form:"contact"`
|
||||
Description *string `form:"description"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *RecruitFormListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Name != nil {
|
||||
filter["name"] = *r.Name
|
||||
}
|
||||
if r.Sex != nil {
|
||||
filter["sex"] = *r.Sex
|
||||
}
|
||||
if r.Age != nil {
|
||||
filter["age"] = *r.Age
|
||||
}
|
||||
if r.Country != nil {
|
||||
filter["country"] = *r.Country
|
||||
}
|
||||
if r.Address != nil {
|
||||
filter["address"] = *r.Address
|
||||
}
|
||||
if err := parseJSONFilter(filter, "contact", r.Contact, &[]officialwebsitemod.ContactInfo{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Description != nil {
|
||||
filter["description"] = *r.Description
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
|
||||
"github.com/mozillazg/go-pinyin"
|
||||
)
|
||||
|
||||
var (
|
||||
seoSlugValidRe = regexp.MustCompile(`^[a-z]+$`) // 纯小写英文字母
|
||||
seoSlugStripRe = regexp.MustCompile(`[^a-z]`) // 非 a-z 一律剔除
|
||||
)
|
||||
|
||||
// seoSlugMaxLen 自动生成 slug 的最大长度(按拼音音节边界截断,避免长标题生成超长 slug)
|
||||
const seoSlugMaxLen = 20
|
||||
|
||||
// GenerateSeoSlug 从标题生成纯小写字母 slug:中文转拼音、英文保留、其余字符剔除,
|
||||
// 并按音节边界累加到 seoSlugMaxLen 为止(不从音节中间截断)。
|
||||
// 例: "优雅Summer 2023" -> "youyasummer"
|
||||
func GenerateSeoSlug(title string) string {
|
||||
if title == "" {
|
||||
return ""
|
||||
}
|
||||
args := pinyin.NewArgs()
|
||||
// 非汉字(英文/数字/符号)原样返回,后续再统一剔除非 a-z
|
||||
args.Fallback = func(r rune, a pinyin.Args) []string {
|
||||
return []string{string(r)}
|
||||
}
|
||||
rows := pinyin.Pinyin(title, args)
|
||||
var b strings.Builder
|
||||
for _, row := range rows {
|
||||
if len(row) == 0 {
|
||||
continue
|
||||
}
|
||||
// 单个音节先剔除非 a-z、转小写
|
||||
syl := seoSlugStripRe.ReplaceAllString(strings.ToLower(row[0]), "")
|
||||
if syl == "" {
|
||||
continue
|
||||
}
|
||||
// 到长度上限则在音节边界停止,避免 slug 过长
|
||||
if b.Len()+len(syl) > seoSlugMaxLen {
|
||||
break
|
||||
}
|
||||
b.WriteString(syl)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// ValidateSeoSlug 校验 slug 格式:非空且纯小写英文字母。
|
||||
func ValidateSeoSlug(s string) bool {
|
||||
return seoSlugValidRe.MatchString(s)
|
||||
}
|
||||
|
||||
// ResolveSeoSlug 统一处理 seoSlug:
|
||||
// - 手填(provided 非空):校验纯小写字母格式,并查重(冲突报错)
|
||||
// - 留空:由 title 生成拼音雏形,冲突时追加后缀去重
|
||||
//
|
||||
// exists 由各表提供(查各自表是否已占用该 slug)。
|
||||
func ResolveSeoSlug(provided, title string, exists func(slug string) (bool, error)) (string, error) {
|
||||
if provided != "" {
|
||||
if !ValidateSeoSlug(provided) {
|
||||
return "", stderr.ErrParamError
|
||||
}
|
||||
used, err := exists(provided)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if used {
|
||||
return "", stderr.ErrParamError
|
||||
}
|
||||
return provided, nil
|
||||
}
|
||||
return UniqueSeoSlug(GenerateSeoSlug(title), exists)
|
||||
}
|
||||
|
||||
// UniqueSeoSlug 基于 base 生成同表唯一的 slug;exists 判断某 slug 是否已被占用。
|
||||
// 冲突时依次追加纯小写字母后缀 a、b…z、aa、ab…zz、aaa… 直到命中未占用值;
|
||||
// base 为空则返回空(走稀疏索引,不参与唯一约束)。
|
||||
func UniqueSeoSlug(base string, exists func(slug string) (bool, error)) (string, error) {
|
||||
if base == "" {
|
||||
return "", nil
|
||||
}
|
||||
// n=0 先试 base 原值,之后依次追加 a、b…z、aa… 后缀(双射 26 进制递增)。
|
||||
// 表内记录有限且各候选互不相同,必能在有限次内命中未占用值。
|
||||
for n := 0; ; n++ {
|
||||
candidate := base
|
||||
if n > 0 {
|
||||
candidate += seoSlugSuffix(n)
|
||||
}
|
||||
used, err := exists(candidate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !used {
|
||||
return candidate, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// seoSlugSuffix 返回第 n 个纯小写字母后缀(n>=1),按双射 26 进制递增:
|
||||
// 1->a 2->b … 26->z 27->aa 28->ab … 52->az 53->ba … 702->zz 703->aaa
|
||||
func seoSlugSuffix(n int) string {
|
||||
var buf []byte
|
||||
for n > 0 {
|
||||
n--
|
||||
buf = append([]byte{byte('a' + n%26)}, buf...)
|
||||
n /= 26
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func ListTag(req *TagListReq) (int64, []officialwebsitemod.Tag, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.Tag{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func CreateTag(req *ModifyTagReq) (officialwebsitemod.Tag, error) {
|
||||
data := req.toMod()
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.Tag{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdateTag(req *ModifyTagReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Tag{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteTag(req *DeleteTagReq) (data DeleteTagResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Tag{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyTagReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
Name *string `json:"name"`
|
||||
Type *string `json:"type"`
|
||||
IsHot *bool `json:"isHot"`
|
||||
Sort *int64 `json:"sort"`
|
||||
IsActive *bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteTagReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeleteTagResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyTagReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyTagReq) toMod() officialwebsitemod.Tag {
|
||||
if req == nil {
|
||||
return officialwebsitemod.Tag{}
|
||||
}
|
||||
return officialwebsitemod.Tag{
|
||||
Name: stringOrZero(req.Name),
|
||||
Type: stringOrZero(req.Type),
|
||||
IsHot: boolOrZero(req.IsHot),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: int64OrZero(req.Sort),
|
||||
IsActive: boolOrZero(req.IsActive),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyTagReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyTagReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.Name != nil {
|
||||
set["name"] = *req.Name
|
||||
}
|
||||
if req.Type != nil {
|
||||
set["type"] = *req.Type
|
||||
}
|
||||
if req.IsHot != nil {
|
||||
set["isHot"] = *req.IsHot
|
||||
}
|
||||
if req.Sort != nil {
|
||||
set["sort"] = *req.Sort
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
set["isActive"] = *req.IsActive
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type TagListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
Name *string `form:"name"`
|
||||
Type *string `form:"type"`
|
||||
IsHot *bool `form:"isHot"`
|
||||
Sort *int64 `form:"sort"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *TagListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Name != nil {
|
||||
filter["name"] = *r.Name
|
||||
}
|
||||
if r.Type != nil {
|
||||
filter["type"] = *r.Type
|
||||
}
|
||||
if r.IsHot != nil {
|
||||
filter["isHot"] = *r.IsHot
|
||||
}
|
||||
if r.Sort != nil {
|
||||
filter["sort"] = *r.Sort
|
||||
}
|
||||
if r.IsActive != nil {
|
||||
filter["isActive"] = *r.IsActive
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
@@ -0,0 +1,652 @@
|
||||
package officialwebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/models/v/tagmod"
|
||||
"91porn-server/models/v/vidmod"
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/stderr"
|
||||
officialwebsitemod "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Service functions
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func CheckVideoExistByVid(vid []primitive.ObjectID) ([]officialwebsitemod.Video, error) {
|
||||
filter := bson.M{"_id": bson.M{"$in": vid}}
|
||||
mod := &officialwebsitemod.Video{}
|
||||
videos, err := mod.FindMany(filter)
|
||||
return videos, err
|
||||
}
|
||||
|
||||
func ListVideo(req *VideoListReq) (int64, []officialwebsitemod.Video, error) {
|
||||
filter, err := req.Query()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
mod := &officialwebsitemod.Video{}
|
||||
total, err := mod.Count(filter)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err := mod.FindMany(filter, req.FindOptions())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
// resolveVideoSeoSlug 处理 seoSlug:手填则校验格式并查重(冲突报错);为空则由标题生成雏形并追加后缀去重。
|
||||
func resolveVideoSeoSlug(provided, title string, excludeID primitive.ObjectID) (string, error) {
|
||||
exists := func(slug string) (bool, error) {
|
||||
filter := officialwebsitemod.M{"seoSlug": slug}
|
||||
if !excludeID.IsZero() {
|
||||
filter["_id"] = officialwebsitemod.M{"$ne": excludeID}
|
||||
}
|
||||
n, err := (&officialwebsitemod.Video{}).Count(filter)
|
||||
return n > 0, err
|
||||
}
|
||||
if provided != "" {
|
||||
if !ValidateSeoSlug(provided) {
|
||||
return "", stderr.ErrParamError
|
||||
}
|
||||
used, err := exists(provided)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if used {
|
||||
return "", stderr.ErrParamError
|
||||
}
|
||||
return provided, nil
|
||||
}
|
||||
return UniqueSeoSlug(GenerateSeoSlug(title), exists)
|
||||
}
|
||||
|
||||
func CreateVideo(req *ModifyVideoReq) (officialwebsitemod.Video, error) {
|
||||
data, err := req.toMod()
|
||||
if err != nil {
|
||||
return officialwebsitemod.Video{}, err
|
||||
}
|
||||
// SEO slug:手填优先(校验唯一),为空则由标题生成雏形并去重
|
||||
if data.SeoSlug, err = resolveVideoSeoSlug(data.SeoSlug, data.Title, primitive.NilObjectID); err != nil {
|
||||
return officialwebsitemod.Video{}, err
|
||||
}
|
||||
if err := data.Create(); err != nil {
|
||||
return officialwebsitemod.Video{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func UpdateVideo(req *ModifyVideoReq) (resp CountResp, err error) {
|
||||
if req == nil || req.ID == "" {
|
||||
return
|
||||
}
|
||||
id, parseErr := primitive.ObjectIDFromHex(req.ID)
|
||||
if parseErr != nil || isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Video{}
|
||||
if err = mod.FindOne(officialwebsitemod.M{"_id": id}); err != nil {
|
||||
return
|
||||
}
|
||||
// 若提交了 seoSlug,先校验/去重(排除自身),回写后由 toM 落库
|
||||
if req.SeoSlug != nil {
|
||||
var slug string
|
||||
if slug, err = resolveVideoSeoSlug(*req.SeoSlug, mod.Title, id); err != nil {
|
||||
return
|
||||
}
|
||||
*req.SeoSlug = slug
|
||||
}
|
||||
var update officialwebsitemod.M
|
||||
if update, err = req.toM(); err != nil || update == nil {
|
||||
return
|
||||
}
|
||||
resp.Count, err = mod.Update(officialwebsitemod.M{"_id": id}, update)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteVideo(req *DeleteVideoReq) (data DeleteVideoResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.CodeEmptyData
|
||||
return
|
||||
}
|
||||
var id primitive.ObjectID
|
||||
if id, err = primitive.ObjectIDFromHex(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(id) {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
mod := &officialwebsitemod.Video{}
|
||||
data.Count, err = mod.Delete(officialwebsitemod.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
func BatchUpdateVideoOwner(req *BatchUpdateVideoOwnerReq) (data BatchUpdateVideoOwnerResp, err error) {
|
||||
if req == nil {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
|
||||
// Check owner is exist
|
||||
var ownerID primitive.ObjectID
|
||||
ownerID, err = primitive.ObjectIDFromHex(req.OwnerID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var heroMod = &officialwebsitemod.Hero{}
|
||||
err = heroMod.FindOne(officialwebsitemod.M{"_id": ownerID})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if isNilObjectID(heroMod.ID) {
|
||||
err = stderr.OfficialWebsiteHeroExist
|
||||
return
|
||||
}
|
||||
|
||||
var update = bson.M{"$set": bson.M{"heroId": ownerID}}
|
||||
// Check album is exist, if exist then add into update
|
||||
if req.AlbumID != "" {
|
||||
var albumID primitive.ObjectID
|
||||
albumID, err = primitive.ObjectIDFromHex(req.AlbumID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var album = &officialwebsitemod.Album{}
|
||||
err = album.FindOne(officialwebsitemod.M{"_id": albumID})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
update = bson.M{"$set": bson.M{"heroId": ownerID, "albumId": albumID}}
|
||||
}
|
||||
|
||||
var videoIDs []primitive.ObjectID
|
||||
for i := range req.VideoIDs {
|
||||
videoID, parseErr := primitive.ObjectIDFromHex(req.VideoIDs[i])
|
||||
err = parseErr
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
videoIDs = append(videoIDs, videoID)
|
||||
}
|
||||
var videoMod = &officialwebsitemod.Video{}
|
||||
filter := bson.M{"_id": bson.M{"$in": videoIDs}}
|
||||
data.Count, err = videoMod.UpdateMany(filter, update)
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Batch (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type BatchUpdateVideoOwnerReq struct {
|
||||
VideoIDs []string `json:"video_ids"`
|
||||
OwnerID string `json:"owner_id"`
|
||||
AlbumID string `json:"album_id"`
|
||||
}
|
||||
|
||||
type BatchUpdateVideoOwnerResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Mutation (Modify) types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type ModifyVideoReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
AlbumID *string `json:"albumId" form:"albumId"`
|
||||
HeroID *string `json:"heroId" form:"heroId"`
|
||||
Title *string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
Cover *string `json:"cover"`
|
||||
Url *string `json:"url"`
|
||||
SeoSlug *string `json:"seoSlug"`
|
||||
Tags *[]officialwebsitemod.Tag `json:"tags"`
|
||||
IsHot *bool `json:"isHot"`
|
||||
Sort *int64 `json:"sort"`
|
||||
IsActive *bool `json:"isActive"`
|
||||
WatchCount *int64 `json:"watchCount"`
|
||||
LikeCount *int64 `json:"likeCount"`
|
||||
CommentCount *int64 `json:"commentCount"`
|
||||
CollectCount *int64 `json:"collectCount"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Delete types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type DeleteVideoReq struct {
|
||||
ID string `json:"id" form:"id"`
|
||||
}
|
||||
|
||||
type DeleteVideoResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toMod — ModifyVideoReq → model struct
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyVideoReq) toMod() (officialwebsitemod.Video, error) {
|
||||
if req == nil {
|
||||
return officialwebsitemod.Video{}, nil
|
||||
}
|
||||
data := officialwebsitemod.Video{
|
||||
Title: stringOrZero(req.Title),
|
||||
Description: stringOrZero(req.Description),
|
||||
Cover: stringOrZero(req.Cover),
|
||||
Url: stringOrZero(req.Url),
|
||||
IsHot: boolOrZero(req.IsHot),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: int64OrZero(req.Sort),
|
||||
IsActive: boolOrZero(req.IsActive),
|
||||
},
|
||||
WatchCount: int64OrZero(req.WatchCount),
|
||||
LikeCount: int64OrZero(req.LikeCount),
|
||||
CommentCount: int64OrZero(req.CommentCount),
|
||||
CollectCount: int64OrZero(req.CollectCount),
|
||||
}
|
||||
if req.AlbumID != nil {
|
||||
if *req.AlbumID != "" {
|
||||
albumID, err := primitive.ObjectIDFromHex(*req.AlbumID)
|
||||
if err != nil || isNilObjectID(albumID) {
|
||||
return officialwebsitemod.Video{}, stderr.ErrParamError
|
||||
}
|
||||
data.AlbumID = albumID
|
||||
}
|
||||
}
|
||||
if req.HeroID != nil {
|
||||
if *req.HeroID != "" {
|
||||
heroID, err := primitive.ObjectIDFromHex(*req.HeroID)
|
||||
if err != nil || isNilObjectID(heroID) {
|
||||
return officialwebsitemod.Video{}, stderr.ErrParamError
|
||||
}
|
||||
data.HeroID = heroID
|
||||
}
|
||||
}
|
||||
if req.Tags != nil {
|
||||
data.Tags = *req.Tags
|
||||
}
|
||||
if req.SeoSlug != nil {
|
||||
data.SeoSlug = *req.SeoSlug
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// toM — ModifyVideoReq → officialwebsitemod.M
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
func (req *ModifyVideoReq) toM() (officialwebsitemod.M, error) {
|
||||
if req == nil {
|
||||
return nil, stderr.CodeEmptyData
|
||||
}
|
||||
set := officialwebsitemod.M{}
|
||||
if req.AlbumID != nil {
|
||||
if *req.AlbumID != "" {
|
||||
albumID, err := primitive.ObjectIDFromHex(*req.AlbumID)
|
||||
if err != nil || isNilObjectID(albumID) {
|
||||
return nil, stderr.ErrParamError
|
||||
}
|
||||
set["albumId"] = albumID
|
||||
}
|
||||
}
|
||||
if req.HeroID != nil {
|
||||
if *req.HeroID != "" {
|
||||
heroID, err := primitive.ObjectIDFromHex(*req.HeroID)
|
||||
if err != nil || isNilObjectID(heroID) {
|
||||
return nil, stderr.ErrParamError
|
||||
}
|
||||
set["heroId"] = heroID
|
||||
}
|
||||
}
|
||||
if req.Title != nil {
|
||||
set["title"] = *req.Title
|
||||
}
|
||||
if req.Description != nil {
|
||||
set["description"] = *req.Description
|
||||
}
|
||||
if req.Cover != nil {
|
||||
set["cover"] = *req.Cover
|
||||
}
|
||||
if req.Url != nil {
|
||||
set["url"] = *req.Url
|
||||
}
|
||||
if req.Tags != nil {
|
||||
set["tags"] = *req.Tags
|
||||
}
|
||||
if req.SeoSlug != nil && *req.SeoSlug != "" {
|
||||
set["seoSlug"] = *req.SeoSlug
|
||||
}
|
||||
if req.IsHot != nil {
|
||||
set["isHot"] = *req.IsHot
|
||||
}
|
||||
if req.Sort != nil {
|
||||
set["sort"] = *req.Sort
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
set["isActive"] = *req.IsActive
|
||||
}
|
||||
if req.WatchCount != nil {
|
||||
set["watchCount"] = *req.WatchCount
|
||||
}
|
||||
if req.LikeCount != nil {
|
||||
set["likeCount"] = *req.LikeCount
|
||||
}
|
||||
if req.CommentCount != nil {
|
||||
set["commentCount"] = *req.CommentCount
|
||||
}
|
||||
if req.CollectCount != nil {
|
||||
set["collectCount"] = *req.CollectCount
|
||||
}
|
||||
if len(set) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
set["updatedAt"] = time.Now().UTC()
|
||||
return officialwebsitemod.M{"$set": set}, nil
|
||||
}
|
||||
|
||||
func BatchImportVideo(req *BatchImportVideoReq) (resp BatchImportVideoResp, err error) {
|
||||
if req == nil || len(req.VideoIds) == 0 {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
objIds := make([]primitive.ObjectID, 0, len(req.VideoIds))
|
||||
videoIDSet := make(map[primitive.ObjectID]struct{}, len(req.VideoIds))
|
||||
for _, videoId := range req.VideoIds {
|
||||
var id primitive.ObjectID
|
||||
id, err = primitive.ObjectIDFromHex(videoId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, exists := videoIDSet[id]; exists {
|
||||
continue
|
||||
}
|
||||
videoIDSet[id] = struct{}{}
|
||||
objIds = append(objIds, id)
|
||||
}
|
||||
if len(objIds) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 1) Filter out videos that already exist in official website video table by `_id`.
|
||||
var videoMod = &officialwebsitemod.Video{}
|
||||
officialVideos, findVideoErr := videoMod.FindMany(officialwebsitemod.M{"_id": bson.M{"$in": objIds}})
|
||||
if findVideoErr != nil {
|
||||
err = findVideoErr
|
||||
return
|
||||
}
|
||||
existedVideoMap := make(map[primitive.ObjectID]struct{}, len(officialVideos))
|
||||
for _, v := range officialVideos {
|
||||
existedVideoMap[v.ID] = struct{}{}
|
||||
}
|
||||
|
||||
needImportVideoIDs := make([]primitive.ObjectID, 0, len(objIds))
|
||||
for _, id := range objIds {
|
||||
if _, exists := existedVideoMap[id]; exists {
|
||||
continue
|
||||
}
|
||||
needImportVideoIDs = append(needImportVideoIDs, id)
|
||||
}
|
||||
if len(needImportVideoIDs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
mats := []vidmod.Matcher{
|
||||
(&vidmod.IDInMatch{IDs: needImportVideoIDs}).New(),
|
||||
}
|
||||
list, err := vidmod.FindMany(mats...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var insertVideos []officialwebsitemod.Video
|
||||
allTagIDs := make([]primitive.ObjectID, 0)
|
||||
allTagIDSet := make(map[primitive.ObjectID]struct{})
|
||||
for _, video := range list {
|
||||
insertVideos = append(insertVideos, officialwebsitemod.Video{
|
||||
ID: video.ID,
|
||||
Title: video.Title,
|
||||
Description: video.Content,
|
||||
Cover: video.Cover,
|
||||
Url: video.SourceURL,
|
||||
IsHot: false,
|
||||
WatchCount: int64(video.FakePlayCount+video.PlayCount) * rand.Int64N(10),
|
||||
LikeCount: int64(video.FakeLikeCount+video.LikeCount) * rand.Int64N(10),
|
||||
CommentCount: int64(video.FakeCommentCount+video.CommentCount) * rand.Int64N(10),
|
||||
CollectCount: int64(video.CollectCount) * rand.Int64N(10),
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
IsActive: true,
|
||||
},
|
||||
BaseModel: officialwebsitemod.BaseModel{
|
||||
CreatedAt: time.Now().UTC(),
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
},
|
||||
})
|
||||
for _, tag := range video.Tags {
|
||||
if _, exists := allTagIDSet[tag]; exists {
|
||||
continue
|
||||
}
|
||||
allTagIDSet[tag] = struct{}{}
|
||||
allTagIDs = append(allTagIDs, tag)
|
||||
}
|
||||
}
|
||||
|
||||
if len(insertVideos) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 2) Filter out tags that already exist in official website tag table by `_id`.
|
||||
var tagMod = &officialwebsitemod.Tag{}
|
||||
existedTagMap := map[primitive.ObjectID]struct{}{}
|
||||
existedOfficialTagInfoMap := map[primitive.ObjectID]officialwebsitemod.Tag{}
|
||||
if len(allTagIDs) > 0 {
|
||||
officialWebsiteTags, findTagErr := tagMod.FindMany(officialwebsitemod.M{
|
||||
"_id": bson.M{"$in": allTagIDs},
|
||||
"type": officialwebsitemod.OfficialWebsiteTagTypeVideo,
|
||||
})
|
||||
if findTagErr != nil {
|
||||
err = findTagErr
|
||||
return
|
||||
}
|
||||
existedTagMap = make(map[primitive.ObjectID]struct{}, len(officialWebsiteTags))
|
||||
for _, t := range officialWebsiteTags {
|
||||
existedTagMap[t.ID] = struct{}{}
|
||||
existedOfficialTagInfoMap[t.ID] = t
|
||||
}
|
||||
}
|
||||
|
||||
needImportTagIDs := make([]primitive.ObjectID, 0, len(allTagIDs))
|
||||
for _, tagID := range allTagIDs {
|
||||
if _, exists := existedTagMap[tagID]; exists {
|
||||
continue
|
||||
}
|
||||
needImportTagIDs = append(needImportTagIDs, tagID)
|
||||
}
|
||||
|
||||
tagsMap, err := tagmod.FindTagsMapByIDS(needImportTagIDs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var insertTags []officialwebsitemod.Tag
|
||||
for _, tagID := range needImportTagIDs {
|
||||
tag, ok := tagsMap[tagID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
insertTags = append(insertTags, officialwebsitemod.Tag{
|
||||
ID: tag.ID,
|
||||
Name: tag.TagName,
|
||||
Type: officialwebsitemod.OfficialWebsiteTagTypeVideo,
|
||||
IsHot: len(tag.HotMark) > 0,
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
IsActive: true,
|
||||
},
|
||||
BaseModel: officialwebsitemod.BaseModel{
|
||||
CreatedAt: time.Now().UTC(),
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Fill video tags from tag info map to keep video docs self-contained.
|
||||
for i := range insertVideos {
|
||||
srcVideo := list[i]
|
||||
videoTags := make([]officialwebsitemod.Tag, 0, len(srcVideo.Tags))
|
||||
for _, tagID := range srcVideo.Tags {
|
||||
if oldTag, exists := existedOfficialTagInfoMap[tagID]; exists {
|
||||
videoTags = append(videoTags, officialwebsitemod.Tag{
|
||||
ID: oldTag.ID,
|
||||
Name: oldTag.Name,
|
||||
Type: officialwebsitemod.OfficialWebsiteTagTypeVideo,
|
||||
IsHot: oldTag.IsHot,
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
Sort: oldTag.Sort,
|
||||
IsActive: true,
|
||||
},
|
||||
})
|
||||
continue
|
||||
}
|
||||
tag, ok := tagsMap[tagID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
videoTags = append(videoTags, officialwebsitemod.Tag{
|
||||
ID: tag.ID,
|
||||
Name: tag.TagName,
|
||||
Type: officialwebsitemod.OfficialWebsiteTagTypeVideo,
|
||||
IsHot: len(tag.HotMark) > 0,
|
||||
SortModel: officialwebsitemod.SortModel{
|
||||
IsActive: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
insertVideos[i].Tags = videoTags
|
||||
}
|
||||
|
||||
// 3) Insert filtered videos and tags into official website tables separately.
|
||||
var ids []primitive.ObjectID
|
||||
ids, err = videoMod.InsertMany(insertVideos)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := range insertTags {
|
||||
if createErr := insertTags[i].Create(); createErr != nil {
|
||||
err = createErr
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
resp.Count = int64(len(ids))
|
||||
return
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// Batch Import types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type BatchImportVideoReq struct {
|
||||
VideoIds []string `json:"videoIds"`
|
||||
}
|
||||
|
||||
type BatchImportVideoResp struct {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// List types
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
type VideoListReq struct {
|
||||
PageReq
|
||||
ID *string `form:"id"`
|
||||
IDs []string `form:"ids"`
|
||||
PrimiteveIDs []primitive.ObjectID `form:"primitiveIds"`
|
||||
AlbumID *string `form:"albumId"`
|
||||
HeroID *string `form:"heroID"`
|
||||
Title *string `form:"title"`
|
||||
Description *string `form:"description"`
|
||||
Cover *string `form:"cover"`
|
||||
Url *string `form:"url"`
|
||||
Tags *string `form:"tags"`
|
||||
IsHot *bool `form:"isHot"`
|
||||
Sort *int64 `form:"sort"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
CreatedAt *time.Time `form:"createdAt"`
|
||||
UpdatedAt *time.Time `form:"updatedAt"`
|
||||
DeletedAt *time.Time `form:"deletedAt"`
|
||||
}
|
||||
|
||||
func (r *VideoListReq) Query() (officialwebsitemod.M, error) {
|
||||
filter := officialwebsitemod.M{}
|
||||
if err := parseObjectIDFilter(filter, "_id", r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(r.IDs) > 0 {
|
||||
var objIDs []primitive.ObjectID
|
||||
for _, id := range r.IDs {
|
||||
objID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objIDs = append(objIDs, objID)
|
||||
}
|
||||
filter["_id"] = bson.M{"$in": objIDs}
|
||||
}
|
||||
if len(r.PrimiteveIDs) > 0 {
|
||||
filter["_id"] = bson.M{"$in": r.PrimiteveIDs}
|
||||
}
|
||||
if err := parseObjectIDFilter(filter, "albumId", r.AlbumID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := parseObjectIDFilter(filter, "heroId", r.HeroID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Title != nil {
|
||||
filter["title"] = *r.Title
|
||||
}
|
||||
if r.Description != nil {
|
||||
filter["description"] = *r.Description
|
||||
}
|
||||
if r.Cover != nil {
|
||||
filter["cover"] = *r.Cover
|
||||
}
|
||||
if r.Url != nil {
|
||||
filter["url"] = *r.Url
|
||||
}
|
||||
if err := parseJSONFilter(filter, "tags", r.Tags, &[]officialwebsitemod.Tag{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.IsHot != nil {
|
||||
filter["isHot"] = *r.IsHot
|
||||
}
|
||||
if r.Sort != nil {
|
||||
filter["sort"] = *r.Sort
|
||||
}
|
||||
if r.IsActive != nil {
|
||||
filter["isActive"] = *r.IsActive
|
||||
}
|
||||
if r.CreatedAt != nil {
|
||||
filter["createdAt"] = *r.CreatedAt
|
||||
}
|
||||
if r.UpdatedAt != nil {
|
||||
filter["updatedAt"] = *r.UpdatedAt
|
||||
}
|
||||
if r.DeletedAt != nil {
|
||||
filter["deletedAt"] = *r.DeletedAt
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
Reference in New Issue
Block a user