feat(moderation): resource-centric reported comments/events pages
Rework 内容审核 pages around reported resources instead of individual reports, matching the new backend endpoints: rows group all reports on one comment/event, with a slide-over listing report details and per-row actions 通过并屏蔽 (approve) / 驳回举报 (reject) / 撤销屏蔽 (revert). Filters: 待处理 / 已屏蔽 / 全部. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
+245
-173
@@ -218,30 +218,33 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/admin/v1/comments/reports": {
|
||||
"/api/admin/v1/comments/reported": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/** [评论举报] 获取举报列表 */
|
||||
/**
|
||||
* [评论审核] 被举报评论列表
|
||||
* @description 按被举报的评论分组列出举报,附带举报明细与屏蔽状态。
|
||||
*/
|
||||
get: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/**
|
||||
* @description optional Filter by status: open, resolved, dismissed.
|
||||
* @example open
|
||||
* @description 可选。按状态过滤: pending(有待处理举报), blocked(已屏蔽), all(默认)。 示例: pending
|
||||
* @example architecto
|
||||
*/
|
||||
status?: string;
|
||||
/**
|
||||
* @description optional Page number.
|
||||
* @example 1
|
||||
* @description 可选。页码。 示例: 1
|
||||
* @example 16
|
||||
*/
|
||||
page?: number;
|
||||
/**
|
||||
* @description optional Page size (max 100).
|
||||
* @example 20
|
||||
* @description 可选。每页数量,最大100。 示例: 20
|
||||
* @example 16
|
||||
*/
|
||||
page_size?: number;
|
||||
};
|
||||
@@ -253,10 +256,10 @@ export interface paths {
|
||||
content: {
|
||||
"application/json": {
|
||||
/**
|
||||
* @example resolved
|
||||
* @example pending
|
||||
* @enum {string|null}
|
||||
*/
|
||||
status?: "open" | "resolved" | "dismissed" | null;
|
||||
status?: "pending" | "blocked" | "all" | null;
|
||||
/**
|
||||
* @description Must be at least 1.
|
||||
* @example 16
|
||||
@@ -282,54 +285,103 @@ export interface paths {
|
||||
/**
|
||||
* @example [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "comment_id": 10,
|
||||
* "reason": "spam",
|
||||
* "message": "Contains spam links",
|
||||
* "status": "open",
|
||||
* "created_at": "2025-12-01T10:10:00Z",
|
||||
* "handled_at": null,
|
||||
* "handled_by": null,
|
||||
* "reporter": {
|
||||
* "uid": "01HXXXX",
|
||||
* "display_name": "Alice"
|
||||
* "kind": "reported_comment",
|
||||
* "id": 10,
|
||||
* "body": "这条评论包含垃圾推广链接",
|
||||
* "body_format": "markdown",
|
||||
* "status": "active",
|
||||
* "is_blocked": false,
|
||||
* "blocked_at": null,
|
||||
* "blocked_by_uid": null,
|
||||
* "author": {
|
||||
* "uid": "01HYYYY",
|
||||
* "display_name": "Bob"
|
||||
* },
|
||||
* "comment": {
|
||||
* "id": 10,
|
||||
* "body": "Root comment"
|
||||
* }
|
||||
* "open_reports_count": 2,
|
||||
* "latest_report_at": "2026-07-11T10:10:00Z",
|
||||
* "reports": [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "reason": "spam",
|
||||
* "message": "含有垃圾推广链接",
|
||||
* "status": "open",
|
||||
* "reporter": {
|
||||
* "uid": "01HXXXX",
|
||||
* "display_name": "Alice"
|
||||
* },
|
||||
* "created_at": "2026-07-11T10:10:00Z",
|
||||
* "handled_at": null
|
||||
* }
|
||||
* ],
|
||||
* "created_at": "2026-07-10T09:00:00Z"
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
data?: {
|
||||
/** @example 1 */
|
||||
id?: number;
|
||||
/** @example reported_comment */
|
||||
kind?: string;
|
||||
/** @example 10 */
|
||||
comment_id?: number;
|
||||
/** @example spam */
|
||||
reason?: string;
|
||||
/** @example Contains spam links */
|
||||
message?: string;
|
||||
/** @example open */
|
||||
id?: number;
|
||||
/** @example 这条评论包含垃圾推广链接 */
|
||||
body?: string;
|
||||
/** @example markdown */
|
||||
body_format?: string;
|
||||
/** @example active */
|
||||
status?: string;
|
||||
/** @example 2025-12-01T10:10:00Z */
|
||||
created_at?: string;
|
||||
/** @example false */
|
||||
is_blocked?: boolean;
|
||||
/** @example null */
|
||||
handled_at?: string;
|
||||
blocked_at?: string;
|
||||
/** @example null */
|
||||
handled_by?: string;
|
||||
reporter?: {
|
||||
/** @example 01HXXXX */
|
||||
blocked_by_uid?: string;
|
||||
author?: {
|
||||
/** @example 01HYYYY */
|
||||
uid?: string;
|
||||
/** @example Alice */
|
||||
/** @example Bob */
|
||||
display_name?: string;
|
||||
};
|
||||
comment?: {
|
||||
/** @example 10 */
|
||||
/** @example 2 */
|
||||
open_reports_count?: number;
|
||||
/** @example 2026-07-11T10:10:00Z */
|
||||
latest_report_at?: string;
|
||||
/**
|
||||
* @example [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "reason": "spam",
|
||||
* "message": "含有垃圾推广链接",
|
||||
* "status": "open",
|
||||
* "reporter": {
|
||||
* "uid": "01HXXXX",
|
||||
* "display_name": "Alice"
|
||||
* },
|
||||
* "created_at": "2026-07-11T10:10:00Z",
|
||||
* "handled_at": null
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
reports?: {
|
||||
/** @example 1 */
|
||||
id?: number;
|
||||
/** @example Root comment */
|
||||
body?: string;
|
||||
};
|
||||
/** @example spam */
|
||||
reason?: string;
|
||||
/** @example 含有垃圾推广链接 */
|
||||
message?: string;
|
||||
/** @example open */
|
||||
status?: string;
|
||||
reporter?: {
|
||||
/** @example 01HXXXX */
|
||||
uid?: string;
|
||||
/** @example Alice */
|
||||
display_name?: string;
|
||||
};
|
||||
/** @example 2026-07-11T10:10:00Z */
|
||||
created_at?: string;
|
||||
/** @example null */
|
||||
handled_at?: string;
|
||||
}[];
|
||||
/** @example 2026-07-10T09:00:00Z */
|
||||
created_at?: string;
|
||||
}[];
|
||||
pagination?: {
|
||||
/** @example 1 */
|
||||
@@ -378,31 +430,6 @@ export interface paths {
|
||||
};
|
||||
};
|
||||
};
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
/** @example false */
|
||||
success?: boolean;
|
||||
/** @example VALIDATION_ERROR */
|
||||
code?: string;
|
||||
/** @example The given data was invalid. */
|
||||
message?: string;
|
||||
data?: {
|
||||
errors?: {
|
||||
/**
|
||||
* @example [
|
||||
* "The selected status is invalid."
|
||||
* ]
|
||||
*/
|
||||
status?: string[];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
put?: never;
|
||||
@@ -413,21 +440,16 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/admin/v1/comments/reports/{report_id}": {
|
||||
"/api/admin/v1/comments/reported/{comment}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/**
|
||||
* @description The ID of the report.
|
||||
* @example 3
|
||||
* @description 评论 ID。
|
||||
* @example 10
|
||||
*/
|
||||
report_id: number;
|
||||
/**
|
||||
* @description Report ID.
|
||||
* @example 1
|
||||
*/
|
||||
report: number;
|
||||
comment: number;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
@@ -437,22 +459,22 @@ export interface paths {
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
/** [评论举报] 处理举报 */
|
||||
/**
|
||||
* [评论审核] 处理被举报评论
|
||||
* @description approve: 举报成立,屏蔽评论并将其全部待处理举报标记已处理;
|
||||
* reject: 举报不成立,驳回全部待处理举报;
|
||||
* revert: 撤销屏蔽(仅对已屏蔽评论有效),举报记录保留。
|
||||
*/
|
||||
patch: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/**
|
||||
* @description The ID of the report.
|
||||
* @example 3
|
||||
* @description 评论 ID。
|
||||
* @example 10
|
||||
*/
|
||||
report_id: number;
|
||||
/**
|
||||
* @description Report ID.
|
||||
* @example 1
|
||||
*/
|
||||
report: number;
|
||||
comment: number;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
@@ -460,8 +482,8 @@ export interface paths {
|
||||
content: {
|
||||
"application/json": {
|
||||
/**
|
||||
* @description Action to take: hide, delete, dismiss.
|
||||
* @example hide
|
||||
* @description 处理动作: approve, reject, revert。
|
||||
* @example approve
|
||||
*/
|
||||
action: string;
|
||||
};
|
||||
@@ -477,16 +499,20 @@ export interface paths {
|
||||
/** @example true */
|
||||
success?: boolean;
|
||||
data?: {
|
||||
/** @example 1 */
|
||||
/** @example reported_comment */
|
||||
kind?: string;
|
||||
/** @example 10 */
|
||||
id?: number;
|
||||
/** @example resolved */
|
||||
status?: string;
|
||||
/** @example 2025-12-01T10:20:00Z */
|
||||
handled_at?: string;
|
||||
/** @example true */
|
||||
is_blocked?: boolean;
|
||||
/** @example 2026-07-11T10:20:00Z */
|
||||
blocked_at?: string;
|
||||
/** @example 01HXXXX */
|
||||
handled_by_uid?: string;
|
||||
blocked_by_uid?: string;
|
||||
/** @example 0 */
|
||||
open_reports_count?: number;
|
||||
};
|
||||
/** @example Report handled */
|
||||
/** @example Moderation applied */
|
||||
message?: string;
|
||||
};
|
||||
};
|
||||
@@ -521,21 +547,6 @@ export interface paths {
|
||||
};
|
||||
};
|
||||
};
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
/** @example false */
|
||||
success?: boolean;
|
||||
/** @example NOT_FOUND */
|
||||
code?: string;
|
||||
/** @example 举报不存在 */
|
||||
message?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
@@ -552,7 +563,7 @@ export interface paths {
|
||||
errors?: {
|
||||
/**
|
||||
* @example [
|
||||
* "The selected action is invalid."
|
||||
* "Comment is not blocked."
|
||||
* ]
|
||||
*/
|
||||
action?: string[];
|
||||
@@ -881,11 +892,11 @@ export interface paths {
|
||||
content: {
|
||||
"application/json": {
|
||||
/**
|
||||
* @example ios
|
||||
* @example android
|
||||
* @enum {string|null}
|
||||
*/
|
||||
platform?: "ios" | "android" | "web" | "desktop" | null;
|
||||
/** @example false */
|
||||
/** @example true */
|
||||
is_online?: boolean | null;
|
||||
/**
|
||||
* @description Must be at least 1.
|
||||
@@ -1311,19 +1322,22 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/admin/v1/file-x/event-reports": {
|
||||
"/api/admin/v1/file-x/reported-events": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/** [事件举报] 获取举报列表 */
|
||||
/**
|
||||
* [事件审核] 被举报事件列表
|
||||
* @description 按被举报的事件分组列出举报,附带举报明细与屏蔽状态。
|
||||
*/
|
||||
get: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/**
|
||||
* @description 可选。按状态过滤: open, resolved, dismissed。 示例: open
|
||||
* @description 可选。按状态过滤: pending(有待处理举报), blocked(已屏蔽), all(默认)。 示例: pending
|
||||
* @example architecto
|
||||
*/
|
||||
status?: string;
|
||||
@@ -1346,10 +1360,10 @@ export interface paths {
|
||||
content: {
|
||||
"application/json": {
|
||||
/**
|
||||
* @example open
|
||||
* @example blocked
|
||||
* @enum {string|null}
|
||||
*/
|
||||
status?: "open" | "resolved" | "dismissed" | null;
|
||||
status?: "pending" | "blocked" | "all" | null;
|
||||
/**
|
||||
* @description Must be at least 1.
|
||||
* @example 16
|
||||
@@ -1375,47 +1389,100 @@ export interface paths {
|
||||
/**
|
||||
* @example [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "kind": "filex_event_report",
|
||||
* "event_id": 25,
|
||||
* "reason": "spam",
|
||||
* "message": "含有大量垃圾推广链接",
|
||||
* "status": "open",
|
||||
* "created_at": "2026-06-06T10:00:00Z",
|
||||
* "handled_at": null,
|
||||
* "reporter": {
|
||||
* "uid": "01HXXXX",
|
||||
* "display_name": "Alice"
|
||||
* "kind": "reported_event",
|
||||
* "id": 25,
|
||||
* "title": "空调清洗上门服务记录",
|
||||
* "visibility": "public",
|
||||
* "is_blocked": false,
|
||||
* "blocked_at": null,
|
||||
* "blocked_by_uid": null,
|
||||
* "author": {
|
||||
* "uid": "01HYYYY",
|
||||
* "display_name": "Bob"
|
||||
* },
|
||||
* "handled_by": null
|
||||
* "open_reports_count": 2,
|
||||
* "latest_report_at": "2026-07-11T10:10:00Z",
|
||||
* "reports": [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "reason": "spam",
|
||||
* "message": "疑似虚假事迹",
|
||||
* "status": "open",
|
||||
* "reporter": {
|
||||
* "uid": "01HXXXX",
|
||||
* "display_name": "Alice"
|
||||
* },
|
||||
* "created_at": "2026-07-11T10:10:00Z",
|
||||
* "handled_at": null
|
||||
* }
|
||||
* ],
|
||||
* "created_at": "2026-07-10T09:00:00Z"
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
data?: {
|
||||
/** @example 1 */
|
||||
id?: number;
|
||||
/** @example filex_event_report */
|
||||
/** @example reported_event */
|
||||
kind?: string;
|
||||
/** @example 25 */
|
||||
event_id?: number;
|
||||
/** @example spam */
|
||||
reason?: string;
|
||||
/** @example 含有大量垃圾推广链接 */
|
||||
message?: string;
|
||||
/** @example open */
|
||||
status?: string;
|
||||
/** @example 2026-06-06T10:00:00Z */
|
||||
created_at?: string;
|
||||
id?: number;
|
||||
/** @example 空调清洗上门服务记录 */
|
||||
title?: string;
|
||||
/** @example public */
|
||||
visibility?: string;
|
||||
/** @example false */
|
||||
is_blocked?: boolean;
|
||||
/** @example null */
|
||||
handled_at?: string;
|
||||
reporter?: {
|
||||
/** @example 01HXXXX */
|
||||
blocked_at?: string;
|
||||
/** @example null */
|
||||
blocked_by_uid?: string;
|
||||
author?: {
|
||||
/** @example 01HYYYY */
|
||||
uid?: string;
|
||||
/** @example Alice */
|
||||
/** @example Bob */
|
||||
display_name?: string;
|
||||
};
|
||||
/** @example null */
|
||||
handled_by?: string;
|
||||
/** @example 2 */
|
||||
open_reports_count?: number;
|
||||
/** @example 2026-07-11T10:10:00Z */
|
||||
latest_report_at?: string;
|
||||
/**
|
||||
* @example [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "reason": "spam",
|
||||
* "message": "疑似虚假事迹",
|
||||
* "status": "open",
|
||||
* "reporter": {
|
||||
* "uid": "01HXXXX",
|
||||
* "display_name": "Alice"
|
||||
* },
|
||||
* "created_at": "2026-07-11T10:10:00Z",
|
||||
* "handled_at": null
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
reports?: {
|
||||
/** @example 1 */
|
||||
id?: number;
|
||||
/** @example spam */
|
||||
reason?: string;
|
||||
/** @example 疑似虚假事迹 */
|
||||
message?: string;
|
||||
/** @example open */
|
||||
status?: string;
|
||||
reporter?: {
|
||||
/** @example 01HXXXX */
|
||||
uid?: string;
|
||||
/** @example Alice */
|
||||
display_name?: string;
|
||||
};
|
||||
/** @example 2026-07-11T10:10:00Z */
|
||||
created_at?: string;
|
||||
/** @example null */
|
||||
handled_at?: string;
|
||||
}[];
|
||||
/** @example 2026-07-10T09:00:00Z */
|
||||
created_at?: string;
|
||||
}[];
|
||||
pagination?: {
|
||||
/** @example 1 */
|
||||
@@ -1474,18 +1541,16 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/admin/v1/file-x/event-reports/{report_id}": {
|
||||
"/api/admin/v1/file-x/reported-events/{event}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/**
|
||||
* @description The ID of the report.
|
||||
* @example 1
|
||||
* @description 事件 ID。
|
||||
* @example 25
|
||||
*/
|
||||
report_id: number;
|
||||
/** @description Optional parameter. 必需。举报ID。 示例: 1 */
|
||||
report: number;
|
||||
event: number;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
@@ -1495,30 +1560,33 @@ export interface paths {
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
/** [事件举报] 处理举报 */
|
||||
/**
|
||||
* [事件审核] 处理被举报事件
|
||||
* @description approve: 举报成立,屏蔽事件并将其全部待处理举报标记已处理;
|
||||
* reject: 举报不成立,驳回全部待处理举报;
|
||||
* revert: 撤销屏蔽(仅对已屏蔽事件有效),举报记录保留。
|
||||
*/
|
||||
patch: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/**
|
||||
* @description The ID of the report.
|
||||
* @example 1
|
||||
* @description 事件 ID。
|
||||
* @example 25
|
||||
*/
|
||||
report_id: number;
|
||||
/** @description Optional parameter. 必需。举报ID。 示例: 1 */
|
||||
report: number;
|
||||
event: number;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: {
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
/**
|
||||
* @description 必需。处理动作: hide, delete, resolve, dismiss。 示例: hide
|
||||
* @example architecto
|
||||
* @description 处理动作: approve, reject, revert。
|
||||
* @example approve
|
||||
*/
|
||||
action?: string;
|
||||
action: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1532,14 +1600,18 @@ export interface paths {
|
||||
/** @example true */
|
||||
success?: boolean;
|
||||
data?: {
|
||||
/** @example 1 */
|
||||
/** @example reported_event */
|
||||
kind?: string;
|
||||
/** @example 25 */
|
||||
id?: number;
|
||||
/** @example resolved */
|
||||
status?: string;
|
||||
/** @example 2026-06-06T10:20:00Z */
|
||||
handled_at?: string;
|
||||
/** @example true */
|
||||
is_blocked?: boolean;
|
||||
/** @example 2026-07-11T10:20:00Z */
|
||||
blocked_at?: string;
|
||||
/** @example 01HXXXX */
|
||||
handled_by_uid?: string;
|
||||
blocked_by_uid?: string;
|
||||
/** @example 0 */
|
||||
open_reports_count?: number;
|
||||
};
|
||||
/** @example 举报已处理 */
|
||||
message?: string;
|
||||
@@ -1607,7 +1679,7 @@ export interface paths {
|
||||
errors?: {
|
||||
/**
|
||||
* @example [
|
||||
* "The selected action is invalid."
|
||||
* "Event is not blocked."
|
||||
* ]
|
||||
*/
|
||||
action?: string[];
|
||||
|
||||
Reference in New Issue
Block a user