15 KiB
15 KiB
举报摄影师接口文档
本文档记录 iOS WildPhotographerReport 模块当前使用的后端接口。
基础约定
- 业务域:举报摄影师
- API 封装:
suixinkan/Features/WildPhotographerReport/API/WildPhotographerReportAPI.swift - 网络入口:
NetworkServices.shared.wildPhotographerReportAPI - 后端成功码:
100000 - 响应包裹:工程统一
APIEnvelope<T> - 当前状态:“首页文案”、“举报类型”、“提交举报”、“我的举报列表”、“举报详情”、“微信小程序分享”、“补充证据提交”和“附近风险地图”已接接口;模块内生产 Mock 数据已移除。
首页文案
用途
“举报摄影师”首页进入时拉取举报须知和举报规则文案。
请求
GET /api/yf-handset-app/photog/report/copy
响应示例
{
"code": 100000,
"msg": "success",
"data": {
"notice": [
"需实名登录",
"请尽量上传清晰证据",
"恶意举报将被追责"
],
"rule_groups": [
{
"title": "可举报行为",
"items": [
"疑似打野摄影师主动揽客",
"未佩戴工牌开展摄影服务",
"引导游客线下付款或私下交易"
]
}
]
},
"time": "2026-07-09 10:15:17"
}
UI 行为
notice用于首页“举报须知”条目展示。rule_groups非空时显示“举报规则”按钮,点击后在举报规则页按分组展示title和items。notice与rule_groups都为空时,隐藏整个“举报须知”模块。- 接口失败时不展示本地写死兜底文案,并 toast 错误。
当前调用位置
WildPhotographerReportHomeViewController.viewDidLoad()WildPhotographerReportHomeViewModel.loadReportCopy(api:)WildPhotographerReportAPI.reportCopy()
1. 获取举报类型
用途
提交举报页面进入时拉取可选举报类型。举报类型由后台动态维护,客户端不能用枚举写死,也不展示图标。
请求
GET /api/yf-handset-app/photog/report/types
请求参数
无。
响应示例
{
"code": 100000,
"msg": "success",
"data": {
"list": [
{
"value": 1,
"label": "私下收款"
},
{
"value": 2,
"label": "疑似打野"
},
{
"value": 3,
"label": "未戴工牌"
},
{
"value": 4,
"label": "其他"
}
]
},
"time": "2026-07-08 14:21:21"
}
iOS 模型
struct WildReportType: Decodable, Hashable {
let value: Int
let label: String
}
struct WildReportTypeListResponse: Decodable, Hashable {
let list: [WildReportType]
}
UI 行为
- 页面加载时调用
WildPhotographerReportSubmitViewModel.loadReportTypes(api:)。 - 按接口返回顺序渲染举报类型。
- 每行最多展示 3 个类型,超过 3 个自动换行。
- 按
label展示文字,不展示图标。 - 默认选中
value == 2的类型;如果接口返回中不存在该类型,则选中列表第一项。 - 接口失败时不展示本地默认类型,并 toast 错误。
当前调用位置
WildPhotographerReportSubmitViewController.viewDidLoad()WildPhotographerReportSubmitViewModel.loadReportTypes(api:)WildPhotographerReportAPI.reportTypes()
2. 提交举报
用途
提交页点击“提交举报”时调用。客户端会先把现场证据和支付截图上传到 OSS,全部上传成功后再提交表单数据。
请求
POST /api/yf-handset-app/photog/report/submit
请求参数
{
"scenic_id": 1,
"report_type": 2,
"desc": "疑似人员在观景台附近主动揽客,并引导游客线下转账。",
"contact_phone": "13800138000",
"location_name": "黄山风景区",
"location_address": "光明顶景区",
"lat": 30.12345,
"lng": 120.12345,
"evidences": [
{
"file_url": "https://example.com/photog_report/20260708/1/report_image.jpg",
"file_type": 1,
"file_name": "report_image.jpg"
},
{
"file_url": "https://example.com/photog_report/20260708/1/report_video.mp4",
"file_type": 2,
"file_name": "report_video.mp4"
}
],
"payment_screenshots": [
{
"file_url": "https://example.com/photog_report/20260708/1/payment.jpg",
"file_type": 1,
"file_name": "payment.jpg"
}
]
}
字段说明
scenic_id:当前景区 ID,来自AppStore.shared.currentScenicId,必须大于 0。report_type:举报类型接口返回的value。desc:举报说明,必填,最多 500 字。store_user_id:被举报摄影师 ID;当前页面无来源,本轮暂不传。contact_phone:当前联系方式输入值,非空才传。location_name/location_address:从当前定位展示文案拆分;无法拆分时使用景区名和完整地址兜底。lat/lng:当前定位快照坐标;定位失败时不提交举报,提示用户重新获取位置。evidences:现场证据,必填,至少 1 项、最多 9 项。payment_screenshots:线下微信、支付宝截图,选填,最多 3 张。file_type:举报提交接口约定为1 = 图片,2 = 视频。
iOS 模型
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]
}
struct WildReportEvidenceRequest: Encodable, Equatable {
let fileURL: String
let fileType: Int
let fileName: String?
}
UI 与上传行为
- 图片、视频和支付截图使用系统相册选择器。
- 图片/视频选择后先保存到本地临时目录,点击附件 tile 可预览本地文件。
- 提交时顺序上传附件到 OSS,按钮展示上传进度并禁用重复提交。
- 任一 OSS 上传失败时不调用提交接口,并保留用户已填写内容。
- 支付截图通过
payment_screenshots独立提交,不替代现场证据必填校验。
当前调用位置
WildPhotographerReportSubmitViewController.submitTapped()WildPhotographerReportSubmitViewModel.submitReport(api:uploader:scenicId:scenicName:)OSSUploadService.uploadWildReportAttachment(...)WildPhotographerReportAPI.submitReport(_:)
3. 我的举报列表
用途
“我的举报”页面进入、切换状态筛选、滚动加载更多时调用。
请求
GET /api/yf-handset-app/photog/report/list
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
scenic_id |
integer | 可选,当前景区 ID,大于 0 时传 |
handle_status |
integer | 可选,状态筛选;“全部”不传该参数,其他筛选 iOS 固定使用该参数 |
status |
integer | 可选,与 handle_status 等价;iOS 不传 |
page |
integer | 可选,默认 1 |
page_size |
integer | 可选,默认 10,最大 50 |
状态码
- 全部:不传
handle_status 0:待处理1:处理中2:已处理
响应示例
{
"code": 100000,
"msg": "success",
"data": {
"list": [
{
"id": 32,
"complaint_no": "JB20260708917",
"title": "私下收款举报",
"report_type": 1,
"report_type_text": "私下收款",
"desc": "我在",
"scenic_id": 128,
"scenic_name": "伊犁那拉提景区-5A",
"location_name": "伊犁那拉提景区-5A",
"latitude": "32.4299428",
"longitude": "119.4403263",
"handle_status": 0,
"handle_status_text": "待处理",
"created_at": "2026-07-08 16:06:59"
}
],
"total": 1,
"page": 1,
"page_size": 10
},
"time": "2026-07-08 16:07:30"
}
iOS 模型
struct WildReportListRequest: Equatable {
let scenicId: Int?
let handleStatus: Int?
let page: Int
let pageSize: Int
}
struct WildReportListResponse: Decodable, Equatable {
let list: [WildReportListItem]
let total: Int
let page: Int
let pageSize: Int
}
UI 行为
- 页面首次进入请求
page=1&page_size=10,不传handle_status。 - 切换筛选时重置为第一页,待处理传
handle_status=0,处理中传handle_status=1,已处理传handle_status=2。 - 滚动到底部时,如果仍有更多数据,则请求下一页并追加。
- 首屏失败显示 toast 和空态;加载更多失败只 toast,并保留已有列表。
- 列表接口暂不返回媒体数量,
WildReportRecord.imageCount/videoCount暂按 0 处理,进入详情页后由详情接口补齐。
当前调用位置
WildPhotographerReportListViewController.viewDidLoad()WildPhotographerReportListViewModel.loadInitial(api:scenicId:)WildPhotographerReportListViewModel.loadMoreIfNeeded(api:scenicId:)WildPhotographerReportAPI.reportList(_:)
4. 举报详情
用途
“举报详情”页面进入时调用。列表页传入 WildReportRecord.serverID,详情接口返回完整举报信息、现场证据、支付截图、补充内容、处理信息和处理时间线。
请求
GET /api/yf-handset-app/photog/report/detail?id=32
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
id |
integer | 必填,举报记录数值 ID,来自列表接口返回的 id |
关键响应字段
complaint_no:页面展示的举报编号。report_type/report_type_text:举报类型。desc:初始举报说明。evidences:初始现场证据,详情页“举报人材料”区域展示。payment_screenshots:支付截图,详情页单独展示。supplements/report_contents:补充内容记录,优先使用supplements,为空时从report_contents过滤type=supplement。location_name/location_address:详情页位置展示。handle_status/handle_status_text:处理状态;iOS 支持 0 待处理、1 处理中、2 已处理、3 驳回。handle_remark:处理备注;handler.remark为空时作为“处理信息”卡的处理意见兜底。handler:处理人结构,包含name、phone、started_at、finished_at、remark,详情页“处理信息”卡优先使用。handler_name/handler_phone/handled_at:处理信息顶层兼容字段;handler缺字段时作为兜底。handle_evidences:处理凭证附件数组,字段同证据附件,并额外支持evidence_kind/evidence_kind_text。timeline:处理进度时间线;为空时只展示列表记录中的当前处理状态,不生成本地模拟流程。
iOS 模型
struct WildReportDetailData: Decodable, Equatable, Hashable
struct WildReportDetailEvidence: Decodable, Equatable, Hashable
struct WildReportDetailHandler: Decodable, Equatable, Hashable
struct WildReportDetailContent: Decodable, Equatable, Hashable
struct WildReportDetailTimelineItem: Decodable, Equatable, Hashable
UI 行为
- 详情页先展示列表带入的基础记录,再异步请求详情接口刷新完整数据。
- 如果传入记录没有
serverID,说明来自本地提交成功页等临时记录,不请求详情接口。 - 详情接口失败时保留现有基础信息,并 toast 错误。
- 图片证据使用 Kingfisher 加载网络图;视频证据展示视频样式缩略块和文件信息。
- 状态为已处理或驳回且存在处理信息时展示“处理信息”卡:处理人、处理人电话、处理时间、处理完成时间、处理意见。
- “处理人电话”展示脱敏文案,点击使用接口原始
handler.phone或handler_phone发起tel://。 handle_evidences非空时在“处理信息”卡内展示“处理凭证”横向缩略图,file_type=2按视频处理,其余按图片处理。
当前调用位置
WildPhotographerReportDetailViewController.viewDidLoad()WildPhotographerReportDetailViewModel.loadDetailIfNeeded(api:)WildPhotographerReportAPI.reportDetail(id:)
5. 举报微信小程序分享
用途
“我的举报”列表卡片和“举报详情”头部点击分享时调用,后端按举报 ID 返回微信小程序分享配置,iOS 映射为 WeChatMiniProgramSharePayload 后调用 WeChatShareService.shareMiniProgram(...)。
请求
GET /api/yf-handset-app/photog/report/share?id=32
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
id |
string | 必填,举报记录服务端 ID;iOS 使用 WildReportRecord.serverID |
响应示例
{
"code": 100000,
"msg": "success",
"data": {
"userName": "wx8c85189bf3bdda29",
"path": "pages/scenic/radar/report-detail/index?id=32",
"title": "私下收款举报",
"imagePath": "/assets/share/report-share-cover.png",
"webpageUrl": "https://www.youfuntour.com",
"withShareTicket": true,
"miniprogramType": 0,
"scene": 0
},
"time": "2026-07-09 15:42:19"
}
字段说明
title:微信分享卡片标题,不能为空。webpageUrl:小程序打不开时的兼容网页地址,微信要求不超过 1024 字节。userName:微信 SDKWXMiniProgramObject.userName字段;请后端确认返回值是否应为小程序原始 IDgh_...。path:小程序页面路径,可携带举报 ID 或分享 token。miniprogramType:0 正式版、1 开发版、2 体验版;由后端按环境明确返回。withShareTicket:是否携带群分享票据。scene:当前仅支持 0 微信好友会话;非 0 会被通用微信分享模块拒绝。imagePath:当前返回的是小程序内资源路径,iOS 不下载;微信小程序预览图暂使用 App 图标兜底。若后续需要定制卡片图,请返回可下载的https图片地址。
当前调用位置
WildPhotographerReportListViewController列表卡片分享按钮WildPhotographerReportDetailViewController详情头部分享按钮WildPhotographerReportAPI.reportShare(id:)
6. 补充证据提交
请求
POST /api/yf-handset-app/photog/report/supplement
请求体
{
"id": 32,
"desc": "补充说明",
"evidences": [
{
"file_url": "https://example.com/supplement.jpg",
"file_type": 1,
"file_name": "supplement.jpg"
}
]
}
字段说明
id:服务端举报 ID,必填,需大于等于 1;本地临时记录没有serverID时不允许补充提交。desc:补充说明,选填,最多 500 字;与evidences至少填写一项。evidences:补充附件,选填,最多 9 项;附件先通过 OSSphotog_report模块上传后再提交 URL。file_type:沿用举报提交接口约定,1 图片,2 视频。
当前调用位置
WildReportSupplementEvidenceViewModel.submit(api:uploader:scenicId:)WildPhotographerReportAPI.supplementReport(_:)WildReportSupplementEvidenceViewController.submitTapped()
生产 Mock 清理
- 已删除本地种子举报、种子风险点、种子补充证据及对应生产代码文件。
- 举报类型、首页文案、列表、详情、补充证据和风险地图均不再使用本地写死数据兜底。
- 提交接口当前无业务
data返回;提交成功页只展示本次用户提交快照,不伪造服务端举报编号,也不写入“我的举报”本地列表。