// // 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 { 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 "" } 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 } }