@hzab/form-render 1.6.17 → 1.6.19

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 (60) hide show
  1. package/CHANGELOG.md +291 -283
  2. package/README.md +239 -239
  3. package/package.json +57 -57
  4. package/src/common/formily-utils.ts +125 -125
  5. package/src/common/schema-handler.ts +253 -253
  6. package/src/common/schema-merge.ts +68 -68
  7. package/src/components/ArrayBase/index.tsx +349 -349
  8. package/src/components/ArrayBase/style.less +90 -90
  9. package/src/components/ArrayBase/style.ts +2 -2
  10. package/src/components/ArrayCards/index.tsx +149 -149
  11. package/src/components/ArrayCards/style.less +14 -14
  12. package/src/components/ArrayCards/style.ts +4 -4
  13. package/src/components/ArrayTable/index.tsx +411 -411
  14. package/src/components/ArrayTable/style.less +52 -52
  15. package/src/components/ArrayTable/style.ts +7 -7
  16. package/src/components/DatePicker/index.tsx +108 -108
  17. package/src/components/LocationListPicker/assets/icon.js +1 -1
  18. package/src/components/LocationListPicker/components/AddrList/index.less +55 -55
  19. package/src/components/LocationListPicker/components/AddrList/index.tsx +75 -75
  20. package/src/components/LocationListPicker/components/Popup/address.schema.json +21 -21
  21. package/src/components/LocationListPicker/components/Popup/index.less +22 -22
  22. package/src/components/LocationListPicker/components/Popup/index.tsx +92 -92
  23. package/src/components/LocationListPicker/index.less +34 -34
  24. package/src/components/LocationListPicker/index.tsx +521 -520
  25. package/src/components/LocationPicker/Map/AMap/common/loader.ts +58 -58
  26. package/src/components/LocationPicker/Map/AMap/common/utils.ts +431 -431
  27. package/src/components/LocationPicker/Map/AMap/index.jsx +51 -51
  28. package/src/components/LocationPicker/README.md +44 -44
  29. package/src/components/LocationPicker/common/utils.ts +30 -30
  30. package/src/components/LocationPicker/components/ModalContent/index.tsx +387 -387
  31. package/src/components/LocationPicker/components/PickerInfo/index.tsx +109 -109
  32. package/src/components/LocationPicker/components/ResInfo/index.less +38 -38
  33. package/src/components/LocationPicker/components/ResInfo/index.tsx +65 -65
  34. package/src/components/LocationPicker/index.tsx +197 -197
  35. package/src/components/PersonnelSelect/index.less +21 -21
  36. package/src/components/PersonnelSelect/index.module.less +33 -33
  37. package/src/components/PersonnelSelect/index.tsx +305 -300
  38. package/src/components/PersonnelSelect/type.ts +92 -92
  39. package/src/components/RichEditor/index.less +38 -38
  40. package/src/components/RichEditor/index.tsx +238 -238
  41. package/src/components/TreeCheckbox/components/CheckboxTable/index.tsx +55 -55
  42. package/src/components/TreeCheckbox/components/TabsRender/index.tsx +58 -58
  43. package/src/components/TreeCheckbox/index.less +12 -12
  44. package/src/components/TreeCheckbox/index.tsx +63 -63
  45. package/src/components/Upload/README.md +64 -64
  46. package/src/components/Upload/common/OfflineUpload.ts +339 -339
  47. package/src/components/Upload/common/customRequest.ts +81 -81
  48. package/src/components/Upload/common/fileName.ts +142 -142
  49. package/src/components/Upload/common/handleIOFileList.ts +393 -393
  50. package/src/components/Upload/common/nanoid.ts +7 -7
  51. package/src/components/Upload/common/ossUpload.js +159 -159
  52. package/src/components/Upload/common/utils.js +194 -194
  53. package/src/components/Upload/components/ItemList/index.tsx +52 -52
  54. package/src/components/Upload/components/PreviewModal/previewRender.tsx +80 -80
  55. package/src/components/Upload/index.tsx +17 -17
  56. package/src/components/Upload/uploader-input.jsx +187 -187
  57. package/src/components/Upload/uploader.jsx +316 -316
  58. package/src/components/UserSelect/index.tsx +123 -123
  59. package/src/components/index.tsx +17 -17
  60. package/src/index.tsx +198 -198
@@ -1,411 +1,411 @@
1
- import React, { Fragment, useState, useRef, useEffect, createContext, useContext, useCallback } from "react";
2
- import { Table, Pagination, Space, Select, Badge } from "antd";
3
- import { PaginationProps } from "antd/lib/pagination";
4
- import { TableProps, ColumnProps } from "antd/lib/table";
5
- import { SelectProps } from "antd/lib/select";
6
- import cls from "classnames";
7
- import { GeneralField, FieldDisplayTypes, ArrayField } from "@formily/core";
8
- import { useField, observer, useFieldSchema, RecursionField, ReactFC } from "@formily/react";
9
- import { isArr, isBool, isFn } from "@formily/shared";
10
- import { Schema } from "@formily/json-schema";
11
- import { usePrefixCls, SortableContainer, SortableElement } from "c-formily-antd/lib/__builtins__";
12
- import { ArrayBase, ArrayBaseMixins, IArrayBaseProps } from "../ArrayBase";
13
-
14
- interface ObservableColumnSource {
15
- field: GeneralField;
16
- columnProps: ColumnProps<any>;
17
- schema: Schema;
18
- display: FieldDisplayTypes;
19
- name: string;
20
- }
21
- interface IArrayTablePaginationProps extends PaginationProps {
22
- dataSource?: any[];
23
- showPagination?: boolean;
24
- children?: (
25
- dataSource: any[],
26
- pagination: React.ReactNode,
27
- options: {
28
- startIndex: number;
29
- },
30
- ) => React.ReactElement;
31
- }
32
-
33
- interface IStatusSelectProps extends SelectProps<any> {
34
- pageSize?: number;
35
- }
36
-
37
- type ComposedArrayTable = React.FC<React.PropsWithChildren<TableProps<any> & IArrayBaseProps>> &
38
- ArrayBaseMixins & {
39
- Column?: React.FC<React.PropsWithChildren<ColumnProps<any>>>;
40
- };
41
-
42
- interface PaginationAction {
43
- totalPage?: number;
44
- pageSize?: number;
45
- showPagination?: boolean;
46
- changePage?: (page: number) => void;
47
- }
48
-
49
- const SortableRow = SortableElement((props: any) => <tr {...props} />);
50
- const SortableBody = SortableContainer((props: any) => <tbody {...props} />);
51
-
52
- const isColumnComponent = (schema: Schema) => {
53
- return schema["x-component"]?.indexOf("Column") > -1;
54
- };
55
-
56
- const isOperationsComponent = (schema: Schema) => {
57
- return schema["x-component"]?.indexOf("Operations") > -1;
58
- };
59
-
60
- const isAdditionComponent = (schema: Schema) => {
61
- return schema["x-component"]?.indexOf("Addition") > -1;
62
- };
63
-
64
- const useArrayTableSources = () => {
65
- const arrayField = useField();
66
- const schema = useFieldSchema();
67
- const parseSources = (schema: Schema): ObservableColumnSource[] => {
68
- if (isColumnComponent(schema) || isOperationsComponent(schema) || isAdditionComponent(schema)) {
69
- if (!schema["x-component-props"]?.["dataIndex"] && !schema["name"]) return [];
70
- const name = schema["x-component-props"]?.["dataIndex"] || schema["name"];
71
- const field = arrayField.query(arrayField.address.concat(name)).take();
72
- const columnProps = field?.component?.[1] || schema["x-component-props"] || {};
73
- const display = field?.display || schema["x-display"] || "visible";
74
- return [
75
- {
76
- name,
77
- display,
78
- field,
79
- schema,
80
- columnProps,
81
- },
82
- ];
83
- } else if (schema.properties) {
84
- return schema.reduceProperties((buf, schema) => {
85
- return buf.concat(parseSources(schema));
86
- }, []);
87
- }
88
- };
89
-
90
- const parseArrayItems = (schema: Schema["items"]) => {
91
- if (!schema) return [];
92
- const sources: ObservableColumnSource[] = [];
93
- const items = isArr(schema) ? schema : [schema];
94
- return items.reduce((columns, schema) => {
95
- const item = parseSources(schema);
96
- if (item) {
97
- return columns.concat(item);
98
- }
99
- return columns;
100
- }, sources);
101
- };
102
-
103
- if (!schema) throw new Error("can not found schema object");
104
-
105
- return parseArrayItems(schema.items);
106
- };
107
-
108
- const useArrayTableColumns = (
109
- dataSource: any[],
110
- field: ArrayField,
111
- sources: ObservableColumnSource[],
112
- ): TableProps<any>["columns"] => {
113
- return sources.reduce((buf, { name, columnProps, schema, display }, key) => {
114
- if (display !== "visible") return buf;
115
- if (!isColumnComponent(schema)) return buf;
116
- return buf.concat({
117
- ...columnProps,
118
- key,
119
- dataIndex: name,
120
- render: (value: any, record: any) => {
121
- const index = dataSource?.indexOf(record);
122
- const children = (
123
- <ArrayBase.Item index={index} record={() => field?.value?.[index]}>
124
- <RecursionField schema={schema} name={index} onlyRenderProperties />
125
- </ArrayBase.Item>
126
- );
127
- return children;
128
- },
129
- });
130
- }, []);
131
- };
132
-
133
- const useAddition = () => {
134
- const schema = useFieldSchema();
135
- return schema.reduceProperties((addition, schema, key) => {
136
- if (isAdditionComponent(schema)) {
137
- return <RecursionField schema={schema} name={key} />;
138
- }
139
- return addition;
140
- }, null);
141
- };
142
-
143
- const schedulerRequest = {
144
- request: null,
145
- };
146
-
147
- const StatusSelect: ReactFC<IStatusSelectProps> = observer(
148
- (props) => {
149
- const field = useField<ArrayField>();
150
- const prefixCls = usePrefixCls("formily-array-table");
151
- const errors = field.errors;
152
- const parseIndex = (address: string) => {
153
- return Number(address.slice(address.indexOf(field.address.toString()) + 1).match(/(\d+)/)?.[1]);
154
- };
155
- const options = props.options?.map(({ label, value }) => {
156
- const val = Number(value);
157
- const hasError = errors.some(({ address }) => {
158
- const currentIndex = parseIndex(address);
159
- const startIndex = (val - 1) * props.pageSize;
160
- const endIndex = val * props.pageSize;
161
- return currentIndex >= startIndex && currentIndex <= endIndex;
162
- });
163
- return {
164
- label: hasError ? <Badge dot>{label}</Badge> : label,
165
- value,
166
- };
167
- });
168
-
169
- const width = String(options?.length).length * 15;
170
-
171
- return (
172
- <Select
173
- value={props.value}
174
- onChange={props.onChange}
175
- options={options}
176
- virtual
177
- style={{
178
- width: width < 60 ? 60 : width,
179
- }}
180
- className={cls(`${prefixCls}-status-select`, {
181
- "has-error": errors?.length,
182
- })}
183
- />
184
- );
185
- },
186
- {
187
- scheduler: (update) => {
188
- clearTimeout(schedulerRequest.request);
189
- schedulerRequest.request = setTimeout(() => {
190
- update();
191
- }, 100);
192
- },
193
- },
194
- );
195
-
196
- const PaginationContext = createContext<PaginationAction>({});
197
- const usePagination = () => {
198
- return useContext(PaginationContext);
199
- };
200
-
201
- const ArrayTablePagination: ReactFC<IArrayTablePaginationProps> = (props) => {
202
- const [current, setCurrent] = useState(1);
203
- const prefixCls = usePrefixCls("formily-array-table");
204
- const showPagination = props.showPagination ?? true;
205
- const pageSize = props.pageSize || 10;
206
- const size = props.size || "default";
207
- const dataSource = props.dataSource || [];
208
- const startIndex = (current - 1) * pageSize;
209
- const endIndex = startIndex + pageSize - 1;
210
- const total = dataSource?.length || 0;
211
- const totalPage = Math.ceil(total / pageSize);
212
- const pages = Array.from(new Array(totalPage)).map((_, index) => {
213
- const page = index + 1;
214
- return {
215
- label: page,
216
- value: page,
217
- };
218
- });
219
- const handleChange = (current: number) => {
220
- setCurrent(current);
221
- };
222
-
223
- useEffect(() => {
224
- if (totalPage > 0 && totalPage < current) {
225
- handleChange(totalPage);
226
- }
227
- }, [totalPage, current]);
228
-
229
- const renderPagination = () => {
230
- if (totalPage <= 1 || !showPagination) return;
231
- return (
232
- <div className={`${prefixCls}-pagination`}>
233
- <Space>
234
- <StatusSelect
235
- value={current}
236
- pageSize={pageSize}
237
- onChange={handleChange}
238
- options={pages}
239
- notFoundContent={false}
240
- />
241
- <Pagination
242
- {...props}
243
- pageSize={pageSize}
244
- current={current}
245
- total={dataSource.length}
246
- size={size}
247
- showSizeChanger={false}
248
- onChange={handleChange}
249
- />
250
- </Space>
251
- </div>
252
- );
253
- };
254
-
255
- return (
256
- <Fragment>
257
- <PaginationContext.Provider
258
- value={{
259
- totalPage,
260
- pageSize,
261
- changePage: handleChange,
262
- showPagination,
263
- }}
264
- >
265
- {props.children?.(
266
- showPagination ? dataSource?.slice(startIndex, endIndex + 1) : dataSource,
267
- renderPagination(),
268
- { startIndex },
269
- )}
270
- </PaginationContext.Provider>
271
- </Fragment>
272
- );
273
- };
274
-
275
- const RowComp: ReactFC<React.HTMLAttributes<HTMLTableRowElement>> = (props) => {
276
- const prefixCls = usePrefixCls("formily-array-table");
277
- const index = props["data-row-key"] || 0;
278
- return (
279
- <SortableRow
280
- lockAxis="y"
281
- {...props}
282
- index={index}
283
- className={cls(props.className, `${prefixCls}-row-${index + 1}`)}
284
- />
285
- );
286
- };
287
-
288
- export const ArrayTable: ComposedArrayTable = observer((props) => {
289
- const ref = useRef<HTMLDivElement>();
290
- const field = useField<ArrayField>();
291
- const prefixCls = usePrefixCls("formily-array-table");
292
- const dataSource = Array.isArray(field.value) ? field.value.slice() : [];
293
- const sources = useArrayTableSources();
294
- const columns = useArrayTableColumns(dataSource, field, sources);
295
- const pagination = isBool(props.pagination) ? { showPagination: props.pagination } : props.pagination;
296
- const addition = useAddition();
297
- const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp, deletePopconfirm, deletePopconfirmTitle } = props;
298
- const defaultRowKey = (record: any) => {
299
- return dataSource.indexOf(record);
300
- };
301
- const addTdStyles = (id: number) => {
302
- const node = ref.current?.querySelector(`.${prefixCls}-row-${id}`);
303
- const helper = document.body.querySelector(`.${prefixCls}-sort-helper`);
304
- if (!helper) return;
305
- const tds = node?.querySelectorAll("td");
306
- if (!tds) return;
307
- requestAnimationFrame(() => {
308
- helper.querySelectorAll("td").forEach((td, index) => {
309
- if (tds[index]) {
310
- td.style.width = getComputedStyle(tds[index]).width;
311
- }
312
- });
313
- });
314
- };
315
- const getWrapperComp = useCallback(
316
- (dataSource: any[], start: number) => (props: any) =>
317
- (
318
- <SortableBody
319
- {...props}
320
- start={start}
321
- list={dataSource.slice()}
322
- accessibility={{
323
- container: ref.current || undefined,
324
- }}
325
- onSortStart={(event) => {
326
- addTdStyles(event.active.id as number);
327
- }}
328
- onSortEnd={({ oldIndex, newIndex }) => {
329
- field.move(oldIndex, newIndex);
330
- }}
331
- className={cls(`${prefixCls}-sort-helper`, props.className)}
332
- />
333
- ),
334
- [field],
335
- );
336
-
337
- return (
338
- <ArrayTablePagination {...pagination} dataSource={dataSource}>
339
- {(dataSource, pager, { startIndex }) => (
340
- <div ref={ref} className={prefixCls}>
341
- <ArrayBase
342
- {...props}
343
- onAdd={onAdd}
344
- onCopy={onCopy}
345
- onRemove={onRemove}
346
- onMoveUp={onMoveUp}
347
- onMoveDown={onMoveDown}
348
- >
349
- <Table
350
- size="small"
351
- bordered
352
- rowKey={defaultRowKey}
353
- {...props}
354
- onChange={() => {}}
355
- pagination={false}
356
- columns={columns}
357
- dataSource={dataSource}
358
- components={{
359
- body: {
360
- wrapper: getWrapperComp(dataSource, startIndex),
361
- row: RowComp,
362
- },
363
- }}
364
- />
365
- <div style={{ marginTop: 5, marginBottom: 5 }}>{pager}</div>
366
- {sources.map((column, key) => {
367
- //专门用来承接对Column的状态管理
368
- if (!isColumnComponent(column.schema)) return;
369
- return React.createElement(RecursionField, {
370
- name: column.name,
371
- schema: column.schema,
372
- onlyRenderSelf: true,
373
- key,
374
- });
375
- })}
376
- {addition}
377
- </ArrayBase>
378
- </div>
379
- )}
380
- </ArrayTablePagination>
381
- );
382
- });
383
-
384
- ArrayTable.displayName = "ArrayTable";
385
-
386
- ArrayTable.Column = () => {
387
- return <Fragment />;
388
- };
389
-
390
- ArrayBase.mixin(ArrayTable);
391
-
392
- const Addition: ArrayBaseMixins["Addition"] = (props) => {
393
- const array = ArrayBase.useArray();
394
- const { totalPage = 0, pageSize = 10, changePage, showPagination } = usePagination();
395
- return (
396
- <ArrayBase.Addition
397
- {...props}
398
- onClick={(e) => {
399
- // 如果添加数据后将超过当前页,则自动切换到下一页
400
- const total = array?.field?.value?.length || 0;
401
- if (showPagination && total === totalPage * pageSize + 1 && isFn(changePage)) {
402
- changePage(totalPage + 1);
403
- }
404
- props.onClick?.(e);
405
- }}
406
- />
407
- );
408
- };
409
- ArrayTable.Addition = Addition;
410
-
411
- export default ArrayTable;
1
+ import React, { Fragment, useState, useRef, useEffect, createContext, useContext, useCallback } from "react";
2
+ import { Table, Pagination, Space, Select, Badge } from "antd";
3
+ import { PaginationProps } from "antd/lib/pagination";
4
+ import { TableProps, ColumnProps } from "antd/lib/table";
5
+ import { SelectProps } from "antd/lib/select";
6
+ import cls from "classnames";
7
+ import { GeneralField, FieldDisplayTypes, ArrayField } from "@formily/core";
8
+ import { useField, observer, useFieldSchema, RecursionField, ReactFC } from "@formily/react";
9
+ import { isArr, isBool, isFn } from "@formily/shared";
10
+ import { Schema } from "@formily/json-schema";
11
+ import { usePrefixCls, SortableContainer, SortableElement } from "c-formily-antd/lib/__builtins__";
12
+ import { ArrayBase, ArrayBaseMixins, IArrayBaseProps } from "../ArrayBase";
13
+
14
+ interface ObservableColumnSource {
15
+ field: GeneralField;
16
+ columnProps: ColumnProps<any>;
17
+ schema: Schema;
18
+ display: FieldDisplayTypes;
19
+ name: string;
20
+ }
21
+ interface IArrayTablePaginationProps extends PaginationProps {
22
+ dataSource?: any[];
23
+ showPagination?: boolean;
24
+ children?: (
25
+ dataSource: any[],
26
+ pagination: React.ReactNode,
27
+ options: {
28
+ startIndex: number;
29
+ },
30
+ ) => React.ReactElement;
31
+ }
32
+
33
+ interface IStatusSelectProps extends SelectProps<any> {
34
+ pageSize?: number;
35
+ }
36
+
37
+ type ComposedArrayTable = React.FC<React.PropsWithChildren<TableProps<any> & IArrayBaseProps>> &
38
+ ArrayBaseMixins & {
39
+ Column?: React.FC<React.PropsWithChildren<ColumnProps<any>>>;
40
+ };
41
+
42
+ interface PaginationAction {
43
+ totalPage?: number;
44
+ pageSize?: number;
45
+ showPagination?: boolean;
46
+ changePage?: (page: number) => void;
47
+ }
48
+
49
+ const SortableRow = SortableElement((props: any) => <tr {...props} />);
50
+ const SortableBody = SortableContainer((props: any) => <tbody {...props} />);
51
+
52
+ const isColumnComponent = (schema: Schema) => {
53
+ return schema["x-component"]?.indexOf("Column") > -1;
54
+ };
55
+
56
+ const isOperationsComponent = (schema: Schema) => {
57
+ return schema["x-component"]?.indexOf("Operations") > -1;
58
+ };
59
+
60
+ const isAdditionComponent = (schema: Schema) => {
61
+ return schema["x-component"]?.indexOf("Addition") > -1;
62
+ };
63
+
64
+ const useArrayTableSources = () => {
65
+ const arrayField = useField();
66
+ const schema = useFieldSchema();
67
+ const parseSources = (schema: Schema): ObservableColumnSource[] => {
68
+ if (isColumnComponent(schema) || isOperationsComponent(schema) || isAdditionComponent(schema)) {
69
+ if (!schema["x-component-props"]?.["dataIndex"] && !schema["name"]) return [];
70
+ const name = schema["x-component-props"]?.["dataIndex"] || schema["name"];
71
+ const field = arrayField.query(arrayField.address.concat(name)).take();
72
+ const columnProps = field?.component?.[1] || schema["x-component-props"] || {};
73
+ const display = field?.display || schema["x-display"] || "visible";
74
+ return [
75
+ {
76
+ name,
77
+ display,
78
+ field,
79
+ schema,
80
+ columnProps,
81
+ },
82
+ ];
83
+ } else if (schema.properties) {
84
+ return schema.reduceProperties((buf, schema) => {
85
+ return buf.concat(parseSources(schema));
86
+ }, []);
87
+ }
88
+ };
89
+
90
+ const parseArrayItems = (schema: Schema["items"]) => {
91
+ if (!schema) return [];
92
+ const sources: ObservableColumnSource[] = [];
93
+ const items = isArr(schema) ? schema : [schema];
94
+ return items.reduce((columns, schema) => {
95
+ const item = parseSources(schema);
96
+ if (item) {
97
+ return columns.concat(item);
98
+ }
99
+ return columns;
100
+ }, sources);
101
+ };
102
+
103
+ if (!schema) throw new Error("can not found schema object");
104
+
105
+ return parseArrayItems(schema.items);
106
+ };
107
+
108
+ const useArrayTableColumns = (
109
+ dataSource: any[],
110
+ field: ArrayField,
111
+ sources: ObservableColumnSource[],
112
+ ): TableProps<any>["columns"] => {
113
+ return sources.reduce((buf, { name, columnProps, schema, display }, key) => {
114
+ if (display !== "visible") return buf;
115
+ if (!isColumnComponent(schema)) return buf;
116
+ return buf.concat({
117
+ ...columnProps,
118
+ key,
119
+ dataIndex: name,
120
+ render: (value: any, record: any) => {
121
+ const index = dataSource?.indexOf(record);
122
+ const children = (
123
+ <ArrayBase.Item index={index} record={() => field?.value?.[index]}>
124
+ <RecursionField schema={schema} name={index} onlyRenderProperties />
125
+ </ArrayBase.Item>
126
+ );
127
+ return children;
128
+ },
129
+ });
130
+ }, []);
131
+ };
132
+
133
+ const useAddition = () => {
134
+ const schema = useFieldSchema();
135
+ return schema.reduceProperties((addition, schema, key) => {
136
+ if (isAdditionComponent(schema)) {
137
+ return <RecursionField schema={schema} name={key} />;
138
+ }
139
+ return addition;
140
+ }, null);
141
+ };
142
+
143
+ const schedulerRequest = {
144
+ request: null,
145
+ };
146
+
147
+ const StatusSelect: ReactFC<IStatusSelectProps> = observer(
148
+ (props) => {
149
+ const field = useField<ArrayField>();
150
+ const prefixCls = usePrefixCls("formily-array-table");
151
+ const errors = field.errors;
152
+ const parseIndex = (address: string) => {
153
+ return Number(address.slice(address.indexOf(field.address.toString()) + 1).match(/(\d+)/)?.[1]);
154
+ };
155
+ const options = props.options?.map(({ label, value }) => {
156
+ const val = Number(value);
157
+ const hasError = errors.some(({ address }) => {
158
+ const currentIndex = parseIndex(address);
159
+ const startIndex = (val - 1) * props.pageSize;
160
+ const endIndex = val * props.pageSize;
161
+ return currentIndex >= startIndex && currentIndex <= endIndex;
162
+ });
163
+ return {
164
+ label: hasError ? <Badge dot>{label}</Badge> : label,
165
+ value,
166
+ };
167
+ });
168
+
169
+ const width = String(options?.length).length * 15;
170
+
171
+ return (
172
+ <Select
173
+ value={props.value}
174
+ onChange={props.onChange}
175
+ options={options}
176
+ virtual
177
+ style={{
178
+ width: width < 60 ? 60 : width,
179
+ }}
180
+ className={cls(`${prefixCls}-status-select`, {
181
+ "has-error": errors?.length,
182
+ })}
183
+ />
184
+ );
185
+ },
186
+ {
187
+ scheduler: (update) => {
188
+ clearTimeout(schedulerRequest.request);
189
+ schedulerRequest.request = setTimeout(() => {
190
+ update();
191
+ }, 100);
192
+ },
193
+ },
194
+ );
195
+
196
+ const PaginationContext = createContext<PaginationAction>({});
197
+ const usePagination = () => {
198
+ return useContext(PaginationContext);
199
+ };
200
+
201
+ const ArrayTablePagination: ReactFC<IArrayTablePaginationProps> = (props) => {
202
+ const [current, setCurrent] = useState(1);
203
+ const prefixCls = usePrefixCls("formily-array-table");
204
+ const showPagination = props.showPagination ?? true;
205
+ const pageSize = props.pageSize || 10;
206
+ const size = props.size || "default";
207
+ const dataSource = props.dataSource || [];
208
+ const startIndex = (current - 1) * pageSize;
209
+ const endIndex = startIndex + pageSize - 1;
210
+ const total = dataSource?.length || 0;
211
+ const totalPage = Math.ceil(total / pageSize);
212
+ const pages = Array.from(new Array(totalPage)).map((_, index) => {
213
+ const page = index + 1;
214
+ return {
215
+ label: page,
216
+ value: page,
217
+ };
218
+ });
219
+ const handleChange = (current: number) => {
220
+ setCurrent(current);
221
+ };
222
+
223
+ useEffect(() => {
224
+ if (totalPage > 0 && totalPage < current) {
225
+ handleChange(totalPage);
226
+ }
227
+ }, [totalPage, current]);
228
+
229
+ const renderPagination = () => {
230
+ if (totalPage <= 1 || !showPagination) return;
231
+ return (
232
+ <div className={`${prefixCls}-pagination`}>
233
+ <Space>
234
+ <StatusSelect
235
+ value={current}
236
+ pageSize={pageSize}
237
+ onChange={handleChange}
238
+ options={pages}
239
+ notFoundContent={false}
240
+ />
241
+ <Pagination
242
+ {...props}
243
+ pageSize={pageSize}
244
+ current={current}
245
+ total={dataSource.length}
246
+ size={size}
247
+ showSizeChanger={false}
248
+ onChange={handleChange}
249
+ />
250
+ </Space>
251
+ </div>
252
+ );
253
+ };
254
+
255
+ return (
256
+ <Fragment>
257
+ <PaginationContext.Provider
258
+ value={{
259
+ totalPage,
260
+ pageSize,
261
+ changePage: handleChange,
262
+ showPagination,
263
+ }}
264
+ >
265
+ {props.children?.(
266
+ showPagination ? dataSource?.slice(startIndex, endIndex + 1) : dataSource,
267
+ renderPagination(),
268
+ { startIndex },
269
+ )}
270
+ </PaginationContext.Provider>
271
+ </Fragment>
272
+ );
273
+ };
274
+
275
+ const RowComp: ReactFC<React.HTMLAttributes<HTMLTableRowElement>> = (props) => {
276
+ const prefixCls = usePrefixCls("formily-array-table");
277
+ const index = props["data-row-key"] || 0;
278
+ return (
279
+ <SortableRow
280
+ lockAxis="y"
281
+ {...props}
282
+ index={index}
283
+ className={cls(props.className, `${prefixCls}-row-${index + 1}`)}
284
+ />
285
+ );
286
+ };
287
+
288
+ export const ArrayTable: ComposedArrayTable = observer((props) => {
289
+ const ref = useRef<HTMLDivElement>();
290
+ const field = useField<ArrayField>();
291
+ const prefixCls = usePrefixCls("formily-array-table");
292
+ const dataSource = Array.isArray(field.value) ? field.value.slice() : [];
293
+ const sources = useArrayTableSources();
294
+ const columns = useArrayTableColumns(dataSource, field, sources);
295
+ const pagination = isBool(props.pagination) ? { showPagination: props.pagination } : props.pagination;
296
+ const addition = useAddition();
297
+ const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp, deletePopconfirm, deletePopconfirmTitle } = props;
298
+ const defaultRowKey = (record: any) => {
299
+ return dataSource.indexOf(record);
300
+ };
301
+ const addTdStyles = (id: number) => {
302
+ const node = ref.current?.querySelector(`.${prefixCls}-row-${id}`);
303
+ const helper = document.body.querySelector(`.${prefixCls}-sort-helper`);
304
+ if (!helper) return;
305
+ const tds = node?.querySelectorAll("td");
306
+ if (!tds) return;
307
+ requestAnimationFrame(() => {
308
+ helper.querySelectorAll("td").forEach((td, index) => {
309
+ if (tds[index]) {
310
+ td.style.width = getComputedStyle(tds[index]).width;
311
+ }
312
+ });
313
+ });
314
+ };
315
+ const getWrapperComp = useCallback(
316
+ (dataSource: any[], start: number) => (props: any) =>
317
+ (
318
+ <SortableBody
319
+ {...props}
320
+ start={start}
321
+ list={dataSource.slice()}
322
+ accessibility={{
323
+ container: ref.current || undefined,
324
+ }}
325
+ onSortStart={(event) => {
326
+ addTdStyles(event.active.id as number);
327
+ }}
328
+ onSortEnd={({ oldIndex, newIndex }) => {
329
+ field.move(oldIndex, newIndex);
330
+ }}
331
+ className={cls(`${prefixCls}-sort-helper`, props.className)}
332
+ />
333
+ ),
334
+ [field],
335
+ );
336
+
337
+ return (
338
+ <ArrayTablePagination {...pagination} dataSource={dataSource}>
339
+ {(dataSource, pager, { startIndex }) => (
340
+ <div ref={ref} className={prefixCls}>
341
+ <ArrayBase
342
+ {...props}
343
+ onAdd={onAdd}
344
+ onCopy={onCopy}
345
+ onRemove={onRemove}
346
+ onMoveUp={onMoveUp}
347
+ onMoveDown={onMoveDown}
348
+ >
349
+ <Table
350
+ size="small"
351
+ bordered
352
+ rowKey={defaultRowKey}
353
+ {...props}
354
+ onChange={() => {}}
355
+ pagination={false}
356
+ columns={columns}
357
+ dataSource={dataSource}
358
+ components={{
359
+ body: {
360
+ wrapper: getWrapperComp(dataSource, startIndex),
361
+ row: RowComp,
362
+ },
363
+ }}
364
+ />
365
+ <div style={{ marginTop: 5, marginBottom: 5 }}>{pager}</div>
366
+ {sources.map((column, key) => {
367
+ //专门用来承接对Column的状态管理
368
+ if (!isColumnComponent(column.schema)) return;
369
+ return React.createElement(RecursionField, {
370
+ name: column.name,
371
+ schema: column.schema,
372
+ onlyRenderSelf: true,
373
+ key,
374
+ });
375
+ })}
376
+ {addition}
377
+ </ArrayBase>
378
+ </div>
379
+ )}
380
+ </ArrayTablePagination>
381
+ );
382
+ });
383
+
384
+ ArrayTable.displayName = "ArrayTable";
385
+
386
+ ArrayTable.Column = () => {
387
+ return <Fragment />;
388
+ };
389
+
390
+ ArrayBase.mixin(ArrayTable);
391
+
392
+ const Addition: ArrayBaseMixins["Addition"] = (props) => {
393
+ const array = ArrayBase.useArray();
394
+ const { totalPage = 0, pageSize = 10, changePage, showPagination } = usePagination();
395
+ return (
396
+ <ArrayBase.Addition
397
+ {...props}
398
+ onClick={(e) => {
399
+ // 如果添加数据后将超过当前页,则自动切换到下一页
400
+ const total = array?.field?.value?.length || 0;
401
+ if (showPagination && total === totalPage * pageSize + 1 && isFn(changePage)) {
402
+ changePage(totalPage + 1);
403
+ }
404
+ props.onClick?.(e);
405
+ }}
406
+ />
407
+ );
408
+ };
409
+ ArrayTable.Addition = Addition;
410
+
411
+ export default ArrayTable;