举报中心模块 · Report Center Module (Phase 9)¶
AstraSentinel · 星穹天巡 — 从静态目录索引升级为完整的举报工作流中枢。
1. 设计目标¶
把举报中心从「26 条 URL 收藏夹」升级为「证据 → 智能推荐 → 自动生成材料 → 提交跟踪」的端到端工作流。
每条证据应该能够:
1. 一键举报 — 详情页点按钮,自动推荐适用渠道
2. 自动生成材料 — 复用 Phase 9 legaldocs.Generate,匹配渠道模板
3. 半自动提交 — 「复制 + 打开外部页面 + 标记已提交 + 截图凭据」
4. 跟踪状态 — 6 状态机 + 审计完整 + 自动写 custody log
5. 批量操作 — 50 条 evidence 一次性打包 / 一次性入库
2. 数据模型¶
2.1 新表¶
| 表 | 用途 |
|---|---|
portal_report_channels |
渠道目录(super_admin 可在线 CRUD) |
portal_report_submissions |
每租户每次举报一行 + 状态机 + 截图凭据 |
2.2 portal_report_channels¶
| 列 | 类型 | 含义 |
|---|---|---|
id |
varchar(64) | 字符串 slug,主键("12377", "douyin_report") |
name_zh / name_en |
varchar(255) | 双语名 |
url |
varchar(1024) | 渠道访问地址 |
category |
varchar(128) | 分类(电信/短信/网络不良 等) |
applicable |
jsonb | 适用类型 array(GIN 索引) |
region |
varchar(32) | china / global / us / eu / jp / kr |
is_official |
bool | 官方监管 vs 平台举报 |
required_fields |
jsonb | 客户必填字段结构化定义 |
template_id |
varchar(64) | 路由到 legaldocs DocType |
active / sort_order |
软删除 + UI 排序 |
2.3 portal_report_submissions¶
| 列 | 类型 | 含义 |
|---|---|---|
id |
uuid | PK |
tenant_id / channel_id |
||
evidence_id? / threat_id? / private_server_id? / social_intel_id? |
uuid | 四 source 排他可选 |
submitted_by_user_id |
uuid | JWT user_id |
status |
enum (CHECK) | draft / submitted / in_review / resolved / rejected / withdrawn |
submitted_at / closed_at |
timestamptz | 自动管理 |
reference_no |
varchar(255) | 外部回执号 |
response_text |
text | 外部回复 |
screenshot_object_key |
varchar(512) | MinIO 路径(reports/<id>/proof.<ext>) |
material_markdown |
text | 提交时冻结的材料原文(不可被后续生成器覆盖) |
title / notes |
3. 14 个新 API¶
3.1 渠道目录¶
GET /api/v1/report-channels?search=®ion=&applicable=&is_official=&active=GET /api/v1/report-channels/:idPOST /api/v1/report-channels(super_admin)PATCH /api/v1/report-channels/:id(super_admin)GET /api/v1/reports-center/channels(legacy,兼容旧 UI)
3.2 智能推荐¶
GET /api/v1/report-channels/recommend?evidence_id|threat_id|private_server_id|social_intel_id=...&severity=®ion=
3.3 材料生成¶
POST /api/v1/report-channels/:id/generate-material- body:
{ evidence_id, case_label?, rights_holder?, recipient?, lawyer_name?, law_firm?, template_id? } - 返回 markdown + missing_required_fields + 实际模板 alias
3.4 提交 CRUD¶
POST /api/v1/report-submissions→ 创建 (含 dedup 409 + force=true)GET /api/v1/report-submissions?status=&channel_id=&evidence_id=&search=&page=GET /api/v1/report-submissions/:idPATCH /api/v1/report-submissions/:id→ 状态机校验后更新POST /api/v1/report-submissions/:id/screenshot→ 截图凭据上传
3.5 批量¶
POST /api/v1/report-channels/:id/batch-package→ ZIP 含 N 份材料POST /api/v1/report-submissions/bulk→ 一次提交多条 + per-item 结果
4. 状态机¶
┌─→ submitted ─┬─→ in_review ─┬─→ resolved (终结)
draft ──┤ │ │
│ ├─→ rejected ──┴─→ submitted (重投)
└─→ withdrawn │ │
└──────────────┴─→ withdrawn (终结)
- resolved / withdrawn 是终结态 — 不可流出
- rejected → submitted 是合法的(platform 拒了,补料再投)
- same → same 是 no-op(PATCH 可盲调不出错)
- DB CHECK 约束(status 枚举)+ application-layer ValidateStatusTransition 双层校验
5. 智能推荐评分模型(5 因素 / 总分 100)¶
| 因素 | 权重 | 触发条件 |
|---|---|---|
applicable_match |
30 | 渠道 applicable[] 与 signal kinds 有重叠 |
domain_match |
25 | source URL 主机匹配渠道平台映射(13 平台预设) |
region_match |
20 | signal.region == channel.region |
official_bonus |
15 | 渠道是官方监管 + 高严重度(crime/copyright_criminal/fraud/...) |
history_success |
10 | 该租户对此渠道历史提交 ≥2 次且解决率 ≥50% |
每个分数对应一条结构化 reason {code, message, delta},UI 渲染 "+30 渠道适用类型命中:copyright"。
6. 模板路由表¶
Channel template_id |
→ legaldocs DocType | 适用渠道 |
|---|---|---|
notary_application |
DocNotaryApplication | 12377 / 12321 / MIIT / SAMR / CNCERT |
forensic_commission |
DocForensicCommission | NCAC / CNIPA / NPPA / SIPO / MPS110 |
cease_desist (alias) |
DocCeaseDesistAttachments | DMCA / YouTube / Steam / Alibaba / TG / Discord / CNNIC |
cease_desist_attachments |
DocCeaseDesistAttachments | WeChat / QQ / 抖音 / B站 / 小红书 / 快手 / 微博 |
| (NULL) | — | cyber_beian (仅查询) |
templateAliasMap 处理 legacy cease_desist → cease_desist_attachments — 0 数据迁移。
7. 完整工作流¶
7.1 单证据流程¶
1. 客户上传证据 → /evidence/<id>
2. 点「举报」按钮 → ReportRecommendModal
GET /report-channels/recommend?evidence_id=<uuid>
3. 看到 top 6 渠道 + 推荐理由
4. 点某条「在举报中心打开」→ /reports-center/?channel=X&evidence_id=Y
5. ReportFlowDrawer 自动跳过 channel + evidence 选择
6. 「生成材料」→ POST /report-channels/<id>/generate-material
7. 编辑 markdown → 「复制 + 打开举报页」
8. 在外部渠道粘贴提交 → 拿到回执号
9. 回到 portal → 「标记已提交」+ 截图凭据
POST /report-submissions
→ 写 REPORT_SUBMITTED custody log(evidence 时间线见到此提交)
10. 后续 PATCH 状态:in_review / resolved / rejected / withdrawn
→ 每次写对应 custody log
7.2 批量流程¶
1. /reports-center 切到「批量举报」tab
2. 选渠道(支持自动材料的)
3. 搜索 + 多选 N 个 evidence
4. 填批次共同字段(案件标签 / 律师 / 律所)
5. 「📥 下载 ZIP」→ N 份 markdown + README.md
ZIP 内 errors/ 子目录占位失败项
6. 律师离线审阅 → 提交 → 拿回执号
7. 回到 portal → 「🚀 批量标记已提交」+ 共用回执号
POST /report-submissions/bulk
→ per-item 结果:✓ created / ⚡ duplicate / ✗ failed
→ 每证据写一条 REPORT_SUBMITTED custody log
8. 前端形态¶
| 路由 | 功能 |
|---|---|
/reports-center/ |
4 tabs: 官方监管 / 平台举报 / 我的记录 / 批量举报 |
/reports-center/?channel=X&evidence_id=Y |
Deep-link,自动打开 ReportFlowDrawer |
/evidence/[id] |
顶部「举报」按钮 |
/threats |
Drawer footer「智能举报推荐」 |
/private-servers |
Drawer footer「智能举报推荐」 |
/social-intel |
Drawer footer「发起举报」(已升级为 ReportRecommendModal) |
8.1 组件清单¶
frontend/src/app/(portal)/reports-center/
├── page.tsx 主页面 + 4 tabs + Hero 4 KPI
├── ChannelCard.tsx 渠道卡(含历史统计 + 自动材料 badge)
├── MySubmissionsList.tsx 我的记录列表 + 状态过滤 + 分页
├── ReportFlowDrawer.tsx 5 步工作流抽屉
├── BatchReportTab.tsx 批量举报 4 步 UI
└── (deep link support via useSearchParams)
frontend/src/components/viz/
└── ReportRecommendModal.tsx 通用智能推荐模态(4 source 复用)
9. 部署 / 运维¶
9.1 部署形态(ai-astraweb)¶
- API:
/usr/local/bin/portal由portal-api.service(systemd) 管理 - Frontend: nginx serve
/var/www/portal/ - 不要用
deploy/deploy-aws.sh— 已 stale
9.2 部署命令¶
# 1. 编译
cd ~/ai/bot/game-guard-portal
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -ldflags="-s -w" -o /tmp/portal-linux ./cmd/portal
# 2. 前端
cd frontend && NEXT_PUBLIC_API_URL=https://portal.astraeye.ai npx next build
# 3. 部 binary
scp /tmp/portal-linux ai-astraweb:/tmp/portal-new
ssh ai-astraweb 'sudo cp /usr/local/bin/portal /usr/local/bin/portal.bak-$(date +%Y%m%d-%H%M%S)
sudo install -m 0755 /tmp/portal-new /usr/local/bin/portal
sudo systemctl restart portal-api'
# 4. 部前端
rsync -avz --delete ~/ai/bot/game-guard-portal/frontend/out/ ai-astraweb:/tmp/portal-frontend-new/
ssh ai-astraweb 'sudo rsync -a --delete /tmp/portal-frontend-new/ /var/www/portal/'
# 5. 验
curl https://portal.astraeye.ai/health
9.3 数据库迁移¶
AutoMigrate 自动建表 + BootstrapReportChannels 幂等 seed 27 条渠道:
portal_report_channels(含 27 条 seed 行)portal_report_submissions(空表)
OnConflict DoNothing 保证 super_admin 在线编辑过的渠道不会被重启 seed 覆盖。
如需手动 golang-migrate:
10. FAQ¶
Q: 为什么不自动提交到外部渠道? A: 外部渠道有 captcha / 登录 / 多步表单,自动化脆弱。半自动(复制 + 打开 + 手动粘贴)更鲁棒,律师 / 公证员的真实工作流就是这样。
Q: cease_desist vs cease_desist_attachments 区别?
A: 同一个 legaldocs.DocType;seed 数据用了旧字面量 cease_desist,alias map 自动映射。新增渠道用规范名。
Q: 批量大小有上限? A: 100。律所一天产能足够;100+ 案件应分批做。
Q: 我的提交被外部拒了怎么办? A: PATCH status=rejected → 补证据 / 改材料 → PATCH status=submitted(合法状态转移)。系统支持 re-file 工作流。
Q: 怎么向新渠道(新增的法院)举报? A: super_admin POST /report-channels 新建,设置 applicable / template_id。其他 tenant 立即看到。无需发版。
11. 法律合规面¶
| 受众 | 用到本模块 |
|---|---|
| 律师 | 一键生成 N 份材料 + ZIP 打包 + 「批量标记已提交」做案件归档 |
| 公证员 | 客户来公证时附带 portal_report_submissions 历史 + screenshot_object_key 凭据 |
| 司法鉴定中心 | material_markdown 字段冻结后的原文 = 司法可采 |
| 互联网法院 | 通过 evidence 上的 REPORT_SUBMITTED 等 custody log 完整时间线,证明权利人已主动维权 |
12. 版本对照¶
| 组件 | 版本 |
|---|---|
templateAliasMap |
v1(cease_desist → cease_desist_attachments) |
reportrecommend scoring |
5 因素 × 100 / reportrecommend/v1 |
report-center schema |
migration 000013 |
| Seed 渠道 | 27 条(14 官方 + 13 平台) |
13. Phase 10 候选¶
- 真正的自动提交(部分渠道开放 API)
- 渠道 SLA 跟踪(自动 polling 外部状态查询页)
- 多 TSA / 多渠道 cross-witness 报告
- 国际渠道扩展(USPTO / EUIPO / KCOPA / JPO)
- 渠道 SLA 报表(按 channel 算 resolution 平均时长 + 拒绝原因分布)