// // ProfileModels.swift // suixinkan // // Created by Codex on 2026/6/20. // import Foundation /// 用户资料响应实体,表示“我的”页面展示的账号基础信息。 struct UserInfoResponse: Decodable, Equatable { let avatar: String let realName: String let phone: String let nickname: String let roleName: String let status: Int let statusName: String /// 用户资料响应的 JSON 字段映射。 enum CodingKeys: String, CodingKey { case avatar case realName = "real_name" case phone case nickname case roleName = "role_name" case status case statusName = "status_name" } /// 创建用户资料实体,主要用于本地更新和预览默认值。 init( avatar: String = "", realName: String = "", phone: String = "", nickname: String = "", roleName: String = "", status: Int = 0, statusName: String = "" ) { self.avatar = avatar self.realName = realName self.phone = phone self.nickname = nickname self.roleName = roleName self.status = status self.statusName = statusName } /// 自定义解码,兼容后端字段类型不稳定的情况。 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) avatar = try container.decodeLossyString(forKey: .avatar) realName = try container.decodeLossyString(forKey: .realName) phone = try container.decodeLossyString(forKey: .phone) nickname = try container.decodeLossyString(forKey: .nickname) roleName = try container.decodeLossyString(forKey: .roleName) status = try container.decodeLossyInt(forKey: .status) ?? 0 statusName = try container.decodeLossyString(forKey: .statusName) } } /// 用户资料更新请求实体,表示昵称、密码和头像修改参数。 struct UpdateInfoRequest: Encodable { let nickname: String? let password: String? let avatar: String? } /// 实名认证响应实体,包裹当前用户的认证详情。 struct RealNameInfoResponse: Decodable, Equatable { let realNameInfo: RealNameInfo? /// 实名认证响应的 JSON 字段映射。 enum CodingKeys: String, CodingKey { case realNameInfo = "real_name_info" } } /// 实名认证信息实体,表示当前用户实名审核状态和失败原因。 struct RealNameInfo: Decodable, Equatable { let realName: String let auditStatus: Int let auditStatusText: String? let rejectReason: String? /// 实名认证信息的 JSON 字段映射。 enum CodingKeys: String, CodingKey { case realName = "real_name" case auditStatus = "audit_status" case auditStatusText = "audit_status_text" case rejectReason = "reject_reason" } /// 自定义解码,兼容审核状态字段类型不稳定的情况。 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) realName = try container.decodeLossyString(forKey: .realName) auditStatus = try container.decodeLossyInt(forKey: .auditStatus) ?? 0 auditStatusText = try container.decodeIfPresent(String.self, forKey: .auditStatusText) rejectReason = try container.decodeIfPresent(String.self, forKey: .rejectReason) } } private extension KeyedDecodingContainer { /// 将 String、数字和 Bool 宽松解码为字符串。 func decodeLossyString(forKey key: Key) throws -> String { if let value = try? decodeIfPresent(String.self, forKey: key) { return value } if let value = try? decodeIfPresent(Int.self, forKey: key) { return String(value) } if let value = try? decodeIfPresent(Double.self, forKey: key) { return String(value) } if let value = try? decodeIfPresent(Bool.self, forKey: key) { return value ? "true" : "false" } return "" } /// 将 Int、Double 或数字字符串宽松解码为整数。 func decodeLossyInt(forKey key: Key) throws -> Int? { if let value = try? decodeIfPresent(Int.self, forKey: key) { return value } if let value = try? decodeIfPresent(String.self, forKey: key) { let text = value.trimmingCharacters(in: .whitespacesAndNewlines) if let intValue = Int(text) { return intValue } if let doubleValue = Double(text) { return Int(doubleValue) } } if let value = try? decodeIfPresent(Double.self, forKey: key) { return Int(value) } return nil } }