在最近开发的功能的过程中,遇到一个很复杂的表单;外层一个大表单;里面有一项是动态添加的,而且内嵌一个表单。每一项还有校验规则;如下图
记录一下调试结果。 无论多少层form, 注意几个事项;
form的model/ref; form_item的prop这个关系到,校验作用具体那个框框
数据还一个json,组件只是渲染UI,逐步分解就好了。
直接上完整代码,如下:
<!--定义巡检项-->
<template>
<div class="drawer__content">
<el-form :model="formUp" ref="formUp">
<el-form-item
label="巡检项名称"
prop="name"
:label-width="formLabelWidth"
:rules="[
{ required: true, message: '请输入巡检项名称', trigger: 'blur' },
]"
>
<el-input
v-model="formUp.name"
autocomplete="off"
maxlength="64"
></el-input>
</el-form-item>
<el-form-item
label="巡检项描述"
prop="description"
:label-width="formLabelWidth"
:rules="[
{ required: false, message: '请输入巡检项描述', trigger: 'blur' },
]"
>
<el-input
v-model="formUp.description"
type="textarea"
autocomplete="off"
maxlength="200"
show-word-limit
></el-input>
</el-form-item>
<el-form-item
label="巡检项登录用户"
prop="itemLevels"
:label-width="formLabelWidth"
:rules="[
{
required: true,
message: '请选择巡检项登录用户',
trigger: 'change',
},
]"
>
<el-checkbox-group v-model="formUp.itemLevels">
<el-checkbox
label="root"
name="type"
:disabled="formUp.itemLevels.includes('oracle')"
></el-checkbox>
<el-checkbox
label="administrator"
name="type"
class="borderRight"
:disabled="formUp.itemLevels.includes('oracle')"
></el-checkbox>
<el-checkbox
label="oracle"
name="type"
:disabled="
formUp.itemLevels.includes('root') ||
formUp.itemLevels.includes('administrator')
"
></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item
label="巡检项分类"
prop="itemCategoryId"
:label-width="formLabelWidth"
:rules="[
{ required: false, message: '请选择巡检项分类', trigger: 'change' },
]"
>
<el-cascader
v-model="formUp.itemCategoryId"
clearable
:filterable="true"
:props="{
value: 'id',
label: 'name',
children: 'children',
emitPath: 'false',
checkStrictly: true,
}"
:options="folderData"
:show-all-levels="false"
>
<template slot-scope="{ node, data }">
<span>{{ data.name }}</span>
</template>
</el-cascader>
</el-form-item>
<el-form-item
label="资源分类"
prop="resourceCateId"
:label-width="formLabelWidth"
:rules="[
{ required: true, message: '请选择资源分类', trigger: 'change' },
]"
>
<el-select
v-model="formUp.resourceCateId"
placeholder="请选择资源分类"
@change="getTemplateArr"
:disabled="setDialogType == 'edit'"
>
<el-option
v-for="resourceItem in resourceArr"
:key="resourceItem.id"
:label="resourceItem.name"
:value="resourceItem.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label="结果判定"
prop="resultCheck"
:label-width="formLabelWidth"
>
<el-switch
v-model="formUp.resultCheck"
active-text="有"
inactive-text="无"
>
</el-switch>
</el-form-item>
<el-form-item :label-width="formLabelWidth">
<div slot="label">
<span
><i style="color: #f56c6c; margin-right: 4px">*</i
>能力模板及表达式配置</span
>
</div>
<div class="addForm">
<el-button
type="primary"
icon="el-icon-circle-plus"
@click="addTemplate(formUp.templateConfigList)"
>增加能力模板</el-button
>
</div>
<div class="formContent">
<div
class="formItem"
v-for="(itemForm, indexA) in formUp.templateConfigList"
:key="indexA"
>
<h4>
能力模板{{ indexA + 1 }}
<i
style="margin-left: 10px; font-size: 16px; cursor: pointer"
class="el-icon-delete-solid"
v-if="indexA > 0"
@click="deleteTemplate(indexA)"
></i>
</h4>
<el-form :model="itemForm" :ref="'formDown' + indexA">
<!-- 选择能力模板 -->
<el-form-item
label="选择能力模板"
prop="abilityTemplateId"
:label-width="formLabelWidthB"
:rules="[
{
required: true,
message: '请选择能力模板',
trigger: 'change',
},
]"
>
<el-select
v-model="itemForm.abilityTemplateId"
placeholder="请选择能力模板"
@change="
changeItemTemplate(itemForm.abilityTemplateId, itemForm)
"
>
<el-option
v-for="(a, index1) in powerArr"
:key="index1"
:label="a.name"
:value="a.id"
></el-option>
</el-select>
</el-form-item>
<!-- 数据库部署模式 -->
<!-- <el-form-item
v-if="formUp.resultCheck"
label="数据库部署模式"
prop="dbDeployType"
:label-width="formLabelWidthB"
:rules="[
{
required: false,
message: '请选择数据库部署模式',
trigger: 'change',
},
]"
>
<el-select
v-model="itemForm.dbDeployType"
placeholder="请选择数据库部署模式"
>
<el-option
v-for="(b, index2) in schemaArr"
:key="index2"
:label="b.name"
:value="b.id"
></el-option>
</el-select>
</el-form-item> -->
<!-- 表达式配置 -->
<el-form-item
v-if="formUp.resultCheck"
:label-width="formLabelWidthB"
>
<div slot="label">
<span
><i style="color: #f56c6c; margin-right: 4px">*</i
>表达式配置</span
>
<el-tooltip class="item" effect="dark" placement="top-start">
<div slot="content">
<p>1. 符合下述表达式时则判定巡检结果正常;</p>
<p>2. 多个表达式时默认按”逻辑与“的关系处理;</p>
</div>
<i class="el-icon-question"></i>
</el-tooltip>
</div>
<div class="addExpression">
<el-button
type="primary"
icon="el-icon-circle-plus"
@click="itemFormAddRules(itemForm)"
>添加表达式</el-button
>
</div>
<div
class="flexBox"
v-for="(m, indexM) in itemForm.resultCheckRule.rules"
:key="indexM"
>
<div class="expressionItem">
<el-form-item
:prop="`resultCheckRule.rules.` + indexM + '.ruleParam'"
:rules="[
{
validator: (rule, value, callback) =>
checkRuleParam(
rule,
value,
callback,
itemForm.resultCheckRule.rules
),
trigger: 'change',
},
]"
>
<el-select
v-model="m.ruleParam"
placeholder="巡检项参数"
clearable
>
<el-option
v-for="(c, index3) in itemForm.ruleParamArr"
:key="index3"
:label="`${c.value}(${c.label})`"
:value-key="c.label"
:value="c"
></el-option>
</el-select>
</el-form-item>
</div>
<div class="expressionItem">
<el-form-item
:prop="
`resultCheckRule.rules.` + indexM + '.ruleOperator'
"
:rules="[
{
required: true,
message: '请选择数据库部署模式',
trigger: 'change',
},
]"
>
<el-select
v-model="m.ruleOperator"
placeholder="表达式符号"
clearable
>
<el-option
v-for="(d, index4) in itemForm.ruleOperator"
:key="index4"
:label="d.label"
:value-key="d.label"
:value="d"
></el-option>
</el-select>
</el-form-item>
</div>
<div class="expressionItem">
<el-form-item
:prop="`resultCheckRule.rules.` + indexM + '.ruleValue'"
:rules="[
{
required: true,
message: '请选择表达式符号',
trigger: 'change',
},
]"
>
<el-input
v-model="m.ruleValue"
placeholder="请输入参数值"
></el-input>
</el-form-item>
</div>
<div class="delBtn">
<i
v-if="indexM > 0"
class="el-icon-delete-solid"
@click="itemFormDeleteRules(itemForm, indexM)"
></i>
</div>
</div>
</el-form-item>
</el-form>
</div>
</div>
</el-form-item>
</el-form>
<div class="drawer__footer">
<el-button @click="cancelForm">取 消</el-button>
<el-button
type="primary"
@click="submitForm(setDialogType)"
:loading="loading"
>{{ loading ? "提交中 ..." : "确 定" }}</el-button
>
</div>
</div>
</template>
<script>
import * as requestMethod from "@/api/inspection/inspectionType/index.js";
export default {
props: {
folderData: {
type: Array,
default: () => [],
},
setDialogType: {
type: String,
default: () => "",
},
setDialogData: {
type: Object,
default: () => {},
},
},
data() {
let checkExpression = (rule, value, callback, indexA) => {
console.log("修改的能力模板内容", value);
if (value == "") {
callback("修改的能力模板内容");
} else {
callback();
}
};
let checkRuleParam = (rule, value, callback, rulesArr) => {
console.log("修改的能力模板内容", value);
console.log("rulesArr", rulesArr);
// 校验是否有重复的
let hasRuleParamlength = rulesArr.filter(
(a) => a.ruleParam.label == value.label
).length;
if (value == "") {
callback("请选择脚本参数");
} else if (hasRuleParamlength > 1) {
callback("脚本参数不能重复");
} else {
callback();
}
};
return {
checkExpression,
checkRuleParam, // 校验表达式参数
loading: false,
// 上班部门表单
formUp: {
name: "", // 名称
description: "", // 描述
itemCategoryId: "", // 巡检项分类
resourceCateId: "", // 资源分类
itemLevels: [], // 用户
resultCheck: true, // 结果判定,默认flase
templateConfigList: [
{
abilityTemplateId: "", // 选择能力模板
// 数据库部署模式,参数去掉了
// dbDeployType: "",
resultCheckRule: {
// 表达式配置
rules: [
{
ruleParam: {
label: "", //
value: "", //
}, // 巡检项参数
ruleOperator: {
label: "",
value: "",
}, // 表达式符合
ruleValue: "", // 参数值
},
], // 表达式配置
},
ruleParamArr: [], // 巡检项参数,由选择的能力模板决定
ruleOperator: [], // 巡检参数表达式数据源
},
],
},
formLabelWidth: "170px",
formLabelWidthB: "128px", // 循环表单项宽度
timer: null,
// 数据源部分
resourceArr: [], // 资源分类数据源
powerArr: [], // 能力模板数据源
schemaArr: [], // 数据库部署模式数据源
// parameterArr: [], // 巡检项参数,数据源
// 巡检项分类展示取参
showProps: {
value: "id",
label: "name",
},
};
},
created() {
// 此处接口获取数据源,下面模拟数据
this.getResourceArr();
},
mounted() {
console.log("row", this.setDialogData);
if (this.setDialogType == "edit") {
let {
name,
description,
itemCategoryId,
resourceCateId,
itemLevels,
resultCheck,
templateConfigList,
} = this.setDialogData;
this.formUp.name = name; // 名称
this.formUp.description = description; // 描述
this.formUp.itemCategoryId = [itemCategoryId]; // 巡检项分类
this.formUp.resourceCateId = resourceCateId; // 资源分类
this.formUp.itemLevels = itemLevels; // 用户
this.formUp.resultCheck = resultCheck; // 结果判定,默认flase
this.formUp.templateConfigList = templateConfigList.map((a) => {
let objTemplateConfig = {
abilityTemplateId: a.abilityTemplateId,
abilityTemplateName: a.abilityTemplateName,
resultCheckRule: a.resultCheckRule,
ruleParamArr: [], // 巡检项参数,由选择的能力模板决定
ruleOperator: [], // 巡检参数表达式数据源
};
return objTemplateConfig;
});
// 根据资源分类,查询模板参数数据源,处理配置templateConfigList每项的ruleParamArr/ruleOperator
this.editFormUpTemplateList(resourceCateId); //
}
// 部署模式固定数据
// this.schemaArr = [
// { id: "RAC", name: "RAC" },
// { id: "Single", name: "单节点" },
// { id: "PowerHA", name: "powerHA" },
// ];
},
methods: {
// 获取资源分类
getResourceArr() {
requestMethod.getResoureConfig("get").then((res) => {
if (res.status || res.code == 200) {
this.resourceArr = res.data;
}
});
},
// 资源分类修改,获取对应的能力模板数据
getTemplateArr(e) {
console.log("选择的资源分类", e);
let parmas = {
resourceCateId: e,
};
requestMethod.getTemplateConfig("get", parmas).then((res) => {
if (res.status || res.code == 200) {
this.powerArr = res.data;
}
});
},
editFormUpTemplateList(id) {
let parmas = {
resourceCateId: id,
};
requestMethod.getTemplateConfig("get", parmas).then((res) => {
let that = this;
if (res.status || res.code == 200) {
this.powerArr = res.data;
let zzPowerArr = res.data;
// 处理现有的数据
this.formUp.templateConfigList = this.formUp.templateConfigList.map(
(m) => {
zzPowerArr.map((n) => {
if (n.id == m.abilityTemplateId) {
m.ruleParamArr = that.objToArray(n.downParaStruct); // 巡检项参数,由选择的能力模板决定
m.ruleOperator = n.ruleOperators; // 巡检参数表达式数据源
}
return true;
});
return m;
}
);
}
});
},
// 当前能力模板的,模板修改,查询对应的表达式参数以及数据源
changeItemTemplate(abilityTemplateId, itemForm) {
console.log("templateId", abilityTemplateId);
console.log("itemForm", itemForm);
requestMethod.getTemplateKeys("get", abilityTemplateId).then((res) => {
if (res.status || res.code == 200) {
itemForm.ruleParamArr = this.objToArray(res.data.downParaStruct); // 当前模板的巡检参数数据源
itemForm.ruleOperator = res.data.ruleOperators; // 当前模板表达式数据源
}
});
},
// 把对象属性参数,转成数组对象
objToArray(obj) {
return Object.entries(obj).map(([name, value]) => ({
label: value.note,
value: name,
type: value.valueType,
// required: value.required,
}));
},
// 能力模板新增表达式
itemFormAddRules(itemForm) {
let obj = {
ruleParam: {
label: "", //
value: "", //
}, // 巡检项参数
ruleOperator: {
label: "",
value: "",
}, // 表达式符合
ruleValue: "", // 参数值
};
itemForm.resultCheckRule.rules = [...itemForm.resultCheckRule.rules, obj];
},
// 能力模板表单删除表达式
itemFormDeleteRules(itemForm, indexM) {
itemForm.resultCheckRule.rules.splice(indexM, 1);
},
// 新增大块的能力模板
addTemplate(templateConfigList) {
let templateObject = {
abilityTemplateId: "", // 选择能力模板
// dbDeployType: "", // 数据库部署模式
resultCheckRule: {
// 表达式配置
rules: [
{
ruleParam: {
label: "", //
value: "", //
}, // 巡检项参数
ruleOperator: {
label: "",
value: "",
}, // 表达式符合
ruleValue: "", // 参数值
},
], // 表达式配置
},
ruleParamArr: [], // 巡检项参数,由选择的能力模板决定
ruleOperator: [], // 巡检参数表达式数据源
};
this.formUp.templateConfigList = [...templateConfigList, templateObject];
},
// 删除大块的能力模板
deleteTemplate(indexA) {
this.formUp.templateConfigList.splice(indexA, 1);
},
// 取消
cancelForm() {
this.loading = false;
this.$emit("closeSetDialog");
},
// 确定
submitForm(type) {
this.$refs["formUp"].validate((valid) => {
if (valid) {
// 把itemCategoryId重数组转成字符串
this.formUp.itemCategoryId = this.formUp.itemCategoryId.join();
let vo = this.formUp;
let xjxId = type == "edit" ? this.setDialogData.id : ""; // 巡检项Id
if (type == "add") {
requestMethod.setInspection("post", vo).then((res) => {
if (res.status) {
this.$message.success("定义巡检项成功");
// 按照左侧数据筛选,重新获取列表数据
this.$emit("closeSetDialog", "getList");
}
});
} else if (type == "edit") {
requestMethod.editInspection("put", vo, xjxId).then((res) => {
if (res.status) {
this.$message.success("配置巡检项成功");
// 按照左侧数据筛选,重新获取列表数据
this.$emit("closeSetDialog", "getList");
}
});
}
} else {
return false;
}
});
},
},
};
</script>
<style lang='less' scoped>
.drawer__content {
padding: 15px;
display: flex;
flex-direction: column;
height: 100%;
overflow: auto;
form {
flex: 1;
}
.borderRight {
border-right: 1px solid #d9dde0;
padding-right: 30px;
}
}
.drawer__footer {
text-align: right;
border-top: 1px solid #e7edf3;
padding-top: 10px;
}
// 能力模板样式处理
.formContent {
margin-top: 10px;
.formItem {
border: 1px solid #e7edf3;
padding: 0 10px;
h4 {
border-bottom: 1px solid #e7edf3;
margin-bottom: 15px;
}
.addExpression {
margin-bottom: 15px;
}
.flexBox {
display: flex;
align-items: flex-start;
.expressionItem {
flex: 1;
margin-right: 10px;
}
.delBtn {
width: 30px;
font-size: 16px;
cursor: pointer;
}
}
}
}
</style>