// // WildPhotographerReportAPI.swift // suixinkan // import Foundation /// 举报摄影师服务协议,封装举报类型等后端接口。 @MainActor protocol WildPhotographerReportServing { /// 拉取提交举报可选类型。 func reportTypes() async throws -> WildReportTypeListResponse /// 拉取举报首页须知与规则文案。 func reportCopy() async throws -> WildReportCopyResponse /// 提交摄影师举报。 func submitReport(_ request: WildReportSubmitRequest) async throws -> WildReportSubmitResponse /// 为已有举报补充证据。 func supplementReport(_ request: WildReportSupplementRequest) async throws /// 拉取附近风险地图点位。 func riskMap(_ request: WildReportRiskMapRequest) async throws -> WildReportRiskMapResponse /// 拉取风险地图单个标记详情。 func markerDetail(_ request: WildReportMarkerDetailRequest) async throws -> WildReportMarkerDetailResponse /// 拉取我的举报列表。 func reportList(_ request: WildReportListRequest) async throws -> WildReportListResponse /// 拉取单条举报详情。 func reportDetail(id: Int) async throws -> WildReportDetailData } /// 举报摄影师 API,负责和 `photog/report` 相关接口通讯。 @MainActor final class WildPhotographerReportAPI: WildPhotographerReportServing { private let client: APIClient /// 初始化举报摄影师 API。 init(client: APIClient) { self.client = client } /// 拉取提交举报可选类型。 func reportTypes() async throws -> WildReportTypeListResponse { try await client.send( APIRequest(method: .get, path: "/api/yf-handset-app/photog/report/types") ) } /// 拉取举报首页须知与规则文案。 func reportCopy() async throws -> WildReportCopyResponse { try await client.send( APIRequest(method: .get, path: "/api/yf-handset-app/photog/report/copy") ) } /// 提交摄影师举报。 func submitReport(_ request: WildReportSubmitRequest) async throws -> WildReportSubmitResponse { try await client.send( APIRequest( method: .post, path: "/api/yf-handset-app/photog/report/submit", body: request ) ) } /// 为已有举报补充证据。 func supplementReport(_ request: WildReportSupplementRequest) async throws { let _: EmptyPayload = try await client.send( APIRequest( method: .post, path: "/api/yf-handset-app/photog/report/supplement", body: request ) ) } /// 拉取附近风险地图点位。 func riskMap(_ request: WildReportRiskMapRequest) async throws -> WildReportRiskMapResponse { try await client.send( APIRequest( method: .get, path: "/api/yf-handset-app/photog/report/risk-map", queryItems: request.queryItems ) ) } /// 拉取风险地图单个标记详情。 func markerDetail(_ request: WildReportMarkerDetailRequest) async throws -> WildReportMarkerDetailResponse { try await client.send( APIRequest( method: .get, path: "/api/yf-handset-app/photog/report/marker-detail", queryItems: request.queryItems ) ) } /// 拉取我的举报列表。 func reportList(_ request: WildReportListRequest) async throws -> WildReportListResponse { try await client.send( APIRequest( method: .get, path: "/api/yf-handset-app/photog/report/list", queryItems: request.queryItems ) ) } /// 拉取单条举报详情。 func reportDetail(id: Int) async throws -> WildReportDetailData { try await client.send( APIRequest( method: .get, path: "/api/yf-handset-app/photog/report/detail", queryItems: [URLQueryItem(name: "id", value: String(id))] ) ) } } /// 补充证据接口请求体。 struct WildReportSupplementRequest: Encodable, Equatable { let id: Int let desc: String? let evidences: [WildReportEvidenceRequest]? } /// 附近风险地图接口请求参数。 struct WildReportRiskMapRequest: Encodable, Equatable { let scenicId: Int let latitude: Double? let longitude: Double? var queryItems: [URLQueryItem] { var items = [URLQueryItem(name: "scenic_id", value: String(scenicId))] if let latitude { items.append(URLQueryItem(name: "latitude", value: String(latitude))) } if let longitude { items.append(URLQueryItem(name: "longitude", value: String(longitude))) } return items } enum CodingKeys: String, CodingKey { case scenicId = "scenic_id" case latitude case longitude } } /// 风险地图标记详情接口请求参数。 struct WildReportMarkerDetailRequest: Encodable, Equatable { let scenicId: Int let markerType: String let id: Int let latitude: Double? let longitude: Double? var queryItems: [URLQueryItem] { var items = [ URLQueryItem(name: "scenic_id", value: String(scenicId)), URLQueryItem(name: "marker_type", value: markerType), URLQueryItem(name: "id", value: String(id)) ] if let latitude { items.append(URLQueryItem(name: "latitude", value: String(latitude))) } if let longitude { items.append(URLQueryItem(name: "longitude", value: String(longitude))) } return items } enum CodingKeys: String, CodingKey { case scenicId = "scenic_id" case markerType = "marker_type" case id case latitude case longitude } } /// 提交举报接口请求体。 struct WildReportSubmitRequest: Encodable, Equatable { let scenicId: Int let reportType: Int let desc: String let storeUserId: Int? let contactPhone: String? let locationName: String? let locationAddress: String? let lat: Double let lng: Double let evidences: [WildReportEvidenceRequest] let paymentScreenshots: [WildReportEvidenceRequest] enum CodingKeys: String, CodingKey { case scenicId = "scenic_id" case reportType = "report_type" case desc case storeUserId = "store_user_id" case contactPhone = "contact_phone" case locationName = "location_name" case locationAddress = "location_address" case lat case lng case evidences case paymentScreenshots = "payment_screenshots" } } /// 提交举报接口响应体,包含后端生成的举报 ID 和举报编号。 struct WildReportSubmitResponse: Decodable, Equatable { let id: Int let complaintNo: String enum CodingKeys: String, CodingKey { case id case complaintNo = "complaint_no" } init(id: Int = 0, complaintNo: String = "") { self.id = id self.complaintNo = complaintNo } 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) ?? "" } } /// 提交举报接口中的附件项。 struct WildReportEvidenceRequest: Encodable, Equatable { let fileURL: String let fileType: Int let fileName: String? enum CodingKeys: String, CodingKey { case fileURL = "file_url" case fileType = "file_type" case fileName = "file_name" } }