feat: connect wild report risk map

This commit is contained in:
2026-07-08 17:52:29 +08:00
parent fd5dc2bbe6
commit 939295d74a
6 changed files with 1829 additions and 135 deletions

View File

@ -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) ?? []
}
}
/// 线