Files
lina/src/components/AutoDataForm/utils.js
2022-11-11 17:28:52 +08:00

189 lines
5.6 KiB
JavaScript

import Vue from 'vue'
import Select2 from '@/components/FormFields/Select2'
import ObjectSelect2 from '@/components/FormFields/NestedObjectSelect2'
import NestedField from '@/components/AutoDataForm/components/NestedField'
import Switcher from '@/components/FormFields/Switcher'
import rules from '@/components/DataForm/rules'
import BasicTree from '@/components/FormFields/BasicTree'
import { assignIfNot } from '@/utils/common'
export class FormFieldGenerator {
constructor(emit) {
this.$emite = emit
this.groups = []
}
generateFieldByType(type, field, fieldMeta, fieldRemoteMeta) {
switch (type) {
case 'labeled_choice':
case 'choice':
if (!fieldRemoteMeta['read_only']) {
field.options = fieldRemoteMeta.choices
}
type = 'radio-group'
break
case 'multiple choice':
field.options = fieldRemoteMeta.choices
console.log('multiple choice: ', field.options)
type = 'checkbox-group'
break
case 'tree':
field.el.tree = fieldRemoteMeta.tree
field.component = BasicTree
break
case 'datetime':
type = 'date-picker'
field.el = {
type: 'datetime'
}
break
case 'field':
type = ''
field.component = Select2
if (fieldRemoteMeta.required) {
field.el.clearable = false
}
if (fieldRemoteMeta.child && fieldRemoteMeta.child.type === 'nested object') {
field.component = ObjectSelect2
}
break
case 'string':
type = 'input'
if (!fieldRemoteMeta['max_length']) {
field.el.type = 'textarea'
field.el.rows = 3
}
if (fieldRemoteMeta['write_only']) {
field.el.type = 'password'
}
break
case 'boolean':
type = ''
field.component = Switcher
break
case 'object_related_field':
field.component = ObjectSelect2
break
case 'm2m_related_field':
field.component = ObjectSelect2
break
case 'nested object':
type = 'nestedField'
field.component = NestedField
field.label = ''
field.labelWidth = 0
field.el.fields = this.generateNestFields(field, fieldMeta, fieldRemoteMeta)
field.el.errors = {}
break
default:
type = 'input'
break
}
// 上面重写了 type
if (type === 'radio-group') {
if (field.options.length > 4) {
type = 'select'
field.el.filterable = true
}
}
field.type = type
return field
}
generateNestFields(field, fieldMeta, fieldRemoteMeta) {
const fields = []
const nestedFields = fieldMeta.fields || []
const nestedFieldsMeta = fieldMeta.fieldsMeta || {}
const nestedFieldsRemoteMeta = fieldRemoteMeta.children || {}
for (const name of nestedFields) {
const f = this.generateField(name, nestedFieldsMeta, nestedFieldsRemoteMeta)
fields.push(f)
}
Vue.$log.debug('NestFields: ', fields)
return fields
}
generateFieldByName(name, field) {
switch (name) {
case 'email':
field.el.type = 'email'
break
case 'password':
field.el.type = 'password'
break
case 'comment':
field.el.type = 'textarea'
break
}
return field
}
generateFieldByOther(field, fieldMeta, fieldRemoteMeta) {
const filedRules = field.rules || []
if (fieldRemoteMeta.required) {
if (field.type === 'input') {
filedRules.push(rules.Required)
} else {
filedRules.push(rules.RequiredChange)
}
}
// 一些 field 有 choices 但不是 choiceField
if (fieldRemoteMeta.choices && field.type.indexOf('choice') === -1) {
field.el.choices = fieldRemoteMeta.choices
}
field.rules = filedRules
return field
}
generateField(name, fieldsMeta, remoteFieldsMeta) {
let field = { id: name, prop: name, el: {}, attrs: {}, rules: [] }
const remoteFieldMeta = remoteFieldsMeta[name] || {}
const fieldMeta = fieldsMeta[name] || {}
field.label = remoteFieldMeta.label
field.helpText = remoteFieldMeta['help_text']
field = this.generateFieldByType(remoteFieldMeta.type, field, fieldMeta, remoteFieldMeta)
field = this.generateFieldByName(name, field)
field = this.generateFieldByOther(field, fieldMeta, remoteFieldMeta)
const el = assignIfNot(fieldMeta.el || {}, field.el)
const rules = fieldMeta.rules || field.rules
field = Object.assign(field, fieldMeta)
field.el = el
field.rules = rules
_.set(field, 'attrs.error', '')
// Vue.$log.debug('Generate field: ', name, field)
return field
}
generateFieldGroup(field, fieldsMeta, remoteFieldsMeta) {
const [groupTitle, fields] = field
const _fields = this.generateFields(fields, fieldsMeta, remoteFieldsMeta)
const group = {
id: groupTitle,
title: groupTitle,
fields: _fields,
name: _fields[0].id
}
this.groups.push(group)
return _fields
}
generateFields(_fields, fieldsMeta, remoteFieldsMeta) {
let fields = []
for (let field of _fields) {
if (field instanceof Array) {
const items = this.generateFieldGroup(field, fieldsMeta, remoteFieldsMeta)
fields = [...fields, ...items]
} else if (typeof field === 'string') {
field = this.generateField(field, fieldsMeta, remoteFieldsMeta)
fields.push(field)
} else if (field instanceof Object) {
if (this.errors) {
this.errors[field.prop] = ''
}
fields.push(field)
}
}
return fields
}
}