topfans/backend/gateway/dto/response_dto.go
zerosaturation 27313f414a feat(profile): render level progress bar in LV box
profile.vue only rendered fan level digit, hiding the fact that
fans level up via accumulated exhibition hours (6h/level, cap 20),
not login/task experience. Users saw "LV X" without "X more
hours to next level", so upgrades felt invisible.

- backend: surface exhibition_hours / next_level_hours on
  CurrentIdentityDTO via a new loadLevelProgress helper in
  user_controller (read-only, no proto regen, no service
  surface change). Full-level responses set next_level_hours =
  exhibition_hours so the client can derive progress=1.
- frontend: split level-box into base track + gold fill + text
  overlay; width bound to progressRatio with 0.4s transition.
  Adds "距 LV X+1 还差 N 小时" hint and MAX indicator for
  full-level users.
2026-07-27 18:02:59 +08:00

139 lines
5.5 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 dto
// ========== 基础结构 ==========
// FanIdentityDTO 粉丝身份信息
type FanIdentityDTO struct {
StarID int64 `json:"star_id"` // 明星ID
IdentityID string `json:"identity_id"` // stars.identity_id如"wyb"
Name string `json:"name"` // stars.name原始名称如"王一博"
Tag string `json:"tag"` // stars.tag昵称标签如"小摩托"
}
// CurrentIdentityDTO 当前身份详情
type CurrentIdentityDTO struct {
StarId int64 `json:"star_id"` // 明星ID
IdentityID string `json:"identity_id"` // "wyb"
IdentityName string `json:"identity_name"` // "王一博"
Tag string `json:"tag"` // "小摩托"
Level int32 `json:"level"`
CrystalBalance int64 `json:"crystal_balance"`
// 升级进度:累计上架时长(实时)与下一级所需小时数
// 满级(>= GetLevelCap时 NextLevelHours = ExhibitionHours 表示已达 100%
ExhibitionHours int64 `json:"exhibition_hours"`
NextLevelHours int64 `json:"next_level_hours"`
}
// ========== 用户信息 ==========
// UserWithIdentityDTO 用户信息(含身份)
type UserWithIdentityDTO struct {
UID int64 `json:"uid"` // 使用 uid值为数据库ID
Nickname string `json:"nickname"`
AvatarURL string `json:"avatar_url,omitempty"`
ChainAddress string `json:"chain_address,omitempty"`
FanIdentity FanIdentityDTO `json:"fan_identity"`
FanLevel int32 `json:"fan_level"`
StarbookLimit int32 `json:"starbook_limit"`
SlotLimit int32 `json:"slot_limit"`
AssetsNum int32 `json:"assets_num"` // assets_count
CrystalBalance int64 `json:"crystal_balance"`
MobileMasked string `json:"mobile_masked,omitempty"` // 脱敏手机号,如 139****0001
}
// ========== 认证相关响应 ==========
// RegisterResponseDTO 注册响应
type RegisterResponseDTO struct {
AccessToken string `json:"access_token"`
ExpiresIn int64 `json:"expires_in"`
User UserWithIdentityDTO `json:"user"`
}
// LoginResponseDTO 登录响应
type LoginResponseDTO struct {
AccessToken string `json:"access_token"`
ExpiresIn int64 `json:"expires_in"`
RefreshToken string `json:"refresh_token,omitempty"`
User UserWithIdentityDTO `json:"user"`
}
// GetMeResponseDTO 获取当前用户响应
type GetMeResponseDTO struct {
UID int64 `json:"uid"`
Nickname string `json:"nickname"`
AvatarURL string `json:"avatar_url,omitempty"`
ChainAddress string `json:"chain_address,omitempty"`
Mobile string `json:"mobile,omitempty"` // 脱敏手机号,如 139****0001
CurrentIdentity CurrentIdentityDTO `json:"current_identity"`
}
// ========== 个人信息相关响应 ==========
// ProfileResponseDTO 个人信息页响应
type ProfileResponseDTO struct {
UID int64 `json:"uid"`
Nickname string `json:"nickname"`
ChainAddress string `json:"chain_address,omitempty"`
FanIdentity FanIdentityDTO `json:"fan_identity"`
FanLevel int32 `json:"fan_level"`
StarbookLimit int32 `json:"starbook_limit"`
SlotLimit int32 `json:"slot_limit"`
AssetsNum int32 `json:"assets_num"`
CrystalBalance int64 `json:"crystal_balance"`
}
// UpdateNicknameResponseDTO 更新昵称响应
type UpdateNicknameResponseDTO struct {
Nickname string `json:"nickname"`
}
// ========== 粉丝身份相关响应 ==========
// FanIdentityListItemDTO 粉丝身份列表项
type FanIdentityListItemDTO struct {
StarID int64 `json:"star_id"` // 88star 的主键 ID用于切换身份
IdentityID string `json:"identity_id"` // "wyb"
Name string `json:"name"` // "王一博"
Tag string `json:"tag"` // "小摩托"
PicURL string `json:"pic_url,omitempty"`
}
// FanIdentityListResponseDTO 粉丝身份列表响应(所有可用明星)
type FanIdentityListResponseDTO struct {
Items []FanIdentityListItemDTO `json:"items"`
Total int `json:"total"`
}
// MyFanIdentityItemDTO 我的粉丝身份项
type MyFanIdentityItemDTO struct {
StarID int64 `json:"star_id"` // 明星ID
IdentityID string `json:"identity_id"` // 身份ID如 "xz"
StarName string `json:"star_name"` // 明星名称
StarTag string `json:"star_tag"` // 明星标签
Nickname string `json:"nickname"` // 用户昵称
Level int32 `json:"level"` // 等级
CrystalBalance int64 `json:"crystal_balance"` // 水晶余额
IsActive bool `json:"is_active"` // 是否激活(当前使用)
}
// MyFanIdentitiesResponseDTO 我的粉丝身份列表响应
type MyFanIdentitiesResponseDTO struct {
Items []MyFanIdentityItemDTO `json:"items"`
Total int `json:"total"`
CurrentStarID int64 `json:"current_star_id"` // 当前激活的明星ID
}
// AddIdentityResponseDTO 添加身份响应
type AddIdentityResponseDTO struct {
Bound bool `json:"bound"`
IdentityID string `json:"identity_id"`
}
// SwitchIdentityResponseDTO 切换身份响应
type SwitchIdentityResponseDTO struct {
AccessToken string `json:"access_token"`
ExpiresIn int64 `json:"expires_in"`
CurrentIdentity CurrentIdentityDTO `json:"current_identity"`
}