VTJ: 数据结构定义

3 阅读8分钟

数据结构定义

引言

本文件面向“数据结构定义”,聚焦于项目模型系统中的核心数据类型,包括 ProjectSchema、PageFile、BlockFile、ApiSchema 等关键接口的定义与用途。我们将逐项说明字段含义、数据类型、约束条件与默认值;阐述数据结构之间的关系与依赖;解释 ProjectSchema 如何整合页面、区块、数据源、国际化、环境变量等子模块;并给出数据验证规则、序列化/反序列化要点、与 DSL 的对应关系,以及最佳实践与设计原则。

项目结构

本项目采用多包工作区(monorepo)组织,核心数据协议位于 packages/core/src/protocols/schemas 下,模型层位于 packages/core/src/models 中,设计器侧的资产加载与物料解析位于 packages/designer/src/framework/assets.ts。文档 wiki 提供了项目与区块模型的高层说明。

graph TB
subgraph "协议层"
PS["ProjectSchema<br/>项目根模型"]
FS["File 协议<br/>FileType/BlockFile/PageFile"]
DS["DataSource 协议<br/>ApiSchema/MetaSchema"]
NS["Node 协议<br/>节点/事件/指令/插槽"]
BS["Block 协议<br/>区块DSL结构"]
HS["History 协议<br/>历史记录"]
SH["Shared 协议<br/>JSONValue/JSFunction/JSExpression"]
end
subgraph "模型层"
PM["ProjectModel<br/>项目模型"]
end
subgraph "设计器侧"
AS["Assets<br/>物料/分组/缓存"]
end
PS --> FS
PS --> DS
PS --> SH
FS --> BS
BS --> NS
BS --> DS
BS --> SH
HS --> BS
PM --> PS
AS --> BS
AS --> NS

核心组件

本节对关键数据结构进行逐一说明,并标注字段含义、类型、约束与默认值。

  • ProjectSchema(项目根模型)

    • 字段与类型
      • id?: string;唯一标识
      • name: string;项目名称(必填)
      • description?: string;项目简介
      • platform?: PlatformType;平台,默认 web
      • locked?: string;锁定标记
      • homepage?: string;首页 pageId
      • dependencies?: Dependencie[];项目依赖
      • pages?: PageFile[];页面集合
      • blocks?: BlockFile[];区块集合
      • apis?: ApiSchema[];项目级 API 数据源
      • meta?: MetaSchema[];配置化查询数据源
      • config?: ProjectConfig;项目母版配置
      • uniConfig?: UniConfig;UniApp 项目配置
      • globals?: GlobalConfig;Web/H5 全局配置
      • i18n?: I18nConfig;国际化配置
      • env?: EnvConfig[];环境变量
      • VTJ_PROJECT?: boolean;项目标记
      • VERSION?: string;版本
      • BASE_PATH?: string;部署目录
      • UID?: string;全局项目标识
    • 约束与默认
      • name 必填;platform 默认 web;i18n.locale/fallbackLocale 默认 zh-CN;UID 自动生成
    • 关系
      • 整合 PageFile、BlockFile、ApiSchema、MetaSchema 等子模块
      • 通过 ProjectModel.toDsl 输出 DSL 时会清理页面 DSL 的冗余字段
  • PageFile(页面文件)

    • 字段与类型
      • 继承自 BlockFile 的所有字段(见下一条)
      • dir?: boolean;是否目录
      • layout?: boolean;是否布局页面
      • icon?: string;菜单图标
      • children?: PageFile[];目录包含的页面
      • mask?: boolean;是否在母版内
      • hidden?: boolean;不在菜单显示
      • raw?: boolean;源码文件(非低代码页面)
      • pure?: boolean;纯净页面
      • cache?: boolean;开启页面缓存
      • meta?: Record<string, any>;路由元信息
      • needLogin?: boolean;UniApp 专用,需登录才可访问
      • style?: Record<string, any>;UniApp 页面窗口表现配置
    • 约束与默认
      • type 为 'page';fromType 一经确定不可更改;urls 在 fromType=UrlSchema 时仅允许一个 JSON 文件
    • 关系
      • 作为 ProjectSchema.pages 的元素;可嵌套形成目录树
  • BlockFile(区块文件)

    • 字段与类型
      • type: FileType;固定为 'block'
      • id: string;唯一标识
      • name: string;文件名
      • title: string;显示标题
      • category?: string;分组
      • market?: MarketInstallInfo;从物料市场安装信息
      • fromType?: 'Schema' | 'UrlSchema' | 'Plugin';创建来源(一经确定不可更改)
      • preset?: boolean;是否预设(预设不可编辑/删除)
      • urls?: string;资源 URL(fromType=Plugin 时允许多个,以逗号分隔)
      • library?: string;Plugin 时的库名
      • dsl?: BlockSchema;区块 DSL 内容
    • 约束与默认
      • fromType 默认 Schema;preset 默认 false;urls 在不同 fromType 下有不同约束
    • 关系
      • 作为 ProjectSchema.blocks 的元素;可被节点引用(NodeFrom)
  • ApiSchema(项目级 API 数据源)

    • 字段与类型
      • id: string;唯一标识
      • name: string;接口名称
      • label?: string;接口描述
      • url: string;请求地址
      • category?: string;分组
      • method?: ApiMethod;请求方法,默认 get/post/put/delete/patch/jsonp
      • settings?: Record<string, any>;请求设置
      • headers?: JSExpression | JSFunction;请求头表达式/函数
      • jsonpOptions?: Record<string, any>;jsonp 配置
      • mockTemplate?: JSFunction;模拟数据模板
      • mock?: boolean;是否启用模拟数据
    • 约束与默认
      • id/name/url 必填;method 默认 get
    • 关系
      • 作为 ProjectSchema.apis 的元素;可被页面级 DataSourceSchema 引用
  • MetaSchema(配置化查询数据源)

    • 字段与类型
      • id: string;唯一标识
      • code: string;功能号
      • title: string;报表名称
      • queryCode: string;查询方案编号
    • 约束与默认
      • id/code/title/queryCode 必填
    • 关系
      • 作为 ProjectSchema.meta 的元素
  • NodeSchema(节点协议)

    • 字段与类型
      • id?: string;节点标识
      • name: string;组件名
      • from?: NodeFrom;来源(字符串/Schema/UrlSchema/Plugin)
      • locked?: boolean;锁定
      • invisible?: boolean;不可见
      • props?: NodeProps;组件属性
      • events?: NodeEvents;绑定事件
      • directives?: NodeDirective[];内置指令
      • children?: NodeChildren;子组件
      • slot?: string | NodeSlot;插槽
    • 约束与默认
      • name 必填;from 可为字符串或对象;props/events/directives 等为可选
    • 关系
      • 作为 BlockSchema.nodes 的元素;与 BlockFile/BlockSchema 协同
  • BlockSchema(区块 DSL)

    • 字段与类型
      • id?: string;唯一标识
      • name: string;组件名
      • locked?: boolean;锁定
      • inject?: BlockInject[];注入
      • state?: BlockState;状态数据
      • lifeCycles?: Record<string, JSFunction>;生命周期
      • methods?: Record<string, JSFunction>;自定义方法
      • computed?: Record<string, JSFunction>;计算属性
      • watch?: BlockWatch[];侦听器
      • css?: string;样式
      • props?: Array<string | BlockProp>;属性参数
      • emits?: Array<string | BlockEmit>;事件
      • expose?: string[];暴露公共属性
      • slots?: Array<string | BlockSlot>;插槽
      • nodes?: NodeSchema[];节点树
      • dataSources?: Record<string, DataSourceSchema>;数据源
      • transform?: Record<string, string>;babel 转换缓存
      • VTJ_BLOCK?: boolean;区块标记
      • VERSION?: string;版本
      • TEMPLATE_ID?: string;模板 id
    • 约束与默认
      • name 必填;nodes 为节点树;dataSources 为页面级引用数据源
    • 关系
      • 作为 BlockFile.dsl 使用;与 NodeSchema/DataSourceSchema 共同构成区块 DSL
  • HistorySchema(历史记录)

    • 字段与类型
      • id: string;页面或区块文件 id
      • items?: HistoryItem[];历史记录项
    • HistoryItem
      • id: string;记录项唯一标识
      • label: string;记录项描述
      • dsl?: BlockSchema;记录项内容(区块 DSL)
      • remark?: string;备注
    • 关系
      • 用于追踪页面/区块变更历史
  • Shared 类型(通用类型)

    • JSONValue/JSONArray/JSONObject;JSExpression/JSFunction;DataType;PlatformType;ParseVueOptions 等
    • 作用
      • 为协议层提供统一的 JSON/JS 代码表示与平台类型定义

架构总览

ProjectSchema 作为项目根模型,聚合页面(PageFile)、区块(BlockFile)、数据源(ApiSchema/MetaSchema)、国际化(I18nConfig)、环境变量(EnvConfig)等子模块。BlockSchema 作为区块的 DSL 描述,内部包含节点树(NodeSchema)、数据源引用(DataSourceSchema)等。设计器侧通过 Assets 将物料(BlockSchema)与节点来源(NodeFrom)进行解析与缓存,最终渲染到页面。

classDiagram
class ProjectSchema {
+string name
+string? id
+PlatformType? platform
+PageFile[]? pages
+BlockFile[]? blocks
+ApiSchema[]? apis
+MetaSchema[]? meta
+ProjectConfig? config
+UniConfig? uniConfig
+GlobalConfig? globals
+I18nConfig? i18n
+EnvConfig[]? env
}
class PageFile {
+FileType type
+string id
+string name
+string title
+boolean? dir
+boolean? layout
+PageFile[]? children
+Record? meta
}
class BlockFile {
+FileType type
+string id
+string name
+string title
+string? urls
+string? library
+BlockSchema? dsl
}
class BlockSchema {
+string name
+NodeSchema[]? nodes
+Record~DataSourceSchema~? dataSources
}
class NodeSchema {
+string name
+NodeProps? props
+NodeEvents? events
+NodeDirective[]? directives
+NodeChildren? children
}
class ApiSchema {
+string id
+string name
+string url
+ApiMethod? method
}
class MetaSchema {
+string id
+string code
+string title
+string queryCode
}
ProjectSchema --> PageFile : "pages"
ProjectSchema --> BlockFile : "blocks"
ProjectSchema --> ApiSchema : "apis"
ProjectSchema --> MetaSchema : "meta"
BlockFile --> BlockSchema : "dsl"
BlockSchema --> NodeSchema : "nodes"
BlockSchema --> ApiSchema : "dataSources(ref)"

详细组件分析

ProjectSchema 与 ProjectModel

  • 职责
    • ProjectSchema 描述项目的完整结构与配置
    • ProjectModel 负责项目实例化、更新、事件派发、DSL 导出等
  • 关键行为
    • update:批量更新项目属性并触发变更事件
    • toDsl:导出 DSL 时清理页面/区块的 dsl 字段,避免冗余
    • active:打开文件并派发激活事件
  • 与 DSL 的关系
    • ProjectModel.toDsl 返回的结构带有 VTJ_PROJECT 标记,作为项目 DSL 的根对象
sequenceDiagram
participant PM as "ProjectModel"
participant PS as "ProjectSchema"
participant EM as "事件发射器"
PM->>PM : update(schema, silent)
PM->>EM : 发射 EVENT_PROJECT_CHANGE
PM->>PM : toDsl(version?)
PM->>PM : 清理 pages/blocks 的 dsl
PM-->>PS : 返回带 __VTJ_PROJECT__ 的 DSL

PageFile 与 BlockFile

  • PageFile
    • 作为页面的文件描述,支持目录、布局、缓存、登录等特性
    • 与 ProjectSchema.pages 集合关联
  • BlockFile
    • 作为可复用区块的文件描述,支持三种来源:Schema、UrlSchema、Plugin
    • 与 ProjectSchema.blocks 集合关联
  • fromType 与 urls 的约束
    • fromType 一经确定不可更改
    • UrlSchema 仅允许一个 JSON 文件;Plugin 支持多个文件(以逗号分隔)
flowchart TD
Start(["开始"]) --> CheckFrom["检查 fromType"]
CheckFrom --> |Schema| UseDSL["使用本地 BlockSchema"]
CheckFrom --> |UrlSchema| LoadURL["加载单个 JSON URL"]
CheckFrom --> |Plugin| LoadPlugin["加载多个 CSS/JS URL"]
UseDSL --> Done(["结束"])
LoadURL --> Done
LoadPlugin --> Done

BlockSchema 与 NodeSchema

  • BlockSchema
    • 描述区块的完整 DSL,包含状态、方法、计算属性、侦听器、样式、属性/事件/插槽、节点树、数据源等
  • NodeSchema
    • 描述节点的属性、事件、指令、插槽与子节点
  • 关系
    • BlockSchema.nodes 为 NodeSchema 数组;BlockSchema.dataSources 引用页面级数据源
classDiagram
class BlockSchema {
+NodeSchema[]? nodes
}
class NodeSchema {
+string name
+NodeProps? props
+NodeEvents? events
+NodeDirective[]? directives
+NodeChildren? children
}
BlockSchema --> NodeSchema : "nodes"

ApiSchema 与 MetaSchema

  • ApiSchema
    • 项目级 API 数据源,支持请求方法、请求头、jsonp、mock 等
  • MetaSchema
    • 配置化查询数据源,包含功能号、报表名、查询方案编号
  • 关系
    • 二者均作为 ProjectSchema 的子模块存在,供页面级 DataSourceSchema 引用

设计器侧资产加载(Assets)

  • 职责
    • 加载物料包、构建分组、解析 BlockSchema、缓存并生成物料描述
  • 关键流程
    • 根据 NodeFrom 解析来源:Schema/UrlSchema/Plugin
    • 从服务获取 DSL 或插件物料,填充组件映射
    • 自动根据 props 类型匹配设置器
sequenceDiagram
participant AS as "Assets"
participant SVC as "Service"
participant PRV as "Provider"
participant MAP as "componentMap"
AS->>AS : getBlockMaterial(from, blockName)
alt from.type == "Schema"
AS->>SVC : getFile(id, project)
SVC-->>AS : BlockSchema
else from.type == "UrlSchema"
AS->>PRV : getDslByUrl(url)
PRV-->>AS : BlockSchema
else from.type == "Plugin"
AS->>SVC : getPluginMaterial(from)
SVC-->>AS : MaterialDescription
AS->>MAP : set(name, material)
end
AS-->>MAP : 缓存并返回物料描述

依赖分析

  • 协议层耦合
    • ProjectSchema 依赖 File、DataSource、Shared 等协议
    • BlockSchema 依赖 NodeSchema、DataSourceSchema、Shared
    • PageFile/BlockFile 依赖 File 协议
  • 模型层与协议层
    • ProjectModel 以 ProjectSchema 为输入,提供更新、事件、DSL 导出能力
  • 设计器侧
    • Assets 通过 Service/Provider 获取 DSL,与 BlockSchema/NodeSchema 协同
graph LR
PS["ProjectSchema"] --> FS["File 协议"]
PS --> DS["DataSource 协议"]
PS --> SH["Shared 协议"]
FS --> BS["Block 协议"]
BS --> NS["Node 协议"]
BS --> DS
PM["ProjectModel"] --> PS
AS["Assets"] --> BS
AS --> NS

性能考虑

  • DSL 导出优化
    • ProjectModel.toDsl 会清理 pages/blocks 的 dsl 字段,避免序列化冗余
    • cleanPagesDsl 递归清理子页面 dsl,降低体积
  • 设计器缓存
    • Assets 使用 caches 缓存已解析的 DSL,减少重复请求
  • 数据结构扁平化
    • PageFile.children 采用数组嵌套,便于遍历与渲染;建议控制层级深度

故障排查指南

  • fromType 与 urls 不一致
    • 症状:fromType=UrlSchema 但 urls 包含多个值,或 fromType=Plugin 但 urls 格式错误
    • 处理:确保 UrlSchema 仅一个 JSON 文件;Plugin 多文件以逗号分隔
  • 页面/区块 DSL 过大
    • 症状:序列化体积过大
    • 处理:调用 cleanPagesDsl 清理 dsl;在导出前执行 ProjectModel.toDsl
  • 物料解析失败
    • 症状:getBlockMaterial 返回空
    • 处理:确认 NodeFrom 类型与参数;检查服务端/URL 是否可达;查看缓存是否命中

结论

本文系统梳理了项目模型中的核心数据结构:ProjectSchema、PageFile、BlockFile、ApiSchema、MetaSchema、BlockSchema、NodeSchema、HistorySchema 以及 Shared 类型。明确了字段语义、类型、约束与默认值,阐述了它们之间的关系与依赖,并结合 ProjectModel 的 DSL 导出与 Assets 的物料解析流程,给出了序列化/反序列化的注意事项与最佳实践。遵循本文的设计原则与约束,可确保项目模型在设计器与渲染器之间稳定流转。

附录

  • 与 DSL 的对应关系
    • ProjectModel.toDsl 输出的 ProjectSchema 带有 VTJ_PROJECT 标记,作为项目 DSL 根对象
    • BlockFile.dsl 为 BlockSchema,作为区块 DSL
    • NodeSchema 作为 BlockSchema.nodes 的元素,承载节点属性、事件、指令与子节点
  • 参考文档
    • 项目与区块模型的高层说明可参考 wiki 文档

参考资料

VTJ.PRO 是一个开源的、AI 驱动的 Vue 3 企业级应用开发平台。它通过 AI 智能体与可视化编排实现高效开发,并支持导出标准 Vue 代码以避免平台锁定。更多信息请访问: