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)