3.1 KiB
3.1 KiB
实例自定义图标技术设计
数据流
本地 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
公开返回:
{
"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:原子保存/读取不可恢复错误;前端显示服务端中文消息。
测试顺序
- 增加聚焦服务集成测试并确认在实现前失败。
- 覆盖默认读取、鉴权、非法输入、上传、覆盖版本、恢复默认与 Git 外置路径。
- 增加前端静态/DOM 契约测试,覆盖设置 UI 和所有图标消费点。
- 实现最小代码使测试通过,再运行总回归。