// // WalletModels.swift // suixinkan // import Foundation /// 钱包汇总响应,用于展示累计金额、当前余额和可提现金额。 struct WalletSummaryResponse: Decodable, Equatable { let amountTotal: String let amountCurrentBalance: String let amountWithdrawable: String enum CodingKeys: String, CodingKey { case amountTotal = "amount_total" case amountCurrentBalance = "amount_current_balance" case amountWithdrawable = "amount_withdrawable" } /// 创建钱包汇总响应。 init(amountTotal: String = "", amountCurrentBalance: String = "", amountWithdrawable: String = "") { self.amountTotal = amountTotal self.amountCurrentBalance = amountCurrentBalance self.amountWithdrawable = amountWithdrawable } /// 宽松解码钱包汇总金额字段。 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) amountTotal = try container.decodeWalletLossyString(forKey: .amountTotal) amountCurrentBalance = try container.decodeWalletLossyString(forKey: .amountCurrentBalance) amountWithdrawable = try container.decodeWalletLossyString(forKey: .amountWithdrawable) } } /// 钱包流水列表响应,用于邀请奖励记录。 struct WalletTransactionListResponse: Decodable, Equatable { let total: Int let list: [WalletTransactionItem] /// 创建钱包流水列表响应。 init(total: Int = 0, list: [WalletTransactionItem] = []) { self.total = total self.list = list } } /// 钱包流水实体,表示一条收入或提现相关记录。 struct WalletTransactionItem: Decodable, Hashable { let id: Int let amount: String let transactionType: Int let transactionTypeLabel: String let createdAt: String let orderNumberSuffix: String let withdrawLabel: String enum CodingKeys: String, CodingKey { case id case amount case transactionType = "transaction_type" case transactionTypeLabel = "transaction_type_label" case createdAt = "created_at" case orderNumberSuffix = "order_number_suffix" case withdrawLabel = "withdraw_label" } /// 创建钱包流水实体。 init( id: Int, amount: String, transactionType: Int = 0, transactionTypeLabel: String = "", createdAt: String, orderNumberSuffix: String = "", withdrawLabel: String = "" ) { self.id = id self.amount = amount self.transactionType = transactionType self.transactionTypeLabel = transactionTypeLabel self.createdAt = createdAt self.orderNumberSuffix = orderNumberSuffix self.withdrawLabel = withdrawLabel } /// 宽松解码钱包流水字段。 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decodeWalletLossyInt(forKey: .id) ?? 0 amount = try container.decodeWalletLossyString(forKey: .amount) transactionType = try container.decodeWalletLossyInt(forKey: .transactionType) ?? 0 transactionTypeLabel = try container.decodeWalletLossyString(forKey: .transactionTypeLabel) createdAt = try container.decodeWalletLossyString(forKey: .createdAt) orderNumberSuffix = try container.decodeWalletLossyString(forKey: .orderNumberSuffix) withdrawLabel = try container.decodeWalletLossyString(forKey: .withdrawLabel) } } private extension KeyedDecodingContainer { func decodeWalletLossyString(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) } return "" } func decodeWalletLossyInt(forKey key: Key) throws -> Int? { if let value = try? decodeIfPresent(Int.self, forKey: key) { return value } if let value = try? decodeIfPresent(Double.self, forKey: key) { return Int(value) } if let value = try? decodeIfPresent(String.self, forKey: key) { let text = value.trimmingCharacters(in: .whitespacesAndNewlines) return Int(text) ?? Double(text).map(Int.init) } return nil } }