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 }