7.7 KiB
7.7 KiB
用户举报 Flutter 对接
本文描述 Flutter App 对接用户举报和房间举报的 HTTP 契约。通用文件上传接口用于上传举报图片并拿到 URL,提交举报接口只接收 JSON。
基础地址
本地开发地址:
http://127.0.0.1:13000
线上环境使用当前 App 配置里的 gateway base URL。下面所有路径都拼在 gateway base URL 后。
请求头
| Header | 必填 | 示例 | 说明 |
|---|---|---|---|
Authorization |
是 | Bearer <access_token> |
登录 access token;举报发起人只从 token 读取,Flutter 不传举报发起人 ID。 |
X-App-Code |
否 | lalu |
App 编码;登录态接口最终以 token 内的 app_code 为准。 |
Content-Type |
提交举报必填 | application/json |
提交举报使用 JSON。 |
Content-Type |
上传图片必填 | multipart/form-data |
上传举报图片使用 multipart。 |
统一响应 envelope:
{
"code": "OK",
"message": "ok",
"request_id": "req_abc",
"data": {}
}
Flutter 只在 code == "OK" 时读取 data。失败时记录 request_id,用于后端排查。
调用顺序
1. 用户在举报弹窗选择举报类型。
2. 如有举报图,逐张调用 POST /api/v1/files/upload,收集每次返回的 data.url。
3. 调用 POST /api/v1/reports 提交举报。
4. 提交成功后关闭弹窗,并用 data.report_id 写本地日志。
上传举报图片
上传接口只负责把文件写入对象存储并返回 URL,不创建举报单。
POST /api/v1/files/upload
Authorization: Bearer <access_token>
X-App-Code: lalu
Content-Type: multipart/form-data
file=<binary>
请求字段:
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
file |
是 | multipart file | 单文件最大 20MB。多图逐张上传,Flutter 把每张图返回的 data.url 放进提交举报接口的 image_urls。 |
成功响应:
{
"code": "OK",
"message": "ok",
"request_id": "req_upload_report_image",
"data": {
"url": "https://cdn.example.com/app/files/10001/20260529/file_xxx.jpg",
"object_key": "app/files/10001/20260529/file_xxx.jpg",
"content_type": "image/jpeg",
"size_bytes": 345678
}
}
Flutter 提交举报时只需要使用 data.url。
提交举报
POST /api/v1/reports
Authorization: Bearer <access_token>
X-App-Code: lalu
Content-Type: application/json
{
"user_id": "10002",
"report_type": "pornography",
"reason": "用户在房间内发布违规内容",
"image_urls": [
"https://cdn.example.com/app/files/10001/20260529/file_xxx.jpg"
]
}
举报房间示例:
POST /api/v1/reports
Authorization: Bearer <access_token>
X-App-Code: lalu
Content-Type: application/json
{
"room_id": "lalu_abc123",
"report_type": "fraud",
"reason": "房间引导线下交易",
"image_urls": []
}
请求字段:
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
user_id |
条件必填 | string | 被举报用户 ID。和 room_id 二选一,只能传一个。 |
room_id |
条件必填 | string | 被举报房间 ID。和 user_id 二选一,只能传一个。 |
report_type |
是 | string | 举报类型,取值见下方枚举。 |
reason |
否 | string | 举报理由;Flutter 可允许用户不填。 |
image_urls |
否 | string[] | 举报图 URL 数组;无图可传 [] 或不传。 |
目标校验规则:
| 场景 | 结果 |
|---|---|
只传 user_id |
举报用户。 |
只传 room_id |
举报房间。 |
user_id 和 room_id 都不传 |
400 INVALID_ARGUMENT。 |
user_id 和 room_id 同时传 |
400 INVALID_ARGUMENT,Flutter 需要拆成一次明确的用户举报或房间举报。 |
举报发起人不在请求体里传。gateway 必须从 Authorization 对应的 access token 读取当前登录用户,避免客户端伪造举报发起人。
举报类型
| UI 文案 | report_type |
|---|---|
| Politics | politics |
| Pornography | pornography |
| Graphic Violence | graphic_violence |
| Verbal Abuse | verbal_abuse |
| Fraud | fraud |
| Illegal Content | illegal_content |
| Minors | minors |
| In-Person Transactions | in_person_transactions |
| Other | other |
返回体模拟数据
举报用户成功:
{
"code": "OK",
"message": "ok",
"request_id": "req_report_user",
"data": {
"report_id": "rpt_10001_1778000000000",
"target_type": "user",
"user_id": "10002",
"room_id": "",
"report_type": "pornography",
"status": "submitted",
"created_at_ms": 1778000000000
}
}
举报房间成功:
{
"code": "OK",
"message": "ok",
"request_id": "req_report_room",
"data": {
"report_id": "rpt_10001_1778000001000",
"target_type": "room",
"user_id": "",
"room_id": "lalu_abc123",
"report_type": "fraud",
"status": "submitted",
"created_at_ms": 1778000001000
}
}
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
report_id |
string | 举报单 ID;Flutter 可用于本地日志和客服排查。 |
target_type |
string | user 或 room,由服务端按本次传入目标生成。 |
user_id |
string | 被举报用户 ID;房间举报返回空字符串。 |
room_id |
string | 被举报房间 ID;用户举报返回空字符串。 |
report_type |
string | 本次提交的举报类型。 |
status |
string | 首次提交固定返回 submitted。 |
created_at_ms |
int64 | 举报创建时间,Unix epoch milliseconds。 |
错误处理
失败返回仍使用统一 envelope:
{
"code": "INVALID_ARGUMENT",
"message": "invalid argument",
"request_id": "req_abc"
}
| HTTP 状态码 | code |
Flutter 处理 |
|---|---|---|
400 |
INVALID_JSON |
JSON 格式错误,检查本地序列化逻辑。 |
400 |
INVALID_ARGUMENT |
user_id/room_id 二选一不满足、report_type 非法、图片 URL 格式非法或字段超长。 |
401 |
UNAUTHORIZED |
token 缺失、无效、过期或会话失效,重新登录。 |
403 |
PROFILE_REQUIRED |
用户资料未完成,跳转资料补全流程。 |
404 |
NOT_FOUND |
被举报用户不存在,刷新页面状态。 |
502 |
UPSTREAM_ERROR |
内部服务暂不可用,可提示稍后重试。 |
Flutter 数据模型建议
class SubmitReportRequest {
SubmitReportRequest({
this.userId,
this.roomId,
required this.reportType,
this.reason,
this.imageUrls = const [],
});
final String? userId;
final String? roomId;
final String reportType;
final String? reason;
final List<String> imageUrls;
Map<String, dynamic> toJson() => {
if (userId != null && userId!.isNotEmpty) 'user_id': userId,
if (roomId != null && roomId!.isNotEmpty) 'room_id': roomId,
'report_type': reportType,
if (reason != null && reason!.trim().isNotEmpty) 'reason': reason!.trim(),
if (imageUrls.isNotEmpty) 'image_urls': imageUrls,
};
}
提交前本地校验:
void validateReportTarget({String? userId, String? roomId}) {
final hasUser = userId != null && userId.trim().isNotEmpty;
final hasRoom = roomId != null && roomId.trim().isNotEmpty;
if (hasUser == hasRoom) {
throw ArgumentError('user_id and room_id must be exactly one');
}
}
实现边界
- Flutter 不传举报发起人 ID,服务端只认 token 中的当前用户。
user_id表示被举报用户,不是举报发起人。room_id表示被举报房间,不要求同时传房间内某个用户。user_id和room_id必须二选一,不能同时提交一个混合举报。- 举报图片先上传再提交 URL;提交举报接口不接收 multipart 文件。
message不作为业务分支依据,Flutter 只按code和 HTTP 状态处理。