
- 在HomeFeature中添加MeDynamicFeature以管理用户动态状态。 - 在MainFeature中集成MeDynamicFeature,支持动态内容的加载与展示。 - 新增MeDynamicView以展示用户的动态列表,支持下拉刷新和上拉加载更多功能。 - 更新MeView以集成用户动态视图,提升用户体验。 - 在APIEndpoints中新增getMyDynamic端点以支持获取用户动态信息。 - 更新DynamicsModels以适应新的动态数据结构,确保数据解析的准确性。 - 在OptimizedDynamicCardView中优化图片处理逻辑,提升动态展示效果。 - 更新相关视图组件以支持动态内容的展示与交互,增强用户体验。
659 lines
20 KiB
Swift
659 lines
20 KiB
Swift
import Foundation
|
||
|
||
// MARK: - Account Model
|
||
/// 账户认证信息模型
|
||
/// 用于承接 oauth/token 和 oauth/ticket 接口的认证数据
|
||
/// 参照 OC 版本的 AccountModel 设计
|
||
struct AccountModel: Codable, Equatable {
|
||
let uid: String? // 用户唯一标识
|
||
let jti: String? // JWT ID
|
||
let tokenType: String? // Token 类型 (bearer)
|
||
let refreshToken: String? // 刷新令牌
|
||
let netEaseToken: String? // 网易云信令牌
|
||
let accessToken: String? // OAuth 访问令牌
|
||
let expiresIn: Int? // 过期时间(秒)
|
||
let scope: String? // 权限范围
|
||
var ticket: String? // 业务会话票据(来自 oauth/ticket)
|
||
|
||
enum CodingKeys: String, CodingKey {
|
||
case uid
|
||
case jti
|
||
case tokenType = "token_type"
|
||
case refreshToken = "refresh_token"
|
||
case netEaseToken
|
||
case accessToken = "access_token"
|
||
case expiresIn = "expires_in"
|
||
case scope
|
||
case ticket
|
||
}
|
||
|
||
/// 检查是否有有效的认证信息
|
||
var hasValidAuthentication: Bool {
|
||
return accessToken != nil && !accessToken!.isEmpty
|
||
}
|
||
|
||
/// 检查是否有有效的业务会话
|
||
var hasValidSession: Bool {
|
||
return hasValidAuthentication && ticket != nil && !ticket!.isEmpty
|
||
}
|
||
|
||
/// 从 IDLoginData 创建 AccountModel
|
||
/// - Parameter loginData: 登录响应数据
|
||
/// - Returns: AccountModel 实例,如果数据无效则返回 nil
|
||
static func from(loginData: IDLoginData) -> AccountModel? {
|
||
// 确保至少有 accessToken 和 uid
|
||
guard let accessToken = loginData.accessToken,
|
||
let uid = loginData.uid else {
|
||
return nil
|
||
}
|
||
|
||
return AccountModel(
|
||
uid: String(uid),
|
||
jti: loginData.jti,
|
||
tokenType: loginData.tokenType,
|
||
refreshToken: loginData.refreshToken,
|
||
netEaseToken: loginData.netEaseToken,
|
||
accessToken: accessToken,
|
||
expiresIn: loginData.expiresIn,
|
||
scope: loginData.scope,
|
||
ticket: nil // 初始为空,后续通过 oauth/ticket 填充
|
||
)
|
||
}
|
||
|
||
/// 更新 ticket 信息
|
||
/// - Parameter ticket: 从 oauth/ticket 获取的票据
|
||
/// - Returns: 更新后的 AccountModel
|
||
func withTicket(_ ticket: String) -> AccountModel {
|
||
var updatedModel = self
|
||
updatedModel.ticket = ticket
|
||
return updatedModel
|
||
}
|
||
}
|
||
|
||
// MARK: - ID Login Request Model
|
||
struct IDLoginAPIRequest: APIRequestProtocol {
|
||
typealias Response = IDLoginResponse
|
||
|
||
let endpoint = APIEndpoint.login.path // 使用枚举定义的登录端点
|
||
let method: HTTPMethod = .POST
|
||
let includeBaseParameters = true
|
||
let queryParameters: [String: String]?
|
||
var bodyParameters: [String: Any]? { nil }
|
||
let timeout: TimeInterval = 30.0
|
||
|
||
/// 初始化ID登录请求
|
||
/// - Parameters:
|
||
/// - phone: DES加密后的用户ID/手机号
|
||
/// - password: DES加密后的密码
|
||
/// - clientSecret: 客户端密钥,固定为"uyzjdhds"
|
||
/// - version: 版本号,固定为"1"
|
||
/// - clientId: 客户端ID,固定为"erban-client"
|
||
/// - grantType: 授权类型,固定为"password"
|
||
init(phone: String, password: String, clientSecret: String = "uyzjdhds", version: String = "1", clientId: String = "erban-client", grantType: String = "password") {
|
||
self.queryParameters = [
|
||
"phone": phone,
|
||
"password": password,
|
||
"client_secret": clientSecret,
|
||
"version": version,
|
||
"client_id": clientId,
|
||
"grant_type": grantType
|
||
];
|
||
}
|
||
}
|
||
|
||
// MARK: - ID Login Response Model
|
||
struct IDLoginResponse: Codable, Equatable {
|
||
let status: String?
|
||
let message: String?
|
||
let code: Int?
|
||
let data: IDLoginData?
|
||
|
||
/// 是否登录成功
|
||
var isSuccess: Bool {
|
||
return code == 200 || status?.lowercased() == "success"
|
||
}
|
||
|
||
/// 错误消息(如果有)
|
||
var errorMessage: String {
|
||
return message ?? "登录失败,请重试"
|
||
}
|
||
}
|
||
|
||
// MARK: - ID Login Data Model
|
||
struct IDLoginData: Codable, Equatable {
|
||
let accessToken: String?
|
||
let refreshToken: String?
|
||
let tokenType: String?
|
||
let expiresIn: Int?
|
||
let scope: String?
|
||
let userInfo: UserInfo?
|
||
let uid: Int? // 修改:从String?改为Int?以匹配API返回
|
||
let netEaseToken: String? // 新增:网易云token
|
||
let jti: String? // 新增:JWT token identifier
|
||
|
||
enum CodingKeys: String, CodingKey {
|
||
case accessToken = "access_token"
|
||
case refreshToken = "refresh_token"
|
||
case tokenType = "token_type"
|
||
case expiresIn = "expires_in"
|
||
case scope
|
||
case userInfo = "user_info"
|
||
case uid
|
||
case netEaseToken
|
||
case jti
|
||
}
|
||
}
|
||
|
||
// MARK: - User Info Model
|
||
struct UserInfo: Codable, Equatable {
|
||
let uid: Int?
|
||
let userId: String? // 兼容旧字段
|
||
let nick: String?
|
||
let nickname: String? // 兼容旧字段
|
||
let avatar: String?
|
||
let region: String?
|
||
let regionDesc: String?
|
||
let gender: Int?
|
||
let birth: Int64?
|
||
let userDesc: String?
|
||
let userLevelVo: UserLevelVo?
|
||
let userVipInfoVO: UserVipInfoVO?
|
||
let medalsPic: [MedalsPic]?
|
||
let userHeadwear: UserHeadwear?
|
||
let privatePhoto: [PrivatePhoto]?
|
||
let createTime: Int64?
|
||
let phoneAreaCode: String?
|
||
let erbanNo: Int?
|
||
let isCertified: Bool?
|
||
let isBindPhone: Bool?
|
||
let isBindApple: Bool?
|
||
let isBindPasswd: Bool?
|
||
let isBindPaymentPwd: Bool?
|
||
let banAccount: Bool?
|
||
let visitNum: Int?
|
||
let fansNum: Int?
|
||
let followNum: Int?
|
||
let visitHide: Bool?
|
||
let visitListView: Bool?
|
||
let newUser: Bool?
|
||
let defUser: Int?
|
||
let platformRole: Int?
|
||
let bindType: Int?
|
||
let showLimitCharge: Bool?
|
||
let uploadGifAvatarPrice: Int?
|
||
let hasRegPacket: Bool?
|
||
let hasPrettyErbanNo: Bool?
|
||
let hasSuperRole: Bool?
|
||
let isRechargeUser: Bool?
|
||
let isFirstCharge: Bool?
|
||
let fromSayHelloChannel: Bool?
|
||
let partitionId: Int?
|
||
let useStatus: Int?
|
||
let micNickColor: String?
|
||
let micCircle: String?
|
||
let audioCard: AudioCard?
|
||
let userInfoSkillVo: UserInfoSkillVo?
|
||
let userInfoCardPic: String?
|
||
let iosBubbleUrl: String?
|
||
let androidBubbleUrl: String?
|
||
let status: String? // 兼容旧字段
|
||
let username: String? // 兼容旧字段
|
||
let email: String? // 兼容旧字段
|
||
let phone: String? // 兼容旧字段
|
||
let updateTime: String? // 兼容旧字段
|
||
|
||
enum CodingKeys: String, CodingKey {
|
||
case uid
|
||
case userId = "user_id"
|
||
case nick
|
||
case nickname
|
||
case avatar
|
||
case region
|
||
case regionDesc
|
||
case gender
|
||
case birth
|
||
case userDesc
|
||
case userLevelVo
|
||
case userVipInfoVO
|
||
case medalsPic
|
||
case userHeadwear
|
||
case privatePhoto
|
||
case createTime
|
||
case phoneAreaCode
|
||
case erbanNo
|
||
case isCertified
|
||
case isBindPhone
|
||
case isBindApple
|
||
case isBindPasswd
|
||
case isBindPaymentPwd
|
||
case banAccount
|
||
case visitNum
|
||
case fansNum
|
||
case followNum
|
||
case visitHide
|
||
case visitListView
|
||
case newUser
|
||
case defUser
|
||
case platformRole
|
||
case bindType
|
||
case showLimitCharge
|
||
case uploadGifAvatarPrice
|
||
case hasRegPacket
|
||
case hasPrettyErbanNo
|
||
case hasSuperRole
|
||
case isRechargeUser
|
||
case isFirstCharge
|
||
case fromSayHelloChannel
|
||
case partitionId
|
||
case useStatus
|
||
case micNickColor
|
||
case micCircle
|
||
case audioCard
|
||
case userInfoSkillVo
|
||
case userInfoCardPic
|
||
case iosBubbleUrl
|
||
case androidBubbleUrl
|
||
case status
|
||
case username
|
||
case email
|
||
case phone
|
||
case updateTime
|
||
}
|
||
}
|
||
|
||
// MARK: - 嵌套对象结构体
|
||
struct UserLevelVo: Codable, Equatable {
|
||
let experUrl: String?
|
||
let charmLevelSeq: Int?
|
||
let experLevelName: String?
|
||
let charmLevelName: String?
|
||
let charmAmount: Int?
|
||
let experLevelGrp: String?
|
||
let charmUrl: String?
|
||
let experLevelSeq: Int?
|
||
let experAmount: Int?
|
||
let charmLevelGrp: String?
|
||
}
|
||
|
||
struct UserVipInfoVO: Codable, Equatable {
|
||
let vipIcon: String?
|
||
let nameplateId: Int?
|
||
let vipLogo: String?
|
||
let userCardBG: String?
|
||
let preventKick: Bool?
|
||
let preventTrace: Bool?
|
||
let preventFollow: Bool?
|
||
let micNickColour: String?
|
||
let micCircle: String?
|
||
let enterRoomEffects: String?
|
||
let medalSeat: Int?
|
||
let friendNickColour: String?
|
||
let visitHide: Bool?
|
||
let visitListView: Bool?
|
||
let privateChatLimit: Bool?
|
||
let nameplateUrl: String?
|
||
let roomPicScreen: Bool?
|
||
let uploadGifAvatar: Bool?
|
||
let expireTime: Int64?
|
||
let enterHide: Bool?
|
||
let vipLevel: Int?
|
||
let vipName: String?
|
||
}
|
||
|
||
struct MedalsPic: Codable, Equatable {
|
||
let picUrl: String?
|
||
let mp4Url: String?
|
||
}
|
||
|
||
struct UserHeadwear: Codable, Equatable {
|
||
let expireTime: Int64?
|
||
let renewPrice: Int?
|
||
let uid: Int?
|
||
let comeFrom: Int?
|
||
let labelType: Int?
|
||
let limitDesc: String?
|
||
let redirectLink: String?
|
||
let headwearId: Int?
|
||
let buyTime: Int64?
|
||
let pic: String?
|
||
let used: Bool?
|
||
let price: Int?
|
||
let originalPrice: Int?
|
||
let type: Int?
|
||
let days: Int?
|
||
let headwearName: String?
|
||
let effect: String?
|
||
let expireDays: Int?
|
||
let status: Int?
|
||
}
|
||
|
||
struct PrivatePhoto: Codable, Equatable {
|
||
let seqNo: Int?
|
||
let photoUrl: String?
|
||
let createTime: Int64?
|
||
let review: Bool?
|
||
let pid: Int?
|
||
}
|
||
|
||
struct AudioCard: Codable, Equatable {
|
||
let uid: Int?
|
||
let status: Int?
|
||
}
|
||
|
||
struct UserInfoSkillVo: Codable, Equatable {
|
||
let liveTag: Bool?
|
||
let liveSkillVoList: [LiveSkillVo]?
|
||
}
|
||
|
||
struct LiveSkillVo: Codable, Equatable {
|
||
// 具体字段根据API返回补充,这里暂留空
|
||
}
|
||
|
||
// MARK: - Login Helper
|
||
struct LoginHelper {
|
||
|
||
/// 创建ID登录请求
|
||
/// 这个方法会自动处理DES加密
|
||
/// - Parameters:
|
||
/// - userID: 原始用户ID
|
||
/// - password: 原始密码
|
||
/// - Returns: 配置好的API请求,如果加密失败返回nil
|
||
static func createIDLoginRequest(userID: String, password: String) async -> IDLoginAPIRequest? {
|
||
// 使用DES加密ID和密码
|
||
let encryptionKey = "1ea53d260ecf11e7b56e00163e046a26"
|
||
|
||
guard let encryptedID = DESEncrypt.encryptUseDES(userID, key: encryptionKey),
|
||
let encryptedPassword = DESEncrypt.encryptUseDES(password, key: encryptionKey) else {
|
||
debugErrorSync("❌ DES加密失败")
|
||
return nil
|
||
}
|
||
|
||
debugInfoSync("🔐 DES加密成功")
|
||
debugInfoSync(" 原始ID: \(userID)")
|
||
debugInfoSync(" 加密后ID: \(encryptedID)")
|
||
debugInfoSync(" 原始密码: \(password)")
|
||
debugInfoSync(" 加密后密码: \(encryptedPassword)")
|
||
|
||
return IDLoginAPIRequest(
|
||
phone: userID,
|
||
password: encryptedPassword
|
||
)
|
||
}
|
||
}
|
||
|
||
// MARK: - Ticket API Models
|
||
|
||
/// Ticket 请求结构体
|
||
struct TicketAPIRequest: APIRequestProtocol {
|
||
typealias Response = TicketResponse
|
||
|
||
let endpoint = "/oauth/ticket"
|
||
let method: HTTPMethod = .POST
|
||
let includeBaseParameters = true
|
||
let queryParameters: [String: String]?
|
||
var bodyParameters: [String: Any]? { nil }
|
||
let timeout: TimeInterval = 30.0
|
||
let customHeaders: [String: String]?
|
||
|
||
/// 初始化 Ticket 请求
|
||
/// - Parameters:
|
||
/// - accessToken: OAuth 访问令牌
|
||
/// - issueType: 签发类型,固定为"multi"
|
||
/// - uid: 用户唯一标识,用于添加到请求头
|
||
init(accessToken: String, issueType: String = "multi", uid: Int? = nil) {
|
||
self.queryParameters = [
|
||
"access_token": accessToken,
|
||
"issue_type": issueType
|
||
]
|
||
|
||
// 设置自定义请求头
|
||
var headers: [String: String] = [:]
|
||
if let uid = uid {
|
||
headers["pub_uid"] = "\(uid)" // 转换为字符串
|
||
}
|
||
self.customHeaders = headers.isEmpty ? nil : headers
|
||
}
|
||
}
|
||
|
||
/// Ticket 响应结构体
|
||
struct TicketResponse: Codable, Equatable {
|
||
let code: Int?
|
||
let message: String?
|
||
let data: TicketData?
|
||
|
||
/// 是否获取成功
|
||
var isSuccess: Bool {
|
||
return code == 200
|
||
}
|
||
|
||
/// 错误消息(如果有)
|
||
var errorMessage: String {
|
||
return message ?? "Ticket 获取失败,请重试"
|
||
}
|
||
|
||
/// 获取 Ticket 字符串
|
||
var ticket: String? {
|
||
return data?.tickets?.first?.ticket
|
||
}
|
||
}
|
||
|
||
/// Ticket 数据结构体
|
||
struct TicketData: Codable, Equatable {
|
||
let tickets: [TicketInfo]?
|
||
}
|
||
|
||
/// Ticket 信息结构体
|
||
struct TicketInfo: Codable, Equatable {
|
||
let ticket: String?
|
||
}
|
||
|
||
// MARK: - Ticket Helper
|
||
struct TicketHelper {
|
||
|
||
/// 创建 Ticket 请求
|
||
/// - Parameters:
|
||
/// - accessToken: OAuth 访问令牌
|
||
/// - uid: 用户唯一标识
|
||
/// - Returns: 配置好的 Ticket API 请求
|
||
static func createTicketRequest(accessToken: String, uid: Int?) -> TicketAPIRequest {
|
||
return TicketAPIRequest(accessToken: accessToken, uid: uid)
|
||
}
|
||
|
||
/// 调试打印 Ticket 请求信息
|
||
/// - Parameters:
|
||
/// - accessToken: OAuth 访问令牌
|
||
/// - uid: 用户唯一标识
|
||
static func debugTicketRequest(accessToken: String, uid: Int?) {
|
||
debugInfoSync("🎫 Ticket 请求调试信息")
|
||
debugInfoSync(" AccessToken: \(accessToken)")
|
||
debugInfoSync(" UID: \(uid?.description ?? "nil")")
|
||
debugInfoSync(" Endpoint: /oauth/ticket")
|
||
debugInfoSync(" Method: POST")
|
||
debugInfoSync(" Headers: pub_uid = \(uid?.description ?? "nil")")
|
||
debugInfoSync(" Parameters: access_token=\(accessToken), issue_type=multi")
|
||
}
|
||
}
|
||
|
||
// MARK: - 兼容旧的LoginResponse(如果需要)
|
||
typealias LoginResponse = IDLoginResponse
|
||
|
||
// MARK: - Email Verification Code Models
|
||
|
||
/// 邮箱验证码获取请求
|
||
struct EmailGetCodeRequest: APIRequestProtocol {
|
||
typealias Response = EmailGetCodeResponse
|
||
|
||
let endpoint = APIEndpoint.emailGetCode.path
|
||
let method: HTTPMethod = .POST
|
||
let includeBaseParameters = true
|
||
let queryParameters: [String: String]?
|
||
var bodyParameters: [String: Any]? { nil }
|
||
let timeout: TimeInterval = 30.0
|
||
|
||
/// 初始化邮箱验证码获取请求
|
||
/// - Parameters:
|
||
/// - emailAddress: DES加密后的邮箱地址
|
||
/// - type: 验证码类型(1=注册/登录)
|
||
init(emailAddress: String, type: Int = 1) {
|
||
self.queryParameters = [
|
||
"emailAddress": emailAddress,
|
||
"type": String(type)
|
||
]
|
||
}
|
||
}
|
||
|
||
/// 邮箱验证码获取响应
|
||
struct EmailGetCodeResponse: Codable, Equatable {
|
||
let status: String?
|
||
let message: String?
|
||
let code: Int?
|
||
let data: String? // 通常为空,成功时只需要检查状态码
|
||
|
||
/// 是否发送成功
|
||
var isSuccess: Bool {
|
||
return code == 200 || status?.lowercased() == "success"
|
||
}
|
||
|
||
/// 错误消息(如果有)
|
||
var errorMessage: String {
|
||
return message ?? "验证码发送失败,请重试"
|
||
}
|
||
}
|
||
|
||
/// 邮箱验证码登录请求
|
||
struct EmailLoginRequest: APIRequestProtocol {
|
||
typealias Response = IDLoginResponse // 复用ID登录的响应模型
|
||
|
||
let endpoint = APIEndpoint.login.path
|
||
let method: HTTPMethod = .POST
|
||
let includeBaseParameters = true
|
||
let queryParameters: [String: String]?
|
||
var bodyParameters: [String: Any]? { nil }
|
||
let timeout: TimeInterval = 30.0
|
||
|
||
/// 初始化邮箱验证码登录请求
|
||
/// - Parameters:
|
||
/// - email: DES加密后的邮箱地址
|
||
/// - code: 验证码
|
||
/// - clientSecret: 客户端密钥,固定为"uyzjdhds"
|
||
/// - version: 版本号,固定为"1"
|
||
/// - clientId: 客户端ID,固定为"erban-client"
|
||
/// - grantType: 授权类型,固定为"email"
|
||
init(email: String, code: String, clientSecret: String = "uyzjdhds", version: String = "1", clientId: String = "erban-client", grantType: String = "email") {
|
||
self.queryParameters = [
|
||
"email": email,
|
||
"code": code,
|
||
"client_secret": clientSecret,
|
||
"version": version,
|
||
"client_id": clientId,
|
||
"grant_type": grantType
|
||
]
|
||
}
|
||
}
|
||
|
||
// MARK: - Email Login Helper
|
||
extension LoginHelper {
|
||
|
||
/// 创建邮箱验证码获取请求
|
||
/// - Parameter email: 原始邮箱地址
|
||
/// - Returns: 配置好的API请求,如果加密失败返回nil
|
||
static func createEmailGetCodeRequest(email: String) -> EmailGetCodeRequest? {
|
||
let encryptionKey = "1ea53d260ecf11e7b56e00163e046a26"
|
||
|
||
guard let encryptedEmail = DESEncrypt.encryptUseDES(email, key: encryptionKey) else {
|
||
debugErrorSync("❌ 邮箱DES加密失败")
|
||
return nil
|
||
}
|
||
|
||
debugInfoSync("🔐 邮箱DES加密成功")
|
||
debugInfoSync(" 原始邮箱: \(email)")
|
||
debugInfoSync(" 加密邮箱: \(encryptedEmail)")
|
||
|
||
return EmailGetCodeRequest(emailAddress: email, type: 1)
|
||
}
|
||
|
||
/// 创建邮箱验证码登录请求
|
||
/// - Parameters:
|
||
/// - email: 原始邮箱地址
|
||
/// - code: 验证码
|
||
/// - Returns: 配置好的API请求,如果加密失败返回nil
|
||
static func createEmailLoginRequest(email: String, code: String) async -> EmailLoginRequest? {
|
||
let encryptionKey = "1ea53d260ecf11e7b56e00163e046a26"
|
||
|
||
guard let encryptedEmail = DESEncrypt.encryptUseDES(email, key: encryptionKey) else {
|
||
await debugErrorSync("❌ 邮箱DES加密失败")
|
||
return nil
|
||
}
|
||
|
||
debugInfoSync("🔐 邮箱验证码登录DES加密成功")
|
||
debugInfoSync(" 原始邮箱: \(email)")
|
||
debugInfoSync(" 加密邮箱: \(encryptedEmail)")
|
||
debugInfoSync(" 验证码: \(code)")
|
||
|
||
return EmailLoginRequest(email: encryptedEmail, code: code)
|
||
}
|
||
}
|
||
|
||
// MARK: - User Info API Models
|
||
|
||
/// 获取用户信息请求模型
|
||
struct GetUserInfoRequest: APIRequestProtocol {
|
||
typealias Response = GetUserInfoResponse
|
||
|
||
let endpoint = APIEndpoint.getUserInfo.path
|
||
let method: HTTPMethod = .GET
|
||
let includeBaseParameters = true
|
||
let queryParameters: [String: String]?
|
||
var bodyParameters: [String: Any]? { nil }
|
||
let timeout: TimeInterval = 30.0
|
||
let shouldShowLoading: Bool = false // 不显示loading,避免影响用户体验
|
||
let shouldShowError: Bool = false // 不显示错误,静默处理
|
||
|
||
/// 初始化获取用户信息请求
|
||
/// - Parameter uid: 要查询的用户ID
|
||
init(uid: String) {
|
||
self.queryParameters = [
|
||
"uid": uid
|
||
]
|
||
}
|
||
}
|
||
|
||
/// 获取用户信息响应模型
|
||
struct GetUserInfoResponse: Codable, Equatable {
|
||
let code: Int?
|
||
let message: String?
|
||
let timestamp: Int64?
|
||
let data: UserInfo?
|
||
|
||
/// 是否获取成功
|
||
var isSuccess: Bool {
|
||
return code == 200
|
||
}
|
||
|
||
/// 错误消息(如果有)
|
||
var errorMessage: String {
|
||
return message ?? "获取用户信息失败,请重试"
|
||
}
|
||
}
|
||
|
||
// MARK: - User Info Helper
|
||
struct UserInfoHelper {
|
||
|
||
/// 创建获取用户信息请求
|
||
/// - Parameter uid: 用户ID
|
||
/// - Returns: 配置好的API请求
|
||
static func createGetUserInfoRequest(uid: String) -> GetUserInfoRequest {
|
||
return GetUserInfoRequest(uid: uid)
|
||
}
|
||
|
||
/// 调试打印获取用户信息请求
|
||
/// - Parameter uid: 用户ID
|
||
static func debugGetUserInfoRequest(uid: String) {
|
||
debugInfoSync("👤 获取用户信息请求调试")
|
||
debugInfoSync(" UID: \(uid)")
|
||
debugInfoSync(" Endpoint: /user/get")
|
||
debugInfoSync(" Method: GET")
|
||
debugInfoSync(" Parameters: uid=\(uid)")
|
||
}
|
||
}
|