Skip to content

Commit

Permalink
new style composite
Browse files Browse the repository at this point in the history
  • Loading branch information
szuprefix committed Sep 3, 2019
1 parent cf9c33e commit c8e8385
Show file tree
Hide file tree
Showing 25 changed files with 1,692 additions and 25 deletions.
7 changes: 7 additions & 0 deletions src/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@
-webkit-line-clamp: 1; /* 限制在一个块元素显示的文本的行数 */
-webkit-box-orient: vertical; /* 垂直排列 */
word-break: break-all; /* 内容自动换行 */
}

.el-drawer__body {
height: 100%;
box-sizing: border-box;
overflow-y: auto;
/*padding: 20px; // According to the situation*/
}
89 changes: 89 additions & 0 deletions src/components/form/Form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* Created by denishuang on 2019/8/25.
*/

import schema from 'async-validator'
import array_normalize from '../../utils/array_normalize'

export function joinErrors(errors) {
let es = {}
for (let n in errors) {
es[n] = errors[n].join("")
}
return es
}
export function defaultWidget (f) {
return f.type == 'boolean' ? 'checkbox' : (['date', 'datetime', 'time'].includes(f.type) ? f.type : ( ['integer', 'decimal'].includes(f.type) ? 'number' : 'text'))
}

export function defaultRuleType(f){
if (f.multiple) {
return 'array'
}
if (f.choices && f.choices.length > 0) {
return typeof f.choices[0][0]
}
return f.model ? 'number' : (['field', 'time'].includes(f.type) ? 'string' : (['integer', 'decimal'].includes(f.type) ? 'number' : f.type))
}

export function defaultSpan(f){
return f.widget == 'textarea' ? {xs: 24, sm: 24, md: 24, lg: 24, xl: 24} : {
xs: 24,
sm: 24,
md: 12,
lg: 12,
xl: 8
}
}
export function defaultRules(f){
let rs = []
if (f.required) {
rs.push({
type: defaultRuleType(f),
required: true,
message: `不能为空`
})
}
if (f.min_length) {
rs.push({min: f.min_length, message: `长度最小为${f.min_length}`})
}
if (f.max_length) {
rs.push({max: f.max_length, message: `长度最大为${f.max_length}`})
}
return rs
}
export function normalizeItem(i){
let a = Object.assign({}, i)
a.label = a.label || a.name
a.rules = a.rules || defaultRules(a)
a.widget = a.widget || defaultWidget(a)
let sp = a.span
a.span = sp && (typeof sp === 'number' && {xs: sp, sm: sp, md: sp, lg: sp, xl: sp} || sp) || {}
a.span = Object.assign({}, defaultSpan(a), a.span)
return a
}
export function normalizeItems(items){
return array_normalize(items,{}, normalizeItem)
}
export function getItemRules (items) {
let d = {}
Object.keys(items).forEach((i) => {
let f = items[i]
let n = f.name
let rs = d[n] = f.rules || []
rs.concat(defaultRules(f))

})
return d

}
export default {
defaultRules,
defaultRuleType,
defaultSpan,
defaultWidget,
normalizeItem,
normalizeItems,
getItemRules,
joinErrors
}
141 changes: 141 additions & 0 deletions src/components/form/Form.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<template>
<el-form ref="form" :inline="elOptions.inline" :size="elOptions.size" :model="formValue" v-if="value"
:inline-message="elOptions.inlineMessage" :hide-required-asterisk="elOptions.hideRequiredAsterisk"
label-position="elOptions.labelPosition"
:label-width="elOptions.labelWidth || elOptions.noLabel && '0px' || (!elOptions.inline && '160px')"
v-loading="loading" :element-loading-text="loading">

<slot name="header"></slot>
<el-alert :title="errors.non_field_errors" type="error" v-if="errors.non_field_errors"
:closable="false"></el-alert>
<el-row>
<template v-for="f in formItems">
<el-col :xs="f.span.xs" :sm="f.span.sm" :md="f.span.md" :lg="f.span.lg" :xl="f.span.xl"
:key="f.name" v-if="!elOptions.inline && !elOptions.oneColumn && f.widget !== 'hidden'">
<form-item :field="f" v-model="formValue" :options="options" :error="errors[f.name]"></form-item>
</el-col>
<form-item :field="f" v-model="formValue" :options="options" :error="errors[f.name]" v-else></form-item>

</template>
<slot name="submit">
<el-col :xs="elOptions.inline?12:24" :sm="elOptions.inline?8:24" :md="elOptions.inline?6:24"
:lg="elOptions.inline?4:24"
:xl="elOptions.inline?3:24" v-if="!elOptions.inline">
<el-form-item>
<actions :items="_actions"></actions>
</el-form-item>
</el-col>
<el-form-item v-else>
<actions :items="_actions"></actions>
</el-form-item>
</slot>
</el-row>
</el-form>
</template>
<script>
import server_response from '../../mixins/server_response'
import schema from 'async-validator'
import FormItem from './FormItem.vue'
import Form from './Form'
import Actions from '../layout/Actions.vue'
export default{
mixins: [
server_response
],
props: {
value: Object,
actions: Array,
items: {type: Array, default: () => []},
url: String,
method: {
type: String, default: 'post'
},
options: {
type: Object,
default: () => {
return {}
}
},
submit: Function,
submitName: {
type: String, default: '提交'
}
},
components: {FormItem, Actions},
data () {
return {
errors: {},
formValue: {},
formItems: []
}
},
created () {
this.formValue = this.value
this.formItems = Form.normalizeItems(this.items)
},
methods: {
doSubmit () {
this.$emit('beforesubmit', this.formValue)
this.loading = `正在${this.submitName}`
if (this.submit) {
return this.submit()
} else {
let action = this.method === 'post' ? this.$http.post : this.$http.put
return action(this.url, this.formValue).then(({data}) => {
return data
})
}
},
onPosted(data){
this.loading = false
this.$message({message: `${this.submitName}成功`, type: 'success'})
this.$emit("form-posted", data)
return data
},
onValidated (valid, notValidFields) {
if (valid) {
this.errors = {}
}
},
onSubmit () {
return this.$refs.form.validate().then(this.onValidated).then(this.doSubmit).then(this.onPosted).catch(e => {
if (e === false) {
this.$message({message: '表单检验未通过,请按提示修改', type: 'error'})
} else {
let error = this.onServerResponseError(e)
if (error.code === 400) {
this.errors = Form.joinErrors(error.msg)
}
}
}
)
},
},
computed: {
rules () {
return Form.getItemRules(this.formItems)
},
_actions () {
return this.actions || [{name: 'submit', label: this.submitName, do: this.onSubmit}]
},
elOptions () {
return this.options.elForm || {}
}
},
watch: {
value(val){
this.formValue = val
},
items (val) {
this.formItems = Form.normalizeItems(val)
}
}
}
</script>
<style scoped></style>
42 changes: 42 additions & 0 deletions src/components/form/FormItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<template>
<el-form-item :prop="field.name" :rules="field.rules" :label="field.label" :error="error"
:ref="field.name"
:style="options.noLabel && {} || options.itemStyle || {minWidth: '350px'}">
<template slot="label" v-if="!options.noLabel">
{{field.label}}
<el-tooltip placement="top" v-if="field.help_text">
<div slot="content" v-html="field.help_text"></div>
<i class="fa fa-info-circle bg-info"></i>
</el-tooltip>
</template>
<template slot="label" v-else><span></span></template>
<template>
<form-widget v-model="value" :field="field"></form-widget>
</template>
</el-form-item>
</template>
<script>
import FormWidget from '../widgets/FormWidget.vue'
export default{
props: {
field: Object,
value: Object,
options: {
type: Object,
default: () => {
return {}
}
},
error: String
},
data () {
return {}
},
components: {
FormWidget,
},
methods: {},
computed: {}
}
</script>
<style scoped></style>

0 comments on commit c8e8385

Please sign in to comment.