Files

3.1 KiB
Raw Permalink Blame History

实例自定义图标技术设计

数据流

本地 PNG/JPEG/WebP
  → 浏览器解码并居中裁剪为 512×512 PNG
  → POST /api/instance-iconBearer二进制≤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_DIRAPP_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=falseversion=defaultURL 仍指向统一读取接口。

GET /api/instance-icon

  • 自定义存在且有效:返回该 PNG。
  • 未配置或运行文件失效:返回 public/icon-192.png
  • Content-Type: image/pngX-Content-Type-Options: nosniff
  • 使用 ETag/no-cache版本化 URL 负责同页缓存刷新。

POST /api/instance-icon

  • 必须通过现有 Bearer token 鉴权。
  • Content-Type: image/pngbody 非空且不超过 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. 实现最小代码使测试通过,再运行总回归。