@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.
- package/CHANGELOG.md +291 -283
- package/README.md +239 -239
- package/package.json +57 -57
- package/src/common/formily-utils.ts +125 -125
- package/src/common/schema-handler.ts +253 -253
- package/src/common/schema-merge.ts +68 -68
- package/src/components/ArrayBase/index.tsx +349 -349
- package/src/components/ArrayBase/style.less +90 -90
- package/src/components/ArrayBase/style.ts +2 -2
- package/src/components/ArrayCards/index.tsx +149 -149
- package/src/components/ArrayCards/style.less +14 -14
- package/src/components/ArrayCards/style.ts +4 -4
- package/src/components/ArrayTable/index.tsx +411 -411
- package/src/components/ArrayTable/style.less +52 -52
- package/src/components/ArrayTable/style.ts +7 -7
- package/src/components/DatePicker/index.tsx +108 -108
- package/src/components/LocationListPicker/assets/icon.js +1 -1
- package/src/components/LocationListPicker/components/AddrList/index.less +55 -55
- package/src/components/LocationListPicker/components/AddrList/index.tsx +75 -75
- package/src/components/LocationListPicker/components/Popup/address.schema.json +21 -21
- package/src/components/LocationListPicker/components/Popup/index.less +22 -22
- package/src/components/LocationListPicker/components/Popup/index.tsx +92 -92
- package/src/components/LocationListPicker/index.less +34 -34
- package/src/components/LocationListPicker/index.tsx +521 -520
- package/src/components/LocationPicker/Map/AMap/common/loader.ts +58 -58
- package/src/components/LocationPicker/Map/AMap/common/utils.ts +431 -431
- package/src/components/LocationPicker/Map/AMap/index.jsx +51 -51
- package/src/components/LocationPicker/README.md +44 -44
- package/src/components/LocationPicker/common/utils.ts +30 -30
- package/src/components/LocationPicker/components/ModalContent/index.tsx +387 -387
- package/src/components/LocationPicker/components/PickerInfo/index.tsx +109 -109
- package/src/components/LocationPicker/components/ResInfo/index.less +38 -38
- package/src/components/LocationPicker/components/ResInfo/index.tsx +65 -65
- package/src/components/LocationPicker/index.tsx +197 -197
- package/src/components/PersonnelSelect/index.less +21 -21
- package/src/components/PersonnelSelect/index.module.less +33 -33
- package/src/components/PersonnelSelect/index.tsx +305 -300
- package/src/components/PersonnelSelect/type.ts +92 -92
- package/src/components/RichEditor/index.less +38 -38
- package/src/components/RichEditor/index.tsx +238 -238
- package/src/components/TreeCheckbox/components/CheckboxTable/index.tsx +55 -55
- package/src/components/TreeCheckbox/components/TabsRender/index.tsx +58 -58
- package/src/components/TreeCheckbox/index.less +12 -12
- package/src/components/TreeCheckbox/index.tsx +63 -63
- package/src/components/Upload/README.md +64 -64
- package/src/components/Upload/common/OfflineUpload.ts +339 -339
- package/src/components/Upload/common/customRequest.ts +81 -81
- package/src/components/Upload/common/fileName.ts +142 -142
- package/src/components/Upload/common/handleIOFileList.ts +393 -393
- package/src/components/Upload/common/nanoid.ts +7 -7
- package/src/components/Upload/common/ossUpload.js +159 -159
- package/src/components/Upload/common/utils.js +194 -194
- package/src/components/Upload/components/ItemList/index.tsx +52 -52
- package/src/components/Upload/components/PreviewModal/previewRender.tsx +80 -80
- package/src/components/Upload/index.tsx +17 -17
- package/src/components/Upload/uploader-input.jsx +187 -187
- package/src/components/Upload/uploader.jsx +316 -316
- package/src/components/UserSelect/index.tsx +123 -123
- package/src/components/index.tsx +17 -17
- package/src/index.tsx +198 -198
|
@@ -1,300 +1,305 @@
|
|
|
1
|
-
import React, { useEffect, useState, useRef, useCallback, useMemo } from "react";
|
|
2
|
-
import { Select, List, Avatar, Spin } from "antd";
|
|
3
|
-
import { connect, mapProps } from "@formily/react";
|
|
4
|
-
import { debounce, isObject
|
|
5
|
-
import type { LabelValue, ScrollPagination, RemoteSelectProps } from "./type";
|
|
6
|
-
|
|
7
|
-
import "./index.less";
|
|
8
|
-
|
|
9
|
-
const defaultListItemConfigs = [
|
|
10
|
-
{ label: "姓名:", key: "userName" },
|
|
11
|
-
{ label: "主部门:", key: "parentName" },
|
|
12
|
-
{ label: "主驻点:", key: "orgName" },
|
|
13
|
-
{ label: "手机号:", key: "phoneNumber" },
|
|
14
|
-
{ label: "身份证号:", key: "idnumber" },
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
const transfromLabelInValueData = (list: LabelValue[], labelKey: string, valueKey: string): LabelValue[] => {
|
|
18
|
-
try {
|
|
19
|
-
return list.map((item) => ({ ...item, label: item?.[labelKey], value: item?.[valueKey] }));
|
|
20
|
-
} catch (e) {
|
|
21
|
-
console.error(e);
|
|
22
|
-
return list;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const RemoteSelect: React.FC<RemoteSelectProps> = ({
|
|
27
|
-
loadData,
|
|
28
|
-
searchData,
|
|
29
|
-
renderItem,
|
|
30
|
-
listItemConfigs,
|
|
31
|
-
labelKey = "userName",
|
|
32
|
-
valueKey = "userId",
|
|
33
|
-
disabledKey = "disabled",
|
|
34
|
-
initialPagination = {},
|
|
35
|
-
avataProps = {},
|
|
36
|
-
disabledStyle,
|
|
37
|
-
customItemNode,
|
|
38
|
-
labelInValue = false,
|
|
39
|
-
isClearable = false,
|
|
40
|
-
...selectProps
|
|
41
|
-
}) => {
|
|
42
|
-
const [search, setSearch] = useState("");
|
|
43
|
-
const [loading, setLoading] = useState(false);
|
|
44
|
-
const [loadingMore, setLoadingMore] = useState(false);
|
|
45
|
-
const [list, setList] = useState<LabelValue[]>([]);
|
|
46
|
-
const [cacheDeafultList, setCacheDeafultList] = useState<LabelValue[]>([]);
|
|
47
|
-
const [pagination, setPagination] = useState<ScrollPagination>({
|
|
48
|
-
pageNum: 1,
|
|
49
|
-
pageSize: 10,
|
|
50
|
-
...initialPagination,
|
|
51
|
-
});
|
|
52
|
-
const selectInstance = useRef<any>(null);
|
|
53
|
-
const total = useRef(0);
|
|
54
|
-
const initSearch = useRef(true);
|
|
55
|
-
|
|
56
|
-
const debounceLoadData = debounce(async (isScrollLoad = false) => {
|
|
57
|
-
try {
|
|
58
|
-
isScrollLoad ? setLoadingMore(true) : setLoading(true);
|
|
59
|
-
|
|
60
|
-
const result = await loadData(search, {
|
|
61
|
-
...pagination,
|
|
62
|
-
pageNum: isScrollLoad ? pagination.pageNum + 1 : 1,
|
|
63
|
-
});
|
|
64
|
-
const { list, pagination: resPagination } = result;
|
|
65
|
-
|
|
66
|
-
total.current = resPagination.total;
|
|
67
|
-
|
|
68
|
-
const transformatList: LabelValue[] = transfromLabelInValueData(list, labelKey, valueKey);
|
|
69
|
-
|
|
70
|
-
setList((prev) => (isScrollLoad ? [...prev, ...transformatList] : transformatList));
|
|
71
|
-
} finally {
|
|
72
|
-
isScrollLoad ? setLoadingMore(false) : setLoading(false);
|
|
73
|
-
}
|
|
74
|
-
}, 500);
|
|
75
|
-
|
|
76
|
-
const debounceHandleScroll = async (e: React.UIEvent<HTMLDivElement>) => {
|
|
77
|
-
const { scrollTop, clientHeight, scrollHeight } = e.currentTarget;
|
|
78
|
-
const isNearBottom = scrollHeight - scrollTop - clientHeight < 30;
|
|
79
|
-
|
|
80
|
-
if (isNearBottom && !loadingMore && list.length <= total.current) {
|
|
81
|
-
await getData(true);
|
|
82
|
-
setPagination((pre) => ({ ...pre, pageNum: pagination.pageNum + 1 }));
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const getData = useCallback(debounceLoadData, [search, pagination, loadData]);
|
|
87
|
-
|
|
88
|
-
// 处理滚动加载
|
|
89
|
-
const handleScroll = useCallback(debounceHandleScroll, [search, loadingMore, loadData]);
|
|
90
|
-
|
|
91
|
-
// 重置list滚动条
|
|
92
|
-
const resetListScroll = () => {
|
|
93
|
-
const listNode = document.getElementById("abt-list");
|
|
94
|
-
listNode && listNode.scrollTo({ top: 0, behavior: "auto" });
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// 处理搜索
|
|
98
|
-
const handleSearch = debounce((value: string) => {
|
|
99
|
-
resetListScroll();
|
|
100
|
-
setSearch(value);
|
|
101
|
-
setPagination((prev) => ({ ...prev, pageNum: 1 }));
|
|
102
|
-
}, 1000);
|
|
103
|
-
|
|
104
|
-
const handleOnDropdownVisibleChange = (open: boolean) => {
|
|
105
|
-
if (!isClearable) return;
|
|
106
|
-
if (open) {
|
|
107
|
-
getData();
|
|
108
|
-
} else {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
filterOption={false}
|
|
275
|
-
|
|
276
|
-
placeholder="请选择人员"
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
},
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
1
|
+
import React, { useEffect, useState, useRef, useCallback, useMemo } from "react";
|
|
2
|
+
import { Select, List, Avatar, Spin } from "antd";
|
|
3
|
+
import { connect, mapProps } from "@formily/react";
|
|
4
|
+
import { debounce, isObject } from "lodash";
|
|
5
|
+
import type { LabelValue, ScrollPagination, RemoteSelectProps } from "./type";
|
|
6
|
+
|
|
7
|
+
import "./index.less";
|
|
8
|
+
|
|
9
|
+
const defaultListItemConfigs = [
|
|
10
|
+
{ label: "姓名:", key: "userName" },
|
|
11
|
+
{ label: "主部门:", key: "parentName" },
|
|
12
|
+
{ label: "主驻点:", key: "orgName" },
|
|
13
|
+
{ label: "手机号:", key: "phoneNumber" },
|
|
14
|
+
{ label: "身份证号:", key: "idnumber" },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const transfromLabelInValueData = (list: LabelValue[], labelKey: string, valueKey: string): LabelValue[] => {
|
|
18
|
+
try {
|
|
19
|
+
return list.map((item) => ({ ...item, label: item?.[labelKey], value: item?.[valueKey] }));
|
|
20
|
+
} catch (e) {
|
|
21
|
+
console.error(e);
|
|
22
|
+
return list;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const RemoteSelect: React.FC<RemoteSelectProps> = ({
|
|
27
|
+
loadData,
|
|
28
|
+
searchData,
|
|
29
|
+
renderItem,
|
|
30
|
+
listItemConfigs,
|
|
31
|
+
labelKey = "userName",
|
|
32
|
+
valueKey = "userId",
|
|
33
|
+
disabledKey = "disabled",
|
|
34
|
+
initialPagination = {},
|
|
35
|
+
avataProps = {},
|
|
36
|
+
disabledStyle,
|
|
37
|
+
customItemNode,
|
|
38
|
+
labelInValue = false,
|
|
39
|
+
isClearable = false,
|
|
40
|
+
...selectProps
|
|
41
|
+
}) => {
|
|
42
|
+
const [search, setSearch] = useState("");
|
|
43
|
+
const [loading, setLoading] = useState(false);
|
|
44
|
+
const [loadingMore, setLoadingMore] = useState(false);
|
|
45
|
+
const [list, setList] = useState<LabelValue[]>([]);
|
|
46
|
+
// const [cacheDeafultList, setCacheDeafultList] = useState<LabelValue[]>([]);
|
|
47
|
+
const [pagination, setPagination] = useState<ScrollPagination>({
|
|
48
|
+
pageNum: 1,
|
|
49
|
+
pageSize: 10,
|
|
50
|
+
...initialPagination,
|
|
51
|
+
});
|
|
52
|
+
const selectInstance = useRef<any>(null);
|
|
53
|
+
const total = useRef(0);
|
|
54
|
+
const initSearch = useRef(true);
|
|
55
|
+
|
|
56
|
+
const debounceLoadData = debounce(async (isScrollLoad = false) => {
|
|
57
|
+
try {
|
|
58
|
+
isScrollLoad ? setLoadingMore(true) : setLoading(true);
|
|
59
|
+
|
|
60
|
+
const result = await loadData(search, {
|
|
61
|
+
...pagination,
|
|
62
|
+
pageNum: isScrollLoad ? pagination.pageNum + 1 : 1,
|
|
63
|
+
});
|
|
64
|
+
const { list, pagination: resPagination } = result;
|
|
65
|
+
|
|
66
|
+
total.current = resPagination.total;
|
|
67
|
+
|
|
68
|
+
const transformatList: LabelValue[] = transfromLabelInValueData(list, labelKey, valueKey);
|
|
69
|
+
|
|
70
|
+
setList((prev) => (isScrollLoad ? [...prev, ...transformatList] : transformatList));
|
|
71
|
+
} finally {
|
|
72
|
+
isScrollLoad ? setLoadingMore(false) : setLoading(false);
|
|
73
|
+
}
|
|
74
|
+
}, 500);
|
|
75
|
+
|
|
76
|
+
const debounceHandleScroll = async (e: React.UIEvent<HTMLDivElement>) => {
|
|
77
|
+
const { scrollTop, clientHeight, scrollHeight } = e.currentTarget;
|
|
78
|
+
const isNearBottom = scrollHeight - scrollTop - clientHeight < 30;
|
|
79
|
+
|
|
80
|
+
if (isNearBottom && !loadingMore && list.length <= total.current) {
|
|
81
|
+
await getData(true);
|
|
82
|
+
setPagination((pre) => ({ ...pre, pageNum: pagination.pageNum + 1 }));
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const getData = useCallback(debounceLoadData, [search, pagination, loadData]);
|
|
87
|
+
|
|
88
|
+
// 处理滚动加载
|
|
89
|
+
const handleScroll = useCallback(debounceHandleScroll, [search, loadingMore, loadData]);
|
|
90
|
+
|
|
91
|
+
// 重置list滚动条
|
|
92
|
+
const resetListScroll = () => {
|
|
93
|
+
const listNode = document.getElementById("abt-list");
|
|
94
|
+
listNode && listNode.scrollTo({ top: 0, behavior: "auto" });
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// 处理搜索
|
|
98
|
+
const handleSearch = debounce((value: string) => {
|
|
99
|
+
resetListScroll();
|
|
100
|
+
setSearch(value);
|
|
101
|
+
setPagination((prev) => ({ ...prev, pageNum: 1 }));
|
|
102
|
+
}, 1000);
|
|
103
|
+
|
|
104
|
+
const handleOnDropdownVisibleChange = (open: boolean) => {
|
|
105
|
+
if (!isClearable) return;
|
|
106
|
+
if (open) {
|
|
107
|
+
getData();
|
|
108
|
+
} else {
|
|
109
|
+
reset();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const reset = () => {
|
|
114
|
+
setSearch("");
|
|
115
|
+
resetListScroll();
|
|
116
|
+
setList([]);
|
|
117
|
+
setPagination((prev) => ({ ...prev, pageNum: 1 }));
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// 处理选项点击事件
|
|
121
|
+
const handleItemClick = (item: LabelValue) => {
|
|
122
|
+
const { value: currentValue, mode, onChange } = selectProps;
|
|
123
|
+
const itemId = item.value;
|
|
124
|
+
|
|
125
|
+
// 多选模式处理
|
|
126
|
+
const handleMultipleSelection = () => {
|
|
127
|
+
const selectedOptions: any[] = Array.isArray(currentValue) ? currentValue : [currentValue];
|
|
128
|
+
|
|
129
|
+
if (labelInValue) {
|
|
130
|
+
const isSelected = selectedOptions.some((opt) => opt.value === itemId);
|
|
131
|
+
|
|
132
|
+
return isSelected
|
|
133
|
+
? selectedOptions.filter((opt) => opt.value !== itemId) // 移除已选项
|
|
134
|
+
: [...selectedOptions, item]; // 添加新选项
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const isSelected = selectedOptions.some((opt) => opt === itemId);
|
|
138
|
+
|
|
139
|
+
return isSelected
|
|
140
|
+
? selectedOptions.filter((opt) => opt !== itemId) // 移除已选项
|
|
141
|
+
: [...selectedOptions, item]; // 添加新选项
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// 单选模式处理
|
|
145
|
+
const handleSingleSelection = () => {
|
|
146
|
+
const isCurrentSelected = (currentValue as LabelValue)?.value === itemId;
|
|
147
|
+
return isCurrentSelected ? undefined : item;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
let resultValue: string | number | any[] | LabelValue;
|
|
151
|
+
|
|
152
|
+
// 执行模式对应处理
|
|
153
|
+
const newValue = mode === "multiple" ? handleMultipleSelection() : handleSingleSelection();
|
|
154
|
+
|
|
155
|
+
if (mode === "multiple") {
|
|
156
|
+
if (labelInValue) resultValue = newValue;
|
|
157
|
+
else resultValue = newValue.map((x: LabelValue | string | number) => (typeof x === "object" ? x?.value : x));
|
|
158
|
+
} else {
|
|
159
|
+
labelInValue ? (resultValue = newValue) : (resultValue = (newValue as unknown as LabelValue).value);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// 触发变更回调
|
|
163
|
+
onChange?.(resultValue, currentValue as any);
|
|
164
|
+
|
|
165
|
+
// 单选模式自动关闭下拉框
|
|
166
|
+
if (mode !== "multiple" && selectInstance.current) selectInstance.current.blur();
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// 合并配置
|
|
170
|
+
const itemConfigs = useMemo(() => {
|
|
171
|
+
if (Array.isArray(listItemConfigs) && listItemConfigs?.length) return listItemConfigs;
|
|
172
|
+
return defaultListItemConfigs;
|
|
173
|
+
}, [listItemConfigs]);
|
|
174
|
+
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
getData();
|
|
177
|
+
}, [search]);
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
// 当value为一个id或者id数组时,需要进行数据查询用以回显label等信息
|
|
180
|
+
if (selectProps.value && typeof searchData === "function" && initSearch.current) {
|
|
181
|
+
searchData?.(selectProps.value).then((res: Record<string, any>) => {
|
|
182
|
+
const listData = transfromLabelInValueData(res.list || [], labelKey, valueKey);
|
|
183
|
+
// setCacheDeafultList(listData);
|
|
184
|
+
setList(listData);
|
|
185
|
+
});
|
|
186
|
+
// 只有初始化时执行
|
|
187
|
+
initSearch.current = false;
|
|
188
|
+
}
|
|
189
|
+
}, [selectProps.value]);
|
|
190
|
+
|
|
191
|
+
// 默认渲染项(增加选中状态和点击处理)
|
|
192
|
+
const defaultRenderItem = useCallback(
|
|
193
|
+
(item: LabelValue) => {
|
|
194
|
+
const { mode, value: selectedValue } = selectProps;
|
|
195
|
+
const { value, [disabledKey]: isDisabled = false } = item;
|
|
196
|
+
// 选中状态判断
|
|
197
|
+
const getSelectionStatus = () => {
|
|
198
|
+
if (mode === "multiple") {
|
|
199
|
+
if (!Array.isArray(selectedValue)) return false;
|
|
200
|
+
const selectedValues = (selectedValue || [])?.map((opt) =>
|
|
201
|
+
(isObject(opt) as unknown as Record<string, any>) ? opt?.value ?? opt?.value : opt,
|
|
202
|
+
);
|
|
203
|
+
return selectedValues.includes(value);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return isObject(selectedValue) ? (selectedValue as LabelValue)?.value === value : selectedValue === value;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// 禁用样式生成
|
|
210
|
+
const generateStyle = (disabled: boolean): React.CSSProperties => {
|
|
211
|
+
if (typeof disabledStyle === "function") {
|
|
212
|
+
return disabledStyle(disabled);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
217
|
+
backgroundColor: disabled ? "#f0f0f0" : getSelectionStatus() ? "#e6f7ff" : "inherit",
|
|
218
|
+
color: disabled ? "#999" : "inherit",
|
|
219
|
+
filter: disabled ? "grayscale(100%)" : "none",
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// 头像组件
|
|
224
|
+
const avatarComponent = <Avatar alt={item.userName} size={60} {...avataProps} src={item.avatar} />;
|
|
225
|
+
|
|
226
|
+
// 用户信息列表
|
|
227
|
+
const userInfoContent = (
|
|
228
|
+
<ul className="abt-user-item-info">
|
|
229
|
+
{itemConfigs.map((configItem, index) => (
|
|
230
|
+
<li key={configItem?.key || index} className="abt-user-item-info__item">
|
|
231
|
+
<span>{configItem?.label}</span>
|
|
232
|
+
<span>{item?.[configItem.key]}</span>
|
|
233
|
+
</li>
|
|
234
|
+
))}
|
|
235
|
+
</ul>
|
|
236
|
+
);
|
|
237
|
+
const itemStyle = generateStyle(isDisabled);
|
|
238
|
+
|
|
239
|
+
const renderCustomItemNode = typeof customItemNode === "function" ? customItemNode?.(item, itemStyle) : null;
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<List.Item key={value} onClick={() => !isDisabled && handleItemClick(item)} style={itemStyle}>
|
|
243
|
+
{renderCustomItemNode || (
|
|
244
|
+
<div className="abt-user-item" key={item?.value}>
|
|
245
|
+
<div className="abt-user-item-avatar">{avatarComponent}</div>
|
|
246
|
+
{userInfoContent}
|
|
247
|
+
</div>
|
|
248
|
+
)}
|
|
249
|
+
</List.Item>
|
|
250
|
+
);
|
|
251
|
+
},
|
|
252
|
+
[selectProps.value, list?.length],
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
// 自定义下拉内容
|
|
256
|
+
const dropdownRender = () => (
|
|
257
|
+
<div>
|
|
258
|
+
<Spin spinning={loading}>
|
|
259
|
+
<List
|
|
260
|
+
id={"abt-list"}
|
|
261
|
+
loading={loadingMore}
|
|
262
|
+
dataSource={list}
|
|
263
|
+
renderItem={renderItem ? renderItem : defaultRenderItem}
|
|
264
|
+
/*@ts-ignore*/
|
|
265
|
+
onScroll={handleScroll}
|
|
266
|
+
style={{ maxHeight: 250, overflowY: "auto" }}
|
|
267
|
+
/>
|
|
268
|
+
</Spin>
|
|
269
|
+
</div>
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
<Select
|
|
274
|
+
filterOption={false}
|
|
275
|
+
showSearch
|
|
276
|
+
placeholder="请选择人员"
|
|
277
|
+
{...selectProps}
|
|
278
|
+
ref={selectInstance}
|
|
279
|
+
onDropdownVisibleChange={handleOnDropdownVisibleChange}
|
|
280
|
+
onSearch={handleSearch}
|
|
281
|
+
dropdownRender={dropdownRender}
|
|
282
|
+
options={list.map((item) => ({
|
|
283
|
+
value: item?.[valueKey] || item?.userId,
|
|
284
|
+
label: item?.[labelKey] || item.userName,
|
|
285
|
+
...item,
|
|
286
|
+
}))}
|
|
287
|
+
/>
|
|
288
|
+
);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const PersonnelSelect = connect(
|
|
292
|
+
RemoteSelect,
|
|
293
|
+
mapProps(
|
|
294
|
+
{
|
|
295
|
+
loading: true,
|
|
296
|
+
},
|
|
297
|
+
(props) => {
|
|
298
|
+
return {
|
|
299
|
+
...props,
|
|
300
|
+
};
|
|
301
|
+
},
|
|
302
|
+
),
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
export { RemoteSelect, PersonnelSelect };
|