kt-template-online-api/API.md

474 lines
36 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.

# KT Template Online API
本文是当前 API 的人工索引。字段细节、Swagger 示例和 DTO 以运行态 Swagger/Knife4j 为准:
- 全量 Swagger`/api`
- OpenAPI JSON`/api-json`
- Admin 分组:`/api/admin`
- QQBot 分组:`/api/qqbot`
- WordPress 分组:`/api/wordpress`
- 基础能力分组:`/api/basic`
## 通用约定
后端固定监听 `48085`。根路径 `GET /` 重定向到 `/api#/`
除文件下载、SSE、反向 WebSocket 等特殊接口外,业务接口统一返回:
```json
{
"code": 200,
"msg": "操作成功",
"data": {}
}
```
错误响应统一把 `err` 输出为字符串:
```json
{
"code": 400,
"msg": "操作失败",
"err": "错误原因"
}
```
### 认证
Admin、Component、Dict、MinIO、Blog 管理、WordPress 管理和 QQBot 管理接口默认需要后台登录态。
支持两种 access token 传递方式:
- `Authorization: Bearer <accessToken>`
- 登录接口写入的 httpOnly `admin_access_token` cookie
公开接口包括 `/auth/login`、`/auth/refresh`、`/auth/logout`、部分 Blog public 接口和根路径。具体以 Controller 上的 `@Public()` 为准。
### ID 与时间
- 后台主键使用 Snowflake 数字 ID接口按字符串返回避免 JavaScript 长整型精度丢失。
- 后端格式化时间字段统一使用 `KtDateTime extends Date`Entity 通过 `@KtDateTimeColumn(format)`、`@KtCreateDateColumn(format)`、`@KtUpdateDateColumn(format)` 在 TypeORM hydrate 边界转换DTO/外部数据源通过 `@KtDateTimeField(format)` + `transformKtDateTimeFields()` 转换。默认输出 `YYYY-MM-DD HH:mm:ss`,可在装饰器中传入格式字符串;响应包装不做递归遍历。
- `POST */save` 默认会删除请求体里的 `id`,防止新增接口误用前端主键。
## 环境变量分组
| 分组 | 关键变量 |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MySQL | `DB_HOST`、`DB_PORT`、`DB_USERNAME`、`DB_PASSWORD`、`DB_DATABASE`、`DB_SYNC` |
| MinIO | `MINIO_ENDPOINT`、`MINIO_PORT`、`MINIO_ACCESS_KEY`、`MINIO_SECRET_KEY`、`MINIO_BUCKET` |
| Admin | `ADMIN_TOKEN_SECRET`、`ADMIN_COOKIE_SECURE`、`SNOWFLAKE_WORKER_ID`、`SNOWFLAKE_DATACENTER_ID` |
| WordPress | `WORDPRESS_BASE_URL`、`WORDPRESS_HOST_HEADER`、`WORDPRESS_ADMIN_USERNAME`、`WORDPRESS_ADMIN_PASSWORD` |
| Loki | `LOG_LEVEL`、`LOG_APP_NAME`、`LOKI_URL`、`LOKI_QUERY_HOST`、`LOKI_QUERY_SELECTOR` |
| QQBot | `QQBOT_ENABLED`、`QQBOT_ACCOUNT_SECRET_KEY`、`QQBOT_REVERSE_WS_PATH`、`QQBOT_REVERSE_WS_TOKEN`、`QQBOT_EVENT_BUS`、`QQBOT_SEND_*`、`QQBOT_COMMAND_MIN_COOLDOWN_MS`、`QQBOT_RULE_MIN_COOLDOWN_MS`、`QQBOT_REPEATER_*` |
| NapCat | `NAPCAT_WEBUI_BASE_URL`、`NAPCAT_WEBUI_TOKEN`、`QQBOT_NAPCAT_*` |
| MQTT | `MQTT_URL`、`MQTT_USERNAME`、`MQTT_PASSWORD`、`MQTT_CLIENT_ID` |
| BangDream | `BANGDREAM_TSUGU_MAIN_SERVER`、`BANGDREAM_TSUGU_DISPLAYED_SERVERS`、`BANGDREAM_TSUGU_CACHE_ROOT` |
| FF14 Market | `FF14_XIVAPI_BASE_URL`、`FF14_UNIVERSALIS_BASE_URL`、`FF14_DEFAULT_WORLD` |
| FFLogs | `FFLOGS_GRAPHQL_URL`、`FFLOGS_TOKEN_URL`、`FFLOGS_CLIENT_ID`、`FFLOGS_CLIENT_SECRET` |
真实密码、Token、OAuth secret 和生产 env 不提交到 Git。
## Admin 与基础后台
### Auth / User
| 方法 | 路径 | 说明 |
| ------ | --------------- | ------------------------------------------------------------------------------------- |
| `POST` | `/auth/login` | 后台登录,返回 accessToken、用户信息和 WordPress 自动登录状态,并写入 httpOnly cookie |
| `POST` | `/auth/refresh` | 通过 refresh token cookie 刷新 accessToken |
| `POST` | `/auth/logout` | 清理 Admin 与 WordPress 登录 cookie |
| `GET` | `/auth/codes` | 获取当前用户按钮权限码 |
| `GET` | `/user/info` | 获取当前用户信息 |
`/auth/login` 会尝试用 env 中的 WordPress 管理员账号建立 WordPress 登录态。WordPress 不可用时Admin 主登录仍成功,返回 `wordpressAuth=null`、`wordpressAvailable=false`,菜单和权限码会过滤 Blog 管理入口。
### Menu / Role / Dept / User Manage
| 方法 | 路径 | 说明 |
| -------- | -------------------------- | ------------------ |
| `GET` | `/menu/all` | 当前用户菜单 |
| `GET` | `/system/menu/list` | 系统菜单树 |
| `GET` | `/system/menu/name-exists` | 菜单 name 重名校验 |
| `GET` | `/system/menu/path-exists` | 菜单 path 重名校验 |
| `POST` | `/system/menu` | 新增菜单 |
| `PUT` | `/system/menu/:id` | 更新菜单 |
| `DELETE` | `/system/menu/:id` | 删除菜单及子菜单 |
| `GET` | `/system/role/list` | 角色分页 |
| `POST` | `/system/role` | 新增角色 |
| `PUT` | `/system/role/:id` | 更新角色 |
| `DELETE` | `/system/role/:id` | 删除角色 |
| `GET` | `/system/dept/list` | 部门树 |
| `POST` | `/system/dept` | 新增部门 |
| `PUT` | `/system/dept/:id` | 更新部门 |
| `DELETE` | `/system/dept/:id` | 删除部门 |
| `GET` | `/system/user/list` | 用户分页 |
| `POST` | `/system/user` | 新增用户 |
| `PUT` | `/system/user/:id` | 更新用户 |
| `DELETE` | `/system/user/:id` | 删除用户 |
### Dict
| 方法 | 路径 | 说明 |
| -------- | ------------------------------ | ---------------------------------------------------------------------------------- |
| `GET` | `/dict/list` | 字典项分页,支持 `dictCode`、`keyword`、`label`、`value`、`childrenCode`、`status` |
| `GET` | `/dict/tree` | 兼容树形字典视图 |
| `GET` | `/dict/groups` | 字典编码分组列表,适合左右表左侧分组 |
| `GET` | `/dict/codes` | 字典编码选项 |
| `GET` | `/dict/getDictByKey` | 按 `dictKey` 获取启用字典项 |
| `GET` | `/dict/getComponentDictByType` | 按组件一级类型查二级类型 |
| `POST` | `/dict/save` | 新增字典项 |
| `POST` | `/dict/update` | 更新字典项 |
| `DELETE` | `/dict/:id` | 物理删除字典项 |
| `POST` | `/dict/toggle` | 启停字典项 |
字典核心字段:
| 字段 | 说明 |
| -------------- | --------------------------------------------------------- |
| `dictCode` | 字典分组,例如 `COMPONENT_TYPE`、`BANGDREAM_SERVER_ALIAS` |
| `label` | 展示文本 |
| `value` | 字典值 |
| `childrenCode` | 关联子分组编码 |
| `sort` | 排序 |
| `status` | `1` 启用 |
### Component
组件接口保持 `/component/*` 路径兼容,但数据表为 `admin_component`
| 方法 | 路径 | 说明 |
| ------ | ----------------------- | -------------------------------------------------------------------- |
| `GET` | `/component/allList` | 全量组件 |
| `GET` | `/component/list` | 组件分页,支持 `pageNo`、`pageSize`、`name`、`type`、`componentType` |
| `GET` | `/component/detail?id=` | 组件详情 |
| `POST` | `/component/save` | 新增组件 |
| `POST` | `/component/update` | 更新组件 |
| `POST` | `/component/remove?id=` | 逻辑删除组件 |
### Timezone / Upload / Demo
| 方法 | 路径 | 说明 |
| ------ | ------------------------------ | ----------------------------- |
| `GET` | `/timezone/getTimezoneOptions` | 时区选项 |
| `GET` | `/timezone/getTimezone` | 当前用户时区 |
| `POST` | `/timezone/setTimezone` | 设置当前用户时区 |
| `POST` | `/upload` | Vben 上传适配,实际写入 MinIO |
| `GET` | `/table/list` | Vben 示例表格 |
| `GET` | `/status` | 状态码测试 |
| `GET` | `/demo/bigint` | BigInt JSON 测试 |
| `GET` | `/test` | GET 测试 |
| `POST` | `/test` | POST 测试 |
## 系统日志
后端通过 `nestjs-pino` 输出结构化日志。配置 Loki 后Admin 日志页面通过后端代理查询,不直连 Loki。
| 方法 | 路径 | 说明 |
| ----- | ---------------------- | --------------------------------------------------------------------------------------------------------- |
| `GET` | `/system/logs` | 日志分页,支持 `level`、`keyword`、`context`、`path`、`requestId`、`startTime`、`endTime`、`rangeMinutes` |
| `GET` | `/system/logs/summary` | 按级别统计 |
| `GET` | `/system/logs/levels` | 日志级别选项 |
| `GET` | `/system/logs/status` | Loki 查询配置状态 |
日志行包含 `timestamp`、`level`、`message`、`method`、`path`、`statusCode`、`durationMs`、`requestId`、`raw` 等字段。
### 系统站内信
站内信用于承接运行期事件,不再作为人工公告入口。后端在接口 5xx、QQBot OneBot 下线 notice、NapCat 容器日志检测到账户离线时自动生成或聚合一条通知,默认通知 `super` 角色;站内信接口在服务端也强制 `super` 角色访问。相同 `dedupeKey` 的事件通过 `active_dedupe_key` 唯一索引聚合,会累加 `occurrenceCount`,刷新 `lastSeenAt`,并把状态重新置为未处理。运行期通知会按表字段长度归一化 `title`、`dedupeKey`、`source`、`eventType` 和 `notifyRoleCode`,长 `dedupeKey` 会保留稳定 hash 后缀,避免长路径接口错误丢通知。
| 方法 | 路径 | 说明 |
| -------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET` | `/system/notice/list` | 日志级站内信分页列表,支持 `keyword`、`severity`、`source`、`eventType`、`status`、`isTop`、`notifyRoleCode`、`notifyUsers`、`pageNo`、`pageSize` |
| `GET` | `/system/notice/detail/:id` | 查询站内信详情 |
| `DELETE` | `/system/notice/:id` | 删除站内信(逻辑删除) |
| `POST` | `/system/notice/toggle` | 标记处理或重新打开(`id`、`status``1` 未处理,`0` 已处理) |
| `POST` | `/system/notice/top` | 切换置顶(`id`、`isTop` |
返回字段包含 `severity`、`source`、`eventType`、`dedupeKey`、`occurrenceCount`、`notifyRoleCode`、`metadata`、`firstSeenAt`、`lastSeenAt`。后端不暴露人工 `save/update` 入口。
## Blog 本地内容
`/blog/*` 是本地博客内容能力,供 `Vue/kt-blog-web` 和 Admin 博客管理使用。
### Blog Article
| 方法 | 路径 | 说明 |
| ------ | -------------------------------- | -------------------------- |
| `GET` | `/blog/article/public/list` | 公开文章分页 |
| `GET` | `/blog/article/public/detail` | 公开文章详情,支持 id/slug |
| `GET` | `/blog/article/list` | 后台文章分页 |
| `GET` | `/blog/article/detail` | 后台文章详情 |
| `POST` | `/blog/article/save` | 新增文章 |
| `POST` | `/blog/article/update` | 更新文章 |
| `POST` | `/blog/article/remove` | 删除文章 |
| `GET` | `/blog/article/category-options` | 文章分类选项 |
| `GET` | `/blog/article/tag-options` | 文章标签选项 |
| `POST` | `/blog/article/import-wordpress` | 从 WordPress 导入文章 |
文章 body 常用字段:
```json
{
"title": "文章标题",
"slug": "post-slug",
"status": "publish",
"content": "Markdown 或 HTML",
"contentFormat": "markdown",
"cover": "",
"categories": ["tech"],
"tags": ["kt"]
}
```
### Blog Category / Tag / Theme
| 方法 | 路径 | 说明 |
| ------ | ------------------------------ | ------------------------- |
| `GET` | `/blog/category/list` | 本地分类分页 |
| `GET` | `/blog/category/detail` | 本地分类详情 |
| `POST` | `/blog/category/save` | 新增分类 |
| `POST` | `/blog/category/update` | 更新分类 |
| `POST` | `/blog/category/remove` | 删除分类 |
| `GET` | `/blog/tag/list` | 本地标签分页 |
| `GET` | `/blog/tag/detail` | 本地标签详情 |
| `POST` | `/blog/tag/save` | 新增标签 |
| `POST` | `/blog/tag/update` | 更新标签 |
| `POST` | `/blog/tag/remove` | 删除标签 |
| `GET` | `/blog/term/options` | 分类/标签选项 |
| `GET` | `/blog/theme/config` | 获取 Argon 主题配置 |
| `POST` | `/blog/theme/save` | 保存本地主题配置 |
| `POST` | `/blog/theme/import-wordpress` | 从 WordPress 导入主题配置 |
## WordPress 代理
`/wordpress/*` 需要 Admin 登录态和 WordPress 登录态。后端优先使用 `kt_wordpress_auth` httpOnly cookie也支持显式透传 WordPress 认证 header。
| 方法 | 路径 | 说明 |
| ------ | ------------------------- | ----------------------------------------------- |
| `POST` | `/wordpress/auth/login` | 使用 env 管理员账号登录 WordPress 并写入 cookie |
| `POST` | `/wordpress/auth/logout` | 清理 WordPress cookie |
| `GET` | `/wordpress/auth/check` | 校验 WordPress 登录态 |
| `GET` | `/wordpress/theme/config` | 读取 WordPress Argon 主题配置 |
### WordPress Article / Tag / Category
| 方法 | 路径 | 说明 |
| ------ | ---------------------------------- | ------------------- |
| `GET` | `/wordpress/article/public/list` | 公开文章列表代理 |
| `GET` | `/wordpress/article/public/detail` | 公开文章详情代理 |
| `GET` | `/wordpress/article/list` | WordPress 文章分页 |
| `GET` | `/wordpress/article/detail` | WordPress 文章详情 |
| `POST` | `/wordpress/article/save` | 新增 WordPress 文章 |
| `POST` | `/wordpress/article/update` | 更新 WordPress 文章 |
| `POST` | `/wordpress/article/remove` | 删除 WordPress 文章 |
| `GET` | `/wordpress/tag/list` | 标签分页 |
| `GET` | `/wordpress/tag/detail` | 标签详情 |
| `POST` | `/wordpress/tag/save` | 新增标签 |
| `POST` | `/wordpress/tag/update` | 更新标签 |
| `POST` | `/wordpress/tag/remove` | 删除标签 |
| `GET` | `/wordpress/category/list` | 分类分页 |
| `GET` | `/wordpress/category/detail` | 分类详情 |
| `POST` | `/wordpress/category/save` | 新增分类 |
| `POST` | `/wordpress/category/update` | 更新分类 |
| `POST` | `/wordpress/category/remove` | 删除分类 |
WordPress rewrite 未开启导致 `/wp-json/*` 返回 404 时,后端会回退到 `?rest_route=/...`
## MinIO
| 方法 | 路径 | 说明 |
| -------- | ----------------------- | ------------------------------- |
| `GET` | `/minio/check` | 检查连接和 bucket |
| `POST` | `/minio/bucket` | 创建 bucket |
| `POST` | `/minio/upload` | 上传文件,`multipart/form-data` |
| `GET` | `/minio/list` | 文件列表 |
| `GET` | `/minio/url` | 临时访问 URL |
| `GET` | `/minio/resource-proxy` | 代理读取资源 |
| `GET` | `/minio/download` | 下载文件流 |
| `DELETE` | `/minio/remove` | 删除文件 |
`bucketName` 不传时使用 `MINIO_BUCKET`
## QQBot 管理
QQBot 运行态包括 NapCat 容器登录、OneBot v11 反向 WebSocket、MQTT 事件总线、账号能力绑定、在线命令、自动回复规则、权限名单、发送/接收日志和插件生态。
### Account / Scan Login
| 方法 | 路径 | 说明 |
| ------ | ----------------------------------------------- | -------------------------- |
| `GET` | `/qqbot/account/list` | QQBot 账号分页 |
| `GET` | `/qqbot/account/enabled` | 启用账号列表 |
| `POST` | `/qqbot/account/save` | 手动新增账号 |
| `POST` | `/qqbot/account/update` | 更新账号 |
| `POST` | `/qqbot/account/scan/create` | 扫码新增账号,创建登录会话 |
| `POST` | `/qqbot/account/scan/refresh?id=` | 对已有账号刷新登录态 |
| `GET` | `/qqbot/account/scan/status?sessionId=` | 查询扫码会话状态 |
| `GET` | `/qqbot/account/scan/events?sessionId=` | SSE 订阅扫码进度 |
| `POST` | `/qqbot/account/scan/qrcode/refresh?sessionId=` | 刷新当前会话二维码 |
| `POST` | `/qqbot/account/scan/captcha/submit` | 提交密码登录安全验证码结果 |
| `POST` | `/qqbot/account/scan/cancel?sessionId=` | 取消扫码会话 |
| `POST` | `/qqbot/account/delete?id=` | 删除账号并断开 WS |
| `POST` | `/qqbot/account/kick?selfId=` | 断开反向 WS 会话 |
| `POST` | `/qqbot/account/bind/command` | 绑定账号和在线命令 |
| `POST` | `/qqbot/account/unbind/command` | 解绑账号和在线命令 |
| `POST` | `/qqbot/account/bind/rule` | 绑定账号和自动回复规则 |
| `POST` | `/qqbot/account/unbind/rule` | 解绑账号和自动回复规则 |
账号保存支持可选 `encryptedLoginPassword`,用于 NapCat 密码登录。前端必须先通过 `/auth/password-public-key` 获取公钥并使用 RSA-OAEP 加密,不传明文 `loginPassword`;后端必须使用显式配置的 `QQBOT_ACCOUNT_SECRET_KEY`(或非默认 `ADMIN_TOKEN_SECRET`)二次加密落库,空值和公开默认值会被拒绝,不在列表/详情中返回。账号列表里的 `connectStatus` 只表示 OneBot 反向 WS`napcat.oneBotOnline`、`napcat.containerOnline`、`napcat.webuiOnline`、`napcat.qqLoginStatus`、`napcat.qqLoginMessage` 分别表示 OneBot、容器、WebUI 和 QQ 登录态,`webuiOnline=null` 表示本次使用缓存且未重新探测 WebUI`qqLoginMessage` 只承载真实 QQ 登录态消息WebUI 配置缺失或请求异常只放在 `lastError`
扫码链路返回 `sessionId`,前端应使用 SSE 查看步骤进度,而不是等待长 HTTP 请求完成。已有账号的更新登录会先重启目标 NapCat 容器尝试 `ACCOUNT`/`-q` 快速登录;目标账号在线则直接完成会话。没有历史登录态的新容器会跳过快速登录,优先尝试保存的登录密码;快速登录失败后,如果账号保存了登录密码,会临时注入 `NAPCAT_QUICK_PASSWORD` 并按 `QQBOT_NAPCAT_PASSWORD_LOGIN_WAIT_MS` / `QQBOT_NAPCAT_LOGIN_POLL_INTERVAL_MS` 轮询密码登录结果,准备阶段的扫码会话会持续续期,避免后台密码登录未完成时前端先判过期。密码登录触发 QQ 安全验证时,接口返回的 `captchaUrl` 只用于前端拉起腾讯验证码;前端必须把腾讯验证码返回的 `ticket`、`randstr`、`sid` 连同 `sessionId` 提交到 `/qqbot/account/scan/captcha/submit`,后端再代理到同一 NapCat 容器的 `/api/QQLogin/CaptchaLogin` 继续密码登录第二步。会话已有 `captchaUrl` 后,`/qqbot/account/scan/status` 遇到 NapCat 继续返回“需要验证码/继续完成验证/安全验证”但不带 URL 时仍保持 `pending` 和原 `captchaUrl`。密码登录成功后会重建容器移除该运行态密码,清理失败则本次登录失败;密码登录仍失败、验证码未完成、离线、账号不匹配或缺少 QQ 号时,再进入重置登录态和二维码兜底流程。看门狗自动登录使用同样的 quick -> password 顺序,但不会自动进入扫码阶段。
同一 QQ 账号只保留一个有效 NapCat 主容器。扫码后如果已有账号绑定到新容器后端会释放旧绑定和未共享的旧容器避免同账号多实例互相挤下线。OneBot notice 只有机器人下线、登录失效、`KickedOffLine` 等账号级信号才会记录 QQ 登录态异常并生成 `qqbot.account.offline` 站内信,普通群成员 kick 不属于账号离线信号。下线原因写入 `lastError` 前按 `last_error` 500 字符列宽截断;后续无错误的普通断连只更新 OneBot 连接状态,不清空该原因。账号列表会按近期缓存检查绑定 NapCat 容器的最新登录状态日志,日志检测默认 5 秒超时;`isOnline:false` 属于 QQ 登录态离线信号;心跳只代表 OneBot/容器通信,不能推导 QQ 登录态;近期连接只用于避免重连瞬间被旧缓存误伤,后续仍必须以 NapCat WebUI/日志检查判断 QQ 登录态。托管容器必须显式配置 `QQBOT_NAPCAT_IMAGE`,不要依赖 `latest` 默认镜像。
外发消息不直接抢发:后端会按 `QQBOT_SEND_GLOBAL_INTERVAL_MS`、`QQBOT_SEND_TARGET_INTERVAL_MS` 和 `QQBOT_SEND_JITTER_MS` 预约发送窗口,默认全局 2500ms、同会话 8000ms、抖动 0-800ms如果等待超过 `QQBOT_SEND_MAX_QUEUE_WAIT_MS`,本次发送会在下发前被拒绝。在线命令和自动回复规则会叠加运行时保底冷却,默认命令 5000ms、规则 30000ms复读机默认连续 4 次相同普通文本才触发,同一会话默认 10 分钟内只复读一次,并限制普通文本长度,减少自动行为被风控识别的概率。
### Command / Rule / Permission
| 方法 | 路径 | 说明 |
| ------ | ---------------------------------------- | ------------------------------------------------------------------- |
| `GET` | `/qqbot/command/list` | 在线命令分页,支持 `pluginKey`、`operationKey`、`selfId`、`enabled` |
| `POST` | `/qqbot/command/save` | 新增在线命令 |
| `POST` | `/qqbot/command/update` | 更新在线命令 |
| `POST` | `/qqbot/command/delete?id=` | 删除在线命令 |
| `POST` | `/qqbot/command/toggle?id=&enabled=` | 启停在线命令 |
| `POST` | `/qqbot/command/test` | 预览测试在线命令 |
| `GET` | `/qqbot/rule/list` | 自动回复规则分页 |
| `POST` | `/qqbot/rule/save` | 新增自动回复规则 |
| `POST` | `/qqbot/rule/update` | 更新自动回复规则 |
| `POST` | `/qqbot/rule/delete?id=` | 删除自动回复规则 |
| `POST` | `/qqbot/rule/toggle?id=&enabled=` | 启停自动回复规则 |
| `GET` | `/qqbot/permission/config` | 权限名单配置 |
| `POST` | `/qqbot/permission/config` | 保存权限名单配置 |
| `GET` | `/qqbot/permission/allowlist` | 白名单分页 |
| `POST` | `/qqbot/permission/allowlist/save` | 新增白名单 |
| `POST` | `/qqbot/permission/allowlist/update` | 更新白名单 |
| `POST` | `/qqbot/permission/allowlist/delete?id=` | 删除白名单 |
| `GET` | `/qqbot/permission/blocklist` | 黑名单分页 |
| `POST` | `/qqbot/permission/blocklist/save` | 新增黑名单 |
| `POST` | `/qqbot/permission/blocklist/update` | 更新黑名单 |
| `POST` | `/qqbot/permission/blocklist/delete?id=` | 删除黑名单 |
`/qqbot/command/test` 示例:
```json
{
"commandId": "2041700000000000001",
"text": "/查曲 夏祭り",
"selfId": "10000",
"targetType": "group",
"targetId": "123456",
"userId": "2354598417"
}
```
线上 smoke 必须按 `operationKey` 查询启用命令 ID 后传入 `commandId`,避免默认 `preview` selfId 误报未匹配命令。
### Plugin / Dashboard / Send / Message
| 方法 | 路径 | 说明 |
| ------ | ------------------------------ | ------------------------------------------ |
| `GET` | `/qqbot/plugin/list` | 插件列表,支持 `triggerMode=command/event` |
| `GET` | `/qqbot/plugin/operation/list` | 插件能力列表 |
| `GET` | `/qqbot/plugin/health` | 插件健康检查 |
| `GET` | `/qqbot/plugin/event/list` | 事件触发插件绑定状态 |
| `POST` | `/qqbot/plugin/event/bind` | 绑定事件触发插件 |
| `POST` | `/qqbot/plugin/event/unbind` | 解绑事件触发插件 |
| `GET` | `/qqbot/dashboard/summary` | QQBot 工作台汇总 |
| `GET` | `/qqbot/send/log/list` | 发送日志分页 |
| `POST` | `/qqbot/send/private` | 发送私聊消息 |
| `POST` | `/qqbot/send/group` | 发送群聊消息 |
| `GET` | `/qqbot/conversation/list` | 会话列表 |
| `GET` | `/qqbot/message/list` | 消息列表 |
### OneBot Reverse WebSocket
`QQBOT_REVERSE_WS_PATH` 默认是 `/qqbot/onebot/reverse`。NapCat 通过反向 WS 连接 APItoken 使用 `QQBOT_REVERSE_WS_TOKEN`
## QQBot 插件能力
### BangDream
插件 key`bangDream`。当前源码根目录为 `src/qqbot/plugins/bangDream`,不再使用旧 `tsugu` 子目录。
| operation key | 命令 | 说明 |
| ----------------------------- | ------------- | ------------------------ |
| `bangdream.song.search` | `/查曲` | 查歌曲信息图片 |
| `bangdream.song.chart` | `/查谱面` | 查谱面图片 |
| `bangdream.song.random` | `/随机曲` | 随机歌曲 |
| `bangdream.song.meta` | `/查询分数表` | 查歌曲分数榜 |
| `bangdream.card.search` | `/查卡` | 查卡牌信息图片 |
| `bangdream.card.illustration` | `/查卡面` | 查卡面插画 |
| `bangdream.character.search` | `/查角色` | 查角色信息 |
| `bangdream.event.search` | `/查活动` | 查活动信息 |
| `bangdream.event.stage` | `/查试炼` | 查活动试炼,保持拆图输出 |
| `bangdream.player.search` | `/查玩家` | 查玩家信息 |
| `bangdream.gacha.search` | `/查卡池` | 查卡池 |
| `bangdream.gacha.simulate` | `/抽卡模拟` | 模拟抽卡 |
| `bangdream.cutoff.detail` | `/ycx` | 单档位预测线 |
| `bangdream.cutoff.all` | `/ycxall` | 全档位预测线 |
| `bangdream.cutoff.recent` | `/lsycx` | 历史/近期档线 |
`registry/operation-registry.ts` 是 BangDream operation、handlerName、别名、冷却和说明的单一来源。新增或调整命令必须同步在线命令 SQL并跑 registry/command-SQL 测试。
### FF14 Market
插件 key`ff14Market`。
| operation key | 说明 |
| ------------------- | ------------------------------------------ |
| `ff14.item.resolve` | 按物品名称或 ID 解析 XIVAPI 物品 |
| `ff14.market.price` | 查询指定服务器/大区的 Universalis 市场价格 |
市场查价支持 `item`、`itemId`、`world`、`dataCenter`、`region`、`hq`、`language`。
### FFLogs
插件 key`fflogs`。
| operation key | 说明 |
| -------------------------- | --------------------------------------------------------------- |
| `fflogs.character.summary` | 查询 FFLogs 角色公开排名;传 `encounter` 时查询指定高难最近记录 |
常用输入:`characterName`、`serverSlug`、`serverRegion`、`encounter`、`limit`、`metric`、`timeframe`、`zoneId`。
## 初始化 SQL
| 文件 | 用途 |
| ---------------------------------------------- | --------------------------------------------------------- |
| `sql/vben-admin-init.sql` | 创建 Admin 基础表、用户、角色、菜单、部门、字典和空组件表 |
| `sql/blog-init.sql` | 初始化本地 Blog 表 |
| `sql/blog-menu.sql` | 初始化 Blog 管理菜单 |
| `sql/qqbot-init.sql` | 初始化 QQBot 表、插件命令和字典 |
| `sql/system-log-menu.sql` | 初始化系统日志菜单和权限 |
| `sql/system-notice-menu.sql` | 初始化系统站内信表与菜单权限 |
| `sql/migrate-dict-to-admin-dict.sql` | 旧 `dict` 迁移到 `admin_dict` |
| `sql/migrate-component-to-admin-component.sql` | 旧 `component` 迁移到 `admin_component` |
| `sql/fix-admin-menu-meta.sql` | 修复菜单 meta 被覆盖为空 |
| `sql/fix-admin-user-zero-id.sql` | 修复旧版本 `admin_user.id=0` 脏数据 |
## 验证入口
常规文档/配置检查:
```bash
git diff --check
```
后端代码检查:
```bash
pnpm run typecheck
pnpm run lint
pnpm test
```
BangDream 图片 smoke
```powershell
.\scripts\bangdream-render-smoke.ps1 -OperationKey bangdream.song.search -Text "夏祭り" -OutFile ".kt-workspace/bangdream-smoke/song.jpg"
.\scripts\bangdream-render-smoke.ps1 -OperationKey bangdream.event.stage -Text "310" -OutFile ".kt-workspace/bangdream-smoke/stage.jpg"
```
Jenkins/K8s 发布后还需要观察 rollout、新 Pod 日志,并跑真实运行态 smoke推送成功不等于发布完成。