Reviewed-on: #20
my-v0
基于 Vue 3 + Vite 的数据大屏低代码编辑器。物料拖入画布,属性面板改 Schema,支持撤销重做、事件联动、数据源绑定与 AI 对话生成,大屏可一键发布为匿名可访问的线上页面。
后端仓库:jiawei/my-v0-server(物料目录、大屏存储与发布、数据源代理、AI Agent、数据文件)
功能特性
- 可视化编辑:物料拖拽入画布,选中、拖拽、缩放、框选多选、标尺、图层排序与右键菜单
- Schema 驱动:页面与物料均为 JSON DSL,属性面板由物料 setters 动态生成表单,内置 Monaco 的 Schema 实时编辑与导入导出
- 撤销重做:模块级历史栈,拖拽 / 输入走批处理,一次操作对应一条历史
- 物料后端下发:物料定义由
GET /api/materials提供,前端按renderer映射本地渲染组件,新增图表无需发版 - 数据能力:静态数据源、API 数据源(经后端代理,规避跨域并隐藏密钥)、数据文件上传与图表绑定、聚合汇总
- 事件系统:物料事件声明、事件配置面板、跨组件联动,事件函数运行在受限沙箱中
- AI 对话:流式对话生成 / 修改大屏,支持上传数据文件分析并据此出图,会话历史按大屏保存
- 大屏管理:列表、封面截图、自动保存(带
revision乐观锁与冲突处理)、预览草稿、发布与分享链接 - 自适应渲染:预览页与线上页按设计稿尺寸等比缩放
技术栈
| 类别 | 选型 |
|---|---|
| 框架 | Vue 3、TypeScript、Pinia、Vue Router |
| 构建 | Vite 8(Rolldown)、unplugin-auto-import、unplugin-vue-components |
| UI / 样式 | Element Plus、Tailwind CSS 4、Iconify |
| 画布 | vue3-moveable(拖拽缩放)、vue3-selecto(框选)、vue3-sketch-ruler(标尺)、vue-draggable-plus(图层排序) |
| 图表 / 表格 / 编辑器 | ECharts、AG Grid、Monaco Editor |
| 其他 | Axios、modern-screenshot(封面)、markstream-vue(流式 Markdown) |
| 质量 | Vitest、ESLint、oxlint、Prettier |
快速开始
环境要求:Node ^22.18.0 || >=24.12.0,包管理器 pnpm。
pnpm install
pnpm dev # http://localhost:3000/my-v0/
开发服务器会把 /api 代理到 http://127.0.0.1:8000,需要先按后端仓库说明启动 my-v0-server。
环境变量
在 .env.development(或对应环境的 .env.*)中配置:
| 变量 | 说明 |
|---|---|
VITE_AUTH_CENTER_URL |
用户中心地址,未登录时跳转至此登录 |
VITE_AUTH_API_URL |
用户中心后端,用于查询当前用户 / 登出(需在其 CORS 中放行本前端 origin) |
常用脚本
pnpm build # vue-tsc 类型检查 + vite build
pnpm type-check # vue-tsc --build
pnpm preview # 预览生产构建
pnpm test # vitest run
pnpm lint # oxlint + eslint(均带 --fix)
pnpm format # prettier --write src/
lint 与 format 会直接改写文件。
路由
站点部署在 /my-v0/ 子路径下(vite.config.ts 的 base)。
| 路径 | 说明 | 登录 |
|---|---|---|
/screens |
大屏管理页(默认入口) | 需要 |
/editor?id= |
编辑器 | 需要 |
/preview?id= |
预览草稿 | 需要 |
/screen?id=<share_id> |
已发布的线上页,匿名可看 | 不需要 |
未登录访问受保护路由时直接跳转用户中心。
项目结构
src/
├── schema/ # 类型定义:MaterialSchema / PageSchema / screen / agent
├── stores/ # editor(页面内容、选中)/ screen(大屏元信息、保存、发布)/ user
├── composables/ # 跨面板能力:useUndoRedo、数据源、文件图表
├── runtime/ # 运行时上下文与事件代码沙箱
├── utils/ # api 请求封装、screenApi、点路径读写、聚合、图表绑定等
├── pages/ # screens(管理页)/ preview / screen(线上页)
├── components/ # ScreenRender、MaterialsGate、MonacoEditor、AggregatePanel 等
├── materials/ # 物料渲染器注册:loadMaterials() + renderer → 组件映射
└── editor/ # 编辑器壳
├── toolbar/ # 工具栏、数据源管理、发布对话框
├── canvas/ # 画布(moveable / selecto / 标尺逻辑在 composables/)
├── composables/ # useAutoSave:防抖自动保存、Ctrl+S、离开前保存
└── panels/ # material / layer / property / chat 四个面板
架构概览
flowchart LR
API[(my-v0-server)]
M[物料面板] -->|拖入| C[画布 / 图层]
P[属性 / AI 面板] -->|改 Schema| E
C --> E[editor store<br/>页面 Schema]
E -->|自动保存| S[screen store]
S <--> API
API -->|物料定义| M
| 模块 | 职责 |
|---|---|
| 物料 | 定义由后端下发,前端按renderer(目前 echarts、text)映射到本地组件;MaterialsGate 等物料加载完再渲染路由 |
| 状态 | editor 管页面内容与选中,screen 管大屏元信息、保存与发布;所有改动经 useUndoRedo 进入统一历史栈 |
| 保存 | 防抖自动保存,带revision 乐观锁,409 时进入冲突处理;预览 / 发布前先保存 |
| 请求 | 统一走utils/api.ts,带 token 并解析 { code, data, msg };数据源取数全部经后端代理 |
| 画布 | 拖拽、缩放、框选、标尺各自封装为 composable,SFC 只负责接线 |
更多约定与踩坑记录见 AGENTS.md;后端接口需求见 docs/backend-api-requirements.md;物料接口快照见 docs/materials。
代码沙箱
事件函数与数据转换代码由用户在编辑器中编写,运行时统一经 runtime/sandbox.ts 执行:
- 作用域隔离:代码包在
with(Proxy)里运行,has恒为true,所有变量查找都被代理拦截,未授权的全局(window、document、localStorage、fetch等)一律返回undefined - 白名单:只放行传入的
scope(事件上下文、节点信息、data),加少量内置对象(Math、Date、JSON、Object、Array等)和定时器 /console/Promise - 入口:
runSandBox执行事件代码(异步);runTransform同步执行数据转换并返回结果
构建与部署
生产构建通过 Rolldown 的 codeSplitting.groups 将 Vue 全家桶、Element Plus、AG Grid、画布交互库拆为独立 chunk;编辑器、ECharts 图表、Monaco 均按需异步加载,加载期间显示 loading 占位,首屏只加载入口与 Vue 相关代码。
主要产物体积(pnpm build):
| Chunk | 未压缩 | gzip | 加载时机 |
|---|---|---|---|
index(入口) |
25.79 kB | 10.55 kB | 首屏 |
vue |
140.68 kB | 53.87 kB | 首屏 |
element-plus |
454.82 kB | 149.11 kB | 首屏 |
screens(管理页) |
16.65 kB | 6.17 kB | 首屏 |
editor |
170.88 kB | 60.46 kB | 进入编辑器 |
canvas |
292.01 kB | 95.25 kB | 进入编辑器 |
ECharts(component) |
1,119.13 kB | 371.60 kB | 首次渲染图表节点 |
ag-grid |
1,166.22 kB | 322.75 kB | 按需,数据文件预览 |
Monacoeditor.api |
3,625.01 kB | 926.35 kB | 首次打开 JSON 编辑器 |
首屏(/screens)JS 合计约 638 kB(gzip 约 218 kB),另有 CSS 约 311 kB(gzip 约 47 kB)。
Docker
项目提供多阶段 Dockerfile(基于 my-v0-base 镜像构建,产物由 nginx 在 3000 端口托管,已配置 SPA 回退与健康检查):
docker build -t my-v0 .
docker run -d -p 3000:3000 my-v0
前端请求路径固定为 /api,生产环境需由外层网关将 /api 转发至后端。