form-driver 0.3.14 → 0.4.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.
@@ -1,9 +1,15 @@
1
1
  import _ from "lodash";
2
2
  import moment from "moment";
3
- import { M3UISpec, MEnumField, MFieldSchema, MFieldSchemaAnonymity, MValidationFail } from './Schema';
4
- import { JSONSchema6 } from 'json-schema';
3
+ import {
4
+ M3UISpec,
5
+ MEnumField,
6
+ MFieldSchema,
7
+ MFieldSchemaAnonymity,
8
+ MValidationFail,
9
+ } from "./Schema";
10
+ import { JSONSchema6 } from "json-schema";
5
11
  import React from "react";
6
- import { SchemaFunc } from './SchemaFunc';
12
+ import { SchemaFunc } from "./SchemaFunc";
7
13
 
8
14
  export type HideMap = { [fieldName: string]: boolean };
9
15
 
@@ -15,24 +21,22 @@ let next = Date.now() - 1617265950471;
15
21
  export let MUtil = {
16
22
  /**
17
23
  * 每次调用,返回不一样的数字
18
- * @returns
24
+ * @returns
19
25
  */
20
- unique(){
21
- return next ++;
26
+ unique() {
27
+ return next++;
22
28
  },
23
29
 
24
- /**
30
+ /**
25
31
  * 枚举字段可以写成空格分隔的字符串,也能写成MEnumField[],这个函数将两种形式转换成统一的MEnumField[]
26
32
  * @deprecated 改成用MUtils.option
27
33
  */
28
34
  standardFields: (fs: string | MEnumField[] | undefined): MEnumField[] => {
29
- if (typeof fs === 'string') {
30
- return fs.split(" ").map(
31
- aEnum => {
32
- const kv = aEnum.split("=");
33
- return { label: kv[0], value: kv[1] ?? kv[0] };
34
- }
35
- );
35
+ if (typeof fs === "string") {
36
+ return fs.split(" ").map((aEnum) => {
37
+ const kv = aEnum.split("=");
38
+ return { label: kv[0], value: kv[1] ?? kv[0] };
39
+ });
36
40
  } else if (fs) {
37
41
  return fs;
38
42
  } else {
@@ -44,27 +48,25 @@ export let MUtil = {
44
48
  * 获取enumFields或者setFields,返回标准的MEnumField[]
45
49
  * @param f 如果f是nil,返回[]
46
50
  */
47
- option: (f:MFieldSchemaAnonymity):MEnumField[] => {
51
+ option: (f: MFieldSchemaAnonymity): MEnumField[] => {
48
52
  let result: MEnumField[];
49
- if(_.isArray(f.option)){
53
+ if (_.isArray(f.option)) {
50
54
  result = f.option;
51
55
  } else {
52
56
  let ori;
53
- if(f.type == "set"){
57
+ if (f.type == "set") {
54
58
  ori = f.setFields;
55
- } else if(f.type == "enum"){
56
- ori = f.enumFields
59
+ } else if (f.type == "enum") {
60
+ ori = f.enumFields;
57
61
  } else {
58
62
  ori = f.option ?? f.setFields ?? f.enumFields; // 只是为了保险
59
63
  }
60
64
 
61
- if (typeof ori === 'string') {
62
- f.option = result = ori.split(" ").map(
63
- aEnum => {
64
- const kv = aEnum.split("=");
65
- return { label: kv[0], value: kv[1] ?? kv[0] };
66
- }
67
- );
65
+ if (typeof ori === "string") {
66
+ f.option = result = ori.split(" ").map((aEnum) => {
67
+ const kv = aEnum.split("=");
68
+ return { label: kv[0], value: kv[1] ?? kv[0] };
69
+ });
68
70
  } else {
69
71
  f.option = result = ori; // TODO children 可能有递归的,还是得靠预处理解决
70
72
  }
@@ -74,11 +76,29 @@ export let MUtil = {
74
76
  },
75
77
 
76
78
  /** 如果出错了,返回这么个元素,可能用在BaseEditor子类或者其他的东西上 */
77
- error: function (msg: string, schema?: MFieldSchema | MFieldSchemaAnonymity): JSX.Element {
78
- return <div key={Date.now()} style={{ color: "white", border: "1px solid darkgrey", background: "red", textAlign: "center", borderRadius: "5px" }}>
79
- {msg}
80
- {schema ? <pre style={{ whiteSpace: "pre-wrap", textAlign: "left" }}>{JSON.stringify(schema)}</pre> : undefined}
81
- </div>;
79
+ error: function (
80
+ msg: string,
81
+ schema?: MFieldSchema | MFieldSchemaAnonymity
82
+ ): JSX.Element {
83
+ return (
84
+ <div
85
+ key={Date.now()}
86
+ style={{
87
+ color: "white",
88
+ border: "1px solid darkgrey",
89
+ background: "red",
90
+ textAlign: "center",
91
+ borderRadius: "5px",
92
+ }}
93
+ >
94
+ {msg}
95
+ {schema ? (
96
+ <pre style={{ whiteSpace: "pre-wrap", textAlign: "left" }}>
97
+ {JSON.stringify(schema)}
98
+ </pre>
99
+ ) : undefined}
100
+ </div>
101
+ );
82
102
  },
83
103
 
84
104
  sign: function (v: number | null | undefined): number | null {
@@ -118,7 +138,7 @@ export let MUtil = {
118
138
 
119
139
  /**
120
140
  * 计算文字的宽度
121
- * @param text
141
+ * @param text
122
142
  */
123
143
  antdTextWidth(text?: string) {
124
144
  if (!text) {
@@ -145,8 +165,11 @@ export let MUtil = {
145
165
  }
146
166
  },
147
167
 
148
- fieldOfLayout: function (fields: MFieldSchema[], spec: M3UISpec): MFieldSchema[] {
149
- const objectFieldMap = _.chain(fields).keyBy('name').value();
168
+ fieldOfLayout: function (
169
+ fields: MFieldSchema[],
170
+ spec: M3UISpec
171
+ ): MFieldSchema[] {
172
+ const objectFieldMap = _.chain(fields).keyBy("name").value();
150
173
  let r: { [key: string]: MFieldSchema } = {};
151
174
  for (let s of spec.segments ?? []) {
152
175
  for (let f of s.fields ?? []) {
@@ -165,8 +188,8 @@ export let MUtil = {
165
188
  * 跟lodash的get一样,除了:
166
189
  * 1. path是nil时返回undefined
167
190
  * 2. path是""时返回原始对象
168
- * @param a
169
- * @param path
191
+ * @param a
192
+ * @param path
170
193
  */
171
194
  get: function (a?: any | null, path?: string | null) {
172
195
  if (_.isNil(a) || _.isNil(path)) {
@@ -185,7 +208,7 @@ export let MUtil = {
185
208
  set: function (a: any | null, path: string | null, v: any) {
186
209
  if (path === "") {
187
210
  // 如果 database 是数组,需要特殊处理
188
- if (_.isArray(a)) a.length = v.length
211
+ if (_.isArray(a)) a.length = v.length;
189
212
  _.assign(a, v);
190
213
  } else {
191
214
  _.set(a, path, v);
@@ -202,7 +225,12 @@ export let MUtil = {
202
225
  * @param database 数据库,会被修改的
203
226
  * @param path 路径
204
227
  */
205
- applyDefaultValue: function (schema: MFieldSchema, database: any, path: string) { // FIXME 多测试下,type是object或其他简单类型的情况
228
+ applyDefaultValue: function (
229
+ schema: MFieldSchema,
230
+ database: any,
231
+ path: string
232
+ ) {
233
+ // FIXME 多测试下,type是object或其他简单类型的情况
206
234
  if (schema.type === "object") {
207
235
  for (let f of schema.objectFields ?? []) {
208
236
  this.applyDefaultValue(f, database, (path ? path + "." : "") + f.name);
@@ -214,8 +242,13 @@ export let MUtil = {
214
242
  }
215
243
  },
216
244
 
217
- filterHide: function (schema: MFieldSchema, database: any[] | object) { // TODO 要改成递归的
218
- const hm = MUtil.hideMap(database, schema.objectFields ?? [], schema.uispec);
245
+ filterHide: function (schema: MFieldSchema, database: any[] | object) {
246
+ // TODO 要改成递归的
247
+ const hm = MUtil.hideMap(
248
+ database,
249
+ schema.objectFields ?? [],
250
+ schema.uispec
251
+ );
219
252
  let finalData: any = _.isArray(database) ? [] : {};
220
253
  for (let k in database) {
221
254
  if (!hm[k]) {
@@ -230,21 +263,28 @@ export let MUtil = {
230
263
  * 支持ShowIfFunc里的函数
231
264
  * TODO 如果segment隐藏,里面的字段全都要隐藏
232
265
  * @returns 示例:
233
- * let {name,role,gender,alias,birthday,company,position,tel,email,citizenship,politicsCode,companyArch,address,work,edu,assistant,student,mib} = data;
266
+ * let {name,role,gender,alias,birthday,company,position,tel,email,citizenship,politicsCode,companyArch,address,work,edu,assistant,student,mib} = data;
234
267
  * return {politicsCode: !(citizenship=='中国大陆'),"segment:学员信息": !(_.intersection(role, ['校友']).length > 0))}
235
- * @param objectFields
268
+ * @param objectFields
236
269
  * @param uispec 用来计算segment是不是要展示,不填就不计算
237
270
  */
238
- hideMap: function (database: any, objectFields: MFieldSchema[], uispec?: M3UISpec): HideMap {
271
+ hideMap: function (
272
+ database: any,
273
+ objectFields: MFieldSchema[],
274
+ uispec?: M3UISpec
275
+ ): HideMap {
239
276
  // 构造字段依赖计算的脚本,类似这样:
240
277
  // let {name,role,gender,alias,tel,email,citizenship,student} = {"name":"aaa","alias":"bbb","tel":"1"};citizenship=='中国大陆'
241
278
 
242
- let l1fields = _.uniq( // 名字要唯一
279
+ let l1fields = _.uniq(
280
+ // 名字要唯一
243
281
  objectFields
244
- .filter(e => !!e.name) // 过滤掉没有名字的字段
245
- .map(e => _.first(e.name.split("."))) // 对于objectFields里类似student.no/student.state的字段,这里只要拼一个student就可以了
282
+ .filter((e) => !!e.name) // 过滤掉没有名字的字段
283
+ .map((e) => _.first(e.name.split("."))) // 对于objectFields里类似student.no/student.state的字段,这里只要拼一个student就可以了
246
284
  );
247
- let showIfScript = `let {${l1fields.join(",")}} = data || {};\nlet hide = {`;
285
+ let showIfScript = `let {${l1fields.join(
286
+ ","
287
+ )}} = data || {};\nlet hide = {`;
248
288
  for (let f of objectFields) {
249
289
  if (f.showIf) {
250
290
  showIfScript += `'${f.name}': !(${f.showIf}),`;
@@ -259,7 +299,7 @@ export let MUtil = {
259
299
 
260
300
  // 如果一个segment里的所有字段都隐藏,segment就要隐藏
261
301
  for (let s of uispec?.segments ?? []) {
262
- const cond = s.fields.map(f => "(hide['" + f + "'])").join(" && ");
302
+ const cond = s.fields.map((f) => "(hide['" + f + "'])").join(" && ");
263
303
  showIfScript += `if(${cond}) { hide["segment:${s.label}"] = true }\n`;
264
304
  }
265
305
 
@@ -267,12 +307,20 @@ export let MUtil = {
267
307
 
268
308
  // eslint-disable-next-line no-new-func
269
309
  try {
270
- const fn = Object.keys(SchemaFunc)
271
- const fv = Object.values(SchemaFunc)
272
- let hideMap = new Function("_", "data", ...fn, showIfScript)(_, database, ...fv);
310
+ const fn = Object.keys(SchemaFunc);
311
+ const fv = Object.values(SchemaFunc);
312
+ let hideMap = new Function("_", "data", ...fn, showIfScript)(
313
+ _,
314
+ database,
315
+ ...fv
316
+ );
273
317
  return hideMap;
274
- } catch (e) {
275
- console.error("Calc hideMap failed: " + e.message, "function(_,data){" + showIfScript + "}", database);
318
+ } catch (e: any) {
319
+ console.error(
320
+ "Calc hideMap failed: " + e.message,
321
+ "function(_,data){" + showIfScript + "}",
322
+ database
323
+ );
276
324
  return {};
277
325
  }
278
326
  },
@@ -280,37 +328,53 @@ export let MUtil = {
280
328
  /**
281
329
  * 计算 showIf 的值
282
330
  * @returns Boolean
283
- * @param database
284
- * @param objectFields
331
+ * @param database
332
+ * @param objectFields
285
333
  */
286
- isShow: function (database: any, objectFields: MFieldSchema[], showIfExpr: string) {
287
- if (!showIfExpr) return true
334
+ isShow: function (
335
+ database: any,
336
+ objectFields: MFieldSchema[],
337
+ showIfExpr: string
338
+ ) {
339
+ if (!showIfExpr) return true;
288
340
  let l1fields = _.uniq(
289
341
  objectFields
290
- .filter(e => !!e.name)
291
- .map(e => _.first(e.name.split(".")))
342
+ .filter((e) => !!e.name)
343
+ .map((e) => _.first(e.name.split(".")))
292
344
  );
293
- let showIfScript = `let {${l1fields.join(",")}} = data || {};\n return ${showIfExpr}`;
345
+ let showIfScript = `let {${l1fields.join(
346
+ ","
347
+ )}} = data || {};\n return ${showIfExpr}`;
294
348
  try {
295
- const fn = Object.keys(SchemaFunc)
296
- const fv = Object.values(SchemaFunc)
297
- let res = new Function("_", "data", ...fn, showIfScript)(_, database, ...fv);
349
+ const fn = Object.keys(SchemaFunc);
350
+ const fv = Object.values(SchemaFunc);
351
+ let res = new Function("_", "data", ...fn, showIfScript)(
352
+ _,
353
+ database,
354
+ ...fv
355
+ );
298
356
  return res;
299
- } catch (e) {
300
- console.error("Calc isShow failed: " + e.message, "function(_,data){" + showIfScript + "}", database);
357
+ } catch (e: any) {
358
+ console.error(
359
+ "Calc isShow failed: " + e.message,
360
+ "function(_,data){" + showIfScript + "}",
361
+ database
362
+ );
301
363
  return true;
302
364
  }
303
365
  },
304
366
 
305
- scoreOf: function(f:MFieldSchema, database:any) {
367
+ scoreOf: function (f: MFieldSchema, database: any) {
306
368
  const v = _.get(database, f.name);
307
- if(f.type == "enum"){
308
- return _.toNumber(MUtil.standardFields(f.enumFields)?.find(e=>e.value == v)?.score);
309
- } else if(f.type == "set"){
369
+ if (f.type == "enum") {
370
+ return _.toNumber(
371
+ MUtil.standardFields(f.enumFields)?.find((e) => e.value == v)?.score
372
+ );
373
+ } else if (f.type == "set") {
310
374
  let score = 0;
311
375
  const opts = MUtil.standardFields(f.setFields);
312
- for(let s of opts){
313
- if(_.find(opts, {value:v})) {
376
+ for (let s of opts) {
377
+ if (_.find(opts, { value: v })) {
314
378
  score += _.toNumber(s.score);
315
379
  }
316
380
  }
@@ -323,37 +387,44 @@ export let MUtil = {
323
387
  /**
324
388
  * 查找fs依赖(通过showIf)的所有字段
325
389
  * @param fs
326
- * @param all
390
+ * @param all
327
391
  * @returns fs依赖的所有字段,包含fs。这个数组中下标小的元素,依赖下标大的元素
328
392
  */
329
- dependency: function (fs:MFieldSchema[], all:MFieldSchema[]) {
393
+ dependency: function (fs: MFieldSchema[], all: MFieldSchema[]) {
330
394
  // 先建个索引
331
395
  const allFieldsIdx = _.keyBy(all, "name");
332
-
396
+
333
397
  // 构造未被依赖的集合
334
398
  let ndep = _.keyBy(all, "name"); // 全体
335
- ndep = _.omit(ndep, fs.map(f=>f.name)); // 去掉fs
336
-
399
+ ndep = _.omit(
400
+ ndep,
401
+ fs.map((f) => f.name)
402
+ ); // 去掉fs
403
+
337
404
  // 构造被依赖的集合
338
405
  let dep = new Map<string, MFieldSchema>();
339
- fs.forEach(f => dep[f.name] = f);
340
-
406
+ fs.forEach((f) => (dep[f.name] = f));
407
+
341
408
  // 循环从ndep里把被依赖的字段放到dep中,直到dep不再增加
342
409
  // 算法有点粗暴,将就用吧
343
- for(let i = 0; i < all.length; i ++) { // 轮数最多all.length,防止卡死
344
- let newDepNames = []
345
- for(let dn in dep) {
346
- const i = _.intersection( dep[dn].showIf?.split(/[^a-zA-Z0-9_$]/), Object.keys(ndep) );
410
+ for (let i = 0; i < all.length; i++) {
411
+ // 轮数最多all.length,防止卡死
412
+ let newDepNames = [];
413
+ for (let dn in dep) {
414
+ const i = _.intersection(
415
+ dep[dn].showIf?.split(/[^a-zA-Z0-9_$]/),
416
+ Object.keys(ndep)
417
+ );
347
418
  newDepNames = newDepNames.concat(i);
348
419
  }
349
420
 
350
421
  let prevSize = Object.keys(dep).length;
351
- for(let n of newDepNames){
422
+ for (let n of newDepNames) {
352
423
  dep[n] = allFieldsIdx[n];
353
- delete ndep[n];
424
+ delete ndep[n];
354
425
  }
355
426
  let afterSize = Object.keys(dep).length;
356
- if(prevSize == afterSize) {
427
+ if (prevSize == afterSize) {
357
428
  break; // 如果找不到更多依赖,就可以结束了
358
429
  }
359
430
  }
@@ -367,11 +438,16 @@ export let MUtil = {
367
438
  * @param dstFormat 转换成的数据格式,默认YYYY年MM月DD日
368
439
  * @param fallback 如果原始数据是nil,返回fallback
369
440
  */
370
- momentFormat: function (s: moment.MomentInput, srcFormat: string = "x", dstFormat: string = "YYYY年MM月DD日", fallback: string = "不详") {
441
+ momentFormat: function (
442
+ s: moment.MomentInput,
443
+ srcFormat: string = "x",
444
+ dstFormat: string = "YYYY年MM月DD日",
445
+ fallback: string = "不详"
446
+ ) {
371
447
  if (_.isNil(s)) {
372
448
  return fallback;
373
449
  }
374
- return moment(s, srcFormat).format(dstFormat)
450
+ return moment(s, srcFormat).format(dstFormat);
375
451
  },
376
452
 
377
453
  /**
@@ -380,23 +456,29 @@ export let MUtil = {
380
456
  * @param base 如果填了一个对象,转换出的属性会放在这个对象上
381
457
  * @param template 如果有子结构,创建子结构的模板
382
458
  */
383
- jsonSchema2MFieldSchema: function (e: JSONSchema6, base: MFieldSchema = { name: "", type: "string" }, template: Partial<MFieldSchema> = {}): MFieldSchema {
459
+ jsonSchema2MFieldSchema: function (
460
+ e: JSONSchema6,
461
+ base: MFieldSchema = { name: "", type: "string" },
462
+ template: Partial<MFieldSchema> = {}
463
+ ): MFieldSchema {
384
464
  switch (e.type) {
385
- case 'string':
465
+ case "string":
386
466
  if (e.enum) {
387
467
  base.type = "enum";
388
- base.enumFields = base.enumFields ?? e.enum.map(v => ({ value: (v ?? "").toString() }))
468
+ base.enumFields =
469
+ base.enumFields ??
470
+ e.enum.map((v) => ({ value: (v ?? "").toString() }));
389
471
  } else {
390
- base.type = "string"
391
- base.max = e.maxLength
472
+ base.type = "string";
473
+ base.max = e.maxLength;
392
474
  }
393
475
  break;
394
- case 'number':
395
- case 'integer':
476
+ case "number":
477
+ case "integer":
396
478
  base.type = "int";
397
479
  break;
398
- case 'object':
399
- base.type = "object"
480
+ case "object":
481
+ base.type = "object";
400
482
  base.objectFields = [];
401
483
  base.uispec = {
402
484
  type: "flowForm",
@@ -405,19 +487,24 @@ export let MUtil = {
405
487
  };
406
488
  for (let key in e.properties) {
407
489
  let jsmField = e.properties[key];
408
- let m3Field: MFieldSchema = _.assign({}, template, { name: key, label: key, type: "object" });
490
+ let m3Field: MFieldSchema = _.assign({}, template, {
491
+ name: key,
492
+ label: key,
493
+ type: "object",
494
+ });
409
495
  if (!_.isBoolean(jsmField)) {
410
496
  m3Field.label = jsmField.title ?? key;
411
497
  this.jsonSchema2MFieldSchema(jsmField, m3Field, template);
412
498
  base.objectFields.push(m3Field);
413
499
  } else {
414
- m3Field.type = "不支持的json schema:object.properties的value是boolean";
415
- base.objectFields.push()
500
+ m3Field.type =
501
+ "不支持的json schema:object.properties的value是boolean";
502
+ base.objectFields.push();
416
503
  }
417
504
  }
418
505
  break;
419
- case 'array':
420
- base.type = "array"
506
+ case "array":
507
+ base.type = "array";
421
508
  base.arrayMember = { label: "", type: "array" };
422
509
  if (_.isArray(e.items)) {
423
510
  base.arrayMember.type = "不支持的json schema:array.items是数组";
@@ -429,9 +516,9 @@ export let MUtil = {
429
516
  base.arrayMember.type = "不支持的json schema:array.items是undefined";
430
517
  }
431
518
  break;
432
- case 'null':
433
- case 'any':
434
- case 'boolean':
519
+ case "null":
520
+ case "any":
521
+ case "boolean":
435
522
  default:
436
523
  base.type = "不支持的json schema:array.items是" + e.type;
437
524
  break;
@@ -442,11 +529,15 @@ export let MUtil = {
442
529
  /**
443
530
  * 修改一个对象里的key
444
531
  * @param object 要修改的对象,
445
- * @param renameTo
532
+ * @param renameTo
446
533
  * @param removeNotExistKey 是否在结果里面去除renameTo里不存在的key
447
534
  * @returns 返回一个改过key名字的新对象
448
535
  */
449
- renameKey: function (object: any, renameTo: { [oldKey: string]: string }, removeNotExistKey: boolean = false): any {
536
+ renameKey: function (
537
+ object: any,
538
+ renameTo: { [oldKey: string]: string },
539
+ removeNotExistKey: boolean = false
540
+ ): any {
450
541
  let result: any = {};
451
542
  for (let oldKey in object) {
452
543
  let newKey = renameTo[oldKey];
@@ -463,7 +554,7 @@ export let MUtil = {
463
554
  },
464
555
 
465
556
  /** 啥也不干的空回调 */
466
- doNothing: function () { },
557
+ doNothing: function () {},
467
558
 
468
559
  /**
469
560
  * 去掉arr中的undefined和null,拼出来一个json path
@@ -477,7 +568,7 @@ export let MUtil = {
477
568
  * @param path 如果path是空的返回也是空的
478
569
  */
479
570
  parentPath: function (path: string): string {
480
- const split = path.replace(/]/g, '').split(/[.\\[]/);
571
+ const split = path.replace(/]/g, "").split(/[.\\[]/);
481
572
  split.splice(-1, 1);
482
573
  return split.join(".");
483
574
  },
@@ -487,31 +578,45 @@ export let MUtil = {
487
578
  * @param s 要校验的schema
488
579
  * @returns 空数组表示校验通过,否则返回校验错误信息
489
580
  */
490
- validateSchema: function (s: MFieldSchema, parentPath?: string): MValidationFail[] {
581
+ validateSchema: function (
582
+ s: MFieldSchema,
583
+ parentPath?: string
584
+ ): MValidationFail[] {
491
585
  let result: MValidationFail[] = [];
492
- const error = (msg: string) => result.push({ message: msg, path: MUtil.jsonPath(parentPath, s.name) });
586
+ const error = (msg: string) =>
587
+ result.push({ message: msg, path: MUtil.jsonPath(parentPath, s.name) });
493
588
  const checkDup = (a: any[], msgIfFail: string) => {
494
589
  if (_.uniq(a).length !== a.length) {
495
590
  error(msgIfFail);
496
591
  }
497
592
  };
498
593
  const checkVL = (fs: MEnumField[]) => {
499
- checkDup(fs.map(f => f.value), s.name + "值有重复");
500
- checkDup(fs.map(f => f.label).filter(l => l), s.name + "文案有重复");
501
- }
594
+ checkDup(
595
+ fs.map((f) => f.value),
596
+ s.name + "值有重复"
597
+ );
598
+ checkDup(
599
+ fs.map((f) => f.label).filter((l) => l),
600
+ s.name + "文案有重复"
601
+ );
602
+ };
502
603
  const stringOnlyEnum = (candidate: string | MEnumField[] | undefined) => {
503
- const ns = MUtil.standardFields(candidate).find(f => !_.isString(f.value))
604
+ const ns = MUtil.standardFields(candidate).find(
605
+ (f) => !_.isString(f.value)
606
+ );
504
607
  if (ns) {
505
- error("暂不支持的选项数据类型:" + JSON.stringify(ns) + ": " + (typeof ns))
608
+ error(
609
+ "暂不支持的选项数据类型:" + JSON.stringify(ns) + ": " + typeof ns
610
+ );
506
611
  }
507
- }
612
+ };
508
613
 
509
614
  if (s.type === "decoration") {
510
615
  return [];
511
616
  } else if (s.type === "enum") {
512
- checkVL(MUtil.standardFields(s.enumFields))
617
+ checkVL(MUtil.standardFields(s.enumFields));
513
618
  } else if (s.type === "set") {
514
- checkVL(MUtil.standardFields(s.setFields))
619
+ checkVL(MUtil.standardFields(s.setFields));
515
620
  } else if (s.type === "matrix") {
516
621
  stringOnlyEnum(s.matrix.x);
517
622
  stringOnlyEnum(s.matrix.y);
@@ -519,19 +624,32 @@ export let MUtil = {
519
624
  if (!s.objectFields) {
520
625
  error("object类型未定义成员");
521
626
  } else {
522
- checkDup(s.objectFields.filter(f => f.type !== 'decoration').map(f => f.name), "字段名有重复");
627
+ checkDup(
628
+ s.objectFields
629
+ .filter((f) => f.type !== "decoration")
630
+ .map((f) => f.name),
631
+ "字段名有重复"
632
+ );
523
633
  for (let f of s.objectFields) {
524
- result = _.concat(result, MUtil.validateSchema(f, MUtil.jsonPath(parentPath, s.name)));
634
+ result = _.concat(
635
+ result,
636
+ MUtil.validateSchema(f, MUtil.jsonPath(parentPath, s.name))
637
+ );
525
638
  }
526
639
 
527
640
  if (s.uispec?.type === "segmentForm") {
528
641
  if (!s.uispec.segments) {
529
642
  error("分段未定义");
530
643
  } else {
531
- checkDup(s.uispec.segments.map(f => f.label), "分段文案有重复");
532
- const fieldsInSegments = _.flatten(s.uispec.segments.map(f => f.fields));
644
+ checkDup(
645
+ s.uispec.segments.map((f) => f.label),
646
+ "分段文案有重复"
647
+ );
648
+ const fieldsInSegments = _.flatten(
649
+ s.uispec.segments.map((f) => f.fields)
650
+ );
533
651
  checkDup(fieldsInSegments, "分段字段有重复");
534
- const fields = s.objectFields.map(f => f.name);
652
+ const fields = s.objectFields.map((f) => f.name);
535
653
  checkDup(fields, "字段名有重复");
536
654
  const notInSegment = _.difference(fields, fieldsInSegments);
537
655
  if (notInSegment.length > 0) {
@@ -551,8 +669,8 @@ export let MUtil = {
551
669
  /**
552
670
  * 参考https://stackoverflow.com/questions/3362471/how-can-i-call-a-javascript-constructor-using-call-or-apply
553
671
  * 示例: var d = applyToConstructor(Date, [2008, 10, 8, 00, 16, 34, 254]);
554
- * @param constructor
555
- * @param argArray
672
+ * @param constructor
673
+ * @param argArray
556
674
  */
557
675
  applyToConstructor: function (constructor, argArray) {
558
676
  var args = [null, ...argArray];
@@ -568,12 +686,21 @@ export let MUtil = {
568
686
  * @param fallback 如果exprOrFunction无效,返回fallback
569
687
  * @param _this this指针
570
688
  */
571
- evalExprOrFunction: function (exprOrFunction, paramName: string[], paramValue: any[], fallback: any = undefined, _this: any = undefined) {
689
+ evalExprOrFunction: function (
690
+ exprOrFunction,
691
+ paramName: string[],
692
+ paramValue: any[],
693
+ fallback: any = undefined,
694
+ _this: any = undefined
695
+ ) {
572
696
  if (_.isFunction(exprOrFunction)) {
573
697
  return exprOrFunction.apply(_this, paramValue);
574
698
  } else if (_.isString(exprOrFunction)) {
575
699
  //return new Function("_", "value", "parent", "return (" + labelExpr + ");")(_, value, parent);
576
- const func = MUtil.applyToConstructor(Function, [...paramName, "return (" + exprOrFunction + ")"]);
700
+ const func = MUtil.applyToConstructor(Function, [
701
+ ...paramName,
702
+ "return (" + exprOrFunction + ")",
703
+ ]);
577
704
  return func.apply(_this, paramValue);
578
705
  } else {
579
706
  return fallback;
@@ -585,7 +712,10 @@ export let MUtil = {
585
712
  * @param hashPrefix nil表示不读取hash里的参数,字符串表示读取hash里的参数,并加上这个前缀返回。默认是返回,但前缀是空字符串
586
713
  */
587
714
  getQuery: function (hashPrefix: string = ""): any {
588
- const arrs = [...window.location.search.split(/[?&]/), ...window.location.hash.split(/[#?&]/)];
715
+ const arrs = [
716
+ ...window.location.search.split(/[?&]/),
717
+ ...window.location.hash.split(/[#?&]/),
718
+ ];
589
719
  const result = {};
590
720
  arrs.forEach((item) => {
591
721
  const kv = item.split(/=/);
@@ -602,16 +732,18 @@ export let MUtil = {
602
732
  * @param id <style>的id,可以没有。如果已经存在,会被覆盖掉。
603
733
  */
604
734
  setCss: function (css: string, id?: string) {
605
- const s = document.getElementById(id) as HTMLStyleElement ?? document.createElement('style');
735
+ const s =
736
+ (document.getElementById(id) as HTMLStyleElement) ??
737
+ document.createElement("style");
606
738
  s.id = id;
607
- s.type = 'text/css';
739
+ s.type = "text/css";
608
740
  s.innerHTML = css;
609
- document.getElementsByTagName('head')[0].appendChild(s);
741
+ document.getElementsByTagName("head")[0].appendChild(s);
610
742
  },
611
743
 
612
744
  /**
613
745
  * escape数值
614
- * @param str - 字符串
746
+ * @param str - 字符串
615
747
  * @returns 会带上引号,类似"abc",str=nil时会返回""
616
748
  */
617
749
  escapeCsv: function (str?: string) {
@@ -627,27 +759,30 @@ export let MUtil = {
627
759
  * @param v2 另一个值
628
760
  * @param tolerate true用==判断,false用===判断
629
761
  */
630
- isEquals: function(v1, v2, tolerate: boolean) {
631
- if(tolerate) {
762
+ isEquals: function (v1, v2, tolerate: boolean) {
763
+ if (tolerate) {
632
764
  return v1 == v2;
633
765
  } else {
634
766
  return v1 === v2;
635
767
  }
636
- }
637
- }
768
+ },
769
+ };
638
770
 
639
771
  /** 压缩数组,如果只有一个元素时,它是数据本身,多于一个元素时才是数组 */
640
772
  export type CompactArrayType<T> = T | T[];
641
773
 
642
774
  export let CompactArray = {
643
- indexOf: function <T>(ca?: CompactArrayType<T> | null, d?: T | null): -1 | number {
775
+ indexOf: function <T>(
776
+ ca?: CompactArrayType<T> | null,
777
+ d?: T | null
778
+ ): -1 | number {
644
779
  if (_.isNil(d) || _.isNil(ca)) {
645
780
  return -1;
646
781
  }
647
782
  if (_.isArray(ca)) {
648
783
  return ca.indexOf(d);
649
784
  } else {
650
- return ca === d ? 0 : -1
785
+ return ca === d ? 0 : -1;
651
786
  }
652
- }
653
- }
787
+ },
788
+ };