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 }