123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <!-- 通用表单组件 -->
- <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>
- </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;
- }
- }
- },
- 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>
- .row {
- &:after {
- content: '';
- width: 0;
- height: 0;
- visibility: hidden;
- clear: both;
- display: block;
- .col {
- float: left;
- }
- }
- }
- .slot-row {
- margin-top: -22px;
- }
- .show-required-icon /deep/ .el-form-item__label {
- &:before {
- content: '*';
- color: #f56c6c;
- margin-right: 4px;
- }
- }
- </style>
|