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> | ... | ... |