feat: connect wild report risk map
This commit is contained in:
@ -868,6 +868,415 @@ enum WildReportRadarMarkerType: String, Hashable {
|
||||
case blue
|
||||
case green
|
||||
case red
|
||||
case yellow
|
||||
}
|
||||
|
||||
/// 风险地图接口标记类型,兼容后端新增枚举。
|
||||
enum WildReportRiskMarkerType: Hashable {
|
||||
case blue
|
||||
case green
|
||||
case red
|
||||
case yellow
|
||||
case unknown(String)
|
||||
|
||||
init(rawValue: String) {
|
||||
switch rawValue.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() {
|
||||
case "blue", "self", "self_location":
|
||||
self = .blue
|
||||
case "green":
|
||||
self = .green
|
||||
case "red":
|
||||
self = .red
|
||||
case "yellow":
|
||||
self = .yellow
|
||||
default:
|
||||
self = .unknown(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: String {
|
||||
switch self {
|
||||
case .blue: return "blue"
|
||||
case .green: return "green"
|
||||
case .red: return "red"
|
||||
case .yellow: return "yellow"
|
||||
case .unknown(let value): return value
|
||||
}
|
||||
}
|
||||
|
||||
var markerKind: WildReportMapMarkerKind {
|
||||
switch self {
|
||||
case .blue:
|
||||
return .selfLocation
|
||||
case .green:
|
||||
return .peerPhotographer
|
||||
case .yellow:
|
||||
return .processingClue
|
||||
case .red, .unknown:
|
||||
return .wildPhotographer
|
||||
}
|
||||
}
|
||||
|
||||
var radarType: WildReportRadarMarkerType {
|
||||
switch self {
|
||||
case .blue:
|
||||
return .blue
|
||||
case .green:
|
||||
return .green
|
||||
case .yellow:
|
||||
return .yellow
|
||||
case .red, .unknown:
|
||||
return .red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 风险地图后端状态字段,兼容数字和字符串两种形态。
|
||||
struct WildReportDecodedHandleStatus: Decodable, Equatable, Hashable {
|
||||
let intValue: Int?
|
||||
let textValue: String?
|
||||
|
||||
init(intValue: Int? = nil, textValue: String? = nil) {
|
||||
self.intValue = intValue
|
||||
self.textValue = textValue
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
if let value = try? container.decode(Int.self) {
|
||||
intValue = value
|
||||
textValue = nil
|
||||
} else if let value = try? container.decode(String.self) {
|
||||
intValue = Int(value)
|
||||
textValue = value
|
||||
} else {
|
||||
intValue = nil
|
||||
textValue = nil
|
||||
}
|
||||
}
|
||||
|
||||
var displayText: String {
|
||||
if let text = textValue?.trimmingCharacters(in: .whitespacesAndNewlines), !text.isEmpty {
|
||||
switch text {
|
||||
case "0": return WildReportStatus.pending.rawValue
|
||||
case "1": return WildReportStatus.processing.rawValue
|
||||
case "2": return WildReportStatus.processed.rawValue
|
||||
case "3": return WildReportStatus.rejected.rawValue
|
||||
default: return text
|
||||
}
|
||||
}
|
||||
return WildReportStatus(handleStatus: intValue ?? 0).rawValue
|
||||
}
|
||||
}
|
||||
|
||||
/// 附近风险地图接口返回体。
|
||||
struct WildReportRiskMapResponse: Decodable, Equatable {
|
||||
let scenicId: Int
|
||||
let scenicName: String
|
||||
let legend: [WildReportRiskLegendItem]
|
||||
let greenMarkerTip: String
|
||||
let markers: [WildReportRiskMapMarkerDTO]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case scenicId = "scenic_id"
|
||||
case scenicName = "scenic_name"
|
||||
case legend
|
||||
case greenMarkerTip = "green_marker_tip"
|
||||
case markers
|
||||
}
|
||||
|
||||
init(
|
||||
scenicId: Int,
|
||||
scenicName: String,
|
||||
legend: [WildReportRiskLegendItem] = [],
|
||||
greenMarkerTip: String = "",
|
||||
markers: [WildReportRiskMapMarkerDTO] = []
|
||||
) {
|
||||
self.scenicId = scenicId
|
||||
self.scenicName = scenicName
|
||||
self.legend = legend
|
||||
self.greenMarkerTip = greenMarkerTip
|
||||
self.markers = markers
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
scenicId = try container.decodeIfPresent(Int.self, forKey: .scenicId) ?? 0
|
||||
scenicName = try container.decodeIfPresent(String.self, forKey: .scenicName) ?? ""
|
||||
legend = try container.decodeIfPresent([WildReportRiskLegendItem].self, forKey: .legend) ?? []
|
||||
greenMarkerTip = try container.decodeIfPresent(String.self, forKey: .greenMarkerTip) ?? ""
|
||||
markers = try container.decodeIfPresent([WildReportRiskMapMarkerDTO].self, forKey: .markers) ?? []
|
||||
}
|
||||
}
|
||||
|
||||
/// 风险地图图例项,兼容后端不同字段命名。
|
||||
struct WildReportRiskLegendItem: Decodable, Equatable, Hashable {
|
||||
let markerType: String?
|
||||
let title: String?
|
||||
let color: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case markerType = "marker_type"
|
||||
case type
|
||||
case title
|
||||
case text
|
||||
case name
|
||||
case color
|
||||
}
|
||||
|
||||
init(markerType: String? = nil, title: String? = nil, color: String? = nil) {
|
||||
self.markerType = markerType
|
||||
self.title = title
|
||||
self.color = color
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
markerType = try container.decodeIfPresent(String.self, forKey: .markerType)
|
||||
?? (try container.decodeIfPresent(String.self, forKey: .type))
|
||||
title = try container.decodeIfPresent(String.self, forKey: .title)
|
||||
?? (try container.decodeIfPresent(String.self, forKey: .text))
|
||||
?? (try container.decodeIfPresent(String.self, forKey: .name))
|
||||
color = try container.decodeIfPresent(String.self, forKey: .color)
|
||||
}
|
||||
}
|
||||
|
||||
/// 风险地图列表接口的标记摘要。
|
||||
struct WildReportRiskMapMarkerDTO: Decodable, Equatable, Hashable {
|
||||
let markerType: String
|
||||
let id: Int
|
||||
let latitude: String
|
||||
let longitude: String
|
||||
let locationName: String
|
||||
let title: String
|
||||
let reportTypeText: String
|
||||
let handleStatus: WildReportDecodedHandleStatus?
|
||||
let handleStatusText: String?
|
||||
let distanceM: Double
|
||||
let createdAt: String
|
||||
let tag: String?
|
||||
let name: String?
|
||||
let avatar: String?
|
||||
let storeName: String?
|
||||
let online: Bool?
|
||||
let greenMarkerTip: String?
|
||||
let activityText: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case markerType = "marker_type"
|
||||
case id
|
||||
case latitude
|
||||
case longitude
|
||||
case locationName = "location_name"
|
||||
case title
|
||||
case reportTypeText = "report_type_text"
|
||||
case handleStatus = "handle_status"
|
||||
case handleStatusText = "handle_status_text"
|
||||
case distanceM = "distance_m"
|
||||
case createdAt = "created_at"
|
||||
case tag
|
||||
case name
|
||||
case avatar
|
||||
case storeName = "store_name"
|
||||
case online
|
||||
case greenMarkerTip = "green_marker_tip"
|
||||
case activityText = "activity_text"
|
||||
}
|
||||
|
||||
init(
|
||||
markerType: String,
|
||||
id: Int,
|
||||
latitude: String,
|
||||
longitude: String,
|
||||
locationName: String,
|
||||
title: String,
|
||||
reportTypeText: String = "",
|
||||
handleStatus: WildReportDecodedHandleStatus? = nil,
|
||||
handleStatusText: String? = nil,
|
||||
distanceM: Double = 0,
|
||||
createdAt: String = "",
|
||||
tag: String? = nil,
|
||||
name: String? = nil,
|
||||
avatar: String? = nil,
|
||||
storeName: String? = nil,
|
||||
online: Bool? = nil,
|
||||
greenMarkerTip: String? = nil,
|
||||
activityText: String? = nil
|
||||
) {
|
||||
self.markerType = markerType
|
||||
self.id = id
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
self.locationName = locationName
|
||||
self.title = title
|
||||
self.reportTypeText = reportTypeText
|
||||
self.handleStatus = handleStatus
|
||||
self.handleStatusText = handleStatusText
|
||||
self.distanceM = distanceM
|
||||
self.createdAt = createdAt
|
||||
self.tag = tag
|
||||
self.name = name
|
||||
self.avatar = avatar
|
||||
self.storeName = storeName
|
||||
self.online = online
|
||||
self.greenMarkerTip = greenMarkerTip
|
||||
self.activityText = activityText
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
markerType = try container.decodeIfPresent(String.self, forKey: .markerType) ?? ""
|
||||
id = try container.decodeIfPresent(Int.self, forKey: .id) ?? 0
|
||||
latitude = try container.decodeIfPresent(String.self, forKey: .latitude) ?? ""
|
||||
longitude = try container.decodeIfPresent(String.self, forKey: .longitude) ?? ""
|
||||
locationName = try container.decodeIfPresent(String.self, forKey: .locationName) ?? ""
|
||||
title = try container.decodeIfPresent(String.self, forKey: .title) ?? ""
|
||||
reportTypeText = try container.decodeIfPresent(String.self, forKey: .reportTypeText) ?? ""
|
||||
handleStatus = try container.decodeIfPresent(WildReportDecodedHandleStatus.self, forKey: .handleStatus)
|
||||
handleStatusText = try container.decodeIfPresent(String.self, forKey: .handleStatusText)
|
||||
distanceM = try container.decodeIfPresent(Double.self, forKey: .distanceM) ?? 0
|
||||
createdAt = try container.decodeIfPresent(String.self, forKey: .createdAt) ?? ""
|
||||
tag = try container.decodeIfPresent(String.self, forKey: .tag)
|
||||
name = try container.decodeIfPresent(String.self, forKey: .name)
|
||||
avatar = try container.decodeIfPresent(String.self, forKey: .avatar)
|
||||
storeName = try container.decodeIfPresent(String.self, forKey: .storeName)
|
||||
online = try container.decodeIfPresent(Bool.self, forKey: .online)
|
||||
greenMarkerTip = try container.decodeIfPresent(String.self, forKey: .greenMarkerTip)
|
||||
activityText = try container.decodeIfPresent(String.self, forKey: .activityText)
|
||||
}
|
||||
}
|
||||
|
||||
/// 风险地图标记详情接口返回体。
|
||||
struct WildReportMarkerDetailResponse: Decodable, Equatable, Hashable {
|
||||
let markerType: String
|
||||
let id: Int
|
||||
let title: String
|
||||
let tag: String
|
||||
let name: String
|
||||
let avatar: String
|
||||
let storeName: String
|
||||
let online: Bool
|
||||
let locationName: String
|
||||
let latitude: String
|
||||
let longitude: String
|
||||
let distanceM: Double
|
||||
let greenMarkerTip: String
|
||||
let activityText: String
|
||||
let reportTypeText: String
|
||||
let handleStatus: WildReportDecodedHandleStatus?
|
||||
let handleStatusText: String
|
||||
let desc: String
|
||||
let reporterName: String
|
||||
let reporterPhone: String
|
||||
let createdAt: String
|
||||
let reportContents: [WildReportDetailContent]
|
||||
let evidences: [WildReportDetailEvidence]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case markerType = "marker_type"
|
||||
case id
|
||||
case title
|
||||
case tag
|
||||
case name
|
||||
case avatar
|
||||
case storeName = "store_name"
|
||||
case online
|
||||
case locationName = "location_name"
|
||||
case latitude
|
||||
case longitude
|
||||
case distanceM = "distance_m"
|
||||
case greenMarkerTip = "green_marker_tip"
|
||||
case activityText = "activity_text"
|
||||
case reportTypeText = "report_type_text"
|
||||
case handleStatus = "handle_status"
|
||||
case handleStatusText = "handle_status_text"
|
||||
case desc
|
||||
case reporterName = "reporter_name"
|
||||
case reporterPhone = "reporter_phone"
|
||||
case contactPhone = "contact_phone"
|
||||
case createdAt = "created_at"
|
||||
case reportContents = "report_contents"
|
||||
case evidences
|
||||
}
|
||||
|
||||
init(
|
||||
markerType: String,
|
||||
id: Int,
|
||||
title: String = "",
|
||||
tag: String = "",
|
||||
name: String = "",
|
||||
avatar: String = "",
|
||||
storeName: String = "",
|
||||
online: Bool = false,
|
||||
locationName: String = "",
|
||||
latitude: String = "",
|
||||
longitude: String = "",
|
||||
distanceM: Double = 0,
|
||||
greenMarkerTip: String = "",
|
||||
activityText: String = "",
|
||||
reportTypeText: String = "",
|
||||
handleStatus: WildReportDecodedHandleStatus? = nil,
|
||||
handleStatusText: String = "",
|
||||
desc: String = "",
|
||||
reporterName: String = "",
|
||||
reporterPhone: String = "",
|
||||
createdAt: String = "",
|
||||
reportContents: [WildReportDetailContent] = [],
|
||||
evidences: [WildReportDetailEvidence] = []
|
||||
) {
|
||||
self.markerType = markerType
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.tag = tag
|
||||
self.name = name
|
||||
self.avatar = avatar
|
||||
self.storeName = storeName
|
||||
self.online = online
|
||||
self.locationName = locationName
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
self.distanceM = distanceM
|
||||
self.greenMarkerTip = greenMarkerTip
|
||||
self.activityText = activityText
|
||||
self.reportTypeText = reportTypeText
|
||||
self.handleStatus = handleStatus
|
||||
self.handleStatusText = handleStatusText
|
||||
self.desc = desc
|
||||
self.reporterName = reporterName
|
||||
self.reporterPhone = reporterPhone
|
||||
self.createdAt = createdAt
|
||||
self.reportContents = reportContents
|
||||
self.evidences = evidences
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
markerType = try container.decodeIfPresent(String.self, forKey: .markerType) ?? ""
|
||||
id = try container.decodeIfPresent(Int.self, forKey: .id) ?? 0
|
||||
title = try container.decodeIfPresent(String.self, forKey: .title) ?? ""
|
||||
tag = try container.decodeIfPresent(String.self, forKey: .tag) ?? ""
|
||||
name = try container.decodeIfPresent(String.self, forKey: .name) ?? ""
|
||||
avatar = try container.decodeIfPresent(String.self, forKey: .avatar) ?? ""
|
||||
storeName = try container.decodeIfPresent(String.self, forKey: .storeName) ?? ""
|
||||
online = try container.decodeIfPresent(Bool.self, forKey: .online) ?? false
|
||||
locationName = try container.decodeIfPresent(String.self, forKey: .locationName) ?? ""
|
||||
latitude = try container.decodeIfPresent(String.self, forKey: .latitude) ?? ""
|
||||
longitude = try container.decodeIfPresent(String.self, forKey: .longitude) ?? ""
|
||||
distanceM = try container.decodeIfPresent(Double.self, forKey: .distanceM) ?? 0
|
||||
greenMarkerTip = try container.decodeIfPresent(String.self, forKey: .greenMarkerTip) ?? ""
|
||||
activityText = try container.decodeIfPresent(String.self, forKey: .activityText) ?? ""
|
||||
reportTypeText = try container.decodeIfPresent(String.self, forKey: .reportTypeText) ?? ""
|
||||
handleStatus = try container.decodeIfPresent(WildReportDecodedHandleStatus.self, forKey: .handleStatus)
|
||||
handleStatusText = try container.decodeIfPresent(String.self, forKey: .handleStatusText) ?? ""
|
||||
desc = try container.decodeIfPresent(String.self, forKey: .desc) ?? ""
|
||||
reporterName = try container.decodeIfPresent(String.self, forKey: .reporterName) ?? ""
|
||||
reporterPhone = try container.decodeIfPresent(String.self, forKey: .reporterPhone)
|
||||
?? (try container.decodeIfPresent(String.self, forKey: .contactPhone))
|
||||
?? ""
|
||||
createdAt = try container.decodeIfPresent(String.self, forKey: .createdAt) ?? ""
|
||||
reportContents = try container.decodeIfPresent([WildReportDetailContent].self, forKey: .reportContents) ?? []
|
||||
evidences = try container.decodeIfPresent([WildReportDetailEvidence].self, forKey: .evidences) ?? []
|
||||
}
|
||||
}
|
||||
|
||||
/// 雷达线索举报内容条目。
|
||||
|
||||
Reference in New Issue
Block a user