137 lines
4.3 KiB
Swift
137 lines
4.3 KiB
Swift
//
|
|
// SettingModels.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// 最新版本响应实体,对齐 Android `VersionResponse`。
|
|
struct VersionResponse: Decodable, Equatable {
|
|
let id: Int
|
|
let type: Int
|
|
let version: String
|
|
let operatorName: String
|
|
let description: String
|
|
let status: Int
|
|
let createdAt: String
|
|
let updatedAt: String
|
|
let deletedAt: String?
|
|
let versionCode: Int
|
|
let apkURL: String
|
|
let isForceUpdate: Int
|
|
let approveNotes: String
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case id
|
|
case type
|
|
case version
|
|
case operatorName = "operator"
|
|
case description
|
|
case status
|
|
case createdAt = "created_at"
|
|
case updatedAt = "updated_at"
|
|
case deletedAt = "deleted_at"
|
|
case versionCode = "version_code"
|
|
case apkURL = "apk_url"
|
|
case isForceUpdate = "is_force_update"
|
|
case approveNotes = "approve_notes"
|
|
}
|
|
|
|
init(
|
|
id: Int = 0,
|
|
type: Int = 0,
|
|
version: String = "",
|
|
operatorName: String = "",
|
|
description: String = "",
|
|
status: Int = 0,
|
|
createdAt: String = "",
|
|
updatedAt: String = "",
|
|
deletedAt: String? = nil,
|
|
versionCode: Int = 0,
|
|
apkURL: String = "",
|
|
isForceUpdate: Int = 0,
|
|
approveNotes: String = ""
|
|
) {
|
|
self.id = id
|
|
self.type = type
|
|
self.version = version
|
|
self.operatorName = operatorName
|
|
self.description = description
|
|
self.status = status
|
|
self.createdAt = createdAt
|
|
self.updatedAt = updatedAt
|
|
self.deletedAt = deletedAt
|
|
self.versionCode = versionCode
|
|
self.apkURL = apkURL
|
|
self.isForceUpdate = isForceUpdate
|
|
self.approveNotes = approveNotes
|
|
}
|
|
|
|
init(from decoder: Decoder) throws {
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
id = try container.decodeLossyInt(forKey: .id) ?? 0
|
|
type = try container.decodeLossyInt(forKey: .type) ?? 0
|
|
version = try container.decodeLossyString(forKey: .version)
|
|
operatorName = try container.decodeLossyString(forKey: .operatorName)
|
|
description = try container.decodeLossyString(forKey: .description)
|
|
status = try container.decodeLossyInt(forKey: .status) ?? 0
|
|
createdAt = try container.decodeLossyString(forKey: .createdAt)
|
|
updatedAt = try container.decodeLossyString(forKey: .updatedAt)
|
|
deletedAt = try container.decodeIfPresent(String.self, forKey: .deletedAt)
|
|
versionCode = try container.decodeLossyInt(forKey: .versionCode) ?? 0
|
|
apkURL = try container.decodeLossyString(forKey: .apkURL)
|
|
isForceUpdate = try container.decodeLossyInt(forKey: .isForceUpdate) ?? 0
|
|
approveNotes = try container.decodeLossyString(forKey: .approveNotes)
|
|
}
|
|
}
|
|
|
|
/// 设置页协议入口实体,表示标题和对应 H5 地址。
|
|
struct SettingAgreementDestination: Equatable {
|
|
let title: String
|
|
let url: URL
|
|
}
|
|
|
|
/// 设置页协议类型。
|
|
enum SettingAgreementKind: CaseIterable {
|
|
case aboutUs
|
|
case userAgreement
|
|
case privacyPolicy
|
|
}
|
|
|
|
private extension KeyedDecodingContainer {
|
|
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 ""
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|