@@ -0,0 +1,161 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/common/stderr"
|
||||
"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"
|
||||
)
|
||||
|
||||
type AlbumListReq struct {
|
||||
SortType int64 `json:"sortType" form:"sortType"` // 1: 创建时间 目前仅支持一种排序方式,后续增加后再完善这个字段
|
||||
|
||||
PageNumber int64 `json:"pageNumber" form:"pageNumber"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize"`
|
||||
}
|
||||
|
||||
type AlbumListResp struct {
|
||||
HasNext bool `json:"hasNext"`
|
||||
List []*AlbumResp `json:"list"`
|
||||
}
|
||||
|
||||
type AlbumResp struct {
|
||||
ID string `json:"id"`
|
||||
HeroID string `json:"heroID"`
|
||||
Title string `json:"title"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
IsHot bool `json:"isHot"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
func (a *AlbumResp) FromModel(album *officialWebsitemod.Album) {
|
||||
if album == nil {
|
||||
return
|
||||
}
|
||||
a.ID = album.ID.Hex()
|
||||
a.HeroID = album.HeroID.Hex()
|
||||
a.Title = album.Title
|
||||
a.SeoSlug = album.SeoSlug
|
||||
a.Description = album.Description
|
||||
a.Cover = album.Cover
|
||||
a.IsHot = album.IsHot
|
||||
a.Tags = make([]string, 0)
|
||||
for _, tag := range album.Tags {
|
||||
a.Tags = append(a.Tags, tag.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func AlbumList(req *AlbumListReq) (resp AlbumListResp, err error) {
|
||||
var sort = bson.D{}
|
||||
switch req.SortType { // 目前仅支持一种排序方式,后续增加后再完善这个字段
|
||||
default:
|
||||
sort = bson.D{{Key: "createdAt", Value: -1}}
|
||||
}
|
||||
|
||||
var albumMod = &officialWebsitemod.Album{}
|
||||
var skip, limit = transPageAndPageNumber(req.PageSize, req.PageNumber)
|
||||
var ops = options.Find().SetSort(sort).SetSkip(skip).SetLimit(limit + 1)
|
||||
albumsData, err := albumMod.FindMany(bson.M{"isActive": true}, ops)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp = AlbumListResp{
|
||||
HasNext: len(albumsData) > int(limit),
|
||||
List: make([]*AlbumResp, 0),
|
||||
}
|
||||
for _, v := range albumsData {
|
||||
var albumResp = &AlbumResp{}
|
||||
albumResp.FromModel(&v)
|
||||
resp.List = append(resp.List, albumResp)
|
||||
}
|
||||
if resp.HasNext {
|
||||
resp.List = resp.List[:len(resp.List)-1]
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
type AlbumDetailReq struct {
|
||||
ID string `uri:"id" form:"id"`
|
||||
PageNumber int64 `json:"pageNumber" form:"pageNumber"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize"`
|
||||
}
|
||||
|
||||
type AlbumDetailResp struct {
|
||||
AlbumResp
|
||||
Videos []AlbumDetailVideoResp `json:"videos"`
|
||||
}
|
||||
|
||||
type AlbumDetailVideoResp struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
Url string `json:"url"`
|
||||
IsHot bool `json:"isHot"`
|
||||
Tags []VideoTagResp `json:"tags"`
|
||||
WatchCount int64 `json:"watchCount"`
|
||||
LikeCount int64 `json:"likeCount"`
|
||||
CommentCount int64 `json:"commentCount"`
|
||||
CollectCount int64 `json:"collectCount"`
|
||||
}
|
||||
|
||||
func AlbumDetail(req *AlbumDetailReq) (resp AlbumDetailResp, err error) {
|
||||
if req.ID == "" {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
|
||||
// 兼容 id 与 seoSlug:24 位 hex 按 _id 查,否则按 seoSlug 查
|
||||
filter := bson.M{}
|
||||
if objID, e := primitive.ObjectIDFromHex(req.ID); e == nil {
|
||||
filter["_id"] = objID
|
||||
} else {
|
||||
filter["seoSlug"] = req.ID
|
||||
}
|
||||
albumMod := &officialWebsitemod.Album{}
|
||||
err = albumMod.FindOne(filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp.FromModel(albumMod)
|
||||
|
||||
// 组装获取专辑下视频列表
|
||||
filter = bson.M{"albumId": albumMod.ID}
|
||||
var skip, limit = transPageAndPageNumber(req.PageSize, req.PageNumber)
|
||||
var option = options.Find().SetSort(bson.D{{Key: "createdAt", Value: -1}}).SetSkip(skip).SetLimit(limit + 1)
|
||||
videoMod := &officialWebsitemod.Video{}
|
||||
var videos []officialWebsitemod.Video
|
||||
videos, err = videoMod.FindMany(filter, option)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, video := range videos {
|
||||
var videoResp = AlbumDetailVideoResp{
|
||||
ID: video.ID.Hex(),
|
||||
Title: video.Title,
|
||||
SeoSlug: video.SeoSlug,
|
||||
Description: video.Description,
|
||||
Cover: video.Cover,
|
||||
Url: video.Url,
|
||||
IsHot: video.IsHot,
|
||||
WatchCount: video.WatchCount,
|
||||
LikeCount: video.LikeCount,
|
||||
CommentCount: video.CommentCount,
|
||||
CollectCount: video.CollectCount,
|
||||
}
|
||||
for _, tag := range video.Tags {
|
||||
videoResp.Tags = append(videoResp.Tags, VideoTagResp{
|
||||
ID: tag.ID.Hex(),
|
||||
Name: tag.Name,
|
||||
})
|
||||
}
|
||||
resp.Videos = append(resp.Videos, videoResp)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/common/stderr"
|
||||
"91porn-server/models/v/officialWebsitemod"
|
||||
"91porn-server/models/v/sourcemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type GetBasicDataResp struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
//域名信息
|
||||
SourceList []*sourcemod.SourceRes `json:"sourceList"`
|
||||
//接口域名
|
||||
Domain []string `json:"domain"`
|
||||
Banner []Banner `json:"banner"`
|
||||
BannersDescription string `json:"bannersDescription" bson:"bannersDescription"`
|
||||
BannersDuration int `json:"bannersDuration" bson:"bannersDuration"`
|
||||
HeroBanner []BasicDataHeroBanner `json:"heroBanner"`
|
||||
Masterpiece []BasicDataMasterpiece `json:"masterpiece"`
|
||||
Business []BasicDataBusiness `json:"business"`
|
||||
AboutUs BasicDataAboutUs `json:"aboutUs"`
|
||||
FAQ []BasicDataFAQ `json:"faq"`
|
||||
HomePageCMS []BasicDataCMSData `json:"homePageCMS"`
|
||||
RecruitCMS []BasicDataCMSData `json:"recruitCMS"`
|
||||
Tags []officialWebsitemod.Tag `json:"tags"`
|
||||
}
|
||||
|
||||
type Banner struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Image string `json:"image"`
|
||||
PhoneImage string `json:"phoneImage"`
|
||||
Thumbnail string `json:"thumbnail"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
type BasicDataHeroBanner struct {
|
||||
HeroID string `json:"heroId"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Image string `json:"image"`
|
||||
URL string `json:"url"`
|
||||
Duration int `json:"duration"`
|
||||
}
|
||||
|
||||
type BasicDataMasterpiece struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type BasicDataBusiness struct {
|
||||
Name string `json:"name"`
|
||||
EnglishName string `json:"englishName"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
Detail []BasicDataBusinessDetail `json:"detail"`
|
||||
}
|
||||
|
||||
type BasicDataBusinessDetail struct {
|
||||
Cover string `json:"cover"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type BasicDataAboutUs struct {
|
||||
Description string `json:"description"`
|
||||
Companies []BasicDataCompanyInfo `json:"companies"`
|
||||
Values string `json:"values"`
|
||||
ValuesImg string `json:"valuesImg"`
|
||||
}
|
||||
|
||||
type BasicDataCompanyInfo struct {
|
||||
Name string `json:"name"`
|
||||
Address string `json:"address"`
|
||||
Description string `json:"description"`
|
||||
Contact []BasicDataContactInfo `json:"contact"`
|
||||
}
|
||||
|
||||
type BasicDataContactInfo struct {
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type SourceResp struct {
|
||||
ID primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
|
||||
IsActive bool `json:"isActive,omitempty" bson:"isActive,omitempty"`
|
||||
Type string `json:"type,omitempty" bson:"type,omitempty"`
|
||||
Domain DomainResp `json:"domain,omitempty" bson:"domain,omitempty"`
|
||||
}
|
||||
|
||||
type DomainResp struct {
|
||||
Weight int `json:"weight,omitempty" bson:"weight,omitempty"`
|
||||
Url string `json:"url,omitempty" bson:"url,omitempty"`
|
||||
Desc string `json:"desc,omitempty" bson:"desc,omitempty"`
|
||||
Status int `json:"status,omitempty" bson:"status,omitempty"`
|
||||
}
|
||||
|
||||
type BasicDataFAQ struct {
|
||||
Question string `json:"question"`
|
||||
Answer string `json:"answer"`
|
||||
}
|
||||
|
||||
type BasicDataCMSData struct {
|
||||
Description string `json:"description"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func GetBasicData() (data GetBasicDataResp, err error) {
|
||||
basicDataMod := &officialWebsitemod.BasicData{}
|
||||
err = basicDataMod.FindOne()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if basicDataMod.ID == primitive.NilObjectID {
|
||||
err = stderr.OfficialWebsiteBasicDataNotExist
|
||||
return
|
||||
}
|
||||
|
||||
data = GetBasicDataResp{
|
||||
Title: basicDataMod.Title,
|
||||
Description: basicDataMod.Description,
|
||||
Banner: make([]Banner, 0),
|
||||
BannersDescription: basicDataMod.BannersDescription,
|
||||
BannersDuration: basicDataMod.BannersDuration,
|
||||
HeroBanner: make([]BasicDataHeroBanner, 0),
|
||||
Masterpiece: make([]BasicDataMasterpiece, 0),
|
||||
Business: make([]BasicDataBusiness, 0),
|
||||
AboutUs: BasicDataAboutUs{},
|
||||
FAQ: make([]BasicDataFAQ, 0),
|
||||
HomePageCMS: make([]BasicDataCMSData, 0),
|
||||
RecruitCMS: make([]BasicDataCMSData, 0),
|
||||
}
|
||||
for _, v := range basicDataMod.Banner {
|
||||
data.Banner = append(data.Banner, Banner{
|
||||
Name: v.Name,
|
||||
Description: v.Description,
|
||||
Image: v.Image,
|
||||
PhoneImage: v.PhoneImage,
|
||||
Thumbnail: v.Thumbnail,
|
||||
URL: v.URL,
|
||||
})
|
||||
}
|
||||
for _, v := range basicDataMod.HeroBanner {
|
||||
data.HeroBanner = append(data.HeroBanner, BasicDataHeroBanner{
|
||||
HeroID: v.HeroID.Hex(),
|
||||
Name: v.Name,
|
||||
Description: v.Description,
|
||||
Image: v.Image,
|
||||
URL: v.URL,
|
||||
Duration: v.Duration,
|
||||
})
|
||||
}
|
||||
for _, v := range basicDataMod.Masterpiece {
|
||||
data.Masterpiece = append(data.Masterpiece, BasicDataMasterpiece{
|
||||
ID: v.ID.Hex(),
|
||||
Name: v.Name,
|
||||
Description: v.Description,
|
||||
Cover: v.Cover,
|
||||
Type: v.Type,
|
||||
})
|
||||
}
|
||||
for _, v := range basicDataMod.Business {
|
||||
data.Business = append(data.Business, BasicDataBusiness{
|
||||
Name: v.Name,
|
||||
EnglishName: v.EnglishName,
|
||||
Description: v.Description,
|
||||
Cover: v.Cover,
|
||||
Detail: make([]BasicDataBusinessDetail, 0, len(v.Detail)),
|
||||
})
|
||||
for _, d := range v.Detail {
|
||||
data.Business[len(data.Business)-1].Detail = append(data.Business[len(data.Business)-1].Detail, BasicDataBusinessDetail{
|
||||
Cover: d.Cover,
|
||||
Description: d.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
data.AboutUs = BasicDataAboutUs{
|
||||
Description: basicDataMod.AboutUs.Description,
|
||||
Values: basicDataMod.AboutUs.Values,
|
||||
ValuesImg: basicDataMod.AboutUs.ValuesImg,
|
||||
}
|
||||
for _, v := range basicDataMod.AboutUs.Companies {
|
||||
data.AboutUs.Companies = append(data.AboutUs.Companies, BasicDataCompanyInfo{
|
||||
Name: v.Name,
|
||||
Address: v.Address,
|
||||
Description: v.Description,
|
||||
Contact: make([]BasicDataContactInfo, 0),
|
||||
})
|
||||
for _, c := range v.Contact {
|
||||
data.AboutUs.Companies[len(data.AboutUs.Companies)-1].Contact = append(data.AboutUs.Companies[len(data.AboutUs.Companies)-1].Contact, BasicDataContactInfo{
|
||||
Type: c.Type,
|
||||
Value: c.Value,
|
||||
})
|
||||
}
|
||||
}
|
||||
for _, v := range basicDataMod.FAQ {
|
||||
data.FAQ = append(data.FAQ, BasicDataFAQ{
|
||||
Question: v.Question,
|
||||
Answer: v.Answer,
|
||||
})
|
||||
}
|
||||
for _, v := range basicDataMod.HomePageCMS {
|
||||
data.HomePageCMS = append(data.HomePageCMS, BasicDataCMSData{
|
||||
Description: v.Description,
|
||||
Value: v.Value,
|
||||
})
|
||||
}
|
||||
for _, v := range basicDataMod.RecruitCMS {
|
||||
data.RecruitCMS = append(data.RecruitCMS, BasicDataCMSData{
|
||||
Description: v.Description,
|
||||
Value: v.Value,
|
||||
})
|
||||
}
|
||||
|
||||
data.Tags = basicDataMod.Tags
|
||||
|
||||
// 域名信息(Domain/SourceList)改由 controller 实时获取,不进基础数据大缓存
|
||||
|
||||
return data, err
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
type BusinessListReq struct{}
|
||||
|
||||
type BusinessListResp struct {
|
||||
Total int64 `json:"total"`
|
||||
ADPlacement []BusinessInfo `json:"adPlacement"`
|
||||
ContentProduction []BusinessInfo `json:"contentProduction"`
|
||||
SubRevenue []BusinessInfo `json:"subRevenue"`
|
||||
}
|
||||
|
||||
type BusinessInfo struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type"` // 业务类型,如"adPlacement", "contentProduction", "subRevenue"
|
||||
ServiceOverview string `json:"serviceOverview"`
|
||||
CollaborationProcess string `json:"collaborationProcess"`
|
||||
CaseStudies string `json:"caseStudies"`
|
||||
}
|
||||
|
||||
func BusinessList(req *BusinessListReq) (resp BusinessListResp, err error) {
|
||||
data, err := (&officialWebsitemod.BusinessData{}).FindMany(nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp = BusinessListResp{
|
||||
Total: int64(len(data)),
|
||||
ADPlacement: make([]BusinessInfo, 0),
|
||||
ContentProduction: make([]BusinessInfo, 0),
|
||||
SubRevenue: make([]BusinessInfo, 0),
|
||||
}
|
||||
for _, v := range data {
|
||||
switch v.Type {
|
||||
case "adPlacement":
|
||||
resp.ADPlacement = append(resp.ADPlacement, BusinessInfo{
|
||||
Title: v.Title,
|
||||
Description: v.Description,
|
||||
Type: v.Type,
|
||||
ServiceOverview: v.ServiceOverview,
|
||||
CollaborationProcess: v.CollaborationProcess,
|
||||
CaseStudies: v.CaseStudies,
|
||||
})
|
||||
case "contentProduction":
|
||||
resp.ContentProduction = append(resp.ContentProduction, BusinessInfo{
|
||||
Title: v.Title,
|
||||
Description: v.Description,
|
||||
Type: v.Type,
|
||||
ServiceOverview: v.ServiceOverview,
|
||||
CollaborationProcess: v.CollaborationProcess,
|
||||
CaseStudies: v.CaseStudies,
|
||||
})
|
||||
case "subRevenue":
|
||||
resp.SubRevenue = append(resp.SubRevenue, BusinessInfo{
|
||||
Title: v.Title,
|
||||
Description: v.Description,
|
||||
Type: v.Type,
|
||||
ServiceOverview: v.ServiceOverview,
|
||||
CollaborationProcess: v.CollaborationProcess,
|
||||
CaseStudies: v.CaseStudies,
|
||||
})
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package officialWebsiteser
|
||||
|
||||
func transPageAndPageNumber(pageSize, pageNumber int64) (skip int64, limit int64) {
|
||||
if pageNumber <= 0 {
|
||||
pageNumber = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
skip = (pageNumber - 1) * pageSize
|
||||
limit = pageSize
|
||||
return skip, limit
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/common"
|
||||
"91porn-server/models/v/officialWebsitemod"
|
||||
"sync"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type HeroListReq struct {
|
||||
SortType int `json:"sortType" form:"sortType"` // 1: 最多粉丝,2: 最新加入,3:后管排序
|
||||
|
||||
PageNumber int64 `json:"pageNumber" form:"pageNumber"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize"`
|
||||
}
|
||||
|
||||
type HeroListResp struct {
|
||||
HasNext bool `json:"hasNext"`
|
||||
List []*HeroResp `json:"list"`
|
||||
}
|
||||
|
||||
type HeroResp struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Avatar string `json:"avatar"`
|
||||
FansCount int64 `json:"fansCount"`
|
||||
Cover string `json:"cover"`
|
||||
}
|
||||
|
||||
func HeroList(req *HeroListReq) (resp HeroListResp, err error) {
|
||||
var sort = bson.M{}
|
||||
switch req.SortType {
|
||||
case 2:
|
||||
sort["createdAt"] = -1
|
||||
case 3:
|
||||
sort["sort"] = -1
|
||||
default:
|
||||
sort["fansCount"] = -1
|
||||
}
|
||||
|
||||
// 分页查询时,查询一条多的数据来判断是否有下一页数据
|
||||
var skip, limit = transPageAndPageNumber(req.PageSize, req.PageNumber)
|
||||
var ops = options.Find().SetSort(sort).SetSkip(skip).SetLimit(limit + 1)
|
||||
data, err := (&officialWebsitemod.Hero{}).FindMany(bson.M{"isActive": true}, ops)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp = HeroListResp{
|
||||
HasNext: len(data) > int(limit),
|
||||
List: make([]*HeroResp, 0),
|
||||
}
|
||||
for _, v := range data {
|
||||
hero := &HeroResp{
|
||||
ID: v.ID.Hex(),
|
||||
Name: v.Name,
|
||||
SeoSlug: v.SeoSlug,
|
||||
Avatar: v.Avatar,
|
||||
FansCount: v.FansCount,
|
||||
Cover: v.Cover,
|
||||
}
|
||||
resp.List = append(resp.List, hero)
|
||||
}
|
||||
// 如果HasNext为true,说明还有下一页数,去除多查询的一条数据
|
||||
if resp.HasNext {
|
||||
resp.List = resp.List[:len(resp.List)-1]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type HeroDetailReq struct {
|
||||
ID string `uri:"id" binding:"required"`
|
||||
}
|
||||
|
||||
type HeroDetailResp struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Avatar string `json:"avatar"`
|
||||
Height int64 `json:"height"`
|
||||
Bust int64 `json:"bust"`
|
||||
Waist int64 `json:"waist"`
|
||||
Hip int64 `json:"hip"`
|
||||
Description string `json:"description"`
|
||||
FansCount int64 `json:"fansCount"`
|
||||
Cover string `json:"cover"`
|
||||
Partners []HeroDetailPartner `json:"partners"`
|
||||
Albums []HeroDetailAlbum `json:"albums"`
|
||||
Videos []HeroDetailVideo `json:"videos"`
|
||||
Photograph []Photograph `json:"photograph"`
|
||||
}
|
||||
|
||||
type HeroDetailAlbum struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
Tags []HeroDetailTag `json:"tags"`
|
||||
IsHot bool `json:"isHot"`
|
||||
}
|
||||
|
||||
type HeroDetailVideo struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
Url string `json:"url"`
|
||||
Tags []HeroDetailTag `json:"tags"`
|
||||
IsHot bool `json:"isHot"`
|
||||
}
|
||||
|
||||
type HeroDetailPartner struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Url string `json:"url"`
|
||||
Logo string `json:"logo"`
|
||||
}
|
||||
|
||||
type Photograph struct {
|
||||
ID string `json:"id" bson:"_id,omitempty"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Cover string `json:"cover" bson:"cover"`
|
||||
Photos []string `json:"photos" bson:"photos"`
|
||||
}
|
||||
|
||||
type HeroDetailTag struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func HeroDetail(req *HeroDetailReq) (resp *HeroDetailResp, err error) {
|
||||
filter := bson.M{"isActive": true}
|
||||
if id, e := primitive.ObjectIDFromHex(req.ID); e == nil {
|
||||
filter["_id"] = id
|
||||
} else {
|
||||
filter["seoSlug"] = req.ID
|
||||
}
|
||||
hero := &officialWebsitemod.Hero{}
|
||||
err = hero.FindOne(filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp = &HeroDetailResp{
|
||||
ID: hero.ID.Hex(),
|
||||
Name: hero.Name,
|
||||
SeoSlug: hero.SeoSlug,
|
||||
Avatar: hero.Avatar,
|
||||
Height: hero.Height,
|
||||
Bust: hero.Bust,
|
||||
Waist: hero.Waist,
|
||||
Hip: hero.Hip,
|
||||
Description: hero.Description,
|
||||
FansCount: hero.FansCount,
|
||||
Cover: hero.Cover,
|
||||
Partners: make([]HeroDetailPartner, 0),
|
||||
Albums: make([]HeroDetailAlbum, 0),
|
||||
Videos: make([]HeroDetailVideo, 0),
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(4)
|
||||
|
||||
// 查询合作伙伴
|
||||
common.Go(func() {
|
||||
defer wg.Done()
|
||||
resp.Partners, err = getHeroDetailPartners(hero.Partners)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
// 查询专辑
|
||||
common.Go(func() {
|
||||
defer wg.Done()
|
||||
resp.Albums, err = getHeroDetailAlbums(hero.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
// 查询视频
|
||||
common.Go(func() {
|
||||
defer wg.Done()
|
||||
resp.Videos, err = getHeroDetailVideos(hero.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
common.Go(func() {
|
||||
defer wg.Done()
|
||||
resp.Photograph, err = getHeroDetailPhotograph(hero.ID)
|
||||
})
|
||||
wg.Wait()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getHeroDetailAlbums(heroID primitive.ObjectID) (albums []HeroDetailAlbum, err error) {
|
||||
var albumMod = &officialWebsitemod.Album{}
|
||||
var filters = bson.M{"heroID": heroID}
|
||||
albumsData, err := albumMod.FindMany(filters, options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "createdAt", Value: -1}}).SetLimit(10))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
albums = make([]HeroDetailAlbum, 0)
|
||||
for _, v := range albumsData {
|
||||
tags := make([]HeroDetailTag, 0)
|
||||
for _, t := range v.Tags {
|
||||
tags = append(tags, HeroDetailTag{
|
||||
ID: t.ID.Hex(),
|
||||
Name: t.Name,
|
||||
})
|
||||
}
|
||||
albums = append(albums, HeroDetailAlbum{
|
||||
ID: v.ID.Hex(),
|
||||
Title: v.Title,
|
||||
SeoSlug: v.SeoSlug,
|
||||
Description: v.Description,
|
||||
Cover: v.Cover,
|
||||
IsHot: v.IsHot,
|
||||
Tags: tags,
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getHeroDetailVideos(heroID primitive.ObjectID) (videos []HeroDetailVideo, err error) {
|
||||
var videoMod = &officialWebsitemod.Video{}
|
||||
var filters = bson.M{"heroID": heroID}
|
||||
videosData, err := videoMod.FindMany(filters, options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "createdAt", Value: -1}}).SetLimit(10))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
videos = make([]HeroDetailVideo, 0)
|
||||
for _, v := range videosData {
|
||||
tags := make([]HeroDetailTag, 0)
|
||||
for _, t := range v.Tags {
|
||||
tags = append(tags, HeroDetailTag{
|
||||
ID: t.ID.Hex(),
|
||||
Name: t.Name,
|
||||
})
|
||||
}
|
||||
videos = append(videos, HeroDetailVideo{
|
||||
ID: v.ID.Hex(),
|
||||
Title: v.Title,
|
||||
SeoSlug: v.SeoSlug,
|
||||
Description: v.Description,
|
||||
Cover: v.Cover,
|
||||
Url: v.Url,
|
||||
IsHot: v.IsHot,
|
||||
Tags: tags,
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getHeroDetailPartners(partnerIds []primitive.ObjectID) (partners []HeroDetailPartner, err error) {
|
||||
var partnerMod = &officialWebsitemod.Partner{}
|
||||
var filters = bson.M{"_id": bson.M{"$in": partnerIds}, "isActive": true}
|
||||
partnersData, err := partnerMod.FindMany(filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
partners = make([]HeroDetailPartner, 0)
|
||||
for i := range partnerIds { // 保持合作伙伴的顺序和Hero中的一致,由后管控制
|
||||
for _, v := range partnersData {
|
||||
if v.ID == partnerIds[i] {
|
||||
partners = append(partners, HeroDetailPartner{
|
||||
ID: v.ID.Hex(),
|
||||
Name: v.Name,
|
||||
Url: v.Url,
|
||||
Logo: v.Logo,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getHeroDetailPhotograph(heroID primitive.ObjectID) (photograph []Photograph, err error) {
|
||||
var photographMod = &officialWebsitemod.Photograph{}
|
||||
var filters = bson.M{"heroId": heroID, "isActive": true}
|
||||
photographData, err := photographMod.FindMany(filters, options.Find().SetSort(bson.D{{Key: "createdAt", Value: -1}}).SetLimit(10))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
photograph = make([]Photograph, 0)
|
||||
for _, v := range photographData {
|
||||
ph := Photograph{
|
||||
ID: v.ID.Hex(),
|
||||
Name: v.Name,
|
||||
Description: v.Description,
|
||||
Cover: v.Cover,
|
||||
Photos: v.Photos,
|
||||
}
|
||||
photograph = append(photograph, ph)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type JobListReq struct {
|
||||
}
|
||||
|
||||
type JobListResp struct {
|
||||
Total int64 `json:"total"`
|
||||
List []JobInfo `json:"list"`
|
||||
}
|
||||
|
||||
type JobInfo struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Requirements string `json:"requirements"`
|
||||
Benefits string `json:"benefits"`
|
||||
JDUrl string `json:"jdUrl"`
|
||||
}
|
||||
|
||||
func JobList(req *JobListReq) (resp JobListResp, err error) {
|
||||
var filter = bson.M{"isActive": true}
|
||||
var jobMod = &officialWebsitemod.Job{}
|
||||
jobs, err := jobMod.FindMany(filter, options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "sort", Value: -1}, {Key: "createdAt", Value: -1}}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp = JobListResp{
|
||||
Total: int64(len(jobs)),
|
||||
List: make([]JobInfo, len(jobs)),
|
||||
}
|
||||
for i, job := range jobs {
|
||||
resp.List[i] = JobInfo{
|
||||
Title: job.Title,
|
||||
Description: job.Description,
|
||||
Requirements: job.Requirements,
|
||||
Benefits: job.Benefits,
|
||||
JDUrl: job.JDUrl,
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/models/v/officialWebsitemod"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type NewsListReq struct {
|
||||
PageNumber int64 `form:"PageNumber"`
|
||||
PageSize int64 `form:"pageSize"`
|
||||
}
|
||||
|
||||
type NewsListResp struct {
|
||||
HasNext bool `json:"hasNext"`
|
||||
List []*NewsResp `json:"list"`
|
||||
}
|
||||
|
||||
type NewsResp struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
Url string `json:"url"`
|
||||
Tags []NewsTagResp `json:"tags"`
|
||||
CreatedAt time.Time `json:"createdAt,omitempty" bson:"createdAt,omitempty"`
|
||||
}
|
||||
|
||||
type NewsTagResp struct {
|
||||
ID string `json:"id,omitempty" bson:"_id,omitempty"`
|
||||
Name string `json:"name,omitempty" bson:"name,omitempty"`
|
||||
Type string `json:"type,omitempty" bson:"type,omitempty"`
|
||||
IsHot bool `json:"isHot,omitempty" bson:"isHot,omitempty"`
|
||||
}
|
||||
|
||||
func NewsList(req *NewsListReq) (resp *NewsListResp, err error) {
|
||||
var filter = bson.M{"isActive": true}
|
||||
var newsMod = &officialWebsitemod.News{}
|
||||
var skip, limit = transPageAndPageNumber(req.PageSize, req.PageNumber)
|
||||
data, err := newsMod.FindMany(filter, options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "sort", Value: -1}, {Key: "createdAt", Value: -1}}).SetSkip(skip).SetLimit(limit+1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp = &NewsListResp{
|
||||
HasNext: len(data) > int(limit),
|
||||
List: make([]*NewsResp, 0),
|
||||
}
|
||||
for _, v := range data {
|
||||
newsResp := &NewsResp{
|
||||
ID: v.ID.Hex(),
|
||||
Title: v.Title,
|
||||
SeoSlug: v.SeoSlug,
|
||||
Description: v.Description,
|
||||
Cover: v.Cover,
|
||||
Url: v.Url,
|
||||
CreatedAt: v.CreatedAt,
|
||||
}
|
||||
for _, tag := range v.Tags {
|
||||
newsResp.Tags = append(newsResp.Tags, NewsTagResp{
|
||||
ID: tag.ID.Hex(),
|
||||
Name: tag.Name,
|
||||
Type: tag.Type,
|
||||
IsHot: tag.IsHot,
|
||||
})
|
||||
}
|
||||
resp.List = append(resp.List, newsResp)
|
||||
}
|
||||
if resp.HasNext {
|
||||
resp.List = resp.List[:len(resp.List)-1]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type NewsDetailReq struct {
|
||||
ID string `uri:"id" binding:"required"`
|
||||
RelatedPageNumber int64 `form:"RelatedPageNumber"`
|
||||
RelatedPageSize int64 `form:"RelatedPageSize"`
|
||||
}
|
||||
|
||||
type NewsDetailResp struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
Url string `json:"url"`
|
||||
Tags []NewsTagResp `json:"tags"`
|
||||
Detail string `json:"detail"`
|
||||
Related []*NewsResp `json:"related"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
func NewsDetail(req *NewsDetailReq) (resp NewsDetailResp, err error) {
|
||||
// 兼容 id 与 seoSlug:24 位 hex 按 _id 查,否则按 seoSlug 查
|
||||
var filter = bson.M{"isActive": true}
|
||||
if id, e := primitive.ObjectIDFromHex(req.ID); e == nil {
|
||||
filter["_id"] = id
|
||||
} else {
|
||||
filter["seoSlug"] = req.ID
|
||||
}
|
||||
var newsMod = &officialWebsitemod.News{}
|
||||
err = newsMod.FindOne(filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp = NewsDetailResp{
|
||||
ID: newsMod.ID.Hex(),
|
||||
Title: newsMod.Title,
|
||||
SeoSlug: newsMod.SeoSlug,
|
||||
Description: newsMod.Description,
|
||||
Cover: newsMod.Cover,
|
||||
Url: newsMod.Url,
|
||||
Detail: newsMod.Detail,
|
||||
CreatedAt: newsMod.CreatedAt,
|
||||
}
|
||||
var tagIDs []primitive.ObjectID
|
||||
for _, tag := range newsMod.Tags {
|
||||
resp.Tags = append(resp.Tags, NewsTagResp{
|
||||
ID: tag.ID.Hex(),
|
||||
Name: tag.Name,
|
||||
Type: tag.Type,
|
||||
IsHot: tag.IsHot,
|
||||
})
|
||||
tagIDs = append(tagIDs, tag.ID)
|
||||
}
|
||||
|
||||
if len(resp.Tags) > 0 {
|
||||
// 组装 Related,根据tagIDs搜索,并按照排序
|
||||
filter = bson.M{"tags._id": bson.M{"$in": tagIDs}, "isActive": true}
|
||||
} else {
|
||||
filter = bson.M{"isActive": true}
|
||||
}
|
||||
skip, limit := transPageAndPageNumber(req.RelatedPageSize, req.RelatedPageNumber)
|
||||
data, err := newsMod.FindMany(filter, options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "sort", Value: -1}, {Key: "createdAt", Value: -1}}).SetSkip(skip).SetLimit(limit))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, v := range data {
|
||||
newsResp := &NewsResp{
|
||||
ID: v.ID.Hex(),
|
||||
Title: v.Title,
|
||||
SeoSlug: v.SeoSlug,
|
||||
Description: v.Description,
|
||||
Cover: v.Cover,
|
||||
Url: v.Url,
|
||||
CreatedAt: v.CreatedAt,
|
||||
}
|
||||
for _, tag := range v.Tags {
|
||||
newsResp.Tags = append(newsResp.Tags, NewsTagResp{
|
||||
ID: tag.ID.Hex(),
|
||||
Name: tag.Name,
|
||||
Type: tag.Type,
|
||||
IsHot: tag.IsHot,
|
||||
})
|
||||
}
|
||||
resp.Related = append(resp.Related, newsResp)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import "91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
type PartnerListReq struct{}
|
||||
|
||||
type PartnerListResp struct {
|
||||
Total int64 `json:"total"`
|
||||
List []PartnerResp `json:"list"`
|
||||
}
|
||||
|
||||
type PartnerResp struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Logo string `json:"logo"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
func PartnerList(req *PartnerListReq) (resp PartnerListResp, err error) {
|
||||
data, err := (&officialWebsitemod.Partner{}).FindMany(nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp = PartnerListResp{
|
||||
Total: int64(len(data)),
|
||||
List: make([]PartnerResp, 0),
|
||||
}
|
||||
for _, v := range data {
|
||||
resp.List = append(resp.List, PartnerResp{
|
||||
Name: v.Name,
|
||||
Description: v.Description,
|
||||
Logo: v.Logo,
|
||||
Url: v.Url,
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type RecruitFormReq struct {
|
||||
Name string `json:"name" form:"name" binding:"required"`
|
||||
Sex int `json:"sex" form:"sex"`
|
||||
Age int `json:"age" form:"age"`
|
||||
Country string `json:"country" form:"country"`
|
||||
Address string `json:"address" form:"address"`
|
||||
Contact []ContactInfoReq `json:"contact" form:"contact" binding:"required,dive"`
|
||||
Description string `json:"description" form:"description"`
|
||||
}
|
||||
|
||||
type ContactInfoReq struct {
|
||||
Type string `json:"type" form:"type"`
|
||||
Value string `json:"value" form:"value"`
|
||||
}
|
||||
|
||||
type RecruitFormResp struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func RecruitForm(req *RecruitFormReq) (resp RecruitFormResp, err error) {
|
||||
if filter, ok := buildRecruitContactFilter(req.Contact); ok {
|
||||
var exist = &officialWebsitemod.RecruitForm{}
|
||||
err = exist.FindOne(filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if exist.ID != primitive.NilObjectID {
|
||||
resp = RecruitFormResp{
|
||||
Message: "您已提交过了,我们会尽快联系您",
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
form := &officialWebsitemod.RecruitForm{
|
||||
Name: req.Name,
|
||||
Sex: req.Sex,
|
||||
Age: req.Age,
|
||||
Country: req.Country,
|
||||
Address: req.Address,
|
||||
Description: req.Description,
|
||||
}
|
||||
for _, v := range req.Contact {
|
||||
form.Contact = append(form.Contact, officialWebsitemod.ContactInfo{
|
||||
Type: v.Type,
|
||||
Value: v.Value,
|
||||
})
|
||||
}
|
||||
err = form.Create()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp = RecruitFormResp{
|
||||
Message: "提交成功",
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func buildRecruitContactFilter(contacts []ContactInfoReq) (officialWebsitemod.M, bool) {
|
||||
if len(contacts) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
orConditions := make([]officialWebsitemod.M, 0, len(contacts))
|
||||
for _, c := range contacts {
|
||||
if c.Type == "" || c.Value == "" {
|
||||
continue
|
||||
}
|
||||
orConditions = append(orConditions, officialWebsitemod.M{
|
||||
"contact": bson.M{
|
||||
"$elemMatch": bson.M{
|
||||
"type": c.Type,
|
||||
"value": c.Value,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if len(orConditions) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if len(orConditions) == 1 {
|
||||
return orConditions[0], true
|
||||
}
|
||||
|
||||
return officialWebsitemod.M{"$or": orConditions}, true
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/models/v/officialWebsitemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type TagListReq struct {
|
||||
Type string `json:"type" form:"type" binding:"required,oneof=video hero album all"`
|
||||
}
|
||||
|
||||
type TagListResp struct {
|
||||
List []*TagResp `json:"list"`
|
||||
}
|
||||
|
||||
type TagResp struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func TagList(req *TagListReq) (resp TagListResp, err error) {
|
||||
var filter = bson.M{}
|
||||
switch req.Type {
|
||||
case "":
|
||||
filter = bson.M{}
|
||||
case "all":
|
||||
filter = bson.M{}
|
||||
default:
|
||||
filter = bson.M{"type": req.Type}
|
||||
}
|
||||
filter["isActive"] = true
|
||||
data, err := (&officialWebsitemod.Tag{}).FindMany(filter, options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "sort", Value: -1}, {Key: "createdAt", Value: -1}}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp = TagListResp{
|
||||
List: make([]*TagResp, 0),
|
||||
}
|
||||
for _, v := range data {
|
||||
resp.List = append(resp.List, &TagResp{
|
||||
ID: v.ID.Hex(),
|
||||
Name: v.Name,
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package officialWebsiteser
|
||||
|
||||
import (
|
||||
"91porn-server/common"
|
||||
"91porn-server/common/stderr"
|
||||
"91porn-server/models/v/officialWebsitemod"
|
||||
"91porn-server/models/v/vidmod"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type VideoListReq struct {
|
||||
Type int64 `json:"type" form:"type"` // 1: 全量,2:专辑ID,3:演员ID, 4: TagID
|
||||
ID string `json:"id" form:"id"` // 专辑ID或者演员ID,根据Type决定
|
||||
Sort int64 `json:"sort" form:"sort"` // 1:热度,2:创建时间,3: 播放量,4:点赞量,5:评论量,6:收藏量
|
||||
PageNumber int64 `json:"pageNumber" form:"pageNumber"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize"`
|
||||
}
|
||||
|
||||
type VideoListResp struct {
|
||||
HasNext bool `json:"hasNext"`
|
||||
List []*VideoResp `json:"list"`
|
||||
}
|
||||
|
||||
type VideoResp struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Cover string `json:"cover"`
|
||||
IsHot bool `json:"isHot"`
|
||||
Tags []VideoTagResp `json:"tags"`
|
||||
}
|
||||
|
||||
type VideoTagResp struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func VideoList(req *VideoListReq) (resp VideoListResp, err error) {
|
||||
var sort interface{}
|
||||
switch req.Sort {
|
||||
case 2:
|
||||
sort = bson.D{{Key: "createdAt", Value: -1}}
|
||||
case 3:
|
||||
sort = bson.D{{Key: "watchCount", Value: -1}}
|
||||
case 4:
|
||||
sort = bson.D{{Key: "likeCount", Value: -1}}
|
||||
case 5:
|
||||
sort = bson.D{{Key: "commentCount", Value: -1}}
|
||||
case 6:
|
||||
sort = bson.D{{Key: "collectCount", Value: -1}}
|
||||
default:
|
||||
sort = bson.D{{Key: "isHot", Value: -1}, {Key: "createdAt", Value: -1}}
|
||||
}
|
||||
var filter = bson.M{}
|
||||
objID, err := primitive.ObjectIDFromHex(req.ID)
|
||||
if err != nil && req.Type != 1 {
|
||||
err = stderr.ErrParamError
|
||||
return
|
||||
}
|
||||
switch req.Type {
|
||||
case 2:
|
||||
filter["albumId"] = objID
|
||||
case 3:
|
||||
filter["heroId"] = objID
|
||||
case 4:
|
||||
filter["tags._id"] = objID
|
||||
}
|
||||
filter["isActive"] = true
|
||||
|
||||
var skip, limit = transPageAndPageNumber(req.PageSize, req.PageNumber)
|
||||
var ops = options.Find().SetSort(sort).SetSkip(skip).SetLimit(limit + 1)
|
||||
videosData, err := (&officialWebsitemod.Video{}).FindMany(filter, ops)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp = VideoListResp{
|
||||
HasNext: len(videosData) > int(limit),
|
||||
List: make([]*VideoResp, 0),
|
||||
}
|
||||
for _, v := range videosData {
|
||||
var videoResp = &VideoResp{
|
||||
ID: v.ID.Hex(),
|
||||
Title: v.Title,
|
||||
SeoSlug: v.SeoSlug,
|
||||
Cover: v.Cover,
|
||||
IsHot: v.IsHot,
|
||||
Tags: make([]VideoTagResp, 0),
|
||||
}
|
||||
for _, tag := range v.Tags {
|
||||
videoResp.Tags = append(videoResp.Tags, VideoTagResp{
|
||||
ID: tag.ID.Hex(),
|
||||
Name: tag.Name,
|
||||
})
|
||||
}
|
||||
resp.List = append(resp.List, videoResp)
|
||||
}
|
||||
if resp.HasNext {
|
||||
resp.List = resp.List[:len(resp.List)-1]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type VideoDetailReq struct {
|
||||
ID string `uri:"id" binding:"required"`
|
||||
}
|
||||
|
||||
type VideoDetailResp struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
SeoSlug string `json:"seoSlug"`
|
||||
Description string `json:"description"`
|
||||
Cover string `json:"cover"`
|
||||
Url string `json:"url"`
|
||||
PlayTime uint `json:"playTime"` // 视频播放时长(秒)
|
||||
IsHot bool `json:"isHot"`
|
||||
Tags []VideoTagResp `json:"tags"`
|
||||
WatchCount int64 `json:"watchCount"`
|
||||
LikeCount int64 `json:"likeCount"`
|
||||
CommentCount int64 `json:"commentCount"`
|
||||
CollectCount int64 `json:"collectCount"`
|
||||
RelatedVideos []VideoResp `json:"relatedVideos"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
func VideoDetail(req *VideoDetailReq) (resp VideoDetailResp, err error) {
|
||||
// 兼容 id 与 seoSlug:24 位 hex 按 _id 查,否则按 seoSlug 查
|
||||
filter := bson.M{"isActive": true}
|
||||
if id, e := primitive.ObjectIDFromHex(req.ID); e == nil {
|
||||
filter["_id"] = id
|
||||
} else {
|
||||
filter["seoSlug"] = req.ID
|
||||
}
|
||||
video := &officialWebsitemod.Video{}
|
||||
err = video.FindOne(filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if video.ID == primitive.NilObjectID {
|
||||
err = stderr.OfficialWebsiteVideoNotExist
|
||||
return
|
||||
}
|
||||
|
||||
resp = VideoDetailResp{
|
||||
ID: video.ID.Hex(),
|
||||
Title: video.Title,
|
||||
SeoSlug: video.SeoSlug,
|
||||
Description: video.Description,
|
||||
Cover: video.Cover,
|
||||
Url: video.Url,
|
||||
IsHot: video.IsHot,
|
||||
Tags: make([]VideoTagResp, 0),
|
||||
WatchCount: video.WatchCount,
|
||||
LikeCount: video.LikeCount,
|
||||
CommentCount: video.CommentCount,
|
||||
CollectCount: video.CollectCount,
|
||||
CreatedAt: video.CreatedAt,
|
||||
}
|
||||
// 播放时长:官网视频复用了视频库(vidmod)的视频 ID,按 ID 反查视频库获取
|
||||
if vid, e := vidmod.GetVideoByID(video.ID); e == nil && vid != nil {
|
||||
resp.PlayTime = vid.PlayTime
|
||||
}
|
||||
for _, tag := range video.Tags {
|
||||
resp.Tags = append(resp.Tags, VideoTagResp{
|
||||
ID: tag.ID.Hex(),
|
||||
Name: tag.Name,
|
||||
})
|
||||
}
|
||||
|
||||
var tagsID = make([]primitive.ObjectID, 0)
|
||||
for _, tag := range video.Tags {
|
||||
tagsID = append(tagsID, tag.ID)
|
||||
}
|
||||
var videoTags []officialWebsitemod.Video
|
||||
var videoNormal []officialWebsitemod.Video
|
||||
var wg = &sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
common.Go(func() {
|
||||
defer wg.Done()
|
||||
if len(tagsID) == 0 {
|
||||
return
|
||||
}
|
||||
filterTags := bson.M{"tags.id": bson.M{"$in": tagsID}, "isActive": true}
|
||||
videoTags, _ = (&officialWebsitemod.Video{}).FindMany(filterTags,
|
||||
options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "createdAt", Value: -1}}).SetLimit(10))
|
||||
})
|
||||
common.Go(func() {
|
||||
defer wg.Done()
|
||||
filterNormal := bson.M{"isActive": true}
|
||||
videoNormal, _ = (&officialWebsitemod.Video{}).FindMany(filterNormal,
|
||||
options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "createdAt", Value: -1}}).SetLimit(10))
|
||||
})
|
||||
wg.Wait()
|
||||
|
||||
var relatedVideosData []officialWebsitemod.Video
|
||||
if len(videoTags) > 0 {
|
||||
relatedVideosData = videoTags
|
||||
} else {
|
||||
relatedVideosData = videoNormal
|
||||
}
|
||||
|
||||
resp.RelatedVideos = make([]VideoResp, 0)
|
||||
for _, v := range relatedVideosData {
|
||||
var videoResp = VideoResp{
|
||||
ID: v.ID.Hex(),
|
||||
Title: v.Title,
|
||||
SeoSlug: v.SeoSlug,
|
||||
Cover: v.Cover,
|
||||
IsHot: v.IsHot,
|
||||
Tags: make([]VideoTagResp, 0),
|
||||
}
|
||||
for _, tag := range v.Tags {
|
||||
videoResp.Tags = append(videoResp.Tags, VideoTagResp{
|
||||
ID: tag.ID.Hex(),
|
||||
Name: tag.Name,
|
||||
})
|
||||
}
|
||||
resp.RelatedVideos = append(resp.RelatedVideos, videoResp)
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user