@hzab/form-render 1.5.0-beta2 → 1.5.0-beta4
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 +1 -0
- package/package.json +1 -1
- package/src/common/schema-handler.ts +4 -4
- package/src/components/LocationPicker/components/ModalContent/index.tsx +0 -1
- package/src/components/Upload/common/customRequest.ts +8 -2
- package/src/components/Upload/common/fileName.ts +11 -2
- package/src/components/Upload/common/handleIOFileList.ts +3 -0
- package/src/components/Upload/common/ossUpload.js +6 -0
- package/src/components/Upload/common/utils.js +17 -0
- package/src/components/Upload/uploader.jsx +6 -1
- package/src/components/index.tsx +0 -3
- package/src/index.tsx +6 -0
- package/src/components/ArrayBase/index.tsx +0 -315
- package/src/components/ArrayBase/style.less +0 -87
- package/src/components/ArrayBase/style.ts +0 -2
- package/src/components/ArrayCards/index.tsx +0 -151
- package/src/components/ArrayCards/style.less +0 -15
- package/src/components/ArrayCards/style.ts +0 -4
- package/src/components/ArrayTable/index.tsx +0 -405
- package/src/components/ArrayTable/style.less +0 -53
- package/src/components/ArrayTable/style.ts +0 -7
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
@@ -14,7 +14,7 @@ export const nanoid = customAlphabet(alphabet, 20);
|
|
14
14
|
*
|
15
15
|
* 2. `$form` is the current Form Model
|
16
16
|
*
|
17
|
-
* 3. `$deps` is the dependencies value
|
17
|
+
* 3. `$deps` is the dependencies value 仅在 run 中存在
|
18
18
|
*
|
19
19
|
* 4. `$observable` function is used to create an persistent observable state object
|
20
20
|
*
|
@@ -30,7 +30,7 @@ export const nanoid = customAlphabet(alphabet, 20);
|
|
30
30
|
**/
|
31
31
|
|
32
32
|
/** formily 执行函数作用域相关参数 */
|
33
|
-
export const formilyDataKeys = ["$form", "$self", "$observable", "$effect", "$memo", "$props", "$values"
|
33
|
+
export const formilyDataKeys = ["$form", "$self", "$observable", "$effect", "$memo", "$props", "$values"];
|
34
34
|
|
35
35
|
/** 自增容器 */
|
36
36
|
export const arrayList = ["ArrayTable", "ArrayCards"];
|
@@ -127,9 +127,9 @@ export const bindCallback = (opt) => {
|
|
127
127
|
}
|
128
128
|
// 设置一个唯一的函数名,用于从 schema scope 传入 formily 事件执行中
|
129
129
|
const fnKey = "fnKey_" + nanoid();
|
130
|
-
// 设置 schemaScope 中的唯一函数,获取执行函数作用域 $form, $self, $observable, $effect, $memo, $props, $values
|
130
|
+
// 设置 schemaScope 中的唯一函数,获取执行函数作用域 $form, $self, $observable, $effect, $memo, $props, $values 相关参数
|
131
131
|
schemaScope._$tempData[fnKey] = function (params, sourceArgs) {
|
132
|
-
const { $form, $self, $observable, $effect, $memo, $props, $values
|
132
|
+
const { $form, $self, $observable, $effect, $memo, $props, $values } = params;
|
133
133
|
// 处理结果数据,各组件返回数据格式不一致
|
134
134
|
const res = handleChangeValue({
|
135
135
|
...opt,
|
@@ -220,7 +220,6 @@ export const ModalContent = observer((props: any) => {
|
|
220
220
|
function onClickMap(ev) {
|
221
221
|
const { lng: evLon, lat: evLat } = ev.lnglat || {};
|
222
222
|
if (element === "Polypoint") {
|
223
|
-
console.log(evLon, evLat);
|
224
223
|
setPickPoint(evLon, evLat, { changeCenter: true });
|
225
224
|
}
|
226
225
|
}
|
@@ -3,8 +3,14 @@ import LUploadOss from "./ossUpload";
|
|
3
3
|
export const getOfflineUploadRequest = (props) => {
|
4
4
|
return ({ action, data, file, filename, headers, method, onSuccess, onProgress, onError }) => {
|
5
5
|
// TODO: 处理请求逻辑
|
6
|
-
|
7
|
-
|
6
|
+
file.ossPromise = new Promise((resolve) => {
|
7
|
+
resolve(file);
|
8
|
+
})
|
9
|
+
.then((file) => {
|
10
|
+
onSuccess(file);
|
11
|
+
return file;
|
12
|
+
})
|
13
|
+
.catch(onError);
|
8
14
|
};
|
9
15
|
};
|
10
16
|
|
@@ -7,6 +7,9 @@ import { nanoid } from "./nanoid";
|
|
7
7
|
* @returns
|
8
8
|
*/
|
9
9
|
export function getFileName(fileUrl) {
|
10
|
+
if (typeof fileUrl !== "string") {
|
11
|
+
return;
|
12
|
+
}
|
10
13
|
const res = fileUrl?.match(/([^\/]+?)\.[^\/\.]+$/);
|
11
14
|
if (res && res.length > 0) {
|
12
15
|
return res?.[1] || res?.[0];
|
@@ -21,6 +24,9 @@ export function getFileName(fileUrl) {
|
|
21
24
|
* @returns
|
22
25
|
*/
|
23
26
|
export function getFullFileName(fileUrl) {
|
27
|
+
if (typeof fileUrl !== "string") {
|
28
|
+
return;
|
29
|
+
}
|
24
30
|
const res = fileUrl?.match(/[^\/]+?\.[^\/\.]+$/);
|
25
31
|
if (res && res.length > 0) {
|
26
32
|
return res[0];
|
@@ -34,10 +40,13 @@ export function getFullFileName(fileUrl) {
|
|
34
40
|
* @param {*} str
|
35
41
|
* @returns
|
36
42
|
*/
|
37
|
-
export const mergeFileName = function (fileName, str) {
|
43
|
+
export const mergeFileName = function (fileName, str = "") {
|
44
|
+
if (typeof fileName !== "string") {
|
45
|
+
return "";
|
46
|
+
}
|
38
47
|
const name = fileName?.match(/([^\/]+?)\.[^\/]+$/)?.[1] || "";
|
39
48
|
const suffix = fileName?.match(/[^\/]+?\.([^\/]+)$/)?.[1] || "";
|
40
|
-
return `${name}${str}.${suffix}`;
|
49
|
+
return `${name}${str ?? ""}.${suffix}`;
|
41
50
|
};
|
42
51
|
|
43
52
|
/**
|
@@ -97,6 +97,9 @@ export const objStrToObj = function (objStr) {
|
|
97
97
|
* @returns
|
98
98
|
*/
|
99
99
|
export function mergePreviewConfig(uri, previewConfig) {
|
100
|
+
if (typeof uri !== "string") {
|
101
|
+
return uri;
|
102
|
+
}
|
100
103
|
let _uri = uri?.trim();
|
101
104
|
// base64 直接返回
|
102
105
|
if (isBase64Str(_uri)) {
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { axios } from "@hzab/data-model";
|
2
2
|
import { getFileNameByFileObj } from "./fileName";
|
3
|
+
import { formatDirStr, mergeDirStr } from "./utils";
|
3
4
|
|
4
5
|
export function getSignature(opt = {}) {
|
5
6
|
const { serverUrl = "/api/v1/user/oss/getWebOssConfig" } = opt;
|
@@ -12,6 +13,9 @@ export function getSignature(opt = {}) {
|
|
12
13
|
return Promise.resolve(window.__ossSignatureRes);
|
13
14
|
}
|
14
15
|
const { axios: _ax = axios, params = {}, axiosConf } = opt;
|
16
|
+
// 处理 dir 格式,必须为非 / 开头, / 结尾。如: test/
|
17
|
+
params.dir = formatDirStr(params.dir);
|
18
|
+
|
15
19
|
return _ax
|
16
20
|
.get(serverUrl, {
|
17
21
|
...axiosConf,
|
@@ -39,6 +43,8 @@ class OssUpload {
|
|
39
43
|
}
|
40
44
|
|
41
45
|
getSignature(serverUrl = this.serverUrl, opt) {
|
46
|
+
// dir 前缀 oss-upload 文件目录
|
47
|
+
opt.params.dir = mergeDirStr("web-upload/", opt.params.dir);
|
42
48
|
return getSignature({
|
43
49
|
...opt,
|
44
50
|
serverUrl,
|
@@ -1,5 +1,22 @@
|
|
1
1
|
import { nanoid } from "nanoid";
|
2
2
|
|
3
|
+
/**
|
4
|
+
* 格式化 dir 字符串,必须为非 / 开头, / 结尾。如: test/
|
5
|
+
* @param {*} dir
|
6
|
+
* @returns
|
7
|
+
*/
|
8
|
+
export const formatDirStr = function (dir) {
|
9
|
+
return dir?.replace(/^\/(.*)\/*$/, "$1").replace(/(.?=*)\/*$/, "$1/");
|
10
|
+
};
|
11
|
+
|
12
|
+
/**
|
13
|
+
* 合并 dir 字符串
|
14
|
+
* @param {*} dir
|
15
|
+
*/
|
16
|
+
export const mergeDirStr = function (dir1, dir2) {
|
17
|
+
return `${formatDirStr(dir1 || "")}${formatDirStr(dir2 || "")}`;
|
18
|
+
};
|
19
|
+
|
3
20
|
/**
|
4
21
|
* 建立一个可以存取该 file 的 url
|
5
22
|
* @param {Object} file 文件
|
@@ -102,7 +102,12 @@ export function Uploader({ onChange, ...props }) {
|
|
102
102
|
let _file = _files[i]?.originFileObj || _files[i];
|
103
103
|
if (!_file.url) {
|
104
104
|
_file.url = (await _file.ossPromise) || _file.ossUrl || typeof _file === "string" ? _file : "";
|
105
|
-
|
105
|
+
if (typeof _file.url === "string") {
|
106
|
+
_files[i].url = _file.url;
|
107
|
+
} else if (typeof _file?.url?.ossUrl === "string") {
|
108
|
+
_file.url = _file?.url?.ossUrl;
|
109
|
+
_files[i].url = _file?.url?.ossUrl;
|
110
|
+
}
|
106
111
|
}
|
107
112
|
}
|
108
113
|
|
package/src/components/index.tsx
CHANGED
package/src/index.tsx
CHANGED
@@ -26,6 +26,8 @@ import {
|
|
26
26
|
FormLayout,
|
27
27
|
FormTab,
|
28
28
|
FormCollapse,
|
29
|
+
ArrayTable,
|
30
|
+
ArrayCards,
|
29
31
|
} from "c-formily-antd";
|
30
32
|
import { Card, Slider, Rate } from "antd";
|
31
33
|
|
@@ -61,6 +63,8 @@ const antdComponents = {
|
|
61
63
|
FormLayout,
|
62
64
|
FormTab,
|
63
65
|
FormCollapse,
|
66
|
+
ArrayTable,
|
67
|
+
ArrayCards,
|
64
68
|
};
|
65
69
|
|
66
70
|
/** schema scope 解决父级无 schema Scope 导致 scope 对象刷新的问题 */
|
@@ -76,6 +80,8 @@ const FormRender = forwardRef((props: any, parentRef) => {
|
|
76
80
|
const SchemaField = useCallback(
|
77
81
|
createSchemaField({
|
78
82
|
components: {
|
83
|
+
ArrayTable,
|
84
|
+
ArrayCards,
|
79
85
|
Space,
|
80
86
|
FormGrid,
|
81
87
|
FormLayout,
|
@@ -1,315 +0,0 @@
|
|
1
|
-
import { CopyOutlined, DeleteOutlined, DownOutlined, MenuOutlined, PlusOutlined, UpOutlined } from "@ant-design/icons";
|
2
|
-
import { ArrayField } from "@formily/core";
|
3
|
-
import { JSXComponent, Schema, useField, useFieldSchema } from "@formily/react";
|
4
|
-
import { clone, isUndef, isValid } from "@formily/shared";
|
5
|
-
import { Button } from "antd";
|
6
|
-
import { ButtonProps } from "antd/lib/button";
|
7
|
-
import cls from "classnames";
|
8
|
-
import React, { createContext, useContext } from "react";
|
9
|
-
import { SortableHandle, usePrefixCls } from "c-formily-antd/lib/__builtins__";
|
10
|
-
|
11
|
-
export interface IArrayBaseAdditionProps extends ButtonProps {
|
12
|
-
title?: string;
|
13
|
-
method?: "push" | "unshift";
|
14
|
-
defaultValue?: any;
|
15
|
-
}
|
16
|
-
export interface IArrayBaseOperationProps extends ButtonProps {
|
17
|
-
title?: string;
|
18
|
-
index?: number;
|
19
|
-
ref?: React.Ref<HTMLElement>;
|
20
|
-
}
|
21
|
-
|
22
|
-
export interface IArrayBaseContext {
|
23
|
-
props: IArrayBaseProps;
|
24
|
-
field: ArrayField;
|
25
|
-
schema: Schema;
|
26
|
-
}
|
27
|
-
|
28
|
-
export interface IArrayBaseItemProps {
|
29
|
-
index: number;
|
30
|
-
record: ((index: number) => Record<string, any>) | Record<string, any>;
|
31
|
-
}
|
32
|
-
|
33
|
-
export type ArrayBaseMixins = {
|
34
|
-
Addition?: React.FC<React.PropsWithChildren<IArrayBaseAdditionProps>>;
|
35
|
-
Copy?: React.FC<React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>>;
|
36
|
-
Remove?: React.FC<React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>>;
|
37
|
-
MoveUp?: React.FC<React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>>;
|
38
|
-
MoveDown?: React.FC<React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>>;
|
39
|
-
SortHandle?: React.FC<React.PropsWithChildren<IArrayBaseOperationProps & { index?: number }>>;
|
40
|
-
Index?: React.FC;
|
41
|
-
useArray?: () => IArrayBaseContext;
|
42
|
-
useIndex?: (index?: number) => number;
|
43
|
-
useRecord?: (record?: number) => any;
|
44
|
-
};
|
45
|
-
|
46
|
-
export interface IArrayBaseProps {
|
47
|
-
disabled?: boolean;
|
48
|
-
onAdd?: (index: number) => void;
|
49
|
-
onCopy?: (index: number) => void;
|
50
|
-
onRemove?: (index: number) => void;
|
51
|
-
onMoveDown?: (index: number) => void;
|
52
|
-
onMoveUp?: (index: number) => void;
|
53
|
-
}
|
54
|
-
|
55
|
-
type ComposedArrayBase = React.FC<React.PropsWithChildren<IArrayBaseProps>> &
|
56
|
-
ArrayBaseMixins & {
|
57
|
-
Item?: React.FC<React.PropsWithChildren<IArrayBaseItemProps>>;
|
58
|
-
mixin?: <T extends JSXComponent>(target: T) => T & ArrayBaseMixins;
|
59
|
-
};
|
60
|
-
|
61
|
-
const ArrayBaseContext = createContext<IArrayBaseContext>(null);
|
62
|
-
|
63
|
-
const ItemContext = createContext<IArrayBaseItemProps>(null);
|
64
|
-
|
65
|
-
const takeRecord = (val: any, index?: number) => (typeof val === "function" ? val(index) : val);
|
66
|
-
|
67
|
-
const useArray = () => {
|
68
|
-
return useContext(ArrayBaseContext);
|
69
|
-
};
|
70
|
-
|
71
|
-
const useIndex = (index?: number) => {
|
72
|
-
const ctx = useContext(ItemContext);
|
73
|
-
return ctx ? ctx.index : index;
|
74
|
-
};
|
75
|
-
|
76
|
-
const useRecord = (record?: number) => {
|
77
|
-
const ctx = useContext(ItemContext);
|
78
|
-
return takeRecord(ctx ? ctx.record : record, ctx?.index);
|
79
|
-
};
|
80
|
-
|
81
|
-
const getSchemaDefaultValue = (schema: Schema) => {
|
82
|
-
if (schema?.type === "array") return [];
|
83
|
-
if (schema?.type === "object") return {};
|
84
|
-
if (schema?.type === "void") {
|
85
|
-
for (let key in schema.properties) {
|
86
|
-
const value = getSchemaDefaultValue(schema.properties[key]);
|
87
|
-
if (isValid(value)) return value;
|
88
|
-
}
|
89
|
-
}
|
90
|
-
};
|
91
|
-
|
92
|
-
const getDefaultValue = (defaultValue: any, schema: Schema) => {
|
93
|
-
if (isValid(defaultValue)) return clone(defaultValue);
|
94
|
-
if (Array.isArray(schema?.items)) return getSchemaDefaultValue(schema?.items[0]);
|
95
|
-
return getSchemaDefaultValue(schema?.items);
|
96
|
-
};
|
97
|
-
|
98
|
-
export const ArrayBase: ComposedArrayBase = (props) => {
|
99
|
-
const field = useField<ArrayField>();
|
100
|
-
const schema = useFieldSchema();
|
101
|
-
return <ArrayBaseContext.Provider value={{ field, schema, props }}>{props.children}</ArrayBaseContext.Provider>;
|
102
|
-
};
|
103
|
-
|
104
|
-
ArrayBase.Item = ({ children, ...props }) => {
|
105
|
-
return <ItemContext.Provider value={props}>{children}</ItemContext.Provider>;
|
106
|
-
};
|
107
|
-
|
108
|
-
const SortHandle = SortableHandle((props: any) => {
|
109
|
-
const prefixCls = usePrefixCls("formily-array-base");
|
110
|
-
return (
|
111
|
-
<MenuOutlined {...props} className={cls(`${prefixCls}-sort-handle`, props.className)} style={{ ...props.style }} />
|
112
|
-
);
|
113
|
-
}) as any;
|
114
|
-
|
115
|
-
ArrayBase.SortHandle = (props) => {
|
116
|
-
const array = useArray();
|
117
|
-
if (!array) return null;
|
118
|
-
if (array.field?.pattern !== "editable") return null;
|
119
|
-
return <SortHandle {...props} />;
|
120
|
-
};
|
121
|
-
|
122
|
-
ArrayBase.Index = (props) => {
|
123
|
-
const index = useIndex();
|
124
|
-
const prefixCls = usePrefixCls("formily-array-base");
|
125
|
-
return (
|
126
|
-
<span {...props} className={`${prefixCls}-index`}>
|
127
|
-
#{index + 1}.
|
128
|
-
</span>
|
129
|
-
);
|
130
|
-
};
|
131
|
-
|
132
|
-
ArrayBase.Addition = (props) => {
|
133
|
-
const self = useField();
|
134
|
-
const array = useArray();
|
135
|
-
const prefixCls = usePrefixCls("formily-array-base");
|
136
|
-
if (!array) return null;
|
137
|
-
if (array.field?.pattern !== "editable" && array.field?.pattern !== "disabled") return null;
|
138
|
-
return (
|
139
|
-
<Button
|
140
|
-
type="dashed"
|
141
|
-
block
|
142
|
-
{...props}
|
143
|
-
disabled={self?.disabled}
|
144
|
-
className={cls(`${prefixCls}-addition`, props.className)}
|
145
|
-
onClick={(e) => {
|
146
|
-
if (array.props?.disabled) return;
|
147
|
-
if (props.onClick) {
|
148
|
-
props.onClick(e);
|
149
|
-
if (e.defaultPrevented) return;
|
150
|
-
}
|
151
|
-
const defaultValue = getDefaultValue(props.defaultValue, array.schema);
|
152
|
-
if (props.method === "unshift") {
|
153
|
-
array.field?.unshift?.(defaultValue);
|
154
|
-
array.props?.onAdd?.(0);
|
155
|
-
} else {
|
156
|
-
array.field?.push?.(defaultValue);
|
157
|
-
array.props?.onAdd?.(array?.field?.value?.length - 1);
|
158
|
-
}
|
159
|
-
}}
|
160
|
-
icon={isUndef(props.icon) ? <PlusOutlined /> : props.icon}
|
161
|
-
>
|
162
|
-
{props.title || self.title}
|
163
|
-
</Button>
|
164
|
-
);
|
165
|
-
};
|
166
|
-
|
167
|
-
ArrayBase.Copy = React.forwardRef((props, ref) => {
|
168
|
-
const self = useField();
|
169
|
-
const array = useArray();
|
170
|
-
const index = useIndex(props.index);
|
171
|
-
const prefixCls = usePrefixCls("formily-array-base");
|
172
|
-
if (!array) return null;
|
173
|
-
if (array.field?.pattern !== "editable") return null;
|
174
|
-
return (
|
175
|
-
<Button
|
176
|
-
type="text"
|
177
|
-
{...props}
|
178
|
-
disabled={self?.disabled}
|
179
|
-
className={cls(`${prefixCls}-copy`, self?.disabled ? `${prefixCls}-copy-disabled` : "", props.className)}
|
180
|
-
ref={ref}
|
181
|
-
onClick={(e) => {
|
182
|
-
if (self?.disabled) return;
|
183
|
-
e.stopPropagation();
|
184
|
-
if (array.props?.disabled) return;
|
185
|
-
if (props.onClick) {
|
186
|
-
props.onClick(e);
|
187
|
-
if (e.defaultPrevented) return;
|
188
|
-
}
|
189
|
-
const value = clone(array?.field?.value[index]);
|
190
|
-
const distIndex = index + 1;
|
191
|
-
array.field?.insert?.(distIndex, value);
|
192
|
-
array.props?.onCopy?.(distIndex);
|
193
|
-
}}
|
194
|
-
icon={isUndef(props.icon) ? <CopyOutlined /> : props.icon}
|
195
|
-
>
|
196
|
-
{props.title || self.title}
|
197
|
-
</Button>
|
198
|
-
);
|
199
|
-
});
|
200
|
-
|
201
|
-
ArrayBase.Remove = React.forwardRef((props, ref) => {
|
202
|
-
const index = useIndex(props.index);
|
203
|
-
const self = useField();
|
204
|
-
const array = useArray();
|
205
|
-
const prefixCls = usePrefixCls("formily-array-base");
|
206
|
-
if (!array) return null;
|
207
|
-
if (array.field?.pattern !== "editable") return null;
|
208
|
-
return (
|
209
|
-
<Button
|
210
|
-
type="text"
|
211
|
-
{...props}
|
212
|
-
disabled={self?.disabled}
|
213
|
-
className={cls(`${prefixCls}-remove`, self?.disabled ? `${prefixCls}-remove-disabled` : "", props.className)}
|
214
|
-
ref={ref}
|
215
|
-
onClick={(e) => {
|
216
|
-
if (self?.disabled) return;
|
217
|
-
e.stopPropagation();
|
218
|
-
if (props.onClick) {
|
219
|
-
props.onClick(e);
|
220
|
-
if (e.defaultPrevented) return;
|
221
|
-
}
|
222
|
-
array.field?.remove?.(index);
|
223
|
-
array.props?.onRemove?.(index);
|
224
|
-
}}
|
225
|
-
icon={isUndef(props.icon) ? <DeleteOutlined /> : props.icon}
|
226
|
-
>
|
227
|
-
{props.title || self.title}
|
228
|
-
</Button>
|
229
|
-
);
|
230
|
-
});
|
231
|
-
|
232
|
-
ArrayBase.MoveDown = React.forwardRef((props, ref) => {
|
233
|
-
const index = useIndex(props.index);
|
234
|
-
const self = useField();
|
235
|
-
const array = useArray();
|
236
|
-
const prefixCls = usePrefixCls("formily-array-base");
|
237
|
-
if (!array) return null;
|
238
|
-
if (array.field?.pattern !== "editable") return null;
|
239
|
-
return (
|
240
|
-
<Button
|
241
|
-
type="text"
|
242
|
-
{...props}
|
243
|
-
disabled={self?.disabled}
|
244
|
-
className={cls(
|
245
|
-
`${prefixCls}-move-down`,
|
246
|
-
self?.disabled ? `${prefixCls}-move-down-disabled` : "",
|
247
|
-
props.className,
|
248
|
-
)}
|
249
|
-
ref={ref}
|
250
|
-
onClick={(e) => {
|
251
|
-
if (self?.disabled) return;
|
252
|
-
e.stopPropagation();
|
253
|
-
if (props.onClick) {
|
254
|
-
props.onClick(e);
|
255
|
-
if (e.defaultPrevented) return;
|
256
|
-
}
|
257
|
-
array.field?.moveDown?.(index);
|
258
|
-
array.props?.onMoveDown?.(index);
|
259
|
-
}}
|
260
|
-
icon={isUndef(props.icon) ? <DownOutlined /> : props.icon}
|
261
|
-
>
|
262
|
-
{props.title || self.title}
|
263
|
-
</Button>
|
264
|
-
);
|
265
|
-
});
|
266
|
-
|
267
|
-
ArrayBase.MoveUp = React.forwardRef((props, ref) => {
|
268
|
-
const index = useIndex(props.index);
|
269
|
-
const self = useField();
|
270
|
-
const array = useArray();
|
271
|
-
const prefixCls = usePrefixCls("formily-array-base");
|
272
|
-
if (!array) return null;
|
273
|
-
if (array.field?.pattern !== "editable") return null;
|
274
|
-
return (
|
275
|
-
<Button
|
276
|
-
type="text"
|
277
|
-
{...props}
|
278
|
-
disabled={self?.disabled}
|
279
|
-
className={cls(`${prefixCls}-move-up`, self?.disabled ? `${prefixCls}-move-up-disabled` : "", props.className)}
|
280
|
-
ref={ref}
|
281
|
-
onClick={(e) => {
|
282
|
-
if (self?.disabled) return;
|
283
|
-
e.stopPropagation();
|
284
|
-
if (props.onClick) {
|
285
|
-
props.onClick(e);
|
286
|
-
if (e.defaultPrevented) return;
|
287
|
-
}
|
288
|
-
array?.field?.moveUp(index);
|
289
|
-
array?.props?.onMoveUp?.(index);
|
290
|
-
}}
|
291
|
-
icon={isUndef(props.icon) ? <UpOutlined /> : props.icon}
|
292
|
-
>
|
293
|
-
{props.title || self.title}
|
294
|
-
</Button>
|
295
|
-
);
|
296
|
-
});
|
297
|
-
|
298
|
-
ArrayBase.useArray = useArray;
|
299
|
-
ArrayBase.useIndex = useIndex;
|
300
|
-
ArrayBase.useRecord = useRecord;
|
301
|
-
ArrayBase.mixin = (target: any) => {
|
302
|
-
target.Index = ArrayBase.Index;
|
303
|
-
target.SortHandle = ArrayBase.SortHandle;
|
304
|
-
target.Addition = ArrayBase.Addition;
|
305
|
-
target.Copy = ArrayBase.Copy;
|
306
|
-
target.Remove = ArrayBase.Remove;
|
307
|
-
target.MoveDown = ArrayBase.MoveDown;
|
308
|
-
target.MoveUp = ArrayBase.MoveUp;
|
309
|
-
target.useArray = ArrayBase.useArray;
|
310
|
-
target.useIndex = ArrayBase.useIndex;
|
311
|
-
target.useRecord = ArrayBase.useRecord;
|
312
|
-
return target;
|
313
|
-
};
|
314
|
-
|
315
|
-
export default ArrayBase;
|
@@ -1,87 +0,0 @@
|
|
1
|
-
@root-entry-name: 'default';
|
2
|
-
@import (reference) '~antd/es/style/themes/index.less';
|
3
|
-
|
4
|
-
@array-base-prefix-cls: ~'@{ant-prefix}-formily-array-base';
|
5
|
-
|
6
|
-
.@{array-base-prefix-cls}-remove,
|
7
|
-
.@{array-base-prefix-cls}-copy {
|
8
|
-
transition: all 0.25s ease-in-out;
|
9
|
-
color: @text-color;
|
10
|
-
font-size: 14px;
|
11
|
-
margin-left: 6px;
|
12
|
-
padding: 0;
|
13
|
-
border: none;
|
14
|
-
width: auto;
|
15
|
-
height: auto;
|
16
|
-
|
17
|
-
&:hover {
|
18
|
-
color: @primary-5;
|
19
|
-
}
|
20
|
-
|
21
|
-
&-disabled {
|
22
|
-
color: @disabled-color;
|
23
|
-
cursor: not-allowed !important;
|
24
|
-
&:hover {
|
25
|
-
color: @disabled-color;
|
26
|
-
}
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
.@{array-base-prefix-cls}-sort-handle {
|
31
|
-
cursor: move;
|
32
|
-
color: #888 !important;
|
33
|
-
// overrid iconfont.less .anticon[tabindex] cursor
|
34
|
-
&.anticon[tabindex] {
|
35
|
-
cursor: move;
|
36
|
-
}
|
37
|
-
}
|
38
|
-
|
39
|
-
.@{array-base-prefix-cls}-addition {
|
40
|
-
transition: all 0.25s ease-in-out;
|
41
|
-
}
|
42
|
-
|
43
|
-
.@{array-base-prefix-cls}-move-down {
|
44
|
-
transition: all 0.25s ease-in-out;
|
45
|
-
color: @text-color;
|
46
|
-
font-size: 14px;
|
47
|
-
margin-left: 6px;
|
48
|
-
padding: 0;
|
49
|
-
border: none;
|
50
|
-
width: auto;
|
51
|
-
height: auto;
|
52
|
-
|
53
|
-
&:hover {
|
54
|
-
color: @primary-5;
|
55
|
-
}
|
56
|
-
|
57
|
-
&-disabled {
|
58
|
-
color: @disabled-color;
|
59
|
-
cursor: not-allowed !important;
|
60
|
-
&:hover {
|
61
|
-
color: @disabled-color;
|
62
|
-
}
|
63
|
-
}
|
64
|
-
}
|
65
|
-
|
66
|
-
.@{array-base-prefix-cls}-move-up {
|
67
|
-
transition: all 0.25s ease-in-out;
|
68
|
-
color: @text-color;
|
69
|
-
font-size: 14px;
|
70
|
-
margin-left: 6px;
|
71
|
-
padding: 0;
|
72
|
-
border: none;
|
73
|
-
width: auto;
|
74
|
-
height: auto;
|
75
|
-
|
76
|
-
&:hover {
|
77
|
-
color: @primary-5;
|
78
|
-
}
|
79
|
-
|
80
|
-
&-disabled {
|
81
|
-
color: @disabled-color;
|
82
|
-
cursor: not-allowed !important;
|
83
|
-
&:hover {
|
84
|
-
color: @disabled-color;
|
85
|
-
}
|
86
|
-
}
|
87
|
-
}
|
@@ -1,151 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import { Card, Empty } from "antd";
|
3
|
-
import { CardProps } from "antd/lib/card";
|
4
|
-
import { ArrayField } from "@formily/core";
|
5
|
-
import { useField, observer, useFieldSchema, RecursionField } from "@formily/react";
|
6
|
-
import cls from "classnames";
|
7
|
-
import { ISchema } from "@formily/json-schema";
|
8
|
-
import { usePrefixCls } from "c-formily-antd/lib/__builtins__";
|
9
|
-
import { ArrayBase, ArrayBaseMixins, IArrayBaseProps } from "../ArrayBase";
|
10
|
-
|
11
|
-
type ComposedArrayCards = React.FC<React.PropsWithChildren<CardProps & IArrayBaseProps>> & ArrayBaseMixins;
|
12
|
-
|
13
|
-
const isAdditionComponent = (schema: ISchema) => {
|
14
|
-
return schema["x-component"]?.indexOf("Addition") > -1;
|
15
|
-
};
|
16
|
-
|
17
|
-
const isIndexComponent = (schema: ISchema) => {
|
18
|
-
return schema["x-component"]?.indexOf?.("Index") > -1;
|
19
|
-
};
|
20
|
-
|
21
|
-
const isRemoveComponent = (schema: ISchema) => {
|
22
|
-
return schema["x-component"]?.indexOf?.("Remove") > -1;
|
23
|
-
};
|
24
|
-
|
25
|
-
const isCopyComponent = (schema: ISchema) => {
|
26
|
-
return schema["x-component"]?.indexOf?.("Copy") > -1;
|
27
|
-
};
|
28
|
-
|
29
|
-
const isMoveUpComponent = (schema: ISchema) => {
|
30
|
-
return schema["x-component"]?.indexOf?.("MoveUp") > -1;
|
31
|
-
};
|
32
|
-
|
33
|
-
const isMoveDownComponent = (schema: ISchema) => {
|
34
|
-
return schema["x-component"]?.indexOf?.("MoveDown") > -1;
|
35
|
-
};
|
36
|
-
|
37
|
-
const isOperationComponent = (schema: ISchema) => {
|
38
|
-
return (
|
39
|
-
isAdditionComponent(schema) ||
|
40
|
-
isRemoveComponent(schema) ||
|
41
|
-
isCopyComponent(schema) ||
|
42
|
-
isMoveDownComponent(schema) ||
|
43
|
-
isMoveUpComponent(schema)
|
44
|
-
);
|
45
|
-
};
|
46
|
-
|
47
|
-
export const ArrayCards: ComposedArrayCards = observer((props) => {
|
48
|
-
const field = useField<ArrayField>();
|
49
|
-
const schema = useFieldSchema();
|
50
|
-
const dataSource = Array.isArray(field.value) ? field.value : [];
|
51
|
-
const prefixCls = usePrefixCls("formily-array-cards", props);
|
52
|
-
const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp, ...cardProps } = props;
|
53
|
-
|
54
|
-
if (!schema) throw new Error("can not found schema object");
|
55
|
-
|
56
|
-
const renderItems = () => {
|
57
|
-
return dataSource?.map((item, index) => {
|
58
|
-
const items = Array.isArray(schema.items) ? schema.items[index] || schema.items[0] : schema.items;
|
59
|
-
const title = (
|
60
|
-
<span>
|
61
|
-
<RecursionField
|
62
|
-
schema={items}
|
63
|
-
name={index}
|
64
|
-
filterProperties={(schema) => {
|
65
|
-
if (!isIndexComponent(schema)) return false;
|
66
|
-
return true;
|
67
|
-
}}
|
68
|
-
onlyRenderProperties
|
69
|
-
/>
|
70
|
-
{props.title || field.title}
|
71
|
-
</span>
|
72
|
-
);
|
73
|
-
const extra = (
|
74
|
-
<span>
|
75
|
-
<RecursionField
|
76
|
-
schema={items}
|
77
|
-
name={index}
|
78
|
-
filterProperties={(schema) => {
|
79
|
-
if (!isOperationComponent(schema)) return false;
|
80
|
-
return true;
|
81
|
-
}}
|
82
|
-
onlyRenderProperties
|
83
|
-
/>
|
84
|
-
{props.extra}
|
85
|
-
</span>
|
86
|
-
);
|
87
|
-
const content = (
|
88
|
-
<RecursionField
|
89
|
-
schema={items}
|
90
|
-
name={index}
|
91
|
-
filterProperties={(schema) => {
|
92
|
-
if (isIndexComponent(schema)) return false;
|
93
|
-
if (isOperationComponent(schema)) return false;
|
94
|
-
return true;
|
95
|
-
}}
|
96
|
-
/>
|
97
|
-
);
|
98
|
-
return (
|
99
|
-
// ! key 用于排序,必须是序号
|
100
|
-
<ArrayBase.Item key={index} index={index} record={() => field.value?.[index]}>
|
101
|
-
<Card
|
102
|
-
{...cardProps}
|
103
|
-
onChange={() => {}}
|
104
|
-
className={cls(`${prefixCls}-item`, props.className)}
|
105
|
-
title={title}
|
106
|
-
extra={extra}
|
107
|
-
>
|
108
|
-
{content}
|
109
|
-
</Card>
|
110
|
-
</ArrayBase.Item>
|
111
|
-
);
|
112
|
-
});
|
113
|
-
};
|
114
|
-
|
115
|
-
const renderAddition = () => {
|
116
|
-
return schema.reduceProperties((addition, schema, key) => {
|
117
|
-
if (isAdditionComponent(schema)) {
|
118
|
-
return <RecursionField schema={schema} name={key} />;
|
119
|
-
}
|
120
|
-
return addition;
|
121
|
-
}, null);
|
122
|
-
};
|
123
|
-
|
124
|
-
const renderEmpty = () => {
|
125
|
-
if (dataSource?.length) return;
|
126
|
-
return (
|
127
|
-
<Card
|
128
|
-
{...cardProps}
|
129
|
-
onChange={() => {}}
|
130
|
-
className={cls(`${prefixCls}-item`, props.className)}
|
131
|
-
title={props.title || field.title}
|
132
|
-
>
|
133
|
-
<Empty />
|
134
|
-
</Card>
|
135
|
-
);
|
136
|
-
};
|
137
|
-
|
138
|
-
return (
|
139
|
-
<ArrayBase onAdd={onAdd} onCopy={onCopy} onRemove={onRemove} onMoveUp={onMoveUp} onMoveDown={onMoveDown}>
|
140
|
-
{renderEmpty()}
|
141
|
-
{renderItems()}
|
142
|
-
{renderAddition()}
|
143
|
-
</ArrayBase>
|
144
|
-
);
|
145
|
-
});
|
146
|
-
|
147
|
-
ArrayCards.displayName = "ArrayCards";
|
148
|
-
|
149
|
-
ArrayBase.mixin(ArrayCards);
|
150
|
-
|
151
|
-
export default ArrayCards;
|
@@ -1,15 +0,0 @@
|
|
1
|
-
@root-entry-name: 'default';
|
2
|
-
@import (reference) '~antd/es/style/themes/index.less';
|
3
|
-
|
4
|
-
@array-base-prefix-cls: ~'@{ant-prefix}-formily-array-base';
|
5
|
-
@array-cards-prefix-cls: ~'@{ant-prefix}-formily-array-cards';
|
6
|
-
|
7
|
-
.@{array-cards-prefix-cls}-item {
|
8
|
-
margin-bottom: 10px !important;
|
9
|
-
}
|
10
|
-
|
11
|
-
.ant-card-extra {
|
12
|
-
.@{array-base-prefix-cls}-copy {
|
13
|
-
margin-left: 6px;
|
14
|
-
}
|
15
|
-
}
|
@@ -1,405 +0,0 @@
|
|
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
|
-
key,
|
120
|
-
dataIndex: name,
|
121
|
-
render: (value: any, record: any) => {
|
122
|
-
const index = dataSource?.indexOf(record);
|
123
|
-
const children = (
|
124
|
-
<ArrayBase.Item index={index} record={() => field?.value?.[index]}>
|
125
|
-
<RecursionField schema={schema} name={index} onlyRenderProperties />
|
126
|
-
</ArrayBase.Item>
|
127
|
-
);
|
128
|
-
return children;
|
129
|
-
},
|
130
|
-
});
|
131
|
-
}, []);
|
132
|
-
};
|
133
|
-
|
134
|
-
const useAddition = () => {
|
135
|
-
const schema = useFieldSchema();
|
136
|
-
return schema.reduceProperties((addition, schema, key) => {
|
137
|
-
if (isAdditionComponent(schema)) {
|
138
|
-
return <RecursionField schema={schema} name={key} />;
|
139
|
-
}
|
140
|
-
return addition;
|
141
|
-
}, null);
|
142
|
-
};
|
143
|
-
|
144
|
-
const schedulerRequest = {
|
145
|
-
request: null,
|
146
|
-
};
|
147
|
-
|
148
|
-
const StatusSelect: ReactFC<IStatusSelectProps> = observer(
|
149
|
-
(props) => {
|
150
|
-
const field = useField<ArrayField>();
|
151
|
-
const prefixCls = usePrefixCls("formily-array-table");
|
152
|
-
const errors = field.errors;
|
153
|
-
const parseIndex = (address: string) => {
|
154
|
-
return Number(address.slice(address.indexOf(field.address.toString()) + 1).match(/(\d+)/)?.[1]);
|
155
|
-
};
|
156
|
-
const options = props.options?.map(({ label, value }) => {
|
157
|
-
const val = Number(value);
|
158
|
-
const hasError = errors.some(({ address }) => {
|
159
|
-
const currentIndex = parseIndex(address);
|
160
|
-
const startIndex = (val - 1) * props.pageSize;
|
161
|
-
const endIndex = val * props.pageSize;
|
162
|
-
return currentIndex >= startIndex && currentIndex <= endIndex;
|
163
|
-
});
|
164
|
-
return {
|
165
|
-
label: hasError ? <Badge dot>{label}</Badge> : label,
|
166
|
-
value,
|
167
|
-
};
|
168
|
-
});
|
169
|
-
|
170
|
-
const width = String(options?.length).length * 15;
|
171
|
-
|
172
|
-
return (
|
173
|
-
<Select
|
174
|
-
value={props.value}
|
175
|
-
onChange={props.onChange}
|
176
|
-
options={options}
|
177
|
-
virtual
|
178
|
-
style={{
|
179
|
-
width: width < 60 ? 60 : width,
|
180
|
-
}}
|
181
|
-
className={cls(`${prefixCls}-status-select`, {
|
182
|
-
"has-error": errors?.length,
|
183
|
-
})}
|
184
|
-
/>
|
185
|
-
);
|
186
|
-
},
|
187
|
-
{
|
188
|
-
scheduler: (update) => {
|
189
|
-
clearTimeout(schedulerRequest.request);
|
190
|
-
schedulerRequest.request = setTimeout(() => {
|
191
|
-
update();
|
192
|
-
}, 100);
|
193
|
-
},
|
194
|
-
},
|
195
|
-
);
|
196
|
-
|
197
|
-
const PaginationContext = createContext<PaginationAction>({});
|
198
|
-
const usePagination = () => {
|
199
|
-
return useContext(PaginationContext);
|
200
|
-
};
|
201
|
-
|
202
|
-
const ArrayTablePagination: ReactFC<IArrayTablePaginationProps> = (props) => {
|
203
|
-
const [current, setCurrent] = useState(1);
|
204
|
-
const prefixCls = usePrefixCls("formily-array-table");
|
205
|
-
const showPagination = props.showPagination ?? true;
|
206
|
-
const pageSize = props.pageSize || 10;
|
207
|
-
const size = props.size || "default";
|
208
|
-
const dataSource = props.dataSource || [];
|
209
|
-
const startIndex = (current - 1) * pageSize;
|
210
|
-
const endIndex = startIndex + pageSize - 1;
|
211
|
-
const total = dataSource?.length || 0;
|
212
|
-
const totalPage = Math.ceil(total / pageSize);
|
213
|
-
const pages = Array.from(new Array(totalPage)).map((_, index) => {
|
214
|
-
const page = index + 1;
|
215
|
-
return {
|
216
|
-
label: page,
|
217
|
-
value: page,
|
218
|
-
};
|
219
|
-
});
|
220
|
-
const handleChange = (current: number) => {
|
221
|
-
setCurrent(current);
|
222
|
-
};
|
223
|
-
|
224
|
-
useEffect(() => {
|
225
|
-
if (totalPage > 0 && totalPage < current) {
|
226
|
-
handleChange(totalPage);
|
227
|
-
}
|
228
|
-
}, [totalPage, current]);
|
229
|
-
|
230
|
-
const renderPagination = () => {
|
231
|
-
if (totalPage <= 1 || !showPagination) return;
|
232
|
-
return (
|
233
|
-
<div className={`${prefixCls}-pagination`}>
|
234
|
-
<Space>
|
235
|
-
<StatusSelect
|
236
|
-
value={current}
|
237
|
-
pageSize={pageSize}
|
238
|
-
onChange={handleChange}
|
239
|
-
options={pages}
|
240
|
-
notFoundContent={false}
|
241
|
-
/>
|
242
|
-
<Pagination
|
243
|
-
{...props}
|
244
|
-
pageSize={pageSize}
|
245
|
-
current={current}
|
246
|
-
total={dataSource.length}
|
247
|
-
size={size}
|
248
|
-
showSizeChanger={false}
|
249
|
-
onChange={handleChange}
|
250
|
-
/>
|
251
|
-
</Space>
|
252
|
-
</div>
|
253
|
-
);
|
254
|
-
};
|
255
|
-
|
256
|
-
return (
|
257
|
-
<Fragment>
|
258
|
-
<PaginationContext.Provider
|
259
|
-
value={{
|
260
|
-
totalPage,
|
261
|
-
pageSize,
|
262
|
-
changePage: handleChange,
|
263
|
-
showPagination,
|
264
|
-
}}
|
265
|
-
>
|
266
|
-
{props.children?.(
|
267
|
-
showPagination ? dataSource?.slice(startIndex, endIndex + 1) : dataSource,
|
268
|
-
renderPagination(),
|
269
|
-
{ startIndex },
|
270
|
-
)}
|
271
|
-
</PaginationContext.Provider>
|
272
|
-
</Fragment>
|
273
|
-
);
|
274
|
-
};
|
275
|
-
|
276
|
-
const RowComp: ReactFC<React.HTMLAttributes<HTMLTableRowElement>> = (props) => {
|
277
|
-
const prefixCls = usePrefixCls("formily-array-table");
|
278
|
-
const index = props["data-row-key"] || 0;
|
279
|
-
return (
|
280
|
-
<SortableRow
|
281
|
-
lockAxis="y"
|
282
|
-
{...props}
|
283
|
-
index={index}
|
284
|
-
className={cls(props.className, `${prefixCls}-row-${index + 1}`)}
|
285
|
-
/>
|
286
|
-
);
|
287
|
-
};
|
288
|
-
|
289
|
-
export const ArrayTable: ComposedArrayTable = observer((props) => {
|
290
|
-
const ref = useRef<HTMLDivElement>();
|
291
|
-
const field = useField<ArrayField>();
|
292
|
-
const prefixCls = usePrefixCls("formily-array-table");
|
293
|
-
const dataSource = Array.isArray(field.value) ? field.value.slice() : [];
|
294
|
-
const sources = useArrayTableSources();
|
295
|
-
const columns = useArrayTableColumns(dataSource, field, sources);
|
296
|
-
const pagination = isBool(props.pagination) ? { showPagination: props.pagination } : props.pagination;
|
297
|
-
const addition = useAddition();
|
298
|
-
const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp } = props;
|
299
|
-
const defaultRowKey = (record: any) => {
|
300
|
-
return dataSource.indexOf(record);
|
301
|
-
};
|
302
|
-
const addTdStyles = (id: number) => {
|
303
|
-
const node = ref.current?.querySelector(`.${prefixCls}-row-${id}`);
|
304
|
-
const helper = document.body.querySelector(`.${prefixCls}-sort-helper`);
|
305
|
-
if (!helper) return;
|
306
|
-
const tds = node?.querySelectorAll("td");
|
307
|
-
if (!tds) return;
|
308
|
-
requestAnimationFrame(() => {
|
309
|
-
helper.querySelectorAll("td").forEach((td, index) => {
|
310
|
-
if (tds[index]) {
|
311
|
-
td.style.width = getComputedStyle(tds[index]).width;
|
312
|
-
}
|
313
|
-
});
|
314
|
-
});
|
315
|
-
};
|
316
|
-
const getWrapperComp = useCallback(
|
317
|
-
(dataSource: any[], start: number) => (props: any) =>
|
318
|
-
(
|
319
|
-
<SortableBody
|
320
|
-
{...props}
|
321
|
-
start={start}
|
322
|
-
list={dataSource.slice()}
|
323
|
-
accessibility={{
|
324
|
-
container: ref.current || undefined,
|
325
|
-
}}
|
326
|
-
onSortStart={(event) => {
|
327
|
-
addTdStyles(event.active.id as number);
|
328
|
-
}}
|
329
|
-
onSortEnd={({ oldIndex, newIndex }) => {
|
330
|
-
field.move(oldIndex, newIndex);
|
331
|
-
}}
|
332
|
-
className={cls(`${prefixCls}-sort-helper`, props.className)}
|
333
|
-
/>
|
334
|
-
),
|
335
|
-
[field],
|
336
|
-
);
|
337
|
-
return (
|
338
|
-
<ArrayTablePagination {...pagination} dataSource={dataSource}>
|
339
|
-
{(dataSource, pager, { startIndex }) => (
|
340
|
-
<div ref={ref} className={prefixCls}>
|
341
|
-
<ArrayBase onAdd={onAdd} onCopy={onCopy} onRemove={onRemove} onMoveUp={onMoveUp} onMoveDown={onMoveDown}>
|
342
|
-
<Table
|
343
|
-
size="small"
|
344
|
-
bordered
|
345
|
-
rowKey={defaultRowKey}
|
346
|
-
{...props}
|
347
|
-
onChange={() => {}}
|
348
|
-
pagination={false}
|
349
|
-
columns={columns}
|
350
|
-
dataSource={dataSource}
|
351
|
-
components={{
|
352
|
-
body: {
|
353
|
-
wrapper: getWrapperComp(dataSource, startIndex),
|
354
|
-
row: RowComp,
|
355
|
-
},
|
356
|
-
}}
|
357
|
-
/>
|
358
|
-
<div style={{ marginTop: 5, marginBottom: 5 }}>{pager}</div>
|
359
|
-
{sources.map((column, key) => {
|
360
|
-
//专门用来承接对Column的状态管理
|
361
|
-
if (!isColumnComponent(column.schema)) return;
|
362
|
-
return React.createElement(RecursionField, {
|
363
|
-
name: column.name,
|
364
|
-
schema: column.schema,
|
365
|
-
onlyRenderSelf: true,
|
366
|
-
// ! key 用于排序,必须是序号
|
367
|
-
key,
|
368
|
-
});
|
369
|
-
})}
|
370
|
-
{addition}
|
371
|
-
</ArrayBase>
|
372
|
-
</div>
|
373
|
-
)}
|
374
|
-
</ArrayTablePagination>
|
375
|
-
);
|
376
|
-
});
|
377
|
-
|
378
|
-
ArrayTable.displayName = "ArrayTable";
|
379
|
-
|
380
|
-
ArrayTable.Column = () => {
|
381
|
-
return <Fragment />;
|
382
|
-
};
|
383
|
-
|
384
|
-
ArrayBase.mixin(ArrayTable);
|
385
|
-
|
386
|
-
const Addition: ArrayBaseMixins["Addition"] = (props) => {
|
387
|
-
const array = ArrayBase.useArray();
|
388
|
-
const { totalPage = 0, pageSize = 10, changePage, showPagination } = usePagination();
|
389
|
-
return (
|
390
|
-
<ArrayBase.Addition
|
391
|
-
{...props}
|
392
|
-
onClick={(e) => {
|
393
|
-
// 如果添加数据后将超过当前页,则自动切换到下一页
|
394
|
-
const total = array?.field?.value.length || 0;
|
395
|
-
if (showPagination && total === totalPage * pageSize + 1 && isFn(changePage)) {
|
396
|
-
changePage(totalPage + 1);
|
397
|
-
}
|
398
|
-
props.onClick?.(e);
|
399
|
-
}}
|
400
|
-
/>
|
401
|
-
);
|
402
|
-
};
|
403
|
-
ArrayTable.Addition = Addition;
|
404
|
-
|
405
|
-
export default ArrayTable;
|
@@ -1,53 +0,0 @@
|
|
1
|
-
@root-entry-name: 'default';
|
2
|
-
@import (reference) '~antd/es/style/themes/index.less';
|
3
|
-
|
4
|
-
@array-table-prefix-cls: ~'@{ant-prefix}-formily-array-table';
|
5
|
-
|
6
|
-
.@{array-table-prefix-cls} {
|
7
|
-
.@{array-table-prefix-cls}-pagination {
|
8
|
-
display: flex;
|
9
|
-
justify-content: center;
|
10
|
-
|
11
|
-
.@{array-table-prefix-cls}-status-select.has-error {
|
12
|
-
.@{ant-prefix}-select-selector {
|
13
|
-
border-color: @error-color !important;
|
14
|
-
}
|
15
|
-
}
|
16
|
-
}
|
17
|
-
|
18
|
-
.@{ant-prefix}-table {
|
19
|
-
table {
|
20
|
-
overflow: hidden;
|
21
|
-
}
|
22
|
-
|
23
|
-
td {
|
24
|
-
visibility: visible;
|
25
|
-
|
26
|
-
.@{ant-prefix}-formily-item:not(.@{ant-prefix}-formily-item-feedback-layout-popover) {
|
27
|
-
margin-bottom: 0 !important;
|
28
|
-
|
29
|
-
.@{ant-prefix}-formily-item-help {
|
30
|
-
position: absolute;
|
31
|
-
font-size: 12px;
|
32
|
-
top: 100%;
|
33
|
-
background: #fff;
|
34
|
-
width: 100%;
|
35
|
-
margin-top: 3px;
|
36
|
-
padding: 3px;
|
37
|
-
z-index: 1;
|
38
|
-
border-radius: 3px;
|
39
|
-
box-shadow: 0 0 10px #eee;
|
40
|
-
animation: none;
|
41
|
-
transform: translateY(0);
|
42
|
-
opacity: 1;
|
43
|
-
}
|
44
|
-
}
|
45
|
-
}
|
46
|
-
}
|
47
|
-
|
48
|
-
.@{array-table-prefix-cls}-sort-helper {
|
49
|
-
background: #fff;
|
50
|
-
border: 1px solid #eee;
|
51
|
-
z-index: 10;
|
52
|
-
}
|
53
|
-
}
|