Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

285 lines
8.3 KiB
Go

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
}