Files
suixinkan_uikit/suixinkan/Features/Home/Models/LocationModels.swift
T

197 lines
5.5 KiB
Swift

//
// LocationModels.swift
// suixinkan
//
import Foundation
/// 位置上报详情,对齐 Android `LocationDetailResponse`。
struct LocationDetailResponse: Decodable, Sendable {
let status: Int
let needReport: Bool
let expireTime: Int64
enum CodingKeys: String, CodingKey {
case status
case needReport = "need_report"
case expireTime = "expire_time"
}
init(status: Int = 0, needReport: Bool = true, expireTime: Int64 = 0) {
self.status = status
self.needReport = needReport
self.expireTime = expireTime
}
}
/// 位置上报结果,对齐 Android `LocationReportResponse`。
struct LocationReportResponse: Decodable, Sendable {
let staffId: String
let expired: Int64
let status: Int
enum CodingKeys: String, CodingKey {
case staffId = "staff_id"
case expired
case status
case storeUserId = "store_user_id"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
staffId = Self.decodeFlexibleString(from: container, forKey: .staffId)
expired = try container.decodeIfPresent(Int64.self, forKey: .expired) ?? 0
status = try container.decodeIfPresent(Int.self, forKey: .status) ?? 0
}
init(staffId: String = "", expired: Int64 = 0, status: Int = 0) {
self.staffId = staffId
self.expired = expired
self.status = status
}
private static func decodeFlexibleString(
from container: KeyedDecodingContainer<CodingKeys>,
forKey key: CodingKeys,
defaultValue: String = ""
) -> String {
if let string = try? container.decode(String.self, forKey: key) {
return string
}
if let intValue = try? container.decode(Int.self, forKey: key) {
return String(intValue)
}
if let int64Value = try? container.decode(Int64.self, forKey: key) {
return String(int64Value)
}
return defaultValue
}
}
/// 历史上报类型筛选,对齐 Android `LocationReportFilterType`。
enum LocationReportFilterType: CaseIterable, Equatable {
case all
case immediate
case marked
case offline
var displayName: String {
switch self {
case .all: "全部"
case .immediate: "立即上报"
case .marked: "标记上报"
case .offline: "离线上报"
}
}
var typeCode: Int {
switch self {
case .all: 0
case .immediate: 1
case .marked: 2
case .offline: 3
}
}
var tagColorHex: UInt {
switch self {
case .all, .immediate: 0x0073FF
case .marked: 0x22C55E
case .offline: 0x999999
}
}
static func from(typeCode: Int) -> LocationReportFilterType {
switch typeCode {
case 1: .immediate
case 2: .marked
case 3: .offline
default: .all
}
}
static func fromReportType(_ type: Int) -> LocationReportFilterType {
switch type {
case 1: .immediate
case 2: .marked
case 3: .offline
default: .all
}
}
}
/// 历史上报单条记录,对齐 Android `LocationReportHistoryItem`。
struct LocationReportHistoryItem: Decodable, Equatable, Identifiable {
let id: Int64
let staffId: Int64
let type: Int
let latitude: String
let longitude: String
let address: String
let ip: String?
let remark: String
let createdAt: String
enum CodingKeys: String, CodingKey {
case id
case staffId = "staff_id"
case type
case latitude
case longitude
case address
case ip
case remark
case createdAt = "created_at"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(Int64.self, forKey: .id) ?? 0
staffId = try container.decodeIfPresent(Int64.self, forKey: .staffId) ?? 0
type = try container.decodeIfPresent(Int.self, forKey: .type) ?? 0
latitude = try container.decodeIfPresent(String.self, forKey: .latitude) ?? ""
longitude = try container.decodeIfPresent(String.self, forKey: .longitude) ?? ""
address = try container.decodeIfPresent(String.self, forKey: .address) ?? ""
ip = try container.decodeIfPresent(String.self, forKey: .ip)
remark = try container.decodeIfPresent(String.self, forKey: .remark) ?? ""
createdAt = try container.decodeIfPresent(String.self, forKey: .createdAt) ?? ""
}
init(
id: Int64 = 0,
staffId: Int64 = 0,
type: Int = 0,
latitude: String = "",
longitude: String = "",
address: String = "",
ip: String? = nil,
remark: String = "",
createdAt: String = ""
) {
self.id = id
self.staffId = staffId
self.type = type
self.latitude = latitude
self.longitude = longitude
self.address = address
self.ip = ip
self.remark = remark
self.createdAt = createdAt
}
var filterType: LocationReportFilterType {
LocationReportFilterType.fromReportType(type)
}
}
/// 历史上报列表响应。
struct LocationReportHistoryListResponse: Decodable, Equatable {
let list: [LocationReportHistoryItem]
let total: Int
init(list: [LocationReportHistoryItem] = [], total: Int = 0) {
self.list = list
self.total = total
}
}