<template> <a-form ref="formRef" :model="formModel"> <!--items--> <div class="data" style="display: flex" v-for="(d, index) in formModel.data" :key="d"> <!--op--> <div class="combination-item operation-item" v-if="remove"> <a class="op" @click="onDelete(index)"> 删除 <!--<ns-icon name="delete" size="15"/>--> </a> </div> <div class="combination-item" v-for="item in combinationOptions" :key="item.label"> <a-form-item :label="item.label" :name="['data', index, item.field]" :rules="formRules[item.field]" > <component :is="item.component" v-bind="item['componentProps']" :v-model="d[item.field]" @change="valueChanges($event, index, item.field)" /> </a-form-item> </div> </div> <!--op--> <div class="combination-item operation-item" v-if="add"> <a class="add" @click="onAdd" :class="{ disabled: leftCount == 0 }"> <!--<ns-icon name="add" size="15"/>--> 添加 <span class="op-label">{{ addName }}</span> </a> <span class="op-limit-msg" >{{ limitMsg }} <span class="leftCount">{{ leftCount }}</span></span > </div> </a-form> </template> <script> import { defineComponent, reactive, ref, toRaw } from 'vue'; export default defineComponent({ name: 'NsDiskCombination', props: { combinationOptions: { type: Array, default: () => [], }, add: { type: Boolean, default: () => false, }, addName: { type: String, default: () => '', }, // // addIcon: { // type: String, // default: () => '', // }, // remove: { type: Boolean, default: () => true, }, limitCount: Number, limitMsg: { type: String, default: () => '', }, // // tip: { // type: String, // default: () => '', // }, }, emits: ['change'], setup(props) { const { limitCount } = props; let leftCount = ref(0); leftCount.value = limitCount; const formModel = reactive({ data: [{}], }); if (formModel.data) { leftCount.value = limitCount - formModel.data.length; } let formRules = {}; props.combinationOptions.forEach((it) => { formRules[it['field']] = it['rules']; }); const onSubmit = function (thisObj) { thisObj.$refs.formRef .validate() .then(() => { console.log('values', toRaw(formModel)); }) .catch((error) => { console.log('error', error); }); }; const valueChanges = function (e, index, fieldName) { let value = e; if (typeof e == 'object' && e && e.target) { value = e.target.value; } formModel['data'][index][fieldName] = value; // onSubmit(this); }; const onAdd = () => { if (limitCount > 0 && limitCount <= formModel.data.length) { return; } formModel['data'].push(reactive({})); leftCount.value = limitCount - formModel.data.length; }; const onDelete = (index) => { formModel['data'].splice(index, 1); leftCount.value = limitCount - formModel.data.length; }; return { formModel, formRules, leftCount, valueChanges, onAdd, onDelete, }; }, }); </script> <style scoped="scoped" lang="less"> .combination-wrapper { display: flex; margin-bottom: 10px; } .combination-item { /*flex: 0 0 33%;*/ margin-right: 10px; .item-label { margin-right: 4px; } &.operation-item { .op { line-height: 30px; } .op-limit-msg { margin-left: 15px; color: #b0bec5; } .add.disabled { color: #bfbfbf; cursor: not-allowed; } } } </style>