112 lines
3.6 KiB
Markdown
112 lines
3.6 KiB
Markdown
# 在线运行预览设计
|
||
|
||
## 目标
|
||
|
||
为 EasyCode 生成出来的项目提供本机在线运行预览能力,让用户不需要手动下载、解压、配置和启动生成项目,也能快速确认真实运行效果。
|
||
|
||
## 第一期范围
|
||
|
||
第一期运行在当前开发机器上。系统会为每个生成项目创建独立的预览工作目录,初始化专用 MySQL 数据库,把生成出来的 Spring Boot 后端和 Vue 前端作为子进程启动,并把本地预览地址返回给前端页面。
|
||
|
||
这一期主要用于开发阶段快速验证,不作为公开的多租户沙箱。
|
||
|
||
## 用户流程
|
||
|
||
1. 用户完成项目预览生成。
|
||
2. 用户打开项目预览页。
|
||
3. 用户点击 `运行预览`。
|
||
4. 后端把生成源码 zip 导出到本地预览工作目录。
|
||
5. 后端创建专用预览数据库,并导入生成 SQL。
|
||
6. 后端在空闲本地端口启动生成出来的 Spring Boot 服务。
|
||
7. 后端在空闲本地端口启动生成出来的 Vue 前端。
|
||
8. 页面展示后端状态、前端状态、日志和外部预览链接。
|
||
9. 用户可以在页面上停止当前预览会话。
|
||
|
||
## 架构
|
||
|
||
该能力在现有源码预览/下载服务旁边新增一个运行预览服务。
|
||
|
||
- 现有 `IFrontProjectPreviewService` 继续负责生成源码 zip。
|
||
- 新增 `IFrontProjectRunPreviewService` 负责运行预览会话。
|
||
- 第一期会话状态保存在内存中,并按 `userId + projectId` 隔离。
|
||
- 工作目录创建在 `preview-workspaces/project-{projectId}` 下。
|
||
- 生成项目会被解压到该工作目录。
|
||
- 预览数据库命名形如 `preview_{projectId}_{timestamp}`。
|
||
- 子进程通过环境变量注入端口和数据库配置,不直接改写生成文件。
|
||
|
||
## 生成模板要求
|
||
|
||
生成后端模板必须从环境变量读取运行配置:
|
||
|
||
```yaml
|
||
server:
|
||
port: ${SERVER_PORT:8080}
|
||
|
||
spring:
|
||
datasource:
|
||
url: ${DB_URL:jdbc:mysql://localhost:3306/vip?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8}
|
||
username: ${DB_USERNAME:root}
|
||
password: ${DB_PASSWORD:123456}
|
||
```
|
||
|
||
生成 Vue 模板必须从环境变量读取前端端口和后端代理地址:
|
||
|
||
```js
|
||
const port = process.env.PORT || 8081
|
||
const apiBaseUrl = process.env.VUE_APP_API_BASE_URL || 'http://localhost:8080'
|
||
```
|
||
|
||
## 后端接口
|
||
|
||
```text
|
||
POST /front/project/{projectId}/run-preview
|
||
GET /front/project/{projectId}/run-preview
|
||
POST /front/project/{projectId}/run-preview/stop
|
||
```
|
||
|
||
所有接口都使用当前前台用户 ID,并且必须调用项目服务校验项目归属。
|
||
|
||
## 会话状态
|
||
|
||
状态枚举:
|
||
|
||
- `NOT_STARTED`
|
||
- `PREPARING`
|
||
- `STARTING`
|
||
- `RUNNING`
|
||
- `FAILED`
|
||
- `STOPPED`
|
||
|
||
返回字段:
|
||
|
||
- `projectId`
|
||
- `status`
|
||
- `message`
|
||
- `backendUrl`
|
||
- `frontendUrl`
|
||
- `backendPort`
|
||
- `frontendPort`
|
||
- `workspacePath`
|
||
- `databaseName`
|
||
- `logs`
|
||
- `startedAt`
|
||
- `updatedAt`
|
||
|
||
## 安全约束
|
||
|
||
第一期不能把生成项目直接运行在宿主 RuoYi 进程里。生成项目必须作为独立子进程启动,并且可以被单独停止。
|
||
|
||
解压工作目录时必须拒绝逃逸工作目录的 zip 条目。每次启动新会话前可以清理项目工作目录,但清理范围必须限制在配置的预览工作根目录内。
|
||
|
||
数据库初始化会创建新数据库并导入生成 SQL。第一期停止预览时暂不自动删除数据库;等预览生命周期稳定后,可以再补清理策略。
|
||
|
||
## 后续阶段
|
||
|
||
第二期建议迁移到 Docker Compose:
|
||
|
||
- 一个生成后端容器
|
||
- 一个生成前端容器
|
||
- 一个 MySQL 容器
|
||
- 反向代理路径,例如 `/preview/{projectId}/`
|
||
- 基于 TTL 的自动清理
|