vue+ Element UI 动态生成表单及校验
第一次写博客,菜的一批,只想记录自己成长道路的一路心血,毕竟快奔三的人转行过来前端不容易啊.因为喜欢看掘金的博客,大咖很多,所以选择这里向前辈看齐.
欢迎吐槽和指正!!!
实现效果:
掘金支持的快捷键:
<el-dialog title="分配权益卡" :visible="equityVisible" width="60%" @close="$emit('close', false)" append-to-body><div class="contentBox">
<div class="content" v-for="(items, mainIndex) in allCardData" :key="mainIndex">
<div class="close" @click="handleDel(mainIndex)" v-show="allCardData.length > 1">
<span class="el-icon-remove"></span>
</div>
<div>
<el-select
v-model="selectItem.organId"
@change="queryOrganDatainfo($event, mainIndex, index)"
v-for="(selectItem, index) in items.organDtoList"
:key="index"
:placeholder="'请选择' + selectItem.name"
>
<el-option v-for="item in selectItem.list" :key="item.organId" :label="item.organName" :value="item.organId" clearable />
</el-select>
</div>
<el-form class="cardBox" :model="itemCard" v-for="(itemCard, cardIndex) in items.distributionDtoList" :key="cardIndex">
<div class="content_card">
<template class="destory">
<span class="el-icon-remove" @click="closeBtn(mainIndex, cardIndex)" v-if="items.distributionDtoList.length > 1"></span>
</template>
<el-form-item>
<el-select v-model="itemCard.packageId" @change="queryOrganChange(itemCard.packageId)" @focus="queryOrganCardData(itemCard.packageId)" placeholder="请选择权益卡">
<el-option v-for="item in secondtypeOptions" :key="item.packageId" :label="item.packageName" :value="item.packageId" />
</el-select>
</el-form-item>
<el-form-item
prop="numbers"
:rules="[
{ required: true, message: '输入不能为空', trigger: ['blur', 'change'] },
{ validator: (rule, value, callback) => validateSku(rule, itemCard.numbers, callback), trigger: ['blur', 'change'] },
{ type: 'number', message: '库存必须为数字' },
]"
>
<span>库存 {{ stock }}</span>
<el-input type="numbers" v-model.number="itemCard.numbers" placeholder="请输入权益卡数量" />
<span>剩余 {{ remain }}</span>
</el-form-item>
</div>
<em class="icon_bar"></em>
<el-link type="primary" v-if="items.distributionDtoList.length > 0" :disabled="items.distributionDtoList.length > 1" @click="addCard('cards', mainIndex)">
添加权益卡
</el-link>
</el-form>
</div>
<div>
<el-button type="primary" plain @click="addCard('items', allCardData.length)" class="assignBtn">添加分配对象 </el-button>
</div>
</div>
<span slot="footer">
<el-button @click="$emit('close', false)">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: 'DistributeEquityCard', // 分配权益卡
props: {
equityVisible: {
type: Boolean,
default: false,
},
agentData: {
type: Object,
default: () => {
return {};
},
},
},
data: () => {
return {
organId: 1,
secondOrgan: '',
threeOrgan: '',
secondtypeOptions: [],
threetypeOptions: [],
stock: '', // 库存
remain: '', // 剩余
showValidate: false, // 表单校验
allCardData: [
{
organDtoList: [
{
organId: '',
name: '省',
list: [],
},
{
organId: '',
name: '市',
list: [],
},
{
organId: '',
name: '支公司',
list: [],
},
{
organId: '',
name: '职场',
list: [],
},
],
distributionDtoList: [
{
packageId: '',
packageName: '',
numbers: '',
},
],
},
],
};
},
created() {
this.queryOrganDatainfo();
this.queryOrganCardData();
},
methods: {
// 获取职场列表
queryOrganDatainfo(val, mainIndex, index) {
// console.log(val, mainIndex, index);
if (val) {
this.organId = val;
}
this.$store.dispatch('Organize/queryTreeList', { organId: this.organId }).then((res) => {
if (res.code === 200) {
if (val && index < 3) {
this.cardData[mainIndex].organDtoList[index + 1].list = res.data;
} else {
this.cardData[0].organDtoList[0].list = res.data;
}
}
});
},
// 选择权益卡内存
queryOrganChange(val) {
for (const i of this.secondtypeOptions) {
if (i.packageId === val) {
this.stock = i.packageNumber;
}
}
},
// 获取权益卡
queryOrganCardData(val) {
// console.log('权益卡', val);
this.$store
.dispatch('healthPack/queryDistributionType', {
organId: this.agentData.organId,
})
.then((res) => {
const { code, data } = res;
if (code === 200) {
this.secondtypeOptions = data;
// console.log(data.packageNumber);
this.stock = data.packageNumber;
}
});
},
// 关闭单条权益卡
closeBtn(mainIndex, cardIndex) {
// console.log('mainIndex:', mainIndex, 'cardIndex:', cardIndex);
this.allCardData[mainIndex].distributionDtoList.forEach((v, i) => {
if (cardIndex === i) {
this.allCardData[mainIndex].distributionDtoList.splice(cardIndex, 1);
}
});
},
// 添加权益卡
addCard(str, index) {
// console.log(str, index);
// 添加分配对象
if (str === 'items') {
this.allCardData.push({
organDtoList: [
{
organId: '',
name: '省',
list: [],
},
{
organId: '',
name: '市',
list: [],
},
{
organId: '',
name: '支公司',
list: [],
},
{
organId: '',
name: '职场',
list: [],
},
],
distributionDtoList: [
{
packageId: '',
packageName: '',
numbers: '',
},
],
});
} else if (str === 'cards') {
// 添加权益卡
this.allCardData[index].distributionDtoList.push({
distributionDtoList: {
packageId: '',
packageName: '',
numbers: '',
},
});
}
},
// 删除分配对象盒子
handleDel(index) {
this.allCardData.splice(index, 1);
},
// 校验库存
validateSku(rule, value, callback) {
if (typeof value === 'string') {
this.remain = Number(this.stock);
callback(new Error('库存必须为数字'));
return;
}
if (value > Number(this.stock)) {
callback(new Error('数量不能大于库存'));
this.remain = Number(this.stock);
} else {
this.remain = Number(this.stock) - value;
callback();
}
},
// 确认按钮逻辑
confirm() {},
},
};
</script>
<style lang="scss" scoped>
.contentBox {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.content {
width: 720px;
// height: 216px;
margin-bottom: 16px;
border: 1px dashed #c7ccd9;
border-radius: 4px;
padding: 24px 40px;
position: relative;
.cardBox {
margin-top: 16px;
display: flex;
flex-direction: row;
align-items: center;
.content_card {
position: relative;
// width: 458px;
height: 56px;
border: 1px dashed #c7ccd9;
border-radius: 4px;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
padding: 0 10px;
padding-top: 20px;
}
.icon_bar {
height: 20px;
width: 1px;
margin-left: 22px;
margin-right: 22px;
background-color: #c7ccd9;
}
}
}
}
.el-icon-remove {
position: absolute;
top: 0;
right: -2px;
color: #2b6fff;
}
.close {
position: absolute;
top: 0;
right: 0;
}
.el-select {
width: 148px;
margin-left: 8px;
}
.el-input {
width: 148px;
}
/deep/.el-form-item__error {
left: 33px;
}
关键代码:
参考链接:
推荐 juejin.im/post/5d4932…
blog.csdn.net/weixin_4327…
blog.csdn.net/weixin_4104…
blog.csdn.net/Beamon__/ar…
自定义校验element官网:element.eleme.io/#/zh-CN/com…
以上是 vue+ Element UI 动态生成表单及校验 的全部内容, 来源链接: utcz.com/a/24451.html