Integrate高德 SDK with simulator-safe build flags, add map views for operating area and punch points, refactor main tabs and key feature screens to UIKit with Diffable lists, and document Swift concurrency defaults in AGENTS.md. Co-authored-by: Cursor <cursoragent@cursor.com>
321 lines
11 KiB
Swift
321 lines
11 KiB
Swift
//
|
||
// PilotCertificationModels.swift
|
||
// suixinkan
|
||
//
|
||
// Created by Codex on 2026/6/25.
|
||
//
|
||
|
||
import Foundation
|
||
|
||
/// 飞手证件类型。
|
||
enum PilotCertType: Int, CaseIterable, Identifiable {
|
||
case idCard = 1
|
||
case caac = 2
|
||
|
||
var id: Int { rawValue }
|
||
|
||
var title: String {
|
||
switch self {
|
||
case .idCard:
|
||
"身份证"
|
||
case .caac:
|
||
"民用无人机驾驶员执照"
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 飞手认证详情响应。
|
||
struct FlyerDetailResponse: Decodable, Equatable {
|
||
let id: Int
|
||
let name: String
|
||
let accountId: String
|
||
let realnameStatus: Int
|
||
let status: Int
|
||
let statusName: String
|
||
let submitTime: String
|
||
let updatedAt: String
|
||
let auditPerson: String
|
||
let auditTime: String
|
||
let auditNote: String
|
||
let certificateType: Int
|
||
let certificateNo: String
|
||
let certificateStartDate: String
|
||
let certificateEndDate: String
|
||
let certificateImage: String
|
||
let droneModel: String
|
||
let droneSn: String
|
||
let contactPhone: String
|
||
let realnameStatusText: String
|
||
let certificationLogs: [FlyerCertificationLogItem]
|
||
|
||
/// 枚举,定义相关常量或状态。
|
||
enum CodingKeys: String, CodingKey {
|
||
case id
|
||
case name = "flyer_nickname"
|
||
case accountId = "account_id"
|
||
case realnameStatus = "realname_status"
|
||
case status
|
||
case statusName = "status_text"
|
||
case submitTime = "created_at"
|
||
case updatedAt = "updated_at"
|
||
case auditPerson = "reviewer"
|
||
case auditTime = "review_time"
|
||
case auditNote = "reject_reason"
|
||
case certificateType = "certificate_type"
|
||
case certificateNo = "certificate_no"
|
||
case certificateStartDate = "certificate_start_date"
|
||
case certificateEndDate = "certificate_end_date"
|
||
case certificateImage = "certificate_image"
|
||
case droneModel = "drone_model"
|
||
case droneSn = "drone_sn"
|
||
case contactPhone = "contact_phone"
|
||
case realnameStatusText = "realname_status_text"
|
||
case certificationLogs = "flyers_certification_logs"
|
||
}
|
||
|
||
/// 初始化实例。
|
||
init(
|
||
id: Int = 0,
|
||
name: String = "",
|
||
accountId: String = "",
|
||
realnameStatus: Int = 2,
|
||
status: Int = 0,
|
||
statusName: String = "",
|
||
submitTime: String = "",
|
||
updatedAt: String = "",
|
||
auditPerson: String = "",
|
||
auditTime: String = "",
|
||
auditNote: String = "",
|
||
certificateType: Int = 2,
|
||
certificateNo: String = "",
|
||
certificateStartDate: String = "",
|
||
certificateEndDate: String = "",
|
||
certificateImage: String = "",
|
||
droneModel: String = "",
|
||
droneSn: String = "",
|
||
contactPhone: String = "",
|
||
realnameStatusText: String = "",
|
||
certificationLogs: [FlyerCertificationLogItem] = []
|
||
) {
|
||
self.id = id
|
||
self.name = name
|
||
self.accountId = accountId
|
||
self.realnameStatus = realnameStatus
|
||
self.status = status
|
||
self.statusName = statusName
|
||
self.submitTime = submitTime
|
||
self.updatedAt = updatedAt
|
||
self.auditPerson = auditPerson
|
||
self.auditTime = auditTime
|
||
self.auditNote = auditNote
|
||
self.certificateType = certificateType
|
||
self.certificateNo = certificateNo
|
||
self.certificateStartDate = certificateStartDate
|
||
self.certificateEndDate = certificateEndDate
|
||
self.certificateImage = certificateImage
|
||
self.droneModel = droneModel
|
||
self.droneSn = droneSn
|
||
self.contactPhone = contactPhone
|
||
self.realnameStatusText = realnameStatusText
|
||
self.certificationLogs = certificationLogs
|
||
}
|
||
|
||
/// 初始化实例。
|
||
init(from decoder: Decoder) throws {
|
||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||
id = try container.pilotDecodeLossyInt(forKey: .id) ?? 0
|
||
name = try container.pilotDecodeLossyString(forKey: .name)
|
||
accountId = try container.pilotDecodeLossyString(forKey: .accountId)
|
||
realnameStatus = try container.pilotDecodeLossyInt(forKey: .realnameStatus) ?? 2
|
||
status = try container.pilotDecodeLossyInt(forKey: .status) ?? 0
|
||
statusName = try container.pilotDecodeLossyString(forKey: .statusName)
|
||
submitTime = try container.pilotDecodeLossyString(forKey: .submitTime)
|
||
updatedAt = try container.pilotDecodeLossyString(forKey: .updatedAt)
|
||
auditPerson = try container.pilotDecodeLossyString(forKey: .auditPerson)
|
||
auditTime = try container.pilotDecodeLossyString(forKey: .auditTime)
|
||
auditNote = try container.pilotDecodeLossyString(forKey: .auditNote)
|
||
certificateType = try container.pilotDecodeLossyInt(forKey: .certificateType) ?? 2
|
||
certificateNo = try container.pilotDecodeLossyString(forKey: .certificateNo)
|
||
certificateStartDate = try container.pilotDecodeLossyString(forKey: .certificateStartDate)
|
||
certificateEndDate = try container.pilotDecodeLossyString(forKey: .certificateEndDate)
|
||
certificateImage = try container.pilotDecodeLossyString(forKey: .certificateImage)
|
||
droneModel = try container.pilotDecodeLossyString(forKey: .droneModel)
|
||
droneSn = try container.pilotDecodeLossyString(forKey: .droneSn)
|
||
contactPhone = try container.pilotDecodeLossyString(forKey: .contactPhone)
|
||
realnameStatusText = try container.pilotDecodeLossyString(forKey: .realnameStatusText)
|
||
certificationLogs = try container.decodeIfPresent([FlyerCertificationLogItem].self, forKey: .certificationLogs) ?? []
|
||
}
|
||
}
|
||
|
||
/// 飞手认证审核日志项。
|
||
struct FlyerCertificationLogItem: Decodable, Identifiable, Equatable {
|
||
let id: Int
|
||
let flyerId: Int
|
||
let operatorName: String
|
||
let action: Int
|
||
let actionText: String
|
||
let rejectReason: String
|
||
let remark: String
|
||
let createdAt: String
|
||
|
||
/// 枚举,定义相关常量或状态。
|
||
enum CodingKeys: String, CodingKey {
|
||
case id
|
||
case flyerId = "flyer_id"
|
||
case operatorName = "operator"
|
||
case action
|
||
case actionText = "action_text"
|
||
case rejectReason = "reject_reason"
|
||
case remark
|
||
case createdAt = "created_at"
|
||
}
|
||
|
||
/// 初始化实例。
|
||
init(
|
||
id: Int = 0,
|
||
flyerId: Int = 0,
|
||
operatorName: String = "",
|
||
action: Int = 0,
|
||
actionText: String = "",
|
||
rejectReason: String = "",
|
||
remark: String = "",
|
||
createdAt: String = ""
|
||
) {
|
||
self.id = id
|
||
self.flyerId = flyerId
|
||
self.operatorName = operatorName
|
||
self.action = action
|
||
self.actionText = actionText
|
||
self.rejectReason = rejectReason
|
||
self.remark = remark
|
||
self.createdAt = createdAt
|
||
}
|
||
|
||
/// 初始化实例。
|
||
init(from decoder: Decoder) throws {
|
||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||
id = try container.pilotDecodeLossyInt(forKey: .id) ?? 0
|
||
flyerId = try container.pilotDecodeLossyInt(forKey: .flyerId) ?? 0
|
||
operatorName = try container.pilotDecodeLossyString(forKey: .operatorName)
|
||
action = try container.pilotDecodeLossyInt(forKey: .action) ?? 0
|
||
actionText = try container.pilotDecodeLossyString(forKey: .actionText)
|
||
rejectReason = try container.pilotDecodeLossyString(forKey: .rejectReason)
|
||
remark = try container.pilotDecodeLossyString(forKey: .remark)
|
||
createdAt = try container.pilotDecodeLossyString(forKey: .createdAt)
|
||
}
|
||
}
|
||
|
||
/// 飞手认证短信验证码请求。
|
||
struct FlyerSendCodeRequest: Encodable, Equatable {
|
||
let phone: String
|
||
}
|
||
|
||
/// 飞手首次认证申请请求。
|
||
struct FlyerApplyRequest: Encodable, Equatable {
|
||
let name: String
|
||
let realnameStatus: Int
|
||
let certificateType: Int
|
||
let certificateNo: String
|
||
let certificateStartDate: String
|
||
let certificateEndDate: String
|
||
let certificateImage: String
|
||
let droneModel: String
|
||
let droneSn: String
|
||
let contactPhone: String
|
||
let code: String
|
||
|
||
/// 枚举,定义相关常量或状态。
|
||
enum CodingKeys: String, CodingKey {
|
||
case name
|
||
case realnameStatus = "realname_status"
|
||
case certificateType = "certificate_type"
|
||
case certificateNo = "certificate_no"
|
||
case certificateStartDate = "certificate_start_date"
|
||
case certificateEndDate = "certificate_end_date"
|
||
case certificateImage = "certificate_image"
|
||
case droneModel = "drone_model"
|
||
case droneSn = "drone_sn"
|
||
case contactPhone = "contact_phone"
|
||
case code
|
||
}
|
||
}
|
||
|
||
/// 飞手认证驳回后编辑请求。
|
||
struct FlyerEditRequest: Encodable, Equatable {
|
||
let id: Int
|
||
let name: String
|
||
let realnameStatus: Int
|
||
let certificateType: Int
|
||
let certificateNo: String
|
||
let certificateStartDate: String
|
||
let certificateEndDate: String
|
||
let certificateImage: String
|
||
let droneModel: String
|
||
let droneSn: String
|
||
let contactPhone: String
|
||
let code: String
|
||
|
||
/// 枚举,定义相关常量或状态。
|
||
enum CodingKeys: String, CodingKey {
|
||
case id
|
||
case name
|
||
case realnameStatus = "realname_status"
|
||
case certificateType = "certificate_type"
|
||
case certificateNo = "certificate_no"
|
||
case certificateStartDate = "certificate_start_date"
|
||
case certificateEndDate = "certificate_end_date"
|
||
case certificateImage = "certificate_image"
|
||
case droneModel = "drone_model"
|
||
case droneSn = "drone_sn"
|
||
case contactPhone = "contact_phone"
|
||
case code
|
||
}
|
||
}
|
||
|
||
/// 飞手认证校验错误。
|
||
enum PilotCertificationValidationError: LocalizedError, Equatable {
|
||
case message(String)
|
||
|
||
var errorDescription: String? {
|
||
switch self {
|
||
case .message(let message):
|
||
message
|
||
}
|
||
}
|
||
}
|
||
|
||
private extension KeyedDecodingContainer {
|
||
/// pilot解码宽松字符串相关逻辑。
|
||
func pilotDecodeLossyString(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 ""
|
||
}
|
||
|
||
/// pilot解码宽松整数相关逻辑。
|
||
func pilotDecodeLossyInt(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
|
||
}
|
||
}
|