接入举报摄影师正式接口

This commit is contained in:
2026-07-08 16:38:15 +08:00
parent 4a78a0c21a
commit 290a01e699
12 changed files with 2586 additions and 218 deletions

View File

@ -32,31 +32,81 @@ enum WildReportAttachmentKind: Hashable {
case payment
}
/// Mock
enum WildReportType: String, CaseIterable, Hashable {
case suspectedWild = "疑似打野"
case noWorkBadge = "未戴工牌"
case other = "其他"
///
struct WildReportType: Decodable, Hashable {
let value: Int
let label: String
var iconName: String {
switch self {
case .suspectedWild: return "person.crop.circle.badge.exclamationmark"
case .noWorkBadge: return "lanyardcard"
case .other: return "ellipsis.circle"
}
static let defaultSelected = WildReportType(value: 2, label: "疑似打野")
static let fallbackOptions = [
WildReportType(value: 1, label: "私下收款"),
WildReportType(value: 2, label: "疑似打野"),
WildReportType(value: 3, label: "未戴工牌"),
WildReportType(value: 4, label: "其他")
]
}
///
struct WildReportTypeListResponse: Decodable, Hashable {
let list: [WildReportType]
init(list: [WildReportType]) {
self.list = list
}
}
///
///
struct WildReportAttachment: Hashable {
let id: UUID
let kind: WildReportAttachmentKind
let title: String
let localFileURL: URL?
let fileName: String
let fileType: Int
let uploadedURL: String?
init(id: UUID = UUID(), kind: WildReportAttachmentKind, title: String) {
init(
id: UUID = UUID(),
kind: WildReportAttachmentKind,
title: String,
localFileURL: URL? = nil,
fileName: String? = nil,
uploadedURL: String? = nil
) {
self.id = id
self.kind = kind
self.title = title
self.localFileURL = localFileURL
self.fileName = fileName ?? "\(title).\(kind.defaultFileExtension)"
self.fileType = kind.reportFileType
self.uploadedURL = uploadedURL
}
}
extension WildReportAttachment {
///
func uploadData() throws -> Data {
guard let localFileURL else { throw OSSUploadError.emptyFile }
return try Data(contentsOf: localFileURL)
}
}
extension WildReportAttachmentKind {
/// 1 2
var reportFileType: Int {
switch self {
case .image, .payment: return 1
case .video: return 2
}
}
///
var defaultFileExtension: String {
switch self {
case .image, .payment: return "jpg"
case .video: return "mp4"
}
}
}
@ -83,6 +133,29 @@ enum WildReportStatus: String, Hashable, CaseIterable {
}
}
extension WildReportStatus {
/// 0 1 2
init(handleStatus: Int, fallbackText: String = "") {
switch handleStatus {
case 0:
self = .pending
case 1:
self = .processing
case 2:
self = .processed
default:
switch fallbackText {
case WildReportStatus.processing.rawValue:
self = .processing
case WildReportStatus.processed.rawValue:
self = .processed
default:
self = .pending
}
}
}
}
///
enum WildReportListFilter: String, CaseIterable, Hashable {
case all = "全部"
@ -91,6 +164,187 @@ enum WildReportListFilter: String, CaseIterable, Hashable {
case processed = "已处理"
}
extension WildReportListFilter {
/// 0 1 2
var handleStatusValue: Int? {
switch self {
case .all: return nil
case .pending: return 0
case .processing: return 1
case .processed: return 2
}
}
}
///
struct WildReportListRequest: Equatable {
let scenicId: Int?
let handleStatus: Int?
let page: Int
let pageSize: Int
init(
scenicId: Int?,
handleStatus: Int?,
page: Int = 1,
pageSize: Int = 10
) {
self.scenicId = scenicId
self.handleStatus = handleStatus
self.page = page
self.pageSize = pageSize
}
var queryItems: [URLQueryItem] {
var items: [URLQueryItem] = []
if let scenicId, scenicId > 0 {
items.append(URLQueryItem(name: "scenic_id", value: String(scenicId)))
}
if let handleStatus {
items.append(URLQueryItem(name: "handle_status", value: String(handleStatus)))
}
items.append(URLQueryItem(name: "page", value: String(max(1, page))))
items.append(URLQueryItem(name: "page_size", value: String(min(max(1, pageSize), 50))))
return items
}
}
///
struct WildReportListResponse: Decodable, Equatable {
let list: [WildReportListItem]
let total: Int
let page: Int
let pageSize: Int
enum CodingKeys: String, CodingKey {
case list
case total
case page
case pageSize = "page_size"
}
init(list: [WildReportListItem], total: Int, page: Int, pageSize: Int) {
self.list = list
self.total = total
self.page = page
self.pageSize = pageSize
}
}
///
struct WildReportListItem: Decodable, Equatable, Hashable {
let id: Int
let complaintNo: String
let title: String
let reportType: Int
let reportTypeText: String
let desc: String
let scenicId: Int
let scenicName: String
let locationName: String
let latitude: String
let longitude: String
let handleStatus: Int
let handleStatusText: String
let createdAt: String
enum CodingKeys: String, CodingKey {
case id
case complaintNo = "complaint_no"
case title
case reportType = "report_type"
case reportTypeText = "report_type_text"
case desc
case scenicId = "scenic_id"
case scenicName = "scenic_name"
case locationName = "location_name"
case latitude
case longitude
case handleStatus = "handle_status"
case handleStatusText = "handle_status_text"
case createdAt = "created_at"
}
init(
id: Int,
complaintNo: String,
title: String,
reportType: Int,
reportTypeText: String,
desc: String,
scenicId: Int,
scenicName: String,
locationName: String,
latitude: String,
longitude: String,
handleStatus: Int,
handleStatusText: String,
createdAt: String
) {
self.id = id
self.complaintNo = complaintNo
self.title = title
self.reportType = reportType
self.reportTypeText = reportTypeText
self.desc = desc
self.scenicId = scenicId
self.scenicName = scenicName
self.locationName = locationName
self.latitude = latitude
self.longitude = longitude
self.handleStatus = handleStatus
self.handleStatusText = handleStatusText
self.createdAt = createdAt
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(Int.self, forKey: .id) ?? 0
complaintNo = try container.decodeIfPresent(String.self, forKey: .complaintNo) ?? ""
title = try container.decodeIfPresent(String.self, forKey: .title) ?? ""
reportType = try container.decodeIfPresent(Int.self, forKey: .reportType) ?? 0
reportTypeText = try container.decodeIfPresent(String.self, forKey: .reportTypeText) ?? ""
desc = try container.decodeIfPresent(String.self, forKey: .desc) ?? ""
scenicId = try container.decodeIfPresent(Int.self, forKey: .scenicId) ?? 0
scenicName = try container.decodeIfPresent(String.self, forKey: .scenicName) ?? ""
locationName = try container.decodeIfPresent(String.self, forKey: .locationName) ?? ""
latitude = try container.decodeIfPresent(String.self, forKey: .latitude) ?? ""
longitude = try container.decodeIfPresent(String.self, forKey: .longitude) ?? ""
handleStatus = try container.decodeIfPresent(Int.self, forKey: .handleStatus) ?? 0
handleStatusText = try container.decodeIfPresent(String.self, forKey: .handleStatusText) ?? ""
createdAt = try container.decodeIfPresent(String.self, forKey: .createdAt) ?? ""
}
/// UIKit
func toRecord() -> WildReportRecord {
let scenic = scenicName.trimmingCharacters(in: .whitespacesAndNewlines)
let location = locationName.trimmingCharacters(in: .whitespacesAndNewlines)
let displayLocation: String
if !scenic.isEmpty, !location.isEmpty, scenic != location {
displayLocation = "\(scenic) · \(location)"
} else if !location.isEmpty {
displayLocation = location
} else {
displayLocation = scenic
}
return WildReportRecord(
id: complaintNo,
title: title.isEmpty ? "\(reportTypeText)举报" : title,
reportType: WildReportType(value: reportType, label: reportTypeText.isEmpty ? "其他" : reportTypeText),
status: WildReportStatus(handleStatus: handleStatus, fallbackText: handleStatusText),
location: displayLocation,
submitTime: createdAt,
description: desc,
wechatID: "",
phoneNumber: "",
imageCount: 0,
videoCount: 0,
handlerInfo: nil
)
}
}
///
struct WildReportSupplementaryEvidence: Hashable {
let id: String