vue+element 循环创建表单,并有一定的验证规则

201 阅读2分钟

场景

  • 后端返回一个jSON数据,根据这个数据循环创建表单

  • 数据如下

const list = [
    {
        "id": 1,
        "name": "ecs 告警清理策略(条)",
        "mode": "count",
        "max": 100000,
        "deception": null,
        "rangeInfo": {
            "max": 100000,
            "min": 1,
            "desc": "范围1-100000"
        }
    },
    {
        "id": 2,
        "name": "系统日志清理策略(条)",
        "mode": "count",
        "max": 1000000,
        "deception": null,
        "rangeInfo": {
            "max": 1000000,
            "min": 1,
            "desc": "范围1-1000000"
        }
    },
    {
        "id": 3,
        "name": "访客数据清理策略(天)",
        "mode": "time",
        "max": 7,
        "deception": null,
        "rangeInfo": {
            "max": 30,
            "min": 1,
            "desc": "范围1-30"
        }
    },
    {
        "id": 4,
        "name": "抓拍数据清理策略(条)",
        "mode": "count",
        "max": 3000000,
        "deception": null,
        "rangeInfo": {
            "max": 3000000,
            "min": 1,
            "desc": "范围1-3000000"
        }
    },
    {
        "id": 5,
        "name": "车通行清理策略(天)",
        "mode": "time",
        "max": 7,
        "deception": null,
        "rangeInfo": {
            "max": 30,
            "min": 1,
            "desc": "范围1-30"
        }
    },
    {
        "id": 6,
        "name": "人通行清理策略(天)",
        "mode": "time",
        "max": 7,
        "deception": null,
        "rangeInfo": {
            "max": 30,
            "min": 1,
            "desc": "范围1-30"
        }
    },
    {
        "id": 10001,
        "name": "是否自动显示告警信息",
        "mode": null,
        "max": 1,
        "deception": "提示:控制前台信息展示平台中的【数字驾驶舱】页面上,摄像机发生告警时是否自动弹出告警简要信息框",
        "rangeInfo": null
    },
    {
        "id": 10000,
        "name": "自动消失时间(秒)",
        "mode": "秒",
        "max": 60,
        "deception": "提示:设置告警简要信息框显示后,多长时间自动消失。设置范围1-60秒。",
        "rangeInfo": null
    }
]
  • 循环渲染处理不难,我当时困在渲染出来后的每一项验证规则不生效,生效错误

  • 项目代码如下,configList就是上面的模拟数据List

<template>
    <div class="content">
        <div class="alarm">
            <el-form :model="form" :rules="rules" label-suffix=":" ref="alarmForm" class="forms">
                <el-form-item
                    v-for="(item, index) of Object.keys(form)"
                    :key="index"
                    :label="getLabel(item)"
                    :prop="item"
                >
                    <el-radio-group v-model.trim="form[item]" v-if="item == 'radio'">
                        <el-radio :label="1"></el-radio>
                        <el-radio :label="0"></el-radio>
                    </el-radio-group>
                    <el-input v-else type="number" v-model.trim="form[item]" maxlength="64" clearable></el-input>
                    <span class="tips">{{ getDes(item) }}</span>
                </el-form-item>
            </el-form>
            <div class="bigTips">提示:参数设置后,重新登录方可生效</div>
            <div class="btnGroup">
                <el-button type="primary" @click="save">{{ $t('public.save') }}</el-button>
            </div>
        </div>
    </div>
</template>
<script>

export default {
    data() {
        return {
            form: {},
            rules: {},
            configList: [],
            configListCpoy: [],
  
        }
    },
 
    mounted() {
        this.getList()
    },
    methods: {
        async getList() {
            const res = await this.$api.addParameter({ model: 'alarm' })
            if (res.resultCode != 0) return

            this.formKey = this.getKey()
            this.configList = res?.configList ?? []
            this.configListCpoy = this.configList.map((v) => {
                return {
                    ...v,
                    key: v.id == 10001 ? 'radio' : this.getKey(),
                }
            })
            this.setForm()
            this.setRules()
        },
        save() {
            this.$refs.alarmForm.validate((valid) => {
                if (!valid) return

                const params = {
                    model: 'alarm',
                    dataList: this.configListCpoy.map((v) => {
                        return {
                            id: v.id,
                            max: +this.form[v.key],
                        }
                    }),
                }
                this.$api.updateParameter(params).then((res) => {
                    if (res.resultCode == 0) {
                        this.$message({
                            type: 'success',
                            message: 'OK',
                        })
                        this.getList()
                    }
                })
            })
        },
        getKey() {
            const arr = [
                'a',
                'b',
                'c',
                'd',
                'e',
                'f',
                'g',
                'h',
                'i',
                'j',
                'k',
                'l',
                'm',
                'n',
                'o',
                'p',
                'q',
                'r',
                's',
                't',
                'u',
                'v',
                'w',
                'x',
                'y',
                'z',
            ]
            const s1 = arr[Math.floor(Math.random() * 26)]
            const s2 = arr[Math.floor(Math.random() * 26)]
            const s3 = arr[Math.floor(Math.random() * 26)]
            const s4 = arr[Math.floor(Math.random() * 26)]
            const res = `${s1}${s2}${s3}${s4}`
            return res
        },
        setForm() {
            this.form = {}
            this.configListCpoy.forEach((v) => {
                this.$set(this.form, v.key, v.max)
            })
        },
        setRules() {
            this.configListCpoy.forEach((v) => {
                if (v.id != 10001) {
                    const min = v?.rangeInfo?.min ? v.rangeInfo.min : -Infinity
                    const max = v?.rangeInfo?.max ? v.rangeInfo.max : Infinity
                    this.$set(this.rules, v.key, [
                        {
                            required: true,
                            trigger: 'blur',
                            validator: (rule, value, callback) => {
                                if (value === '') {
                                    callback(new Error('此项为必填项'))
                                } else if (parseInt(value) < min || parseInt(value) > max) {
                                    callback(new Error('请输入范围内的数值'))
                                } else {
                                    callback()
                                }
                            },
                        },
                    ])
                } else {
                    this.$set(this.rules, v.key, [
                        {
                            required: true,
                            message: '此项为必填项',
                        },
                    ])
                }
            })
        },
        getLabel(key) {
            const cur = this.configListCpoy.find((v) => v.key == key)
            return cur?.name || ''
        },
        getDes(key) {
            const cur = this.configListCpoy.find((v) => v.key == key)
            return cur?.rangeInfo?.desc || ''
        },
    },
}
</script>
<style lang="scss" scoped>
@import './AlarmParam.scss';
</style>

  • 渲染效果如下

image.png