# 二开实例:Tab页拆分+样式调整+校验 首先,我们新建一个具有若干文本框的例子,这里只讲思路,因此不设计其他字段,也不做除了必填的其他校验,我们的要求是,Tab页拆分的内容可以随便切换填写,但是**步骤表示的必须先写当前步骤才能填写后续内容**。 代码因为篇幅限制,去掉了和思路无关的部分。 ```vue ``` 可以看出,在进行二开拆分后,使用v-if、v-show配合响应式变量定义,可以轻松拆分选项卡和步骤条。这里特别注意的是,子类需要继承父类的expose方法,而正常情况下该需求无法实现,这里可以实现的原因是父类的formApi实际上就是expose的全部内容,因此我们在对外暴露的时候,只需要合并formApi就可以,对于其他组件,该方法不成立。 除了父类的内容外,我们还对外提供了切换选项卡和步骤的方法,以便校验错误的时候跳转到对应选项卡,方便修改。 接下来要手动修改原有的验证方法,打开components/Form.vue文件,也就是代码自动生成的表单。 ```javascript // 校验form 通过返回表单数据 async function validate() { let values = []; try { /* 这里就是我们的方法,这个返回值很有迷惑性,values在校验失败的时候是false,成功时候为key-value的对象,不是数组 */ values = await /*systemFormRef.value?.validate()*/ customValidate(); //添加隐藏组件 // 无关代码省略 } finally { } return values; } ``` 然后手动实现校验过程: ```javascript import { useMessage } from '/@/hooks/web/useMessage'; const { createMessage } = useMessage(); function validateField(schema, formValues) { // 这里只考虑了必填校验 如果需要其他校验自己完成 if (!schema?.componentProps?.required) { return true; } return formValues[schema.field]; } async function customValidate() { const schemas = data.formDataProps.schemas; // 组件在选项卡的第几页,实际上每个选项卡要校验的不止一个字段 const pageMapping = { wenBenKuang17845: 0, wenBenKuang46888: 1, wenBenKuang73214: 2 }; // 组件在步骤的第几页 const stepMapping = { buZhou119202: 0, buZhou212978: 1, buZhou316637: 2 }; const stepFlag = [1, 1, 1]; const formValues = systemFormRef.value.getFieldsValue(); // 这个函数可以取到formModel let pageField = null; // 这种遍历只针对主表有效,如果用了子表还要对子表校验 for (let i = 0; i < schemas.length; i++) { let schema = schemas[i]; if (validateField(schema, formValues)) { continue; } const field = schema.field; // 记下来第一个未通过的字段,后面都不需要校验了,因为要跳转过去 if (pageMapping[field] !== undefined && pageField === null) { pageField = pageMapping[field]; break; } // 记下来哪些步骤页面没填完 if (stepMapping[field] !== undefined) { stepFlag[stepMapping[field]] = 0; } } if (pageField !== null) { systemFormRef.value.onClickTab(pageField); // 手动触发一次校验函数,让红框显示出来 systemFormRef.value.validate(); return Promise.reject(false); } const strStepFlag = stepFlag.join(''); // 拼接后的步骤标志1表示填完,0表示没填完,如果出现01的序列,如101,表示步骤1填了,步骤2没填,步骤3填了 // 按照我们假定的场景,只有1填完才能填2 const valResult = strStepFlag.indexOf('01'); if (valResult > -1) { // 假设序列为101,那返回值为1,也就是步骤2没填 createMessage.warn(`步骤${valResult + 1}完成后才能填写后面内容`); systemFormRef.value.onClickTab(2); // 我们知道哪页有步骤条,所以可以写死 systemFormRef.value.onClickStep(valResult); return Promise.reject(false); } return formValues; } ```