Skip to content

Instantly share code, notes, and snippets.

@wisetc
Created July 1, 2019 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wisetc/9ce627ce55073969c40d5f446b09e070 to your computer and use it in GitHub Desktop.
Save wisetc/9ce627ce55073969c40d5f446b09e070 to your computer and use it in GitHub Desktop.
Field definition
.trusteeship-form {
$labelWidth: 8em;
display: flex;
flex-wrap: wrap;
.suffix-text {
color: #666;
position: relative;
left: -2em;
}
.el-input {
width: 18em;
}
.el-form-item__label {
width: $labelWidth;
text-align: right;
}
._form-item {
width: 48%;
padding-right: 1.2em;
}
._hr {
width: 100%;
margin-bottom: 24px;
margin-top: -8px;
border-color: #E0E0E0;
border-width: 1px;
border-top: none;
}
.nested-field-set {
display: flex;
width: 50%;
.el-form-item__content > div {
width: 3em;
.el-input {
width: 100%;
}
}
.el-select .el-input .el-input__icon {
display: none;
}
.el-select .el-input__icon+.el-input__inner {
padding-right: 5px;
padding-left: 5px;
text-align: center;
}
.el-form-item {
display: flex;
.el-form-item__label {
width: 3em;
}
}
// 合成的字段
.nest-field-set__label {
width: $labelWidth;
padding-top: 11px;
padding-right: 12px;
line-height: 1;
text-align: right;
font-size: 14px;
color: #48576a;
}
}
.linebreak {
display: block;
width: 100%;
}
.full-width-form-item {
width: 80%;
.el-form-item__content {
width: 80%;
}
}
}
<el-form ref="form" inline class="trusteeship-form" :model="form" @change.native="handleFormChange">
<template v-for="(field, i) in fieldDefs">
<template v-if="show(field)">
<!-- 嵌套类型,手动嵌套一波 -->
<div :key="i" v-if="field.widget === 'div'" v-bind="field.rest" class="nested-field-set">
<div class="nest-field-set__label">{{field.label}}</div>
<template v-for="(nestedField, fieldK) in field.fieldSet">
<el-form-item
v-if="show(nestedField)"
:key="fieldK"
:prop="nestedField.id"
:label="nestedField.hideLabel ? '' : nestedField.label"
:rules="nestedField.rules"
:error="errors[field.id]"
>
<el-input
v-if="!nestedField.widget"
:value="form[nestedField.id]"
@input="v => { form[nestedField.id] = isNumber(nestedField.type) ? Number(v) : v }"
placeholder=""
v-bind="nestedField.rest"
>
<!-- <template v-if="nestedField.suffixText" slot="append">{{nestedField.suffixText}}</template> -->
</el-input>
<el-select
v-else-if="nestedField.widget === 'select'"
v-model="form[nestedField.id]"
placeholder=""
v-bind="nestedField.rest"
>
<el-option v-for="(opt, j) in nestedField.options" :key="j" v-bind="opt"></el-option>
</el-select>
<span class="suffix-text" v-if="nestedField.suffixText">{{nestedField.suffixText}}</span>
</el-form-item>
</template>
</div>
<template v-else-if="field.widget === 'textarea'">
<div :key="'key' + i" class="linebreak"></div>
<el-form-item
:key="i"
:prop="field.id"
:label="field.label"
:rules="field.rules"
class="full-width-form-item"
>
<el-input
v-model="form[field.id]"
type="textarea"
v-bind="field.rest"
/>
</el-form-item>
</template>
<el-form-item
v-else
:key="i"
:prop="field.id"
:label="field.hideLabel ? '' : field.label"
:rules="field.rules"
:error="errors[field.id]"
class="_form-item"
>
<el-input
v-if="!field.widget"
:value="form[field.id]"
@input="v => { form[field.id] = isNumber(field.type) ? Number(v) : v }"
v-model="form[field.id]"
placeholder=""
v-bind="field.rest"
>
<template v-if="field.suffixText" slot="append">{{field.suffixText}}</template>
</el-input>
<el-select v-else-if="field.widget === 'select'" v-model="form[field.id]">
<el-option v-for="(opt, j) in field.options" :key="j" v-bind="opt"></el-option>
</el-select>
<el-cascader
v-else-if="field.widget === 'cascader'"
v-model="form[field.id]"
:options="field.options"
v-bind="field.rest"
>
</el-cascader>
<el-radio-group v-else-if="field.widget === 'radio'" v-model="form[field.id]">
<el-radio :label="true">是</el-radio>
<el-radio :label="false">否</el-radio>
</el-radio-group>
<el-radio-group v-else-if="field.widget === 'radioGroup' && Array.isArray(field.options)" v-model="form[field.id]">
<el-radio v-for="(o, i) in field.options" :key="i" :label="o.value">{{o.label}}</el-radio>
</el-radio-group>
<el-date-picker
v-else-if="field.widget === 'date'"
v-model="form[field.id]"
v-bind="field.rest"
>
</el-date-picker>
</el-form-item>
</template>
<hr :key="'key' + i" v-if="field.close" class="_hr" />
</template>
</el-form>
import { dateStr, getCascaderLabel, getLabel, cycle2Number, isDate, getTime } from '../utils'
export default {
methods: {
getFieldObject(fieldDef, form) {
const id = fieldDef.id
let value = form[id]
let labelValue
if (typeof fieldDef.postMethod === 'function') {
value = fieldDef.postMethod(value)
}
if (typeof fieldDef.formatter === 'function' && value) {
labelValue = fieldDef.formatter(value)
} else if (isDate(fieldDef.type) && value) {
// date
value = getTime(value)
labelValue = dateStr(value)
} else if (fieldDef.type === Array && fieldDef.widget === 'date') {
// date array
if (Array.isArray(value) && value.filter(Boolean).length) {
labelValue = value.map(t => dateStr(t)).join(' 至 ')
} else {
value = null
labelValue = 'N/A'
}
} else if (fieldDef.widget === 'cascader') {
labelValue = getCascaderLabel(value, fieldDef.options)
} else if (fieldDef.options && Array.isArray(fieldDef.options)) {
labelValue = getLabel(value, fieldDef.options)
}
return {
label: fieldDef.label,
id,
value,
labelValue,
hidden: fieldDef.hidden,
}
}
},
}
enum Widget {
div,
radio,
radioGroup,
select,
date
}
interface Option {
label: string;
value: string;
}
interface Field {
label: string;
hideLabel?: boolean;
id: string;
type: Function;
defaultValue?: any;
belongsTo?: string;
widget?: Widget;
options?: Option[];
fetchMethod?: () => Promise<any>;
delayFetchMethod?: () => Promise<any>;
suffixText?: String;
postMethod?(val: any): any;
fieldSet?: Field[];
close?: boolean;
rest?: object;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment