Files
suixinkan_uikit/suixinkan/Features/Profile/Models/ProfileModels.swift

627 lines
22 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.

//
// ProfileModels.swift
// suixinkan
//
import Foundation
///
struct UserInfoResponse: Decodable, Equatable {
let avatar: String
let realName: String
let phone: String
let nickname: String
let roleName: String
let status: Int
let statusName: String
enum CodingKeys: String, CodingKey {
case avatar
case realName = "real_name"
case phone
case nickname
case roleName = "role_name"
case status
case statusName = "status_name"
}
init(
avatar: String = "",
realName: String = "",
phone: String = "",
nickname: String = "",
roleName: String = "",
status: Int = 0,
statusName: String = ""
) {
self.avatar = avatar
self.realName = realName
self.phone = phone
self.nickname = nickname
self.roleName = roleName
self.status = status
self.statusName = statusName
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
avatar = try container.decodeLossyString(forKey: .avatar)
realName = try container.decodeLossyString(forKey: .realName)
phone = try container.decodeLossyString(forKey: .phone)
nickname = try container.decodeLossyString(forKey: .nickname)
roleName = try container.decodeLossyString(forKey: .roleName)
status = try container.decodeLossyInt(forKey: .status) ?? 0
statusName = try container.decodeLossyString(forKey: .statusName)
}
}
///
struct UpdateInfoRequest: Encodable {
let nickname: String?
let password: String?
let avatar: String?
}
/// Android `ProfileInfoResponse`
struct PhotographerProfileInfoResponse: Decodable, Equatable {
let id: Int
let scenicId: Int
let photogUid: Int
let realName: String
let nickname: String
let avatar: String
let scenicCertification: [String]
let description: String
let attrLabel: [String]
let shootLabel: [String]
let cameraDevice: [String]
let businessStartTime: String
let businessEndTime: String
let holidayStartTime: String
let holidayEndTime: String
let businessRange: [Int]
let acceptOrderStatus: Int
let schedule: [String: [PhotographerSchedule]]
let virtualPhone: String
enum CodingKeys: String, CodingKey {
case id
case scenicId = "scenic_id"
case photogUid = "photog_uid"
case realName = "real_name"
case nickname
case avatar
case scenicCertification = "scenic_certification"
case description
case attrLabel = "attr_label"
case shootLabel = "shoot_label"
case cameraDevice = "camera_device"
case businessStartTime = "business_start_time"
case businessEndTime = "business_end_time"
case holidayStartTime = "holiday_start_time"
case holidayEndTime = "holiday_end_time"
case businessRange = "business_range"
case acceptOrderStatus = "accept_order_status"
case schedule
case virtualPhone = "virtual_phone"
}
init(
id: Int = 0,
scenicId: Int = 0,
photogUid: Int = 0,
realName: String = "",
nickname: String = "",
avatar: String = "",
scenicCertification: [String] = [],
description: String = "",
attrLabel: [String] = [],
shootLabel: [String] = [],
cameraDevice: [String] = [],
businessStartTime: String = "",
businessEndTime: String = "",
holidayStartTime: String = "",
holidayEndTime: String = "",
businessRange: [Int] = [],
acceptOrderStatus: Int = 0,
schedule: [String: [PhotographerSchedule]] = [:],
virtualPhone: String = ""
) {
self.id = id
self.scenicId = scenicId
self.photogUid = photogUid
self.realName = realName
self.nickname = nickname
self.avatar = avatar
self.scenicCertification = scenicCertification
self.description = description
self.attrLabel = attrLabel
self.shootLabel = shootLabel
self.cameraDevice = cameraDevice
self.businessStartTime = businessStartTime
self.businessEndTime = businessEndTime
self.holidayStartTime = holidayStartTime
self.holidayEndTime = holidayEndTime
self.businessRange = businessRange
self.acceptOrderStatus = acceptOrderStatus
self.schedule = schedule
self.virtualPhone = virtualPhone
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeLossyInt(forKey: .id) ?? 0
scenicId = try container.decodeLossyInt(forKey: .scenicId) ?? 0
photogUid = try container.decodeLossyInt(forKey: .photogUid) ?? 0
realName = try container.decodeLossyString(forKey: .realName)
nickname = try container.decodeLossyString(forKey: .nickname)
avatar = try container.decodeLossyString(forKey: .avatar)
scenicCertification = try container.decodeLossyStringArray(forKey: .scenicCertification)
description = try container.decodeLossyString(forKey: .description)
attrLabel = try container.decodeLossyStringArray(forKey: .attrLabel)
shootLabel = try container.decodeLossyStringArray(forKey: .shootLabel)
cameraDevice = try container.decodeLossyStringArray(forKey: .cameraDevice)
businessStartTime = try container.decodeLossyString(forKey: .businessStartTime)
businessEndTime = try container.decodeLossyString(forKey: .businessEndTime)
holidayStartTime = try container.decodeLossyString(forKey: .holidayStartTime)
holidayEndTime = try container.decodeLossyString(forKey: .holidayEndTime)
businessRange = try container.decodeLossyIntArray(forKey: .businessRange)
acceptOrderStatus = try container.decodeLossyInt(forKey: .acceptOrderStatus) ?? 0
schedule = try container.decodeScheduleMap(forKey: .schedule)
virtualPhone = try container.decodeLossyString(forKey: .virtualPhone)
}
}
/// Android `ScheduleEntity`
struct PhotographerSchedule: Decodable, Equatable, Hashable, Sendable {
let id: Int
let name: String
let remark: String
let startTime: String
let endTime: String
let scheduleDate: String
let orderNumber: String?
let userNickname: String?
let userPhone: String?
let orderStatus: Int?
let orderStatusName: String?
enum CodingKeys: String, CodingKey {
case id
case name
case remark
case startTime = "start_time"
case endTime = "end_time"
case scheduleDate = "schedule_date"
case orderNumber = "order_number"
case userNickname = "user_nickname"
case userPhone = "user_phone"
case orderStatus = "order_status"
case orderStatusName = "order_status_name"
}
init(
id: Int = 0,
name: String = "",
remark: String = "",
startTime: String = "",
endTime: String = "",
scheduleDate: String = "",
orderNumber: String? = nil,
userNickname: String? = nil,
userPhone: String? = nil,
orderStatus: Int? = nil,
orderStatusName: String? = nil
) {
self.id = id
self.name = name
self.remark = remark
self.startTime = startTime
self.endTime = endTime
self.scheduleDate = scheduleDate
self.orderNumber = orderNumber
self.userNickname = userNickname
self.userPhone = userPhone
self.orderStatus = orderStatus
self.orderStatusName = orderStatusName
}
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)
remark = try container.decodeLossyString(forKey: .remark)
startTime = try container.decodeLossyString(forKey: .startTime)
endTime = try container.decodeLossyString(forKey: .endTime)
scheduleDate = try container.decodeLossyString(forKey: .scheduleDate)
orderNumber = try container.decodeIfPresent(String.self, forKey: .orderNumber)
userNickname = try container.decodeIfPresent(String.self, forKey: .userNickname)
userPhone = try container.decodeIfPresent(String.self, forKey: .userPhone)
orderStatus = try container.decodeLossyInt(forKey: .orderStatus)
orderStatusName = try container.decodeIfPresent(String.self, forKey: .orderStatusName)
}
}
/// Android `UpdateProfileInfoRequest`
struct UpdatePhotographerProfileInfoRequest: Encodable, Equatable {
let scenicId: String
let description: String
let cameraDevice: [String]
let attrLabel: [String]
let shootLabel: [String]
let businessStartTime: String
let businessEndTime: String
let holidayStartTime: String
let holidayEndTime: String
let businessRange: [Int]
let acceptOrderStatus: Int
enum CodingKeys: String, CodingKey {
case scenicId = "scenic_id"
case description
case cameraDevice = "camera_device"
case attrLabel = "attr_label"
case shootLabel = "shoot_label"
case businessStartTime = "business_start_time"
case businessEndTime = "business_end_time"
case holidayStartTime = "holiday_start_time"
case holidayEndTime = "holiday_end_time"
case businessRange = "business_range"
case acceptOrderStatus = "accept_order_status"
}
}
/// Android `AddScheduleRequest`
struct AddPhotographerScheduleRequest: Encodable, Equatable {
var scenicId: String
var name: String
var remark: String
var startTime: String
var endTime: String
var scheduleDate: String
var orderNumber: String?
enum CodingKeys: String, CodingKey {
case scenicId = "scenic_id"
case name
case remark
case startTime = "start_time"
case endTime = "end_time"
case scheduleDate = "schedule_date"
case orderNumber = "order_number"
}
}
/// Android `ScheduleDeleteRequest`
struct PhotographerScheduleDeleteRequest: Encodable, Equatable {
let id: Int
}
///
struct RealNameInfoResponse: Decodable, Equatable {
let realNameInfo: RealNameInfo?
enum CodingKeys: String, CodingKey {
case realNameInfo = "real_name_info"
}
}
///
struct RealNameInfo: Decodable, Equatable {
let realName: String
let idCardNo: String
let auditStatus: Int
let auditStatusText: String?
let rejectReason: String?
let startDate: String?
let endDate: String?
let isLongValid: Bool
let frontUrl: String?
let backUrl: String?
let auditorId: Int?
let auditor: RealNameAuditor?
let auditAt: String?
var verified: Bool {
auditStatus == 2
}
enum CodingKeys: String, CodingKey {
case realName = "real_name"
case idCardNo = "id_card_no"
case auditStatus = "audit_status"
case auditStatusText = "audit_status_text"
case rejectReason = "reject_reason"
case startDate = "start_date"
case endDate = "end_date"
case isLongValid = "is_long_valid"
case frontUrl = "front_url"
case backUrl = "back_url"
case auditorId = "auditor_id"
case auditor
case auditAt = "audit_at"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
realName = try container.decodeLossyString(forKey: .realName)
idCardNo = try container.decodeLossyString(forKey: .idCardNo)
auditStatus = try container.decodeLossyInt(forKey: .auditStatus) ?? 0
auditStatusText = try container.decodeIfPresent(String.self, forKey: .auditStatusText)
rejectReason = try container.decodeIfPresent(String.self, forKey: .rejectReason)
startDate = try container.decodeIfPresent(String.self, forKey: .startDate)
endDate = try container.decodeIfPresent(String.self, forKey: .endDate)
isLongValid = (try container.decodeLossyInt(forKey: .isLongValid) ?? 0) == 1
frontUrl = try container.decodeIfPresent(String.self, forKey: .frontUrl)
backUrl = try container.decodeIfPresent(String.self, forKey: .backUrl)
auditorId = try container.decodeLossyInt(forKey: .auditorId)
auditor = try container.decodeIfPresent(RealNameAuditor.self, forKey: .auditor)
auditAt = try container.decodeIfPresent(String.self, forKey: .auditAt)
}
}
///
struct RealNameAuditor: Decodable, Equatable {
let id: Int
let name: String
enum CodingKeys: String, CodingKey {
case id
case name
}
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 RealNameAuthRequest: Encodable, Equatable {
let realName: String
let idCardNo: String
let smsVerifyCode: String
let startDate: String
let endDate: String
let isLongValid: Int
let frontUrl: String
let backUrl: String
enum CodingKeys: String, CodingKey {
case realName = "real_name"
case idCardNo = "id_card_no"
case smsVerifyCode = "sms_verify_code"
case startDate = "start_date"
case endDate = "end_date"
case isLongValid = "is_long_valid"
case frontUrl = "front_url"
case backUrl = "back_url"
}
}
///
struct BankCardInfoResponse: Decodable, Equatable {
let bankCard: BankCardInfo?
enum CodingKeys: String, CodingKey {
case bankCard = "bank_card"
}
}
///
struct BankCardInfo: Decodable, Equatable {
let realName: String
let bankName: String
let branchName: String
let cardNumber: String
let frontUrl: String?
let backUrl: String?
let provinceCode: String?
let cityCode: String?
let rejectReason: String
let auditStatus: Int
let auditStatusLabel: String
let auditAt: String?
let auditorId: Int?
let auditor: RealNameAuditor?
enum CodingKeys: String, CodingKey {
case realName = "real_name"
case bankName = "bank_name"
case branchName = "branch_name"
case cardNumber = "card_number"
case frontUrl = "front_url"
case backUrl = "back_url"
case provinceCode = "province_code"
case cityCode = "city_code"
case rejectReason = "reject_reason"
case auditStatus = "audit_status"
case auditStatusLabel = "audit_status_label"
case auditAt = "audit_at"
case auditorId = "auditor_id"
case auditor
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
realName = try container.decodeLossyString(forKey: .realName)
bankName = try container.decodeLossyString(forKey: .bankName)
branchName = try container.decodeLossyString(forKey: .branchName)
cardNumber = try container.decodeLossyString(forKey: .cardNumber)
frontUrl = try container.decodeIfPresent(String.self, forKey: .frontUrl)
backUrl = try container.decodeIfPresent(String.self, forKey: .backUrl)
provinceCode = try container.decodeIfPresent(String.self, forKey: .provinceCode)
cityCode = try container.decodeIfPresent(String.self, forKey: .cityCode)
rejectReason = try container.decodeLossyString(forKey: .rejectReason)
auditStatus = try container.decodeLossyInt(forKey: .auditStatus) ?? 0
auditStatusLabel = try container.decodeLossyString(forKey: .auditStatusLabel)
auditAt = try container.decodeIfPresent(String.self, forKey: .auditAt)
auditorId = try container.decodeLossyInt(forKey: .auditorId)
auditor = try container.decodeIfPresent(RealNameAuditor.self, forKey: .auditor)
}
}
///
struct BankListResponse: Decodable, Equatable {
let banks: [String]
enum CodingKeys: String, CodingKey {
case banks
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
banks = try container.decodeIfPresent([String].self, forKey: .banks) ?? []
}
}
///
struct AreasResponse: Decodable, Equatable, Identifiable {
let id: Int
let code: String
let name: String
let children: [AreasResponse]
enum CodingKeys: String, CodingKey {
case id
case code
case name
case children
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeLossyInt(forKey: .id)
?? container.decodeLossyInt(forKey: .code)
?? 0
let decodedCode = try container.decodeLossyString(forKey: .code)
.trimmingCharacters(in: .whitespacesAndNewlines)
code = decodedCode.isEmpty ? "\(id)" : decodedCode
name = try container.decodeLossyString(forKey: .name)
children = try container.decodeIfPresent([AreasResponse].self, forKey: .children) ?? []
}
init(id: Int, code: String, name: String, children: [AreasResponse] = []) {
self.id = id
self.code = code
self.name = name
self.children = children
}
}
///
struct UpdateBankInfoRequest: Encodable, Equatable {
let realName: String
let cardNumber: String
let bankName: String
let branchName: String
let frontUrl: String
let backUrl: String
let provinceCode: String
let cityCode: String
let smsVerifyCode: String
enum CodingKeys: String, CodingKey {
case realName = "real_name"
case cardNumber = "card_number"
case bankName = "bank_name"
case branchName = "branch_name"
case frontUrl = "front_url"
case backUrl = "back_url"
case provinceCode = "province_code"
case cityCode = "city_code"
case smsVerifyCode = "sms_verify_code"
}
}
///
enum ProfileValidationError: LocalizedError, Equatable {
case emptyNickname
case shortPassword
var errorDescription: String? {
switch self {
case .emptyNickname:
"请输入昵称"
case .shortPassword:
"密码至少 6 位"
}
}
}
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
}
func decodeLossyStringArray(forKey key: Key) throws -> [String] {
if let values = try? decodeIfPresent([String].self, forKey: key) {
return values
}
if let values = try? decodeIfPresent([Int].self, forKey: key) {
return values.map(String.init)
}
if let value = try? decodeIfPresent(String.self, forKey: key) {
let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
return text.isEmpty ? [] : [text]
}
return []
}
func decodeLossyIntArray(forKey key: Key) throws -> [Int] {
if let values = try? decodeIfPresent([Int].self, forKey: key) {
return values
}
if let values = try? decodeIfPresent([String].self, forKey: key) {
return values.compactMap { Int($0.trimmingCharacters(in: .whitespacesAndNewlines)) }
}
if let value = try? decodeIfPresent(Int.self, forKey: key) {
return [value]
}
return []
}
func decodeScheduleMap(forKey key: Key) throws -> [String: [PhotographerSchedule]] {
if let values = try? decodeIfPresent([String: [PhotographerSchedule]].self, forKey: key) {
return values
}
if let values = try? decodeIfPresent([PhotographerSchedule].self, forKey: key) {
return Dictionary(grouping: values) { $0.scheduleDate }
.filter { !$0.key.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
}
return [:]
}
}