mirror of
https://github.com/jumpserver/lina.git
synced 2026-01-15 14:24:39 +00:00
189 lines
5.6 KiB
JavaScript
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
|
|
}
|
|
}
|