El Schema Form
基于 JSON Schema/Element 的表单自动化解决方案
JSON Schema
基于 JSON Schema,简单高效
# El Schema Form
文档可能未及时更新,最新文档请查看 https://gitlab.mobvista.com/playable/el-schema-form。
# 安装
yarn add ssh://git@gitlab.mobvista.com:playable/el-schema-form.git
# 引入 el-schema-form-item,el-schema-form-fieldset
一般情况下,推荐使用,ElSchemaFormFieldset 或 ElSchemaFormItem 组件,更灵活。ElSchemaForm 更适合交互简单且需要表单嵌套的场景使用。
什么是 ElSchemaFormFieldset 与 ElSchemaFormItem?
- ElSchemaFormFieldset 表单控件组
- ElSchemaFormItem 表单控件
ElSchemaFormFieldset 支持 slot。
import { ElSchemaFormItem, ElSchemaFormFieldset } from 'el-schema-form'
ElSchemaFormFieldset 示例:
<template>
<div class="form-item-test">
<h2>fieldset 是对象</h2>
<el-form :model="model" ref="form">
<form-fieldset
:model="model"
:fieldset="formItemList"
@change="handleChange"
>
<el-form-item slot="slotTest" v-bind="formItemList.slotTest">
slotTest
<el-input v-bind="formItemList.slotTest.field" :value="model.slotTest" @input="val => model.slotTest = val"></el-input>
</el-form-item>
</form-fieldset>
<el-button @click="submit">确定</el-button>
</el-form>
<h2>fieldset 是数组</h2>
<el-form :model="model2" ref="form">
<form-fieldset
:model="model2"
:fieldset="formItemList2"
@change="handleChange2"
>
</form-fieldset>
<el-button @click="submit">确定</el-button>
</el-form>
</div>
</template>
<script>
import FormFieldset from '../../package/FormFieldset'
import DynamicFormItemField from '@/components/DynamicFormItemField'
export default {
name: 'FormItemTest',
components: {
FormFieldset
},
data () {
return {
model: {
name: 'name',
organizer: 'organizer',
count: 33,
region: 'shanghai',
date: '',
delivery: false,
types: [1, 2],
resource: '',
desc: '',
extra_value: 'extra value',
link: '//google.com',
plain_text: '文本示例文案',
dynamic_component: '',
dynamic_component2: '',
image: '',
hobby: ['打篮球222'],
color: '#000000',
slotTest: 'slotTest'
},
model2: {
width: 853.8083504010178,
height: 131.63953804649594,
anchoredX: 143.06230140095516,
anchoredY: 167.24184529970657,
scaleX: 1,
scaleY: 1,
pivotX: 0,
pivotY: 0,
rotation: 0,
alpha: 1,
colorTint: '#ffffff'
}
}
},
computed: {
formItemList () {
return {
slotTest: {
slot: 'slotTest',
label: '活动名称 slot',
prop: 'slotTest',
field: {
placeholder: '活动名称',
type: 'textarea',
listeners: {
input: (val, e) => {
console.log(val, 'input')
},
'~focus' (val) {
console.log(val, 'foucs')
},
change (val) {
console.log(val, 'change')
},
blur (val) {
console.log(val, 'blur')
}
}
},
rules: [
{
required: true,
message: '活动名称不能为空',
trigger: 'change'
}
],
description: '活动名称描述'
},
name: {
component: 'input',
label: '活动名称 input',
prop: 'name',
field: {
placeholder: '活动名称',
type: 'textarea',
listeners: {
input: (val, e) => {
console.log(val, 'input')
},
'~focus' (val) {
console.log(val, 'foucs')
},
change (val) {
console.log(val, 'change')
},
blur (val) {
console.log(val, 'blur')
}
}
},
rules: [
{
required: true,
message: '活动名称不能为空',
trigger: 'change'
}
],
description: '活动名称描述'
},
count: {
component: 'input',
label: '参加人数 label',
prop: 'count',
rules: [
{
required: true,
message: '参加人数不能为空',
trigger: 'change'
},
{ min: 10, max: 100, type: 'number' }
],
field: {
placeholder: '参加人数',
type: 'number'
}
},
organizer: {
component: 'autocomplete',
visible: this.model.name === 'name',
label: '活动举办方',
prop: 'organizer',
rules: [{ required: true, message: '活动举办方不能为空' }],
field: {
placeholder: '活动举办方',
fetchSuggestions () {
console.log('fetchSuggestions')
}
}
},
region: {
component: 'select',
label: '活动区域',
prop: 'region',
rules: [
{ required: true, message: '请选择活动区域', trigger: 'change' }
],
field: {
clearable: true,
options: [
{
value: 'shanghai',
label: '上海'
},
{
value: 'beijing',
label: '北京'
}
],
placeholder: '活动区域'
}
},
date: {
component: 'date-picker',
label: '活动日期',
prop: 'date',
rules: [{ required: true, message: '请选择活动日期' }],
field: {
placeholder: '活动日期'
}
},
delivery: {
component: 'switch',
label: '即时配送',
field: {},
prop: 'delivery'
},
types: {
component: 'checkbox-group',
label: '活动性质',
prop: 'types',
// rules: [
// { required: true, message: '请选择活动性质', trigger: 'change' }
// ],
field: {
options: [
{
value: 1,
label: '美食/餐厅线上活动'
},
{
value: 2,
label: '地推活动'
},
{
value: 3,
label: '线下主题活动'
},
{
value: 4,
label: '单纯品牌曝光'
}
]
}
},
resource: {
component: 'radio-group',
label: '特殊资源',
rules: [{ required: true, message: '请选择资源类型' }],
prop: 'resource',
field: {
options: [
{
value: 1,
label: '线上品牌商赞助'
},
{
value: 2,
label: '线下场地免费'
}
]
}
},
desc: {
component: 'input',
label: '活动形式',
prop: 'desc',
rules: [{ required: true, message: '活动形式不能为空' }],
field: {
type: 'textarea'
}
},
link: {
component: 'link',
label: '链接示例',
prop: 'link',
field: {
target: '_blank',
text: '谷歌链接'
}
},
plain_text: {
component: 'plain-text',
label: '文本示例',
prop: 'plain_text'
},
dynamic_component: {
label: '动态表单控件示例1',
component: DynamicFormItemField,
rules: [{ required: true, message: '请选择动态组件' }],
prop: 'dynamic_component',
field: {
options: [
{
value: 1,
label: '选项一'
},
{
value: 2,
label: '选项二'
}
]
}
},
image: {
label: '上传图片',
component: 'upload',
rules: [
{ required: true, message: '请上传图片', trigger: ['change'] }
],
prop: 'image',
field: {
action: '',
tip: '提示信息',
drag: true,
// listType: 'picture'
multiple: true,
uploadText: 'upload text'
// drag: true,
// component: {
// render: h => {
// return (
// <div>
// <i class="el-icon-upload"></i>
// <div class="el-upload__text">
// 将文件拖到此处,或<em>点击上传</em>
// </div>
// <div class="el-upload__tip" slot="tip">
// 只能上传jpg/png文件,且不超过500kb
// </div>
// </div>
// )
// }
// }
}
},
color: {
label: '颜色',
prop: 'color',
component: 'color-picker',
rules: [
{ required: true, message: '请选择颜色', trigger: ['change'] }
]
}
}
},
formItemList2 () {
return [
{
prop: 'width',
component: 'input',
field: { type: 'number' },
label: '宽度'
},
{
prop: 'height',
component: 'input',
field: { type: 'number' },
label: '高度'
},
{
prop: 'anchoredX',
component: 'input',
field: { type: 'number' },
label: '坐标X'
},
{
prop: 'anchoredY',
component: 'input',
field: { type: 'number' },
label: '坐标Y'
},
{
prop: 'rotation',
component: 'input',
field: { type: 'number' },
label: '旋转度'
},
{
prop: 'alpha',
component: 'input',
field: { type: 'number' },
label: '透明度'
},
{ prop: 'colorTint', component: 'color-picker', label: '颜色滤镜' }
]
}
},
methods: {
handleChange (data) {
this.model[data.prop] = data.value
},
handleChange2 (data) {
console.log(data)
this.model2[data.prop] = data.value
},
async submit () {
const valid = await this.$refs.form.validate()
console.log(valid)
}
}
}
</script>
<style scoped></style>
ElSchemaFormItem 示例:详见项目中的 FormItemTest.vue。
# 全局引入 el-schema-form
import ElSchemaForm from 'el-schema-form'
import 'el-schema-form/dist/el-schema-form.css'
Vue.use(ElSchemaForm)