feat: add WeChat sharing and invite flow

This commit is contained in:
2026-07-07 16:53:39 +08:00
parent f1937e23d4
commit a80c181bd7
160 changed files with 7557 additions and 849 deletions

View File

@ -0,0 +1,127 @@
//
// 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
}
}