|
@@ -1,219 +1,238 @@
|
|
|
<!-- 通用表单组件 -->
|
|
|
<template>
|
|
|
- <el-form
|
|
|
- class="no-scrollbar"
|
|
|
- :disabled="disabled"
|
|
|
- label-position="right"
|
|
|
- :label-width="labelWidth.replace(/[^0-9]/g, '') + 'px'"
|
|
|
- :rules="rules"
|
|
|
- :model="data"
|
|
|
- ref="form"
|
|
|
- status-icon
|
|
|
- >
|
|
|
- <div class="row">
|
|
|
- <div class="col" v-for="(item, index) in cols" :key="index" :style="'width:' + width">
|
|
|
- <template v-for="(row, index) in item">
|
|
|
- <el-form-item
|
|
|
- v-if="row.offShow ? false : true"
|
|
|
- :key="index"
|
|
|
- :label="row.label"
|
|
|
- :prop="row.prop || row.slot"
|
|
|
- :class="{ 'show-required-icon': row.showRequired }"
|
|
|
- :error="errors[row.prop || row.slot]"
|
|
|
- >
|
|
|
- <!-- 过滤器 -->
|
|
|
- <p v-if="row.filter">{{ ft[row.filter](data[row.prop], row.filterParams) }}</p>
|
|
|
- <!-- 过滤方法 -->
|
|
|
- <p v-else-if="row.format">{{ row.format(data[row.prop], data) }}</p>
|
|
|
- <!-- 绑定事件 -->
|
|
|
- <a v-else-if="row.click" href="javascript:;" @click="row.click"
|
|
|
- ><span>{{ data[row.prop] }}</span></a
|
|
|
- >
|
|
|
- <!-- 日期控件 -->
|
|
|
- <el-date-picker
|
|
|
- v-else-if="row.date"
|
|
|
- v-model="data[row.prop]"
|
|
|
- :value-format="row.dateFormat || 'yyyy-MM-dd'"
|
|
|
- type="date"
|
|
|
- :editable="row.editable || false"
|
|
|
- placeholder="选择日期"
|
|
|
- :class="row.widt ? 'width100':''"
|
|
|
- @change="(obj) => (row.change ? row.change(obj) : {})"
|
|
|
- ></el-date-picker>
|
|
|
- <!-- input输入框 -->
|
|
|
- <el-input
|
|
|
- v-else-if="row.input"
|
|
|
- clearable
|
|
|
- v-trim
|
|
|
- :disabled="row.disabled"
|
|
|
- v-model.trim="data[row.prop]"
|
|
|
- :placeholder="row.placeholder || '请输入' + row.label.replace(':', '').replace(':', '')"
|
|
|
- :maxlength="row.maxlength"
|
|
|
- ></el-input>
|
|
|
- <!-- textarea输入框 -->
|
|
|
- <el-input
|
|
|
- v-else-if="row.textarea"
|
|
|
- v-trim
|
|
|
- v-model.trim="data[row.prop]"
|
|
|
- type="textarea"
|
|
|
- resize="none"
|
|
|
- :rows="row.rows || 3"
|
|
|
- :placeholder="'请输入' + row.label.replace(':', '').replace(':', '')"
|
|
|
- :maxlength="row.maxlength"
|
|
|
- :show-word-limit="row.maxlength"
|
|
|
- ></el-input>
|
|
|
- <!-- 插槽 -->
|
|
|
- <slot v-else-if="row.slot" :name="row.slot"></slot>
|
|
|
- <!-- zz-select -->
|
|
|
- <zz-select
|
|
|
- v-else-if="row.options"
|
|
|
- :disabled="row.disabled"
|
|
|
- v-model="data[row.prop]"
|
|
|
- :options="row.options"
|
|
|
- :placeholder="'请选择' + row.label.replace(':', '').replace(':', '')"
|
|
|
- @change="(val) => row.change && row.change(val)"
|
|
|
- ></zz-select>
|
|
|
- <!-- zz-cache -->
|
|
|
- <zz-cache
|
|
|
- v-else-if="row.cache"
|
|
|
- :getter="row.cache"
|
|
|
- v-model="data[row.prop]"
|
|
|
- @change="(val) => row.change && row.change(val)"
|
|
|
- :labelValue="row.labelValue"
|
|
|
- ></zz-cache>
|
|
|
- <!-- 默认输出绑定的值 -->
|
|
|
- <p v-else class="ellipsis" v-tip :data-txt="data[row.prop]">{{ data[row.prop] || '-' }}</p>
|
|
|
- </el-form-item>
|
|
|
- </template>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <!-- 表单按钮插槽 -->
|
|
|
- <div v-if="$slots.btns">
|
|
|
- <el-form-item>
|
|
|
- <slot name="btns"></slot>
|
|
|
- </el-form-item>
|
|
|
- </div>
|
|
|
- <slot name="row" class="slot-row"></slot>
|
|
|
- </el-form>
|
|
|
+ <el-form
|
|
|
+ class="no-scrollbar"
|
|
|
+ :disabled="disabled"
|
|
|
+ label-position="right"
|
|
|
+ :label-width="labelWidth.replace(/[^0-9]/g, '') + 'px'"
|
|
|
+ :rules="rules"
|
|
|
+ :model="data"
|
|
|
+ ref="form"
|
|
|
+ status-icon
|
|
|
+ >
|
|
|
+ <div class="row">
|
|
|
+ <div
|
|
|
+ class="col"
|
|
|
+ v-for="(item, index) in cols"
|
|
|
+ :key="index"
|
|
|
+ :style="'width:' + width"
|
|
|
+ >
|
|
|
+ <template v-for="(row, index) in item">
|
|
|
+ <el-form-item
|
|
|
+ v-if="row.offShow ? false : true"
|
|
|
+ :key="index"
|
|
|
+ :label="row.label"
|
|
|
+ :prop="row.prop || row.slot"
|
|
|
+ :class="{ 'show-required-icon': row.showRequired }"
|
|
|
+ :error="errors[row.prop || row.slot]"
|
|
|
+ >
|
|
|
+ <!-- 过滤器 -->
|
|
|
+ <p v-if="row.filter">{{ ft[row.filter](data[row.prop], row.filterParams) }}</p>
|
|
|
+ <!-- 过滤方法 -->
|
|
|
+ <p v-else-if="row.format">{{ row.format(data[row.prop], data) }}</p>
|
|
|
+ <!-- 绑定事件 -->
|
|
|
+ <a
|
|
|
+ v-else-if="row.click"
|
|
|
+ href="javascript:;"
|
|
|
+ @click="row.click"
|
|
|
+ ><span>{{ data[row.prop] }}</span></a>
|
|
|
+ <!-- 日期控件 -->
|
|
|
+ <el-date-picker
|
|
|
+ v-else-if="row.date"
|
|
|
+ v-model="data[row.prop]"
|
|
|
+ :value-format="row.dateFormat || 'yyyy-MM-dd'"
|
|
|
+ type="date"
|
|
|
+ :editable="row.editable || false"
|
|
|
+ placeholder="选择日期"
|
|
|
+ :class="row.widt ? 'width100':''"
|
|
|
+ @change="(obj) => (row.change ? row.change(obj) : {})"
|
|
|
+ ></el-date-picker>
|
|
|
+ <!-- input输入框 -->
|
|
|
+ <el-input
|
|
|
+ v-else-if="row.input"
|
|
|
+ clearable
|
|
|
+ v-trim
|
|
|
+ :disabled="row.disabled"
|
|
|
+ v-model.trim="data[row.prop]"
|
|
|
+ :placeholder="row.placeholder || '请输入' + row.label.replace(':', '').replace(':', '')"
|
|
|
+ :maxlength="row.maxlength"
|
|
|
+ ></el-input>
|
|
|
+ <!-- textarea输入框 -->
|
|
|
+ <el-input
|
|
|
+ v-else-if="row.textarea"
|
|
|
+ v-trim
|
|
|
+ v-model.trim="data[row.prop]"
|
|
|
+ type="textarea"
|
|
|
+ resize="none"
|
|
|
+ :rows="row.rows || 3"
|
|
|
+ :placeholder="'请输入' + row.label.replace(':', '').replace(':', '')"
|
|
|
+ :maxlength="row.maxlength"
|
|
|
+ :show-word-limit="row.maxlength"
|
|
|
+ ></el-input>
|
|
|
+ <!-- 插槽 -->
|
|
|
+ <slot
|
|
|
+ v-else-if="row.slot"
|
|
|
+ :name="row.slot"
|
|
|
+ ></slot>
|
|
|
+ <!-- zz-select -->
|
|
|
+ <zz-select
|
|
|
+ v-else-if="row.options"
|
|
|
+ :disabled="row.disabled"
|
|
|
+ v-model="data[row.prop]"
|
|
|
+ :options="row.options"
|
|
|
+ :placeholder="'请选择' + row.label.replace(':', '').replace(':', '')"
|
|
|
+ @change="(val) => row.change && row.change(val)"
|
|
|
+ ></zz-select>
|
|
|
+ <!-- zz-cache -->
|
|
|
+ <zz-cache
|
|
|
+ v-else-if="row.cache"
|
|
|
+ :getter="row.cache"
|
|
|
+ v-model="data[row.prop]"
|
|
|
+ @change="(val) => row.change && row.change(val)"
|
|
|
+ :labelValue="row.labelValue"
|
|
|
+ ></zz-cache>
|
|
|
+ <!-- 默认输出绑定的值 -->
|
|
|
+ <p
|
|
|
+ v-else
|
|
|
+ class="ellipsis"
|
|
|
+ v-tip
|
|
|
+ :data-txt="data[row.prop]"
|
|
|
+ >{{ data[row.prop] || '-' }}</p>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 表单按钮插槽 -->
|
|
|
+ <div v-if="$slots.btns">
|
|
|
+ <el-form-item>
|
|
|
+ <slot name="btns"></slot>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ <slot
|
|
|
+ name="row"
|
|
|
+ class="slot-row"
|
|
|
+ ></slot>
|
|
|
+ </el-form>
|
|
|
</template>
|
|
|
<script>
|
|
|
export default {
|
|
|
- name: 'zz-form',
|
|
|
- props: {
|
|
|
- /*
|
|
|
- 字段设置:二维数组,包括label名字设置,字段绑定设置,第二维有多少个集合就有多少列
|
|
|
- [
|
|
|
- [
|
|
|
- {
|
|
|
- lable: 'label名,必须',
|
|
|
- prop: '绑定字段,必须',
|
|
|
- filter: 'vue过滤器名,',
|
|
|
- filterParams: '过滤的参数',
|
|
|
- format: '过滤方法,',
|
|
|
- click: '绑定的click事件',
|
|
|
- date: '日期输入控件',
|
|
|
- dateFormat: '日期控件的返回值格式化字符串,默认为"yyyy-MM-dd"'
|
|
|
- change: 'date改变时触发的事件'
|
|
|
- input: 'input输入框',
|
|
|
- textarea: '内容输入框',
|
|
|
- rows: '内容输入框的行数,默认4行',
|
|
|
- slot: '插槽名',
|
|
|
- }
|
|
|
- ]
|
|
|
- .
|
|
|
- .
|
|
|
- .
|
|
|
- ]
|
|
|
- */
|
|
|
- cols: {
|
|
|
- type: Array,
|
|
|
- default() {
|
|
|
- return [];
|
|
|
- }
|
|
|
- },
|
|
|
- // 绑定数据
|
|
|
- data: {
|
|
|
- type: Object,
|
|
|
- default() {
|
|
|
- return {};
|
|
|
- }
|
|
|
- },
|
|
|
- // 表单校验
|
|
|
- rules: {
|
|
|
- type: Object,
|
|
|
- default() {
|
|
|
- return {};
|
|
|
- }
|
|
|
- },
|
|
|
- // 表单标签宽度
|
|
|
- labelWidth: {
|
|
|
- type: String,
|
|
|
- default() {
|
|
|
- return '80px';
|
|
|
- }
|
|
|
- },
|
|
|
- // 错误的项目字段消息对象{prop: '错误消息'}
|
|
|
- errors: {
|
|
|
- type: Object,
|
|
|
- default() {
|
|
|
- return {};
|
|
|
- }
|
|
|
- },
|
|
|
- disabled: {
|
|
|
- type: Boolean,
|
|
|
- default() {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
+ name: 'zz-form',
|
|
|
+ props: {
|
|
|
+ /*
|
|
|
+字段设置:二维数组,包括label名字设置,字段绑定设置,第二维有多少个集合就有多少列
|
|
|
+[
|
|
|
+ [
|
|
|
+ {
|
|
|
+ lable: 'label名,必须',
|
|
|
+ prop: '绑定字段,必须',
|
|
|
+ filter: 'vue过滤器名,',
|
|
|
+ filterParams: '过滤的参数',
|
|
|
+ format: '过滤方法,',
|
|
|
+ click: '绑定的click事件',
|
|
|
+ date: '日期输入控件',
|
|
|
+ dateFormat: '日期控件的返回值格式化字符串,默认为"yyyy-MM-dd"'
|
|
|
+ change: 'date改变时触发的事件'
|
|
|
+ input: 'input输入框',
|
|
|
+ textarea: '内容输入框',
|
|
|
+ rows: '内容输入框的行数,默认4行',
|
|
|
+ slot: '插槽名',
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ .
|
|
|
+ .
|
|
|
+ .
|
|
|
+]
|
|
|
+*/
|
|
|
+ cols: {
|
|
|
+ type: Array,
|
|
|
+ default () {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
},
|
|
|
- data() {
|
|
|
- let self = this;
|
|
|
- return {
|
|
|
- ft: self.$root.$options.filters
|
|
|
- };
|
|
|
+ // 绑定数据
|
|
|
+ data: {
|
|
|
+ type: Object,
|
|
|
+ default () {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
},
|
|
|
- methods: {
|
|
|
- validate(resolve, reject) {
|
|
|
- this.$parent.errors = {};
|
|
|
- this.$refs.form.validate((valid) => {
|
|
|
- if (valid) {
|
|
|
- resolve && resolve();
|
|
|
- } else {
|
|
|
- this.$nextTick(() => {
|
|
|
- const isError = this.$el.querySelectorAll('.is-error');
|
|
|
- if (isError && isError[0]) {
|
|
|
- isError[0].querySelector('input').focus();
|
|
|
- }
|
|
|
- });
|
|
|
- reject && reject();
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- resetFields() {
|
|
|
- this.$refs.form.resetFields();
|
|
|
- },
|
|
|
- clearValidate() {
|
|
|
- this.$refs.form.clearValidate();
|
|
|
- }
|
|
|
+ // 表单校验
|
|
|
+ rules: {
|
|
|
+ type: Object,
|
|
|
+ default () {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
},
|
|
|
- computed: {
|
|
|
- width() {
|
|
|
- return 100 / this.cols.length + '%';
|
|
|
- }
|
|
|
+ // 表单标签宽度
|
|
|
+ labelWidth: {
|
|
|
+ type: String,
|
|
|
+ default () {
|
|
|
+ return '80px';
|
|
|
+ }
|
|
|
},
|
|
|
- watch: {
|
|
|
- errors(n) {
|
|
|
- const len = Object.keys(n).length;
|
|
|
- if (len) {
|
|
|
- this.$nextTick(() => {
|
|
|
- const isError = this.$el.querySelectorAll('.is-error');
|
|
|
- if (isError && isError[0]) {
|
|
|
- isError[0].querySelector('input').focus();
|
|
|
- }
|
|
|
- });
|
|
|
+ // 错误的项目字段消息对象{prop: '错误消息'}
|
|
|
+ errors: {
|
|
|
+ type: Object,
|
|
|
+ default () {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
+ },
|
|
|
+ disabled: {
|
|
|
+ type: Boolean,
|
|
|
+ default () {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data () {
|
|
|
+ let self = this;
|
|
|
+ return {
|
|
|
+
|
|
|
+ ft: self.$root.$options.filters
|
|
|
+ };
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ validate (resolve, reject) {
|
|
|
+ this.$parent.errors = {};
|
|
|
+ this.$refs.form.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ resolve && resolve();
|
|
|
+ } else {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const isError = this.$el.querySelectorAll('.is-error');
|
|
|
+ if (isError && isError[0]) {
|
|
|
+ isError[0].querySelector('input').focus();
|
|
|
}
|
|
|
+ });
|
|
|
+ reject && reject();
|
|
|
}
|
|
|
+ });
|
|
|
+ },
|
|
|
+ resetFields () {
|
|
|
+ this.$refs.form.resetFields();
|
|
|
+ },
|
|
|
+ clearValidate () {
|
|
|
+ this.$refs.form.clearValidate();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ width () {
|
|
|
+ return 100 / this.cols.length + '%';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ errors (n) {
|
|
|
+ const len = Object.keys(n).length;
|
|
|
+ if (len) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const isError = this.$el.querySelectorAll('.is-error');
|
|
|
+ if (isError && isError[0]) {
|
|
|
+ isError[0].querySelector('input').focus();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
};
|
|
|
</script>
|
|
|
<style lang='scss' scoped>
|