@hzab/form-render 1.3.0 → 1.3.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/CHANGELOG.md CHANGED
@@ -1,9 +1,18 @@
1
+ # @hzab/form-render@1.3.2
2
+
3
+ fix: schema props 为 schemaScope 字符串的情况
4
+
5
+ # @hzab/form-render@1.3.1
6
+
7
+ feat: 表单 onChange 事件(目前仅做触发,值计算后续优化)
8
+
1
9
  # @hzab/form-render@1.3.0
2
10
 
3
11
  break: 去除 lib,默认 src
4
12
 
5
13
  # @hzab/form-render@1.2.5
6
- - fix: LocationListPicker组件高度调整与删除点位修复
14
+
15
+ - fix: LocationListPicker 组件高度调整与删除点位修复
7
16
 
8
17
  # @hzab/form-render@1.2.4
9
18
 
@@ -12,7 +21,7 @@ fix: UserSelect InfoRender
12
21
 
13
22
  # @hzab/form-render@1.2.3
14
23
 
15
- - fix: 富文本添加loading样式
24
+ - fix: 富文本添加 loading 样式
16
25
 
17
26
  # @hzab/form-render@1.2.2
18
27
 
package/README.md CHANGED
@@ -116,16 +116,17 @@ import FormRender from "@hzab/form-render";
116
116
 
117
117
  ### InfoPanel Attributes
118
118
 
119
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
120
- | ------------- | ------- | ---- | ---------- | -------------------------------------- |
121
- | schema | Object | 是 | - | 数据信息的 schema |
122
- | schemaScope | Object | 否 | - | 全局作用域,用于实现协议表达式变量注入 |
123
- | layout | Object | 否 | horizontal | 表单布局,horizontal vertical \ inline |
124
- | initialValues | Object | 否 | - | form 初始值 |
125
- | components | Object | 否 | - | 自定义组件 |
126
- | formOptions | Object | 否 | - | createForm 的参数 |
127
- | disabled | boolean | 否 | - | 禁用状态 |
128
- | readOnly | boolean | 否 | - | 只读状态 |
119
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
120
+ | ------------- | -------- | ---- | ---------- | -------------------------------------------------- |
121
+ | schema | Object | 是 | - | 数据信息的 schema |
122
+ | schemaScope | Object | 否 | - | 全局作用域,用于实现协议表达式变量注入 |
123
+ | layout | Object | 否 | horizontal | 表单布局,horizontal vertical \ inline |
124
+ | initialValues | Object | 否 | - | form 初始值 |
125
+ | components | Object | 否 | - | 自定义组件 |
126
+ | formOptions | Object | 否 | - | createForm 的参数 |
127
+ | disabled | boolean | 否 | - | 禁用状态 |
128
+ | readOnly | boolean | 否 | - | 只读状态 |
129
+ | onChange | Function | 否 | - | 表单 onChange 事件(目前仅做触发,值计算后续优化) |
129
130
 
130
131
  ### 方法 Methods
131
132
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/form-render",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -0,0 +1,176 @@
1
+ import _ from "lodash";
2
+
3
+ /** 自增容器 */
4
+ export const arrayList = ["ArrayTable", "ArrayCards"];
5
+ /** 不需要绑定事件的目标 */
6
+ export const skipBindList = ["FormCollapse", "FormCollapse.CollapsePanel"];
7
+ /** change 回调返回 parent 数据的组件 */
8
+ export const returnParentValue = ["ArrayTable", "ArrayCards"];
9
+
10
+ /**
11
+ * schema 每项添加 onChange,解决无全局 onChange 问题
12
+ * @param schema
13
+ * @param onChange
14
+ * @returns
15
+ */
16
+ export const bindOnChange = (schema, opt) => {
17
+ const { schemaScope, onChange, formRender, parent, isCloneDeep = true } = opt || {};
18
+ let _schema = isCloneDeep ? _.cloneDeep(schema) : schema;
19
+ _schema = _schema.schema || _schema;
20
+ Object.keys(_schema.properties || {})?.forEach((key) => {
21
+ let item = _schema.properties[key];
22
+ if (!item) {
23
+ return;
24
+ }
25
+ const componentName = item["x-component"];
26
+ // 解决 name 丢失的问题
27
+ item.name = key;
28
+
29
+ const comProps = item?.["x-component-props"];
30
+ if (!comProps) {
31
+ item["x-component-props"] = {};
32
+ } else if (isScopeKey(comProps)) {
33
+ item["x-component-props"] = getValByScope(comProps, schemaScope) || {};
34
+ }
35
+
36
+ const bindParams = {
37
+ componentName,
38
+ target: item["x-component-props"],
39
+ targetKey: key,
40
+ targetId: key,
41
+ formOnChange: onChange,
42
+ schemaScope,
43
+ formRender,
44
+ parent,
45
+ };
46
+
47
+ // 不需要绑定事件的目标:折叠面板不需要设置 onChange 事件,否则会导致触发多次
48
+ if (!skipBindList.includes(componentName)) {
49
+ // 绑定新的 change 事件
50
+ bindCallback({
51
+ ...bindParams,
52
+ actionName: "onChange",
53
+ });
54
+ }
55
+
56
+ // 处理自增表格、卡片等情况
57
+ if (arrayList.includes(componentName)) {
58
+ bindOnChange(item.items, {
59
+ ...opt,
60
+ parent: item,
61
+ isCloneDeep: false,
62
+ });
63
+ // 处理点击新增、删除、排序操作
64
+ const actions = ["onAdd", "onCopy", "onRemove", "onMoveDown", "onMoveUp"];
65
+ actions.forEach((actionName) => {
66
+ bindCallback({
67
+ ...bindParams,
68
+ actionName,
69
+ });
70
+ });
71
+ }
72
+
73
+ // 处理嵌套的情况
74
+ if (item.properties) {
75
+ bindOnChange(item, {
76
+ ...opt,
77
+ isCloneDeep: false,
78
+ });
79
+ }
80
+ });
81
+ return _schema;
82
+ };
83
+
84
+ /**
85
+ * 添加回调函数
86
+ * @param target
87
+ * @param name
88
+ * @param formOnChange
89
+ */
90
+ export const bindCallback = (opt) => {
91
+ const { target, actionName, schemaScope, formOnChange } = opt || {};
92
+ const tempFn = target[actionName];
93
+ target[actionName] = function (...sourceArgs) {
94
+ // 处理结果数据,各组件返回数据格式不一致
95
+ const res = handleChangeValue({
96
+ ...opt,
97
+ sourceArgs,
98
+ });
99
+ // 触发组件 onChange 事件
100
+ if (isScopeKey(tempFn)) {
101
+ // schemaScope 传入方式
102
+ const fn = schemaScope && schemaScope[getScopeKey(tempFn)];
103
+ typeof fn === "function" && fn(...sourceArgs, res);
104
+ } else if (typeof tempFn === "function") {
105
+ // 直接传入函数的方式
106
+ tempFn(...sourceArgs, res);
107
+ }
108
+ formOnChange && formOnChange(res);
109
+ };
110
+ };
111
+
112
+ /**
113
+ * 从 onChange 事件中获取数据
114
+ * @param args
115
+ */
116
+ export const handleChangeValue = (opt) => {
117
+ const { componentName, formRender, parent, targetKey, actionName, sourceArgs } = opt || {};
118
+ console.log("parent", parent);
119
+ // 自增表格、卡片无法获知当前编辑内容所在的索引,导致无法知道当前值
120
+ const res = {
121
+ key: targetKey,
122
+ actionName: actionName,
123
+ formRender,
124
+ formValues: formRender.values,
125
+ sourceArgs: sourceArgs,
126
+ // value: formRender.getValuesIn(targetKey),
127
+ // parent,
128
+ // TODO: 自增情况下无法获知索引
129
+ // parentValue: formRender.getValuesIn(parent?.name),
130
+ };
131
+
132
+ // TODO: 自增返回父级值?
133
+ // if (returnParentValue.includes(parent?.["x-component"])) {
134
+ // res.value = res.parentValue;
135
+ // }
136
+
137
+ return res;
138
+ };
139
+
140
+ /**
141
+ * 是否是 scope key
142
+ * @param strKey
143
+ * @returns
144
+ */
145
+ export const isScopeKey = (strKey) => {
146
+ if (typeof strKey !== "string") {
147
+ return false;
148
+ }
149
+ const key = strKey.trim();
150
+ return key.startsWith("{{") && key.endsWith("}}");
151
+ };
152
+
153
+ /**
154
+ * 获取 scope key
155
+ * @param strKey
156
+ * @returns
157
+ */
158
+ export const getScopeKey = (strKey) => {
159
+ if (!isScopeKey(strKey)) {
160
+ return "";
161
+ }
162
+ const key = strKey.trim();
163
+ return key.replace(/^\{\{/, "").replace(/\}\}$/, "");
164
+ };
165
+
166
+ /**
167
+ * 通过字符串获取 schemaScope 中的数据
168
+ * @param strKey
169
+ * @param schemaScope
170
+ * @returns
171
+ */
172
+ export const getValByScope = (strKey, schemaScope = {}) => {
173
+ if (isScopeKey(strKey)) {
174
+ return schemaScope && schemaScope[getScopeKey(strKey)];
175
+ }
176
+ };
package/src/index.tsx CHANGED
@@ -30,9 +30,11 @@ import {
30
30
  ArrayCards,
31
31
  } from "c-formily-antd";
32
32
  import { Card, Slider, Rate } from "antd";
33
+
33
34
  // 自定义组件
34
35
  import * as customComponents from "./components/index";
35
36
  import { GlobalPropsContext } from "./common/global-props-context";
37
+ import { bindOnChange } from "./common/schema-handler";
36
38
 
37
39
  import "./index.less";
38
40
 
@@ -146,6 +148,14 @@ const FormRender = forwardRef((props: any, parentRef) => {
146
148
  ...props.schema?.form,
147
149
  };
148
150
 
151
+ const schema = useMemo(() => {
152
+ return bindOnChange(props.schema, {
153
+ schemaScope: props.schemaScope,
154
+ onChange: props.onChange,
155
+ formRender,
156
+ });
157
+ }, []);
158
+
149
159
  return (
150
160
  <GlobalPropsContext.Provider value={props}>
151
161
  <Form
@@ -158,7 +168,7 @@ const FormRender = forwardRef((props: any, parentRef) => {
158
168
  onAutoSubmitFailed={autoSubmitFailed}
159
169
  >
160
170
  <FormLayout {...formLayoutProps}>
161
- <SchemaField schema={props.schema.schema}></SchemaField>
171
+ <SchemaField schema={schema}></SchemaField>
162
172
  <div className="form-render-footer xxm">{footer}</div>
163
173
  </FormLayout>
164
174
  </Form>