Files
yidaima/RuoYi-Vue/docs/superpowers/specs/2026-05-25-online-run-preview-design.md

3.6 KiB
Raw Permalink Blame History

在线运行预览设计

目标

为 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}
  • 子进程通过环境变量注入端口和数据库配置,不直接改写生成文件。

生成模板要求

生成后端模板必须从环境变量读取运行配置:

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 模板必须从环境变量读取前端端口和后端代理地址:

const port = process.env.PORT || 8081
const apiBaseUrl = process.env.VUE_APP_API_BASE_URL || 'http://localhost:8080'

后端接口

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 的自动清理