Skip to content

Schema 参考

Schema 是 EasyInk 的核心数据结构,描述文档的完整结构。它是设计器和预览器之间的唯一桥梁。

对宿主应用而言,传入设计器的是 DocumentSchemaInput:所有顶层字段都可以省略,pageguides 的必填子字段也可以省略。框架会通过 normalizeDocumentSchema() 补齐默认值,进入 DesignerStore、Viewer、自动保存和导出链路后的内部模型始终是完整 DocumentSchema

ts
import { normalizeDocumentSchema } from '@easyink/schema'

const schema = normalizeDocumentSchema({
  page: { width: 80 },
})

// schema.page => { mode: 'fixed', width: 80, height: 297 }
// schema.guides => { x: [], y: [] }
// schema.elements => []

validateSchemaIssues() 仍用于判断一个对象是否已经是完整合法的内部 Schema;缺字段的输入不应直接交给画布或预览器消费,应先归一化。

DocumentSchema

ts
interface DocumentSchema {
  version: string                    // Schema 版本号
  meta?: DocumentMeta                // 文档元信息
  unit: UnitType                     // 全局单位:'mm' | 'pt' | 'px' | 'inch'
  page: PageSchema                   // 页面配置
  guides: GuideSchema                // 辅助线
  elements: MaterialNode[]           // 元素列表
  groups?: ElementGroupSchema[]      // 元素分组
  extensions?: Record<string, unknown> // 扩展数据(如 AI、自定义插件)
  compat?: BenchmarkCompatState      // 兼容层数据
}

DocumentSchemaInput

DocumentSchemaInput 是给宿主传入设计器或调用归一化函数时使用的宽松输入类型:

ts
type DocumentSchemaInput = Partial<Omit<DocumentSchema, 'page' | 'guides' | 'elements' | 'groups'>> & {
  page?: Partial<PageSchema>
  guides?: Partial<GuideSchema>
  elements?: MaterialNode[]
  groups?: ElementGroupSchema[]
}

默认值来自 createDefaultSchema():A4、mmfixed、空辅助线、空元素列表。已有合法字段会保留,缺失或非法的必需字段会回退到默认值。

DocumentMeta

ts
interface DocumentMeta {
  name?: string
  description?: string
  author?: string
  createdAt?: string
  updatedAt?: string
}

PageSchema

页面配置定义纸张尺寸、分页模式和打印参数。

ts
interface PageSchema {
  mode: PageMode            // 'fixed' | 'stack' | 'label'
  width: number             // 页面宽度
  height: number            // 页面高度
  pages?: number            // 页数(fixed 模式)
  scale?: PageScale         // 缩放模式
  radius?: string           // 页面圆角
  offsetX?: number          // 水平偏移
  offsetY?: number          // 垂直偏移
  copies?: number           // 打印份数
  blankPolicy?: BlankPolicy // 空白页策略
  label?: LabelPageConfig   // 标签页配置
  grid?: GridConfig         // 网格配置
  font?: string             // 默认字体
  background?: PageBackground // 页面背景
  print?: PagePrintConfig   // 打印配置
  extensions?: Record<string, unknown>
}

分页模式

模式说明
fixed固定页面,元素绝对定位,支持多页
stack堆叠流式,元素按 Y 轴排列,自动分页
label标签模式,多列多行网格布局

LabelPageConfig

标签模式的网格配置:

ts
interface LabelPageConfig {
  columns: number    // 列数
  gap: number        // 列间距
  rows?: number      // 行数
  rowGap?: number    // 行间距
}

PageBackground

ts
interface PageBackground {
  color?: string           // 背景颜色
  image?: string           // 背景图片 URL
  repeat?: BackgroundRepeat // 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat'
  width?: number
  height?: number
  offsetX?: number
  offsetY?: number
}

PagePrintConfig

ts
interface PagePrintConfig {
  orientation?: 'auto' | 'portrait' | 'landscape'
  horizontalOffset?: number  // 打印水平偏移
  verticalOffset?: number    // 打印垂直偏移
}

GridConfig

ts
interface GridConfig {
  enabled: boolean
  width: number   // 网格单元宽度
  height: number  // 网格单元高度
}

MaterialNode

元素节点是文档中的可视对象。

ts
interface MaterialNode<TProps = Record<string, unknown>> {
  id: string                   // 唯一标识
  type: string                 // 物料类型(如 'text'、'image'、'table-data')
  name?: string                // 显示名称
  unit?: UnitType              // 坐标单位(覆盖全局 unit)
  x: number                    // X 坐标
  y: number                    // Y 坐标
  width: number                // 宽度
  height: number               // 高度
  rotation?: number            // 旋转角度
  alpha?: number               // 透明度(0-1)
  zIndex?: number              // 层级
  hidden?: boolean             // 是否隐藏
  locked?: boolean             // 是否锁定
  print?: PrintBehavior        // 打印行为
  props: TProps                // 物料属性(由物料类型决定)
  binding?: BindingRef | BindingRef[]  // 数据绑定
  animations?: AnimationSchema[]       // 动画
  children?: MaterialNode[]    // 子元素(容器类物料)
  diagnostics?: NodeDiagnosticState[]  // 节点级诊断
  extensions?: Record<string, unknown>
  compat?: BenchmarkElementCompatState
}

常见物料类型

type说明主要 props
text文本content, fontSize, fontFamily, color, textAlign, fontWeight
image图片src, objectFit
barcode条码value, format
qrcode二维码value
line线条direction, strokeColor, strokeWidth
rect矩形fill, strokeColor, strokeWidth
ellipse椭圆fill, strokeColor
table-static静态表格table: TableSchema
table-data数据表格table: TableDataSchema
container容器children
chart图表图表配置
svgSVGSVG 内容

BindingRef

数据绑定引用。

ts
interface BindingRef {
  sourceId: string           // 设计时数据源 ID,Viewer 不用它选择数据根
  sourceName?: string        // 设计时数据源名称
  sourceTag?: string         // 设计时数据源标签
  fieldPath: string          // 运行时 data 根路径,如 'customer/name' 或 'items/price'
  fieldKey?: string          // 字段 key
  fieldLabel?: string        // 字段标签
  format?: BindingDisplayFormat  // 格式化规则
  bindIndex?: number         // 绑定索引(多绑定时区分主/次)
  required?: boolean         // 是否必填
  extensions?: Record<string, unknown>
}

AnimationSchema

ts
interface AnimationSchema {
  trigger: string    // 触发条件
  type: string       // 动画类型
  duration?: number  // 持续时间(毫秒)
  delay?: number     // 延迟(毫秒)
  options?: Record<string, unknown>
}

TableNode

表格元素扩展了 MaterialNode,增加了 table 属性。

ts
interface TableNode extends MaterialNode {
  type: 'table-static' | 'table-data'
  table: TableSchema
}

interface TableSchema {
  kind: 'static' | 'data'
  topology: TableTopologySchema  // 行列拓扑
  layout: TableLayoutConfig      // 布局配置
  diagnostics?: LayoutDiagnostic[]
}

interface TableTopologySchema {
  columns: TableColumnSchema[]   // 列定义(ratio 为宽度比例)
  rows: TableRowSchema[]         // 行定义
}

interface TableRowSchema {
  height: number
  role: TableRowRole             // 'header' | 'body' | 'footer'
  cells: TableCellSchema[]
}

interface TableCellSchema {
  rowSpan?: number
  colSpan?: number
  content?: {
    text?: string
    elements?: MaterialNode[]    // 单元格内嵌元素
    editMode?: 'inline-text' | 'rich-text' | 'hosted'
  }
  binding?: BindingRef
  typography?: CellTypography
}

工具函数

ts
// 类型守卫
isTableNode(node)      // 是否为表格节点
isTableDataNode(node)  // 是否为数据表格节点

// 属性访问
getNodeProps<T>(node)  // 获取类型化的 props

最小 Schema 示例

json
{
  "version": "1",
  "unit": "mm",
  "page": {
    "mode": "fixed",
    "width": 210,
    "height": 297
  },
  "guides": { "x": [], "y": [] },
  "elements": [
    {
      "id": "text-1",
      "type": "text",
      "x": 20,
      "y": 20,
      "width": 170,
      "height": 10,
      "props": {
        "content": "Hello EasyInk",
        "fontSize": 24,
        "fontFamily": "sans-serif"
      }
    }
  ]
}