@hzab/form-render 1.4.1-beta → 1.5.0-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 +3 -2
- package/package.json +1 -1
- package/src/common/schema-handler.ts +84 -29
- package/src/components/ArrayBase/index.tsx +315 -0
- package/src/components/ArrayBase/style.less +87 -0
- package/src/components/ArrayBase/style.ts +2 -0
- package/src/components/ArrayCards/index.tsx +11 -18
- package/src/components/ArrayTable/index.tsx +6 -14
- package/src/components/DatePicker/index.tsx +1 -2
- package/src/components/Upload/README.md +28 -20
- package/src/components/Upload/common/customRequest.ts +34 -0
- package/src/components/Upload/common/fileName.ts +62 -0
- package/src/components/Upload/common/handleIOFileList.ts +302 -0
- package/src/components/Upload/common/nanoid.ts +7 -0
- package/src/components/Upload/common/ossUpload.js +9 -13
- package/src/components/Upload/common/utils.js +29 -13
- package/src/components/Upload/components/ItemList/index.tsx +2 -3
- package/src/components/Upload/components/PreviewModal/index.tsx +0 -1
- package/src/components/Upload/uploader-input.jsx +48 -12
- package/src/components/Upload/uploader.jsx +88 -83
- package/src/components/index.tsx +1 -0
- package/src/index.tsx +11 -8
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
import _ from "lodash";
|
2
|
+
import { customAlphabet } from "nanoid";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* 指定 nanoid 字符集合
|
6
|
+
*/
|
7
|
+
export const alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
8
|
+
export const nanoid = customAlphabet(alphabet, 20);
|
9
|
+
|
10
|
+
/** formily 执行函数作用域相关参数 */
|
11
|
+
export const formilyDataKeys = ["$form", "$self", "$observable", "$effect", "$memo", "$props", "$values"];
|
2
12
|
|
3
13
|
/** 自增容器 */
|
4
14
|
export const arrayList = ["ArrayTable", "ArrayCards"];
|
@@ -29,8 +39,8 @@ export const bindOnChange = (schema, opt) => {
|
|
29
39
|
const comProps = item?.["x-component-props"];
|
30
40
|
if (!comProps) {
|
31
41
|
item["x-component-props"] = {};
|
32
|
-
} else if (isScopeKey(comProps)) {
|
33
|
-
item["x-component-props"] =
|
42
|
+
} else if (isScopeKey(comProps, schemaScope)) {
|
43
|
+
item["x-component-props"] = getScopeKeyVal(comProps, schemaScope) || {};
|
34
44
|
}
|
35
45
|
|
36
46
|
const bindParams = {
|
@@ -90,16 +100,24 @@ export const bindOnChange = (schema, opt) => {
|
|
90
100
|
export const bindCallback = (opt) => {
|
91
101
|
const { target, actionName, schemaScope, formOnChange } = opt || {};
|
92
102
|
const tempFn = target[actionName];
|
93
|
-
|
103
|
+
if (!schemaScope._$tempData) {
|
104
|
+
schemaScope._$tempData = {};
|
105
|
+
}
|
106
|
+
// 设置一个唯一的函数名,用于从 schema scope 传入 formily 事件执行中
|
107
|
+
const fnKey = "fnKey_" + nanoid();
|
108
|
+
// 设置 schemaScope 中的唯一函数,获取执行函数作用域 $form, $self, $observable, $effect, $memo, $props, $values 相关参数
|
109
|
+
schemaScope._$tempData[fnKey] = function (params, sourceArgs) {
|
110
|
+
const { $form, $self, $observable, $effect, $memo, $props, $values } = params;
|
94
111
|
// 处理结果数据,各组件返回数据格式不一致
|
95
112
|
const res = handleChangeValue({
|
96
113
|
...opt,
|
97
114
|
sourceArgs,
|
98
115
|
});
|
99
116
|
// 触发组件 onChange 事件
|
100
|
-
if (
|
117
|
+
if (isRunStr(tempFn)) {
|
101
118
|
// schemaScope 传入方式
|
102
|
-
const fn =
|
119
|
+
const fn = handleSchemaStrVal(tempFn, { ...params, ...schemaScope });
|
120
|
+
|
103
121
|
typeof fn === "function" && fn(...sourceArgs, res);
|
104
122
|
} else if (typeof tempFn === "function") {
|
105
123
|
// 直接传入函数的方式
|
@@ -107,6 +125,17 @@ export const bindCallback = (opt) => {
|
|
107
125
|
}
|
108
126
|
formOnChange && formOnChange(res);
|
109
127
|
};
|
128
|
+
|
129
|
+
// 通过 formily 字符串执行的方式回去函数作用域参数
|
130
|
+
target[actionName] = `{{
|
131
|
+
function t() {
|
132
|
+
// 执行 ${fnKey} 唯一函数,formily 当前函数作用域相关参数
|
133
|
+
return _$tempData && _$tempData.${fnKey} && _$tempData.${fnKey}(
|
134
|
+
{ ${formilyDataKeys.join(", ")} },
|
135
|
+
arguments
|
136
|
+
);
|
137
|
+
}
|
138
|
+
}}`;
|
110
139
|
};
|
111
140
|
|
112
141
|
/**
|
@@ -114,8 +143,7 @@ export const bindCallback = (opt) => {
|
|
114
143
|
* @param args
|
115
144
|
*/
|
116
145
|
export const handleChangeValue = (opt) => {
|
117
|
-
const {
|
118
|
-
console.log("parent", parent);
|
146
|
+
const { formRender, targetKey, actionName, sourceArgs } = opt || {};
|
119
147
|
// 自增表格、卡片无法获知当前编辑内容所在的索引,导致无法知道当前值
|
120
148
|
const res = {
|
121
149
|
key: targetKey,
|
@@ -123,26 +151,16 @@ export const handleChangeValue = (opt) => {
|
|
123
151
|
formRender,
|
124
152
|
formValues: formRender.values,
|
125
153
|
sourceArgs: sourceArgs,
|
126
|
-
// value: formRender.getValuesIn(targetKey),
|
127
|
-
// parent,
|
128
|
-
// TODO: 自增情况下无法获知索引
|
129
|
-
// parentValue: formRender.getValuesIn(parent?.name),
|
130
154
|
};
|
131
155
|
|
132
|
-
// TODO: 自增返回父级值?
|
133
|
-
// if (returnParentValue.includes(parent?.["x-component"])) {
|
134
|
-
// res.value = res.parentValue;
|
135
|
-
// }
|
136
|
-
|
137
156
|
return res;
|
138
157
|
};
|
139
158
|
|
140
159
|
/**
|
141
|
-
*
|
142
|
-
* @param
|
143
|
-
* @returns
|
160
|
+
* 是否是可执行字符串,为 {{}} 包裹的字符串
|
161
|
+
* @param params
|
144
162
|
*/
|
145
|
-
export const
|
163
|
+
export const isRunStr = (strKey) => {
|
146
164
|
if (typeof strKey !== "string") {
|
147
165
|
return false;
|
148
166
|
}
|
@@ -151,12 +169,12 @@ export const isScopeKey = (strKey) => {
|
|
151
169
|
};
|
152
170
|
|
153
171
|
/**
|
154
|
-
*
|
155
|
-
* @param
|
156
|
-
* @returns
|
172
|
+
* 获取可执行字符串,返回 {{}} 包裹的字符串
|
173
|
+
* @param params
|
157
174
|
*/
|
158
|
-
export const
|
159
|
-
|
175
|
+
export const getRunStr = (strKey) => {
|
176
|
+
const _isRunStr = isRunStr(strKey);
|
177
|
+
if (!_isRunStr) {
|
160
178
|
return "";
|
161
179
|
}
|
162
180
|
const key = strKey.trim();
|
@@ -164,13 +182,50 @@ export const getScopeKey = (strKey) => {
|
|
164
182
|
};
|
165
183
|
|
166
184
|
/**
|
167
|
-
*
|
185
|
+
* 处理 schema 字符串值
|
186
|
+
* 1.可执行字符串({{}}包裹的字符串):schema scope 取出对应的值,否则转为可执行函数
|
187
|
+
* 2.其他情况直接返回对应数据
|
168
188
|
* @param strKey
|
169
189
|
* @param schemaScope
|
170
190
|
* @returns
|
171
191
|
*/
|
172
|
-
export const
|
173
|
-
|
174
|
-
|
192
|
+
export const handleSchemaStrVal = (strKey, schemaScope) => {
|
193
|
+
const _str = getRunStr(strKey);
|
194
|
+
if (!_str) {
|
195
|
+
return strKey;
|
196
|
+
}
|
197
|
+
let fn = getScopeKeyVal(_str, schemaScope);
|
198
|
+
if (fn) {
|
199
|
+
return fn;
|
200
|
+
}
|
201
|
+
return new Function("$root", `with($root) { return (${_str}) }`)(schemaScope);
|
202
|
+
};
|
203
|
+
|
204
|
+
/**
|
205
|
+
* 是否是 schema scope key
|
206
|
+
* @param strKey
|
207
|
+
* @returns
|
208
|
+
*/
|
209
|
+
export const isScopeKey = (strKey, schemaScope) => {
|
210
|
+
const key = getRunStr(strKey);
|
211
|
+
if (!schemaScope || typeof schemaScope !== "object") {
|
212
|
+
throw new Error("请传入正确的 schema scope");
|
213
|
+
}
|
214
|
+
// 判断是否是 scope 变量名
|
215
|
+
if (!schemaScope?.[key]) {
|
216
|
+
return false;
|
217
|
+
}
|
218
|
+
return key;
|
219
|
+
};
|
220
|
+
|
221
|
+
/**
|
222
|
+
* 获取 schema scope key
|
223
|
+
* @param strKey
|
224
|
+
* @returns
|
225
|
+
*/
|
226
|
+
export const getScopeKeyVal = (strKey, schemaScope) => {
|
227
|
+
if (!isScopeKey(strKey, schemaScope)) {
|
228
|
+
return "";
|
175
229
|
}
|
230
|
+
return schemaScope[getRunStr(strKey)];
|
176
231
|
};
|
@@ -0,0 +1,315 @@
|
|
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;
|
@@ -0,0 +1,87 @@
|
|
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,4 +1,4 @@
|
|
1
|
-
import React
|
1
|
+
import React from "react";
|
2
2
|
import { Card, Empty } from "antd";
|
3
3
|
import { CardProps } from "antd/lib/card";
|
4
4
|
import { ArrayField } from "@formily/core";
|
@@ -6,8 +6,8 @@ import { useField, observer, useFieldSchema, RecursionField } from "@formily/rea
|
|
6
6
|
import cls from "classnames";
|
7
7
|
import { ISchema } from "@formily/json-schema";
|
8
8
|
import { usePrefixCls } from "c-formily-antd/lib/__builtins__";
|
9
|
-
import { ArrayBase, ArrayBaseMixins, IArrayBaseProps } from "
|
10
|
-
|
9
|
+
import { ArrayBase, ArrayBaseMixins, IArrayBaseProps } from "../ArrayBase";
|
10
|
+
|
11
11
|
type ComposedArrayCards = React.FC<React.PropsWithChildren<CardProps & IArrayBaseProps>> & ArrayBaseMixins;
|
12
12
|
|
13
13
|
const isAdditionComponent = (schema: ISchema) => {
|
@@ -47,19 +47,12 @@ const isOperationComponent = (schema: ISchema) => {
|
|
47
47
|
export const ArrayCards: ComposedArrayCards = observer((props) => {
|
48
48
|
const field = useField<ArrayField>();
|
49
49
|
const schema = useFieldSchema();
|
50
|
+
const dataSource = Array.isArray(field.value) ? field.value : [];
|
50
51
|
const prefixCls = usePrefixCls("formily-array-cards", props);
|
51
|
-
const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp } = props;
|
52
|
-
|
53
|
-
return Array.isArray(field.value)
|
54
|
-
? field.value?.map((item) => {
|
55
|
-
return {
|
56
|
-
...item,
|
57
|
-
_key: item?.id || nanoid(),
|
58
|
-
};
|
59
|
-
})
|
60
|
-
: [];
|
61
|
-
}, [field.value?.length]);
|
52
|
+
const { onAdd, onCopy, onRemove, onMoveDown, onMoveUp, ...cardProps } = props;
|
53
|
+
|
62
54
|
if (!schema) throw new Error("can not found schema object");
|
55
|
+
|
63
56
|
const renderItems = () => {
|
64
57
|
return dataSource?.map((item, index) => {
|
65
58
|
const items = Array.isArray(schema.items) ? schema.items[index] || schema.items[0] : schema.items;
|
@@ -91,7 +84,6 @@ export const ArrayCards: ComposedArrayCards = observer((props) => {
|
|
91
84
|
{props.extra}
|
92
85
|
</span>
|
93
86
|
);
|
94
|
-
|
95
87
|
const content = (
|
96
88
|
<RecursionField
|
97
89
|
schema={items}
|
@@ -104,9 +96,10 @@ export const ArrayCards: ComposedArrayCards = observer((props) => {
|
|
104
96
|
/>
|
105
97
|
);
|
106
98
|
return (
|
107
|
-
|
99
|
+
// ! key 用于排序,必须是序号
|
100
|
+
<ArrayBase.Item key={index} index={index} record={() => field.value?.[index]}>
|
108
101
|
<Card
|
109
|
-
{...
|
102
|
+
{...cardProps}
|
110
103
|
onChange={() => {}}
|
111
104
|
className={cls(`${prefixCls}-item`, props.className)}
|
112
105
|
title={title}
|
@@ -132,7 +125,7 @@ export const ArrayCards: ComposedArrayCards = observer((props) => {
|
|
132
125
|
if (dataSource?.length) return;
|
133
126
|
return (
|
134
127
|
<Card
|
135
|
-
{...
|
128
|
+
{...cardProps}
|
136
129
|
onChange={() => {}}
|
137
130
|
className={cls(`${prefixCls}-item`, props.className)}
|
138
131
|
title={props.title || field.title}
|