# MC Report System API 文档 Base URL: `http://:3100/api` ## 通用约定 | 项 | 说明 | |----|------| | 认证头 | `Authorization: Bearer `(登录后获得) | | API 密钥头 | `x-api-key: `(安装时生成,注入前端页面,所有请求需携带) | | 外部密钥头 | `x-external-key: `(仅 /api/external 插件接口) | | 内容类型 | `application/json`(文件上传用 `multipart/form-data`) | | 错误格式 | `{ "error": "错误信息" }` | | 限流 | 登录 8/min、注册 3/min、工单 500/min、匿名提交 5/min、全局 300/min | **角色**:`owner`(服主) / `admin`(管理员) / `player`(玩家) --- ## 一、认证 Auth ### POST /auth/send-verify-code 发送邮箱验证码(注册前校验邮箱归属)。 ```json { "email": "player@example.com" } ``` 响应: `{ "code_id": "uuid", "message": "验证码已发送" }` > 若 SMTP 未配置,返回 `{ code_id, code, dev: true }`(开发模式直显验证码)。 ### POST /auth/register 注册账号(需先获取邮箱验证码)。 ```json { "username": "player1", "password": "******", "email": "p@example.com", "game_name": "Steve", "game_uid": "NETEASE_UID_001", "source": "netease", // netease | skin(皮肤站可不填 UID) "captcha_id": "uuid", "captcha_answer": "abcd", "code_id": "uuid", "code": "123456" } ``` 响应 201: `{ "message": "注册成功,请登录" }` > 注册时自动在 `user_identities` 中创建主身份记录。 ### POST /auth/login ```json { "username": "player1", "password": "******" } ``` 响应: ```json { "token": "", "user": { "id": 1, "username": "player1", "email": "p@example.com", "game_name": "Steve", "game_uid": "NETEASE_UID_001", "role": "player", "source": "netease" } } ``` ### GET /auth/me *(认证)* 返回当前用户完整信息,含 `identities` 数组(全部已绑定身份)。 ### GET /auth/identities *(认证)* 列出当前账号绑定的全部身份(一个账号可同时绑定网易端 + 皮肤站)。 响应: ```json [ { "id": 1, "source": "netease", "game_name": "Steve", "game_uid": "NETEASE_UID_001", "created_at": "..." }, { "id": 2, "source": "skin", "game_name": "Alex", "game_uid": "SKIN_UUID_002", "created_at": "..." } ] ``` ### POST /auth/identities *(认证)* 绑定新来源身份(同来源仅能绑一个,游戏名全局唯一)。 ```json { "source": "skin", "game_name": "Alex", "game_uid": "SKIN_UUID_002" } ``` | 规则 | 说明 | |------|------| | source | 必填,`netease` 或 `skin` | | game_name | 必填,不能与其他账号已绑定的游戏名重复 | | game_uid | 网易端必填 | | 同来源重复 | 拒绝(先删除再重新绑定) | | 至少保留一个 | 解绑时若只剩一个身份则拒绝 | **皮肤站 UUID 自动查询**:皮肤站来源时,可通过 `GET /settings/uuid-lookup?site=<皮肤站地址>&name=<用户名>` 自动获取 UUID(调 Yggdrasil API `POST {site}/api/yggdrasil/api/profiles/minecraft`,带 SSRF 防护与 10s 超时)。站点皮肤站地址可在系统设置配置,前端绑定弹窗自动带出。 ### DELETE /auth/identities/:id *(认证)* 解绑身份。响应: `{ "message": "已解绑" }` ### PUT /auth/profile *(认证)* 更新个人资料(game_name / game_uid / email)。主身份变更会同步到 `user_identities`。 ### PUT /auth/password *(认证)* ```json { "oldPassword": "旧密码", "newPassword": "新密码" } ``` ### POST /auth/forgot-password ```json { "email": "p@example.com" } ``` 发送重置链接(使用 `reset_password` 模板,1 小时有效)。 ### POST /auth/reset-password ```json { "token": "", "password": "新密码" } ``` ### POST /auth/verify-email 验证邮箱(token 或 6 位验证码): ```json { "code": "" } ``` --- ## 二、工单 Tickets 状态机:`pending → processing → awaiting_info → resolved / rejected → closed(7天自动关闭)`;结果申诉 `appealing`。 ### GET /tickets *(认证)* 工单列表(带过滤)。Query: `type` / `status` / `priority` / `claimed=0|1` / `search`。 - player: 仅自己的工单 - admin: 待处理 + 自己接的(建议/投诉管理员/结果申诉不可见) - owner: 全部 ### GET /tickets/stats *(认证)* ```json { "total": 12, "byStatus": { "pending": 3, "processing": 2 } } ``` ### GET /tickets/unclaimed *(admin/owner)* 待认领工单。Query: `type`。 ### GET /tickets/reported-players *(admin/owner)* 被举报人聚合统计(次数/处理中/已解决/已驳回/最近时间/常见原因)。 ### GET /tickets/tracking?token=xxx 凭追踪标识查工单(匿名追踪用,无需登录)。 ### GET /tickets/:id *(认证)* 工单详情(含 responses / attachments / transfers / parent_ticket)。 ### POST /tickets *(可选认证)* 提交工单(支持匿名;登录用户可选用任一已绑定身份)。 `multipart/form-data` 或 JSON: ```json { "type": "report", // report | suggestion | appeal | result_appeal "title": "标题", "reporter_game_name": "Steve", // 登录用户可传自己的任一身份,后端校验归属 "reporter_game_uid": "UID", "target_game_name": "Alex", // 举报必填(与 UID 至少一项) "target_game_uid": "UID", "reason": "举报原因", // report/appeal 必填 "description": "详细描述", // suggestion/appeal 必填 "priority": "medium", // low|medium|high|urgent "is_admin_complaint": 0, // 投诉管理员(仅服主可见) "parent_ticket_id": null // result_appeal 必填(原工单) } ``` 响应 201: `{ "id": 8, "tracking_token": "uuid", "message": "提交成功" }`(Set-Cookie 留存 tracking_token) ### PUT /tickets/:id *(admin/owner)* 更新状态/优先级/处理备注。 ```json { "status": "processing", "priority": "high", "claim_note": "内部备注" } ``` ### POST /tickets/:id/claim *(admin/owner)* 接单认领(建议/投诉管理员/结果申诉仅服主可认领)。 ```json { "claim_note": "内部备注", "initial_reply": "给玩家的初始回复" } ``` ### POST /tickets/:id/transfer *(admin/owner)* 转单。`{ "to_user_id": 2, "reason": "原因" }` ### POST /tickets/:id/response *(认证)* 回复/补充。`{ "content": "内容" }` ### POST /tickets/:id/anon-response 匿名补充(凭 tracking_token Cookie)。 ### POST /tickets/batch *(admin/owner)* 批量操作。`{ "ids": [1,2], "action": "delete|status|close", "status": "resolved" }` --- ## 三、封禁 Bans *(owner)* ### GET /bans、GET /bans/active、GET /bans/min-duration *(认证)* 封禁列表 / 生效中 / 最短时长校验。 ### POST /bans *(owner)* ```json { "player_name": "Alex", "player_uid": "UID", "source": "netease|skin", "type": "ban|mute|warn|other", "duration": "7天", "reason": "原因", "ticket_id": null } ``` ### PUT /bans/:id *(owner)* 更新状态(`active|expired|appealed|lifted`)/原因/时长。 ### DELETE /bans/:id *(owner)* 删除记录。 --- ## 四、用户管理 Users *(admin/owner)* ### GET /users *(admin/owner)*、GET /users/:id *(admin/owner)* 用户列表(含 `identity_count` 身份数)/ 详情(含 `identities` 全部身份、管辖子服务器)。 ### POST /users *(admin/owner)* 创建用户(自动写入 user_identities 主身份)。角色 owner 仅服主可建。 ### PUT /users/:id *(admin/owner)* 更新邮箱/游戏名/UID/来源/角色/状态/密码/管辖服务器。主身份字段变化自动同步 `user_identities`。 ### POST /users/:id/identities *(admin/owner)* 管理员为用户绑定额外来源身份(多身份管理)。 ```json { "source": "skin", "game_name": "Alex", "game_uid": "SKIN_UUID" } ``` 规则同 `POST /auth/identities`(同来源唯一、游戏名全局唯一、网易端必填 UID)。皮肤站来源同样支持「获取 UUID」辅助查询。 ### DELETE /users/:id/identities/:identityId *(admin/owner)* 管理员解绑用户身份(至少保留一个)。 ### GET /users/:id/servers *(admin/owner)* 管辖子服务器列表。 --- ## 五、系统设置 Settings *(admin/owner)* | 端点 | 说明 | |------|------| | GET /settings/settings | 全部设置(站点名称/地址/版权/ICP/SMTP) | | PUT /settings/settings | 批量更新设置 | | GET /settings/email-templates | 邮件模板列表 | | GET /settings/email-templates/:code | 模板详情 | | PUT /settings/email-templates/:code | 更新模板(subject/body,支持 HTML 与 {{变量}}) | 可用模板: `verify_email` / `email_code` / `ticket_created` / `ticket_updated` / `ticket_claimed` / `ticket_transferred` / `reset_password` --- ## 六、通知 Notifications *(admin/owner)* ### GET/POST /notifications 列表 / 创建 `{ name, type: "webhook|email", webhook_url, events: "all|ticket_created,..." }` ### PUT/DELETE /notifications/:id 更新(名称/地址/类型/启用)/删除。 ### POST /notifications/:id/test 发送测试 Webhook。 --- ## 七、投票 Polls | 端点 | 认证 | 说明 | |------|------|------| | GET /polls/groups | 认证 | 分组/子服列表 | | POST /polls/groups | owner | 添加分组 | | DELETE /polls/groups/:id | owner | 删除分组 | | GET /polls/active | 认证 | 当前生效投票(按分组聚合,含票数/我的投票) | | GET/PUT/DELETE /polls/:id | owner | 详情/更新/删除 | | POST /polls | owner | 创建(≥2选项,同子服仅一个进行中) | | POST /polls/:id/vote | 认证 | 投票(管理员 1.5 票权,一人一票) | --- ## 八、更新内容 Features | 端点 | 认证 | 说明 | |------|------|------| | GET /features | 认证 | 列表(状态: 待定/计划中/已完成) | | POST /features | owner | 创建 | | PUT/DELETE /features/:id | owner | 更新/删除 | | POST /features/:id/vote | 认证 | 点赞 | | POST /features/:id/comment | 认证 | 发表评论 | --- ## 九、导出 Export *(owner)* | 端点 | 说明 | |------|------| | GET /export/tickets?type=&status=&start_date=&end_date=&format=csv | 工单导出 | | GET /export/reported-players?format=csv | 被举报人统计导出 | | GET /export/audit-logs?start_date=&end_date=&format=csv | 操作日志导出 | | GET /export/dashboard | 控制台统计(总数/类型/状态/今日/用户数/月度趋势) | --- ## 九·五、日志 Logs *(admin/owner)* 系统自动记录邮件发送结果、Webhook 调用、服务器错误,后台「系统日志」页可查,方便排查。 | 端点 | 说明 | |------|------| | GET /logs/emails?status=sent\|failed&email=&limit= | 邮件日志(收件人/模板/主题/状态/错误) | | GET /logs/system?level=info\|warn\|error&source=&limit= | 系统日志(级别/来源/消息/详情) | 记录来源:mailer(SMTP 未配置/发送成功/失败)、webhook(拦截内网/非2xx/发送失败)、server(500 错误中间件)。日志写库失败不影响主流程,表自动迁移创建。 --- ## 十、验证码与文件 | 端点 | 说明 | |------|------| | GET /captcha | SVG 验证码 `{ id, svg }`(5 分钟有效) | | GET /uploads/:storedName | 附件下载(鉴权;玩家仅可访问自己工单附件) | --- ## 十一、外部 API(游戏插件 / Java 服务器) 认证:`x-external-key: `(安装时生成)。插件登录后可携带 Bearer JWT。 | 端点 | 认证 | 说明 | |------|------|------| | POST /external/auth/register | — | 插件注册(邮箱验证链接) | | POST /external/auth/login | — | 插件登录,返回 JWT | | GET /external/my-tickets | Bearer | 我的工单列表(limit ≤50) | | GET /external/my-tickets/:id | Bearer | 我的工单详情 | | POST /external/tickets | client | 提交工单(带 `server` 可选;返回 id + tracking_token) | | GET /external/tickets/track?token= | client | 按追踪码查工单状态+回复(提交→处理→结束全流程) | | GET /external/all-tickets | client | 全部工单(分页 page/limit ≤200,可按 `server`/`status`/`type` 过滤) | | GET /external/all-tickets/:id | client | 工单详情(含回复/附件) | | GET /external/bans?server=&status=&player= | client | 拉取封禁列表(可按子服/状态/玩家过滤) | | POST /external/bans | client | 新增封禁(可带 `server`) | | GET /external/reported-players?server= | client | 被举报统计(可按子服过滤) | | GET /external/servers | client | 服务器列表(含外部别名) | | GET /external/stats?server= | client | 工单统计(可按子服过滤) | | POST /external/clients | Bearer(owner/admin) | 创建 API 客户端,返回 client_id + secret(仅显示一次) | | GET /external/clients | Bearer(owner/admin) | 客户端列表 | | PUT /external/clients/:id | Bearer(owner/admin) | 启用/停用客户端 | | DELETE /external/clients/:id | Bearer(owner/admin) | 删除客户端 | ### 外部鉴权(三选一) | 方式 | 请求头 | 适用 | |------|--------|------| | 多客户端(推荐) | `x-api-client-id` + `x-api-secret` | QQ机器人等外部系统,后台可创建/停用多个客户端 | | 旧版单 key | `x-external-key` | 兼容旧部署(`config.external_api_key`) | | 用户 JWT | `Authorization: Bearer ` | 插件/已登录用户 | ### 子服务器定位(`server` 参数) 每个子服可在「服务器管理」配置**外部别名(alias)**,外部 API 的 `server` 参数支持三种写法: - **别名**: `survival`(推荐,改名不影响) - **分组/子服**: `网易服务器/生存服` - **子服名**: `生存服`(同名时取第一个) 工单/封禁按提交时的 `server` 归属存储,查询时用同一参数即可精确拉取对应子服数据。 --- ## 十二、安装与健康 | 端点 | 说明 | |------|------| | GET /install/status | `{ installed: true|false }` | | POST /install/check-db | 测试数据库连接(不存在则自动建库;库名仅字母数字下划线) | | POST /install/complete | 完成安装:建表 + 创建服主 + 生成密钥(完成后无需重启,自动加载业务路由) | | GET /health | `{ status: "ok", installed: true|false }` | 安装流程(两步):`check-db` → `complete` → 前端自动刷新并跳转登录。 --- ## 数据兼容与迁移 新增多来源身份功能时,`backend/db.js` 的 `migrateAdditions` 自动执行(幂等): 1. 创建 `user_identities` 表(UNIQUE(user_id, source)) 2. 从 `users` 表回填主身份:`INSERT IGNORE ... SELECT id, source, game_name, game_uid FROM users` 3. 注册/插件注册/管理员创建用户时自动写入主身份记录 4. 管理员编辑主身份字段时自动同步 `user_identities` 5. 工单提交:登录用户可选择任一已绑定身份(后端校验归属);匿名仍走表单字段 > 老数据无需手工处理,服务启动时自动迁移;`users` 表原有字段(主身份)保持不变,完全向后兼容。 外部 API 功能新增迁移(幂等,服务启动自动执行): 1. 创建 `api_clients` 表(多客户端鉴权) 2. `server_groups` 加 `alias` 列(子服外部别名) 3. `tickets` / `bans` 加 `server_name` 列(按子服归属存储) > 老工单/封禁 `server_name` 为空串,不影响原有查询;新提交的数据自动带子服归属。