基于JSON Schema的前端可视化活动编辑器

先看效果,为一个可视化活动编辑器。

vue-editor

演示地址:https://form.lljj.me/vue-editor.html#/editor
项目地址:https://github.com/lljj-x/vue-json-schema-form/

基于 JSON Schema 开箱即用的简单活动可视化编辑器。

背景

在做生成一个可视化店铺装修系统的时候,需要解决配置数据表单的通用性,参阅了一些现用的解决方案,最终通过 JSON Schema 来生成对应的表单和校验规则。

参考资料:https://github.com/CntChen/cntchen.github.io/issues/15

JSON Schema 主要运用在如下几点:

  • 基于 JSON Schema 来动态生成数据配置表单和数据校验
  • 结合发布流程同步 JSON Schema 到后端系统做接口数据校验
  • 活动版块对应一个 JSON Schema 和一份视图 View组件 即可

实现

首先可视化编辑器需要做到板块的管理,这些板块支持可视化的编辑配置和效果展示,最终相互组装为一个页面。

每个板块我们不可避免的需要一个 View组件 来做展示,因为每个板块都长得不一样。板块配置表单和数据校验都通过 JSON Schema 来实现,然后再通过一个拖动的容器来承载这些板块以及一些其它的数据配置。

如下图:
vue-editor

这样当我们在添加新的板块时,只需要开发一个 View组件 ,和书写一份 JSON Schema 来定义数据即可。

功能介绍

基于Vue,依赖 ElementUi、vuedraggable、@lljj/vue-json-schema-form

  • 板块支持配置化
  • 支持可添加数,是否可删除,置顶,置底,图标配置
  • 支持拖动或者点击上下移动,复制删除等调整页面布局
  • 支持页面预览模式
  • 支持编辑还原数据和默认板块数据配置
  • 视图组件支持异步加载
  • 不支持嵌套组件

添加新的板块只需要在 config/tools.js 导入新增的板块,并且配置好工具栏即可,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import * as componentPackFlashSaleGoodsList from '../viewComponents/FlashSaleGoodsList';

const tools = [
{
groupName: '图文类',
componentList: [{
// 比如这里添加新增的模块
title: '秒杀商品', // 板块标题
maxNum: 3, // 最多可添加次数
icon: 'el-icon-picture', // 工具栏图标类名
componentPack: componentPackFlashSaleGoodsList, // 重点是这个当前板块的组件包
additional: {
bottomDisplay: true, // 是否置底显示
topDisplay: true, // 是否置顶显示
unRemove: true // 是否为不可移除
}
}]
}
]

新增板块文件结构如下:( viewComponents/FlashSaleGoodsList/index.js 这里对应上面工具栏配置导入的组件包文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import propsSchema from './schema.json';
import uiSchema from './uiSchema.js';
import errorSchema from './errorSchema.js';

// 这里可以异步导入
const View = () => import('./View.vue');

const NAME = propsSchema.id;
const componentViewName = `${NAME}View`;

export {
propsSchema, // JSON Schema 定义数据结构和生成表单 vue-json-schema-form 参数
componentViewName, // 视图View组件name,需要自己保持唯一
View, // 视图View组件
uiSchema, // uiSchema 辅助增强表单样式 不必须 vue-json-schema-form 参数
errorSchema, // 辅助增强表单校验错误提示 不必须 vue-json-schema-form 参数
// customRule, // 自定义的校验规则 vue-json-schema-form 参数 (需要更多的vue-json-schema-form 参数参数可自己添加)
};

导出模块解释如下:

  • propsSchemarequired JSON Schema配置,必须包含一个 id 的属性,并且要保证唯一,在保存和编辑数据时用来标识当前组件。传递给 vue-json-schema-form 生成表单;
  • componentViewNamerequired 板块View组件名,唯一,建议通过 id + View 拼接,只是为了在注册组件时的组件名,其实我也可以帮你生成,但是我没有;
  • Viewrequired required 板块View组件,需要异步导入就 () => import(‘./xxx.vue’),View 组件必须包含一个名为 formData 的props接受当前表单数据;
  • uiSchema: 传递给 vue-json-schema-form 生成表单,用于增强生成表单的样式,可选;
  • errorSchema: 传递给 vue-json-schema-form 生成表单,用于增强表单的校验提示信息
  • customRule: 传递给 vue-json-schema-form 生成表单,用于自定义校验表单数据

如果需要更多 vue-json-schema-form 参数可直接在 packages/demo/src/vue-editor/views/editor/Editor.vue 渲染 VueElementForm 组件时添加即可。

  • 新增板块可参见 /packages/demo/src/vue-editor/views/editor/viewComponents 内现有板块
  • 工具栏和默认数据配置在 /packages/demo/src/vue-editor/views/editor/config 文件夹内

整个实现相对比较简单,感兴趣的可以花上两个小时看下源码,欢迎讨论提问。