@veltra/utils 1.1.36 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -5
- package/dist/index.js +1 -2
- package/dist/types/component-common.d.ts +25 -1
- package/dist/types/form-context.d.ts +13 -5
- package/dist/types/form-context.js +2 -2
- package/dist/types/form-context.js.map +1 -1
- package/dist/types/index.d.ts +3 -4
- package/package.json +1 -1
- package/src/index.ts +0 -2
- package/src/types/component-common.ts +26 -0
- package/src/types/form-context.ts +17 -6
- package/src/types/index.ts +0 -1
- package/dist/form/validate.d.ts +0 -33
- package/dist/form/validate.js +0 -197
- package/dist/form/validate.js.map +0 -1
- package/dist/types/utils/form/validate.d.ts +0 -34
- package/src/form/validate.ts +0 -278
- package/src/types/utils/form/validate.ts +0 -33
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,6 @@ import { getHighlightChunks } from "./dom/highlight.js";
|
|
|
6
6
|
import { getNearestScrollParent, getScrollParents, scrollIntoContainerView } from "./dom/position.js";
|
|
7
7
|
import { removeStyles, setStyles, withUnit } from "./dom/style.js";
|
|
8
8
|
import { zIndex } from "./dom/z-index.js";
|
|
9
|
-
import { Data, PresetRule, ValidateRule, ValidatorConfig } from "./types/utils/form/validate.js";
|
|
10
|
-
import { Validator } from "./form/validate.js";
|
|
11
9
|
import { createIncrease } from "./helper/create-increase.js";
|
|
12
10
|
import { createToggle } from "./helper/create-toggle.js";
|
|
13
11
|
import { AnimeConfig, Tween, TweenConfig } from "./helper/tween.js";
|
|
@@ -15,6 +13,6 @@ import { nextFrame } from "./helper/frame.js";
|
|
|
15
13
|
import { extractNormalVNodes, isComment, isFragment, isTemplate, isTextNode, shallowComputed } from "./helper/vue.js";
|
|
16
14
|
import { middleProxy } from "./reactive/proxy.js";
|
|
17
15
|
import { DeconstructValue, DefineEvent, Index, Null, RenderReturn, Undef } from "./types/helper.js";
|
|
18
|
-
import { BreakpointName, ColorType, ComponentProps, ComponentSize, FormComponentProps, PropsWithServerQuery } from "./types/component-common.js";
|
|
19
|
-
import { FormContextModel, FormContextProps, injectFormContext, provideFormContext } from "./types/form-context.js";
|
|
20
|
-
export { AnimeConfig, BEM, BEMFactory, BreakpointName, CLS_PREFIX, ColorType, ComponentProps, ComponentSize,
|
|
16
|
+
import { BreakpointName, ColorType, ComponentProps, ComponentSize, FormComponentProps, PresetRule, PropsWithServerQuery, ValidateRule } from "./types/component-common.js";
|
|
17
|
+
import { FormContextModel, FormContextProps, FormFieldItem, injectFormContext, provideFormContext } from "./types/form-context.js";
|
|
18
|
+
export { AnimeConfig, BEM, BEMFactory, BreakpointName, CLS_PREFIX, ColorType, ComponentProps, ComponentSize, DeconstructValue, DefineEvent, ExpandTransition, ExpandTransitionOptions, FORM_EMPTY_CONTENT, FormComponentProps, FormContextModel, FormContextProps, FormFieldItem, Index, NAME_SPACE, Null, PresetRule, PropsWithServerQuery, RenderReturn, Tween, TweenConfig, Undef, ValidateRule, addClass, bem, createIncrease, createToggle, extractNormalVNodes, getHighlightChunks, getNearestScrollParent, getScrollParents, injectFormContext, isComment, isFragment, isTemplate, isTextNode, makeBEM, middleProxy, nextFrame, provideFormContext, removeClass, removeStyles, scrollIntoContainerView, setStyles, shallowComputed, withUnit, zIndex };
|
package/dist/index.js
CHANGED
|
@@ -7,11 +7,10 @@ import { getHighlightChunks } from "./dom/highlight.js";
|
|
|
7
7
|
import { getNearestScrollParent, getScrollParents, scrollIntoContainerView } from "./dom/position.js";
|
|
8
8
|
import { createIncrease } from "./helper/create-increase.js";
|
|
9
9
|
import { zIndex } from "./dom/z-index.js";
|
|
10
|
-
import { Validator } from "./form/validate.js";
|
|
11
10
|
import { createToggle } from "./helper/create-toggle.js";
|
|
12
11
|
import { Tween } from "./helper/tween.js";
|
|
13
12
|
import { nextFrame } from "./helper/frame.js";
|
|
14
13
|
import { extractNormalVNodes, isComment, isFragment, isTemplate, isTextNode, shallowComputed } from "./helper/vue.js";
|
|
15
14
|
import { middleProxy } from "./reactive/proxy.js";
|
|
16
15
|
import { injectFormContext, provideFormContext } from "./types/form-context.js";
|
|
17
|
-
export { CLS_PREFIX, ExpandTransition, FORM_EMPTY_CONTENT, NAME_SPACE, Tween,
|
|
16
|
+
export { CLS_PREFIX, ExpandTransition, FORM_EMPTY_CONTENT, NAME_SPACE, Tween, addClass, bem, createIncrease, createToggle, extractNormalVNodes, getHighlightChunks, getNearestScrollParent, getScrollParents, injectFormContext, isComment, isFragment, isTemplate, isTextNode, makeBEM, middleProxy, nextFrame, provideFormContext, removeClass, removeStyles, scrollIntoContainerView, setStyles, shallowComputed, withUnit, zIndex };
|
|
@@ -8,6 +8,28 @@ interface ComponentProps {
|
|
|
8
8
|
/** 组件尺寸 */
|
|
9
9
|
size?: ComponentSize;
|
|
10
10
|
}
|
|
11
|
+
type PresetRule = 'email' | 'phone' | 'num' | 'url' | 'idCard';
|
|
12
|
+
/** 字段校验规则 */
|
|
13
|
+
interface ValidateRule {
|
|
14
|
+
/** 是否必填 */
|
|
15
|
+
required?: boolean | string;
|
|
16
|
+
/** 长度单位 */
|
|
17
|
+
length?: number | [number, string];
|
|
18
|
+
/** 最小值 */
|
|
19
|
+
min?: number | [number, string];
|
|
20
|
+
/** 最大值 */
|
|
21
|
+
max?: number | [number, string];
|
|
22
|
+
/** 最小长度 */
|
|
23
|
+
minLen?: number | [number, string];
|
|
24
|
+
/** 最大长度 */
|
|
25
|
+
maxLen?: number | [number, string];
|
|
26
|
+
/** 匹配 */
|
|
27
|
+
match?: RegExp | [RegExp, string] | string;
|
|
28
|
+
/** 预设 */
|
|
29
|
+
preset?: PresetRule;
|
|
30
|
+
/** 自定义校验 */
|
|
31
|
+
validator?: (value: any, data: Record<string, any>) => Promise<string> | string;
|
|
32
|
+
}
|
|
11
33
|
/** 表单组件通用属性 */
|
|
12
34
|
interface FormComponentProps extends ComponentProps {
|
|
13
35
|
/** 在表单控件内时的提示 */
|
|
@@ -24,6 +46,8 @@ interface FormComponentProps extends ComponentProps {
|
|
|
24
46
|
disabled?: boolean;
|
|
25
47
|
/** 是否只读 */
|
|
26
48
|
readonly?: boolean;
|
|
49
|
+
/** 校验规则 */
|
|
50
|
+
rules?: ValidateRule;
|
|
27
51
|
}
|
|
28
52
|
/** 带有服务端交互功能的组件属性 */
|
|
29
53
|
interface PropsWithServerQuery {
|
|
@@ -33,5 +57,5 @@ interface PropsWithServerQuery {
|
|
|
33
57
|
query?: Record<string, any>;
|
|
34
58
|
}
|
|
35
59
|
//#endregion
|
|
36
|
-
export { BreakpointName, ColorType, ComponentProps, ComponentSize, FormComponentProps, PropsWithServerQuery };
|
|
60
|
+
export { BreakpointName, ColorType, ComponentProps, ComponentSize, FormComponentProps, PresetRule, PropsWithServerQuery, ValidateRule };
|
|
37
61
|
//# sourceMappingURL=component-common.d.ts.map
|
|
@@ -18,17 +18,25 @@ interface FormContextProps {
|
|
|
18
18
|
readonly?: boolean;
|
|
19
19
|
/** 是否隐藏提示 */
|
|
20
20
|
noTips?: boolean;
|
|
21
|
-
/**
|
|
22
|
-
model?:
|
|
21
|
+
/** 表单数据 */
|
|
22
|
+
model?: Record<string, any>;
|
|
23
23
|
}
|
|
24
24
|
type FormPropsLike = Partial<FormContextProps> & Record<string, any>;
|
|
25
|
+
interface FormFieldItem {
|
|
26
|
+
validate: () => Promise<boolean>;
|
|
27
|
+
clearValidate?: () => void;
|
|
28
|
+
}
|
|
25
29
|
type DIContext = {
|
|
26
|
-
/** 表单属性 */formProps: FormPropsLike;
|
|
30
|
+
/** 表单属性 */formProps: FormPropsLike; /** 注册表单字段 */
|
|
31
|
+
registerField: (field: string, item: FormFieldItem) => void; /** 注销表单字段 */
|
|
32
|
+
unregisterField: (field: string) => void; /** 校验指定字段,未传 keys 时校验全部已注册字段 */
|
|
33
|
+
validateFields?: (keys?: string[]) => Promise<boolean>; /** 是否需要校验 */
|
|
34
|
+
shouldValidate?: () => boolean;
|
|
27
35
|
};
|
|
28
|
-
declare function provideFormContext
|
|
36
|
+
declare function provideFormContext(context: DIContext): void;
|
|
29
37
|
declare function injectFormContext(): {
|
|
30
38
|
/** 是否在表单中 */inForm: boolean;
|
|
31
39
|
} & Partial<DIContext>;
|
|
32
40
|
//#endregion
|
|
33
|
-
export { FormContextModel, FormContextProps, injectFormContext, provideFormContext };
|
|
41
|
+
export { FormContextModel, FormContextProps, FormFieldItem, injectFormContext, provideFormContext };
|
|
34
42
|
//# sourceMappingURL=form-context.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { inject, provide } from "vue";
|
|
2
2
|
//#region src/types/form-context.ts
|
|
3
3
|
const FormComponentDIKey = Symbol("FormComponentDIKey");
|
|
4
|
-
function provideFormContext(
|
|
5
|
-
|
|
4
|
+
function provideFormContext(context) {
|
|
5
|
+
provide(FormComponentDIKey, context);
|
|
6
6
|
}
|
|
7
7
|
function injectFormContext() {
|
|
8
8
|
const context = inject(FormComponentDIKey, void 0) || {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-context.js","names":[],"sources":["../../src/types/form-context.ts"],"sourcesContent":["import { type InjectionKey, inject, provide } from 'vue'\n\nimport type { ComponentSize } from './component-common'\n\nexport interface FormContextModel {\n errors: Map<any, string[] | undefined>\n fields: Record<string, { required?: unknown }>\n}\n\nexport interface FormContextProps {\n /** 表单列宽 */\n labelWidth?: string | number\n /** 表单尺寸 */\n size?: ComponentSize\n /** 是否禁用 */\n disabled?: boolean\n /** 是否只读 */\n readonly?: boolean\n /** 是否隐藏提示 */\n noTips?: boolean\n /**
|
|
1
|
+
{"version":3,"file":"form-context.js","names":[],"sources":["../../src/types/form-context.ts"],"sourcesContent":["import { type InjectionKey, inject, provide } from 'vue'\n\nimport type { ComponentSize } from './component-common'\n\nexport interface FormContextModel {\n errors: Map<any, string[] | undefined>\n fields: Record<string, { required?: unknown }>\n}\n\nexport interface FormContextProps {\n /** 表单列宽 */\n labelWidth?: string | number\n /** 表单尺寸 */\n size?: ComponentSize\n /** 是否禁用 */\n disabled?: boolean\n /** 是否只读 */\n readonly?: boolean\n /** 是否隐藏提示 */\n noTips?: boolean\n /** 表单数据 */\n model?: Record<string, any>\n}\n\ntype FormPropsLike = Partial<FormContextProps> & Record<string, any>\n\nexport interface FormFieldItem {\n validate: () => Promise<boolean>\n clearValidate?: () => void\n}\n\ntype DIContext = {\n /** 表单属性 */\n formProps: FormPropsLike\n /** 注册表单字段 */\n registerField: (field: string, item: FormFieldItem) => void\n /** 注销表单字段 */\n unregisterField: (field: string) => void\n /** 校验指定字段,未传 keys 时校验全部已注册字段 */\n validateFields?: (keys?: string[]) => Promise<boolean>\n /** 是否需要校验 */\n shouldValidate?: () => boolean\n}\n\nconst FormComponentDIKey: InjectionKey<DIContext> = Symbol('FormComponentDIKey')\n\nexport function provideFormContext(context: DIContext): void {\n provide(FormComponentDIKey, context)\n}\n\nexport function injectFormContext(): {\n /** 是否在表单中 */\n inForm: boolean\n} & Partial<DIContext> {\n const context = inject(FormComponentDIKey, undefined) || {}\n return { inForm: !!context, ...context }\n}\n"],"mappings":";;AA4CA,MAAM,qBAA8C,OAAO,oBAAoB;AAE/E,SAAgB,mBAAmB,SAA0B;CAC3D,QAAQ,oBAAoB,OAAO;AACrC;AAEA,SAAgB,oBAGO;CACrB,MAAM,UAAU,OAAO,oBAAoB,KAAA,CAAS,KAAK,CAAC;CAC1D,OAAO;EAAE,QAAQ,CAAC,CAAC;EAAS,GAAG;CAAQ;AACzC"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Data, PresetRule, ValidateRule, ValidatorConfig } from "./utils/form/validate.js";
|
|
2
1
|
import { DeconstructValue, DefineEvent, Index, Null, RenderReturn, Undef } from "./helper.js";
|
|
3
|
-
import { BreakpointName, ColorType, ComponentProps, ComponentSize, FormComponentProps, PropsWithServerQuery } from "./component-common.js";
|
|
4
|
-
import { FormContextModel, FormContextProps, injectFormContext, provideFormContext } from "./form-context.js";
|
|
5
|
-
export { BreakpointName, ColorType, ComponentProps, ComponentSize,
|
|
2
|
+
import { BreakpointName, ColorType, ComponentProps, ComponentSize, FormComponentProps, PresetRule, PropsWithServerQuery, ValidateRule } from "./component-common.js";
|
|
3
|
+
import { FormContextModel, FormContextProps, FormFieldItem, injectFormContext, provideFormContext } from "./form-context.js";
|
|
4
|
+
export { BreakpointName, ColorType, ComponentProps, ComponentSize, DeconstructValue, DefineEvent, FormComponentProps, FormContextModel, FormContextProps, FormFieldItem, Index, Null, PresetRule, PropsWithServerQuery, RenderReturn, Undef, ValidateRule, injectFormContext, provideFormContext };
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -11,6 +11,30 @@ export interface ComponentProps {
|
|
|
11
11
|
size?: ComponentSize
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export type PresetRule = 'email' | 'phone' | 'num' | 'url' | 'idCard'
|
|
15
|
+
|
|
16
|
+
/** 字段校验规则 */
|
|
17
|
+
export interface ValidateRule {
|
|
18
|
+
/** 是否必填 */
|
|
19
|
+
required?: boolean | string
|
|
20
|
+
/** 长度单位 */
|
|
21
|
+
length?: number | [number, string]
|
|
22
|
+
/** 最小值 */
|
|
23
|
+
min?: number | [number, string]
|
|
24
|
+
/** 最大值 */
|
|
25
|
+
max?: number | [number, string]
|
|
26
|
+
/** 最小长度 */
|
|
27
|
+
minLen?: number | [number, string]
|
|
28
|
+
/** 最大长度 */
|
|
29
|
+
maxLen?: number | [number, string]
|
|
30
|
+
/** 匹配 */
|
|
31
|
+
match?: RegExp | [RegExp, string] | string
|
|
32
|
+
/** 预设 */
|
|
33
|
+
preset?: PresetRule
|
|
34
|
+
/** 自定义校验 */
|
|
35
|
+
validator?: (value: any, data: Record<string, any>) => Promise<string> | string
|
|
36
|
+
}
|
|
37
|
+
|
|
14
38
|
/** 表单组件通用属性 */
|
|
15
39
|
export interface FormComponentProps extends ComponentProps {
|
|
16
40
|
/** 在表单控件内时的提示 */
|
|
@@ -30,6 +54,8 @@ export interface FormComponentProps extends ComponentProps {
|
|
|
30
54
|
disabled?: boolean
|
|
31
55
|
/** 是否只读 */
|
|
32
56
|
readonly?: boolean
|
|
57
|
+
/** 校验规则 */
|
|
58
|
+
rules?: ValidateRule
|
|
33
59
|
}
|
|
34
60
|
|
|
35
61
|
/** 带有服务端交互功能的组件属性 */
|
|
@@ -18,23 +18,34 @@ export interface FormContextProps {
|
|
|
18
18
|
readonly?: boolean
|
|
19
19
|
/** 是否隐藏提示 */
|
|
20
20
|
noTips?: boolean
|
|
21
|
-
/**
|
|
22
|
-
model?:
|
|
21
|
+
/** 表单数据 */
|
|
22
|
+
model?: Record<string, any>
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
type FormPropsLike = Partial<FormContextProps> & Record<string, any>
|
|
26
26
|
|
|
27
|
+
export interface FormFieldItem {
|
|
28
|
+
validate: () => Promise<boolean>
|
|
29
|
+
clearValidate?: () => void
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
type DIContext = {
|
|
28
33
|
/** 表单属性 */
|
|
29
34
|
formProps: FormPropsLike
|
|
35
|
+
/** 注册表单字段 */
|
|
36
|
+
registerField: (field: string, item: FormFieldItem) => void
|
|
37
|
+
/** 注销表单字段 */
|
|
38
|
+
unregisterField: (field: string) => void
|
|
39
|
+
/** 校验指定字段,未传 keys 时校验全部已注册字段 */
|
|
40
|
+
validateFields?: (keys?: string[]) => Promise<boolean>
|
|
41
|
+
/** 是否需要校验 */
|
|
42
|
+
shouldValidate?: () => boolean
|
|
30
43
|
}
|
|
31
44
|
|
|
32
45
|
const FormComponentDIKey: InjectionKey<DIContext> = Symbol('FormComponentDIKey')
|
|
33
46
|
|
|
34
|
-
export function provideFormContext
|
|
35
|
-
|
|
36
|
-
provide(FormComponentDIKey, { formProps: props })
|
|
37
|
-
}
|
|
47
|
+
export function provideFormContext(context: DIContext): void {
|
|
48
|
+
provide(FormComponentDIKey, context)
|
|
38
49
|
}
|
|
39
50
|
|
|
40
51
|
export function injectFormContext(): {
|
package/src/types/index.ts
CHANGED
package/dist/form/validate.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Data, ValidateRule, ValidatorConfig } from "../types/utils/form/validate.js";
|
|
2
|
-
|
|
3
|
-
//#region src/form/validate.d.ts
|
|
4
|
-
/** */
|
|
5
|
-
declare class Validator<Rules extends Record<string, ValidateRule> = Record<string, ValidateRule>, Field extends keyof Rules = keyof Rules> {
|
|
6
|
-
protected rules: Rules;
|
|
7
|
-
private config?;
|
|
8
|
-
constructor(rules: Rules, config?: ValidatorConfig);
|
|
9
|
-
/** 是否存在规则 */
|
|
10
|
-
private get existRules();
|
|
11
|
-
/**
|
|
12
|
-
* 校验单条数据
|
|
13
|
-
* @param data 数据
|
|
14
|
-
*/
|
|
15
|
-
private validateSingleData;
|
|
16
|
-
private validateValue;
|
|
17
|
-
private validateValueLazy;
|
|
18
|
-
/**
|
|
19
|
-
* 校验多条数据
|
|
20
|
-
* @param field 需要校验的字段
|
|
21
|
-
*/
|
|
22
|
-
private validateManyData;
|
|
23
|
-
/**
|
|
24
|
-
* 校验
|
|
25
|
-
* @param data 数据
|
|
26
|
-
* @param fields 字段
|
|
27
|
-
* @returns
|
|
28
|
-
*/
|
|
29
|
-
validate(data: Data, fields?: Field | Field[]): Promise<{ [key in Field]?: string[] }>;
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { Validator };
|
|
33
|
-
//# sourceMappingURL=validate.d.ts.map
|
package/dist/form/validate.js
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { o } from "@cat-kit/core";
|
|
2
|
-
//#region src/form/validate.ts
|
|
3
|
-
const isEmpty = (value) => {
|
|
4
|
-
return value === null || value === void 0;
|
|
5
|
-
};
|
|
6
|
-
const presetRules = {
|
|
7
|
-
email(v) {
|
|
8
|
-
if (!/^([\w_-]+)@([\w-]+[.]?)*[\w]+\.[a-zA-Z]{2,10}$/.test(v)) return "邮箱格式不正确";
|
|
9
|
-
},
|
|
10
|
-
phone(v) {
|
|
11
|
-
if (!/^\d{11}$/.test(v)) return "手机号格式不正确";
|
|
12
|
-
},
|
|
13
|
-
num(v) {
|
|
14
|
-
if (!/^\d+$/.test(v)) return "数字格式不正确";
|
|
15
|
-
},
|
|
16
|
-
url(v) {
|
|
17
|
-
if (!/^(ftp|https?):\/\/([\w_-]+)\.([\w-]+[.]?)*[\w]+\.[a-zA-Z]{2,10}(.*)/.test(v)) return "链接格式不正确";
|
|
18
|
-
},
|
|
19
|
-
idCard(v) {
|
|
20
|
-
if (!/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/.test(v)) return "身份证格式不正确";
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
/** 预设规则 */
|
|
24
|
-
const ruleTypes = {
|
|
25
|
-
required(value, required) {
|
|
26
|
-
if (required === false) return;
|
|
27
|
-
const errMsg = typeof required === "string" ? required : "该项不能为空";
|
|
28
|
-
if (isEmpty(value)) return errMsg;
|
|
29
|
-
if (Array.isArray(value) && !value.length) return errMsg;
|
|
30
|
-
if (typeof value === "string" && !value) return errMsg;
|
|
31
|
-
},
|
|
32
|
-
min(value, rule) {
|
|
33
|
-
if (isEmpty(value)) return;
|
|
34
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule;
|
|
35
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项必须大于等于${_rule}`;
|
|
36
|
-
if (typeof value !== "number") return `${value}不是一个数字`;
|
|
37
|
-
if (value < _rule) return errMsg;
|
|
38
|
-
},
|
|
39
|
-
max(value, rule) {
|
|
40
|
-
if (isEmpty(value)) return;
|
|
41
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule;
|
|
42
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项必须小于等于${_rule}`;
|
|
43
|
-
if (typeof value !== "number") return `${value}不是一个数字`;
|
|
44
|
-
if (value > _rule) return errMsg;
|
|
45
|
-
},
|
|
46
|
-
minLen(value, rule) {
|
|
47
|
-
if (isEmpty(value)) return;
|
|
48
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule;
|
|
49
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须大于等于${_rule}`;
|
|
50
|
-
if (!Array.isArray(value) && typeof value !== "string") return `${value}不是一个字符串或数组`;
|
|
51
|
-
if (value.length < _rule) return errMsg;
|
|
52
|
-
},
|
|
53
|
-
maxLen(value, rule) {
|
|
54
|
-
if (isEmpty(value)) return;
|
|
55
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule;
|
|
56
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须小于等于:${_rule}`;
|
|
57
|
-
if (!Array.isArray(value) && typeof value !== "string") return `${value}不是一个字符串或数组`;
|
|
58
|
-
if (value.length > _rule) return errMsg;
|
|
59
|
-
},
|
|
60
|
-
match(value, rule) {
|
|
61
|
-
if (isEmpty(value) || value === "") return;
|
|
62
|
-
if (typeof rule === "string") {
|
|
63
|
-
if (!rule) return;
|
|
64
|
-
rule = new RegExp(rule);
|
|
65
|
-
}
|
|
66
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule;
|
|
67
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项不匹配正则:${_rule}`;
|
|
68
|
-
if (typeof value !== "string") return `${value}不是一个字符串`;
|
|
69
|
-
if (!_rule.test(value)) return errMsg;
|
|
70
|
-
},
|
|
71
|
-
preset(value, rule) {
|
|
72
|
-
if (isEmpty(value) || value === "" || !rule) return;
|
|
73
|
-
if (typeof value !== "string") return `${value}不是一个字符串`;
|
|
74
|
-
const ruleValidator = presetRules[rule];
|
|
75
|
-
return ruleValidator(value);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
/** */
|
|
79
|
-
var Validator = class {
|
|
80
|
-
rules;
|
|
81
|
-
config;
|
|
82
|
-
constructor(rules, config) {
|
|
83
|
-
this.rules = rules;
|
|
84
|
-
if (config) this.config = config;
|
|
85
|
-
}
|
|
86
|
-
/** 是否存在规则 */
|
|
87
|
-
get existRules() {
|
|
88
|
-
for (const _ in this.rules) return true;
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* 校验单条数据
|
|
93
|
-
* @param data 数据
|
|
94
|
-
*/
|
|
95
|
-
async validateSingleData(data, fields) {
|
|
96
|
-
const fieldErrors = {};
|
|
97
|
-
if (!this.existRules) return fieldErrors;
|
|
98
|
-
const lazy = this.config?.lazy ?? true;
|
|
99
|
-
fields = fields ? Array.isArray(fields) ? fields : [fields] : Object.keys(this.rules);
|
|
100
|
-
if (lazy) {
|
|
101
|
-
for (let i = 0; i < fields.length; i++) {
|
|
102
|
-
const field = fields[i];
|
|
103
|
-
const errors = await this.validateValueLazy(data, field);
|
|
104
|
-
if (errors.length === 0) continue;
|
|
105
|
-
fieldErrors[field] = errors;
|
|
106
|
-
}
|
|
107
|
-
return fieldErrors;
|
|
108
|
-
} else {
|
|
109
|
-
for (let i = 0; i < fields.length; i++) {
|
|
110
|
-
const field = fields[i];
|
|
111
|
-
const errors = await this.validateValue(data, field);
|
|
112
|
-
if (errors.length === 0) continue;
|
|
113
|
-
fieldErrors[field] = errors;
|
|
114
|
-
}
|
|
115
|
-
return fieldErrors;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
async validateValue(data, field) {
|
|
119
|
-
const rules = this.rules[field];
|
|
120
|
-
const value = o(data).get(field);
|
|
121
|
-
const { validator, required, ...normalRules } = rules;
|
|
122
|
-
let errors = [];
|
|
123
|
-
if (required) {
|
|
124
|
-
const err = ruleTypes.required(value, required);
|
|
125
|
-
err && errors.push(err);
|
|
126
|
-
}
|
|
127
|
-
for (const ruleKey in normalRules) {
|
|
128
|
-
const validate = ruleTypes[ruleKey];
|
|
129
|
-
if (!validate) continue;
|
|
130
|
-
const err = validate(value, normalRules[ruleKey]);
|
|
131
|
-
err && errors.push(err);
|
|
132
|
-
}
|
|
133
|
-
if (validator) {
|
|
134
|
-
const err = await validator(value, data);
|
|
135
|
-
err && errors.push(err);
|
|
136
|
-
}
|
|
137
|
-
return errors;
|
|
138
|
-
}
|
|
139
|
-
async validateValueLazy(data, field) {
|
|
140
|
-
const rules = this.rules[field];
|
|
141
|
-
const value = o(data).get(field);
|
|
142
|
-
let errors = [];
|
|
143
|
-
if (!rules) return errors;
|
|
144
|
-
const { validator, required, ...normalRules } = rules;
|
|
145
|
-
if (required) {
|
|
146
|
-
const err = ruleTypes.required(value, required);
|
|
147
|
-
if (err) {
|
|
148
|
-
errors.push(err);
|
|
149
|
-
return errors;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
for (const ruleKey in normalRules) {
|
|
153
|
-
const validate = ruleTypes[ruleKey];
|
|
154
|
-
if (!validate) continue;
|
|
155
|
-
const err = validate(value, normalRules[ruleKey]);
|
|
156
|
-
if (err) {
|
|
157
|
-
errors.push(err);
|
|
158
|
-
return errors;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
if (validator) {
|
|
162
|
-
const err = await validator(value, data);
|
|
163
|
-
if (err) {
|
|
164
|
-
errors.push(err);
|
|
165
|
-
return errors;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return errors;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* 校验多条数据
|
|
172
|
-
* @param field 需要校验的字段
|
|
173
|
-
*/
|
|
174
|
-
async validateManyData(data, field) {
|
|
175
|
-
let i = 0;
|
|
176
|
-
while (i < data.length) {
|
|
177
|
-
const item = data[i];
|
|
178
|
-
const fieldErrors = await this.validateSingleData(item, field);
|
|
179
|
-
if (Object.keys(fieldErrors).length > 0) return fieldErrors;
|
|
180
|
-
i++;
|
|
181
|
-
}
|
|
182
|
-
return {};
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* 校验
|
|
186
|
-
* @param data 数据
|
|
187
|
-
* @param fields 字段
|
|
188
|
-
* @returns
|
|
189
|
-
*/
|
|
190
|
-
async validate(data, fields) {
|
|
191
|
-
return Array.isArray(data) ? this.validateManyData(data, fields) : this.validateSingleData(data, fields);
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
//#endregion
|
|
195
|
-
export { Validator };
|
|
196
|
-
|
|
197
|
-
//# sourceMappingURL=validate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","names":[],"sources":["../../src/form/validate.ts"],"sourcesContent":["import { o } from '@cat-kit/core'\n\nimport type { Undef } from '../types/helper'\nimport type { ValidateRule, Data, ValidatorConfig, PresetRule } from '../types/utils/form/validate'\n\nconst isEmpty = (value: any): value is null | undefined => {\n return value === null || value === undefined\n}\n\nconst presetRules: Record<PresetRule, (value: string) => string | undefined> = {\n email(v) {\n const re = /^([\\w_-]+)@([\\w-]+[.]?)*[\\w]+\\.[a-zA-Z]{2,10}$/\n if (!re.test(v)) {\n return '邮箱格式不正确'\n }\n },\n phone(v) {\n const re = /^\\d{11}$/\n if (!re.test(v)) {\n return '手机号格式不正确'\n }\n },\n num(v) {\n const re = /^\\d+$/\n if (!re.test(v)) {\n return '数字格式不正确'\n }\n },\n url(v) {\n const re = /^(ftp|https?):\\/\\/([\\w_-]+)\\.([\\w-]+[.]?)*[\\w]+\\.[a-zA-Z]{2,10}(.*)/\n if (!re.test(v)) {\n return '链接格式不正确'\n }\n },\n\n idCard(v) {\n const re = /^(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9]|X)$/\n if (!re.test(v)) {\n return '身份证格式不正确'\n }\n }\n}\n\n/** 预设规则 */\nconst ruleTypes = {\n required(value: any, required: ValidateRule['required']): Undef<string> {\n if (required === false) return\n\n const errMsg = typeof required === 'string' ? required : '该项不能为空'\n if (isEmpty(value)) return errMsg\n\n if (Array.isArray(value) && !value.length) return errMsg\n if (typeof value === 'string' && !value) return errMsg\n },\n min(value: any, rule: ValidateRule['min']): Undef<string> {\n if (isEmpty(value)) return\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项必须大于等于${_rule}`\n if (typeof value !== 'number') return `${value}不是一个数字`\n if (value < _rule) return errMsg\n },\n max(value: any, rule: ValidateRule['max']): Undef<string> {\n if (isEmpty(value)) return\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项必须小于等于${_rule}`\n if (typeof value !== 'number') return `${value}不是一个数字`\n if (value > _rule) return errMsg\n },\n\n minLen(value: any, rule: ValidateRule['minLen']): Undef<string> {\n if (isEmpty(value)) return\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须大于等于${_rule}`\n if (!Array.isArray(value) && typeof value !== 'string') return `${value}不是一个字符串或数组`\n if (value.length < _rule) return errMsg\n },\n maxLen(value: any, rule: ValidateRule['maxLen']): Undef<string> {\n if (isEmpty(value)) return\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须小于等于:${_rule}`\n if (!Array.isArray(value) && typeof value !== 'string') return `${value}不是一个字符串或数组`\n if (value.length > _rule) return errMsg\n },\n match(value: any, rule: ValidateRule['match']): Undef<string> {\n if (isEmpty(value) || value === '') return\n if (typeof rule === 'string') {\n if (!rule) return\n rule = new RegExp(rule)\n }\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项不匹配正则:${_rule}`\n if (typeof value !== 'string') return `${value}不是一个字符串`\n if (!_rule.test(value)) return errMsg\n },\n preset(value: any, rule: ValidateRule['preset']): Undef<string> {\n if (isEmpty(value) || value === '' || !rule) return\n if (typeof value !== 'string') return `${value}不是一个字符串`\n const ruleValidator = presetRules[rule]\n return ruleValidator(value)\n }\n}\n/** */\nexport class Validator<\n Rules extends Record<string, ValidateRule> = Record<string, ValidateRule>,\n Field extends keyof Rules = keyof Rules\n> {\n protected rules: Rules\n\n private config?: ValidatorConfig\n\n constructor(rules: Rules, config?: ValidatorConfig) {\n this.rules = rules\n if (config) {\n this.config = config\n }\n }\n\n /** 是否存在规则 */\n private get existRules() {\n for (const _ in this.rules) {\n return true\n }\n return false\n }\n\n /**\n * 校验单条数据\n * @param data 数据\n */\n private async validateSingleData(\n data: Record<any, any>,\n fields?: Field | Field[]\n ): Promise<{ [key in Field]?: string[] }> {\n const fieldErrors: { [key in Field]?: string[] } = {}\n\n if (!this.existRules) return fieldErrors\n\n const lazy = this.config?.lazy ?? true\n\n fields = fields\n ? Array.isArray(fields)\n ? fields\n : [fields]\n : (Object.keys(this.rules) as Field[])\n\n // 懒校验,当有一个规则不通过,剩下的规则不再校验\n if (lazy) {\n // 校验字段\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i]!\n // oxlint-disable-next-line no-await-in-loop -- 懒校验需按字段顺序短路\n const errors = await this.validateValueLazy(data, field)\n if (errors.length === 0) continue\n fieldErrors[field] = errors\n }\n return fieldErrors\n } else {\n // 校验字段\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i]!\n // oxlint-disable-next-line no-await-in-loop -- 按字段顺序校验以便尽早收集错误\n const errors = await this.validateValue(data, field)\n if (errors.length === 0) continue\n fieldErrors[field] = errors\n }\n\n return fieldErrors\n }\n }\n\n private async validateValue(data: Record<any, any>, field: Field) {\n const rules = this.rules[field]!\n const value = o(data).get(field as string)\n\n const { validator, required, ...normalRules } = rules\n\n let errors: string[] = []\n\n // 必填要先去校验\n if (required) {\n const err = ruleTypes.required(value, required)\n err && errors.push(err)\n }\n\n // 校验规则\n for (const ruleKey in normalRules) {\n const validate = ruleTypes[ruleKey]\n if (!validate) continue\n const err = validate(value, normalRules[ruleKey])\n err && errors.push(err)\n }\n\n // 自定义校验\n if (validator) {\n const err = await validator(value, data)\n err && errors.push(err)\n }\n\n return errors\n }\n\n private async validateValueLazy(data: Record<any, any>, field: Field): Promise<string[]> {\n const rules = this.rules[field]\n const value = o(data).get(field as string)\n let errors: string[] = []\n\n if (!rules) return errors\n\n const { validator, required, ...normalRules } = rules\n\n // 必填要先去校验\n if (required) {\n const err = ruleTypes.required(value, required)\n if (err) {\n errors.push(err)\n return errors\n }\n }\n\n // 校验规则\n for (const ruleKey in normalRules) {\n const validate = ruleTypes[ruleKey]\n if (!validate) continue\n\n const err = validate(value, normalRules[ruleKey])\n\n if (err) {\n errors.push(err)\n return errors\n }\n }\n\n // 自定义校验最火校验\n if (validator) {\n const err = await validator(value, data)\n if (err) {\n errors.push(err)\n return errors\n }\n }\n\n return errors\n }\n\n /**\n * 校验多条数据\n * @param field 需要校验的字段\n */\n private async validateManyData(\n data: Data,\n field?: Field | Field[]\n ): Promise<{ [key in Field]?: string[] }> {\n let i = 0\n while (i < data.length) {\n const item = data[i]!\n // oxlint-disable-next-line no-await-in-loop -- 多条数据校验命中首条错误即返回\n const fieldErrors = await this.validateSingleData(item, field)\n if (Object.keys(fieldErrors).length > 0) {\n return fieldErrors\n }\n i++\n }\n\n return {}\n }\n\n /**\n * 校验\n * @param data 数据\n * @param fields 字段\n * @returns\n */\n async validate(data: Data, fields?: Field | Field[]): Promise<{ [key in Field]?: string[] }> {\n return Array.isArray(data)\n ? this.validateManyData(data, fields)\n : this.validateSingleData(data, fields)\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
//#region src/types/utils/form/validate.d.ts
|
|
2
|
-
type Data = Record<string, any>;
|
|
3
|
-
type PresetRule = 'email' | 'phone' | 'num' | 'url' | 'idCard';
|
|
4
|
-
/** 字段校验规则 */
|
|
5
|
-
interface ValidateRule {
|
|
6
|
-
/** 是否必填 */
|
|
7
|
-
required?: boolean | string;
|
|
8
|
-
/** 长度单位 */
|
|
9
|
-
length?: number | [number, string];
|
|
10
|
-
/** 最小值 */
|
|
11
|
-
min?: number | [number, string];
|
|
12
|
-
/** 最大值 */
|
|
13
|
-
max?: number | [number, string];
|
|
14
|
-
/** 最小长度 */
|
|
15
|
-
minLen?: number | [number, string];
|
|
16
|
-
/** 最大长度 */
|
|
17
|
-
maxLen?: number | [number, string];
|
|
18
|
-
/** 匹配 */
|
|
19
|
-
match?: RegExp | [RegExp, string] | string;
|
|
20
|
-
/** 预设 */
|
|
21
|
-
preset?: PresetRule;
|
|
22
|
-
/** 自定义校验 */
|
|
23
|
-
validator?: (value: any, data: Data) => Promise<string> | string;
|
|
24
|
-
}
|
|
25
|
-
interface ValidatorConfig {
|
|
26
|
-
/**
|
|
27
|
-
* 是否懒校验,为true时在任意一个字段的的任意规则校验不通过时立马结束校验,性能稍微高一点,但是不能得出所有的错误
|
|
28
|
-
* @default true
|
|
29
|
-
*/
|
|
30
|
-
lazy?: boolean;
|
|
31
|
-
}
|
|
32
|
-
//#endregion
|
|
33
|
-
export { Data, PresetRule, ValidateRule, ValidatorConfig };
|
|
34
|
-
//# sourceMappingURL=validate.d.ts.map
|
package/src/form/validate.ts
DELETED
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
import { o } from '@cat-kit/core'
|
|
2
|
-
|
|
3
|
-
import type { Undef } from '../types/helper'
|
|
4
|
-
import type { ValidateRule, Data, ValidatorConfig, PresetRule } from '../types/utils/form/validate'
|
|
5
|
-
|
|
6
|
-
const isEmpty = (value: any): value is null | undefined => {
|
|
7
|
-
return value === null || value === undefined
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const presetRules: Record<PresetRule, (value: string) => string | undefined> = {
|
|
11
|
-
email(v) {
|
|
12
|
-
const re = /^([\w_-]+)@([\w-]+[.]?)*[\w]+\.[a-zA-Z]{2,10}$/
|
|
13
|
-
if (!re.test(v)) {
|
|
14
|
-
return '邮箱格式不正确'
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
phone(v) {
|
|
18
|
-
const re = /^\d{11}$/
|
|
19
|
-
if (!re.test(v)) {
|
|
20
|
-
return '手机号格式不正确'
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
num(v) {
|
|
24
|
-
const re = /^\d+$/
|
|
25
|
-
if (!re.test(v)) {
|
|
26
|
-
return '数字格式不正确'
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
url(v) {
|
|
30
|
-
const re = /^(ftp|https?):\/\/([\w_-]+)\.([\w-]+[.]?)*[\w]+\.[a-zA-Z]{2,10}(.*)/
|
|
31
|
-
if (!re.test(v)) {
|
|
32
|
-
return '链接格式不正确'
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
idCard(v) {
|
|
37
|
-
const re = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/
|
|
38
|
-
if (!re.test(v)) {
|
|
39
|
-
return '身份证格式不正确'
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** 预设规则 */
|
|
45
|
-
const ruleTypes = {
|
|
46
|
-
required(value: any, required: ValidateRule['required']): Undef<string> {
|
|
47
|
-
if (required === false) return
|
|
48
|
-
|
|
49
|
-
const errMsg = typeof required === 'string' ? required : '该项不能为空'
|
|
50
|
-
if (isEmpty(value)) return errMsg
|
|
51
|
-
|
|
52
|
-
if (Array.isArray(value) && !value.length) return errMsg
|
|
53
|
-
if (typeof value === 'string' && !value) return errMsg
|
|
54
|
-
},
|
|
55
|
-
min(value: any, rule: ValidateRule['min']): Undef<string> {
|
|
56
|
-
if (isEmpty(value)) return
|
|
57
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule!
|
|
58
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项必须大于等于${_rule}`
|
|
59
|
-
if (typeof value !== 'number') return `${value}不是一个数字`
|
|
60
|
-
if (value < _rule) return errMsg
|
|
61
|
-
},
|
|
62
|
-
max(value: any, rule: ValidateRule['max']): Undef<string> {
|
|
63
|
-
if (isEmpty(value)) return
|
|
64
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule!
|
|
65
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项必须小于等于${_rule}`
|
|
66
|
-
if (typeof value !== 'number') return `${value}不是一个数字`
|
|
67
|
-
if (value > _rule) return errMsg
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
minLen(value: any, rule: ValidateRule['minLen']): Undef<string> {
|
|
71
|
-
if (isEmpty(value)) return
|
|
72
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule!
|
|
73
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须大于等于${_rule}`
|
|
74
|
-
if (!Array.isArray(value) && typeof value !== 'string') return `${value}不是一个字符串或数组`
|
|
75
|
-
if (value.length < _rule) return errMsg
|
|
76
|
-
},
|
|
77
|
-
maxLen(value: any, rule: ValidateRule['maxLen']): Undef<string> {
|
|
78
|
-
if (isEmpty(value)) return
|
|
79
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule!
|
|
80
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须小于等于:${_rule}`
|
|
81
|
-
if (!Array.isArray(value) && typeof value !== 'string') return `${value}不是一个字符串或数组`
|
|
82
|
-
if (value.length > _rule) return errMsg
|
|
83
|
-
},
|
|
84
|
-
match(value: any, rule: ValidateRule['match']): Undef<string> {
|
|
85
|
-
if (isEmpty(value) || value === '') return
|
|
86
|
-
if (typeof rule === 'string') {
|
|
87
|
-
if (!rule) return
|
|
88
|
-
rule = new RegExp(rule)
|
|
89
|
-
}
|
|
90
|
-
let _rule = Array.isArray(rule) ? rule[0] : rule!
|
|
91
|
-
let errMsg = Array.isArray(rule) ? rule[1] : `该项不匹配正则:${_rule}`
|
|
92
|
-
if (typeof value !== 'string') return `${value}不是一个字符串`
|
|
93
|
-
if (!_rule.test(value)) return errMsg
|
|
94
|
-
},
|
|
95
|
-
preset(value: any, rule: ValidateRule['preset']): Undef<string> {
|
|
96
|
-
if (isEmpty(value) || value === '' || !rule) return
|
|
97
|
-
if (typeof value !== 'string') return `${value}不是一个字符串`
|
|
98
|
-
const ruleValidator = presetRules[rule]
|
|
99
|
-
return ruleValidator(value)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
/** */
|
|
103
|
-
export class Validator<
|
|
104
|
-
Rules extends Record<string, ValidateRule> = Record<string, ValidateRule>,
|
|
105
|
-
Field extends keyof Rules = keyof Rules
|
|
106
|
-
> {
|
|
107
|
-
protected rules: Rules
|
|
108
|
-
|
|
109
|
-
private config?: ValidatorConfig
|
|
110
|
-
|
|
111
|
-
constructor(rules: Rules, config?: ValidatorConfig) {
|
|
112
|
-
this.rules = rules
|
|
113
|
-
if (config) {
|
|
114
|
-
this.config = config
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** 是否存在规则 */
|
|
119
|
-
private get existRules() {
|
|
120
|
-
for (const _ in this.rules) {
|
|
121
|
-
return true
|
|
122
|
-
}
|
|
123
|
-
return false
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* 校验单条数据
|
|
128
|
-
* @param data 数据
|
|
129
|
-
*/
|
|
130
|
-
private async validateSingleData(
|
|
131
|
-
data: Record<any, any>,
|
|
132
|
-
fields?: Field | Field[]
|
|
133
|
-
): Promise<{ [key in Field]?: string[] }> {
|
|
134
|
-
const fieldErrors: { [key in Field]?: string[] } = {}
|
|
135
|
-
|
|
136
|
-
if (!this.existRules) return fieldErrors
|
|
137
|
-
|
|
138
|
-
const lazy = this.config?.lazy ?? true
|
|
139
|
-
|
|
140
|
-
fields = fields
|
|
141
|
-
? Array.isArray(fields)
|
|
142
|
-
? fields
|
|
143
|
-
: [fields]
|
|
144
|
-
: (Object.keys(this.rules) as Field[])
|
|
145
|
-
|
|
146
|
-
// 懒校验,当有一个规则不通过,剩下的规则不再校验
|
|
147
|
-
if (lazy) {
|
|
148
|
-
// 校验字段
|
|
149
|
-
for (let i = 0; i < fields.length; i++) {
|
|
150
|
-
const field = fields[i]!
|
|
151
|
-
// oxlint-disable-next-line no-await-in-loop -- 懒校验需按字段顺序短路
|
|
152
|
-
const errors = await this.validateValueLazy(data, field)
|
|
153
|
-
if (errors.length === 0) continue
|
|
154
|
-
fieldErrors[field] = errors
|
|
155
|
-
}
|
|
156
|
-
return fieldErrors
|
|
157
|
-
} else {
|
|
158
|
-
// 校验字段
|
|
159
|
-
for (let i = 0; i < fields.length; i++) {
|
|
160
|
-
const field = fields[i]!
|
|
161
|
-
// oxlint-disable-next-line no-await-in-loop -- 按字段顺序校验以便尽早收集错误
|
|
162
|
-
const errors = await this.validateValue(data, field)
|
|
163
|
-
if (errors.length === 0) continue
|
|
164
|
-
fieldErrors[field] = errors
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return fieldErrors
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
private async validateValue(data: Record<any, any>, field: Field) {
|
|
172
|
-
const rules = this.rules[field]!
|
|
173
|
-
const value = o(data).get(field as string)
|
|
174
|
-
|
|
175
|
-
const { validator, required, ...normalRules } = rules
|
|
176
|
-
|
|
177
|
-
let errors: string[] = []
|
|
178
|
-
|
|
179
|
-
// 必填要先去校验
|
|
180
|
-
if (required) {
|
|
181
|
-
const err = ruleTypes.required(value, required)
|
|
182
|
-
err && errors.push(err)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// 校验规则
|
|
186
|
-
for (const ruleKey in normalRules) {
|
|
187
|
-
const validate = ruleTypes[ruleKey]
|
|
188
|
-
if (!validate) continue
|
|
189
|
-
const err = validate(value, normalRules[ruleKey])
|
|
190
|
-
err && errors.push(err)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// 自定义校验
|
|
194
|
-
if (validator) {
|
|
195
|
-
const err = await validator(value, data)
|
|
196
|
-
err && errors.push(err)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return errors
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
private async validateValueLazy(data: Record<any, any>, field: Field): Promise<string[]> {
|
|
203
|
-
const rules = this.rules[field]
|
|
204
|
-
const value = o(data).get(field as string)
|
|
205
|
-
let errors: string[] = []
|
|
206
|
-
|
|
207
|
-
if (!rules) return errors
|
|
208
|
-
|
|
209
|
-
const { validator, required, ...normalRules } = rules
|
|
210
|
-
|
|
211
|
-
// 必填要先去校验
|
|
212
|
-
if (required) {
|
|
213
|
-
const err = ruleTypes.required(value, required)
|
|
214
|
-
if (err) {
|
|
215
|
-
errors.push(err)
|
|
216
|
-
return errors
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// 校验规则
|
|
221
|
-
for (const ruleKey in normalRules) {
|
|
222
|
-
const validate = ruleTypes[ruleKey]
|
|
223
|
-
if (!validate) continue
|
|
224
|
-
|
|
225
|
-
const err = validate(value, normalRules[ruleKey])
|
|
226
|
-
|
|
227
|
-
if (err) {
|
|
228
|
-
errors.push(err)
|
|
229
|
-
return errors
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// 自定义校验最火校验
|
|
234
|
-
if (validator) {
|
|
235
|
-
const err = await validator(value, data)
|
|
236
|
-
if (err) {
|
|
237
|
-
errors.push(err)
|
|
238
|
-
return errors
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return errors
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* 校验多条数据
|
|
247
|
-
* @param field 需要校验的字段
|
|
248
|
-
*/
|
|
249
|
-
private async validateManyData(
|
|
250
|
-
data: Data,
|
|
251
|
-
field?: Field | Field[]
|
|
252
|
-
): Promise<{ [key in Field]?: string[] }> {
|
|
253
|
-
let i = 0
|
|
254
|
-
while (i < data.length) {
|
|
255
|
-
const item = data[i]!
|
|
256
|
-
// oxlint-disable-next-line no-await-in-loop -- 多条数据校验命中首条错误即返回
|
|
257
|
-
const fieldErrors = await this.validateSingleData(item, field)
|
|
258
|
-
if (Object.keys(fieldErrors).length > 0) {
|
|
259
|
-
return fieldErrors
|
|
260
|
-
}
|
|
261
|
-
i++
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return {}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* 校验
|
|
269
|
-
* @param data 数据
|
|
270
|
-
* @param fields 字段
|
|
271
|
-
* @returns
|
|
272
|
-
*/
|
|
273
|
-
async validate(data: Data, fields?: Field | Field[]): Promise<{ [key in Field]?: string[] }> {
|
|
274
|
-
return Array.isArray(data)
|
|
275
|
-
? this.validateManyData(data, fields)
|
|
276
|
-
: this.validateSingleData(data, fields)
|
|
277
|
-
}
|
|
278
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export type Data = Record<string, any>
|
|
2
|
-
|
|
3
|
-
export type PresetRule = 'email' | 'phone' | 'num' | 'url' | 'idCard'
|
|
4
|
-
|
|
5
|
-
/** 字段校验规则 */
|
|
6
|
-
export interface ValidateRule {
|
|
7
|
-
/** 是否必填 */
|
|
8
|
-
required?: boolean | string
|
|
9
|
-
/** 长度单位 */
|
|
10
|
-
length?: number | [number, string]
|
|
11
|
-
/** 最小值 */
|
|
12
|
-
min?: number | [number, string]
|
|
13
|
-
/** 最大值 */
|
|
14
|
-
max?: number | [number, string]
|
|
15
|
-
/** 最小长度 */
|
|
16
|
-
minLen?: number | [number, string]
|
|
17
|
-
/** 最大长度 */
|
|
18
|
-
maxLen?: number | [number, string]
|
|
19
|
-
/** 匹配 */
|
|
20
|
-
match?: RegExp | [RegExp, string] | string
|
|
21
|
-
/** 预设 */
|
|
22
|
-
preset?: PresetRule
|
|
23
|
-
/** 自定义校验 */
|
|
24
|
-
validator?: (value: any, data: Data) => Promise<string> | string
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface ValidatorConfig {
|
|
28
|
-
/**
|
|
29
|
-
* 是否懒校验,为true时在任意一个字段的的任意规则校验不通过时立马结束校验,性能稍微高一点,但是不能得出所有的错误
|
|
30
|
-
* @default true
|
|
31
|
-
*/
|
|
32
|
-
lazy?: boolean
|
|
33
|
-
}
|