Files
suixinkan_uikit/suixinkan/Features/WildPhotographerReport/举报摄影师接口.md

490 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 举报摄影师接口文档
本文档记录 iOS `WildPhotographerReport` 模块当前使用的后端接口。
## 基础约定
- 业务域:举报摄影师
- API 封装:`suixinkan/Features/WildPhotographerReport/API/WildPhotographerReportAPI.swift`
- 网络入口:`NetworkServices.shared.wildPhotographerReportAPI`
- 后端成功码:`100000`
- 响应包裹:工程统一 `APIEnvelope<T>`
- 当前状态:“首页文案”、“举报类型”、“提交举报”、“我的举报列表”、“举报详情”、“微信小程序分享”、“补充证据提交”和“附近风险地图”已接接口;模块内生产 Mock 数据已移除。
## 首页文案
### 用途
“举报摄影师”首页进入时拉取举报须知和举报规则文案。
### 请求
```http
GET /api/yf-handset-app/photog/report/copy
```
### 响应示例
```json
{
"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. 获取举报类型
### 用途
提交举报页面进入时拉取可选举报类型。举报类型由后台动态维护,客户端不能用枚举写死,也不展示图标。
### 请求
```http
GET /api/yf-handset-app/photog/report/types
```
### 请求参数
无。
### 响应示例
```json
{
"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 模型
```swift
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全部上传成功后再提交表单数据。
### 请求
```http
POST /api/yf-handset-app/photog/report/submit
```
### 请求参数
```json
{
"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 模型
```swift
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. 我的举报列表
### 用途
“我的举报”页面进入、切换状态筛选、滚动加载更多时调用。
### 请求
```http
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`:已处理
### 响应示例
```json
{
"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 模型
```swift
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`,详情接口返回完整举报信息、现场证据、支付截图、补充内容、处理信息和处理时间线。
### 请求
```http
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 模型
```swift
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(...)`
### 请求
```http
GET /api/yf-handset-app/photog/report/share?id=32
```
### 请求参数
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| `id` | string | 必填,举报记录服务端 IDiOS 使用 `WildReportRecord.serverID` |
### 响应示例
```json
{
"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`:微信 SDK `WXMiniProgramObject.userName` 字段;请后端确认返回值是否应为小程序原始 ID `gh_...`
- `path`:小程序页面路径,可携带举报 ID 或分享 token。
- `miniprogramType`0 正式版、1 开发版、2 体验版;由后端按环境明确返回。
- `withShareTicket`:是否携带群分享票据。
- `scene`:当前仅支持 0 微信好友会话;非 0 会被通用微信分享模块拒绝。
- `imagePath`当前返回的是小程序内资源路径iOS 不下载;微信小程序预览图暂使用 App 图标兜底。若后续需要定制卡片图,请返回可下载的 `https` 图片地址。
### 当前调用位置
- `WildPhotographerReportListViewController` 列表卡片分享按钮
- `WildPhotographerReportDetailViewController` 详情头部分享按钮
- `WildPhotographerReportAPI.reportShare(id:)`
## 6. 补充证据提交
### 请求
```http
POST /api/yf-handset-app/photog/report/supplement
```
### 请求体
```json
{
"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 项;附件先通过 OSS `photog_report` 模块上传后再提交 URL。
- `file_type`沿用举报提交接口约定1 图片2 视频。
### 当前调用位置
- `WildReportSupplementEvidenceViewModel.submit(api:uploader:scenicId:)`
- `WildPhotographerReportAPI.supplementReport(_:)`
- `WildReportSupplementEvidenceViewController.submitTapped()`
## 生产 Mock 清理
- 已删除本地种子举报、种子风险点、种子补充证据及对应生产代码文件。
- 举报类型、首页文案、列表、详情、补充证据和风险地图均不再使用本地写死数据兜底。
- 提交接口当前无业务 `data` 返回;提交成功页只展示本次用户提交快照,不伪造服务端举报编号,也不写入“我的举报”本地列表。