Initial commit

This commit is contained in:
lofyer
2026-08-24 17:27:41 +08:00
commit 5ff80caf7e
45 changed files with 11485 additions and 0 deletions
+124
View File
@@ -0,0 +1,124 @@
# 公共反馈 API
## Endpoint
```text
POST /api/v1/feedback
```
该接口不使用用户账户。服务端按来源 IP 和 `installationId` 的 keyed
digest 分别限流,并使用 `(productKey, clientRequestId)` 保证幂等。
生产环境必须使用 HTTPS。若请求包含 `Origin`,它必须与服务端
`PUBLIC_ORIGIN` 的 origin 完全一致。桌面应用的 Main 进程请求通常不发送
`Origin`。
## JSON 提交
```http
POST /api/v1/feedback HTTP/1.1
Content-Type: application/json
{
"schemaVersion": 1,
"productKey": "goodbuddy",
"category": "bug",
"title": "魔法笔记页签不可见",
"description": "平台功能中的魔法笔记页签被布局压缩,无法看到或点击。",
"contactEmail": "user@example.com",
"environment": {
"appVersion": "0.11.0",
"platform": "windows",
"architecture": "x64",
"locale": "zh-CN"
},
"installationId": "00000000-0000-4000-8000-000000000101",
"clientRequestId": "00000000-0000-4000-8000-000000000102"
}
```
## Multipart 提交截图
使用 `multipart/form-data` 时:
- `payload`:上述 JSON 的字符串形式
- `screenshot`:可选,最多一个 PNG、JPEG 或 WebP 文件
```sh
curl \
--fail-with-body \
--form 'payload={
"schemaVersion":1,
"productKey":"goodbuddy",
"category":"bug",
"title":"魔法笔记页签不可见",
"description":"平台功能中的魔法笔记页签被布局压缩,无法看到或点击。",
"installationId":"00000000-0000-4000-8000-000000000101",
"clientRequestId":"00000000-0000-4000-8000-000000000102"
}' \
--form 'screenshot=@capture.png;type=image/png' \
https://feedback.example.com/api/v1/feedback
```
服务端会验证实际解码格式,只接受单帧 PNG、JPEG 或 WebP,随后应用方向
信息、重编码为 PNG 并去除原文件元数据。
输入和重编码后的文件都必须满足 `MAX_SCREENSHOT_BYTES`。最大边长为
8192 像素,最大像素数为 3200 万。
## 字段
| 字段 | 必填 | 约束 |
| --- | --- | --- |
| `schemaVersion` | 是 | 当前固定为 `1` |
| `productKey` | 是 | 2–64 位小写字母、数字或连字符,产品必须启用 |
| `category` | 是 | `bug`、`feature`、`experience`、`other` |
| `title` | 是 | 去除首尾空白后 1–120 字符 |
| `description` | 是 | 去除首尾空白后 10–5000 字符 |
| `contactEmail` | 否 | 有效邮箱,最多 254 字符 |
| `environment.appVersion` | 环境存在时 | 1–64 字符 |
| `environment.platform` | 环境存在时 | `windows`、`macos`、`linux`、`unknown` |
| `environment.architecture` | 环境存在时 | `x64`、`arm64`、`unknown` |
| `environment.locale` | 否 | 2–32 字符 |
| `installationId` | 是 | 应用安装级随机 UUID,不应使用硬件 ID |
| `clientRequestId` | 是 | 每次新反馈生成的随机 UUID;重试时保持不变 |
请求对象采用严格 schema,未声明字段会导致请求失败。
## 成功响应
首次创建返回 HTTP 201:
```json
{
"reference": "GOODBUDDY-000001",
"duplicate": false
}
```
同一产品和 `clientRequestId` 的重试返回 HTTP 200,并返回原编号:
```json
{
"reference": "GOODBUDDY-000001",
"duplicate": true
}
```
## 错误
| HTTP | 含义 |
| --- | --- |
| 400 | 字段、JSON、multipart 或图片无效 |
| 403 | 请求 `Origin` 不允许 |
| 404 | 产品不存在或已停用 |
| 413 | 请求体超过限制 |
| 429 | IP 或安装实例超过提交频率 |
| 500 | 服务端内部错误 |
客户端应:
1. 为一次用户提交生成 `clientRequestId`,网络重试时复用。
2. 设置明确的连接与总超时。
3. 限制响应体大小,只接受 JSON。
4. 将非 2xx 响应作为失败处理,并向用户保留输入内容。
5. 仅在用户明确选择后添加截图。