feat: 更新素材管理和举报风险地图

This commit is contained in:
2026-07-09 12:20:02 +08:00
parent 9b92d81902
commit 42aca73588
42 changed files with 6164 additions and 1369 deletions

View File

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