@hzab/list-render 1.10.10 → 1.10.12-beta
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 +10 -0
- package/package.json +5 -3
- package/src/common/cloneSchema.ts +63 -0
- package/src/common/handleQuerySchema.ts +3 -2
- package/src/common/handleReactions.js +3 -2
- package/src/common/utils.js +281 -279
- package/src/components/Formily/FormilyEditTable.tsx +15 -7
- package/src/components/Formily/FormilyField.tsx +16 -5
- package/src/list-render.jsx +11 -12
- package/src/query-render/index.jsx +2 -2
- package/src/table-render/index.jsx +3 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
# @hzab/list-render@1.10.12
|
|
2
|
+
|
|
3
|
+
fix: table 响应数据 去除 inTable == false 的字段
|
|
4
|
+
feat: schema title 支持传入 ReactNode
|
|
5
|
+
feat: schema clone 函数
|
|
6
|
+
|
|
7
|
+
# @hzab/list-render@1.10.11
|
|
8
|
+
|
|
9
|
+
fix: 行内编辑统一 onEdit 获取数据,单元格编辑支持传入其他参数
|
|
10
|
+
|
|
1
11
|
# @hzab/list-render@1.10.10
|
|
2
12
|
|
|
3
13
|
fix: 解决 FormModal 与 DetailModal 相互影响的问题
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hzab/list-render",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.12-beta",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "src",
|
|
6
6
|
"scripts": {
|
|
@@ -27,15 +27,16 @@
|
|
|
27
27
|
"@hzab/permissions": "^1.0.0",
|
|
28
28
|
"@hzab/schema-descriptions": "^1.3.0",
|
|
29
29
|
"@hzab/webpack-config": "^0.7.2",
|
|
30
|
+
"@hzab/utils": "^1.0.7",
|
|
30
31
|
"@types/react": "^17.0.62",
|
|
31
32
|
"@types/react-dom": "^17.0.20",
|
|
32
33
|
"antd": "^4.24.12",
|
|
33
34
|
"axios": "^1.4.0",
|
|
34
35
|
"eslint": "^8.30.0",
|
|
35
|
-
"mobx": "^6.7.0",
|
|
36
|
-
"mobx-react": "^7.6.0",
|
|
37
36
|
"less": "^4.1.3",
|
|
38
37
|
"lodash": "^4.17.21",
|
|
38
|
+
"mobx": "^6.7.0",
|
|
39
|
+
"mobx-react": "^7.6.0",
|
|
39
40
|
"react": "^17.0.2",
|
|
40
41
|
"react-dom": "^17.0.2",
|
|
41
42
|
"react-router-dom": "^6.8.1",
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"@hzab/form-render": ">=1.0.0",
|
|
50
51
|
"@hzab/formily-result-utils": ">=1.2.0",
|
|
51
52
|
"@hzab/schema-descriptions": ">=1.0.0",
|
|
53
|
+
"@hzab/utils": ">=1.0.7",
|
|
52
54
|
"antd": "4.x",
|
|
53
55
|
"axios": ">=1.4.0",
|
|
54
56
|
"c-formily-antd": "2.3.1",
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 检测是否为原生 HTML DOM 节点
|
|
5
|
+
* @param {any} node 待检测对象
|
|
6
|
+
* @returns {boolean} 是否为原生 DOM 节点
|
|
7
|
+
*/
|
|
8
|
+
function isHtmlDomNode(node) {
|
|
9
|
+
// 先判断浏览器环境,避免 SSR 报错;兼容 Node/HTMLElement 类型
|
|
10
|
+
return !!(typeof window !== "undefined" && node && (node instanceof HTMLElement || node instanceof Node));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 增强版 Formily Schema 克隆函数
|
|
15
|
+
* 解决 lodash cloneDeep 丢失 React DOM/原生 DOM 的问题,兼容多种特殊类型
|
|
16
|
+
* @param {object} schema 待克隆的 Formily Schema
|
|
17
|
+
* @returns {object} 克隆后的 Schema
|
|
18
|
+
*/
|
|
19
|
+
export function cloneSchema(schema) {
|
|
20
|
+
// 1. 基础类型(null/undefined/字符串/数字/布尔)直接返回
|
|
21
|
+
if (schema === null || typeof schema !== "object") {
|
|
22
|
+
return schema;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 2. React 虚拟DOM:直接保留原引用,不拷贝
|
|
26
|
+
if (React.isValidElement(schema)) {
|
|
27
|
+
return schema;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 3. 原生 HTML DOM 节点:直接保留原引用
|
|
31
|
+
if (isHtmlDomNode(schema)) {
|
|
32
|
+
return schema;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 4. 函数:Formily Schema 中的校验/格式化函数等,保留原引用
|
|
36
|
+
if (typeof schema === "function") {
|
|
37
|
+
return schema;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 5. 日期对象:创建新的 Date 实例,保证值相同但引用不同
|
|
41
|
+
if (schema instanceof Date) {
|
|
42
|
+
return new Date(schema.getTime());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 6. 正则对象:创建新的 RegExp 实例,保留源和标志
|
|
46
|
+
if (schema instanceof RegExp) {
|
|
47
|
+
return new RegExp(schema.source, schema.flags);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 7. 数组:递归克隆每一项
|
|
51
|
+
if (Array.isArray(schema)) {
|
|
52
|
+
return schema.map((item) => cloneSchema(item));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 8. 普通对象:递归克隆自有属性
|
|
56
|
+
const clonedObj = {};
|
|
57
|
+
for (const key in schema) {
|
|
58
|
+
if (Object.prototype.hasOwnProperty.call(schema, key)) {
|
|
59
|
+
clonedObj[key] = cloneSchema(schema[key]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return clonedObj;
|
|
63
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
|
-
import { getFieldMap } from "./utils";
|
|
3
2
|
import {
|
|
4
3
|
isRunStr,
|
|
5
4
|
handleSchemaStrVal,
|
|
6
5
|
isScopeKey as formIsScopeKey,
|
|
7
6
|
getScopeKeyVal,
|
|
8
7
|
} from "@hzab/form-render/src/common/schema-handler";
|
|
8
|
+
import { cloneSchema } from "@hzab/utils/src/formily/cloneSchema";
|
|
9
9
|
import { URL_PARAM_NAME } from "./constant";
|
|
10
|
+
import { getFieldMap } from "./utils";
|
|
10
11
|
|
|
11
12
|
// ===================== 类型定义 =====================
|
|
12
13
|
|
|
@@ -72,7 +73,7 @@ export const handleQuerySchema = (opt) => {
|
|
|
72
73
|
index += 1;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
const fieldMap = getFieldMap(
|
|
76
|
+
const fieldMap = getFieldMap(cloneSchema(schema));
|
|
76
77
|
filters?.forEach((key) => {
|
|
77
78
|
const item = fieldMap[key];
|
|
78
79
|
if (item) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { cloneDeep } from "lodash";
|
|
2
1
|
import { autorun, observable } from "@formily/reactive";
|
|
2
|
+
|
|
3
|
+
import { cloneSchema } from "@hzab/utils/src/formily/cloneSchema";
|
|
3
4
|
import { getStateFunc } from "./formily-utils";
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -14,7 +15,7 @@ export function handleReactions(fieldList, opt = {}) {
|
|
|
14
15
|
return fieldList;
|
|
15
16
|
}
|
|
16
17
|
const resList = [];
|
|
17
|
-
|
|
18
|
+
cloneSchema(fieldList).forEach((item) => {
|
|
18
19
|
handleReaction(item, opt);
|
|
19
20
|
resList.push(item);
|
|
20
21
|
});
|
package/src/common/utils.js
CHANGED
|
@@ -1,279 +1,281 @@
|
|
|
1
|
-
import { Schema } from "@formily/json-schema";
|
|
2
|
-
import _ from "lodash";
|
|
3
|
-
import dayjs from "dayjs";
|
|
4
|
-
import advancedFormat from "dayjs/plugin/advancedFormat";
|
|
5
|
-
import weekOfYear from "dayjs/plugin/weekOfYear";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
* @param {Object}
|
|
24
|
-
* @
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const {} =
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
_boxList = [];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
getFieldMap(field, fieldMap);
|
|
134
|
-
} else {
|
|
135
|
-
fieldMap
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
*
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
? field.
|
|
163
|
-
: field.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
*
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
*
|
|
213
|
-
* @param {
|
|
214
|
-
* @
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
"
|
|
233
|
-
"
|
|
234
|
-
"
|
|
235
|
-
"
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
1
|
+
import { Schema } from "@formily/json-schema";
|
|
2
|
+
import _ from "lodash";
|
|
3
|
+
import dayjs from "dayjs";
|
|
4
|
+
import advancedFormat from "dayjs/plugin/advancedFormat";
|
|
5
|
+
import weekOfYear from "dayjs/plugin/weekOfYear";
|
|
6
|
+
|
|
7
|
+
import { cloneSchema } from "@hzab/utils/src/formily/cloneSchema";
|
|
8
|
+
|
|
9
|
+
dayjs.extend(advancedFormat);
|
|
10
|
+
dayjs.extend(weekOfYear);
|
|
11
|
+
|
|
12
|
+
const dateFormatEnum = {
|
|
13
|
+
time: "YYYY-MM-DD HH:mm:ss",
|
|
14
|
+
date: "YYYY-MM-DD",
|
|
15
|
+
week: "YYYY年 w周",
|
|
16
|
+
quarter: "YYYY年 Q季度",
|
|
17
|
+
month: "YYYY-MM",
|
|
18
|
+
year: "YYYY",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 获取 field 对应的值
|
|
23
|
+
* @param {Object} field schema 项
|
|
24
|
+
* @param {Object} data 数据
|
|
25
|
+
* @param {Object} opt 配置项
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
export function getVal(field = {}, data = {}, opt = {}) {
|
|
29
|
+
const {} = opt;
|
|
30
|
+
let val = _.get(data, field.name);
|
|
31
|
+
const {} = field || {};
|
|
32
|
+
const xComponent = field["x-component"];
|
|
33
|
+
const xComponentProps = field["x-component-props"] || {};
|
|
34
|
+
|
|
35
|
+
if (val && (xComponent === "DatePicker" || xComponent === "DatePicker.RangePicker")) {
|
|
36
|
+
const { picker, showTime } = xComponentProps || {};
|
|
37
|
+
const mode = showTime === true ? "time" : picker || "date";
|
|
38
|
+
const _formatEnum = opt.dateFormatEnum || dateFormatEnum;
|
|
39
|
+
const format = xComponentProps?.format || _formatEnum[mode];
|
|
40
|
+
|
|
41
|
+
if (Array.isArray(val)) {
|
|
42
|
+
return val.map((it) => getDateVal(it, format)).join(" ~ ");
|
|
43
|
+
}
|
|
44
|
+
return getDateVal(val, format);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (val && (xComponent === "TimePicker" || xComponent === "TimePicker.RangePicker")) {
|
|
48
|
+
const format = xComponentProps?.format || "HH:mm:ss";
|
|
49
|
+
if (Array.isArray(val)) {
|
|
50
|
+
return val.map((it) => dayjs(it).format(format)).join(" ~ ");
|
|
51
|
+
}
|
|
52
|
+
return dayjs(val).format(format);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (xComponent === "Switch") {
|
|
56
|
+
if (val === undefined || val === false || val === field.inactiveValue) {
|
|
57
|
+
return field.inactiveText || "否";
|
|
58
|
+
}
|
|
59
|
+
if (val === true || val === field.activeValue) {
|
|
60
|
+
return field.activeText || "是";
|
|
61
|
+
}
|
|
62
|
+
return val;
|
|
63
|
+
}
|
|
64
|
+
if (typeof field.relation === "object") {
|
|
65
|
+
const { key, name, label } = field.relation;
|
|
66
|
+
return data[key]?.[name];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const dataSource = field?.dataSource || field.enum;
|
|
70
|
+
if (
|
|
71
|
+
(xComponent === "Select" || xComponent === "Radio.Group" || xComponent === "Checkbox.Group") &&
|
|
72
|
+
Array.isArray(dataSource)
|
|
73
|
+
) {
|
|
74
|
+
if (!Array.isArray(val)) {
|
|
75
|
+
return getFieldOptItByVal(val, field, opt)?.label || val;
|
|
76
|
+
} else if (Array.isArray(val)) {
|
|
77
|
+
let _val = [];
|
|
78
|
+
val.forEach((valIt) => {
|
|
79
|
+
_val.push(getFieldOptItByVal(val, field, opt)?.label || valIt);
|
|
80
|
+
});
|
|
81
|
+
val = _val;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (Array.isArray(val)) {
|
|
86
|
+
return val.join("、");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return val;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function getDateVal(val, format) {
|
|
93
|
+
return dayjs(val).format(format);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getFieldList(_schema, fieldList = [], opt = {}, isTableSortXIdex = false) {
|
|
97
|
+
const schema = _schema?.schema || _schema;
|
|
98
|
+
|
|
99
|
+
// 解决 schema 字符串可执行代码、变量等
|
|
100
|
+
const properties = Schema.getOrderProperties(schema);
|
|
101
|
+
const { boxList = [] } = opt || {};
|
|
102
|
+
let _boxList = ["FormGrid", "FormGrid.GridColumn"];
|
|
103
|
+
if (Array.isArray(boxList)) {
|
|
104
|
+
_boxList = [..._boxList, ...boxList];
|
|
105
|
+
} else if (boxList === false) {
|
|
106
|
+
_boxList = [];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
schema?.properties &&
|
|
110
|
+
properties.forEach((item) => {
|
|
111
|
+
const field = item.schema;
|
|
112
|
+
if (!field.name) {
|
|
113
|
+
field.name = item.key;
|
|
114
|
+
}
|
|
115
|
+
const componentName = field["x-component"];
|
|
116
|
+
if (_boxList.includes(componentName)) {
|
|
117
|
+
getFieldList(field, fieldList, opt);
|
|
118
|
+
} else {
|
|
119
|
+
fieldList.push(field);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
isTableSortXIdex && fieldList.sort((a, b) => a["x-index"] - b["x-index"]);
|
|
123
|
+
return fieldList;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function getFieldMap(_schema, fieldMap = {}) {
|
|
127
|
+
// const fieldMap = _.keyBy(getFieldList(_schema), "name");
|
|
128
|
+
const schema = _schema?.schema || _schema;
|
|
129
|
+
schema?.properties &&
|
|
130
|
+
Object.keys(schema?.properties).forEach((key) => {
|
|
131
|
+
const field = schema?.properties[key];
|
|
132
|
+
if (field["x-component"] === "FormGrid") {
|
|
133
|
+
getFieldMap(field, fieldMap);
|
|
134
|
+
} else if (field["x-component"] === "FormGrid.GridColumn") {
|
|
135
|
+
getFieldMap(field, fieldMap);
|
|
136
|
+
} else {
|
|
137
|
+
fieldMap[key] = field;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return fieldMap;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function objToFormData(data) {
|
|
145
|
+
const formData = new FormData();
|
|
146
|
+
Object.keys(data)?.forEach((key) => {
|
|
147
|
+
formData.set(key, data[key]);
|
|
148
|
+
});
|
|
149
|
+
return formData;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 根据 val 获取对应的 options 项数据
|
|
154
|
+
* @param {string|number|boolean} val
|
|
155
|
+
* @param {Object} field
|
|
156
|
+
*/
|
|
157
|
+
export const getFieldOptItByVal = function (val, field, opt) {
|
|
158
|
+
if (!field) {
|
|
159
|
+
return {};
|
|
160
|
+
}
|
|
161
|
+
const options = Array.isArray(field.enum)
|
|
162
|
+
? field.enum
|
|
163
|
+
: Array.isArray(field.options)
|
|
164
|
+
? field.options
|
|
165
|
+
: field.dataSource || [];
|
|
166
|
+
return getOptItByVal(val, options, {
|
|
167
|
+
fieldNames: field.fieldNames || field["x-component-props"]?.fieldNames,
|
|
168
|
+
...opt,
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 根据 val 获取对应的 options 项数据,并进行数据归一化处理
|
|
174
|
+
* value, label, children
|
|
175
|
+
* @param {string|number|boolean} val
|
|
176
|
+
* @param {Object} field
|
|
177
|
+
*/
|
|
178
|
+
export const getOptItByVal = function (val, options, opt) {
|
|
179
|
+
const { fieldNames } = opt || {};
|
|
180
|
+
const { value = "value", label = "label", children = "children" } = fieldNames || {};
|
|
181
|
+
for (let i = 0; i < options.length; i++) {
|
|
182
|
+
const it = options[i];
|
|
183
|
+
if (it?.[value] === val) {
|
|
184
|
+
return {
|
|
185
|
+
...it,
|
|
186
|
+
value: it?.[value],
|
|
187
|
+
label: it?.[label],
|
|
188
|
+
children: it?.[children],
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// 递归处理
|
|
192
|
+
const _children = it?.[children];
|
|
193
|
+
if (Array.isArray(_children) && _children.length > 0) {
|
|
194
|
+
const child = getOptItByVal(val, _children, opt);
|
|
195
|
+
return {
|
|
196
|
+
...child,
|
|
197
|
+
value: child?.[value],
|
|
198
|
+
label: child?.[label],
|
|
199
|
+
children: child?.[children],
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 移除 schema.properties 中包含 "inTable": false 的字段
|
|
207
|
+
* @param {Object} data - 原始数据对象
|
|
208
|
+
* @returns {Object} - 处理后的新对象
|
|
209
|
+
*/
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 移除表格中标记为inTable:false的字段
|
|
213
|
+
* @param {Object} data - 原始数据
|
|
214
|
+
* @param {Object} [opt={}] - 配置选项
|
|
215
|
+
* @param {Array} [opt.boxList=[]] - 需要递归处理的组件类型列表
|
|
216
|
+
* @returns {Object} 处理后的数据
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
export function removeInTableFalseFields(_schema, opt = {}) {
|
|
220
|
+
// 1. 深拷贝原始数据
|
|
221
|
+
const result = cloneSchema(_schema);
|
|
222
|
+
|
|
223
|
+
// 2. 获取schema对象(支持直接传入schema或包含schema的对象)
|
|
224
|
+
const schema = result?.schema || result;
|
|
225
|
+
|
|
226
|
+
// 3. 处理容器组件配置
|
|
227
|
+
const { boxList = [] } = opt;
|
|
228
|
+
const _boxList =
|
|
229
|
+
boxList === false
|
|
230
|
+
? []
|
|
231
|
+
: [
|
|
232
|
+
"Card",
|
|
233
|
+
"FormGrid",
|
|
234
|
+
"ArrayCards",
|
|
235
|
+
"Collapse",
|
|
236
|
+
"Tabs",
|
|
237
|
+
"FormGrid.GridColumn",
|
|
238
|
+
...(Array.isArray(boxList) ? boxList : []),
|
|
239
|
+
];
|
|
240
|
+
|
|
241
|
+
// 4. 递归删除inTable:false的字段
|
|
242
|
+
const processProperties = (properties) => {
|
|
243
|
+
if (!properties || typeof properties !== "object") return;
|
|
244
|
+
|
|
245
|
+
Object.keys(properties).forEach((key) => {
|
|
246
|
+
const item = properties[key];
|
|
247
|
+
|
|
248
|
+
// 处理容器组件递归
|
|
249
|
+
if (item["x-component"] && _boxList.includes(item["x-component"])) {
|
|
250
|
+
if (item.properties) {
|
|
251
|
+
processProperties(item.properties);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// 处理数组类型的子项
|
|
255
|
+
else if (item.items?.properties) {
|
|
256
|
+
processProperties(item.items.properties);
|
|
257
|
+
}
|
|
258
|
+
// 处理普通字段
|
|
259
|
+
else if (item.inTable === false) {
|
|
260
|
+
delete properties[key];
|
|
261
|
+
}
|
|
262
|
+
// 移除x-display
|
|
263
|
+
else if (item["x-display"]) {
|
|
264
|
+
delete item["x-display"];
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
// 5. 处理主properties
|
|
270
|
+
if (schema.properties) {
|
|
271
|
+
processProperties(schema.properties);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// 6. 移除form的布局属性
|
|
275
|
+
if (result.form) {
|
|
276
|
+
delete result.form.labelCol;
|
|
277
|
+
delete result.form.wrapperCol;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
@@ -27,7 +27,7 @@ export interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
27
27
|
index: number;
|
|
28
28
|
editable: boolean;
|
|
29
29
|
onEdit: (record: Partial<Item> & { key: React.Key }, dataIndex: string, opt: Object) => void;
|
|
30
|
-
onSave: () => void;
|
|
30
|
+
onSave: (field: { type: string; name: string }) => void;
|
|
31
31
|
onCancel: () => void;
|
|
32
32
|
topProps: {
|
|
33
33
|
config: { hasEdit: boolean | Function };
|
|
@@ -100,7 +100,7 @@ export const EditableCell: React.FC<EditableCellProps> = ({
|
|
|
100
100
|
/>
|
|
101
101
|
{editMode !== "line" ? (
|
|
102
102
|
<div className="cell-editing-actions">
|
|
103
|
-
<CheckOutlined className="table-cell-confirm-icon" onClick={onSave} />
|
|
103
|
+
<CheckOutlined className="table-cell-confirm-icon" onClick={() => onSave(field)} />
|
|
104
104
|
<CloseOutlined className="table-cell-cancel-icon" onClick={onCancel} />
|
|
105
105
|
</div>
|
|
106
106
|
) : null}
|
|
@@ -195,13 +195,20 @@ export const useEditTable = (props) => {
|
|
|
195
195
|
const onEdit = async (record: Partial<Item> & { key: React.Key }, key, opt = { fieldRef: null }) => {
|
|
196
196
|
const { fieldRef } = opt || {};
|
|
197
197
|
editingFiledRef.current = fieldRef;
|
|
198
|
-
|
|
199
|
-
// const value = await (props.onEdit && props.onEdit(record));
|
|
200
198
|
formRender?.setValues(record);
|
|
201
199
|
setEditingId(record[idKey]);
|
|
202
200
|
setEditingKey(key);
|
|
203
201
|
};
|
|
204
202
|
|
|
203
|
+
/**
|
|
204
|
+
* 点击编辑按钮
|
|
205
|
+
* @param record
|
|
206
|
+
*/
|
|
207
|
+
const onEditAFetch = async (record: Partial<Item> & { key: React.Key }, ...args) => {
|
|
208
|
+
const value = await (props.onEdit && props.onEdit(record));
|
|
209
|
+
onEdit.call(this, value, ...args);
|
|
210
|
+
};
|
|
211
|
+
|
|
205
212
|
const onCancel = () => {
|
|
206
213
|
setEditingId("");
|
|
207
214
|
setEditingKey("");
|
|
@@ -211,11 +218,11 @@ export const useEditTable = (props) => {
|
|
|
211
218
|
/**
|
|
212
219
|
* 保存数据
|
|
213
220
|
*/
|
|
214
|
-
const onSave = async () => {
|
|
221
|
+
const onSave = async (field) => {
|
|
215
222
|
try {
|
|
216
223
|
// 点击保存,数据抛出
|
|
217
224
|
(await formRender?.validate()) as Item;
|
|
218
|
-
onEditSubmit && (await onEditSubmit(formRender.values));
|
|
225
|
+
onEditSubmit && (await onEditSubmit(formRender.values, { field } ));
|
|
219
226
|
// 清除编辑目标
|
|
220
227
|
setEditingId("");
|
|
221
228
|
setEditingKey("");
|
|
@@ -246,7 +253,7 @@ export const useEditTable = (props) => {
|
|
|
246
253
|
? isEditing(record) && isEditingCell(col.dataIndex)
|
|
247
254
|
: isEditing(record),
|
|
248
255
|
topProps: props.topProps,
|
|
249
|
-
onEdit,
|
|
256
|
+
onEdit: onEditAFetch,
|
|
250
257
|
onSave,
|
|
251
258
|
onCancel,
|
|
252
259
|
}),
|
|
@@ -274,6 +281,7 @@ export const useEditTable = (props) => {
|
|
|
274
281
|
});
|
|
275
282
|
|
|
276
283
|
return {
|
|
284
|
+
onEditAFetch,
|
|
277
285
|
onEdit,
|
|
278
286
|
SchemaField,
|
|
279
287
|
mergedColumns,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { memo,
|
|
1
|
+
import { memo, useMemo, useCallback } from "react";
|
|
2
2
|
import { createForm } from "@formily/core";
|
|
3
|
-
import {
|
|
3
|
+
import { antdComponents, customComponents } from "@hzab/form-render";
|
|
4
|
+
import { createSchemaField, useField, useFieldSchema, Schema } from "@formily/react";
|
|
4
5
|
import { Form } from "c-formily-antd";
|
|
5
|
-
import {
|
|
6
|
+
import { cloneSchema } from "@hzab/utils/src/formily/cloneSchema";
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
+
import { handleReaction } from "../../common/handleReactions";
|
|
8
9
|
|
|
9
10
|
type formilyFieldPropsT = {
|
|
10
11
|
schema: Schema;
|
|
@@ -19,6 +20,16 @@ type formilyFieldPropsT = {
|
|
|
19
20
|
export const FormilyField = memo(function (props: formilyFieldPropsT) {
|
|
20
21
|
const { schema, formilyRef, schemaScope, components, reactionOpts } = props;
|
|
21
22
|
const { fields, fieldSchemas } = formilyRef.current || {};
|
|
23
|
+
const _schema = useMemo(() => {
|
|
24
|
+
const schemaRmInTable = cloneSchema(schema);
|
|
25
|
+
// 去除 inTable = false 的字段
|
|
26
|
+
Object.keys(schemaRmInTable?.schema?.properties)?.forEach((key) => {
|
|
27
|
+
if (schemaRmInTable?.schema?.properties?.[key]?.inTable === false) {
|
|
28
|
+
delete schemaRmInTable?.schema?.properties?.[key];
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return schemaRmInTable;
|
|
32
|
+
}, [schema]);
|
|
22
33
|
const SchemaField = useCallback(
|
|
23
34
|
createSchemaField({
|
|
24
35
|
// @ts-ignore
|
|
@@ -60,7 +71,7 @@ export const FormilyField = memo(function (props: formilyFieldPropsT) {
|
|
|
60
71
|
style={{ display: "none", width: 0, height: 0, overflow: "hidden" }}
|
|
61
72
|
form={formRender}
|
|
62
73
|
>
|
|
63
|
-
<SchemaField schema={
|
|
74
|
+
<SchemaField schema={_schema}></SchemaField>
|
|
64
75
|
</Form>
|
|
65
76
|
);
|
|
66
77
|
});
|
package/src/list-render.jsx
CHANGED
|
@@ -70,7 +70,6 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
70
70
|
const [total, setTotal] = useState(0);
|
|
71
71
|
const [list, setList] = useState([]);
|
|
72
72
|
const [formState, setFormState] = useState("");
|
|
73
|
-
const [rowId, setRowId] = useState(0);
|
|
74
73
|
const [listLoading, setListLoading] = useState(false);
|
|
75
74
|
const formModalRef = useRef();
|
|
76
75
|
const detailModalRef = useRef();
|
|
@@ -329,14 +328,11 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
329
328
|
}
|
|
330
329
|
|
|
331
330
|
function handleDetail(data, id) {
|
|
332
|
-
setRowId(id);
|
|
333
331
|
let title = data[modalConf?.title?.detailKey] || modalConf?.title?.detailText || "详情";
|
|
334
332
|
detailModalRef.current.show(data, title);
|
|
335
333
|
}
|
|
336
334
|
|
|
337
335
|
function onEdit(row, idx) {
|
|
338
|
-
//编辑的时候提前存id和状态
|
|
339
|
-
setRowId(row[idKey]);
|
|
340
336
|
setFormState("edit");
|
|
341
337
|
|
|
342
338
|
if (props.fetchOnEdit !== false) {
|
|
@@ -367,24 +363,27 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
367
363
|
|
|
368
364
|
function handleEdit(data, id) {
|
|
369
365
|
const { editMode = "modal" } = props;
|
|
370
|
-
|
|
371
|
-
if (
|
|
366
|
+
// 整行编辑的模式下列表数据回填
|
|
367
|
+
if (editMode == "line") {
|
|
372
368
|
return tableRef.current.onEditByTable(data, id);
|
|
373
369
|
}
|
|
374
|
-
|
|
375
|
-
|
|
370
|
+
if (editMode === "modal") {
|
|
371
|
+
let title = data[modalConf?.title?.editKey] || modalConf?.title?.editText || "编辑";
|
|
372
|
+
formModalRef.current.show(data, title, "edit");
|
|
373
|
+
}
|
|
376
374
|
}
|
|
377
375
|
|
|
378
|
-
async function onEditSubmit(data) {
|
|
376
|
+
async function onEditSubmit(data, opt) {
|
|
379
377
|
let _data = data;
|
|
380
378
|
if (isPatchUpdate) {
|
|
381
379
|
if (model?.patchMap === "function") {
|
|
382
|
-
_data = model.patchMap(data);
|
|
380
|
+
_data = model.patchMap(data, opt);
|
|
383
381
|
}
|
|
384
382
|
} else if (typeof model?.updateMap === "function") {
|
|
385
|
-
_data = model.updateMap(data);
|
|
383
|
+
_data = model.updateMap(data, opt);
|
|
386
384
|
}
|
|
387
385
|
|
|
386
|
+
// 行内编辑确认前的校验
|
|
388
387
|
if (props.onEditReqVerify) {
|
|
389
388
|
await props.onEditReqVerify(_data);
|
|
390
389
|
}
|
|
@@ -394,7 +393,7 @@ const ListRender = forwardRef(function (props, parentRef) {
|
|
|
394
393
|
}
|
|
395
394
|
const request = isPatchUpdate ? model?.patch : model?.update;
|
|
396
395
|
return request
|
|
397
|
-
.bind(model)(_data, { id:
|
|
396
|
+
.bind(model)(_data, { id: data[idKey] })
|
|
398
397
|
.then((res) => {
|
|
399
398
|
getList();
|
|
400
399
|
message.success(res?._message || "编辑成功");
|
|
@@ -4,10 +4,10 @@ import dayjs from "dayjs";
|
|
|
4
4
|
import _ from "lodash";
|
|
5
5
|
|
|
6
6
|
import FormRender from "@hzab/form-render";
|
|
7
|
+
import { cloneSchema } from "@hzab/utils/src/formily/cloneSchema";
|
|
7
8
|
import { handleQuerySchema } from "../common/handleQuerySchema";
|
|
8
9
|
|
|
9
10
|
import "./index.less";
|
|
10
|
-
import { onFieldValueChange } from "@formily/core";
|
|
11
11
|
|
|
12
12
|
function QueryRender(props, parentRef) {
|
|
13
13
|
const [schema, setSchema] = useState({});
|
|
@@ -20,7 +20,7 @@ function QueryRender(props, parentRef) {
|
|
|
20
20
|
handleQuerySchema({
|
|
21
21
|
...props?.config,
|
|
22
22
|
schemaScope: { ...props.schemaScope, scenario: "query" },
|
|
23
|
-
schema:
|
|
23
|
+
schema: cloneSchema(props.schema),
|
|
24
24
|
search: props.search,
|
|
25
25
|
filters: _.cloneDeep(props.filters),
|
|
26
26
|
onSearch,
|
|
@@ -218,12 +218,12 @@ const TableRender = forwardRef(function (props, tableRef) {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
columns.push({
|
|
221
|
-
field,
|
|
221
|
+
// field, // title 传入 ReactNode,内部深克隆导致页面报错白屏
|
|
222
222
|
editable: true,
|
|
223
223
|
..._colConf,
|
|
224
224
|
onCell: (record, rowIndex) =>
|
|
225
225
|
_colConf?.onCell?.({ ...record, _field: { ...field, ...(fieldSchemas?.[name] || {}) } }, rowIndex) || {},
|
|
226
|
-
title: isFunction(_colConf?.title) ? _colConf?.title() : _title,
|
|
226
|
+
title: () => (isFunction(_colConf?.title) ? _colConf?.title() : _title),
|
|
227
227
|
key: name,
|
|
228
228
|
dataIndex: name,
|
|
229
229
|
render: getColRender(colRender),
|
|
@@ -283,10 +283,6 @@ const TableRender = forwardRef(function (props, tableRef) {
|
|
|
283
283
|
<Button
|
|
284
284
|
type="link"
|
|
285
285
|
onClick={() => {
|
|
286
|
-
// // 可编辑表格使用对应回调
|
|
287
|
-
// if (isEditTable) {
|
|
288
|
-
// return onEditByTable && onEditByTable(record, index);
|
|
289
|
-
// }
|
|
290
286
|
props.onEdit && props.onEdit(record, index);
|
|
291
287
|
}}
|
|
292
288
|
>
|
|
@@ -430,7 +426,7 @@ const TableRender = forwardRef(function (props, tableRef) {
|
|
|
430
426
|
<Table {...tableProps} />
|
|
431
427
|
)}
|
|
432
428
|
<FormilyField
|
|
433
|
-
schema={
|
|
429
|
+
schema={topProps.schema}
|
|
434
430
|
formilyRef={formilyRef}
|
|
435
431
|
components={props.components}
|
|
436
432
|
schemaScope={{
|