form-driver 0.4.0 → 0.4.2
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/m3.css +129 -1
- package/dist/m3.js +1 -1
- package/es/m3.css +129 -1
- package/es/m3.js +1196 -386
- package/lib/m3.css +129 -1
- package/lib/m3.js +1192 -382
- package/package.json +3 -2
- package/src/framework/Assembly.tsx +53 -23
- package/src/framework/Init.tsx +4 -0
- package/src/framework/M3.tsx +2 -2
- package/src/framework/MViewer.tsx +32 -8
- package/src/framework/Validator.ts +131 -68
- package/src/types/MSetType.ts +1 -1
- package/src/types/MWeightType.ts +113 -0
- package/src/ui/BaseViewer.tsx +64 -42
- package/src/ui/editor/basic/AIntBox.tsx +13 -10
- package/src/ui/editor/complex/AArrayGrid.tsx +229 -101
- package/src/ui/editor/complex/ACheckDrag.tsx +46 -40
- package/src/ui/editor/complex/AForm.tsx +273 -125
- package/src/ui/editor/complex/AWeight.tsx +257 -0
- package/src/ui/widget/EnhancedSortDrag.less +142 -0
- package/src/ui/widget/EnhancedSortDrag.tsx +498 -0
- package/src/ui/widget/SortDrag.less +1 -1
- package/src/ui/widget/SortDrag.tsx +1 -14
- package/types/framework/Assembly.d.ts +1 -1
- package/types/framework/MViewer.d.ts +1 -0
- package/types/framework/Validator.d.ts +2 -2
- package/types/types/MWeightType.d.ts +2 -0
- package/types/ui/editor/complex/AArrayGrid.d.ts +1 -1
- package/types/ui/editor/complex/AForm.d.ts +2 -2
- package/types/ui/editor/complex/AWeight.d.ts +42 -0
- package/types/ui/widget/EnhancedSortDrag.d.ts +59 -0
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "form-driver",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "An efficient framework for creating forms.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"authors": [
|
|
7
|
+
"曹志贤 <1546158360@qq.com>",
|
|
7
8
|
"龙湖 <59775976@qq.com>",
|
|
8
9
|
"云开 <2313303800@qq.com>"
|
|
9
10
|
],
|
|
@@ -136,4 +137,4 @@
|
|
|
136
137
|
"engines": {
|
|
137
138
|
"node": ">=v14.15.4"
|
|
138
139
|
}
|
|
139
|
-
}
|
|
140
|
+
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import React, { ClassType } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
MValidationResult,
|
|
4
|
+
MFieldSchemaAnonymity,
|
|
5
|
+
MProp,
|
|
6
|
+
MValidationFail,
|
|
7
|
+
} from "./Schema";
|
|
3
8
|
import { CHANGE_SCHEMA_CALLBACK } from "../framework/Schema";
|
|
4
9
|
import _ from "lodash";
|
|
5
|
-
import { MUtil } from
|
|
10
|
+
import { MUtil } from "./MUtil";
|
|
6
11
|
import { MType, PluginType } from "../types/MType";
|
|
7
12
|
|
|
8
13
|
export type MORPH = "readable" | "editor";
|
|
9
|
-
export type VIEWER = ClassType<MProp, any, any
|
|
14
|
+
export type VIEWER = ClassType<MProp, any, any>;
|
|
10
15
|
|
|
11
16
|
/** 统一的视觉样式 */
|
|
12
17
|
export interface MTheme {
|
|
@@ -39,8 +44,8 @@ const defaultTheme: MTheme = {
|
|
|
39
44
|
READABLE_INVALID: "❓",
|
|
40
45
|
READABLE_ERROR: "❗",
|
|
41
46
|
|
|
42
|
-
themeName: "antMiddle"
|
|
43
|
-
}
|
|
47
|
+
themeName: "antMiddle",
|
|
48
|
+
};
|
|
44
49
|
|
|
45
50
|
/**
|
|
46
51
|
* 注册viewer,type,morph(viewer和type之间的关联)
|
|
@@ -49,7 +54,13 @@ export class Assembly {
|
|
|
49
54
|
types: { [name: string]: MType } = {};
|
|
50
55
|
viewers: { [name: string]: VIEWER } = {};
|
|
51
56
|
editors: { [name: string]: EDITOR } = {};
|
|
52
|
-
morph: {
|
|
57
|
+
morph: {
|
|
58
|
+
[name: /*MORPH*/ string]: {
|
|
59
|
+
[typeName: string]:
|
|
60
|
+
| string
|
|
61
|
+
| ClassType<MProp, any, any> /* viewer name or viewer */;
|
|
62
|
+
};
|
|
63
|
+
} = {};
|
|
53
64
|
|
|
54
65
|
theme: MTheme = defaultTheme;
|
|
55
66
|
|
|
@@ -59,8 +70,13 @@ export class Assembly {
|
|
|
59
70
|
let r;
|
|
60
71
|
if (_.isString(s.toReadable)) {
|
|
61
72
|
// eslint-disable-next-line no-new-func
|
|
62
|
-
r = new Function(
|
|
63
|
-
"
|
|
73
|
+
r = new Function(
|
|
74
|
+
"_",
|
|
75
|
+
"value",
|
|
76
|
+
"theme",
|
|
77
|
+
"const {READABLE_UNKNOWN, READABLE_BLANK, READABLE_INVALID, READABLE_ERROR} = theme; return " +
|
|
78
|
+
s.toReadable
|
|
79
|
+
)(_, v, this.theme);
|
|
64
80
|
} else if (_.isFunction(s.toReadable)) {
|
|
65
81
|
r = s.toReadable(v, parent, this);
|
|
66
82
|
}
|
|
@@ -71,12 +87,15 @@ export class Assembly {
|
|
|
71
87
|
}
|
|
72
88
|
return r;
|
|
73
89
|
} else {
|
|
74
|
-
return s.type + "类型无效"
|
|
90
|
+
return s.type + "类型无效";
|
|
75
91
|
}
|
|
76
|
-
}
|
|
92
|
+
};
|
|
77
93
|
|
|
78
94
|
/** 根据定义返回View,返回nil表示没有可用的View */
|
|
79
|
-
getViewerOf(
|
|
95
|
+
getViewerOf(
|
|
96
|
+
f: MFieldSchemaAnonymity,
|
|
97
|
+
morph: MORPH
|
|
98
|
+
): ClassType<any, any, any> {
|
|
80
99
|
if (f.editor && morph === "editor") {
|
|
81
100
|
if (_.isString(f.editor)) {
|
|
82
101
|
return _.get(this.viewers, f.editor);
|
|
@@ -90,22 +109,30 @@ export class Assembly {
|
|
|
90
109
|
return f.readable;
|
|
91
110
|
}
|
|
92
111
|
} else {
|
|
93
|
-
const viewer: string | ClassType<MProp, any, any>
|
|
112
|
+
const viewer: string | ClassType<MProp, any, any> = _.get(
|
|
113
|
+
this.morph,
|
|
114
|
+
morph + "." + f.type
|
|
115
|
+
);
|
|
94
116
|
if (_.isString(viewer)) {
|
|
95
117
|
return _.get(this.viewers, viewer);
|
|
96
118
|
} else {
|
|
97
|
-
return viewer
|
|
119
|
+
return viewer;
|
|
98
120
|
}
|
|
99
121
|
}
|
|
100
122
|
}
|
|
101
123
|
|
|
102
|
-
validate(
|
|
124
|
+
validate(
|
|
125
|
+
s: MFieldSchemaAnonymity,
|
|
126
|
+
v: any,
|
|
127
|
+
path: string = ""
|
|
128
|
+
): MValidationFail | undefined {
|
|
103
129
|
let result: MValidationResult = undefined;
|
|
104
130
|
for (let validator of this.types[s.type].validators) {
|
|
105
131
|
result = validator(this, s, v, path);
|
|
106
|
-
|
|
132
|
+
|
|
133
|
+
if (result === "pass" && s.type !== "weight") {
|
|
107
134
|
return undefined;
|
|
108
|
-
} else if (result) {
|
|
135
|
+
} else if (typeof result === "object") {
|
|
109
136
|
MUtil.debug("校验", path, result.message);
|
|
110
137
|
return result;
|
|
111
138
|
}
|
|
@@ -115,8 +142,10 @@ export class Assembly {
|
|
|
115
142
|
|
|
116
143
|
addViewer(name: string, v: VIEWER) {
|
|
117
144
|
if (this.viewers[name]) {
|
|
118
|
-
console.error(
|
|
119
|
-
|
|
145
|
+
console.error(
|
|
146
|
+
`addViewer: 已经存在名为 ${name} 的 Viewer,无法再次添加!`
|
|
147
|
+
);
|
|
148
|
+
return;
|
|
120
149
|
} else {
|
|
121
150
|
this.viewers[name] = v;
|
|
122
151
|
}
|
|
@@ -124,8 +153,10 @@ export class Assembly {
|
|
|
124
153
|
|
|
125
154
|
addEditor(name: string, v: EDITOR) {
|
|
126
155
|
if (this.editors[name]) {
|
|
127
|
-
console.error(
|
|
128
|
-
|
|
156
|
+
console.error(
|
|
157
|
+
`addEditor: 已经存在名为 ${name} 的 Editor,无法再次添加!`
|
|
158
|
+
);
|
|
159
|
+
return;
|
|
129
160
|
} else {
|
|
130
161
|
this.editors[name] = v;
|
|
131
162
|
}
|
|
@@ -139,12 +170,11 @@ export class Assembly {
|
|
|
139
170
|
* @param typeParam 类型的描述对象
|
|
140
171
|
*/
|
|
141
172
|
addType(typeParam: PluginType) {
|
|
142
|
-
const { name, type, editor, readable = "DivViewer" } = typeParam
|
|
173
|
+
const { name, type, editor, readable = "DivViewer" } = typeParam;
|
|
143
174
|
this.types[name] = type;
|
|
144
|
-
|
|
175
|
+
|
|
145
176
|
_.set(this.morph, "editor." + name, editor);
|
|
146
177
|
_.set(this.morph, "readable." + name, readable);
|
|
147
|
-
|
|
148
178
|
}
|
|
149
179
|
|
|
150
180
|
constructor() {
|
package/src/framework/Init.tsx
CHANGED
|
@@ -34,6 +34,7 @@ import { AExperience } from "../ui/editor/complex/AExperience";
|
|
|
34
34
|
import { ACnAddress } from "../ui/editor/complex/ACnAddress";
|
|
35
35
|
import { AArray } from "../ui/editor/complex/AArray";
|
|
36
36
|
import { ACheckDrag } from "../ui/editor/complex/ACheckDrag";
|
|
37
|
+
import { AWeight } from "../ui/editor/complex/AWeight";
|
|
37
38
|
import { AArrayGrid } from "../ui/editor/complex/AArrayGrid";
|
|
38
39
|
import { ARangePicker } from "../ui/editor/basic/ARangePicker";
|
|
39
40
|
import { AIntDiff } from "../ui/editor/complex/AIntDiff";
|
|
@@ -48,6 +49,7 @@ import { A } from "../ui/readable/A";
|
|
|
48
49
|
import { ADialogForm } from "../ui/editor/complex/ADialogForm";
|
|
49
50
|
import { MVLPairType } from "../types/MVLPairType";
|
|
50
51
|
import { MKvSetType } from "../types/MKvSetType";
|
|
52
|
+
import { MWeightType } from "../types/MWeightType";
|
|
51
53
|
import { AKvSet } from "../ui/editor/basic/AKvSet";
|
|
52
54
|
import { ACascadePicker } from "../ui/editor/basic/ACascadePicker";
|
|
53
55
|
import { MCascadeType } from "../types/MCascadeType";
|
|
@@ -74,6 +76,7 @@ export function ensureM3() {
|
|
|
74
76
|
yearMonth: MDateTimeType,
|
|
75
77
|
yearMonthDay: MDateTimeType,
|
|
76
78
|
set: MSetType,
|
|
79
|
+
weight: MWeightType,
|
|
77
80
|
array: MArrayType,
|
|
78
81
|
string: MStringType,
|
|
79
82
|
intDiff: MIntDiffType,
|
|
@@ -127,6 +130,7 @@ export function ensureM3() {
|
|
|
127
130
|
ADialogForm: ADialogForm,
|
|
128
131
|
AKvSet: AKvSet,
|
|
129
132
|
ACascadePicker: ACascadePicker,
|
|
133
|
+
AWeight: AWeight,
|
|
130
134
|
});
|
|
131
135
|
|
|
132
136
|
assembly.morph = _.merge(assembly.morph, {
|
package/src/framework/M3.tsx
CHANGED
|
@@ -102,7 +102,7 @@ const M3 = (props: React.PropsWithChildren<M3Prop & { debug?: boolean }>) => {
|
|
|
102
102
|
|
|
103
103
|
return debug ? (
|
|
104
104
|
<MViewerDebug
|
|
105
|
-
key={k}
|
|
105
|
+
// key={k}
|
|
106
106
|
{...props}
|
|
107
107
|
database={database}
|
|
108
108
|
schema={schema}
|
|
@@ -111,7 +111,7 @@ const M3 = (props: React.PropsWithChildren<M3Prop & { debug?: boolean }>) => {
|
|
|
111
111
|
/>
|
|
112
112
|
) : (
|
|
113
113
|
<MViewer
|
|
114
|
-
key={k}
|
|
114
|
+
// key={k}
|
|
115
115
|
{...props}
|
|
116
116
|
database={database}
|
|
117
117
|
schema={schema}
|
|
@@ -68,14 +68,14 @@ interface State {
|
|
|
68
68
|
* 一个完整的表单
|
|
69
69
|
*/
|
|
70
70
|
export class MViewer extends React.Component<MViewerProp, State> {
|
|
71
|
-
database: any;
|
|
72
|
-
|
|
71
|
+
database: any = {};
|
|
73
72
|
constructor(p: MViewerProp) {
|
|
74
73
|
super(p);
|
|
75
74
|
this.state = {
|
|
76
75
|
forceValid: false,
|
|
77
76
|
ctrlVersion: 1,
|
|
78
77
|
};
|
|
78
|
+
console.log("执行 constructor");
|
|
79
79
|
|
|
80
80
|
ensureM3();
|
|
81
81
|
|
|
@@ -95,6 +95,32 @@ export class MViewer extends React.Component<MViewerProp, State> {
|
|
|
95
95
|
this.recover();
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
// ⚠️ 新增:监听 props 变化
|
|
99
|
+
componentDidUpdate(prevProps: MViewerProp) {
|
|
100
|
+
console.log("MViewer: componentDidUpdate");
|
|
101
|
+
// 检查 schema 是否变化
|
|
102
|
+
if (!_.isEqual(prevProps.schema, this.props.schema)) {
|
|
103
|
+
console.log("MViewer: schema changed", {
|
|
104
|
+
prevSchema: prevProps.schema,
|
|
105
|
+
nextSchema: this.props.schema,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// 重新初始化 database
|
|
109
|
+
this.database = assembly.types[this.props.schema.type]?.standardValue(
|
|
110
|
+
assembly,
|
|
111
|
+
this.props.schema,
|
|
112
|
+
this.props.database,
|
|
113
|
+
false
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
// 填入默认值
|
|
117
|
+
MUtil.applyDefaultValue(this.props.schema, this.props.database, "");
|
|
118
|
+
|
|
119
|
+
// 触发重新渲染
|
|
120
|
+
this.setState({ ctrlVersion: this.state.ctrlVersion + 1 });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
98
124
|
recover() {
|
|
99
125
|
const { ctrlVersion } = this.state;
|
|
100
126
|
const { persistant } = this.props;
|
|
@@ -109,11 +135,13 @@ export class MViewer extends React.Component<MViewerProp, State> {
|
|
|
109
135
|
const props = this.props;
|
|
110
136
|
const database = this.database;
|
|
111
137
|
const { ctrlVersion, forceValid } = this.state;
|
|
112
|
-
|
|
113
138
|
return (
|
|
114
139
|
<MContext.Provider
|
|
115
140
|
value={{
|
|
116
|
-
rootProps:
|
|
141
|
+
rootProps: {
|
|
142
|
+
...props,
|
|
143
|
+
database,
|
|
144
|
+
},
|
|
117
145
|
forceValid,
|
|
118
146
|
setForceValid: (b) => {
|
|
119
147
|
this.setState({ forceValid: true });
|
|
@@ -191,10 +219,6 @@ export function SubmitBar(props: {
|
|
|
191
219
|
ctx.rootProps.schema,
|
|
192
220
|
ctx.rootProps.database
|
|
193
221
|
);
|
|
194
|
-
// console.log("当前数据格式", {
|
|
195
|
-
// schema: ctx.rootProps.schema,
|
|
196
|
-
// database: ctx.rootProps.database,
|
|
197
|
-
// });
|
|
198
222
|
const submit = props.onSubmit ?? ctx.rootProps.onSubmit;
|
|
199
223
|
ctx.setForceValid(true);
|
|
200
224
|
if (r) {
|
|
@@ -1,32 +1,46 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
|
-
import { Assembly, assembly } from
|
|
3
|
-
import { MFieldSchemaAnonymity, MValidationResult} from
|
|
2
|
+
import { Assembly, assembly } from "./Assembly";
|
|
3
|
+
import { MFieldSchemaAnonymity, MValidationResult } from "./Schema";
|
|
4
4
|
|
|
5
|
-
export type VALIDATOR = (
|
|
5
|
+
export type VALIDATOR = (
|
|
6
|
+
a: Assembly,
|
|
7
|
+
schema: MFieldSchemaAnonymity,
|
|
8
|
+
value: any,
|
|
9
|
+
path: string
|
|
10
|
+
) => MValidationResult;
|
|
6
11
|
|
|
7
12
|
/**
|
|
8
13
|
* 非空校验,数据不能是null/undefined/""/NaN/[]
|
|
9
14
|
* 要在其他条件之前,以便required=false时短路掉nil的数据,否则后面的校验全都得处理nil
|
|
10
|
-
* @param a
|
|
11
|
-
* @param schema
|
|
12
|
-
* @param value
|
|
13
|
-
* @param path
|
|
14
|
-
* @returns
|
|
15
|
+
* @param a
|
|
16
|
+
* @param schema
|
|
17
|
+
* @param value
|
|
18
|
+
* @param path
|
|
19
|
+
* @returns
|
|
15
20
|
*/
|
|
16
|
-
export function validateRequired(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
export function validateRequired(
|
|
22
|
+
a: Assembly,
|
|
23
|
+
schema: MFieldSchemaAnonymity,
|
|
24
|
+
value: any,
|
|
25
|
+
path: string
|
|
26
|
+
): MValidationResult {
|
|
27
|
+
if (schema.required) {
|
|
28
|
+
if (
|
|
29
|
+
_.isNil(value) ||
|
|
30
|
+
value === "" ||
|
|
31
|
+
_.isNaN(value) ||
|
|
32
|
+
(_.isArray(value) && value.length == 0)
|
|
33
|
+
) {
|
|
34
|
+
return { message: "您还没有填完这一项", path };
|
|
21
35
|
}
|
|
22
36
|
// 凡是总有例外
|
|
23
|
-
if(schema.type === "set" && schema.openOption) {
|
|
24
|
-
if(value.length === 1 && !value[0]){
|
|
25
|
-
return {message:
|
|
37
|
+
if (schema.type === "set" && schema.openOption) {
|
|
38
|
+
if (value.length === 1 && !value[0]) {
|
|
39
|
+
return { message: "您还没有填完这一项", path }; // 开放set,只勾了开放选项,没有填内容,也要算空
|
|
26
40
|
}
|
|
27
41
|
}
|
|
28
42
|
} else {
|
|
29
|
-
if(_.isNil(value)) {
|
|
43
|
+
if (_.isNil(value)) {
|
|
30
44
|
return "pass";
|
|
31
45
|
}
|
|
32
46
|
}
|
|
@@ -34,22 +48,32 @@ export function validateRequired(a:Assembly, schema:MFieldSchemaAnonymity, value
|
|
|
34
48
|
}
|
|
35
49
|
|
|
36
50
|
/** 和validateRequired相同,但不短路 */
|
|
37
|
-
export function validateRequiredNS(
|
|
51
|
+
export function validateRequiredNS(
|
|
52
|
+
a: Assembly,
|
|
53
|
+
schema: MFieldSchemaAnonymity,
|
|
54
|
+
value: any,
|
|
55
|
+
path: string
|
|
56
|
+
): MValidationResult {
|
|
38
57
|
const v = validateRequired(a, schema, value, path);
|
|
39
|
-
if(v === "pass"){
|
|
58
|
+
if (v === "pass") {
|
|
40
59
|
return undefined;
|
|
41
60
|
}
|
|
42
61
|
}
|
|
43
62
|
|
|
44
|
-
export function validateDateMinMax(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
63
|
+
export function validateDateMinMax(
|
|
64
|
+
a: Assembly,
|
|
65
|
+
schema: MFieldSchemaAnonymity,
|
|
66
|
+
value: any,
|
|
67
|
+
path: string
|
|
68
|
+
): MValidationResult {
|
|
69
|
+
if (schema.min) {
|
|
70
|
+
if (!value || value < schema.min) {
|
|
71
|
+
return { message: `请选择${schema.min}之后的时间`, path };
|
|
48
72
|
}
|
|
49
73
|
}
|
|
50
|
-
if(schema.max){
|
|
51
|
-
if(!value || value > schema.max) {
|
|
52
|
-
return {message: `请选择${schema.min}之前的时间`, path};
|
|
74
|
+
if (schema.max) {
|
|
75
|
+
if (!value || value > schema.max) {
|
|
76
|
+
return { message: `请选择${schema.min}之前的时间`, path };
|
|
53
77
|
}
|
|
54
78
|
}
|
|
55
79
|
return undefined;
|
|
@@ -60,15 +84,20 @@ export function validateDateMinMax(a:Assembly, schema:MFieldSchemaAnonymity, val
|
|
|
60
84
|
* @param schema
|
|
61
85
|
* @param value 应该是个数组
|
|
62
86
|
*/
|
|
63
|
-
export function validateArrayItemMinMax(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
87
|
+
export function validateArrayItemMinMax(
|
|
88
|
+
a: Assembly,
|
|
89
|
+
schema: MFieldSchemaAnonymity,
|
|
90
|
+
value: any,
|
|
91
|
+
path: string
|
|
92
|
+
): MValidationResult {
|
|
93
|
+
if (schema.min) {
|
|
94
|
+
if (!value || value.length < schema.min) {
|
|
95
|
+
return { message: `至少选择${schema.min}项`, path };
|
|
67
96
|
}
|
|
68
97
|
}
|
|
69
|
-
if(schema.max){
|
|
70
|
-
if(!value || value.length > schema.max) {
|
|
71
|
-
return {message: `最多选择${schema.max}项`, path};
|
|
98
|
+
if (schema.max) {
|
|
99
|
+
if (!value || value.length > schema.max) {
|
|
100
|
+
return { message: `最多选择${schema.max}项`, path };
|
|
72
101
|
}
|
|
73
102
|
}
|
|
74
103
|
return undefined;
|
|
@@ -79,15 +108,20 @@ export function validateArrayItemMinMax(a:Assembly, schema:MFieldSchemaAnonymity
|
|
|
79
108
|
* @param schema
|
|
80
109
|
* @param value 应该是个字符串
|
|
81
110
|
*/
|
|
82
|
-
export function validateStringMinMax(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
111
|
+
export function validateStringMinMax(
|
|
112
|
+
a: Assembly,
|
|
113
|
+
schema: MFieldSchemaAnonymity,
|
|
114
|
+
value: any,
|
|
115
|
+
path: string
|
|
116
|
+
): MValidationResult {
|
|
117
|
+
if (schema.min) {
|
|
118
|
+
if (!value || value.length < schema.min) {
|
|
119
|
+
return { message: `至少${schema.min}个字`, path };
|
|
86
120
|
}
|
|
87
121
|
}
|
|
88
|
-
if(schema.max){
|
|
89
|
-
if(value && value.length > schema.max) {
|
|
90
|
-
return {message: `最多${schema.max}个字`, path};
|
|
122
|
+
if (schema.max) {
|
|
123
|
+
if (value && value.length > schema.max) {
|
|
124
|
+
return { message: `最多${schema.max}个字`, path };
|
|
91
125
|
}
|
|
92
126
|
}
|
|
93
127
|
return undefined;
|
|
@@ -98,29 +132,42 @@ export function validateStringMinMax(a:Assembly, schema:MFieldSchemaAnonymity, v
|
|
|
98
132
|
* @param schema
|
|
99
133
|
* @param value 应该是个数字
|
|
100
134
|
*/
|
|
101
|
-
export function validateNumberMinMax(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
135
|
+
export function validateNumberMinMax(
|
|
136
|
+
a: Assembly,
|
|
137
|
+
schema: MFieldSchemaAnonymity,
|
|
138
|
+
value: any,
|
|
139
|
+
path: string
|
|
140
|
+
): MValidationResult {
|
|
141
|
+
const temp = Number(value);
|
|
142
|
+
if (!_.isNil(schema.max)) {
|
|
143
|
+
if (!_.isFinite(temp) || temp > schema.max) {
|
|
144
|
+
return { message: `最多${schema.max}`, path };
|
|
106
145
|
}
|
|
107
146
|
}
|
|
108
|
-
if(!_.isNil(schema.min)){
|
|
109
|
-
if(!_.isFinite(temp) || temp < schema.min) {
|
|
110
|
-
return {message: `最少${schema.min}`, path};
|
|
147
|
+
if (!_.isNil(schema.min)) {
|
|
148
|
+
if (!_.isFinite(temp) || temp < schema.min) {
|
|
149
|
+
return { message: `最少${schema.min}`, path };
|
|
111
150
|
}
|
|
112
151
|
}
|
|
113
152
|
return undefined;
|
|
114
153
|
}
|
|
115
154
|
|
|
116
|
-
export function generateRegexValidate(
|
|
117
|
-
|
|
155
|
+
export function generateRegexValidate(
|
|
156
|
+
regex: RegExp,
|
|
157
|
+
mismatchMsg: string
|
|
158
|
+
): VALIDATOR {
|
|
159
|
+
return function (
|
|
160
|
+
a: Assembly,
|
|
161
|
+
schema: MFieldSchemaAnonymity,
|
|
162
|
+
value: any,
|
|
163
|
+
path: string
|
|
164
|
+
): MValidationResult {
|
|
118
165
|
const asstr = _.toString(value);
|
|
119
|
-
if(
|
|
120
|
-
return {message: mismatchMsg, path};
|
|
166
|
+
if (!regex.test(asstr)) {
|
|
167
|
+
return { message: mismatchMsg, path };
|
|
121
168
|
}
|
|
122
169
|
return undefined;
|
|
123
|
-
}
|
|
170
|
+
};
|
|
124
171
|
}
|
|
125
172
|
|
|
126
173
|
/**
|
|
@@ -128,27 +175,43 @@ export function generateRegexValidate(regex:RegExp, mismatchMsg:string):VALIDATO
|
|
|
128
175
|
* 可以用Object.prototype.toString.call(<预期的类型>)来查看你想要的数据类型的expectType
|
|
129
176
|
* @param expectType 预期类型,例如:"[object Object]" "[object Null]" "[object Number]" "[object Date]" "[object Array]"
|
|
130
177
|
* @param mismatchMsg 如果不匹配,提示的错误信息
|
|
131
|
-
* @returns
|
|
178
|
+
* @returns
|
|
132
179
|
*/
|
|
133
|
-
export function generateJsPrototypeValidate(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
180
|
+
export function generateJsPrototypeValidate(
|
|
181
|
+
expectType: string,
|
|
182
|
+
mismatchMsg: string = "数据有误,请重填此项"
|
|
183
|
+
): VALIDATOR {
|
|
184
|
+
return function (
|
|
185
|
+
a: Assembly,
|
|
186
|
+
schema: MFieldSchemaAnonymity,
|
|
187
|
+
value: any,
|
|
188
|
+
path: string
|
|
189
|
+
): MValidationResult {
|
|
190
|
+
if (Object.prototype.toString.call(value) == expectType) {
|
|
191
|
+
return undefined;
|
|
137
192
|
} else {
|
|
138
|
-
return {message: mismatchMsg, path};
|
|
193
|
+
return { message: mismatchMsg, path };
|
|
139
194
|
}
|
|
140
|
-
}
|
|
195
|
+
};
|
|
141
196
|
}
|
|
142
197
|
|
|
143
|
-
export function generateSchemaValidate(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
198
|
+
export function generateSchemaValidate(
|
|
199
|
+
valueSchema: MFieldSchemaAnonymity,
|
|
200
|
+
mismatchMsg?: string
|
|
201
|
+
): VALIDATOR {
|
|
202
|
+
return function (
|
|
203
|
+
a: Assembly,
|
|
204
|
+
schema: MFieldSchemaAnonymity,
|
|
205
|
+
value: any,
|
|
206
|
+
path: string
|
|
207
|
+
): MValidationResult {
|
|
208
|
+
const r = assembly.validate(valueSchema, value, "");
|
|
209
|
+
if (!r) {
|
|
147
210
|
return r;
|
|
148
211
|
} else {
|
|
149
|
-
return {message: mismatchMsg ?? r.message, path};
|
|
212
|
+
return { message: mismatchMsg ?? r.message, path };
|
|
150
213
|
}
|
|
151
|
-
}
|
|
214
|
+
};
|
|
152
215
|
}
|
|
153
216
|
|
|
154
217
|
export default {
|
|
@@ -157,5 +220,5 @@ export default {
|
|
|
157
220
|
validateDateMinMax,
|
|
158
221
|
validateStringMinMax,
|
|
159
222
|
validateNumberMinMax,
|
|
160
|
-
generateRegexValidate
|
|
161
|
-
}
|
|
223
|
+
generateRegexValidate,
|
|
224
|
+
};
|
package/src/types/MSetType.ts
CHANGED
|
@@ -18,7 +18,7 @@ function validateCandidate(
|
|
|
18
18
|
): MValidationResult {
|
|
19
19
|
let fs = MUtil.option(schema);
|
|
20
20
|
const openOption = _.clone(schema.openOption ?? schema.setOpen);
|
|
21
|
-
|
|
21
|
+
if (!value) return undefined;
|
|
22
22
|
for (let v of value) {
|
|
23
23
|
let vIsOk = false;
|
|
24
24
|
for (let f of fs) {
|