...
|
...
|
@@ -3,7 +3,7 @@ import { QxWidgetIcon } from '@qx/common'; |
3
|
3
|
import { Collapse, Dropdown, Empty, Tag } from 'antd';
|
4
|
4
|
import cls from 'classnames';
|
5
|
5
|
import { cloneDeep } from 'lodash-es';
|
6
|
|
-import React, { useEffect, useMemo, useState } from 'react';
|
|
6
|
+import React, { useEffect, useState } from 'react';
|
7
|
7
|
import { QxBaseIcon } from '../qx-base-icon';
|
8
|
8
|
import { request } from '../utils';
|
9
|
9
|
import './index.less';
|
...
|
...
|
@@ -68,6 +68,8 @@ interface NodeFieldDisPlay { |
68
|
68
|
node?: INode;
|
69
|
69
|
nodes?: INode[];
|
70
|
70
|
limitTypes?: string[];
|
|
71
|
+ value?: string;
|
|
72
|
+ subset?: boolean;
|
71
|
73
|
}
|
72
|
74
|
|
73
|
75
|
const icon = (icon: any) => {
|
...
|
...
|
@@ -85,52 +87,18 @@ export const useNodeFieldDisplay = ({ |
85
|
87
|
node,
|
86
|
88
|
nodes,
|
87
|
89
|
limitTypes,
|
|
90
|
+ value,
|
|
91
|
+ subset = true,
|
88
|
92
|
}: NodeFieldDisPlay) => {
|
89
|
|
- const sourceParentNodes =
|
|
93
|
+ const sourceParentNodes = cloneDeep(
|
90
|
94
|
getParentNodes(node, nodes).filter(
|
91
|
95
|
(node) => !['default_DF_BRANCH'].includes(node.type),
|
92
|
|
- ) || [];
|
93
|
|
-
|
94
|
|
- const optionalNodes = useMemo(() => {
|
95
|
|
- const targetParentNodes = cloneDeep(sourceParentNodes);
|
96
|
|
- if (!limitTypes) return targetParentNodes;
|
97
|
|
-
|
98
|
|
- function getEffectiveNodes(nodes: INode[]) {
|
99
|
|
- return nodes.reduce<INode[]>((pre, cur) => {
|
100
|
|
- const curNode = cur;
|
101
|
|
-
|
102
|
|
- if (Array.isArray(curNode.data?.result)) {
|
103
|
|
- const resultNodes = (curNode.data.result as FiledType[]).filter(
|
104
|
|
- (i) => {
|
105
|
|
- if (i.child && Array.isArray(i.child)) {
|
106
|
|
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
|
107
|
|
- i.child = getEffectiveResult(i.child);
|
108
|
|
- }
|
109
|
|
- return limitTypes!.includes(i.type);
|
110
|
|
- },
|
111
|
|
- );
|
112
|
|
-
|
113
|
|
- if (resultNodes?.length) {
|
114
|
|
- curNode.data.result = resultNodes;
|
115
|
|
- pre.push(curNode);
|
116
|
|
- }
|
117
|
|
- }
|
118
|
|
-
|
119
|
|
- return pre;
|
120
|
|
- }, []);
|
121
|
|
- }
|
122
|
|
-
|
123
|
|
- function getEffectiveResult(result: FiledType[]) {
|
124
|
|
- return result.filter((item) => {
|
125
|
|
- if (item.child && Array.isArray(item.child)) {
|
126
|
|
- item.child = getEffectiveResult(item.child);
|
127
|
|
- }
|
128
|
|
- return limitTypes?.includes(item.fieldType);
|
129
|
|
- });
|
130
|
|
- }
|
|
96
|
+ ) || [],
|
|
97
|
+ );
|
131
|
98
|
|
132
|
|
- return getEffectiveNodes(targetParentNodes);
|
133
|
|
- }, [limitTypes, sourceParentNodes]);
|
|
99
|
+ // const [targetParentNodes, setTargetParentNodes] = useState(sourceParentNodes)
|
|
100
|
+ const [inputDisplay, setInputDisplay] = useState<React.ReactNode>();
|
|
101
|
+ const [optionalNodes, setOptionalNodes] = useState<INode[]>([]); // 根据 fieldType 过滤后的 nodes
|
134
|
102
|
|
135
|
103
|
const getId = (val?: string) => {
|
136
|
104
|
if (!val) return;
|
...
|
...
|
@@ -150,11 +118,12 @@ export const useNodeFieldDisplay = ({ |
150
|
118
|
let index = 0;
|
151
|
119
|
while (n && index <= 20) {
|
152
|
120
|
displayConfig = [];
|
153
|
|
- const curNode = optionalNodes[index] || {};
|
|
121
|
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
122
|
+ const curNode = cloneDeep(optionalNodes[index]) || {};
|
154
|
123
|
displayConfig.push({
|
155
|
124
|
title: curNode.name,
|
156
|
125
|
icon: curNode.icon,
|
157
|
|
- ...(optionalNodes[index] || {}),
|
|
126
|
+ ...curNode,
|
158
|
127
|
});
|
159
|
128
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
160
|
129
|
recursionNodeResult(curNode.data?.result);
|
...
|
...
|
@@ -187,20 +156,13 @@ export const useNodeFieldDisplay = ({ |
187
|
156
|
return (
|
188
|
157
|
<>
|
189
|
158
|
{displayConfig?.map((item, idx) => (
|
190
|
|
- <div
|
191
|
|
- key={idx}
|
192
|
|
- className='qx-node-select-input__content-item'
|
193
|
|
- >
|
|
159
|
+ <div key={idx} className="qx-node-select-input__content-item">
|
194
|
160
|
{item.icon && (
|
195
|
|
- <span
|
196
|
|
- className='qx-node-select-input__content-item__icon'
|
197
|
|
- >
|
|
161
|
+ <span className="qx-node-select-input__content-item__icon">
|
198
|
162
|
{icon(item.icon)}
|
199
|
163
|
</span>
|
200
|
164
|
)}
|
201
|
|
- <span
|
202
|
|
- className='qx-node-select-input__content-item__text'
|
203
|
|
- >
|
|
165
|
+ <span className="qx-node-select-input__content-item__text">
|
204
|
166
|
{item.type &&
|
205
|
167
|
FileTypeMap[item.type] &&
|
206
|
168
|
!item.icon &&
|
...
|
...
|
@@ -208,9 +170,7 @@ export const useNodeFieldDisplay = ({ |
208
|
170
|
{item.title}
|
209
|
171
|
</span>
|
210
|
172
|
{idx !== displayConfig.length - 1 && (
|
211
|
|
- <span
|
212
|
|
- className='qx-node-select-input__content-item__arrow'
|
213
|
|
- >
|
|
173
|
+ <span className="qx-node-select-input__content-item__arrow">
|
214
|
174
|
<svg
|
215
|
175
|
xmlns="http://www.w3.org/2000/svg"
|
216
|
176
|
width="1em"
|
...
|
...
|
@@ -227,9 +187,137 @@ export const useNodeFieldDisplay = ({ |
227
|
187
|
);
|
228
|
188
|
};
|
229
|
189
|
|
|
190
|
+ const renderInputDisplay = (val: string = value || '') => {
|
|
191
|
+ setInputDisplay(
|
|
192
|
+ <Tag bordered={false} className="qx-node-select-input__content">
|
|
193
|
+ {genDisplayDom(val)}
|
|
194
|
+ </Tag>,
|
|
195
|
+ );
|
|
196
|
+ };
|
|
197
|
+
|
|
198
|
+ /***
|
|
199
|
+ * 查找有 formId 的 result
|
|
200
|
+ */
|
|
201
|
+ const findResultByFormId = () => {
|
|
202
|
+ const forms: FiledType[] = [];
|
|
203
|
+ sourceParentNodes.forEach((node) => {
|
|
204
|
+ if (Array.isArray(node.data?.result)) {
|
|
205
|
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
206
|
+ recursionNodeResult(node.data?.result);
|
|
207
|
+ }
|
|
208
|
+ });
|
|
209
|
+
|
|
210
|
+ function recursionNodeResult(result: FiledType[] | FiledType) {
|
|
211
|
+ if (!Array.isArray(result) && result) {
|
|
212
|
+ if (result.qxProps && result.qxProps?.formId) {
|
|
213
|
+ forms.push(result);
|
|
214
|
+ }
|
|
215
|
+ }
|
|
216
|
+ if (Array.isArray(result)) {
|
|
217
|
+ result.forEach((i) => {
|
|
218
|
+ if (i.qxProps && i.qxProps?.formId) {
|
|
219
|
+ forms.push(i);
|
|
220
|
+ } else if (i.child) {
|
|
221
|
+ recursionNodeResult(i.child);
|
|
222
|
+ }
|
|
223
|
+ });
|
|
224
|
+ }
|
|
225
|
+ }
|
|
226
|
+
|
|
227
|
+ return forms;
|
|
228
|
+ };
|
|
229
|
+
|
|
230
|
+ /**
|
|
231
|
+ * 查询所有 formId 的字段,并给 result 添加 child
|
|
232
|
+ */
|
|
233
|
+ const handleGetAppsFields = async () => {
|
|
234
|
+ const forms = findResultByFormId();
|
|
235
|
+ const ids = forms.map((item) => item.qxProps?.formId);
|
|
236
|
+ if (Array.isArray(ids) && ids.length && subset) {
|
|
237
|
+ try {
|
|
238
|
+ const data = await getAppsFields(ids as any[]);
|
|
239
|
+ Object.keys(data).forEach((id) => {
|
|
240
|
+ const form = forms.find((item) => item.qxProps?.formId === id);
|
|
241
|
+ if (!form) return;
|
|
242
|
+
|
|
243
|
+ const childItem = data[id].map((item: FiledType) => ({
|
|
244
|
+ ...item,
|
|
245
|
+ icon: (
|
|
246
|
+ <span className="qx-node-select-item__icon">
|
|
247
|
+ <QxWidgetIcon widgetName={item.extract?.widget || 'qxInput'} />
|
|
248
|
+ </span>
|
|
249
|
+ ),
|
|
250
|
+ title: item.name,
|
|
251
|
+ id: item.code,
|
|
252
|
+ type: item.extract?.fieldType,
|
|
253
|
+ }));
|
|
254
|
+
|
|
255
|
+ if (Array.isArray(form.child)) {
|
|
256
|
+ form.child.push(childItem);
|
|
257
|
+ } else {
|
|
258
|
+ form.child = childItem;
|
|
259
|
+ }
|
|
260
|
+ });
|
|
261
|
+ // console.log(2222222, targetParentNodes, forms);
|
|
262
|
+ } catch (error) {
|
|
263
|
+ // appsFields = {};
|
|
264
|
+ } finally {
|
|
265
|
+ renderInputDisplay();
|
|
266
|
+ }
|
|
267
|
+ }
|
|
268
|
+ return sourceParentNodes;
|
|
269
|
+ };
|
|
270
|
+
|
|
271
|
+ const getOptionalNodes = async () => {
|
|
272
|
+ const targetParentNodes = await handleGetAppsFields();
|
|
273
|
+ if (!limitTypes) return setOptionalNodes(targetParentNodes);
|
|
274
|
+
|
|
275
|
+ function getEffectiveResult(result: FiledType[]) {
|
|
276
|
+ const newResult = [];
|
|
277
|
+ for (let i = 0; i < result.length; i++) {
|
|
278
|
+ const resultItem = result[i] || {};
|
|
279
|
+ if (resultItem.child) {
|
|
280
|
+ resultItem.child = getEffectiveResult(resultItem.child);
|
|
281
|
+ if (
|
|
282
|
+ (Array.isArray(resultItem.child) && resultItem.child.length) ||
|
|
283
|
+ limitTypes?.includes(resultItem.type)
|
|
284
|
+ ) {
|
|
285
|
+ newResult.push(resultItem);
|
|
286
|
+ }
|
|
287
|
+ } else if (limitTypes?.includes(resultItem.type)) {
|
|
288
|
+ newResult.push(resultItem);
|
|
289
|
+ }
|
|
290
|
+ }
|
|
291
|
+
|
|
292
|
+ return newResult;
|
|
293
|
+ }
|
|
294
|
+
|
|
295
|
+ function getEffectiveNodes(nodes: INode[]) {
|
|
296
|
+ for (let i = 0; i <= nodes.length; i++) {
|
|
297
|
+ const node = nodes[i] || {};
|
|
298
|
+ const nodeResult = node.data?.result;
|
|
299
|
+ if (Array.isArray(nodeResult) && nodeResult.length) {
|
|
300
|
+ node.data.result = getEffectiveResult(nodeResult);
|
|
301
|
+ }
|
|
302
|
+ }
|
|
303
|
+
|
|
304
|
+ return nodes;
|
|
305
|
+ }
|
|
306
|
+
|
|
307
|
+ const newNodes = getEffectiveNodes(targetParentNodes);
|
|
308
|
+ setOptionalNodes([...newNodes]);
|
|
309
|
+ };
|
|
310
|
+
|
|
311
|
+ useEffect(() => {
|
|
312
|
+ getOptionalNodes();
|
|
313
|
+ }, []);
|
|
314
|
+
|
230
|
315
|
return {
|
231
|
316
|
genDisplayDom,
|
232
|
317
|
optionalNodes,
|
|
318
|
+ // targetParentNodes,
|
|
319
|
+ renderInputDisplay,
|
|
320
|
+ inputDisplay,
|
233
|
321
|
};
|
234
|
322
|
};
|
235
|
323
|
|
...
|
...
|
@@ -266,7 +354,7 @@ const SelectItem = (props: any) => { |
266
|
354
|
);
|
267
|
355
|
}
|
268
|
356
|
|
269
|
|
- if (!props.child) {
|
|
357
|
+ if (!props.child || !props.child.length) {
|
270
|
358
|
return (
|
271
|
359
|
<div
|
272
|
360
|
className={cls('qx-node-select-item')}
|
...
|
...
|
@@ -317,14 +405,10 @@ export const QxFlowNodeFieldSelector: React.FC<NodeFieldSelectProps> = ( |
317
|
405
|
|
318
|
406
|
const [visible, setVisible] = useState(false);
|
319
|
407
|
|
320
|
|
- const [inputDisplay, setInputDisplay] = useState<React.ReactNode>();
|
321
|
|
-
|
322
|
|
- const { optionalNodes, genDisplayDom } = useNodeFieldDisplay(props);
|
|
408
|
+ const { optionalNodes, renderInputDisplay, inputDisplay } =
|
|
409
|
+ useNodeFieldDisplay(props);
|
323
|
410
|
|
324
|
411
|
const getOptions = () => {
|
325
|
|
- if (!optionalNodes.length) {
|
326
|
|
- return <Empty />;
|
327
|
|
- }
|
328
|
412
|
return optionalNodes.map((node) => ({
|
329
|
413
|
label: (
|
330
|
414
|
<div className={cls('qx-node-select-dropdown-header')}>
|
...
|
...
|
@@ -352,96 +436,6 @@ export const QxFlowNodeFieldSelector: React.FC<NodeFieldSelectProps> = ( |
352
|
436
|
}));
|
353
|
437
|
};
|
354
|
438
|
|
355
|
|
- const getForms = () => {
|
356
|
|
- const forms: FiledType[] = [];
|
357
|
|
- optionalNodes.forEach((node) => {
|
358
|
|
- if (Array.isArray(node.data?.result)) {
|
359
|
|
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
|
360
|
|
- recursionNodeResult(node.data?.result);
|
361
|
|
- }
|
362
|
|
- });
|
363
|
|
-
|
364
|
|
- function recursionNodeResult(result: FiledType[] | FiledType) {
|
365
|
|
- if (!Array.isArray(result) && result) {
|
366
|
|
- if (result.qxProps && result.qxProps?.formId) {
|
367
|
|
- forms.push(result);
|
368
|
|
- }
|
369
|
|
- }
|
370
|
|
- if (Array.isArray(result)) {
|
371
|
|
- result.forEach((i) => {
|
372
|
|
- if (i.qxProps && i.qxProps?.formId) {
|
373
|
|
- forms.push(i);
|
374
|
|
- } else if (i.child) {
|
375
|
|
- recursionNodeResult(i.child);
|
376
|
|
- }
|
377
|
|
- });
|
378
|
|
- }
|
379
|
|
- }
|
380
|
|
-
|
381
|
|
- return forms;
|
382
|
|
- };
|
383
|
|
-
|
384
|
|
- const renderInputDisplay = (val: string = props.value || '') => {
|
385
|
|
- setInputDisplay(
|
386
|
|
- <Tag bordered={false} className="qx-node-select-input__content">
|
387
|
|
- {genDisplayDom(val)}
|
388
|
|
- </Tag>,
|
389
|
|
- );
|
390
|
|
- };
|
391
|
|
-
|
392
|
|
- const handleGetAppsFields = async () => {
|
393
|
|
- const forms = getForms();
|
394
|
|
- const ids = forms.map(
|
395
|
|
- (item) => item.qxProps?.formId && !props.limitTypes?.includes(item.type),
|
396
|
|
- );
|
397
|
|
- console.log(ids, 'ids')
|
398
|
|
- if (Array.isArray(ids) && ids.length) {
|
399
|
|
- try {
|
400
|
|
- const data = await getAppsFields(ids as any[]);
|
401
|
|
- Object.keys(data).forEach((id) => {
|
402
|
|
- forms.forEach((i) => {
|
403
|
|
- if (i.qxProps?.formId === id) {
|
404
|
|
- if (Array.isArray(i.child)) {
|
405
|
|
- i.child.push(
|
406
|
|
- data[id].map((item: FiledType) => ({
|
407
|
|
- icon: (
|
408
|
|
- <span className="qx-node-select-item__icon">
|
409
|
|
- <QxWidgetIcon
|
410
|
|
- widgetName={item.extract?.widget || 'qxInput'}
|
411
|
|
- />
|
412
|
|
- </span>
|
413
|
|
- ),
|
414
|
|
- title: item.name,
|
415
|
|
- code: item.code,
|
416
|
|
- id: item.code,
|
417
|
|
- type: item.extract?.fieldType,
|
418
|
|
- })),
|
419
|
|
- );
|
420
|
|
- } else {
|
421
|
|
- i.child = data[id].map((item: FiledType) => ({
|
422
|
|
- icon: (
|
423
|
|
- <span className="qx-node-select-item__icon">
|
424
|
|
- <QxWidgetIcon
|
425
|
|
- widgetName={item.extract?.widget || 'qxInput'}
|
426
|
|
- />
|
427
|
|
- </span>
|
428
|
|
- ),
|
429
|
|
- title: item.name,
|
430
|
|
- code: item.code,
|
431
|
|
- id: item.code,
|
432
|
|
- type: item.extract?.fieldType,
|
433
|
|
- }));
|
434
|
|
- }
|
435
|
|
- }
|
436
|
|
- });
|
437
|
|
- });
|
438
|
|
- renderInputDisplay();
|
439
|
|
- } catch (error) {
|
440
|
|
- // appsFields = {};
|
441
|
|
- }
|
442
|
|
- }
|
443
|
|
- };
|
444
|
|
-
|
445
|
439
|
const handleItemClick = (nodeKey: string, item: any) => {
|
446
|
440
|
const newValue = '${' + `${nodeKey}|${item.id}` + '}';
|
447
|
441
|
props.onChange?.(newValue, item);
|
...
|
...
|
@@ -452,23 +446,27 @@ export const QxFlowNodeFieldSelector: React.FC<NodeFieldSelectProps> = ( |
452
|
446
|
};
|
453
|
447
|
|
454
|
448
|
useEffect(() => {
|
455
|
|
- handleGetAppsFields();
|
456
|
|
- }, []);
|
457
|
|
-
|
458
|
|
- useEffect(() => {
|
459
|
449
|
setVisible(props.open ?? false);
|
460
|
450
|
}, [props.open]);
|
461
|
451
|
|
|
452
|
+ const dropdownRender = () => {
|
|
453
|
+ const items = getOptions();
|
|
454
|
+ if (Array.isArray(items) && items.length) {
|
|
455
|
+ return <Collapse ghost expandIconPosition="end" items={items} />;
|
|
456
|
+ } else {
|
|
457
|
+ return <Empty />;
|
|
458
|
+ }
|
|
459
|
+ };
|
|
460
|
+
|
462
|
461
|
return (
|
463
|
462
|
<div className={cls('qx-node-select')}>
|
464
|
463
|
<Dropdown
|
|
464
|
+ destroyPopupOnHide
|
465
|
465
|
trigger={['click']}
|
466
|
466
|
overlayStyle={{ width: `${props?.width}px` }}
|
467
|
467
|
overlayClassName={cls('qx-node-select-dropdown')}
|
468
|
468
|
open={visible}
|
469
|
|
- dropdownRender={() => (
|
470
|
|
- <Collapse ghost expandIconPosition="end" items={getOptions()} />
|
471
|
|
- )}
|
|
469
|
+ dropdownRender={dropdownRender}
|
472
|
470
|
onOpenChange={(open) => {
|
473
|
471
|
if (mode === 'select') {
|
474
|
472
|
setVisible(open);
|
...
|
...
|
@@ -505,6 +503,7 @@ export interface NodeFieldSelectProps { |
505
|
503
|
width?: number;
|
506
|
504
|
mode?: 'select' | 'variable';
|
507
|
505
|
open?: boolean;
|
|
506
|
+ subset?: boolean;
|
508
|
507
|
}
|
509
|
508
|
|
510
|
509
|
export interface FiledType {
|
...
|
...
|
|