Initial commit: web_hghl_server
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package homeser
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/redis"
|
||||
)
|
||||
|
||||
const (
|
||||
appHomeCacheKey = "app:home:data"
|
||||
appHomeCacheTTL = time.Minute * 5
|
||||
)
|
||||
|
||||
// getHomeDataCache 读取 APP 首页 Redis 缓存,缓存异常时降级查库
|
||||
func getHomeDataCache() *proto.DataResp {
|
||||
cacheData, err1 := redis.Get(appHomeCacheKey)
|
||||
if err1 != nil {
|
||||
log.Warn("读取APP首页缓存失败", log.Any("cacheKey", appHomeCacheKey), log.E(err1))
|
||||
return nil
|
||||
}
|
||||
if cacheData == nil || *cacheData == "" {
|
||||
return nil
|
||||
}
|
||||
resp := &proto.DataResp{}
|
||||
if err1 := json.Unmarshal([]byte(*cacheData), resp); err1 != nil {
|
||||
log.Warn("解析APP首页缓存失败", log.Any("cacheKey", appHomeCacheKey), log.E(err1))
|
||||
return nil
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
// setHomeDataCache 写入 APP 首页 Redis 缓存,缓存异常不影响主流程
|
||||
func setHomeDataCache(resp proto.DataResp) {
|
||||
bytes, err1 := json.Marshal(resp)
|
||||
if err1 != nil {
|
||||
log.Warn("序列化APP首页缓存失败", log.Any("cacheKey", appHomeCacheKey), log.E(err1))
|
||||
return
|
||||
}
|
||||
if err1 := redis.Set(appHomeCacheKey, string(bytes), appHomeCacheTTL); err1 != nil {
|
||||
log.Warn("写入APP首页缓存失败", log.Any("cacheKey", appHomeCacheKey), log.E(err1))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package homeser
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/app/service/actressser"
|
||||
"videoweb/app/service/configser"
|
||||
"videoweb/app/service/playletser"
|
||||
"videoweb/app/service/translationser"
|
||||
"videoweb/app/service/videoser"
|
||||
"videoweb/pub/common/netutil"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/models/homebannermod"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
const homeBannerListLimit int64 = 30
|
||||
|
||||
var homeBannerAppProjection = bson.D{
|
||||
{Key: homebannermod.FN.HomeBanner.Id, Value: 1},
|
||||
{Key: homebannermod.FN.HomeBanner.Name, Value: 1},
|
||||
{Key: homebannermod.FN.HomeBanner.Image, Value: 1},
|
||||
{Key: homebannermod.FN.HomeBanner.VerticalImage, Value: 1},
|
||||
{Key: homebannermod.FN.HomeBanner.Url, Value: 1},
|
||||
{Key: homebannermod.FN.HomeBanner.Rank, Value: 1},
|
||||
{Key: homebannermod.FN.HomeBanner.Status, Value: 1},
|
||||
}
|
||||
|
||||
// HomeData 获取首页数据,包含公共配置、公告、广告和各业务首页数据
|
||||
func HomeData(ctx context.Context) (proto.DataResp, *srvdef.SrvErr) {
|
||||
if cacheData := getHomeDataCache(); cacheData != nil {
|
||||
configser.RewriteImageCdn(ctx, cacheData)
|
||||
return *cacheData, nil
|
||||
}
|
||||
// 数据组装
|
||||
config := configser.GetConfigInfo()
|
||||
data := proto.DataResp{
|
||||
Path: homeRequestPath(ctx),
|
||||
Config: config,
|
||||
Advitise: configser.GetAdvitise(),
|
||||
Announcement: configser.GetAnnouncement(),
|
||||
HomeBannerList: make([]proto.HomeBannerInfo, 0),
|
||||
PlayletData: proto.HomePlayletDataResp{
|
||||
RecommendList: make([]proto.PlayletData, 0),
|
||||
NewestList: make([]proto.PlayletData, 0),
|
||||
HotList: make([]proto.PlayletData, 0),
|
||||
},
|
||||
VideoData: proto.HomeVideoDataResp{
|
||||
RecommendList: make([]proto.VideoInfo, 0),
|
||||
NewestList: make([]proto.VideoInfo, 0),
|
||||
HotList: make([]proto.VideoInfo, 0),
|
||||
},
|
||||
ActressInfoList: make([]proto.ActressInfo, 0),
|
||||
}
|
||||
// 并分查询
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
var err1 *srvdef.SrvErr
|
||||
setErr := func(err *srvdef.SrvErr) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if err1 == nil {
|
||||
err1 = err
|
||||
}
|
||||
}
|
||||
wg.Add(4)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
list, err := HomeBannerList(ctx, config.ImgCdn)
|
||||
if err != nil {
|
||||
setErr(err)
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
data.HomeBannerList = list
|
||||
mu.Unlock()
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
playletData, err := playletser.HomePlayletData(ctx, config.ImgCdn)
|
||||
if err != nil {
|
||||
setErr(err)
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
data.PlayletData = playletData
|
||||
mu.Unlock()
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
videoData, err := videoser.HomeVideoDataForHome(ctx, config.ImgCdn)
|
||||
if err != nil {
|
||||
setErr(err)
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
data.VideoData = videoData
|
||||
mu.Unlock()
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
list, err := actressser.HomeActressData(ctx)
|
||||
if err != nil {
|
||||
setErr(err)
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
data.ActressInfoList = list
|
||||
mu.Unlock()
|
||||
}()
|
||||
wg.Wait()
|
||||
if err1 != nil {
|
||||
return data, err1
|
||||
}
|
||||
setHomeDataCache(data)
|
||||
configser.RewriteImageCdn(ctx, &data)
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// HomeBannerList 查询启用的首页banner信息列表
|
||||
func HomeBannerList(ctx context.Context, imgCdn string) ([]proto.HomeBannerInfo, *srvdef.SrvErr) {
|
||||
list, err := homebannermod.FindManyHomeBanner(ctx, bson.M{
|
||||
homebannermod.FN.HomeBanner.Status: true,
|
||||
}, options.Find().
|
||||
SetProjection(homeBannerAppProjection).
|
||||
SetSort(bson.D{
|
||||
{Key: homebannermod.FN.HomeBanner.Rank, Value: -1},
|
||||
{Key: homebannermod.FN.HomeBanner.CreatedAt, Value: -1},
|
||||
{Key: homebannermod.FN.HomeBanner.Id, Value: -1},
|
||||
}).
|
||||
SetLimit(homeBannerListLimit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]proto.HomeBannerInfo, 0, len(list))
|
||||
for _, item := range list {
|
||||
if item == nil {
|
||||
continue
|
||||
}
|
||||
result = append(result, proto.HomeBannerInfo{
|
||||
Id: item.Id,
|
||||
Name: item.Name,
|
||||
Image: netutil.MergeURL(imgCdn, item.Image),
|
||||
VerticalImage: netutil.MergeURL(imgCdn, item.VerticalImage),
|
||||
Url: item.Url,
|
||||
Rank: item.Rank,
|
||||
Status: item.Status,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// HomeBaseData 获取首页公共配置数据
|
||||
func HomeBaseData(ctx context.Context) proto.HomeBaseResp {
|
||||
resp := proto.HomeBaseResp{
|
||||
Translations: translationser.GetTranslationData(),
|
||||
Config: configser.GetRequestConfig(ctx),
|
||||
BottonTranslations: translationser.GetTranslationBottomList(),
|
||||
Advitise: configser.GetAdvitise(),
|
||||
Announcement: configser.GetAnnouncement(),
|
||||
}
|
||||
configser.RewriteImageCdn(ctx, &resp)
|
||||
return resp
|
||||
}
|
||||
|
||||
// HomeTagsData 获取首页标签数据
|
||||
func HomeTagsData(ctx context.Context) proto.HomeTagsResp {
|
||||
resp := proto.HomeTagsResp{
|
||||
HomeBaseResp: HomeBaseData(ctx),
|
||||
VideoTagsList: configser.GetHomeVideoTagList(),
|
||||
PlayletTagsList: configser.GetHomePlayletTagList(),
|
||||
}
|
||||
configser.RewriteImageCdn(ctx, &resp)
|
||||
return resp
|
||||
}
|
||||
|
||||
// homeRequestPath 从 gin 上下文中提取当前请求路径,避免 API 层重复组装首页响应字段
|
||||
func homeRequestPath(ctx context.Context) string {
|
||||
ginCtx, ok := ctx.(*gin.Context)
|
||||
if !ok || ginCtx.Request == nil || ginCtx.Request.URL == nil {
|
||||
return ""
|
||||
}
|
||||
return ginCtx.Request.URL.Path
|
||||
}
|
||||
Reference in New Issue
Block a user