新增运营区域与飞手认证模块,并完善直播推流就绪流程
将运营区域与飞手认证从首页占位页迁移为完整模块,扩展 Live 播放与推流就绪流程,并新增飞手证书 OSS 上传。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -0,0 +1,310 @@
|
||||
//
|
||||
// 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user