Files
web_huangguo2_h5/app/api/web/profile.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

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)
}