85 lines
3.1 KiB
Markdown
85 lines
3.1 KiB
Markdown
# 实例自定义图标技术设计
|
||
|
||
## 数据流
|
||
|
||
```text
|
||
本地 PNG/JPEG/WebP
|
||
→ 浏览器解码并居中裁剪为 512×512 PNG
|
||
→ POST /api/instance-icon(Bearer,二进制,≤4 MiB)
|
||
→ 服务端验证 Content-Type、PNG 签名、IHDR 尺寸
|
||
→ CONFIG_DIR/.instance-icon.png.tmp 原子 rename
|
||
→ 返回 { custom, version, updatedAt, url }
|
||
→ 前端更新 favicon、Apple Touch、登录 Logo、通知图标与设置预览
|
||
```
|
||
|
||
## 持久化与升级
|
||
|
||
- 正式文件:`CONFIG_DIR/instance-icon.png`。
|
||
- 临时文件:`CONFIG_DIR/.instance-icon.png.tmp`,失败时清理。
|
||
- 默认 `CONFIG_DIR` 为 `APP_DIR/config`;`.gitignore` 精确忽略这两个文件。
|
||
- 如果部署设置 `CC_WEB_CONFIG_DIR` 到仓库外,图标自动跟随外置配置目录。
|
||
- 不覆盖任何 `public/*.png`,源码升级只更新默认兜底图。
|
||
|
||
## HTTP 契约
|
||
|
||
### GET /api/instance-icon/config
|
||
|
||
公开返回:
|
||
|
||
```json
|
||
{
|
||
"custom": true,
|
||
"version": "sha256-short-hash",
|
||
"updatedAt": "ISO-8601",
|
||
"url": "/api/instance-icon?v=sha256-short-hash"
|
||
}
|
||
```
|
||
|
||
未配置时 `custom=false`,`version=default`,URL 仍指向统一读取接口。
|
||
|
||
### GET /api/instance-icon
|
||
|
||
- 自定义存在且有效:返回该 PNG。
|
||
- 未配置或运行文件失效:返回 `public/icon-192.png`。
|
||
- `Content-Type: image/png`、`X-Content-Type-Options: nosniff`。
|
||
- 使用 ETag/no-cache;版本化 URL 负责同页缓存刷新。
|
||
|
||
### POST /api/instance-icon
|
||
|
||
- 必须通过现有 Bearer token 鉴权。
|
||
- 仅 `Content-Type: image/png`,body 非空且不超过 4 MiB。
|
||
- 必须是标准 PNG 签名,IHDR 宽高均为 512。
|
||
- 固定路径原子写入;返回最新配置对象。
|
||
|
||
### DELETE /api/instance-icon
|
||
|
||
- 必须通过现有 Bearer token 鉴权。
|
||
- 删除实例运行文件,幂等返回默认配置对象。
|
||
|
||
### GET /api/site.webmanifest
|
||
|
||
- 未自定义:保留现有 192/512 默认图标声明。
|
||
- 已自定义:使用版本化 `/api/instance-icon`,声明 512×512。
|
||
|
||
## 前端契约
|
||
|
||
- head 中 favicon、Apple Touch 与 Manifest 从首屏即指向动态 API,默认服务端兜底避免闪烁。
|
||
- 需要动态更新的图片用 `data-instance-icon` 标识;图标 link 用 `data-instance-icon-link` 标识。
|
||
- `instanceIconUrl(config)` 是唯一 URL 生成入口;浏览器通知和 Service Worker 默认也用 `/api/instance-icon`。
|
||
- 外观设置中新增“实例图标”区:预览、选择图标、恢复默认、状态文字。
|
||
- 客户端拒绝非 PNG/JPEG/WebP;使用 canvas 居中裁剪,不拉伸;上传失败保留旧图标。
|
||
|
||
## 错误语义
|
||
|
||
- 401:未鉴权写操作。
|
||
- 400:空内容、错误 MIME、非法 PNG、非 512×512。
|
||
- 413:超过 4 MiB。
|
||
- 500:原子保存/读取不可恢复错误;前端显示服务端中文消息。
|
||
|
||
## 测试顺序
|
||
|
||
1. 增加聚焦服务集成测试并确认在实现前失败。
|
||
2. 覆盖默认读取、鉴权、非法输入、上传、覆盖版本、恢复默认与 Git 外置路径。
|
||
3. 增加前端静态/DOM 契约测试,覆盖设置 UI 和所有图标消费点。
|
||
4. 实现最小代码使测试通过,再运行总回归。
|