# Opentu 二开指南 本文面向准备自部署、换成自有 API 中转站、继续开发 Opentu 的团队。 ## 项目介绍 Opentu 是一个以画布为中心的 AI 创作平台。它把白板、流程图、思维导图、素材库、任务队列、PPT/Markdown/Mermaid 转换,以及图片、视频、音频、文本等 AI 生成能力整合在同一个工作区里。 核心价值是:用户不需要在多个工具之间复制内容,AI 生成结果、素材、任务状态和知识内容都可以沉淀在画布上继续编辑。 ## 技术栈 - Monorepo:Nx workspace - 包管理:pnpm - Web 应用:React 18 + Vite - UI/画布:Plait、TDesign React、自研 drawnix 包 - 本地存储:localStorage / IndexedDB,API Key 等敏感配置由设置管理器统一处理 - 构建产物:`dist/apps/web` - PWA:`apps/web/vite.sw.config.ts` 构建 Service Worker ## 目录结构 ```text apps/web/ # Web 入口、Vite 配置、public 静态资源、Service Worker packages/drawnix/ # 画布、AI 工具、设置弹窗、供应商路由、任务队列等主逻辑 packages/react-board/ # Plait React 画布适配 packages/react-text/ # 文本渲染组件 packages/utils/ # 通用工具 docs/ # 开发与部署文档 scripts/ # 版本、发布、构建辅助脚本 ``` ## 本地开发 环境要求: ```bash node --version # 需要 Node.js 20+ pnpm --version # 推荐 pnpm 10.x ``` 安装依赖: ```bash NPM_TOKEN=dummy PNPM_HOME=.pnpm-home PNPM_STORE_DIR=.pnpm-store pnpm install --frozen-lockfile ``` 本仓库的 `package.json` 声明了 `pnpm@10.21.0`。如果本机 pnpm 版本不同,pnpm 10 可能会尝试自动切换包管理器版本,导致本地递归安装。已在 `.npmrc` 中加入: ```ini manage-package-manager-versions=false ``` 启动开发服务: ```bash NPM_TOKEN=dummy NX_DAEMON=false pnpm start ``` 默认访问: ```text http://localhost:7200 ``` 如果 Nx daemon 因本地权限无法启动,保留 `NX_DAEMON=false`。如果只想绕过 Nx 直启 Web: ```bash cd apps/web ../../node_modules/.bin/vite serve --host 127.0.0.1 --port 7200 ``` ## 构建与部署 生产构建: ```bash NPM_TOKEN=dummy NX_DAEMON=false pnpm build:web ``` 构建完成后静态文件在: ```text dist/apps/web ``` 部署方式: - 静态托管:把 `dist/apps/web` 部署到 Nginx、Vercel、Netlify、Cloudflare Pages 等。 - Docker:仓库根目录已有 `Dockerfile`,会执行 `pnpm install --frozen-lockfile && pnpm build`,然后用静态网站镜像托管 `dist/apps/web`。 - CDN 混合部署:参考 `docs/NPM_CDN_DEPLOY.md` 和 `docs/CDN_DEPLOYMENT.md`。 ## API 供应商与 Key 绑定 当前默认供应商已对接 `https://truemodel.benchu.cloud/`。用户实际输入的 API Key 不写死在代码里,而是通过设置弹窗保存到浏览器本地配置,并同步给 Service Worker 任务队列使用。 主要配置入口: ```text packages/drawnix/src/utils/settings-manager.ts ``` 关键常量: ```ts TUZI_PROVIDER_DEFAULT_BASE_URL = 'https://truemodel.benchu.cloud/'; TUZI_DEFAULT_PROVIDER_NAME = 'TrueModel'; ``` TrueModel 中转站按 OpenAI 兼容方式接入,Base URL 使用: ```text https://truemodel.benchu.cloud/ ``` 浏览器实际发起请求时会自动走同源代理: ```text /api/truemodel/v1 ``` 这样可以绕开中转站没有开放浏览器 CORS 的问题。用户界面里仍然展示和保存 `https://truemodel.benchu.cloud/`,代理只影响运行时请求地址。 供应商类型选择: ```text providerType: openai-compatible authType: bearer ``` 也就是说用户绑定 key 后,请求会以: ```http Authorization: Bearer 用户填写的key ``` 发送到 TrueModel 中转站。 ## 同源代理与 CORS 浏览器直接请求 `https://truemodel.benchu.cloud/models` 时,如果中转站没有返回 `Access-Control-Allow-Origin`,会被 CORS 拦截。当前项目已内置同源代理: - 本地开发:`apps/web/vite.config.ts` 把 `/api/truemodel/*` 代理到 `https://truemodel.benchu.cloud/*`。 - Vercel:`vercel.json` 已增加 `/api/truemodel/:path*` rewrite。 - Netlify:`netlify.toml` 与 `apps/web/public/_redirects` 已增加 `/api/truemodel/*` proxy。 - 其他自托管:需要在 Nginx、Caddy 或你的后端里配置同样的反向代理。 Nginx 示例: ```nginx location /api/truemodel/ { proxy_pass https://truemodel.benchu.cloud/; proxy_set_header Host truemodel.benchu.cloud; proxy_set_header Authorization $http_authorization; proxy_ssl_server_name on; } ``` ## TrueModel 对接点 默认 Base URL: ```text packages/drawnix/src/utils/settings-manager.ts ``` ```ts export const TUZI_PROVIDER_DEFAULT_BASE_URL = 'https://truemodel.benchu.cloud/'; ``` 注册和领 Key 引导: ```text packages/drawnix/src/components/settings-dialog/settings-dialog.tsx packages/drawnix/src/utils/gemini-api/auth.ts ``` 当前指向: ```text https://truemodel.benchu.cloud ``` 内置 iframe 工具透传接口地址: ```text packages/drawnix/src/tools/built-in-manifests.tsx ``` 当前 Chat-MJ 工具 URL 中包含: ```text https://truemodel.benchu.cloud ``` 后续需要重点检查模型能力。 Opentu 不只是聊天应用,还会调用图片、视频、音频等生成接口。你的 sub2api 至少需要确认: - `/v1/models` 是否可用,影响模型发现。 - `/v1/chat/completions` 是否可用,影响文本和 Agent。 - `/v1/images/generations`、`/v1/images/edits` 是否可用,影响出图和修图。 - 视频、音乐、异步任务接口是否兼容当前供应商协议;不兼容时要在 `packages/drawnix/src/services/provider-routing/` 增加 binding/adapter。 ## 用户绑定方式 用户可以在应用内打开设置,进入供应商配置,填写: ```text API 地址: https://truemodel.benchu.cloud/ API Key: 用户自己的TrueModel key ``` 也可以通过 URL 预填配置: ```text https://你的站点/?settings={"url":"https://truemodel.benchu.cloud/","key":"用户key"} ``` 项目会读取 `settings` 参数,写入本地设置后从地址栏移除参数。生产环境不建议长期通过 URL 传 key,只适合首次导入或内部测试。 ## 后续二开重点 - 品牌替换:`README.md`、`apps/web/public/logo*`、`apps/web/public/manifest.json`、`apps/web/public/home.html`。 - 默认供应商:`settings-manager.ts` 里的默认 profiles 和 presets。 - 设置弹窗文案:`settings-dialog.tsx` 与 `i18n.tsx`。 - 模型路由:`packages/drawnix/src/services/provider-routing/`。 - 具体模型适配:`packages/drawnix/src/services/model-adapters/`、`audio-api-service.ts`、`video-api-service.ts`、`media-api/`。 - 工具箱:`packages/drawnix/src/tools/` 与 `components/toolbox-drawer/`。 - PWA 缓存:`apps/web/vite.sw.config.ts`、`apps/web/public/sw-debug/`。 ## 本次本地验证记录 - 已 clone 到 `/Users/jammy/jstudio/opentu`。 - 已完成依赖安装。 - 已执行 `NPM_TOKEN=dummy NX_DAEMON=false pnpm build:web`,构建成功。 - 已通过直启 Vite 方式运行在 `http://127.0.0.1:7200/`。 - 已验证 `/api/truemodel/v1/models` 代理可转发到 TrueModel 模型接口。