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.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/dist/m3.css +310 -0
  4. package/dist/m3.js +1 -0
  5. package/es/m3.css +310 -0
  6. package/es/m3.js +20919 -0
  7. package/lib/m3.css +310 -0
  8. package/lib/m3.js +20959 -0
  9. package/package.json +132 -0
  10. package/src/.DS_Store +0 -0
  11. package/src/framework/Ajax.ts +96 -0
  12. package/src/framework/Assembly.tsx +165 -0
  13. package/src/framework/Init.tsx +196 -0
  14. package/src/framework/M3.tsx +94 -0
  15. package/src/framework/MContext.ts +15 -0
  16. package/src/framework/MFieldViewer.tsx +32 -0
  17. package/src/framework/MUtil.tsx +653 -0
  18. package/src/framework/MViewer.less +128 -0
  19. package/src/framework/MViewer.tsx +180 -0
  20. package/src/framework/MViewerDebug.tsx +95 -0
  21. package/src/framework/Persistant.ts +90 -0
  22. package/src/framework/Schema.ts +386 -0
  23. package/src/framework/SchemaFunc.ts +30 -0
  24. package/src/framework/Validator.ts +160 -0
  25. package/src/framework/editorMap.ts +109 -0
  26. package/src/index.ts +33 -0
  27. package/src/types/MArrayType.ts +73 -0
  28. package/src/types/MCascadeType.ts +35 -0
  29. package/src/types/MCnAddressType.ts +54 -0
  30. package/src/types/MDateRangeType.ts +52 -0
  31. package/src/types/MDateTimeType.ts +53 -0
  32. package/src/types/MDecorationType.ts +6 -0
  33. package/src/types/MEnumType.ts +65 -0
  34. package/src/types/MExperienceType.ts +81 -0
  35. package/src/types/MFloatType.ts +10 -0
  36. package/src/types/MGB2260Type.ts +56 -0
  37. package/src/types/MIntDiffType.ts +6 -0
  38. package/src/types/MIntType.ts +44 -0
  39. package/src/types/MKvSetType.ts +50 -0
  40. package/src/types/MMatrixType.ts +52 -0
  41. package/src/types/MObjectType.ts +89 -0
  42. package/src/types/MSetType.ts +220 -0
  43. package/src/types/MStringType.ts +27 -0
  44. package/src/types/MTelType.ts +14 -0
  45. package/src/types/MType.ts +77 -0
  46. package/src/types/MVLPairType.ts +35 -0
  47. package/src/types/gb2260.json +1 -0
  48. package/src/ui/BaseViewer.tsx +110 -0
  49. package/src/ui/editor/.DS_Store +0 -0
  50. package/src/ui/editor/basic/.DS_Store +0 -0
  51. package/src/ui/editor/basic/ACascadePicker.tsx +114 -0
  52. package/src/ui/editor/basic/ACheckBox.tsx +104 -0
  53. package/src/ui/editor/basic/ADatetimePicker.tsx +76 -0
  54. package/src/ui/editor/basic/AGB2260.tsx +52 -0
  55. package/src/ui/editor/basic/AInputBox.tsx +59 -0
  56. package/src/ui/editor/basic/AIntBox.tsx +39 -0
  57. package/src/ui/editor/basic/AKvSet.less +9 -0
  58. package/src/ui/editor/basic/AKvSet.tsx +90 -0
  59. package/src/ui/editor/basic/ARadio.tsx +86 -0
  60. package/src/ui/editor/basic/ARangePicker.tsx +129 -0
  61. package/src/ui/editor/basic/ARate.less +8 -0
  62. package/src/ui/editor/basic/ARate.tsx +37 -0
  63. package/src/ui/editor/basic/ARemoteSelector.tsx +116 -0
  64. package/src/ui/editor/basic/ASelector.tsx +88 -0
  65. package/src/ui/editor/basic/ASetSelector.tsx +65 -0
  66. package/src/ui/editor/basic/ASpecInputBox.tsx +20 -0
  67. package/src/ui/editor/basic/ATreeSelect.tsx +41 -0
  68. package/src/ui/editor/basic/AUpload.tsx +119 -0
  69. package/src/ui/editor/basic/NPS.less +21 -0
  70. package/src/ui/editor/basic/NPS.tsx +47 -0
  71. package/src/ui/editor/complex/AArray.less +10 -0
  72. package/src/ui/editor/complex/AArray.tsx +104 -0
  73. package/src/ui/editor/complex/AArrayGrid.tsx +115 -0
  74. package/src/ui/editor/complex/ACnAddress.less +15 -0
  75. package/src/ui/editor/complex/ACnAddress.tsx +61 -0
  76. package/src/ui/editor/complex/ADialogForm.tsx +45 -0
  77. package/src/ui/editor/complex/AExperience.tsx +85 -0
  78. package/src/ui/editor/complex/AForm.less +35 -0
  79. package/src/ui/editor/complex/AForm.tsx +340 -0
  80. package/src/ui/editor/complex/AIntDiff.tsx +77 -0
  81. package/src/ui/editor/complex/AMatrix.less +18 -0
  82. package/src/ui/editor/complex/AMatrix.tsx +242 -0
  83. package/src/ui/editor/complex/ATable.less +4 -0
  84. package/src/ui/editor/complex/ATable.tsx +33 -0
  85. package/src/ui/editor/complex/JsonEditor.tsx +37 -0
  86. package/src/ui/readable/A.tsx +33 -0
  87. package/src/ui/readable/ArrayViewer.tsx +46 -0
  88. package/src/ui/readable/DecorationViewer.tsx +76 -0
  89. package/src/ui/readable/DivViewer.tsx +11 -0
  90. package/src/ui/widget/Collapsible.tsx +156 -0
  91. package/src/ui/widget/Segment.less +39 -0
  92. package/src/ui/widget/Segment.tsx +40 -0
  93. package/src/ui/widget/SegmentEditSwitch.tsx +46 -0
  94. package/src/ui/widget/SelectBox.tsx +43 -0
  95. package/src/ui/widget/UnderlineInputBox.less +47 -0
  96. package/src/ui/widget/UnderlineInputBox.tsx +10 -0
  97. package/types/framework/Ajax.d.ts +5 -0
  98. package/types/framework/Assembly.d.ts +59 -0
  99. package/types/framework/Init.d.ts +4 -0
  100. package/types/framework/M3.d.ts +6 -0
  101. package/types/framework/MContext.d.ts +11 -0
  102. package/types/framework/MFieldViewer.d.ts +8 -0
  103. package/types/framework/MUtil.d.ts +180 -0
  104. package/types/framework/MViewer.d.ts +75 -0
  105. package/types/framework/MViewerDebug.d.ts +11 -0
  106. package/types/framework/Persistant.d.ts +17 -0
  107. package/types/framework/Schema.d.ts +306 -0
  108. package/types/framework/SchemaFunc.d.ts +14 -0
  109. package/types/framework/Validator.d.ts +53 -0
  110. package/types/framework/editorMap.d.ts +107 -0
  111. package/types/index.d.ts +21 -0
  112. package/types/types/MArrayType.d.ts +2 -0
  113. package/types/types/MCascadeType.d.ts +11 -0
  114. package/types/types/MCnAddressType.d.ts +2 -0
  115. package/types/types/MDateRangeType.d.ts +7 -0
  116. package/types/types/MDateTimeType.d.ts +11 -0
  117. package/types/types/MDecorationType.d.ts +7 -0
  118. package/types/types/MEnumType.d.ts +2 -0
  119. package/types/types/MExperienceType.d.ts +5 -0
  120. package/types/types/MFloatType.d.ts +2 -0
  121. package/types/types/MGB2260Type.d.ts +9 -0
  122. package/types/types/MIntDiffType.d.ts +2 -0
  123. package/types/types/MIntType.d.ts +2 -0
  124. package/types/types/MKvSetType.d.ts +11 -0
  125. package/types/types/MMatrixType.d.ts +5 -0
  126. package/types/types/MObjectType.d.ts +11 -0
  127. package/types/types/MSetType.d.ts +7 -0
  128. package/types/types/MStringType.d.ts +2 -0
  129. package/types/types/MTelType.d.ts +4 -0
  130. package/types/types/MType.d.ts +46 -0
  131. package/types/types/MVLPairType.d.ts +5 -0
  132. package/types/ui/BaseViewer.d.ts +45 -0
  133. package/types/ui/editor/basic/ACascadePicker.d.ts +11 -0
  134. package/types/ui/editor/basic/ACheckBox.d.ts +17 -0
  135. package/types/ui/editor/basic/ADatetimePicker.d.ts +15 -0
  136. package/types/ui/editor/basic/AGB2260.d.ts +10 -0
  137. package/types/ui/editor/basic/AInputBox.d.ts +8 -0
  138. package/types/ui/editor/basic/AIntBox.d.ts +9 -0
  139. package/types/ui/editor/basic/AKvSet.d.ts +19 -0
  140. package/types/ui/editor/basic/ARadio.d.ts +14 -0
  141. package/types/ui/editor/basic/ARangePicker.d.ts +30 -0
  142. package/types/ui/editor/basic/ARate.d.ts +13 -0
  143. package/types/ui/editor/basic/ARemoteSelector.d.ts +15 -0
  144. package/types/ui/editor/basic/ASelector.d.ts +14 -0
  145. package/types/ui/editor/basic/ASetSelector.d.ts +10 -0
  146. package/types/ui/editor/basic/ASpecInputBox.d.ts +9 -0
  147. package/types/ui/editor/basic/ATreeSelect.d.ts +18 -0
  148. package/types/ui/editor/basic/AUpload.d.ts +33 -0
  149. package/types/ui/editor/basic/NPS.d.ts +13 -0
  150. package/types/ui/editor/complex/AArray.d.ts +11 -0
  151. package/types/ui/editor/complex/AArrayGrid.d.ts +13 -0
  152. package/types/ui/editor/complex/ACnAddress.d.ts +10 -0
  153. package/types/ui/editor/complex/ADialogForm.d.ts +11 -0
  154. package/types/ui/editor/complex/AExperience.d.ts +16 -0
  155. package/types/ui/editor/complex/AForm.d.ts +46 -0
  156. package/types/ui/editor/complex/AIntDiff.d.ts +14 -0
  157. package/types/ui/editor/complex/AMatrix.d.ts +48 -0
  158. package/types/ui/editor/complex/ATable.d.ts +9 -0
  159. package/types/ui/editor/complex/JsonEditor.d.ts +9 -0
  160. package/types/ui/readable/A.d.ts +5 -0
  161. package/types/ui/readable/ArrayViewer.d.ts +5 -0
  162. package/types/ui/readable/DecorationViewer.d.ts +3 -0
  163. package/types/ui/readable/DivViewer.d.ts +5 -0
  164. package/types/ui/widget/Collapsible.d.ts +46 -0
  165. package/types/ui/widget/Segment.d.ts +18 -0
  166. package/types/ui/widget/SegmentEditSwitch.d.ts +20 -0
  167. package/types/ui/widget/SelectBox.d.ts +13 -0
  168. package/types/ui/widget/UnderlineInputBox.d.ts +6 -0
package/package.json ADDED
@@ -0,0 +1,132 @@
1
+ {
2
+ "name": "form-driver",
3
+ "version": "0.1.0",
4
+ "description": "An efficient framework for creating forms.",
5
+ "license": "MIT",
6
+ "authors": [
7
+ "龙湖 <59775976@qq.com>",
8
+ "云开 <2313303800@qq.com>"
9
+ ],
10
+ "scripts": {
11
+ "start": "webpack-dev-server --inline --progress --config webpack.demo.js --compress",
12
+ "clean": "rimraf lib dist es coverage types",
13
+ "build": "rollup -c",
14
+ "b": "npm run clean && npm run build",
15
+ "i": "tnpm install && tnpm install @ali/m3 @ali/m3-plugin-richtext @ali/m3-plugin-hp-org",
16
+ "ri": "rm -rf node_modules && npm run i",
17
+ "pub": "npm run b && npm version patch && npm publish && git push",
18
+ "patch": "npm version patch && npm publish && git push",
19
+ "submodule": "git submodule update --init",
20
+ "ut-pull": "cd ./demo/src/ut_autoTest/ut_case && git pull",
21
+ "ut-test": "cd ./demo/src/ut_autoTest/ut_case && source ./.venv/bin/activate && python run_ui.py",
22
+ "demo:build": "cross-env NODE_ENV=production webpack --config webpack.demo.js",
23
+ "docs:i": "cd docs && tnpm install",
24
+ "docs:ri": "cd docs && rm -rf node_modules && npm run i",
25
+ "docs:start": "cd docs && dumi dev",
26
+ "docs:build": "cd docs && dumi build",
27
+ "docs:upload": "cd docs && hp upload ./dist m3/ --free",
28
+ "docs:pub": "cd docs && npm run build && npm run upload"
29
+ },
30
+ "keywords": [
31
+ "m3",
32
+ "form",
33
+ "form-driver"
34
+ ],
35
+ "homepage": "https://github.com/alibaba/form-driver",
36
+ "bugs": {
37
+ "url": "https://github.com/alibaba/form-driver/issues"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/alibaba/form-driver.git"
42
+ },
43
+ "main": "lib/m3.js",
44
+ "module": "es/m3.js",
45
+ "unpkg": "dist/m3.js",
46
+ "types": "types/index.d.ts",
47
+ "files": [
48
+ "dist",
49
+ "lib",
50
+ "es",
51
+ "src",
52
+ "types"
53
+ ],
54
+ "displayName": "form-driver",
55
+ "dependencies": {
56
+ "@ant-design/icons": "^4.3.0",
57
+ "@babel/runtime": "^7.9.2",
58
+ "@testing-library/jest-dom": "^5.11.4",
59
+ "@testing-library/react": "^11.1.0",
60
+ "@testing-library/user-event": "^12.1.10",
61
+ "antd": "^4.16.5",
62
+ "antd-mobile": "^2.3.4",
63
+ "lodash": "^4.17.20",
64
+ "moment": "^2.29.1",
65
+ "react": "^17.0.1",
66
+ "react-dom": "^17.0.1"
67
+ },
68
+ "devDependencies": {
69
+ "@ant-design/tools": "^13.5.0-beta.1",
70
+ "@babel/cli": "^7.12.10",
71
+ "@babel/core": "^7.12.10",
72
+ "@babel/plugin-external-helpers": "^7.12.1",
73
+ "@babel/plugin-proposal-class-properties": "^7.12.1",
74
+ "@babel/plugin-proposal-decorators": "^7.12.12",
75
+ "@babel/plugin-proposal-object-rest-spread": "^7.12.1",
76
+ "@babel/plugin-transform-react-display-name": "^7.12.1",
77
+ "@babel/plugin-transform-react-jsx": "^7.12.12",
78
+ "@babel/plugin-transform-runtime": "^7.12.10",
79
+ "@babel/preset-env": "^7.12.11",
80
+ "@babel/preset-react": "^7.12.10",
81
+ "@babel/preset-typescript": "^7.12.7",
82
+ "@rollup/plugin-babel": "^5.0.0",
83
+ "@rollup/plugin-image": "^2.0.6",
84
+ "@rollup/plugin-replace": "^2.3.2",
85
+ "@types/lodash": "^4.14.165",
86
+ "@types/node": "^14.14.10",
87
+ "@types/react": "^17.0.0",
88
+ "@types/react-dom": "^17.0.0",
89
+ "babel-core": "^7.0.0-0",
90
+ "babel-eslint": "^8.0.1",
91
+ "babel-jest": "^22.2.2",
92
+ "babel-loader": "^7.1.2",
93
+ "babel-plugin-import": "^1.13.3",
94
+ "cross-env": "^7.0.3",
95
+ "css-loader": "^0.28.0",
96
+ "css-minimizer-webpack-plugin": "^3.0.0",
97
+ "dingtalk-jsapi": "^2.13.20",
98
+ "happypack": "^5.0.1",
99
+ "html-loader": "^0.5.1",
100
+ "html-webpack-plugin": "^3.2.0",
101
+ "less": "^3.11.1",
102
+ "less-loader": "^7.2.1",
103
+ "mini-css-extract-plugin": "^0.5.0",
104
+ "npm-run-all": "^4.1.1",
105
+ "postcss": "^8.2.4",
106
+ "postcss-cssnext": "^3.1.0",
107
+ "postcss-nested": "^5.0.3",
108
+ "postcss-preset-env": "^6.7.0",
109
+ "postcss-simple-vars": "^6.0.2",
110
+ "react-intl": "^5.18.1",
111
+ "rimraf": "^2.5.2",
112
+ "rollup": "^2.38.0",
113
+ "rollup-plugin-babel": "^4.4.0",
114
+ "rollup-plugin-commonjs": "^10.1.0",
115
+ "rollup-plugin-json": "^4.0.0",
116
+ "rollup-plugin-node-resolve": "^5.2.0",
117
+ "rollup-plugin-postcss": "^4.0.0",
118
+ "rollup-plugin-serve": "^1.0.1",
119
+ "rollup-plugin-terser": "^7.0.2",
120
+ "rollup-plugin-typescript2": "^0.29.0",
121
+ "style-loader": "^0.20.0",
122
+ "ts-loader": "^8.0.14",
123
+ "ts-node-dev": "^1.0.0",
124
+ "typescript": "^3.8.3",
125
+ "webpack": "^4.16.1",
126
+ "webpack-cli": "^3.1.0",
127
+ "webpack-dev-server": "^3.1.11"
128
+ },
129
+ "engines": {
130
+ "node": ">=v14.15.4"
131
+ }
132
+ }
package/src/.DS_Store ADDED
Binary file
@@ -0,0 +1,96 @@
1
+ import { message } from 'antd';
2
+
3
+ function generateQueryStr(obj = {}) {
4
+ let str = ''
5
+ const keys = Object.keys(obj)
6
+ if (keys.length > 0) {
7
+ const arr = []
8
+ keys.forEach(k => {
9
+ arr.push(`${k}=${encodeURIComponent(obj[k])}`)
10
+ })
11
+ str = `?${arr.join('&')}`
12
+ }
13
+ return str
14
+ }
15
+
16
+ export const Ajax = {
17
+ req(method:'GET'|'POST'|'PUT', apiPath:string, urlArgs:any, body:any, headers:any,
18
+ prompt:any = {succ:"提交完成", networkFail:"网络异常", bizFail:"提交失败"}):Promise<any> {
19
+ const args = {
20
+ method: method,
21
+ body: JSON.stringify(body),
22
+ headers: {'Content-Type': 'application/json', ...headers}
23
+ }
24
+ return new Promise<any>(function(resolve, reject) {
25
+ fetch(`${apiPath}${generateQueryStr(urlArgs)}`, args)
26
+ .then(d => d.json())
27
+ .then(resp => {
28
+ if(resp.errorCode === 0) {
29
+ if(prompt.succ){
30
+ message.success(prompt.succ);
31
+ }
32
+ resolve(resp);
33
+ } else {
34
+ message.error(resp.message ?? prompt.bizFail);
35
+ reject(resp);
36
+ }
37
+ })
38
+ .catch(e=>{
39
+ console.log(e);
40
+ message.error(prompt.networkFail);
41
+ reject();
42
+ })
43
+ });
44
+ },
45
+
46
+ post(apiPath:string, data:any, succMsg:string = "提交完成"):Promise<any> {
47
+ const args = {
48
+ method: 'POST',
49
+ body:JSON.stringify(data),
50
+ headers: {'Content-Type': 'application/json'}
51
+ }
52
+ return new Promise<any>(function(resolve, reject){
53
+ fetch(apiPath, args)
54
+ .then(d => d.json())
55
+ .then(resp => {
56
+ if(resp.errorCode === 0) {
57
+ if(succMsg){
58
+ message.success(succMsg);
59
+ }
60
+ resolve(resp);
61
+ } else {
62
+ message.error(resp.message);
63
+ reject(resp);
64
+ }
65
+ })
66
+ .catch(e=>{
67
+ console.log(e);
68
+ message.error("网络异常");
69
+ reject();
70
+ })
71
+ });
72
+ },
73
+
74
+ get(apiPath:string, data?:object):Promise<any> {
75
+ if (data) {
76
+ apiPath = `${apiPath}${generateQueryStr(data)}`
77
+ }
78
+ return new Promise<void>(function(resolve, reject){
79
+ fetch(apiPath)
80
+ .then(res => res.json())
81
+ .then(resp => {
82
+ if(resp.errorCode === 0) {
83
+ resolve(resp);
84
+ } else {
85
+ message.error(resp.message);
86
+ reject();
87
+ }
88
+ })
89
+ .catch(e=>{
90
+ message.error("网络异常");
91
+ reject();
92
+ })
93
+ });
94
+ }
95
+ }
96
+
@@ -0,0 +1,165 @@
1
+ import React, { ClassType } from "react";
2
+ import { MValidationResult, MFieldSchemaAnonymity, MProp, MValidationFail } from './Schema';
3
+ import _ from "lodash";
4
+ import { MUtil } from './MUtil';
5
+ import { MType, PluginType } from "../types/MType";
6
+
7
+ export type MORPH = "readable" | "editor";
8
+ export type VIEWER = ClassType<MProp, any, any>
9
+
10
+ /** 统一的视觉样式 */
11
+ export interface MTheme {
12
+ // 负向数据展示文案
13
+ /** 数据未知时展示 */
14
+ readonly READABLE_UNKNOWN: string;
15
+ /** 数据为空的时候展示 */
16
+ readonly READABLE_BLANK: string;
17
+ /** 数据有问题时展示 */
18
+ readonly READABLE_INVALID: string;
19
+ /** 代码有问题时展示 */
20
+ readonly READABLE_ERROR: string;
21
+
22
+ /** @deprecated theme的名字 */
23
+ readonly themeName: "antMiddle" | string;
24
+ }
25
+
26
+ export interface EDITOR {
27
+ // 编辑器
28
+ editor: string;
29
+ // 数据类型
30
+ type: string;
31
+ // 阅读器
32
+ readable: string;
33
+ }
34
+
35
+ const defaultTheme: MTheme = {
36
+ READABLE_UNKNOWN: "?",
37
+ READABLE_BLANK: "-",
38
+ READABLE_INVALID: "❓",
39
+ READABLE_ERROR: "❗",
40
+
41
+ themeName: "antMiddle"
42
+ }
43
+
44
+ let rootHideMap = {}
45
+ /**
46
+ * 注册viewer,type,morph(viewer和type之间的关联)
47
+ */
48
+ export class Assembly {
49
+ types: { [name: string]: MType } = {};
50
+ viewers: { [name: string]: VIEWER } = {};
51
+ editors: { [name: string]: EDITOR } = {};
52
+ morph: { [name: /*MORPH*/ string]: { [typeName: string]: string | ClassType<MProp, any, any> /* viewer name or viewer */ } } = {}
53
+
54
+ theme: MTheme = defaultTheme;
55
+
56
+ toReadable = (s: MFieldSchemaAnonymity, v: any, parent: any): string => {
57
+ const t = this.types[s.type];
58
+ if (t) {
59
+ let r;
60
+ if (_.isString(s.toReadable)) {
61
+ // eslint-disable-next-line no-new-func
62
+ r = new Function("_", "value", "theme",
63
+ "const {READABLE_UNKNOWN, READABLE_BLANK, READABLE_INVALID, READABLE_ERROR} = theme; return " + s.toReadable)(_, v, this.theme);
64
+ } else if (_.isFunction(s.toReadable)) {
65
+ r = s.toReadable(v, parent, this);
66
+ }
67
+ r = r ?? t.toReadable(this, s, v);
68
+
69
+ if (s.postfix) {
70
+ r += s.postfix;
71
+ }
72
+ return r;
73
+ } else {
74
+ return s.type + "类型无效"
75
+ }
76
+ }
77
+
78
+ /** 根据定义返回View,返回nil表示没有可用的View */
79
+ getViewerOf(f: MFieldSchemaAnonymity, morph: MORPH): ClassType<any, any, any> {
80
+ if (f.editor && morph === "editor") {
81
+ if (_.isString(f.editor)) {
82
+ return _.get(this.viewers, f.editor);
83
+ } else {
84
+ return f.editor;
85
+ }
86
+ } else if (f.readable && morph === "readable") {
87
+ if (_.isString(f.readable)) {
88
+ return _.get(this.viewers, f.readable);
89
+ } else {
90
+ return f.readable;
91
+ }
92
+ } else {
93
+ const viewer: string | ClassType<MProp, any, any> = _.get(this.morph, morph + "." + f.type);
94
+ if (_.isString(viewer)) {
95
+ return _.get(this.viewers, viewer);
96
+ } else {
97
+ return viewer
98
+ }
99
+ }
100
+ }
101
+
102
+ validate(s: MFieldSchemaAnonymity, v: any, path: string = ""): MValidationFail | undefined {
103
+ let result: MValidationResult = undefined;
104
+ for (let validator of this.types[s.type].validators) {
105
+ result = validator(this, s, v, path);
106
+ if (result === "pass") {
107
+ return undefined;
108
+ } else if (result) {
109
+ MUtil.debug("校验", path, result.message);
110
+ return result;
111
+ }
112
+ }
113
+ return undefined;
114
+ }
115
+
116
+ addViewer(name: string, v: VIEWER) {
117
+ if (this.viewers[name]) {
118
+ console.error(`addViewer: 已经存在名为 ${name} 的 Viewer,无法再次添加!`)
119
+ return
120
+ } else {
121
+ this.viewers[name] = v;
122
+ }
123
+ }
124
+
125
+ addEditor(name: string, v: EDITOR) {
126
+ if (this.editors[name]) {
127
+ console.error(`addEditor: 已经存在名为 ${name} 的 Editor,无法再次添加!`)
128
+ return
129
+ } else {
130
+ this.editors[name] = v;
131
+ }
132
+ }
133
+
134
+ /**
135
+ * 增加一种数据类型
136
+ * 例:
137
+ * const hpOrg = {name: "hpOrg", type: {validators: ..., toReadable: ...}, editor: HPOrgEditor, readable: "DivViewer"}
138
+ * addType(hpOrg)
139
+ * @param typeParam 类型的描述对象
140
+ */
141
+ addType(typeParam: PluginType) {
142
+ const { name, type, editor, readable = "DivViewer" } = typeParam
143
+ this.types[name] = type;
144
+ _.set(this.morph, "editor." + name, editor);
145
+ _.set(this.morph, "readable." + name, readable);
146
+
147
+ }
148
+
149
+ constructor() {
150
+ // 校验types是否使用了无效的编辑器名字
151
+ for (let morphName in this.morph) {
152
+ for (let typeName in this.morph[morphName]) {
153
+ if (!this.types[typeName]) {
154
+ throw SyntaxError(`类型${typeName}未定义`);
155
+ }
156
+ const viewerName = this.morph[morphName][typeName];
157
+ if (!this.viewers[viewerName]) {
158
+ throw SyntaxError(`视图${viewerName}未定义`);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+
165
+ export const assembly: Assembly = new Assembly();
@@ -0,0 +1,196 @@
1
+ import { assembly } from './Assembly';
2
+ import { MEnumType } from "../types/MEnumType";
3
+ import { MGB2260Type } from "../types/MGB2260Type";
4
+ import { MDateTimeType } from '../types/MDateTimeType';
5
+ import { MSetType } from '../types/MSetType';
6
+ import { MArrayType } from "../types/MArrayType";
7
+ import { MStringType } from '../types/MStringType';
8
+ import { MIntDiffType } from '../types/MIntDiffType';
9
+ import { MIntType } from '../types/MIntType';
10
+ import { MMatrixType } from "../types/MMatrixType";
11
+ import { MObjectType } from "../types/MObjectType";
12
+ import { MExperienceType } from "../types/MExperienceType";
13
+ import { MCnAddress } from "../types/MCnAddressType";
14
+ import { MTelType, MCnPhoneType, MEmailType } from '../types/MTelType';
15
+ import { MDateRangeType } from "../types/MDateRangeType";
16
+ import { ArrayViewer } from '../ui/readable/ArrayViewer';
17
+ import { ADatetimePicker } from "../ui/editor/basic/ADatetimePicker";
18
+ import { AGB2260 } from "../ui/editor/basic/AGB2260";
19
+ import { ARadio } from "../ui/editor/basic/ARadio";
20
+ import { ARate } from "../ui/editor/basic/ARate";
21
+ import { AUpload } from "../ui/editor/basic/AUpload";
22
+ import { ATreeSelect } from "../ui/editor/basic/ATreeSelect";
23
+ import { NPS } from "../ui/editor/basic/NPS";
24
+ import { AIntBox } from "../ui/editor/basic/AIntBox";
25
+ import { ACheckBox } from "../ui/editor/basic/ACheckBox";
26
+ import { AInputBox } from "../ui/editor/basic/AInputBox";
27
+ import { AMatrix } from '../ui/editor/complex/AMatrix';
28
+ import { ASpecInputBox } from '../ui/editor/basic/ASpecInputBox';
29
+ import { AForm } from '../ui/editor/complex/AForm';
30
+ import { DivViewer } from '../ui/readable/DivViewer';
31
+ import { ASelector } from "../ui/editor/basic/ASelector";
32
+ import { ASetSelector } from '../ui/editor/basic/ASetSelector';
33
+ import { AExperience } from '../ui/editor/complex/AExperience';
34
+ import { ACnAddress } from '../ui/editor/complex/ACnAddress';
35
+ import { AArray } from '../ui/editor/complex/AArray';
36
+ import { AArrayGrid } from '../ui/editor/complex/AArrayGrid';
37
+ import { ARangePicker } from '../ui/editor/basic/ARangePicker';
38
+ import { AIntDiff } from '../ui/editor/complex/AIntDiff';
39
+ import { MFloatType } from '../types/MFloatType';
40
+ import { MDecorationType } from '../types/MDecorationType';
41
+ import { DecorationViewer } from '../ui/readable/DecorationViewer';
42
+ import { ATable } from '../ui/editor/complex/ATable';
43
+ import { ARemoteSelector } from '../ui/editor/basic/ARemoteSelector';
44
+ import { JsonEditor } from '../ui/editor/complex/JsonEditor';
45
+ import _ from "lodash";
46
+ import { A } from '../ui/readable/A';
47
+ import { ADialogForm } from '../ui/editor/complex/ADialogForm';
48
+ import { MVLPairType } from '../types/MVLPairType';
49
+ import { MKvSetType } from '../types/MKvSetType';
50
+ import { AKvSet } from '../ui/editor/basic/AKvSet';
51
+ import { ACascadePicker } from '../ui/editor/basic/ACascadePicker';
52
+ import { MCascadeType } from '../types/MCascadeType';
53
+ import editorMap from './editorMap';
54
+
55
+
56
+ let init = false;
57
+ /**
58
+ * 确保m3已经初始化ensureM3
59
+ */
60
+ export function ensureM3(){
61
+ if(init){
62
+ return;
63
+ }
64
+ init = true;
65
+ assembly.types = _.merge(assembly.types, {
66
+ "enum": MEnumType,
67
+ "gb2260": MGB2260Type,
68
+ "datetime": MDateTimeType,
69
+ "year": MDateTimeType,
70
+ "yearMonth": MDateTimeType,
71
+ "yearMonthDay": MDateTimeType,
72
+ "set": MSetType,
73
+ "array": MArrayType,
74
+ "string": MStringType,
75
+ "intDiff": MIntDiffType,
76
+ "int": MIntType,
77
+ "float": MFloatType,
78
+ "matrix": MMatrixType,
79
+ "object": MObjectType,
80
+ "experience": MExperienceType,
81
+ "cnAddress": MCnAddress,
82
+ "tel": MTelType,
83
+ "email": MEmailType,
84
+ "cnPhone": MCnPhoneType,
85
+ "dateRange": MDateRangeType,
86
+ "decoration": MDecorationType,
87
+ "vl": MVLPairType,
88
+ "kvSet": MKvSetType,
89
+ "cascade": MCascadeType,
90
+ });
91
+
92
+ // 实验性组件 AArray、ATable、ADialogForm、AForm、ASetSelector、JsonEditor
93
+ assembly.viewers = _.merge(assembly.viewers, {
94
+ "ADatetimePicker": ADatetimePicker,
95
+ "AGB2260": AGB2260,
96
+ "ARadio": ARadio,
97
+ "ARate": ARate,
98
+ "AUpload": AUpload,
99
+ "ATreeSelect": ATreeSelect,
100
+ "NPS": NPS,
101
+ "ACheckBox": ACheckBox,
102
+ "AIntBox": AIntBox,
103
+ "AInputBox": AInputBox,
104
+ "AMatrix": AMatrix,
105
+ "ASpecInputBox": ASpecInputBox,
106
+ "AForm": AForm,
107
+ "AArray": AArray,
108
+ "AArrayGrid": AArrayGrid,
109
+ "ARangePicker": ARangePicker,
110
+ "AIntDiff": AIntDiff,
111
+ "ACnAddress": ACnAddress,
112
+ "AExperience": AExperience,
113
+ "ASetSelector": ASetSelector,
114
+ "ASelector": ASelector,
115
+ "DivViewer": DivViewer,
116
+ "ArrayViewer": ArrayViewer,
117
+ "DecorationViewer": DecorationViewer,
118
+ "ATable": ATable,
119
+ "ARemoteSelector": ARemoteSelector,
120
+ "JsonEditor": JsonEditor,
121
+ "A": A,
122
+ "ADialogForm": ADialogForm,
123
+ "AKvSet": AKvSet,
124
+ "ACascadePicker": ACascadePicker,
125
+ });
126
+
127
+ assembly.morph = _.merge(assembly.morph, {
128
+ // 编辑
129
+ "editor": {
130
+ "enum": "ASelector",
131
+ "gb2260":"AGB2260",
132
+ "datetime": "ADatetimePicker",
133
+ "year": "ADatetimePicker",
134
+ "yearMonth": "ADatetimePicker",
135
+ "yearMonthDay": "ADatetimePicker",
136
+ "set": "ACheckBox",
137
+ "array": "AArray",
138
+ "string": "AInputBox",
139
+
140
+ "intDiff": "AIntDiff",
141
+ "int": "AIntBox",
142
+ "float": "AIntBox",
143
+
144
+ "matrix": "AMatrix",
145
+ "object": "AForm",
146
+
147
+ "experience": "AExperience",
148
+ "kvSet": "AKvSet",
149
+
150
+ // TODO 这些类型还没有校验
151
+ "cnAddress": "ACnAddress",
152
+ "tel": "ASpecInputBox",
153
+ "email": "ASpecInputBox",
154
+ "cnPhone": "ASpecInputBox",
155
+ "dateRange": "ARangePicker",
156
+ "decoration": "DecorationViewer",
157
+
158
+ "vl": "ARemoteSelector",
159
+ "cascade": "ACascadePicker"
160
+ },
161
+ // 详情
162
+ "readable": {
163
+ "enum": "DivViewer",
164
+ "gb2260": "DivViewer",
165
+ "datetime": "DivViewer",
166
+ "year": "DivViewer",
167
+ "yearMonth": "DivViewer",
168
+ "yearMonthDay": "DivViewer",
169
+
170
+ "set": "DivViewer",
171
+ "array": "ArrayViewer",
172
+ "string": "DivViewer",
173
+
174
+ "intDiff": "DivViewer",
175
+ "int": "DivViewer",
176
+ "float": "DivViewer",
177
+
178
+ "matrix": "DivViewer",
179
+ "object": "AForm",
180
+ "experience": "DivViewer",
181
+ "kvSet": "DivViewer",
182
+
183
+ "cnAddress": "DivViewer",
184
+ "tel": "DivViewer",
185
+ "email": "DivViewer",
186
+ "cnPhone": "DivViewer",
187
+ "dateRange":"DivViewer",
188
+ "decoration": "DecorationViewer",
189
+ "vl": "DivViewer",
190
+
191
+ "cascade": "DivViewer"
192
+ }
193
+ })
194
+
195
+ assembly.editors = _.merge(assembly.editors, editorMap)
196
+ }
@@ -0,0 +1,94 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { M3Prop, MViewer } from './MViewer';
3
+ import { MViewerDebug } from './MViewerDebug';
4
+ import editorMap from './editorMap';
5
+ import { MFieldSchema, M3UISpec, MFieldSchemaAnonymity } from "../../src/framework/Schema";
6
+ import _ from "lodash";
7
+
8
+ // 外部 schema 转化为内部
9
+ function deal(fieldSchema: MFieldSchemaAnonymity | MFieldSchema) {
10
+ if(fieldSchema.arrayMember){
11
+ deal(fieldSchema.arrayMember);
12
+ } else if(fieldSchema.objectFields){
13
+ for(let f of fieldSchema.objectFields){
14
+ deal(f);
15
+ }
16
+ } else {
17
+ let opt = fieldSchema.option ?? fieldSchema.setFields ?? fieldSchema.enumFields
18
+ if (opt) {
19
+ if (typeof opt === 'string') {
20
+ fieldSchema.option = opt.split(" ").map(
21
+ aEnum => {
22
+ const kv = aEnum.split("=");
23
+ return { label: kv[0], value: kv[1] ?? kv[0] };
24
+ }
25
+ );
26
+ } else {
27
+ fieldSchema.option = opt
28
+ }
29
+ }
30
+
31
+ fieldSchema.openOption = fieldSchema.openOption ?? fieldSchema.setOpen ?? fieldSchema.enumOpen
32
+
33
+ if (!fieldSchema.type && fieldSchema.editor) {
34
+ Object.assign(fieldSchema, editorMap[fieldSchema.editor])
35
+ }
36
+ }
37
+ }
38
+
39
+ // 标准化 schema
40
+ function standardSchema(schema: MFieldSchema | MFieldSchema[], layout?: M3UISpec) {
41
+ const _schema = _.cloneDeep(schema)
42
+ if (_.isArray(_schema)) {
43
+ _schema.forEach(item => {
44
+ deal(item)
45
+ })
46
+ const temp: MFieldSchema = {
47
+ name: '__root__',
48
+ type: 'object',
49
+ objectFields: _schema
50
+ }
51
+ if (layout) {
52
+ temp.uispec = layout
53
+ }
54
+ return _.cloneDeep(temp)
55
+ } else {
56
+ deal(_schema)
57
+ return _schema
58
+ }
59
+ }
60
+
61
+
62
+ const M3 = (props: React.PropsWithChildren<M3Prop & { debug?: boolean }>) => {
63
+ const [prevProp, setPrevProp] = useState(props);
64
+
65
+ let [database, setDatabase] = useState(_.cloneDeep(props.database))
66
+ let [schema, setSchema] = useState(standardSchema(props.schema))
67
+ let [k, setK] = useState(0)
68
+
69
+ // debug 属性为真 且 页面地址携带 debug 参数,开启调试模式
70
+ let debug = props.debug || (window.location.search.indexOf("debug") >= 0 || window.location.hash.indexOf("debug") >= 0);
71
+
72
+ useEffect(() => {
73
+ if(props.schema != prevProp.schema) {
74
+ setSchema(standardSchema(props.schema))
75
+ setPrevProp(props);
76
+ setK(++k)
77
+ }
78
+ }, [props.schema])
79
+
80
+ useEffect(() => {
81
+ if(props.database != prevProp.database) {
82
+ setDatabase(_.cloneDeep(props.database))
83
+ setPrevProp(props);
84
+ setK(++k)
85
+ }
86
+ }, [props.database])
87
+
88
+ return (
89
+ debug ? <MViewerDebug key={k} {...props} database={database} schema={schema} /> :
90
+ <MViewer key={k} {...props} database={database} schema={schema} />
91
+ );
92
+ }
93
+
94
+ export default M3;