230 lines
6.7 KiB
Go
230 lines
6.7 KiB
Go
package web
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
"videoweb/app/service/authser"
|
|
"videoweb/app/service/playletser"
|
|
"videoweb/app/service/usercenterser"
|
|
"videoweb/pub/common/log"
|
|
"videoweb/pub/common/useragent"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type profileWork struct {
|
|
Title, Meta, Episodes, Badge, Image, Progress, Remaining, URL string
|
|
}
|
|
|
|
// Profile 从当前会话拉取用户信息、观看历史和收藏,不展示演示账号数据。
|
|
func Profile(c *gin.Context) {
|
|
data := gin.H{
|
|
"title": "个人中心 - 黄果短剧", "navActive": "profile", "accountTab": "profile",
|
|
}
|
|
responses := gin.H{}
|
|
loadAccountSummary(c, data, responses)
|
|
if useragent.TokenFromRequest(c.Request) != "" {
|
|
fetchProfileLists(c, data, responses)
|
|
}
|
|
if pretty, err := json.MarshalIndent(responses, "", " "); err == nil {
|
|
data["responseJSON"] = string(pretty)
|
|
}
|
|
HTMLOK(c, "profile.html", data)
|
|
}
|
|
|
|
func loadAccountSummary(c *gin.Context, data, responses gin.H) {
|
|
data["userName"] = "未登录"
|
|
data["balance"] = "—"
|
|
data["historyCount"] = "—"
|
|
data["favoriteCount"] = "—"
|
|
data["chasingCount"] = "—"
|
|
data["boughtChapterCount"] = "—"
|
|
user := authser.SyncUserOnEnter(c)
|
|
if user == nil {
|
|
if useragent.TokenFromRequest(c.Request) != "" {
|
|
responses["auth/getInfo"] = gin.H{"error": "加载失败"}
|
|
fetchProfileStats(c, data, responses)
|
|
return
|
|
}
|
|
responses["auth/getInfo"] = gin.H{"error": "暂无登录会话"}
|
|
return
|
|
}
|
|
applyProfileInfo(data, responses, user)
|
|
if useragent.TokenFromRequest(c.Request) != "" {
|
|
fetchProfileStats(c, data, responses)
|
|
}
|
|
}
|
|
|
|
func fetchProfileStats(c *gin.Context, data, responses gin.H) {
|
|
stats, code, err := usercenterser.Fetch(c)
|
|
if retry, _ := authser.OnSessionExpired(c, code); retry {
|
|
stats, code, err = usercenterser.Fetch(c)
|
|
}
|
|
if err != nil || stats == nil {
|
|
responses["user/center/data"] = gin.H{"error": "加载失败"}
|
|
if err != nil {
|
|
log.Error("fetch user center data failed", log.E(err))
|
|
}
|
|
return
|
|
}
|
|
responses["user/center/data"] = gin.H{"code": code, "data": stats}
|
|
data["historyCount"] = fmt.Sprint(stats.WatchCount)
|
|
data["favoriteCount"] = fmt.Sprint(stats.CollectCount)
|
|
data["chasingCount"] = fmt.Sprint(stats.ChasingCount)
|
|
data["boughtChapterCount"] = fmt.Sprint(stats.BoughtChapterCount)
|
|
}
|
|
|
|
func fetchProfileLists(c *gin.Context, data, responses gin.H) {
|
|
query := playletser.HistoryListQuery{PageNum: 1, PageSize: 6}
|
|
history, code, err := playletser.FetchHistoryList(c, query)
|
|
if retry, _ := authser.OnSessionExpired(c, code); retry {
|
|
history, _, err = playletser.FetchHistoryList(c, query)
|
|
}
|
|
if err == nil && history != nil {
|
|
responses["playlet/history/list"] = gin.H{"code": 200, "data": history}
|
|
data["history"] = profileHistoryWorks(history.List)
|
|
} else if err != nil {
|
|
responses["playlet/history/list"] = gin.H{"error": "加载失败"}
|
|
log.Error("fetch profile history failed", log.E(err))
|
|
data["historyUnavailable"] = true
|
|
}
|
|
|
|
collectQuery := playletser.CollectListQuery{PageNum: 1, PageSize: 6, WatchStatus: 0}
|
|
favorites, code, err := playletser.FetchCollectList(c, collectQuery)
|
|
if retry, _ := authser.OnSessionExpired(c, code); retry {
|
|
favorites, _, err = playletser.FetchCollectList(c, collectQuery)
|
|
}
|
|
if err == nil && favorites != nil {
|
|
responses["playlet/collect/list"] = gin.H{"code": 200, "data": favorites}
|
|
data["favorites"] = profileFavoriteWorks(favorites.List)
|
|
} else if err != nil {
|
|
responses["playlet/collect/list"] = gin.H{"error": "加载失败"}
|
|
log.Error("fetch profile favorites failed", log.E(err))
|
|
data["favoritesUnavailable"] = true
|
|
}
|
|
}
|
|
|
|
func applyProfileInfo(data, responses gin.H, user *authser.LoginResp) {
|
|
if user == nil {
|
|
return
|
|
}
|
|
// 登录响应可能包含 token;调试区域只展示非凭证字段。
|
|
rawUser, _ := json.Marshal(user)
|
|
var safeUser map[string]any
|
|
_ = json.Unmarshal(rawUser, &safeUser)
|
|
delete(safeUser, "token")
|
|
responses["auth/getInfo"] = gin.H{"code": 200, "data": safeUser}
|
|
name := strings.TrimSpace(user.NickName)
|
|
if name == "" {
|
|
name = strings.TrimSpace(user.AccountNo)
|
|
}
|
|
if name == "" {
|
|
name = "用户"
|
|
}
|
|
data["userName"] = name
|
|
data["setting"] = authser.BuildSettingVM(user)
|
|
data["userID"] = user.UserID
|
|
data["userId"] = fmt.Sprint(user.UserID)
|
|
data["balance"] = fmt.Sprint(user.Recharge)
|
|
data["recharge"] = user.Recharge
|
|
data["rechargeText"] = authser.FormatRecharge(user.Recharge)
|
|
if avatar := safeProfileImage(user.Avatar); avatar != "" {
|
|
data["avatar"] = avatar
|
|
}
|
|
}
|
|
|
|
func safeProfileImage(raw string) string {
|
|
raw = strings.TrimSpace(raw)
|
|
if strings.HasPrefix(raw, "/static/") {
|
|
return raw
|
|
}
|
|
u, err := url.Parse(raw)
|
|
if err == nil && (u.Scheme == "https" || u.Scheme == "http") && u.Host != "" {
|
|
return raw
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func profileHistoryWorks(items []playletser.PlayletHistoryData) []profileWork {
|
|
works := make([]profileWork, 0, len(items))
|
|
for _, item := range items {
|
|
if len(works) == 6 {
|
|
break
|
|
}
|
|
name := strings.TrimSpace(item.Title)
|
|
if name == "" {
|
|
name = strings.TrimSpace(item.PlayName)
|
|
}
|
|
if name == "" {
|
|
continue
|
|
}
|
|
progress := 0
|
|
if item.TotalEpisode > 0 {
|
|
progress = item.WatchedCount * 100 / item.TotalEpisode
|
|
}
|
|
if progress < 0 {
|
|
progress = 0
|
|
}
|
|
if progress > 100 {
|
|
progress = 100
|
|
}
|
|
meta := "观看记录"
|
|
if item.LastEpisode > 0 {
|
|
meta = fmt.Sprintf("看至第 %d 集", item.LastEpisode)
|
|
}
|
|
remaining := ""
|
|
if item.UnwatchedCount > 0 {
|
|
remaining = fmt.Sprintf("剩 %d 集", item.UnwatchedCount)
|
|
}
|
|
works = append(works, profileWork{Title: name, Meta: meta, Image: profileCover(item.Cover), Progress: fmt.Sprintf("%d%%", progress), Remaining: remaining, URL: profilePlayURL(item.Slug, item.ID, item.LastEpisode)})
|
|
}
|
|
return works
|
|
}
|
|
|
|
func profileFavoriteWorks(items []playletser.PlayletCollectData) []profileWork {
|
|
works := make([]profileWork, 0, len(items))
|
|
for _, item := range items {
|
|
if len(works) == 6 {
|
|
break
|
|
}
|
|
name := strings.TrimSpace(item.Title)
|
|
if name == "" {
|
|
name = strings.TrimSpace(item.PlayName)
|
|
}
|
|
if name == "" {
|
|
continue
|
|
}
|
|
work := profileWork{Title: name, Meta: strings.Join(item.ThemeNames, " "), Image: profileCover(item.Cover), URL: profilePlayURL(item.Slug, item.ID, 1)}
|
|
if item.TotalEpisode > 0 {
|
|
work.Episodes = fmt.Sprintf("全 %d 集", item.TotalEpisode)
|
|
}
|
|
if item.IsFeatured {
|
|
work.Badge = "爆剧"
|
|
}
|
|
works = append(works, work)
|
|
}
|
|
return works
|
|
}
|
|
|
|
func profileCover(raw string) string {
|
|
if safe := safeProfileImage(raw); safe != "" {
|
|
return safe
|
|
}
|
|
return "/static/images/placeholder.png?v=2"
|
|
}
|
|
|
|
func profilePlayURL(slug string, id int64, episode int) string {
|
|
if slug == "" {
|
|
if id <= 0 {
|
|
return ""
|
|
}
|
|
slug = fmt.Sprint(id)
|
|
}
|
|
if episode < 1 {
|
|
episode = 1
|
|
}
|
|
return "/play/" + url.PathEscape(slug) + "/" + fmt.Sprint(episode)
|
|
}
|