文档

封面 AI 助手 开发文档

这个项目是什么

封面 AI 助手(cover-ai)是给封面/配图场景用的 AI 生图与修图服务:文字描述出图、上传参考图改图、本地素材库管理。实现上刻意做到极简——零依赖单文件 Node 服务(server.js)+ 一个 HTML 单页(ui.html),Docker 一条命令跑起来,镜像只有几十 MB。它还能被「米图设计」(快图设计/kuaitu-editor)的素材面板直接调用,作为编辑器的 AI 配图后端。

关键设计:AI 接口不在服务端配置。使用者在页面顶部「API 设置」里填自己的接口地址 + API Key + 模型,Key 只存浏览器 localStorage,服务端只做转发(不写日志、不落盘、不进镜像)。

技术栈与架构

层 实现
运行时 Node 20(node:20-alpine 镜像),零 npm 依赖——只用内置 http、fetch,不装 express、不带 node_modules
服务端 server.js 单文件:HTTP 路由 + 静态页 + AI 请求转发 + 素材库文件存储
前端 ui.html 单页(内联样式与脚本),三个页签:AI 生图 / AI 修图 / 素材库
存储 宿主目录挂载 /data:gallery/ 存生成图、gallery.json 存元数据、hub.json 存机器码
授权中心 复用自建 CardAuth 的「免费工具遥测」三接口:版本推送、公告、安装/在线统计

数据流:浏览器把 x-ai-base / x-ai-key / x-ai-model 放在请求头发给本服务 → 服务端转发到使用者配置的 AI 接口(OpenAI 兼容:/images/generations、/chat/completions、/images/edits)→ 生成图写入 /data/gallery/ → 前端从 /img/:name 取图。同源问题的解法:米图设计(8126 端口)通过 /ai-img/* 反代本服务的 /img/*,避免画布 canvas 被跨域污染。

仓库结构

├── server.js      # 零依赖 Node 服务(全部后端逻辑)
├── ui.html        # 单页前端(生图/修图/素材库 + API 设置 + 授权中心 UI)
├── Dockerfile     # node:20-alpine,COPY server.js ui.html,EXPOSE 3000
├── restart.sh     # 生产重建脚本(从 CardAuth 库动态读授权 KEY 注入 env)
├── README.md
└── .gitignore

接口一览

GET    /                  UI(单页)
GET    /api/ai-config     默认接口地址/模型/注册链接(服务端 env 下发)
GET    /api/health        健康检查(含 version 与 hub 状态)
GET    /api/models        拉模型清单        要求头 x-ai-base + x-ai-key
POST   /api/gen           {prompt, size, model} → 生成          要求 x-ai-key
POST   /api/redraw        {image, prompt, size, model} → 重画    要求 x-ai-key
POST   /api/edit          {image, prompt} → 真·修图(images/edits)要求 x-ai-key
GET    /api/gallery       历史图列表(基础功能,不要 Key)
DELETE /api/gallery/:name 删图
GET    /img/:name         取图(供编辑器跨端口反代)
POST   /api/hub/refresh   绕过节流强刷一次授权中心

Key 的处理约定:没带 Key 的 AI 请求一律 403 {needKey:true} 并附注册链接;未配置时 /api/models、/api/gen 等全部拒绝,只有素材库/健康检查可用。

部署与配置

docker pull gitea.88531.cn/jinghui/cover-ai:latest   # 免登录拉已发布镜像
# 或本地构建
docker build -t cover-ai:1.0 .
docker run -d --name cover-ai --restart always --memory 384m -p 8128:3000 \
  -v $PWD:/data \
  -e PUBLIC_BASE=http://<本机地址>:8128 \
  -e AI_BASE=https://ai.88531.cn/v1 \
  -e AI_MODEL=mimo-v2.6-flash \
  -e REGISTER_URL=https://ai.88531.cn/register \
  -e VERSION=1.0.0 \
  -e HUB_PROJECT_ID=<授权中心项目id> \
  -e HUB_API_KEY=<项目 api_key> \
  cover-ai:1.0

环境变量(server.js 中读取的真实键):

键 含义 默认/说明
PORT 监听端口 3000
DATA 数据目录 /data(gallery/、hub.json 落这里,宿主挂载持久化)
PUBLIC_BASE 对外访问地址 用于下发给前端/链接拼接
AI_BASE / AI_MODEL 前端「API 设置」表单的默认接口地址与默认模型 只是默认值,使用者可改
REGISTER_URL 无 Key 时的引导注册链接 —
VERSION 当前版本号(右上角徽章) —
HUB_HOST 授权中心地址(CardAuth) 不配 = unconfigured
HUB_PROJECT_ID / HUB_API_KEY 授权中心项目 id 与 API Key 不配也能跑,只是没有更新提示和公告
HUB_DISABLED 设 1 彻底关掉授权中心上报 —

没有 OMNI_KEY 这类服务端密钥——Key 由每个使用者在页面里自己填。HUB_* 是授权中心对接(版本推送/公告/安装与在线统计),授权中心不可达不影响任何功能(失败开放)。

构建与发布

改了 server.js / ui.html 必须重新 docker build(两个文件是 COPY 进镜像的)。发布镜像到 Gitea 镜像仓库 gitea.88531.cn/jinghui/cover-ai:latest(同步推 1.0 标签)。发新版的顺序:先把新镜像推出去 → 再在 CardAuth 写 ca_project_versions(新版本 is_latest=1)→ 客户端 6 小时内(或重启后)看到提示;公告写 ca_announcements 且 status 必须 = 1(默认 0 是静默隐身)。

二次开发要点

相关链接