Files
suixinkan_ios_new/suixinkan/Features/ScenicPermission/Models/ScenicPermissionModels.swift
汉秋 c5374666de Add ScenicPermission module and AMap CocoaPods with simulator support.
Integrate scenic selection and permission flows into home routing, add AMap SDK for device builds while keeping arm64 simulators compilable via Podfile post_install hooks.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 10:15:26 +08:00

337 lines
12 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// ScenicPermissionModels.swift
// suixinkan
//
// Created by Codex on 2026/6/23.
//
import Foundation
///
struct ScenicAreaNode: Decodable, Equatable, Identifiable {
let id: String
let code: String
let name: String
let children: [ScenicAreaNode]
enum CodingKeys: String, CodingKey {
case id
case code
case name
case children
}
///
init(id: String, code: String = "", name: String, children: [ScenicAreaNode] = []) {
self.id = id
self.code = code
self.name = name
self.children = children
}
/// id/code
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
code = try container.decodeLossyString(forKey: .code)
let rawId = try container.decodeLossyString(forKey: .id).trimmingCharacters(in: .whitespacesAndNewlines)
id = rawId.isEmpty ? code : rawId
name = try container.decodeLossyString(forKey: .name)
children = try container.decodeIfPresent([ScenicAreaNode].self, forKey: .children) ?? []
}
}
///
struct ScenicApplicationPendingsResponse: Decodable, Equatable {
let items: [ScenicApplicationPendingResponse]
enum CodingKeys: String, CodingKey {
case items
case list
case data
}
///
init(items: [ScenicApplicationPendingResponse] = []) {
self.items = items
}
/// items/list/data
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
items = try container.decodeIfPresent([ScenicApplicationPendingResponse].self, forKey: .items)
?? container.decodeIfPresent([ScenicApplicationPendingResponse].self, forKey: .list)
?? container.decodeIfPresent([ScenicApplicationPendingResponse].self, forKey: .data)
?? []
}
}
///
struct ScenicApplicationPendingResponse: Decodable, Equatable, Identifiable {
let id: Int
let code: String
let scenicId: Int
let scenicName: String
let scenicImages: String
let scenicProvince: String
let scenicCity: String
let coopType: Int
let remark: String?
let status: Int
let rejectReason: String?
let auditedBy: String?
let auditedAt: String?
let auditNote: String?
let createdAt: String
enum CodingKeys: String, CodingKey {
case id
case code
case scenicId = "scenic_id"
case scenicName = "scenic_name"
case scenicImages = "scenic_images"
case scenicProvince = "scenic_province"
case scenicCity = "scenic_city"
case coopType = "coop_type"
case remark
case status
case rejectReason = "reject_reason"
case auditedBy = "audited_by"
case auditedAt = "audited_at"
case auditNote = "audit_note"
case createdAt = "created_at"
}
///
init(
id: Int,
code: String = "",
scenicId: Int = 0,
scenicName: String,
scenicImages: String = "",
scenicProvince: String = "",
scenicCity: String = "",
coopType: Int = 1,
remark: String? = nil,
status: Int = 1,
rejectReason: String? = nil,
auditedBy: String? = nil,
auditedAt: String? = nil,
auditNote: String? = nil,
createdAt: String = ""
) {
self.id = id
self.code = code
self.scenicId = scenicId
self.scenicName = scenicName
self.scenicImages = scenicImages
self.scenicProvince = scenicProvince
self.scenicCity = scenicCity
self.coopType = coopType
self.remark = remark
self.status = status
self.rejectReason = rejectReason
self.auditedBy = auditedBy
self.auditedAt = auditedAt
self.auditNote = auditNote
self.createdAt = createdAt
}
///
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeLossyInt(forKey: .id) ?? 0
code = try container.decodeLossyString(forKey: .code)
scenicId = try container.decodeLossyInt(forKey: .scenicId) ?? 0
scenicName = try container.decodeLossyString(forKey: .scenicName)
if let images = try? container.decode([String].self, forKey: .scenicImages) {
scenicImages = images.joined(separator: ",")
} else {
scenicImages = try container.decodeLossyString(forKey: .scenicImages)
}
scenicProvince = try container.decodeLossyString(forKey: .scenicProvince)
scenicCity = try container.decodeLossyString(forKey: .scenicCity)
coopType = try container.decodeLossyInt(forKey: .coopType) ?? 1
remark = try? container.decodeIfPresent(String.self, forKey: .remark)
status = try container.decodeLossyInt(forKey: .status) ?? 0
rejectReason = try? container.decodeIfPresent(String.self, forKey: .rejectReason)
auditedBy = try? container.decodeIfPresent(String.self, forKey: .auditedBy)
auditedAt = try? container.decodeIfPresent(String.self, forKey: .auditedAt)
auditNote = try? container.decodeIfPresent(String.self, forKey: .auditNote)
createdAt = try container.decodeLossyString(forKey: .createdAt)
}
}
///
struct ScenicApplicationSubmitRequest: Encodable, Equatable {
let scenicName: String?
let scenicImages: [String]?
let scenicProvince: String
let scenicCity: String
let coopType: Int
let remark: String
let scenicId: Int
enum CodingKeys: String, CodingKey {
case scenicName = "scenic_name"
case scenicImages = "scenic_images"
case scenicProvince = "scenic_province"
case scenicCity = "scenic_city"
case coopType = "coop_type"
case remark
case scenicId = "scenic_id"
}
}
/// /
struct RoleApplyPendingResponse: Decodable, Equatable, Hashable, Identifiable {
let id: Int
let code: String
let roleId: Int
let roleName: String
let scenicList: [RoleApplyScenicItem]
let status: Int
let statusLabel: String
let createdAt: String
let auditedBy: String?
let auditedAt: String?
let auditNote: String?
enum CodingKeys: String, CodingKey {
case id
case code
case roleId = "role_id"
case roleName = "role_name"
case scenicList = "scenic_list"
case status
case statusLabel = "status_label"
case createdAt = "created_at"
case auditedBy = "audited_by"
case auditedAt = "audited_at"
case auditNote = "audit_note"
}
///
init(
id: Int,
code: String = "",
roleId: Int,
roleName: String,
scenicList: [RoleApplyScenicItem] = [],
status: Int = 1,
statusLabel: String = "审核中",
createdAt: String = "",
auditedBy: String? = nil,
auditedAt: String? = nil,
auditNote: String? = nil
) {
self.id = id
self.code = code
self.roleId = roleId
self.roleName = roleName
self.scenicList = scenicList
self.status = status
self.statusLabel = statusLabel
self.createdAt = createdAt
self.auditedBy = auditedBy
self.auditedAt = auditedAt
self.auditNote = auditNote
}
///
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeLossyInt(forKey: .id) ?? 0
code = try container.decodeLossyString(forKey: .code)
roleId = try container.decodeLossyInt(forKey: .roleId) ?? 0
roleName = try container.decodeLossyString(forKey: .roleName)
scenicList = try container.decodeIfPresent([RoleApplyScenicItem].self, forKey: .scenicList) ?? []
status = try container.decodeLossyInt(forKey: .status) ?? 0
statusLabel = try container.decodeLossyString(forKey: .statusLabel)
createdAt = try container.decodeLossyString(forKey: .createdAt)
auditedBy = try? container.decodeIfPresent(String.self, forKey: .auditedBy)
auditedAt = try? container.decodeIfPresent(String.self, forKey: .auditedAt)
auditNote = try? container.decodeIfPresent(String.self, forKey: .auditNote)
}
}
///
struct RoleApplyScenicItem: Decodable, Equatable, Hashable, Identifiable {
let id: Int
let name: String
enum CodingKeys: String, CodingKey {
case id
case name
}
///
init(id: Int, name: String) {
self.id = id
self.name = name
}
/// ID
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeLossyInt(forKey: .id) ?? 0
name = try container.decodeLossyString(forKey: .name)
}
}
///
struct RoleApplySubmitRequest: Encodable, Equatable {
let scenicId: [Int]
let roleId: Int
enum CodingKeys: String, CodingKey {
case scenicId = "scenic_id"
case roleId = "role_id"
}
}
///
struct ScenicApplicationUploadPlaceholder: Encodable, Equatable {
let fileName: String
let fileType: String
let fileSize: Int64
enum CodingKeys: String, CodingKey {
case fileName = "file_name"
case fileType = "file_type"
case fileSize = "file_size"
}
}
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 ? "1" : "0"
}
return ""
}
///
func decodeLossyInt(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) {
return Int(value.trimmingCharacters(in: .whitespacesAndNewlines))
}
return nil
}
}