Files
hadja_server/app/service/playletthemeser/theme.go
T
rootandClaude Opus 4.7 79ac89b458 Initial commit
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-11-07 10:47:18 +08:00

110 lines
2.9 KiB
Go

package playletthemeser
import (
"context"
"strings"
"videoweb/app/api/proto"
"videoweb/app/service/configser"
"videoweb/app/service/playletcache"
"videoweb/pub/common/netutil"
"videoweb/pub/common/srvdef"
"videoweb/pub/pubdef"
"videoweb/pub/seo/h5path"
)
// List 查询 app 端短剧题材列表(读题材缓存,含 SEO)
func List(ctx context.Context) (*proto.PlayletThemeListResponse, *srvdef.SrvErr) {
list := playletcache.ListEnabledThemes()
imgCdn := configser.GetAppImageCdn(configser.ClientIPFromCtx(ctx))
items := make([]*proto.PlayletThemeItem, 0, len(list))
for _, item := range list {
if item == nil {
continue
}
items = append(items, &proto.PlayletThemeItem{
Id: item.Id,
Name: item.Name,
Slug: item.Slug,
Icon: mergeThemeIcon(imgCdn, item.Icon),
Rank: item.Rank,
Status: item.Status,
IsRecommend: item.IsRecommend,
PlayletCount: item.PlayletCount,
SeoInfo: buildThemeSeoInfo(item),
})
}
return &proto.PlayletThemeListResponse{List: items}, nil
}
// buildThemeSeoInfo 将题材后台 SEO 转为页面 SeoInfo,缺失字段回退题材名/站点默认。
func buildThemeSeoInfo(item *playletcache.ThemeItem) *proto.SeoInfo {
seo := configser.GetSiteSeoInfo()
if item == nil {
return &seo
}
custom := normalizeThemeSeoValue(item.SeoInfo)
if title := strings.TrimSpace(custom.Title); title != "" {
seo.Title = title
} else if name := strings.TrimSpace(item.Name); name != "" {
seo.Title = name
}
if desc := strings.TrimSpace(custom.Description); desc != "" {
seo.Description = desc
}
if len(custom.Keyworld) > 0 {
seo.Keywords = append([]string{}, custom.Keyworld...)
}
pagePath := h5path.ListTheme(item.Slug, item.Id)
seo.CanonicalURL = joinCanonicalURL(seo.CanonicalURL, pagePath)
return &seo
}
func normalizeThemeSeoValue(seo pubdef.SeoValue) pubdef.SeoValue {
seo.Title = strings.TrimSpace(seo.Title)
seo.Description = strings.TrimSpace(seo.Description)
if seo.Keyworld == nil {
seo.Keyworld = make([]string, 0)
return seo
}
words := make([]string, 0, len(seo.Keyworld))
for _, word := range seo.Keyworld {
word = strings.TrimSpace(word)
if word == "" {
continue
}
words = append(words, word)
}
seo.Keyworld = words
return seo
}
func joinCanonicalURL(baseURL, pagePath string) string {
pagePath = strings.TrimSpace(pagePath)
if pagePath == "" {
return strings.TrimSpace(baseURL)
}
if !strings.HasPrefix(pagePath, "/") {
pagePath = "/" + pagePath
}
baseURL = strings.TrimSpace(baseURL)
if baseURL == "" {
return pagePath
}
return strings.TrimRight(baseURL, "/") + pagePath
}
// mergeThemeIcon 给题材图标拼接图片域名
func mergeThemeIcon(imgCdn string, icon string) string {
icon = strings.TrimSpace(icon)
if icon == "" {
return ""
}
if strings.HasPrefix(icon, "http://") || strings.HasPrefix(icon, "https://") {
return icon
}
if imgCdn == "" {
return icon
}
return netutil.MergeURL(imgCdn, icon)
}