fix(@vben/web-antdv-next): 更新表单验证逻辑,使用 Promise 处理异步校验
parent
d8c8775af2
commit
1f7d21d8e6
|
|
@ -1,4 +1,4 @@
|
|||
import type { Rule } from 'antdv-next/es/form';
|
||||
import type { FormItemProps } from 'antdv-next';
|
||||
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
|
|
@ -6,6 +6,8 @@ import { isEmpty } from '@vben/utils';
|
|||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
type FormItemRule = NonNullable<FormItemProps['rules']>[number];
|
||||
|
||||
export namespace ThingModelApi {
|
||||
/** IoT 物模型数据 */
|
||||
export interface ThingModel {
|
||||
|
|
@ -95,46 +97,42 @@ export namespace ThingModelApi {
|
|||
|
||||
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
||||
function buildRequiredNumberValidator(label: string) {
|
||||
return (_rule: any, value: any, callback: any) => {
|
||||
return (_rule: any, value: any) => {
|
||||
if (isEmpty(value)) {
|
||||
callback(new Error(`${label}不能为空`));
|
||||
return;
|
||||
return Promise.reject(new Error(`${label}不能为空`));
|
||||
}
|
||||
if (Number.isNaN(Number(value))) {
|
||||
callback(new Error(`${label}必须是数字`));
|
||||
return;
|
||||
return Promise.reject(new Error(`${label}必须是数字`));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
};
|
||||
}
|
||||
|
||||
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
||||
export function buildIdentifierLikeNameValidator(label: string) {
|
||||
return (_rule: any, value: string, callback: any) => {
|
||||
return (_rule: any, value: string) => {
|
||||
if (isEmpty(value)) {
|
||||
callback(new Error(`${label}不能为空`));
|
||||
return;
|
||||
return Promise.reject(new Error(`${label}不能为空`));
|
||||
}
|
||||
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
||||
callback(new Error(`${label}必须以中文、英文字母或数字开头`));
|
||||
return;
|
||||
return Promise.reject(
|
||||
new Error(`${label}必须以中文、英文字母或数字开头`),
|
||||
);
|
||||
}
|
||||
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
||||
callback(
|
||||
return Promise.reject(
|
||||
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (value.length > 20) {
|
||||
callback(new Error(`${label}长度不能超过 20 个字符`));
|
||||
return;
|
||||
return Promise.reject(new Error(`${label}长度不能超过 20 个字符`));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
};
|
||||
}
|
||||
|
||||
/** IoT 物模型表单校验规则 */
|
||||
export const ThingModelFormRules: Record<string, Rule[]> = {
|
||||
export const ThingModelFormRules: Record<string, FormItemRule[]> = {
|
||||
name: [
|
||||
{ required: true, message: '功能名称不能为空', trigger: 'blur' },
|
||||
{
|
||||
|
|
@ -153,7 +151,7 @@ export const ThingModelFormRules: Record<string, Rule[]> = {
|
|||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
validator: (_rule: any, value: string, callback: any) => {
|
||||
validator: (_rule: any, value: string) => {
|
||||
const reservedKeywords = [
|
||||
'set',
|
||||
'get',
|
||||
|
|
@ -164,18 +162,16 @@ export const ThingModelFormRules: Record<string, Rule[]> = {
|
|||
'value',
|
||||
];
|
||||
if (reservedKeywords.includes(value)) {
|
||||
callback(
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (/^\d+$/.test(value)) {
|
||||
callback(new Error('标识符不能是纯数字'));
|
||||
return;
|
||||
return Promise.reject(new Error('标识符不能是纯数字'));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -71,20 +71,18 @@ const rules: Record<string, Rule[]> = {
|
|||
key: [
|
||||
{ required: true, message: '流程标识不能为空', trigger: 'blur' },
|
||||
{
|
||||
validator: (_rule: any, value: string, callback: any) => {
|
||||
validator: (_rule: any, value: string) => {
|
||||
if (!value) {
|
||||
callback();
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (!/^[a-z_][-\w.$]*$/i.test(value)) {
|
||||
callback(
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
'只能包含字母、数字、下划线、连字符和点号,且必须以字母或下划线开头',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -122,23 +122,21 @@ function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
|||
}
|
||||
|
||||
/** 触发器校验 */
|
||||
function validateTriggers(_rule: any, value: any, callback: any) {
|
||||
function validateTriggers(_rule: any, value: any) {
|
||||
const error = validateSceneRuleTriggers(value);
|
||||
if (error) {
|
||||
callback(new Error(error));
|
||||
return;
|
||||
return Promise.reject(new Error(error));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/** 执行器校验 */
|
||||
function validateActions(_rule: any, value: any, callback: any) {
|
||||
function validateActions(_rule: any, value: any) {
|
||||
const error = validateSceneRuleActions(value);
|
||||
if (error) {
|
||||
callback(new Error(error));
|
||||
return;
|
||||
return Promise.reject(new Error(error));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const formRules = reactive({
|
||||
|
|
|
|||
|
|
@ -35,51 +35,44 @@ function deleteEnum(index: number) {
|
|||
}
|
||||
|
||||
/** 校验单项枚举值:必填、数字、不重复 */
|
||||
function validateEnumValue(_rule: any, value: any, callback: any) {
|
||||
function validateEnumValue(_rule: any, value: any) {
|
||||
if (isEmpty(value)) {
|
||||
callback(new Error('枚举值不能为空'));
|
||||
return;
|
||||
return Promise.reject(new Error('枚举值不能为空'));
|
||||
}
|
||||
if (Number.isNaN(Number(value))) {
|
||||
callback(new Error('枚举值必须是数字'));
|
||||
return;
|
||||
return Promise.reject(new Error('枚举值必须是数字'));
|
||||
}
|
||||
const sameCount = dataSpecsList.value.filter(
|
||||
(it) => it.value === value,
|
||||
).length;
|
||||
if (sameCount > 1) {
|
||||
callback(new Error('枚举值不能重复'));
|
||||
return;
|
||||
return Promise.reject(new Error('枚举值不能重复'));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/** 校验整个枚举列表:非空、无空项、无非法数字、无重复 */
|
||||
function validateEnumList(_rule: any, _value: any, callback: any) {
|
||||
function validateEnumList(_rule: any, _value: any) {
|
||||
if (isEmpty(dataSpecsList.value)) {
|
||||
callback(new Error('请至少添加一个枚举项'));
|
||||
return;
|
||||
return Promise.reject(new Error('请至少添加一个枚举项'));
|
||||
}
|
||||
const hasEmpty = dataSpecsList.value.some(
|
||||
(item) => isEmpty(item.value) || isEmpty(item.name),
|
||||
);
|
||||
if (hasEmpty) {
|
||||
callback(new Error('存在未填写的枚举值或描述'));
|
||||
return;
|
||||
return Promise.reject(new Error('存在未填写的枚举值或描述'));
|
||||
}
|
||||
const hasInvalidNumber = dataSpecsList.value.some((item) =>
|
||||
Number.isNaN(Number(item.value)),
|
||||
);
|
||||
if (hasInvalidNumber) {
|
||||
callback(new Error('存在非数字的枚举值'));
|
||||
return;
|
||||
return Promise.reject(new Error('存在非数字的枚举值'));
|
||||
}
|
||||
const values = dataSpecsList.value.map((item) => item.value);
|
||||
if (new Set(values).size !== values.length) {
|
||||
callback(new Error('存在重复的枚举值'));
|
||||
return;
|
||||
return Promise.reject(new Error('存在重复的枚举值'));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,53 +36,46 @@ function unitChange(unitSpecs: any) {
|
|||
}
|
||||
|
||||
/** 校验最小值 */
|
||||
function validateMin(_rule: any, _value: any, callback: any) {
|
||||
function validateMin(_rule: any, _value: any) {
|
||||
const min = Number(dataSpecs.value.min);
|
||||
const max = Number(dataSpecs.value.max);
|
||||
if (Number.isNaN(min)) {
|
||||
callback(new Error('请输入有效的数值'));
|
||||
return;
|
||||
return Promise.reject(new Error('请输入有效的数值'));
|
||||
}
|
||||
if (!Number.isNaN(max) && min >= max) {
|
||||
callback(new Error('最小值必须小于最大值'));
|
||||
return;
|
||||
return Promise.reject(new Error('最小值必须小于最大值'));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/** 校验最大值 */
|
||||
function validateMax(_rule: any, _value: any, callback: any) {
|
||||
function validateMax(_rule: any, _value: any) {
|
||||
const min = Number(dataSpecs.value.min);
|
||||
const max = Number(dataSpecs.value.max);
|
||||
if (Number.isNaN(max)) {
|
||||
callback(new Error('请输入有效的数值'));
|
||||
return;
|
||||
return Promise.reject(new Error('请输入有效的数值'));
|
||||
}
|
||||
if (!Number.isNaN(min) && max <= min) {
|
||||
callback(new Error('最大值必须大于最小值'));
|
||||
return;
|
||||
return Promise.reject(new Error('最大值必须大于最小值'));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/** 校验步长 */
|
||||
function validateStep(_rule: any, _value: any, callback: any) {
|
||||
function validateStep(_rule: any, _value: any) {
|
||||
const step = Number(dataSpecs.value.step);
|
||||
if (Number.isNaN(step)) {
|
||||
callback(new Error('请输入有效的数值'));
|
||||
return;
|
||||
return Promise.reject(new Error('请输入有效的数值'));
|
||||
}
|
||||
if (step <= 0) {
|
||||
callback(new Error('步长必须大于 0'));
|
||||
return;
|
||||
return Promise.reject(new Error('步长必须大于 0'));
|
||||
}
|
||||
const min = Number(dataSpecs.value.min);
|
||||
const max = Number(dataSpecs.value.max);
|
||||
if (!Number.isNaN(min) && !Number.isNaN(max) && step > max - min) {
|
||||
callback(new Error('步长不能大于最大值与最小值的差值'));
|
||||
return;
|
||||
return Promise.reject(new Error('步长不能大于最大值与最小值的差值'));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,12 +33,11 @@ const structFormRef = ref();
|
|||
const formData = ref<any>(buildEmptyFormData());
|
||||
|
||||
/** 校验结构体属性对象非空 */
|
||||
function validateStructSpecsList(_rule: any, _value: any, callback: any) {
|
||||
function validateStructSpecsList(_rule: any, _value: any) {
|
||||
if (isEmpty(dataSpecsList.value)) {
|
||||
callback(new Error('请至少添加一个结构体属性对象'));
|
||||
return;
|
||||
return Promise.reject(new Error('请至少添加一个结构体属性对象'));
|
||||
}
|
||||
callback();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
|
|
|
|||
Loading…
Reference in New Issue