Files
web_hgtv_h5/app/service/playletser/detail.go
T
谢宇宁andClaude Opus 5.5 3639d2184a Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 14:47:17 +07:00

134 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package playletser
import (
"fmt"
"net/url"
"strconv"
"strings"
"videoweb/app/service/authser"
"videoweb/app/service/upstream"
"videoweb/pub/common/log"
"github.com/gin-gonic/gin"
)
const (
detailPath = "/api/app/playlet/detail"
defaultEpisodeRange = 30
)
// EpisodeRange 剧集分段(仅 UI 分页展示,非接口字段映射)。
type EpisodeRange struct {
Start int
End int
Label string
}
// FetchDetail 根据短剧 ID 查询详情。
func FetchDetail(c *gin.Context, id int64) (*PlayletInfoResp, error) {
if id <= 0 {
return nil, fmt.Errorf("playlet detail invalid id")
}
return fetchDetail(c, "id", strconv.FormatInt(id, 10))
}
// FetchDetailByKey 优先按 slug 查询;纯数字路由段按 ID 查询。
func FetchDetailByKey(c *gin.Context, key string) (*PlayletInfoResp, error) {
key = strings.TrimSpace(key)
if key == "" {
return nil, fmt.Errorf("playlet detail missing route key")
}
if id := ParseDetailID(key); id > 0 {
return FetchDetail(c, id)
}
return fetchDetail(c, "slug", key)
}
func fetchDetail(c *gin.Context, queryKey, value string) (*PlayletInfoResp, error) {
authser.EnsureGuestOnEnter(c)
env, err := fetchDetailOnce(c, queryKey, value)
if err != nil {
return nil, err
}
if env.Code != 200 && authser.IsSessionExpiredCode(env.Code) {
if authser.RecoverContentSession(c, env.Code) {
env, err = fetchDetailOnce(c, queryKey, value)
if err != nil {
return nil, err
}
}
}
if env.Code != 200 {
return nil, fmt.Errorf("playlet detail code=%d msg=%s tip=%s", env.Code, env.Msg, env.Tip)
}
env.Data.SeoInfo.Normalize()
return &env.Data, nil
}
func fetchDetailOnce(c *gin.Context, queryKey, value string) (*APIEnvelope[PlayletInfoResp], error) {
params := url.Values{}
params.Set(queryKey, value)
var env APIEnvelope[PlayletInfoResp]
if err := upstream.GetJSON(c, detailPath+"?"+params.Encode(), &env); err != nil {
return nil, err
}
return &env, nil
}
// FetchDetailOrNilByKey 失败或无效时返回 nil。
func FetchDetailOrNilByKey(c *gin.Context, key string) *PlayletInfoResp {
data, err := FetchDetailByKey(c, key)
if err != nil {
log.Error("fetch playlet detail by route key failed", log.E(err))
return nil
}
if data == nil || data.ID <= 0 {
return nil
}
return data
}
// ParseDetailID 解析纯数字路由段。
func ParseDetailID(raw string) int64 {
id, err := strconv.ParseInt(strings.TrimSpace(raw), 10, 64)
if err != nil || id <= 0 {
return 0
}
return id
}
// BuildEpisodeRanges 按集数分段(默认每段 30 集)。
func BuildEpisodeRanges(chapters []PlayletChapterData, totalEpisode, size int) []EpisodeRange {
if size <= 0 {
size = defaultEpisodeRange
}
maxEp := 0
for _, ch := range chapters {
if ch.CurrentEpisode > maxEp {
maxEp = ch.CurrentEpisode
}
}
if totalEpisode > maxEp {
maxEp = totalEpisode
}
if maxEp <= 0 {
maxEp = len(chapters)
}
if maxEp <= 0 {
return nil
}
out := make([]EpisodeRange, 0, (maxEp+size-1)/size)
for start := 1; start <= maxEp; start += size {
end := start + size - 1
if end > maxEp {
end = maxEp
}
out = append(out, EpisodeRange{
Start: start,
End: end,
Label: fmt.Sprintf("%d–%d", start, end),
})
}
return out
}