vue+ Element UI 动态生成表单及校验

2,540 阅读3分钟

第一次写博客,菜的一批,只想记录自己成长道路的一路心血,毕竟快奔三的人转行过来前端不容易啊.因为喜欢看掘金的博客,大咖很多,所以选择这里向前辈看齐. 欢迎吐槽和指正!!!

实现效果:

掘金支持的快捷键:

    <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.cn/post/684490… blog.csdn.net/weixin_4327… blog.csdn.net/weixin_4104… blog.csdn.net/Beamon__/ar… 自定义校验element官网:element.eleme.io/#/zh-CN/com…