feat: 更新README

This commit is contained in:
2026-10-12 01:09:52 -07:00
parent 158433c487
commit 9547e4abef
3 changed files with 107 additions and 85 deletions
-11
View File
@@ -1,11 +0,0 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "my-v0",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["dev"],
"port": 3000
}
]
}
+1
View File
@@ -40,6 +40,7 @@ __screenshots__/
AGENTS.md
.agents
.claude
skills-lock.json.agents/
docs/
+106 -74
View File
@@ -1,108 +1,140 @@
# my-v0
Vue 3 + Vite 大屏低代码编辑器前端
基于 Vue 3 + Vite 的数据大屏低代码编辑器。物料拖入画布,属性面板改 Schema,支持撤销重做、事件联动、数据源绑定与 AI 对话生成,大屏可一键发布为匿名可访问的线上页面。
> **后端仓库**:[jiawei/my-v0-server](https://git.qflink.xyz/jiawei/my-v0-server)(物料目录、大屏存储与发布、数据源代理、AI Agent、数据文件)
## 功能特性
- **可视化编辑**:物料拖拽入画布,选中、拖拽、缩放、框选多选、标尺、图层排序与右键菜单
- **Schema 驱动**:页面与物料均为 JSON DSL,属性面板由物料 setters 动态生成表单,内置 Monaco 的 Schema 实时编辑与导入导出
- **撤销重做**:模块级历史栈,拖拽 / 输入走批处理,一次操作对应一条历史
- **物料后端下发**:物料定义由 `GET /api/materials` 提供,前端按 `renderer` 映射本地渲染组件,新增图表无需发版
- **数据能力**:静态数据源、API 数据源(经后端代理,规避跨域并隐藏密钥)、数据文件上传与图表绑定、聚合汇总
- **事件系统**:物料事件声明、事件配置面板、跨组件联动,事件函数运行在受限沙箱中
- **AI 对话**:流式对话生成 / 修改大屏,支持上传数据文件分析并据此出图,会话历史按大屏保存
- **大屏管理**:列表、封面截图、自动保存(带 `revision` 乐观锁与冲突处理)、预览草稿、发布与分享链接
- **自适应渲染**:预览页与线上页按设计稿尺寸等比缩放
## 技术栈
- **框架**:Vue 3、Vite、TypeScript、Pinia、Vue Router
- **样式 / UI**:Tailwind CSS、Element Plus、Iconify
- **画布**:vue3-moveable(拖拽缩放)、vue3-selecto(框选)、vue3-sketch-ruler(标尺)、vue-draggable-plus(图层拖拽排序)
- **图表 / 编辑器**:ECharts、Monaco Editor
- **数据**:Axios、Mock.js
| 类别 | 选型 |
| --- | --- |
| 框架 | 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
环境要求:Node `^22.18.0 || >=24.12.0`,包管理器 [pnpm](https://pnpm.io/)。
```sh
pnpm install
pnpm dev
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) |
### 常用脚本
```sh
pnpm build # vue-tsc --build + vite build
pnpm type-check
pnpm preview
pnpm lint # oxlint + eslint(都会 --fix)
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` 会直接改写文件。
生产构建通过 Vite 8 的 Rolldown `codeSplitting.groups` 拆分 Vue、Element Plus 和画布交互依赖;编辑器、ECharts 图表和 Monaco 编辑器均按实际使用时异步加载。异步模块加载期间显示 loading,避免首次打开编辑器、首次拖入图表或打开 JSON 编辑器时出现空白区域
## 路由
### 首屏效果
站点部署在 `/my-v0/` 子路径下(`vite.config.ts` 的 `base`)。
- 页面加载时间:实测约从 `6 s` 降至 `1 s`
- 首屏入口 JS:从 `6,585.31 kB`(gzip `1,751.85 kB`)降至 `165.12 kB`(gzip `60.45 kB`)
- 入口 JS 未压缩体积减少约 `97.5%`,gzip 体积减少约 `96.5%`
| 路径 | 说明 | 登录 |
| --- | --- | --- |
| `/screens` | 大屏管理页(默认入口) | 需要 |
| `/editor?id=` | 编辑器 | 需要 |
| `/preview?id=` | 预览草稿 | 需要 |
| `/screen?id=<share_id>` | 已发布的线上页,匿名可看 | 不需要 |
### 生产构建产物
未登录访问受保护路由时直接跳转用户中心。
以下数据来自 `pnpm build`:
## 项目结构
| Chunk | 未压缩体积 | gzip 体积 | 加载时机 |
| --------------------------- | ----------: | --------: | -------------------- |
| 入口`index` JS | 165.12 kB | 60.45 kB | 首屏 |
| `vue` | 96.61 kB | 37.58 kB | 首屏 |
| `element-plus` JS | 294.87 kB | 99.25 kB | 编辑器加载后 |
| `canvas` JS | 292.04 kB | 95.24 kB | 编辑器加载后 |
| 编辑器业务 JS | 79.36 kB | 25.17 kB | 编辑器加载后 |
| 图表`component` / ECharts | 1,166.65 kB | 389.20 kB | 首次渲染图表节点 |
| `MonacoEditor` JS | 58.71 kB | 15.63 kB | 首次打开 JSON 编辑器 |
| Monaco`editor.api` JS | 3,625.00 kB | 926.34 kB | 首次打开 JSON 编辑器 |
```
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 四个面板
```
Monaco 的 CSS 为 `308.18 kB`(gzip `101.96 kB`),同样延迟到首次打开 JSON 编辑器后加载
## 架构要点
Element Plus CSS 为 `116.01 kB`(gzip `16.05 kB`),随编辑器模块加载
**物料**。`MaterialDefinition`(目录项 + setters + 默认 Schema)由后端下发,`MaterialSchema` 是画布上的实例(多一个 `id`)。`App.vue` 中的 `MaterialsGate` 等待 `loadMaterials()` 完成后才渲染路由。新增渲染器只需在 `materials/` 下加组件目录,并在 `rendererMap` 中映射;目前支持 `echarts` 与 `text`。
## 项目目标
**状态与历史**。修改 Schema 一律通过 `useUndoRedo()` 的 `applyChange` / `startBatch` / `commitBatch`,面板与工具栏共用同一历史栈。切换大屏使用 `editor.loadPage()`(清空选中与历史)。
### 一、编辑器核心架构
**保存**。`useAutoSave` 深度监听页面并防抖保存,请求携带 `revision`,后端返回 409 时弹出冲突处理。预览与发布前先 `await screen.save()` 以保证读到最新草稿。
- ~~项目初始化与基础布局~~
- ~~工具栏实现~~
- ~~物料面板(可扩展架构)~~
- ~~图层面板~~
- ~~插件化注册机制~~
- ~~物料 DSL 设计~~
- ~~拖拽渲染流程~~
- ~~节点拖动与缩放~~
- ~~框选与多选操作~~
- ~~画布标尺接入~~
- ~~图层排序与画布层级联动~~
- ~~页面 DSL 设计与落地~~
- ~~属性面板~~
- ~~右键菜单~~
- ~~组合式函数拆分~~
- ~~撤销重做基础能力~~
- ~~批处理与历史记录管理~~
- ~~ECharts 图表物料接入~~
**请求与数据源**。所有请求经 `utils/api.ts` 的 `requestJson`,统一带 token、解析 `{ code, data, msg }` 信封,非 0 抛 `ApiError`。数据源取数一律走后端代理:编辑 / 预览走 `/api/datasource/fetch`,线上页按 `shareId` 走匿名接口。
### 二、代码与数据能力
**画布**。三套尺寸互相独立:`viewportSize`(标尺视口)、`rulerCanvasSize`(冻结工作区)、`canvasStyle`(白底,跟随 store)。节点 DOM 带 `data-node-id` 与 `canvas-node`,封面截图依赖 `[data-canvas-stage]`。
- ~~网页代码编辑器接入~~
- ~~页面 Schema 导入导出与实时编辑~~
- ~~静态数据源~~
- ~~API 数据源~~
- ~~数据源管理界面~~
- ~~API 数据源调试~~
- ~~加载、刷新与请求复用~~
更多约定与踩坑记录见 [AGENTS.md](AGENTS.md);后端接口需求见 [docs/backend-api-requirements.md](docs/backend-api-requirements.md);物料接口快照见 [docs/materials](docs/materials/README.md)。
### 三、运行时与预览能力
## 构建与部署
- ~~大屏自适应预览~~
- ~~页面持久化与独立访问~~
- ~~运行时上下文~~
生产构建通过 Rolldown 的 `codeSplitting.groups` 将 Vue 全家桶、Element Plus、AG Grid、画布交互库拆为独立 chunk;编辑器、ECharts 图表、Monaco 均按需异步加载,加载期间显示 loading 占位。
### 四、事件系统
| 指标 | 优化前 | 优化后 |
| --- | ---: | ---: |
| 首屏入口 JS(未压缩) | 6,585.31 kB | 165.12 kB |
| 首屏入口 JS(gzip) | 1,751.85 kB | 60.45 kB |
| 页面加载时间(实测) | ≈ 6 s | ≈ 1 s |
- ~~事件调度机制~~
- ~~事件配置面板~~
- ~~跨组件事件联动~~
- ~~事件函数编辑体验优化~~
- ~~代码沙箱~~
- ~~物料可触发事件声明~~
- ......
主要 chunk 与加载时机:
### 五、后端规划
| Chunk | 未压缩 | gzip | 加载时机 |
| --- | ---: | ---: | --- |
| `index` | 165.12 kB | 60.45 kB | 首屏 |
| `vue` | 96.61 kB | 37.58 kB | 首屏 |
| `element-plus` | 294.87 kB | 99.25 kB | 进入编辑器 |
| `canvas` | 292.04 kB | 95.24 kB | 进入编辑器 |
| 图表 / ECharts | 1,166.65 kB | 389.20 kB | 首次渲染图表节点 |
| Monaco `editor.api` | 3,625.00 kB | 926.34 kB | 首次打开 JSON 编辑器 |
### Docker
项目提供多阶段 `Dockerfile`(基于 `my-v0-base` 镜像构建,产物由 nginx 在 3000 端口托管,已配置 SPA 回退与健康检查):
```sh
docker build -t my-v0 .
docker run -d -p 3000:3000 my-v0
```
前端请求路径固定为 `/api`,生产环境需由外层网关将 `/api` 转发至后端。