Commit c4e52be16cbc189e678a5acb125f62a215e2790f
1 parent
bcaa9a07
refactor: qx-base-condition & qx-flow-node-selector
Showing
3 changed files
with
125 additions
and
89 deletions
... | ... | @@ -7,6 +7,7 @@ import { QxBaseIcon } from '../qx-base-icon'; |
7 | 7 | import { QxFieldSetter } from '../qx-field-setter'; |
8 | 8 | import type { INode } from '../qx-flow-node-selector'; |
9 | 9 | import { |
10 | + FieldMapType, | |
10 | 11 | QxFlowNodeFieldSelector, |
11 | 12 | useNodeFieldDisplay, |
12 | 13 | } from '../qx-flow-node-selector'; |
... | ... | @@ -681,7 +682,9 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
681 | 682 | node, |
682 | 683 | nodes, |
683 | 684 | subset, |
684 | - params | |
685 | + params, | |
686 | + fieldGroupType, | |
687 | + isMixValue, | |
685 | 688 | }) => { |
686 | 689 | const valuesObj = value?.valuesObj?.[0] || {}; |
687 | 690 | const [open, setOpen] = useState(false); |
... | ... | @@ -732,36 +735,37 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
732 | 735 | const { genDisplayDom } = useNodeFieldDisplay({ |
733 | 736 | node: node, |
734 | 737 | nodes: nodes, |
735 | - limitTypes: [field.fieldType], | |
738 | + limitTypes: [field.extract?.fieldType], | |
736 | 739 | value: valuesObj?.value, |
737 | - subset | |
740 | + subset, | |
738 | 741 | }); |
739 | 742 | |
740 | 743 | const getName = (values: any[]) => { |
741 | - return values.map((value) => genDisplayDom(value)) | |
742 | - } | |
744 | + return Array.isArray(values) | |
745 | + ? values.map((value) => genDisplayDom(value)) | |
746 | + : []; | |
747 | + }; | |
743 | 748 | |
744 | 749 | const RenderContent = ( |
745 | 750 | <> |
746 | 751 | <QxFieldSetter |
747 | 752 | params={params || field?.params} |
748 | 753 | value={value?.valuesObj} |
749 | - fieldGroupType={value?.fieldGroupType} | |
754 | + fieldGroupType={fieldGroupType} | |
750 | 755 | onChange={handleChange} |
751 | - isMultiple={multipleType.includes(value?.fieldGroupType)} | |
756 | + isMultiple={multipleType.includes(fieldGroupType)} | |
752 | 757 | isRange={optValTypeCheck.isRangeType(value?.opt)} |
753 | 758 | disabled={optValTypeCheck.isEmptyType(value?.opt)} |
754 | 759 | getName={getName} |
755 | 760 | widget={field.extract?.widget} |
761 | + isMixValue={isMixValue} | |
762 | + /> | |
763 | + <ControlOutlined | |
764 | + onClick={() => { | |
765 | + setOpen(!open); | |
766 | + }} | |
767 | + className="qx-base-condition-item__content-suffix" | |
756 | 768 | /> |
757 | - {mode === 'variable' && ( | |
758 | - <ControlOutlined | |
759 | - onClick={() => { | |
760 | - setOpen(!open); | |
761 | - }} | |
762 | - className="qx-base-condition-item__content-suffix" | |
763 | - /> | |
764 | - )} | |
765 | 769 | </> |
766 | 770 | ); |
767 | 771 | |
... | ... | @@ -774,7 +778,7 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
774 | 778 | className="qx-base-condition-item__header-filter__select" |
775 | 779 | bordered={false} |
776 | 780 | fieldNames={{ label: 'text', value: 'key' }} |
777 | - options={ConditionCol[value.fieldGroupType]?.operations || []} | |
781 | + options={ConditionCol[fieldGroupType]?.operations || []} | |
778 | 782 | onChange={handleFilerChange} |
779 | 783 | /> |
780 | 784 | ); |
... | ... | @@ -788,10 +792,14 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
788 | 792 | <div className="qx-base-condition-item__header"> |
789 | 793 | <div className="qx-base-condition-item__header-left"> |
790 | 794 | <span className="qx-base-condition-item__header-icon"> |
791 | - <QxWidgetIcon widgetName={field?.extract?.widget} /> | |
795 | + {field.extract?.widget ? ( | |
796 | + <QxWidgetIcon widgetName={field.extract.widget} /> | |
797 | + ) : ( | |
798 | + `[${FieldMapType[field.extract.fieldType]}]` | |
799 | + )} | |
792 | 800 | </span> |
793 | 801 | <span className="qx-base-condition-item__header-text"> |
794 | - {field.fieldName} | |
802 | + {field.name} | |
795 | 803 | </span> |
796 | 804 | </div> |
797 | 805 | <div className="qx-base-condition-item__header-right"> |
... | ... | @@ -809,22 +817,18 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
809 | 817 | </div> |
810 | 818 | </div> |
811 | 819 | <div className="qx-base-condition-item__content"> |
812 | - {mode === 'variable' ? ( | |
813 | - <QxFlowNodeFieldSelector | |
814 | - mode={mode} | |
815 | - node={node!} | |
816 | - nodes={nodes!} | |
817 | - open={open} | |
818 | - value={valuesObj?.value} | |
819 | - onChange={handleAssignment} | |
820 | - limitTypes={[field.fieldType]} | |
821 | - subset={subset} | |
822 | - > | |
823 | - {RenderContent} | |
824 | - </QxFlowNodeFieldSelector> | |
825 | - ) : ( | |
826 | - RenderContent | |
827 | - )} | |
820 | + <QxFlowNodeFieldSelector | |
821 | + mode="variable" | |
822 | + node={node!} | |
823 | + nodes={nodes!} | |
824 | + open={open} | |
825 | + value={valuesObj?.value} | |
826 | + onChange={handleAssignment} | |
827 | + limitTypes={[field.extract?.fieldType]} | |
828 | + subset={subset} | |
829 | + > | |
830 | + {RenderContent} | |
831 | + </QxFlowNodeFieldSelector> | |
828 | 832 | </div> |
829 | 833 | </div> |
830 | 834 | ); |
... | ... | @@ -848,6 +852,6 @@ export interface QxBaseConditionItemProps { |
848 | 852 | mode?: string; |
849 | 853 | node?: INode; |
850 | 854 | nodes?: INode[]; |
851 | - [key: string]: any | |
855 | + [key: string]: any; | |
852 | 856 | // customDisplay?: (val: string) => React.ReactNode; |
853 | 857 | } | ... | ... |
1 | -import React, { useEffect, useState } from 'react'; | |
1 | +import React from 'react'; | |
2 | 2 | import { QxBaseConditionItem } from '../qx-base-condition-item'; |
3 | 3 | import { INode } from '../qx-flow-node-selector'; |
4 | 4 | import './index.less'; |
... | ... | @@ -11,42 +11,46 @@ const FieldBaseType = { |
11 | 11 | }; |
12 | 12 | |
13 | 13 | export const QxBaseCondition: React.FC<QxBaseConditionProps> = (props) => { |
14 | - const [localOptions, setLocalOptions] = useState(props.options || []); | |
14 | + // const [localOptions, setLocalOptions] = useState(props.value || props.options || []); | |
15 | 15 | |
16 | - const getDefaultConditionOptions = (item: QxBaseConditionField) => ({ | |
17 | - ...item, | |
18 | - fieldGroupType: | |
19 | - FieldBaseType[item.fieldType] || | |
20 | - item.fieldGroupType || | |
21 | - item.fieldType || | |
22 | - 'TEXT', | |
23 | - mappingValues: [], | |
24 | - opt: 'IS', | |
25 | - valuesObj: [], | |
26 | - }); | |
16 | + const getDefaultCondition = (item: QxBaseConditionField) => { | |
17 | + return { | |
18 | + type: item.extract?.fieldType, | |
19 | + code: item.code, | |
20 | + title: item.name, | |
21 | + opt: 'IS', | |
22 | + }; | |
23 | + }; | |
27 | 24 | |
28 | 25 | const handleItemChange = (val: any, key: number) => { |
29 | 26 | props.onChange?.( |
30 | - localOptions?.map((item, idx) => { | |
27 | + props.value?.map((item, idx) => { | |
31 | 28 | if (idx === key) return val; |
32 | 29 | return props.value?.[idx] |
33 | 30 | ? props.value?.[idx] |
34 | - : getDefaultConditionOptions(item); | |
31 | + : getDefaultCondition(item); | |
35 | 32 | }), |
36 | 33 | ); |
37 | 34 | }; |
38 | 35 | |
39 | 36 | const handleDelete = (key: number) => { |
40 | - localOptions.splice(key, 1); | |
41 | - setLocalOptions([...localOptions]); | |
42 | - props.onChange?.([...localOptions]); | |
37 | + if (props.value && Array.isArray(props.value)) { | |
38 | + props.value.splice(key, 1); | |
39 | + props.onChange?.([...props.value]); | |
40 | + } | |
43 | 41 | }; |
44 | 42 | |
45 | - useEffect(() => { | |
46 | - setLocalOptions(props.options); | |
47 | - }, [props.options]); | |
43 | + const getFieldGroupType = (fieldExtract: QxBaseConditionField['extract']) => { | |
44 | + return ( | |
45 | + fieldExtract?.fieldGroupType || | |
46 | + FieldBaseType[fieldExtract.fieldType] || | |
47 | + fieldExtract?.fieldType || | |
48 | + 'TEXT' | |
49 | + ); | |
50 | + }; | |
48 | 51 | |
49 | - const RenderCondition = localOptions?.map((item, key) => ( | |
52 | + | |
53 | + const RenderCondition = props.value?.map((item, key) => ( | |
50 | 54 | <div className="qx-base-condition-list-item" key={item.code || key}> |
51 | 55 | {(props?.showIdx ?? true) && ( |
52 | 56 | <span className="qx-base-condition-list-item__idx">{key + 1}.</span> |
... | ... | @@ -55,14 +59,14 @@ export const QxBaseCondition: React.FC<QxBaseConditionProps> = (props) => { |
55 | 59 | key={item.code || key} |
56 | 60 | mode={props.mode || 'condition'} |
57 | 61 | {...item} |
62 | + fieldGroupType={getFieldGroupType(item.field.extract)} | |
58 | 63 | value={Object.assign( |
59 | 64 | {}, |
60 | - getDefaultConditionOptions(item), | |
65 | + getDefaultCondition(item.field), | |
61 | 66 | props.value?.[key] || {}, |
62 | 67 | )} |
63 | 68 | nodes={props.nodes} |
64 | 69 | node={props.node} |
65 | - field={item} | |
66 | 70 | subset={props.subset} |
67 | 71 | onChange={(val) => handleItemChange(val, key)} |
68 | 72 | remove={() => handleDelete(key)} |
... | ... | @@ -77,14 +81,21 @@ export const QxBaseCondition: React.FC<QxBaseConditionProps> = (props) => { |
77 | 81 | ); |
78 | 82 | }; |
79 | 83 | |
80 | -export interface QxBaseConditionField { | |
81 | - field: string; | |
84 | +export interface QxBaseConditionFieldExtract { | |
85 | + widget: string; | |
86 | + $base?: boolean; | |
87 | + allowSelect?: boolean; | |
88 | + fieldKey: string; | |
82 | 89 | fieldType: keyof typeof FieldBaseType; |
83 | - fieldName: string; | |
84 | - fieldGroupType: string; | |
85 | - qxProps?: string; | |
86 | - extract: any; | |
87 | - params?: any | |
90 | + fieldGroupType?: string; | |
91 | + relId?: string; | |
92 | + [key: string]: any; | |
93 | +} | |
94 | + | |
95 | +export interface QxBaseConditionField { | |
96 | + name?: string; | |
97 | + code: string; | |
98 | + extract: QxBaseConditionFieldExtract; | |
88 | 99 | } |
89 | 100 | |
90 | 101 | export interface QxBaseConditionOptionsProps extends QxBaseConditionField { | ... | ... |
1 | -import { ControlOutlined } from '@ant-design/icons'; | |
2 | 1 | import { QxWidgetIcon } from '@qx/common'; |
3 | 2 | import { Collapse, Dropdown, Empty, Tag } from 'antd'; |
4 | 3 | import cls from 'classnames'; |
... | ... | @@ -50,7 +49,7 @@ export const getParentNodes = ( |
50 | 49 | return parentNode; |
51 | 50 | }; |
52 | 51 | |
53 | -export enum FileTypeMap { | |
52 | +export enum FieldMapType { | |
54 | 53 | 'STRING' = '文本', |
55 | 54 | 'NUMBER' = '数字', |
56 | 55 | 'BOOL' = '布尔', |
... | ... | @@ -164,9 +163,9 @@ export const useNodeFieldDisplay = ({ |
164 | 163 | )} |
165 | 164 | <span className="qx-node-select-input__content-item__text"> |
166 | 165 | {item.type && |
167 | - FileTypeMap[item.type] && | |
166 | + FieldMapType[item.type] && | |
168 | 167 | !item.icon && |
169 | - `[${FileTypeMap[item.type]}]`} | |
168 | + `[${FieldMapType[item.type]}]`} | |
170 | 169 | {item.title} |
171 | 170 | </span> |
172 | 171 | {idx !== displayConfig.length - 1 && ( |
... | ... | @@ -268,14 +267,42 @@ export const useNodeFieldDisplay = ({ |
268 | 267 | return sourceParentNodes; |
269 | 268 | }; |
270 | 269 | |
270 | + const correctionNodeField = (fields: FiledType[] | FiledType) => { | |
271 | + if (Array.isArray(fields)) { | |
272 | + for (let i = 0; i <= fields.length; i++) { | |
273 | + correctionNodeField(fields[i]); | |
274 | + } | |
275 | + } else if (fields) { | |
276 | + Object.assign(fields, { | |
277 | + ...fields, | |
278 | + name: fields.title, | |
279 | + extract: { | |
280 | + ...(fields.extract || {}), | |
281 | + fieldType: fields.type, | |
282 | + fieldKey: fields.code, | |
283 | + }, | |
284 | + child: correctionNodeField(fields.child!), | |
285 | + }); | |
286 | + } | |
287 | + | |
288 | + return fields; | |
289 | + }; | |
290 | + | |
271 | 291 | const getOptionalNodes = async () => { |
272 | 292 | const targetParentNodes = await handleGetAppsFields(); |
293 | + | |
294 | + for (let i = 0; i< targetParentNodes.length;i++) { | |
295 | + correctionNodeField(targetParentNodes[i].data?.result || []) | |
296 | + } | |
297 | + | |
273 | 298 | if (!limitTypes) return setOptionalNodes(targetParentNodes); |
274 | 299 | |
275 | 300 | function getEffectiveResult(result: FiledType[]) { |
276 | 301 | const newResult = []; |
277 | 302 | for (let i = 0; i < result.length; i++) { |
278 | - const resultItem = result[i] || {}; | |
303 | + const resultItem = result[i] || {}; | |
304 | + correctionNodeField(resultItem) | |
305 | + | |
279 | 306 | if (resultItem.child) { |
280 | 307 | resultItem.child = getEffectiveResult(resultItem.child); |
281 | 308 | if ( |
... | ... | @@ -333,8 +360,8 @@ const SelectItem = (props: any) => { |
333 | 360 | label: ( |
334 | 361 | <span> |
335 | 362 | {/* @ts-ignore */} |
336 | - {`[${FileTypeMap[props.type]}]`} | |
337 | - {props.title} | |
363 | + {`[${FieldMapType[props.extract?.fieldType]}]`} | |
364 | + {props.name} | |
338 | 365 | </span> |
339 | 366 | ), |
340 | 367 | key: props.id, |
... | ... | @@ -361,8 +388,8 @@ const SelectItem = (props: any) => { |
361 | 388 | onClick={() => props.onClick(props)} |
362 | 389 | > |
363 | 390 | {/* @ts-ignore */} |
364 | - {props.icon ? props.icon : `[${FileTypeMap[props.type]}]`} | |
365 | - {props.title} | |
391 | + {props.icon ? props.icon : `[${FieldMapType[props.extract?.fieldType]}]`} | |
392 | + {props.name} | |
366 | 393 | </div> |
367 | 394 | ); |
368 | 395 | } |
... | ... | @@ -377,8 +404,8 @@ const SelectItem = (props: any) => { |
377 | 404 | label: ( |
378 | 405 | <span> |
379 | 406 | {/* @ts-ignore */} |
380 | - {`[${FileTypeMap[props.type]}]`} | |
381 | - {props.title} | |
407 | + {`[${FieldMapType[props.extract?.fieldType]}]`} | |
408 | + {props.name} | |
382 | 409 | </span> |
383 | 410 | ), |
384 | 411 | key: props.id, |
... | ... | @@ -401,14 +428,13 @@ const SelectItem = (props: any) => { |
401 | 428 | export const QxFlowNodeFieldSelector: React.FC<NodeFieldSelectProps> = ( |
402 | 429 | props, |
403 | 430 | ) => { |
404 | - const { mode = 'select' } = props; | |
405 | - | |
406 | 431 | const [visible, setVisible] = useState(false); |
407 | 432 | |
408 | 433 | const { optionalNodes, renderInputDisplay, inputDisplay } = |
409 | 434 | useNodeFieldDisplay(props); |
410 | 435 | |
411 | 436 | const getOptions = () => { |
437 | + console.log('optionalNodes', optionalNodes); | |
412 | 438 | return optionalNodes.map((node) => ({ |
413 | 439 | label: ( |
414 | 440 | <div className={cls('qx-node-select-dropdown-header')}> |
... | ... | @@ -468,7 +494,7 @@ export const QxFlowNodeFieldSelector: React.FC<NodeFieldSelectProps> = ( |
468 | 494 | open={visible} |
469 | 495 | dropdownRender={dropdownRender} |
470 | 496 | onOpenChange={(open) => { |
471 | - if (mode === 'select') { | |
497 | + if (props.children) { | |
472 | 498 | setVisible(open); |
473 | 499 | } |
474 | 500 | }} |
... | ... | @@ -476,16 +502,11 @@ export const QxFlowNodeFieldSelector: React.FC<NodeFieldSelectProps> = ( |
476 | 502 | {props.children ? ( |
477 | 503 | props.children |
478 | 504 | ) : ( |
479 | - <div className={cls('qx-node-select-input')}> | |
505 | + <div | |
506 | + className={cls('qx-node-select-input')} | |
507 | + onClick={() => setVisible(!visible)} | |
508 | + > | |
480 | 509 | {inputDisplay} |
481 | - {mode === 'variable' && ( | |
482 | - <span | |
483 | - className="qx-node-select-input__suffix" | |
484 | - onClick={() => setVisible(!visible)} | |
485 | - > | |
486 | - <ControlOutlined /> | |
487 | - </span> | |
488 | - )} | |
489 | 510 | </div> |
490 | 511 | )} |
491 | 512 | </Dropdown> | ... | ... |