项目:运营搭建平台(vue3-course) | 版本:v1.0 | 生成日期:2026-10-05 | 依据:源码分析
本仓库的正式名称是「运营搭建平台」(根 README.md 第 1 行;package.json 的 name 字段为空字符串 ?,仓库目录名 vue3-course 是历史遗留的课程仓命名,不改变项目实质——它不是教学示例,而是一个功能完整的全栈低代码平台,这一点以 packages/ 的实际内容为准)。
平台的定位是:让运营/编辑人员在不写代码(或少写代码)的前提下,通过可视化编辑器搭建运营页面与数据看板,经受控的发布流程交付给公网访客访问。一句话概括其产品闭环:
登录管理台 → 新建/编辑页面或看板(可视化拖拽)→ 绑定数据源 → test / pre / prod 三阶段发布 → 访客按 UUID 链接访问(公开或令牌)→ 访问统计回流。
平台由两条并列的搭建线组成,共享账号、权限、数据源与发布语义:
packages/materials/ 下的 material-banner-slides、material-product-list),经构建发布到 mock CDN,编辑器通过 requirejs 以 AMD 方式运行时加载物料并直渲染(packages/work-front/src/pages/manage/modules/page-editor.tsx 的 initAMDEnv)。发布时服务端用 Vite 真实构建出 index.esm.js / bundle.js / bundle.css 产物(packages/work-server/src/service/page-static.ts)。packages/charts/src/meta/ 下 nativeMetas.ts + elementPlusMetas.ts,共 57 种——elementPlusMetas 的 53 个 Element Plus 组件 + nativeMetas 的 4 个原生元素),编辑器内以 iframe 画布 + postMessage 协议渲染(packages/work-front/src/pages/dashboard-canvas/)。发布是纯 JSON 快照落库(dashboard_info_test/_pre/_prod 三张表),不需要构建产物。目标用户分三类,与 RBAC 三种种子角色一一对应(packages/init-database/src/sql/insert_role.sql 与 insert_role_permission_*.sql):
portal-server(6001 端口)按链接访问已发布的页面/看板,其权限边界由发布白名单与访问方式(public/token)决定。从演进脉络看,仓库带有明显的"课程项目长成产品"的层积痕迹:tiny-engine-study/ 存放 OpenTiny TinyEngine 2.11.0 的完整源码副本(仅作借鉴,不参与构建),配套的 tiny-engine-borrow-plan.md 是一份按现状重排的借鉴落地清单,其中记录了几个关键里程碑——产品主线收敛为"页面搭建 + 发布"(独立的组件库包 @my/components 已删除;随后 2026-09-25 的归档决策进一步明确主线聚焦看板线、旧页面线冻结:页面线停止新功能投入只修阻断性缺陷、已发布页面永久兼容,docs/plans/page-line-freeze-2026-09.md,《16-决策记录ADR》ADR-010)、前端构建从 Webpack 迁移到 Vite、管理端表单全面 schema 化(work-front/src/ui/ 的 DynamicForm 适配层)。该计划还明确了一个重要的架构判断:两条搭建线"协议先统一,渲染方式暂不合并"——先让页面线与看板线共用物料属性协议与配置器注册表,画布层是否统一留待协议统一后再评估。这份清单是理解"代码为什么是现在这个形状"的最佳导读,细节层面的设计决策见《01-系统架构》。
| 功能域 | 功能点 | 关键入口/实现 |
|---|---|---|
| 账号与认证 | 注册 / 登录 / 登出 / 改密 / 在线状态查询 / 滑动续期 | packages/work-server/src/controller/user.ts |
| 权限(RBAC) | 角色-权限码模型,requirePermission(code) 路由级拦截 | packages/work-server/src/middleware/rbac.ts、packages/work-server/src/service/rbac.ts |
| 看板编辑器 | 文档流/绝对定位双布局、拖拽、多选、撤销重做、区块、大纲、就地文本编辑、快捷键 | packages/work-front/src/pages/dashboard-editor/ |
| 看板状态与脚本 | 页面状态变量(pageState)+ 页面方法(pageMethods,AsyncFunction 编译)+ 组件显隐条件 + 事件绑定 | packages/shared/src/runtime.ts、packages/shared/src/schema/index.ts |
| AI 辅助搭建 | AI 对话生成/修改组件补丁(SSE 流式),服务端持有密钥,按用户限流配额 | packages/work-server/src/controller/ai.ts、packages/work-front/src/pages/dashboard-editor/composables/ai-patch.ts |
| 出码 | 看板 schema → 可独立运行的 Vue3 + Vite 工程 zip | packages/dashboard-codegen/index.ts、packages/work-server/src/controller/codegen.ts |
| 模板中心 | 存为模板 / 从模板新建 / 分类重命名 / 取消模板 / SVG 线框缩略图,页面线与看板线各一套 | packages/work-server/src/service/dashboard-templates.ts、page-templates.ts、packages/work-server/src/util/thumbnail.ts |
| 数据源 | MySQL / PostgreSQL / API / CSV / 静态 五类;mock 数据;测试连接;CSV 上传 | packages/work-server/src/service/data-query.ts、util/data-query/* |
| 数据库连接 | MySQL/PG 连接管理(口令 AES-256-GCM 加密落库),数据源按 connectionId 引用 | packages/work-server/src/service/db-connection.ts、packages/work-server/src/util/secret-box.ts |
| 三阶段发布 | test → pre → prod,版本自增、发布快照、可下线(unpublish)、发布状态查询 | packages/work-server/src/service/dashboard-stage.ts、page-stage.ts |
| 访问控制 | 资产归属(owner_uuid 认领)+ 可见范围(private/department/public)+ 访问方式(public/token 令牌门) | packages/work-server/src/util/visibility.ts、packages/portal-server/src/util/access-gate.ts |
| 门户渲染 | /d/:uuid 看板、/p/:uuid 页面、demo 页;iframe 嵌入代码生成 | packages/portal-server/src/controller/dashboard.ts、page.ts |
| 访问统计 | 服务端 PV 埋点(30 分钟去重)、按天统计查询 | packages/portal-server/src/util/visit-track.ts、packages/work-server/src/service/visit-stats.ts |
| 物料管理 | 物料 CRUD、版本快照、快照回滚、物料预览 | packages/work-server/src/controller/material.ts、work-front/src/pages/manage/views/material-* |
| 页面搭建 | AMD 物料拖拽编辑、行/填充/数据表单、发布流程视图 | packages/work-front/src/pages/manage/modules/page-editor.tsx、packages/work-front/src/pages/manage/views/page-flow.vue |
| 历史与回滚 | 看板快照(保存自动 + 手动 + 发布时)、快照详情、diff、回滚;页面快照同构 | packages/work-server/src/service/dashboard-snapshot.ts、page-snapshot.ts |
| 回收站 | 看板软删/回收站/恢复(恢复不动发布状态) | packages/work-server/src/controller/dashboard.ts |
| 日志 | 前端日志上报(匿名限流)、日志查询、页面轨迹 | packages/work-server/src/controller/log-info.ts、packages/portal-server/src/controller/log.ts |
逐项展开前先点破这张表的骨架:两条搭建线在实现上刻意差异化,在平台能力上完全同构。差异在"物料与渲染"——页面线的物料是独立 npm 包、经构建发布到 CDN、运行时 AMD 加载直渲染,适合"一块区域一个强交互组件"的活动页形态;看板线的物料是本地组件元表、发布产物是纯 JSON 快照,适合"多组件 + 数据绑定"的看板形态。同构在"平台件"——账号与 RBAC、快照与回滚、模板中心、test/pre/prod 三阶段发布语义、可见范围与令牌门、PV 统计,两线各有一套但行为一致,这正是 borrow-plan 里"协议先统一"的落点。理解了这个骨架,再按行读表就不会迷失在细节里:凡是"数据怎么进来"(数据源/连接/AI/出码)都是为编辑器服务的;凡是"草稿怎么安全地变成线上资产"(快照/模板/发布/回收站)都围绕发布语义展开。各域的接口契约与页面交互分别见《03-接口设计》《02-页面设计》,端到端流程见《05-核心流程》。
| 层 | 技术 | 版本 | 选型理由(依据源码注释与依赖声明) |
|---|---|---|---|
| 前端框架 | Vue | ^3.5.42(workspace overrides 锁定) | 平台以 Vue3 生态为底座;pnpm-workspace.yaml 用 overrides 强制全仓单版本,避免多实例 |
| 前端路由 | vue-router | 4 | 管理端 SPA(base /page),createWebHistory + 全局登录守卫(packages/work-front/src/router.ts) |
| UI 组件库 | Element Plus | ^2.14.5 | 管理台与编辑器 UI;同时作为看板物料来源(elementPlusMetas.ts),charts 以 peerDependencies 引用 |
| 图表 | ECharts + vue-echarts | ^5.5.1 / ^6.7.3 | 看板图表运行时;@my/charts 封装 Line/Bar/Pie/Area/MetricCard/DataTable |
| 表格 | vxe-table | ^4.7.0 | 数据表格物料(DataTable)大数据量场景 |
| 代码编辑器 | CodeMirror 6 | ^6.0.2 | 编辑器内 Schema / 页面 JS 面板(packages/work-front/src/pages/dashboard-editor/modules/designer-ui/CodeEditor.vue) |
| 栅格拖拽 | grid-layout-plus | ^1.0.5 | 看板画布 24 列栅格布局的拖拽/缩放底层 |
| 后端框架 | Koa | ^3.2.1 | 两个服务端(work-server/portal-server)统一用 Koa + @koa/router ^15.7 |
| 数据库驱动 | mysql2 / pg | ^3.6.0 / ^8.22.0 | mysql2 连平台主库与 MySQL 数据源;pg 仅作为 PostgreSQL 数据源查询驱动 |
| 认证 | jsonwebtoken + bcryptjs | ^9.0.0 / ^3.0.3 | JWT 签名 HttpOnly cookie 登录态;bcrypt 逐用户盐口令哈希(存量 HMAC 透明迁移) |
| 压缩/打包 | jszip | ^3.10.1 | 出码功能生成工程 zip |
| 构建 | Vite + vite-node + Rollup + ts-morph | ^7.3.6 等 | 前端产物、服务端 CJS 打包、共享包 ESM/CJS 双格式、dts 生成(scripts/build-*.ts) |
| 语言 | TypeScript | ^5.9.3 | 全仓 TS;vue-tsc 管 web 侧类型 |
| 测试 | Vitest | ^4.1.11 | test.projects 分 server(node)/web(jsdom) 两线;coverage 用 @vitest/coverage-v8 |
| CI | GitHub Actions + MySQL 8.4 service | — | .github/workflows/ci.yml:lint → build → db:init → test → typecheck 五道门禁 |
| 包管理 | pnpm | 10.34.5(packageManager 字段锁定) | workspace 协议(workspace:*)连接各包;publicHoistPattern: '*' 保证 vite-node/ts-node 直跑 |
| 运行时 | Node.js 22 | — | CI setup-node@4 指定 22;@tsconfig/node22 基线 |
vue3-course/
├─ package.json # 根脚本中枢:build/dev/db:init/test/start 全部经 vite-node 调 scripts/*.ts
├─ pnpm-workspace.yaml # workspace 清单 + vue 单版本 override + 全量 hoist
├─ vitest.config.js # 测试分线:server(node) / web(jsdom) 两个 project,maxWorkers=2
├─ scripts/ # 构建与开发脚本(vite-node 执行的 TS 脚本,非 shell)
│ ├─ build-module.ts # @my/business + @my/shared → dist(rollup,ESM+CJS)
│ ├─ build-work-front.ts # work-front → dist/admin/** 与 dist/visitor/** 两个产物桶
│ ├─ build-work-server.ts # work-server 打 CJS 包并拷 admin 桶静态产物
│ ├─ build-portal-server.ts # portal-server 打 CJS 包并拷 visitor 桶静态产物
│ ├─ build-materials.ts # 物料包 → mock CDN(带版本号目录)
│ └─ migrate-secrets.ts # db:encrypt-secrets / db:decrypt-secrets 凭据迁移
├─ packages/
│ ├─ shared/ (@my/shared) # 看板 Schema 类型、物料协议、页面方法运行时——前后端与渲染端共用的"宪法"
│ ├─ charts/ (@my/charts) # 图表/EP 渲染运行时 + 物料元表(nativeMetas/elementPlusMetas)
│ ├─ business/ (@my/business) # 业务基础件:Drag 拖拽引擎、home 组件、主题;产出 ESM/CJS/CSS
│ ├─ dashboard-codegen/ # 看板出码器:schema → 独立 Vue3+Vite 工程源码(被 work-server 消费)
│ ├─ work-front/ (@my/work-front) # 唯一前端包:管理台+编辑器(admin 桶)与访客渲染器(visitor 桶)
│ ├─ work-server/ (@my/work-server) # 主后端 :8001——登录态、RBAC、看板/页面/物料/数据源/发布/AI/出码
│ ├─ portal-server/(@my/portal-server) # 访客门户 :6001——/d/:uuid、/p/:uuid、令牌门、白名单取数转发
│ ├─ server-kit/ (@my/server-kit) # 两服务端共用基建:连接池/事务、安全响应头、cookie/CSRF、限流、CDN 镜像
│ ├─ init-database/(@my/init-database) # db:init:建库建表(40 个 SQL 文件)+ 角色/权限/种子账号/示例数据
│ ├─ materials/ # 独立物料包(material-banner-slides / material-product-list)
│ └─ mocks/ # mock-cdn(文件型 CDN,物料与页面产物存放处)、mock-logger
├─ docs/plans/ # 16 份设计/决策文档(部署运维、发布、模板、RBAC、合并服务等)
├─ tiny-engine-study/ # OpenTiny TinyEngine 2.11.0 完整源码副本,仅作借鉴参考,不参与构建
├─ tiny-engine-borrow-plan.md# TinyEngine 借鉴落地任务清单(协议统一、iframe 画布、AI 补丁等)
└─ demos/ # 独立 html/js 演示脚本,不属于 workspace包间依赖关系(来自各 package.json 的 dependencies/workspace:* 声明):work-front → shared/charts/business;charts → shared;work-server → server-kit/work-front(静态产物)/mock-cdn/mock-logger;portal-server → server-kit/work-front/mock-cdn/mock-logger;server-kit → mock-cdn。
依赖图里有三个"承重墙"式的包,改动须格外谨慎。@my/shared 被全仓称为"宪法":看板 Schema 类型、物料协议、页面方法运行时都被前端、两个服务端与访客渲染器共同消费,任何类型变更都是跨端联动的契约变更;work-front 的 admin/visitor 双产物桶是安全边界——构建脚本按 URL 参数分发产物,访客门户的公开目录里不存在编辑器代码,桶隔离的动机与实现见《01-系统架构》;server-kit 则把两个服务端都会用到的连接池/事务、安全响应头、cookie/CSRF、限流收敛为一处,避免两服务在安全基线上各自漂移。工程侧另有几个降低协作成本的约定值得留意:根 package.json 的 scripts 全部经 vite-node 直跑 TS 脚本(免编译、与业务代码同一套 TS 配置)、pnpm-workspace.yaml 用 overrides 把 Vue 锁为全仓单版本(防多实例)、Vitest 以 server/web 两个 project 分线跑测试。
生产模式四步(摘自根 README.md 与 docs/plans/deploy-ops-2026-09.md,细节见本系列 06 篇):
pnpm i # 1. 安装依赖(postinstall 会自动执行整包构建)
# 先把 .env 的 MYSQL_* 改成你本机数据库账号(可参照 .env.example)
npm run db:init # 2. 建库建表 + 写入 admin001/admin002 种子账号(初始密码 88888888)
npm run start:work # 3a. 启动后台全栈(8001:管理台/编辑器/预览)
npm run start:portal # 3b. 启动访客门户(6001:/d/:uuid /p/:uuid)开发模式则分别跑 npm run dev:work-server(8001)、npm run dev:work-front(Vite dev server,8002,/api 代理到 8001)、npm run dev:portal-server(6001)、npm run dev:portal-front(6002)。
首次访问路径:登录 http://127.0.0.1:8001/page/sign-in → 页面管理 http://127.0.0.1:8001/page/manage/page-list 或看板管理 .../dashboard-list → 编辑并发布 → 访客按 http://127.0.0.1:6001/d/${uuid} 访问。
两条必须先记住的硬约束:db:init 必须先于新版代码上线(老库列宽放宽,否则写入 1406 报错);JWT_SECRET / SECRET_BOX_KEY 生产缺失会拒绝启动(packages/work-server/src/index.ts 启动自检)。
docs/plans/deploy-ops-2026-09.md。