form-driver 0.1.0
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/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/m3.css +310 -0
- package/dist/m3.js +1 -0
- package/es/m3.css +310 -0
- package/es/m3.js +20919 -0
- package/lib/m3.css +310 -0
- package/lib/m3.js +20959 -0
- package/package.json +132 -0
- package/src/.DS_Store +0 -0
- package/src/framework/Ajax.ts +96 -0
- package/src/framework/Assembly.tsx +165 -0
- package/src/framework/Init.tsx +196 -0
- package/src/framework/M3.tsx +94 -0
- package/src/framework/MContext.ts +15 -0
- package/src/framework/MFieldViewer.tsx +32 -0
- package/src/framework/MUtil.tsx +653 -0
- package/src/framework/MViewer.less +128 -0
- package/src/framework/MViewer.tsx +180 -0
- package/src/framework/MViewerDebug.tsx +95 -0
- package/src/framework/Persistant.ts +90 -0
- package/src/framework/Schema.ts +386 -0
- package/src/framework/SchemaFunc.ts +30 -0
- package/src/framework/Validator.ts +160 -0
- package/src/framework/editorMap.ts +109 -0
- package/src/index.ts +33 -0
- package/src/types/MArrayType.ts +73 -0
- package/src/types/MCascadeType.ts +35 -0
- package/src/types/MCnAddressType.ts +54 -0
- package/src/types/MDateRangeType.ts +52 -0
- package/src/types/MDateTimeType.ts +53 -0
- package/src/types/MDecorationType.ts +6 -0
- package/src/types/MEnumType.ts +65 -0
- package/src/types/MExperienceType.ts +81 -0
- package/src/types/MFloatType.ts +10 -0
- package/src/types/MGB2260Type.ts +56 -0
- package/src/types/MIntDiffType.ts +6 -0
- package/src/types/MIntType.ts +44 -0
- package/src/types/MKvSetType.ts +50 -0
- package/src/types/MMatrixType.ts +52 -0
- package/src/types/MObjectType.ts +89 -0
- package/src/types/MSetType.ts +220 -0
- package/src/types/MStringType.ts +27 -0
- package/src/types/MTelType.ts +14 -0
- package/src/types/MType.ts +77 -0
- package/src/types/MVLPairType.ts +35 -0
- package/src/types/gb2260.json +1 -0
- package/src/ui/BaseViewer.tsx +110 -0
- package/src/ui/editor/.DS_Store +0 -0
- package/src/ui/editor/basic/.DS_Store +0 -0
- package/src/ui/editor/basic/ACascadePicker.tsx +114 -0
- package/src/ui/editor/basic/ACheckBox.tsx +104 -0
- package/src/ui/editor/basic/ADatetimePicker.tsx +76 -0
- package/src/ui/editor/basic/AGB2260.tsx +52 -0
- package/src/ui/editor/basic/AInputBox.tsx +59 -0
- package/src/ui/editor/basic/AIntBox.tsx +39 -0
- package/src/ui/editor/basic/AKvSet.less +9 -0
- package/src/ui/editor/basic/AKvSet.tsx +90 -0
- package/src/ui/editor/basic/ARadio.tsx +86 -0
- package/src/ui/editor/basic/ARangePicker.tsx +129 -0
- package/src/ui/editor/basic/ARate.less +8 -0
- package/src/ui/editor/basic/ARate.tsx +37 -0
- package/src/ui/editor/basic/ARemoteSelector.tsx +116 -0
- package/src/ui/editor/basic/ASelector.tsx +88 -0
- package/src/ui/editor/basic/ASetSelector.tsx +65 -0
- package/src/ui/editor/basic/ASpecInputBox.tsx +20 -0
- package/src/ui/editor/basic/ATreeSelect.tsx +41 -0
- package/src/ui/editor/basic/AUpload.tsx +119 -0
- package/src/ui/editor/basic/NPS.less +21 -0
- package/src/ui/editor/basic/NPS.tsx +47 -0
- package/src/ui/editor/complex/AArray.less +10 -0
- package/src/ui/editor/complex/AArray.tsx +104 -0
- package/src/ui/editor/complex/AArrayGrid.tsx +115 -0
- package/src/ui/editor/complex/ACnAddress.less +15 -0
- package/src/ui/editor/complex/ACnAddress.tsx +61 -0
- package/src/ui/editor/complex/ADialogForm.tsx +45 -0
- package/src/ui/editor/complex/AExperience.tsx +85 -0
- package/src/ui/editor/complex/AForm.less +35 -0
- package/src/ui/editor/complex/AForm.tsx +340 -0
- package/src/ui/editor/complex/AIntDiff.tsx +77 -0
- package/src/ui/editor/complex/AMatrix.less +18 -0
- package/src/ui/editor/complex/AMatrix.tsx +242 -0
- package/src/ui/editor/complex/ATable.less +4 -0
- package/src/ui/editor/complex/ATable.tsx +33 -0
- package/src/ui/editor/complex/JsonEditor.tsx +37 -0
- package/src/ui/readable/A.tsx +33 -0
- package/src/ui/readable/ArrayViewer.tsx +46 -0
- package/src/ui/readable/DecorationViewer.tsx +76 -0
- package/src/ui/readable/DivViewer.tsx +11 -0
- package/src/ui/widget/Collapsible.tsx +156 -0
- package/src/ui/widget/Segment.less +39 -0
- package/src/ui/widget/Segment.tsx +40 -0
- package/src/ui/widget/SegmentEditSwitch.tsx +46 -0
- package/src/ui/widget/SelectBox.tsx +43 -0
- package/src/ui/widget/UnderlineInputBox.less +47 -0
- package/src/ui/widget/UnderlineInputBox.tsx +10 -0
- package/types/framework/Ajax.d.ts +5 -0
- package/types/framework/Assembly.d.ts +59 -0
- package/types/framework/Init.d.ts +4 -0
- package/types/framework/M3.d.ts +6 -0
- package/types/framework/MContext.d.ts +11 -0
- package/types/framework/MFieldViewer.d.ts +8 -0
- package/types/framework/MUtil.d.ts +180 -0
- package/types/framework/MViewer.d.ts +75 -0
- package/types/framework/MViewerDebug.d.ts +11 -0
- package/types/framework/Persistant.d.ts +17 -0
- package/types/framework/Schema.d.ts +306 -0
- package/types/framework/SchemaFunc.d.ts +14 -0
- package/types/framework/Validator.d.ts +53 -0
- package/types/framework/editorMap.d.ts +107 -0
- package/types/index.d.ts +21 -0
- package/types/types/MArrayType.d.ts +2 -0
- package/types/types/MCascadeType.d.ts +11 -0
- package/types/types/MCnAddressType.d.ts +2 -0
- package/types/types/MDateRangeType.d.ts +7 -0
- package/types/types/MDateTimeType.d.ts +11 -0
- package/types/types/MDecorationType.d.ts +7 -0
- package/types/types/MEnumType.d.ts +2 -0
- package/types/types/MExperienceType.d.ts +5 -0
- package/types/types/MFloatType.d.ts +2 -0
- package/types/types/MGB2260Type.d.ts +9 -0
- package/types/types/MIntDiffType.d.ts +2 -0
- package/types/types/MIntType.d.ts +2 -0
- package/types/types/MKvSetType.d.ts +11 -0
- package/types/types/MMatrixType.d.ts +5 -0
- package/types/types/MObjectType.d.ts +11 -0
- package/types/types/MSetType.d.ts +7 -0
- package/types/types/MStringType.d.ts +2 -0
- package/types/types/MTelType.d.ts +4 -0
- package/types/types/MType.d.ts +46 -0
- package/types/types/MVLPairType.d.ts +5 -0
- package/types/ui/BaseViewer.d.ts +45 -0
- package/types/ui/editor/basic/ACascadePicker.d.ts +11 -0
- package/types/ui/editor/basic/ACheckBox.d.ts +17 -0
- package/types/ui/editor/basic/ADatetimePicker.d.ts +15 -0
- package/types/ui/editor/basic/AGB2260.d.ts +10 -0
- package/types/ui/editor/basic/AInputBox.d.ts +8 -0
- package/types/ui/editor/basic/AIntBox.d.ts +9 -0
- package/types/ui/editor/basic/AKvSet.d.ts +19 -0
- package/types/ui/editor/basic/ARadio.d.ts +14 -0
- package/types/ui/editor/basic/ARangePicker.d.ts +30 -0
- package/types/ui/editor/basic/ARate.d.ts +13 -0
- package/types/ui/editor/basic/ARemoteSelector.d.ts +15 -0
- package/types/ui/editor/basic/ASelector.d.ts +14 -0
- package/types/ui/editor/basic/ASetSelector.d.ts +10 -0
- package/types/ui/editor/basic/ASpecInputBox.d.ts +9 -0
- package/types/ui/editor/basic/ATreeSelect.d.ts +18 -0
- package/types/ui/editor/basic/AUpload.d.ts +33 -0
- package/types/ui/editor/basic/NPS.d.ts +13 -0
- package/types/ui/editor/complex/AArray.d.ts +11 -0
- package/types/ui/editor/complex/AArrayGrid.d.ts +13 -0
- package/types/ui/editor/complex/ACnAddress.d.ts +10 -0
- package/types/ui/editor/complex/ADialogForm.d.ts +11 -0
- package/types/ui/editor/complex/AExperience.d.ts +16 -0
- package/types/ui/editor/complex/AForm.d.ts +46 -0
- package/types/ui/editor/complex/AIntDiff.d.ts +14 -0
- package/types/ui/editor/complex/AMatrix.d.ts +48 -0
- package/types/ui/editor/complex/ATable.d.ts +9 -0
- package/types/ui/editor/complex/JsonEditor.d.ts +9 -0
- package/types/ui/readable/A.d.ts +5 -0
- package/types/ui/readable/ArrayViewer.d.ts +5 -0
- package/types/ui/readable/DecorationViewer.d.ts +3 -0
- package/types/ui/readable/DivViewer.d.ts +5 -0
- package/types/ui/widget/Collapsible.d.ts +46 -0
- package/types/ui/widget/Segment.d.ts +18 -0
- package/types/ui/widget/SegmentEditSwitch.d.ts +20 -0
- package/types/ui/widget/SelectBox.d.ts +13 -0
- package/types/ui/widget/UnderlineInputBox.d.ts +6 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { MUtil } from "../framework/MUtil";
|
|
2
|
+
import { MFieldSchemaAnonymity, MValidationResult } from "../framework/Schema";
|
|
3
|
+
import { MType } from "./MType";
|
|
4
|
+
import { validateRequired } from "../framework/Validator";
|
|
5
|
+
import _, { result } from "lodash";
|
|
6
|
+
import { Assembly } from '../framework/Assembly';
|
|
7
|
+
|
|
8
|
+
export function validateObject(assembly:Assembly, schema:MFieldSchemaAnonymity, value:any, path:string): MValidationResult {
|
|
9
|
+
if(schema.objectFields){
|
|
10
|
+
let objectFieldMap = _.chain(schema.objectFields).keyBy('name').value();
|
|
11
|
+
if(schema.uispec?.segments){
|
|
12
|
+
const fields = _.flatten(schema.uispec?.segments.map(e=>e.fields)).filter(e=>_.isString(e)) as string[];
|
|
13
|
+
objectFieldMap = _.pick(objectFieldMap, fields);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const hideMap = MUtil.hideMap(value, schema.objectFields);
|
|
17
|
+
for(let k in objectFieldMap){
|
|
18
|
+
const f = objectFieldMap[k];
|
|
19
|
+
if(hideMap[k]){ // 隐藏的字段不要校验
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const r = assembly.validate(f, _.get(value, f.name), path ? path + "." + f.name : f.name);
|
|
23
|
+
if(r){
|
|
24
|
+
return r;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} else if(!_.isNil(value) && !_.isObject(value)){
|
|
28
|
+
return {message: "不是有效JSON", path};
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* JSON对象
|
|
35
|
+
* 注意:
|
|
36
|
+
* 1. string/number/boolean等不算有效的JSON对象
|
|
37
|
+
* 2. undefined/null在required=false时是有效的
|
|
38
|
+
*/
|
|
39
|
+
export const MObjectType: MType = {
|
|
40
|
+
validators: [validateRequired, validateObject],
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 对象转换成readable文案时,会默认选择展示对象的label/name/id,如果都没有,展示JSON.stringify后的字符串
|
|
44
|
+
* @param assembly
|
|
45
|
+
* @param s
|
|
46
|
+
* @param vs
|
|
47
|
+
*/
|
|
48
|
+
toReadable: (assembly:Assembly, s:MFieldSchemaAnonymity, vs:any):string => {
|
|
49
|
+
if(_.isNil(vs)){
|
|
50
|
+
return assembly.theme.READABLE_BLANK;
|
|
51
|
+
} else if(_.isObject(vs)) {
|
|
52
|
+
return vs["label"] ?? vs["name"] ?? vs["id"] ?? JSON.stringify(vs);
|
|
53
|
+
} else {
|
|
54
|
+
return result.toString();
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
standardValue: (assembly:Assembly, s:MFieldSchemaAnonymity, v:any, strict: boolean):any => {
|
|
59
|
+
// 类型正确
|
|
60
|
+
if(!_.isObject(v)) {
|
|
61
|
+
return s.defaultValue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 数值正确
|
|
65
|
+
// 注意,m3的object是开放的,允许数据中出现未定义的字段,所以只处理在schema里有的字段,不会改变schema里没有的字段
|
|
66
|
+
for(let f of s.objectFields) {
|
|
67
|
+
const type = assembly.types[f.type];
|
|
68
|
+
if(!type){
|
|
69
|
+
console.warn(`对象成员字段${f.name}的类型无效:${f.type}`)
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
v[f.name] = type.standardValue(assembly, f, v[f.name], strict);
|
|
73
|
+
}
|
|
74
|
+
return v;
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
createDefaultValue: (assembly:Assembly, schema:MFieldSchemaAnonymity):any =>{
|
|
78
|
+
let newItem;
|
|
79
|
+
if(schema.defaultValue){
|
|
80
|
+
newItem = _.cloneDeep(schema.defaultValue);
|
|
81
|
+
} else {
|
|
82
|
+
newItem = {};
|
|
83
|
+
for(let memberField of schema.objectFields){
|
|
84
|
+
newItem[memberField.name] = assembly.types[memberField.type]?.createDefaultValue(assembly, memberField);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return newItem;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
|
|
2
|
+
import { MUtil } from "../framework/MUtil";
|
|
3
|
+
import { MFieldSchemaAnonymity, MValidationResult } from "../framework/Schema";
|
|
4
|
+
import { MType} from "./MType";
|
|
5
|
+
|
|
6
|
+
import { validateArrayItemMinMax, validateRequired } from "../framework/Validator";
|
|
7
|
+
import { assembly, Assembly } from "../framework/Assembly";
|
|
8
|
+
import _ from "lodash";
|
|
9
|
+
|
|
10
|
+
// 选项是否合法、开放选项是否合法
|
|
11
|
+
function validateCandidate(a:Assembly, schema:MFieldSchemaAnonymity, value:any, path:string): MValidationResult {
|
|
12
|
+
let fs = MUtil.option(schema);
|
|
13
|
+
const openOption = _.clone(schema.openOption ?? schema.setOpen)
|
|
14
|
+
|
|
15
|
+
for(let v of value){
|
|
16
|
+
let vIsOk = false;
|
|
17
|
+
for(let f of fs){
|
|
18
|
+
if(MUtil.isEquals(f.value, v, schema.tolerate)){
|
|
19
|
+
vIsOk = true;
|
|
20
|
+
break; // v校验ok
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if(!vIsOk) {
|
|
24
|
+
if(openOption) {
|
|
25
|
+
openOption.required = true; // 既然勾上了开放选项,就必须填
|
|
26
|
+
const vr = assembly.validate(openOption, v, path);
|
|
27
|
+
if(vr) { // 开放值无效
|
|
28
|
+
return vr;
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
return {message:"请重新选择", path};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const MSetType: MType & {
|
|
39
|
+
change: (isAdd:boolean, newValue:any, value:any[], s:MFieldSchemaAnonymity)=>any[],
|
|
40
|
+
openValueIndex: (s:MFieldSchemaAnonymity, vs: any[])=>number,
|
|
41
|
+
clearOpenValue: (s:MFieldSchemaAnonymity, vs: any[], keepOne:boolean)=>any[]
|
|
42
|
+
} = {
|
|
43
|
+
validators: [validateRequired, validateCandidate, validateArrayItemMinMax],
|
|
44
|
+
|
|
45
|
+
toReadable: (assembly:Assembly, s:MFieldSchemaAnonymity, vs:any):string => {
|
|
46
|
+
const fs = MUtil.option(s);
|
|
47
|
+
if(_.isNil(vs)){
|
|
48
|
+
return assembly.theme.READABLE_BLANK;
|
|
49
|
+
} else if(!_.isArray(vs)){
|
|
50
|
+
return assembly.theme.READABLE_ERROR;
|
|
51
|
+
}
|
|
52
|
+
return vs.map((v:any) => {
|
|
53
|
+
for(let f of fs) {
|
|
54
|
+
if(f.value === v){
|
|
55
|
+
return f.label ?? v;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return s.openOption ? v : assembly.theme.READABLE_INVALID
|
|
59
|
+
}).join(", ");
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
standardValue: (a:Assembly, s:MFieldSchemaAnonymity, vs:any, strict:boolean):any => {
|
|
63
|
+
// 类型正确
|
|
64
|
+
if(!_.isArray(vs)){
|
|
65
|
+
return s.defaultValue;
|
|
66
|
+
}
|
|
67
|
+
if(!strict){
|
|
68
|
+
return vs;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 数值正确
|
|
72
|
+
const fs = MUtil.option(s);
|
|
73
|
+
const result = [];
|
|
74
|
+
let openValueFound = false; // 只能有一个开放值
|
|
75
|
+
for(let v of vs) {
|
|
76
|
+
let matched = false;
|
|
77
|
+
for(let f of fs){
|
|
78
|
+
if(MUtil.isEquals(f.value, v, s.tolerate)){
|
|
79
|
+
result.push(v)
|
|
80
|
+
matched = true;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if((s.openOption ?? s.setOpen)&& !matched && !openValueFound && !_.isNil(v)) { // 使用第一个非nil的开放值
|
|
85
|
+
openValueFound = true;
|
|
86
|
+
result.push(v);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 考虑exclusive和max的情况下,计算新增/删除一个值以后集合应该变成什么
|
|
94
|
+
* @param isAdd true=要向prevValue里新增newValue,false=要从prevValue里去除newValue
|
|
95
|
+
* @param newValue 要加入或者去除的值
|
|
96
|
+
* @param prevValue 数组形式的newValue加入或者去除前的集合
|
|
97
|
+
* @param s schema
|
|
98
|
+
* @returns 修改后的集合,可能不是newValue对象
|
|
99
|
+
*/
|
|
100
|
+
change: (isAdd:boolean, newValue:any, prevValue:any[], s:MFieldSchemaAnonymity):any[] => {
|
|
101
|
+
if(isAdd) {
|
|
102
|
+
// 如果有多个不在option中的值,就只保留一个
|
|
103
|
+
prevValue = MSetType.clearOpenValue(s, prevValue, true);
|
|
104
|
+
|
|
105
|
+
if(prevValue?.indexOf(newValue) >= 0){ // 如果要add的值已经存在了,直接返回即可
|
|
106
|
+
return prevValue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 处理排他选项
|
|
110
|
+
const option = MUtil.option(s);
|
|
111
|
+
const newFs = _.find(option, {value:newValue});
|
|
112
|
+
// 把所有exclusive跟自己不同的都清掉(newFs空是开放选项,不用管)
|
|
113
|
+
if(newFs) {
|
|
114
|
+
prevValue = prevValue?.filter(v => {
|
|
115
|
+
const fs = _.find(option, {value:v});
|
|
116
|
+
if(fs && fs.exclusive !== newFs.exclusive) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 新值加入
|
|
124
|
+
if(!_.isArray(prevValue)){
|
|
125
|
+
prevValue = [];
|
|
126
|
+
}
|
|
127
|
+
prevValue.push(newValue);
|
|
128
|
+
|
|
129
|
+
// 处理max限制
|
|
130
|
+
const max = s.max ?? Number.MAX_VALUE;
|
|
131
|
+
while(max > 0 && prevValue.length > max) { // 超过上限了,要删到上限为止,但不能删新加的那条
|
|
132
|
+
for(let d of prevValue) {
|
|
133
|
+
if(d !== newValue){
|
|
134
|
+
MUtil.arrayRemove(prevValue, d);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
MUtil.arrayRemove(prevValue, newValue);
|
|
141
|
+
|
|
142
|
+
// 如果有多个不在option中的值,就只保留一个
|
|
143
|
+
prevValue = MSetType.clearOpenValue(s, prevValue, true);
|
|
144
|
+
}
|
|
145
|
+
if(!prevValue?.length) { // 如果删光了,或者只剩个开放选项,但是没有填
|
|
146
|
+
prevValue = undefined;
|
|
147
|
+
}
|
|
148
|
+
return prevValue;
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 清除不在option中的选项
|
|
153
|
+
* @param s schema
|
|
154
|
+
* @param vs 值
|
|
155
|
+
* @param keepOne 是否在schema允许的情况下(有openOption)保留一个有意义的(尽量非nil)开放选项
|
|
156
|
+
*/
|
|
157
|
+
clearOpenValue: (s:MFieldSchemaAnonymity, vs: any[], keepOne:boolean):any[] =>{
|
|
158
|
+
if(!vs){
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const opt = MUtil.option(s);
|
|
162
|
+
const result = [];
|
|
163
|
+
|
|
164
|
+
let openValue;
|
|
165
|
+
let openValueFound = false;
|
|
166
|
+
|
|
167
|
+
for(let i = 0; i < vs.length; i ++) {
|
|
168
|
+
const matched = opt.find(o => MUtil.isEquals(vs[i], o.value, s.tolerate));
|
|
169
|
+
if(matched) {
|
|
170
|
+
result.push(matched.value);
|
|
171
|
+
} else {
|
|
172
|
+
openValue = openValue ?? vs[i]
|
|
173
|
+
openValueFound = true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if(openValueFound && keepOne && (s.openOption ?? s.setOpen)) {
|
|
178
|
+
result.push(openValue);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return result;
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 获取开放选项的下标。
|
|
186
|
+
* @param s
|
|
187
|
+
* @param vs
|
|
188
|
+
* 1. 优先把nil值作为开放选项(为了尽量保留有意义的值)
|
|
189
|
+
* 2. 如果没有nil,最后一个在option中未出现的值作为开放选项
|
|
190
|
+
* 例如
|
|
191
|
+
* openValueIndex(assembly, [a,b,c], [a, e, null, f]) = 2
|
|
192
|
+
* openValueIndex(assembly, [a,b,c], [a, e, d, f]) = 3
|
|
193
|
+
* @returns -1表示没有找到开放选项
|
|
194
|
+
*/
|
|
195
|
+
openValueIndex: (s:MFieldSchemaAnonymity, vs: any[]):number =>{
|
|
196
|
+
if(!vs){
|
|
197
|
+
return -1;
|
|
198
|
+
}
|
|
199
|
+
const opt = MUtil.option(s);
|
|
200
|
+
let openIdx = -1;
|
|
201
|
+
for(let i = 0; i < vs.length; i ++) {
|
|
202
|
+
const v = vs[i];
|
|
203
|
+
if(_.isNil(v)) {
|
|
204
|
+
return i;
|
|
205
|
+
}
|
|
206
|
+
if(! opt.find(o => MUtil.isEquals(v, o.value, s.tolerate)) ) {
|
|
207
|
+
openIdx = i;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return openIdx;
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
createDefaultValue: (assembly:Assembly, s:MFieldSchemaAnonymity):any =>{
|
|
214
|
+
if(s.defaultValue){
|
|
215
|
+
return _.clone(s.defaultValue);
|
|
216
|
+
} else {
|
|
217
|
+
return []; // 默认不选
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
import { MFieldSchemaAnonymity } from "../framework/Schema";
|
|
3
|
+
import { EmtpyType, MType} from "./MType";
|
|
4
|
+
import { validateRequired, validateStringMinMax, generateRegexValidate } from '../framework/Validator';
|
|
5
|
+
import { Assembly } from '../framework/Assembly';
|
|
6
|
+
import _ from "lodash";
|
|
7
|
+
|
|
8
|
+
export const MStringType: MType = _.assign({}, EmtpyType, {
|
|
9
|
+
validators: [validateRequired, generateRegexValidate(/[^\s]|(^$)/, "不能全都填空格"), validateStringMinMax],
|
|
10
|
+
|
|
11
|
+
createDefaultValue: (assembly:Assembly, s:MFieldSchemaAnonymity):any =>{
|
|
12
|
+
return s.defaultValue ?? "";
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
toReadable: (assembly:Assembly, s:MFieldSchemaAnonymity, vs:any):string => {
|
|
16
|
+
if(_.isNil(vs)){
|
|
17
|
+
return assembly.theme.READABLE_BLANK;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if(!_.isString(vs)){
|
|
21
|
+
return assembly.theme.READABLE_INVALID;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return vs;
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
import { EmtpyType, MType} from "./MType";
|
|
3
|
+
import { validateRequired, generateRegexValidate } from '../framework/Validator';
|
|
4
|
+
import _ from "lodash";
|
|
5
|
+
|
|
6
|
+
export const MCnPhoneType: MType = _.assign({}, EmtpyType, {
|
|
7
|
+
validators: [validateRequired, generateRegexValidate(/^1[3456789]\d{9}$/, "输入有效手机号")],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const MEmailType: MType = _.assign({}, EmtpyType, {
|
|
11
|
+
validators: [validateRequired, generateRegexValidate(/^.+[@].+[.].+$/, "输入有效电子邮件地址")],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const MTelType = MCnPhoneType;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { MFieldSchemaAnonymity } from '../framework/Schema';
|
|
2
|
+
import { VALIDATOR } from "../framework/Validator";
|
|
3
|
+
import { Assembly } from '../framework/Assembly';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import { ClassType } from 'react';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 定义一个数据类型的处理规则
|
|
9
|
+
*/
|
|
10
|
+
export interface MType {
|
|
11
|
+
/** 这种数据类型的验证器 */
|
|
12
|
+
validators: VALIDATOR[];
|
|
13
|
+
|
|
14
|
+
/** 将字段值转换成可读字符串的表达式 */
|
|
15
|
+
toReadable: (assembly:Assembly, s:MFieldSchemaAnonymity, v:any)=>string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 预处理数据,使其符合schema描述
|
|
19
|
+
* 1. strict=true:处理后完全符合schema描述,例如set中option未出现的值,对于有tolerate配置的enum选项转换成option中的值
|
|
20
|
+
* 2. strict=false:处理后数据类型符合schema描述,但值未必符合,例如保证set值是数组,但可能并非都是schema中定义的候选值
|
|
21
|
+
* 3. 即使strict模式,nil也是被允许的,表示值未填
|
|
22
|
+
* 4. 如果数据类型不正确,此方法应返回defaultValue
|
|
23
|
+
* @param strict 严格模式
|
|
24
|
+
*/
|
|
25
|
+
standardValue: (assembly:Assembly, s:MFieldSchemaAnonymity, v:any, strict:boolean)=>any;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 获取此类型的默认值
|
|
29
|
+
*/
|
|
30
|
+
createDefaultValue:(assembly:Assembly, s:MFieldSchemaAnonymity)=>any;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 定义一个插件类型
|
|
35
|
+
*/
|
|
36
|
+
export interface PluginType {
|
|
37
|
+
/** 数据类型的字段 */
|
|
38
|
+
name: string;
|
|
39
|
+
|
|
40
|
+
/** 数据类型的处理规则 */
|
|
41
|
+
type: MType;
|
|
42
|
+
|
|
43
|
+
/** 数据类型的编辑模式 */
|
|
44
|
+
editor: ClassType<any, any, any> | string;
|
|
45
|
+
|
|
46
|
+
/** 数据类型的展示模式 */
|
|
47
|
+
readable: ClassType<any, any, any> | string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const EmtpyType = {
|
|
51
|
+
validators: [],
|
|
52
|
+
|
|
53
|
+
createDefaultValue: (assembly:Assembly, s:MFieldSchemaAnonymity):any =>{
|
|
54
|
+
if(s.defaultValue){
|
|
55
|
+
return _.clone(s.defaultValue);
|
|
56
|
+
} else {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
standardValue: (assembly:Assembly, s:MFieldSchemaAnonymity, v:any, strict:boolean):any => v,
|
|
62
|
+
|
|
63
|
+
toReadable: (assembly:Assembly, s:MFieldSchemaAnonymity, vs:any):string => {
|
|
64
|
+
if(_.isNil(vs)){
|
|
65
|
+
return assembly.theme.READABLE_BLANK;
|
|
66
|
+
}
|
|
67
|
+
return vs;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createDefaultValue(assembly:Assembly, s:MFieldSchemaAnonymity) {
|
|
72
|
+
if(s.defaultValue){
|
|
73
|
+
return _.clone(s.defaultValue);
|
|
74
|
+
} else {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
import { MFieldSchemaAnonymity, MValidationResult } from "../framework/Schema";
|
|
3
|
+
import { EmtpyType, MType} from "./MType";
|
|
4
|
+
import { validateRequired } from "../framework/Validator";
|
|
5
|
+
import { Assembly } from "../framework/Assembly";
|
|
6
|
+
import _ from "lodash";
|
|
7
|
+
|
|
8
|
+
function vlValidator(assembly:Assembly, schema:MFieldSchemaAnonymity, value:any, path:string): MValidationResult {
|
|
9
|
+
if(!value.label) {
|
|
10
|
+
return {message: "缺少标题,请重选此项", path}
|
|
11
|
+
} else if(!value.value) {
|
|
12
|
+
return {message: "缺少值,请重选此项", path}
|
|
13
|
+
} else{
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 数据示例 { "value": 608793, "label": "test小二" }
|
|
20
|
+
*/
|
|
21
|
+
export const MVLPairType: MType = _.assign({}, EmtpyType, {
|
|
22
|
+
validators: [validateRequired, vlValidator],
|
|
23
|
+
|
|
24
|
+
toReadable: (assembly:Assembly, s:MFieldSchemaAnonymity, vs:any):string => {
|
|
25
|
+
if(_.isNil(vs)){
|
|
26
|
+
return assembly.theme.READABLE_BLANK;
|
|
27
|
+
}
|
|
28
|
+
if(_.isObject(vs) && !_.isArray(vs)) {
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
return vs.label ?? vs.value ?? assembly.theme.READABLE_INVALID;
|
|
31
|
+
} else {
|
|
32
|
+
return assembly.theme.READABLE_INVALID;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
});
|