通过自然语言与 AI 交互,支持流式 SSE 输出和多模型智能路由(DeepSeek / 通义千问)。
AI 自动生成完整代码,支持三种模式:
| 模式 | 说明 |
|---|---|
| 单文件 HTML | 快速生成独立 HTML 页面 |
| 多文件项目 | 生成包含 HTML/CSS/JS 的多文件结构 |
| Vue 项目 | 工作流编排生成完整 Vue 项目,Docker 隔离构建,构建产物做完整性校验 |
生成的代码打包为 ZIP 下载,或一键部署到内置服务器。
注册登录、Redis 会话管理、角色权限控制(用户/管理员)、敏感词过滤;精选应用公开可见(未登录可浏览),对话记录、Vue 源码、编辑、下载与部署仅创建者和管理员。AI 生成代码在独立预览域运行,通过短时签名 token 鉴权(HMAC + 15 分钟过期),不会获得主站同源权限。Vue 编辑模式使用受控消息桥与预览页通信;预览 CSP 默认仅允许同源联网和图片、字体等必要资源,外部 API 必须显式配置白名单。
- Redis 旁路缓存
- Redisson 分布式限流
- AOP 接口限流与权限校验
| 依赖 | 版本 | 说明 |
|---|---|---|
| JDK | 21+ | 后端运行环境(构建链路用到虚拟线程) |
| Maven | 3.9+ | 后端构建(无 mvnw wrapper,使用系统 Maven) |
| Node.js | 20+ | 前端构建与开发 |
| MySQL | 8+ | 数据存储(执行 sql/create.sql 建库建表) |
| Redis | 7+ | 会话 / 缓存 / 分布式锁 / 限流(可无密码) |
| Docker | 20+ | 仅 Vue 项目生成需要(隔离构建容器) |
# 创建 fish_ai_code 库与 user / app / chat_history 三张表
mysql -u root -p < sql/create.sql后端通过 application-local.yaml 读取本地配置,但该文件已被 .gitignore 忽略(避免密钥入库)。新环境需要从模板复制:
# 复制模板为本地配置(模板含所有配置项与占位符说明)
cp src/main/resources/application-local.yaml.example src/main/resources/application-local.yaml
# 编辑 application-local.yaml,填入真实值:
# - spring.datasource.password MySQL 密码
# - langchain4j.open-ai.*.api-key DeepSeek API Key(4 处,可填同一把)
# - (可选)pexels.api-key / undraw.token 图片搜索,不填则跳过图片收集
# - app.preview-token-secret 预览签名密钥(模板已带本地开发默认值,生产用环境变量覆盖)
# - app.preview-origin / app.preview-frame-ancestor 预览域与主站地址(本地模板已配置)
# - app.preview-connect-src 生成应用可访问的 API 白名单(默认仅预览域自身)DeepSeek API Key 在 https://platform.deepseek.com 申请。 如果不用图片搜索功能,Pexels / Undraw 配置可留空,不影响核心生成流程。
Vue 项目的构建在隔离的 Docker 容器中执行(--network none 离线构建),需要先构建一次基础镜像(预装依赖缓存):
docker build -t fish-ai-code-vue-builder:20 -f docker/vue-builder/Dockerfile docker/vue-builder只生成 HTML / 多文件模式可以跳过这步;用 Vue 模式前必须构建镜像,否则报"镜像不存在"。
mvn spring-boot:run后端默认监听 http://localhost:8911/api(context-path=/api)。
cd fish-ai-code-frontend
npm install
npm run dev前端默认 http://localhost:3000,Vite 已配置 /api 代理到后端 8911,开发期无需处理跨域。
后端只允许配置中的 Origin 携带 Cookie 跨域访问(CORS_ALLOWED_ORIGINS,逗号分隔)。注意:CORS_ALLOWED_ORIGINS 必须同时包含主站与预览域——预览 iframe 内的 Vue 静态资源(<script type="module" crossorigin>)是带 Origin 头的跨域请求,若预览域不在白名单,后端会对这些资源返回 403,表现为预览只剩 CSS 背景(纯色页面)、JS 组件全部不渲染。本地开发默认已同时包含 http://localhost:3000 与 http://preview.localhost:3000;Docker 部署未设置 CORS_ALLOWED_ORIGINS 时默认回退 APP_ORIGIN(主站),配置了独立预览域时必须显式把预览域加进 CORS_ALLOWED_ORIGINS。
本地预览使用 http://preview.localhost:3000。*.localhost 会自动解析到本机,Vite 也会响应该地址;不要把预览域改为主站地址,否则不可信代码将失去独立域隔离。
| 地址 | 用途 |
|---|---|
http://localhost:3000 |
前端页面 |
http://localhost:8911/api/doc.html |
接口文档(Knife4j,可在线调试) |
mvn test当前集成测试会连接 application-test.yaml 配置的本机 MySQL 和 Redis,运行前需确保两者已启动并已执行建表脚本。纯前端构建可在 fish-ai-code-frontend 目录执行 npm run build。
整个项目(前端 + 后端 + MySQL + Redis)已打包为 Docker Compose 编排,服务器只需装 Docker,3 步即可上线:
# 1. 复制环境变量模板并填入真实密钥
cp .env.example .env
# 必填:DEEPSEEK_API_KEY(https://platform.deepseek.com 申请)
# PREVIEW_TOKEN_SECRET(预览静态资源签名密钥,用 `openssl rand -base64 32` 生成)
# PREVIEW_ORIGIN(独立预览域,例如 https://preview.example.com)
# APP_ORIGIN(主站域,例如 https://app.example.com)
# 可选:DB_PASSWORD / REDIS_PASSWORD / PEXELS_API_KEY / UNDRAW_TOKEN / 端口等
# 2. 构建 Vue 隔离构建镜像(仅使用 Vue 项目生成需要,HTML/多文件模式可跳过)
docker build -t fish-ai-code-vue-builder:20 -f docker/vue-builder/Dockerfile docker/vue-builder
# 3. 一键启动(首次会自动拉取镜像、构建前后端、初始化数据库)
docker compose up -d --build启动后访问 http://<服务器IP>:80(前端)、http://<服务器IP>/api/doc.html(接口文档)。
Compose 包含的服务:
| 服务 | 镜像 | 说明 |
|---|---|---|
frontend |
自定义(node 构建 → nginx) | 托管前端静态资源,反代 /api 到后端(SSE 已关闭缓冲) |
backend |
自定义(maven 构建 → JRE) | Spring Boot,配置全部环境变量化(application-docker.yaml) |
mysql |
mysql:8.0 | 首次启动自动执行 sql/create.sql 建库建表,数据持久化到 volume |
redis |
redis:7-alpine | 会话 / 缓存 / 分布式锁 / 限流 |
常用命令:
docker compose ps # 查看状态
docker compose logs -f backend # 查看后端日志
docker compose down # 停止(保留数据)
docker compose down -v # 停止并清空数据库数据(慎用)
docker compose up -d # 重新启动(不重新构建)Vue 构建说明:后端容器通过挂载
/var/run/docker.sock调用宿主机 Docker 运行隔离构建(--network none、只读、无内核能力),构建镜像需先在宿主机执行第 2 步的docker build。由于 docker.sock 模式下--mount的 bind 源由宿主机 daemon 按宿主机文件系统解析,compose 已通过CODE_OUTPUT_HOST_DIR(即${PWD}/data/code_output)把宿主机代码输出根目录传给后端(vue-build.host-code-output-dir),后端会把构建命令的挂载源映射为宿主机绝对路径。 数据目录:生成的代码在data/code_output/,部署产物在data/code_deploy/(已加入 .gitignore)。部署产物由 nginx 通过http://<主机>/deploy/{deployKey}提供访问(后端返回的部署链接即此格式)。 预览域配置:为PREVIEW_ORIGIN配置独立域名并解析到与主站相同的入口,例如主站为https://app.example.com、预览域为https://preview.example.com。APP_ORIGIN必须填写主站完整 Origin,供 CSP 的frame-ancestors精确允许嵌入;不要填写通配符。同时必须把预览域加进CORS_ALLOWED_ORIGINS(与主站逗号分隔,如CORS_ALLOWED_ORIGINS=https://app.example.com,https://preview.example.com),否则预览 iframe 内的 Vue 静态资源跨域请求会被 403 拒绝(见"常见问题")。若生成应用需要访问第三方 API,在PREVIEW_CONNECT_SRC中填写精确地址,例如'self' https://api.example.com,多个地址以空格分隔。默认仅允许预览域自身联网。
# 打包(跳过测试)→ 生成 target/fish-ai-code-0.0.1-SNAPSHOT.jar
mvn clean package -DskipTests
# 启动(jar 包方式,与 mvn spring-boot:run 同配置)
java -jar target/fish-ai-code-0.0.1-SNAPSHOT.jarcd fish-ai-code-frontend
npm install
npm run build # 产物在 dist/前端产物建议用 Nginx 托管,并将 /api 反向代理到后端:
server {
listen 80;
root /path/to/fish-ai-code-frontend/dist;
index index.html;
# 前端路由(React Router)
location / {
try_files $uri $uri/ /index.html;
}
# 后端 API 反向代理
location /api/ {
proxy_pass http://127.0.0.1:8911;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}application-local.yaml的server.address: 0.0.0.0允许外部访问,请确保防火墙 / 安全组只开放必要端口PREVIEW_TOKEN_SECRET必须使用强随机值;预览 token 默认有效 15 分钟,前端会在约 12 分钟时自动续签并刷新预览 iframe,避免 Vue 懒加载资源因签名过期而失败- HTTPS 部署时设置
SESSION_COOKIE_SECURE=true,使登录 Cookie 只通过 HTTPS 发送;本地 HTTP 调试保持默认false - AI 流式生成请求默认超时 600 秒(环境变量
AI_STREAM_REQUEST_TIMEOUT,Docker profile 默认 600s)。Vue 模式文件多、耗时长,一般够用;如遇断流/“生成失败”,可相应调大该值 - 代码生成目录
tmp/code_output/与部署目录tmp/code_deploy/在启动目录下生成,建议给足磁盘空间 - 部署访问域名可在
application.yaml的app.deploy.host配置(默认http://localhost),Docker 方式在.env里配APP_DEPLOY_HOST;部署链接格式为{host}/deploy/{deployKey},由 nginx 的location /deploy/服务
| 问题 | 原因与解决 |
|---|---|
启动报 Could not resolve placeholder 'spring.data.redis.password' |
application-local.yaml 缺失或未复制模板;按第二步复制并配置 |
| Vue 模式报"镜像不存在" | 未执行 docker build -t fish-ai-code-vue-builder:20 ...(Docker 方式见生产部署第 2 步) |
docker compose up 报 DEEPSEEK_API_KEY is missing |
未复制 .env 或未填 key;cp .env.example .env 后填写 |
docker compose up 报 502 / backend 未就绪 |
后端启动需约 10 秒(等 MySQL/Redis 健康检查),稍等重试;docker compose logs -f backend 查看 |
| 服务器访问不了前端 | 确认 FRONTEND_PORT(默认 80)已在防火墙 / 安全组放行 |
| 预览页空白或浏览器提示拒绝嵌入 | 检查 PREVIEW_ORIGIN 是否为独立预览域、DNS / HTTPS 是否指向入口,以及 APP_ORIGIN 是否为主站完整 Origin |
预览只剩纯色背景、JS 组件不渲染(控制台报 403 Forbidden,资源 URL 形如 /api/static/.../assets/index-xxx.js) |
预览域不在 CORS 白名单:<script type="module" crossorigin> 跨域加载带 Origin 头,后端对不在 CORS_ALLOWED_ORIGINS 的 Origin 返回 403。把预览域加入 CORS_ALLOWED_ORIGINS(本地开发须包含 http://preview.localhost:3000,生产须与主站一起显式配置)后重启后端 |
| 生成应用请求 API 失败 | 默认 CSP 只允许同源联网;在 PREVIEW_CONNECT_SRC 中加入精确 API 地址后重启后端 |
| 生成时提示"一分钟内请求次数过多" | 接口限流(默认 10 次/分钟),稍等再试或调大 @RateLimit |
| 生成的页面没有图片 | Pexels / Undraw key 未配置或无效,图片收集失败不影响代码生成 |
| 端口被占用 | 传统方式后端 8911 / 前端 3000;Docker 方式在 .env 中改 BACKEND_PORT / FRONTEND_PORT |
| Vue 生成中途断开 / 报“生成失败” | 多为 AI 流式请求超时。默认已是 600 秒(AI_STREAM_REQUEST_TIMEOUT),如模型输出偏慢可在环境变量中调大该值后重启后端 |
后端
- Java 21 + Spring Boot 3.5 — 核心框架
- MyBatis-Flex — ORM
- MySQL 8 — 持久化存储
- LangChain4j — AI 模型统一接入(流式、多模型路由)
- Redis — 会话管理、旁路缓存
- Redisson — 分布式限流
- Knife4j — 接口文档
前端
- React 19 + TypeScript + Vite
- Ant Design 6 — UI 组件库
- Zustand — 状态管理
- React Router 8 — 路由管理
- React Markdown + React Syntax Highlighter — 代码渲染与高亮
AI 模型
- DeepSeek — 默认对话与推理模型
- 阿里云百炼(通义千问) — 智能路由分类任务


