Files
web_huangguo2_h5/app/api/web/favorites.go
T
谢宇宁andClaude Opus 5.5 0fbdba5ccf Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:47:47 +07:00

339 lines
10 KiB
Go

package web
import (
"fmt"
"strconv"
"strings"
"videoweb/app/service/authser"
"videoweb/app/service/playletser"
"videoweb/app/service/videoser"
"videoweb/pub/common/log"
"videoweb/pub/common/useragent"
"github.com/gin-gonic/gin"
)
type favoriteWork struct {
ID int64
Title string
Genre string
DesktopMeta string
Episodes string
Badge string
Image string
Kind string
URL string
DramaID int64
Episode int
VideoID int64
TotalEpisode int
}
// Favorites 我的收藏:短剧 / 剧集(视频) / 章节收藏。
// 文档:
// http://172.104.181.99:25319/swagger/index.html#/app短剧相关接口/get_api_app_playlet_collect_list
// http://172.104.181.99:25319/swagger/index.html#/视频相关接口/get_api_app_video_collect_list
func Favorites(c *gin.Context) {
filter, page, validRoute := favoritesRoute(c)
if !validRoute {
NotFound(c)
return
}
data := gin.H{"title": "我的收藏 - 黄果短剧", "navActive": "favorites", "accountTab": "favorites"}
responses := gin.H{}
loadAccountSummary(c, data, responses)
status := 0
switch filter {
case "short", "chapter", "series":
case "following":
status = 1
case "finished":
status = 2
default:
filter = "all"
}
data["filter"] = filter
pageSize := 12
query := playletser.CollectListQuery{PageNum: page, PageSize: pageSize, WatchStatus: status}
if useragent.TokenFromRequest(c.Request) == "" {
responses["playlet/collect/list"] = gin.H{"error": "暂无登录会话"}
responses["video/collect/list"] = gin.H{"error": "暂无登录会话"}
data["favoritesResponse"] = responses["playlet/collect/list"]
data["playletCollectResponse"] = responses["playlet/collect/list"]
data["videoCollectResponse"] = responses["video/collect/list"]
data["favoritesDebug"] = responses
renderFavorites(c, data)
return
}
if filter == "chapter" {
list, code, err := playletser.FetchChapterCollectList(c, query)
if retry, _ := authser.OnSessionExpired(c, code); retry {
list, _, err = playletser.FetchChapterCollectList(c, query)
}
if err != nil {
log.Error("fetch chapter favorites page failed", log.E(err))
responses["playlet/chapter/collect/list"] = gin.H{"error": "加载失败", "msg": err.Error()}
data["favoritesUnavailable"] = true
} else if list != nil {
responses["playlet/chapter/collect/list"] = gin.H{"code": 200, "data": list}
data["paging"] = makeFavoritesPage(query.PageNum, query.PageSize, list.TotalCount, filter)
data["favorites"] = chapterFavoriteWorks(list.List)
} else {
responses["playlet/chapter/collect/list"] = gin.H{"code": code, "data": list}
}
data["favoritesResponse"] = responses["playlet/chapter/collect/list"]
data["playletCollectResponse"] = responses["playlet/chapter/collect/list"]
data["favoritesDebug"] = responses
renderFavorites(c, data)
return
}
if filter == "series" {
loadVideoFavorites(c, data, responses, page, pageSize)
data["favoritesResponse"] = responses["video/collect/list"]
data["playletCollectResponse"] = gin.H{}
data["videoCollectResponse"] = responses["video/collect/list"]
data["favoritesDebug"] = responses
renderFavorites(c, data)
return
}
var works []favoriteWork
var totalCount int64
playletFailed := false
videoFailed := false
if filter == "all" || filter == "short" || filter == "following" || filter == "finished" {
list, code, err := playletser.FetchCollectList(c, query)
if retry, _ := authser.OnSessionExpired(c, code); retry {
list, code, err = playletser.FetchCollectList(c, query)
}
if err == nil && list != nil {
responses["playlet/collect/list"] = gin.H{"code": 200, "data": list}
works = append(works, playletFavoriteWorks(list.List)...)
totalCount += list.TotalCount
} else if err != nil {
responses["playlet/collect/list"] = gin.H{"error": "加载失败", "msg": err.Error()}
log.Error("fetch favorites page failed", log.E(err))
playletFailed = true
} else {
responses["playlet/collect/list"] = gin.H{"code": code, "data": list}
}
}
if filter == "all" {
videoQuery := videoser.CollectListQuery{PageNum: page, PageSize: pageSize}
videoList, videoCode, videoErr := videoser.FetchCollectList(c, videoQuery)
if retry, _ := authser.OnSessionExpired(c, videoCode); retry {
videoList, videoCode, videoErr = videoser.FetchCollectList(c, videoQuery)
}
if videoErr == nil && videoList != nil {
responses["video/collect/list"] = gin.H{"code": 200, "data": videoList}
works = append(works, videoFavoriteWorks(videoList.List)...)
totalCount += videoList.TotalCount
} else if videoErr != nil {
responses["video/collect/list"] = gin.H{"error": "加载失败", "msg": videoErr.Error()}
log.Error("fetch video favorites page failed", log.E(videoErr))
videoFailed = true
} else {
responses["video/collect/list"] = gin.H{"code": videoCode, "data": videoList}
}
}
if playletFailed && (filter != "all" || videoFailed) {
data["favoritesUnavailable"] = true
}
if filter == "all" && playletFailed && videoFailed {
data["favoritesUnavailable"] = true
}
data["paging"] = makeFavoritesPage(page, pageSize, totalCount, filter)
data["favorites"] = works
data["favoritesResponse"] = responses["playlet/collect/list"]
data["playletCollectResponse"] = responses["playlet/collect/list"]
data["videoCollectResponse"] = responses["video/collect/list"]
data["favoritesDebug"] = responses
renderFavorites(c, data)
}
// renderFavorites 收藏为空时附带「大家都在看」后渲染。
func renderFavorites(c *gin.Context, data gin.H) {
attachFavoritesRecommended(c, data)
HTMLOK(c, "favorites.html", data)
}
// attachFavoritesRecommended 列表为空时拉取最热短剧(与搜索无结果一致)。
// 上游:GET /api/app/playlet/all/list sortType=2
func attachFavoritesRecommended(c *gin.Context, data gin.H) {
if works, ok := data["favorites"].([]favoriteWork); ok && len(works) > 0 {
return
}
watchingQ := playletser.AllListQuery{
PageNum: 1,
PageSize: 6,
SortType: 2, // 最热
UpdateStatus: 0,
}
watching := playletser.FetchAllListOrEmpty(c, watchingQ)
if watching == nil || len(watching.List) == 0 {
return
}
list := watching.List
if len(list) > 6 {
list = list[:6]
}
data["recommended"] = list
}
func loadVideoFavorites(c *gin.Context, data gin.H, responses gin.H, page, pageSize int) {
videoQuery := videoser.CollectListQuery{PageNum: page, PageSize: pageSize}
list, code, err := videoser.FetchCollectList(c, videoQuery)
if retry, _ := authser.OnSessionExpired(c, code); retry {
list, code, err = videoser.FetchCollectList(c, videoQuery)
}
if err != nil {
log.Error("fetch video favorites page failed", log.E(err))
responses["video/collect/list"] = gin.H{"error": "加载失败", "msg": err.Error()}
data["favoritesUnavailable"] = true
return
}
if list == nil {
responses["video/collect/list"] = gin.H{"code": code, "data": list}
return
}
responses["video/collect/list"] = gin.H{"code": 200, "data": list}
data["paging"] = makeFavoritesPage(page, pageSize, list.TotalCount, "series")
data["favorites"] = videoFavoriteWorks(list.List)
}
func favoritesRoute(c *gin.Context) (filter string, page int, valid bool) {
if c.Request.URL.Query().Has("filter") {
return "", 0, false
}
filter = strings.TrimSpace(c.Param("filter"))
switch filter {
case "":
filter = "all"
case "short", "chapter", "series", "following", "finished":
default:
return "", 0, false
}
page, valid = accountPageNum(c)
if !valid {
return "", 0, false
}
return filter, page, true
}
func favoritesPagePath(filter string, page int) string {
path := "/favorites"
if filter != "" && filter != "all" {
path += "/" + filter
}
if page > 1 {
path += "/page/" + strconv.Itoa(page)
}
return path
}
func makeFavoritesPage(page, size int, count int64, filter string) accountPage {
total := int((count + int64(size) - 1) / int64(size))
pagination := accountPage{Current: page, Total: total, Count: count}
if page > 1 {
pagination.PrevURL = favoritesPagePath(filter, page-1)
}
if page < total {
pagination.NextURL = favoritesPagePath(filter, page+1)
}
return pagination
}
func playletFavoriteWorks(items []playletser.PlayletCollectData) []favoriteWork {
works := make([]favoriteWork, 0, len(items))
for _, item := range items {
title := strings.TrimSpace(item.PlayName)
if title == "" {
title = strings.TrimSpace(item.Title)
}
if title == "" {
continue
}
work := favoriteWork{
ID: item.ID, Title: title, Genre: strings.Join(item.ThemeNames, " "),
Image: profileCover(item.Cover), Kind: "short",
URL: playletser.ChapterPlayPath(item.Slug, item.ID, item.LastChapterID),
DramaID: item.ID, Episode: item.LastEpisode, VideoID: item.LastChapterID,
TotalEpisode: item.TotalEpisode,
}
if work.Episode <= 0 {
work.Episode = 1
}
if item.TotalEpisode > 0 {
work.Episodes = fmt.Sprintf("全 %d 集", item.TotalEpisode)
work.DesktopMeta = work.Episodes
}
if item.IsFeatured {
work.Badge = "爆剧"
}
works = append(works, work)
}
return works
}
func chapterFavoriteWorks(items []playletser.PlayletChapterCollectData) []favoriteWork {
works := make([]favoriteWork, 0, len(items))
for _, item := range items {
title := strings.TrimSpace(item.PlayletTitle)
if title == "" {
continue
}
work := favoriteWork{
ID: item.ChapterID, Title: title, Image: profileCover(item.PlayletCover), Kind: "chapter",
URL: playletser.ChapterPlayPath(item.PlayletSlug, item.PlayletID, item.ChapterID), DesktopMeta: item.ChapterTitle,
DramaID: item.PlayletID, Episode: item.CurrentEpisode, VideoID: item.ChapterID,
TotalEpisode: item.TotalEpisode,
}
if work.Episode <= 0 {
work.Episode = 1
}
if item.CurrentEpisode > 0 {
work.Genre = fmt.Sprintf("第 %d 集", item.CurrentEpisode)
}
if item.TotalEpisode > 0 {
work.Episodes = fmt.Sprintf("全 %d 集", item.TotalEpisode)
}
works = append(works, work)
}
return works
}
func videoFavoriteWorks(items []videoser.VideoCollectData) []favoriteWork {
works := make([]favoriteWork, 0, len(items))
for _, item := range items {
title := strings.TrimSpace(item.Title)
if title == "" {
continue
}
work := favoriteWork{
ID: item.ID, Title: title, Genre: strings.Join(item.Keyworld, " "),
Image: profileCover(item.CoverImg), Kind: "series",
URL: videoser.VideoPlayURL(item.Slug, item.ID),
}
if item.VideoTime > 0 {
work.Episodes = formatVideoDuration(item.VideoTime)
work.DesktopMeta = work.Episodes
} else {
work.Episodes = "剧集"
work.DesktopMeta = "剧集"
}
works = append(works, work)
}
return works
}