Commit 04129d565215a68f370e114fd2b5491455fccd46
Merge remote-tracking branch 'origin/feature/dataflow' into feature/dataflow
Showing
11 changed files
with
917 additions
and
180 deletions
| ... | ... | @@ -53,16 +53,10 @@ |
| 53 | 53 | color: @N7; |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | - &-value-render { | |
| 57 | - position: absolute; | |
| 58 | - background-color: #fff; | |
| 59 | - width: calc(100% - 33px); | |
| 60 | - height: 30px; | |
| 61 | - display: flex; | |
| 62 | - align-items: center; | |
| 63 | - top: 1px; | |
| 64 | - left: 8px; | |
| 65 | - z-index: 1; | |
| 56 | + .qx-field-setter { | |
| 57 | + .ant-tag { | |
| 58 | + display: flex; | |
| 59 | + } | |
| 66 | 60 | } |
| 67 | 61 | } |
| 68 | 62 | ... | ... |
| 1 | 1 | import { ControlOutlined } from '@ant-design/icons'; |
| 2 | -import { Select, Tooltip, Input } from 'antd'; | |
| 2 | +import { Select, Tooltip } from 'antd'; | |
| 3 | 3 | import { size } from 'lodash-es'; |
| 4 | 4 | import React, { useState } from 'react'; |
| 5 | 5 | import type { QxBaseConditionField } from '../qx-base-condition'; |
| 6 | 6 | import { QxBaseIcon } from '../qx-base-icon'; |
| 7 | 7 | import { QxFieldSetter } from '../qx-field-setter'; |
| 8 | +import type { INode } from '../qx-flow-node-selector'; | |
| 9 | +import { | |
| 10 | + QxFlowNodeFieldSelector, | |
| 11 | + useNodeFieldDisplay, | |
| 12 | +} from '../qx-flow-node-selector'; | |
| 13 | +import { QxWidgetIcon } from '../qx-widget-icon'; | |
| 8 | 14 | |
| 9 | 15 | import './index.less'; |
| 10 | 16 | |
| ... | ... | @@ -666,147 +672,22 @@ const optValTypeCheck = { |
| 666 | 672 | }, |
| 667 | 673 | }; |
| 668 | 674 | |
| 669 | -export const WidgetsIcon = ({ widgetName }: { widgetName: string }) => { | |
| 670 | - let iconType: string = ''; | |
| 671 | - switch (widgetName) { | |
| 672 | - case 'qxInput': | |
| 673 | - iconType = 'icon-field-text'; | |
| 674 | - break; | |
| 675 | - case 'qxNumber': | |
| 676 | - iconType = 'icon-field-num'; | |
| 677 | - break; | |
| 678 | - case 'dateTime': | |
| 679 | - case 'qxDatetime': | |
| 680 | - iconType = 'icon-field-datetime'; | |
| 681 | - break; | |
| 682 | - case 'qxTime': | |
| 683 | - iconType = 'icon-field-time'; | |
| 684 | - break; | |
| 685 | - case 'qxSwitch': | |
| 686 | - iconType = 'icon-field-boolean'; | |
| 687 | - break; | |
| 688 | - case 'qxSelect': | |
| 689 | - iconType = 'icon-field-select'; | |
| 690 | - break; | |
| 691 | - case 'qxMultiSelect': | |
| 692 | - iconType = 'icon-field-multi-select'; | |
| 693 | - break; | |
| 694 | - case 'qxMobile': | |
| 695 | - iconType = 'icon-field-mobile'; | |
| 696 | - break; | |
| 697 | - case 'qxMoney': | |
| 698 | - iconType = 'icon-field-finance'; | |
| 699 | - break; | |
| 700 | - case 'qxEmail': | |
| 701 | - iconType = 'icon-field-email'; | |
| 702 | - break; | |
| 703 | - case 'qxPercent': | |
| 704 | - iconType = 'icon-field-percent'; | |
| 705 | - break; | |
| 706 | - case 'qxUpload': | |
| 707 | - iconType = 'icon-field-file'; | |
| 708 | - break; | |
| 709 | - case 'qxUploadImage': | |
| 710 | - iconType = 'icon-field-img'; | |
| 711 | - break; | |
| 712 | - case 'qxAddress': | |
| 713 | - iconType = 'icon-field-address'; | |
| 714 | - break; | |
| 715 | - case 'qxRichText': | |
| 716 | - iconType = 'icon-field-richtext'; | |
| 717 | - break; | |
| 718 | - case 'qxLocation': | |
| 719 | - iconType = 'icon-field-location'; | |
| 720 | - break; | |
| 721 | - case 'orgSelector': | |
| 722 | - iconType = 'icon-field-department'; | |
| 723 | - break; | |
| 724 | - case 'userSelector': | |
| 725 | - iconType = 'icon-field-user'; | |
| 726 | - break; | |
| 727 | - case 'createdBy': | |
| 728 | - case 'created_by': | |
| 729 | - iconType = 'icon-field-created-by'; | |
| 730 | - break; | |
| 731 | - case 'createdAt': | |
| 732 | - case 'created_at': | |
| 733 | - iconType = 'icon-field-created-at'; | |
| 734 | - break; | |
| 735 | - case 'updatedBy': | |
| 736 | - case 'updated_by': | |
| 737 | - iconType = 'icon-field-updated-by'; | |
| 738 | - break; | |
| 739 | - case 'updatedAt': | |
| 740 | - case 'updated_at': | |
| 741 | - iconType = 'icon-field-updated-at'; | |
| 742 | - break; | |
| 743 | - case 'qxBizNo': | |
| 744 | - iconType = 'icon-field-no'; | |
| 745 | - break; | |
| 746 | - case 'relSelector': | |
| 747 | - iconType = 'icon-field-rel'; | |
| 748 | - break; | |
| 749 | - case 'relField': | |
| 750 | - iconType = 'icon-field-ref'; | |
| 751 | - break; | |
| 752 | - case 'subform': | |
| 753 | - case 'table': | |
| 754 | - iconType = 'icon-field-subform'; | |
| 755 | - break; | |
| 756 | - case 'qxTree': | |
| 757 | - iconType = 'icon-field-tree'; | |
| 758 | - break; | |
| 759 | - case 'qxFormula': | |
| 760 | - iconType = 'icon-field-formula'; | |
| 761 | - break; | |
| 762 | - case 'qxDivider': | |
| 763 | - iconType = 'icon-field-divider'; | |
| 764 | - break; | |
| 765 | - case 'qxRemark': | |
| 766 | - iconType = 'icon-field-remark'; | |
| 767 | - break; | |
| 768 | - case 'qxEmbed': | |
| 769 | - iconType = 'icon-field-embed '; | |
| 770 | - break; | |
| 771 | - case 'qxTabs': | |
| 772 | - iconType = 'icon-editor_tab'; | |
| 773 | - break; | |
| 774 | - case 'qxLayout': | |
| 775 | - iconType = 'icon-editor_grid'; | |
| 776 | - break; | |
| 777 | - case 'simple': | |
| 778 | - iconType = 'icon-editor_layout'; | |
| 779 | - break; | |
| 780 | - case 'tabC': | |
| 781 | - iconType = 'icon-editor_tab'; | |
| 782 | - break; | |
| 783 | - case 'layout': | |
| 784 | - iconType = 'icon-editor_grid'; | |
| 785 | - break; | |
| 786 | - default: | |
| 787 | - iconType = 'icon-field-text'; | |
| 788 | - break; | |
| 789 | - } | |
| 790 | - return <QxBaseIcon type={iconType} />; | |
| 791 | -}; | |
| 792 | - | |
| 793 | 675 | export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
| 794 | 676 | value, |
| 795 | 677 | field, |
| 796 | 678 | remove, |
| 797 | 679 | onChange, |
| 798 | 680 | mode = 'condition', |
| 799 | - ValueAssignmentPopup, | |
| 681 | + node, | |
| 682 | + nodes, | |
| 800 | 683 | }) => { |
| 801 | - const [CustomValueRender, setCustomValueRender] = | |
| 802 | - useState<() => React.ReactNode>(); | |
| 803 | - | |
| 684 | + const valuesObj = value?.valuesObj?.[0] || {}; | |
| 804 | 685 | const [open, setOpen] = useState(false); |
| 805 | 686 | |
| 806 | - const handleChange = (val: any) => { | |
| 687 | + const handleChange = (val: any[]) => { | |
| 807 | 688 | onChange?.({ |
| 808 | 689 | ...(value || {}), |
| 809 | - mappingValues: val?.map((i: any) => i.value), | |
| 690 | + mappingValues: val?.length ? val?.map((i: any) => i.value) : [], | |
| 810 | 691 | valuesObj: val, |
| 811 | 692 | }); |
| 812 | 693 | }; |
| ... | ... | @@ -841,23 +722,23 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
| 841 | 722 | onChange?.(newValue); |
| 842 | 723 | }; |
| 843 | 724 | |
| 844 | - const handleDefaultValueSettingChange = ( | |
| 845 | - val: any, | |
| 846 | - valueRender: () => React.ReactNode, | |
| 847 | - ) => { | |
| 848 | - handleChange(val); | |
| 849 | - setCustomValueRender(() => valueRender); | |
| 725 | + const handleAssignment = (value: string) => { | |
| 726 | + handleChange([{ type: 'FIELD', value }]); | |
| 727 | + setOpen(false); | |
| 850 | 728 | }; |
| 851 | 729 | |
| 852 | - const handleOpenChange = setOpen; | |
| 730 | + const { genDisplayDom } = useNodeFieldDisplay({ | |
| 731 | + node: node, | |
| 732 | + nodes: nodes, | |
| 733 | + limitTypes: [field.fieldType], | |
| 734 | + }); | |
| 735 | + | |
| 736 | + const getName = (values: any[]) => { | |
| 737 | + return values.map((value) => genDisplayDom(value)) | |
| 738 | + } | |
| 853 | 739 | |
| 854 | 740 | const RenderContent = ( |
| 855 | 741 | <> |
| 856 | - {typeof CustomValueRender === 'function' && ( | |
| 857 | - <div className="qx-base-condition-item__content-value-render"> | |
| 858 | - {CustomValueRender()} | |
| 859 | - </div> | |
| 860 | - )} | |
| 861 | 742 | <QxFieldSetter |
| 862 | 743 | value={value?.valuesObj} |
| 863 | 744 | fieldGroupType={value?.fieldGroupType} |
| ... | ... | @@ -865,11 +746,12 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
| 865 | 746 | isMultiple={multipleType.includes(value?.fieldGroupType)} |
| 866 | 747 | isRange={optValTypeCheck.isRangeType(value?.opt)} |
| 867 | 748 | disabled={optValTypeCheck.isEmptyType(value?.opt)} |
| 749 | + getName={getName} | |
| 868 | 750 | /> |
| 869 | - {typeof ValueAssignmentPopup !== 'undefined' && ( | |
| 751 | + {mode === 'variable' && ( | |
| 870 | 752 | <ControlOutlined |
| 871 | 753 | onClick={() => { |
| 872 | - handleOpenChange(!open); | |
| 754 | + setOpen(!open); | |
| 873 | 755 | }} |
| 874 | 756 | className="qx-base-condition-item__content-suffix" |
| 875 | 757 | /> |
| ... | ... | @@ -900,7 +782,7 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
| 900 | 782 | <div className="qx-base-condition-item__header"> |
| 901 | 783 | <div className="qx-base-condition-item__header-left"> |
| 902 | 784 | <span className="qx-base-condition-item__header-icon"> |
| 903 | - <WidgetsIcon widgetName={field?.extract?.widget} /> | |
| 785 | + <QxWidgetIcon widgetName={field?.extract?.widget} /> | |
| 904 | 786 | </span> |
| 905 | 787 | <span className="qx-base-condition-item__header-text"> |
| 906 | 788 | {field.fieldName} |
| ... | ... | @@ -921,16 +803,18 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
| 921 | 803 | </div> |
| 922 | 804 | </div> |
| 923 | 805 | <div className="qx-base-condition-item__content"> |
| 924 | - {typeof ValueAssignmentPopup !== 'undefined' ? ( | |
| 925 | - <ValueAssignmentPopup | |
| 806 | + {mode === 'variable' ? ( | |
| 807 | + <QxFlowNodeFieldSelector | |
| 808 | + mode={mode} | |
| 809 | + node={node!} | |
| 810 | + nodes={nodes!} | |
| 926 | 811 | open={open} |
| 927 | - value={value} | |
| 928 | - field={field} | |
| 929 | - onChange={handleDefaultValueSettingChange} | |
| 930 | - onOpenChange={handleOpenChange} | |
| 812 | + value={valuesObj?.value} | |
| 813 | + onChange={handleAssignment} | |
| 814 | + limitTypes={[field.fieldType]} | |
| 931 | 815 | > |
| 932 | 816 | {RenderContent} |
| 933 | - </ValueAssignmentPopup> | |
| 817 | + </QxFlowNodeFieldSelector> | |
| 934 | 818 | ) : ( |
| 935 | 819 | RenderContent |
| 936 | 820 | )} |
| ... | ... | @@ -942,9 +826,10 @@ export const QxBaseConditionItem: React.FC<QxBaseConditionItemProps> = ({ |
| 942 | 826 | export interface ValueAssignmentPopupProps |
| 943 | 827 | extends Omit<QxBaseConditionItemProps, 'onChange'> { |
| 944 | 828 | children?: React.ReactNode; |
| 945 | - onChange?: (val: any, valueRender: () => React.ReactNode) => void; | |
| 829 | + onChange?: (val: any) => void; | |
| 946 | 830 | open?: boolean; |
| 947 | 831 | onOpenChange?: (open: boolean) => void; |
| 832 | + onClear?: () => void; | |
| 948 | 833 | } |
| 949 | 834 | |
| 950 | 835 | export interface QxBaseConditionItemProps { |
| ... | ... | @@ -952,6 +837,9 @@ export interface QxBaseConditionItemProps { |
| 952 | 837 | value?: any; |
| 953 | 838 | onChange?: (val: any) => void; |
| 954 | 839 | remove?: (field: QxBaseConditionField) => void; |
| 955 | - ValueAssignmentPopup?: React.FC<ValueAssignmentPopupProps>; | |
| 840 | + ValueAssignment?: React.FC<ValueAssignmentPopupProps>; | |
| 956 | 841 | mode?: string; |
| 842 | + node?: INode; | |
| 843 | + nodes?: INode[]; | |
| 844 | + // customDisplay?: (val: string) => React.ReactNode; | |
| 957 | 845 | } | ... | ... |
| 1 | 1 | import React, { useEffect, useState } from 'react'; |
| 2 | -import type { ValueAssignmentPopupProps } from '../qx-base-condition-item'; | |
| 3 | 2 | import { QxBaseConditionItem } from '../qx-base-condition-item'; |
| 4 | 3 | import './index.less'; |
| 4 | +import { INode } from '../qx-flow-node-selector'; | |
| 5 | 5 | |
| 6 | 6 | export enum FieldBaseType { |
| 7 | 7 | STRING = 'TEXT', |
| ... | ... | @@ -9,9 +9,8 @@ export enum FieldBaseType { |
| 9 | 9 | YEAR_SEC = 'DATE', |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | - | |
| 13 | 12 | export const QxBaseCondition: React.FC<QxBaseConditionProps> = (props) => { |
| 14 | - const [localOptions, setLocalOptions] = useState(props.value || props.options || []); | |
| 13 | + const [localOptions, setLocalOptions] = useState(props.options || []); | |
| 15 | 14 | |
| 16 | 15 | const getDefaultConditionOptions = (item: QxBaseConditionField) => ({ |
| 17 | 16 | ...item, |
| ... | ... | @@ -36,7 +35,7 @@ export const QxBaseCondition: React.FC<QxBaseConditionProps> = (props) => { |
| 36 | 35 | const handleDelete = (key: number) => { |
| 37 | 36 | localOptions.splice(key, 1); |
| 38 | 37 | setLocalOptions([...localOptions]); |
| 39 | - props.onChange?.([...localOptions]) | |
| 38 | + props.onChange?.([...localOptions]); | |
| 40 | 39 | }; |
| 41 | 40 | |
| 42 | 41 | useEffect(() => { |
| ... | ... | @@ -52,13 +51,16 @@ export const QxBaseCondition: React.FC<QxBaseConditionProps> = (props) => { |
| 52 | 51 | key={item.code || key} |
| 53 | 52 | mode={props.mode} |
| 54 | 53 | {...item} |
| 55 | - value={props.value?.[key] || getDefaultConditionOptions(item)} | |
| 54 | + value={Object.assign( | |
| 55 | + {}, | |
| 56 | + getDefaultConditionOptions(item), | |
| 57 | + props.value?.[key] || {}, | |
| 58 | + )} | |
| 59 | + nodes={props.nodes} | |
| 60 | + node={props.node} | |
| 56 | 61 | field={item} |
| 57 | 62 | onChange={(val) => handleItemChange(val, key)} |
| 58 | 63 | remove={() => handleDelete(key)} |
| 59 | - ValueAssignmentPopup={ | |
| 60 | - (item.showValueAssignmentPopup ?? true) ? props.ValueAssignmentPopup : undefined | |
| 61 | - } | |
| 62 | 64 | /> |
| 63 | 65 | </div> |
| 64 | 66 | )); |
| ... | ... | @@ -80,13 +82,13 @@ export interface QxBaseConditionField { |
| 80 | 82 | } |
| 81 | 83 | |
| 82 | 84 | export interface QxBaseConditionOptionsProps extends QxBaseConditionField { |
| 83 | - showValueAssignmentPopup?: boolean; | |
| 85 | + showValueAssignment?: boolean; | |
| 84 | 86 | isMultiple?: boolean; |
| 85 | 87 | isRange?: boolean; |
| 86 | 88 | [key: string]: any; |
| 87 | 89 | } |
| 88 | 90 | |
| 89 | -export type QxBaseConditionMode = 'condition' | 'variable' | |
| 91 | +export type QxBaseConditionMode = 'condition' | 'variable'; | |
| 90 | 92 | |
| 91 | 93 | export interface QxBaseConditionProps { |
| 92 | 94 | showIdx?: boolean; |
| ... | ... | @@ -94,5 +96,6 @@ export interface QxBaseConditionProps { |
| 94 | 96 | options: QxBaseConditionOptionsProps[]; |
| 95 | 97 | value: any[]; |
| 96 | 98 | onChange?: (val: any[]) => void; |
| 97 | - ValueAssignmentPopup?: React.FC<ValueAssignmentPopupProps>; | |
| 99 | + nodes?: INode[] | |
| 100 | + node?: INode | |
| 98 | 101 | } | ... | ... |
| ... | ... | @@ -156,6 +156,7 @@ export interface paramColSelectProps extends ColSelectProps { |
| 156 | 156 | iconText?: string; // Popover-icon 自定义 后面跟随文本 |
| 157 | 157 | allowClear?: boolean; |
| 158 | 158 | popupOnBody?: boolean; // 下拉 跟随 body 还是自身 |
| 159 | + getName?: (val: any) => void | |
| 159 | 160 | } |
| 160 | 161 | |
| 161 | 162 | export const QxFieldSetter: React.FC<paramColSelectProps> = ({ |
| ... | ... | @@ -355,7 +356,7 @@ export const QxFieldSetter: React.FC<paramColSelectProps> = ({ |
| 355 | 356 | * @param str 字符串形式 |
| 356 | 357 | * @param joinParent 拼接父节点 |
| 357 | 358 | */ |
| 358 | - const getName = (val: string[], str?: boolean, joinParent?: boolean) => { | |
| 359 | + const getName = props?.getName || ((val: string[], str?: boolean, joinParent?: boolean) => { | |
| 359 | 360 | const name: any[] = []; |
| 360 | 361 | let flag: boolean = false; |
| 361 | 362 | (colsTree || []).map((tree) => { |
| ... | ... | @@ -440,7 +441,7 @@ export const QxFieldSetter: React.FC<paramColSelectProps> = ({ |
| 440 | 441 | } else { |
| 441 | 442 | return flag ? name : val; |
| 442 | 443 | } |
| 443 | - }; | |
| 444 | + }); | |
| 444 | 445 | |
| 445 | 446 | /** |
| 446 | 447 | * 名称转换 | ... | ... |
| ... | ... | @@ -41,7 +41,9 @@ export default () => { |
| 41 | 41 | hideCurrentOrg={true} |
| 42 | 42 | hideCurrentUser={true} |
| 43 | 43 | isMixValue={false} |
| 44 | - onChange={() => {}} | |
| 44 | + onChange={(val) => { | |
| 45 | + console.log(222222,val) | |
| 46 | + }} | |
| 45 | 47 | tableFields={optionsList} |
| 46 | 48 | params={{ funCoded: 'cjQhMZnwkO2QoVzxVPC', useId: true }} |
| 47 | 49 | value={{ | ... | ... |
src/qx-flow-node-selector/index.less
0 → 100644
| 1 | +@import '~@qx/ui/src/style/variable.less'; | |
| 2 | + | |
| 3 | +@ant-prefix-cls: ~'ant'; | |
| 4 | + | |
| 5 | +.qx-node-select { | |
| 6 | + &-dropdown { | |
| 7 | + max-height: calc(8 * 32px); | |
| 8 | + overflow: auto; | |
| 9 | + background-color: white; | |
| 10 | + box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), | |
| 11 | + 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05); | |
| 12 | + border-radius: 8px; | |
| 13 | + | |
| 14 | + &-header { | |
| 15 | + display: flex; | |
| 16 | + align-items: center; | |
| 17 | + &__icon { | |
| 18 | + width: 14px; | |
| 19 | + height: 14px; | |
| 20 | + font-size: 14px; | |
| 21 | + line-height: 14px; | |
| 22 | + // color: @N7; | |
| 23 | + margin-right: 4px; | |
| 24 | + display: inline-block; | |
| 25 | + border-radius: 50%; | |
| 26 | + overflow: hidden; | |
| 27 | + // border: 1px solid @N6; | |
| 28 | + display: flex; | |
| 29 | + align-items: center; | |
| 30 | + justify-content: center; | |
| 31 | + | |
| 32 | + > img { | |
| 33 | + width: 14px; | |
| 34 | + height: 14px; | |
| 35 | + } | |
| 36 | + } | |
| 37 | + } | |
| 38 | + | |
| 39 | + .qx-node-select-item__icon { | |
| 40 | + margin-right: 4px; | |
| 41 | + } | |
| 42 | + | |
| 43 | + .@{ant-prefix-cls}-collapse-header, | |
| 44 | + .@{ant-prefix-cls}-collapse-content { | |
| 45 | + padding: 7px !important; | |
| 46 | + font-size: 14px; | |
| 47 | + } | |
| 48 | + | |
| 49 | + .@{ant-prefix-cls}-collapse-content { | |
| 50 | + background-color: @N3 !important; | |
| 51 | + padding: 0 !important; | |
| 52 | + | |
| 53 | + &-box { | |
| 54 | + padding: 0 !important; | |
| 55 | + } | |
| 56 | + } | |
| 57 | + } | |
| 58 | + | |
| 59 | + &-item { | |
| 60 | + width: 100%; | |
| 61 | + padding: 7px 16px 7px 32px !important; | |
| 62 | + &:hover { | |
| 63 | + background-color: @N4; | |
| 64 | + cursor: pointer; | |
| 65 | + } | |
| 66 | + | |
| 67 | + &__group { | |
| 68 | + padding: 0 0 0px 32px !important; | |
| 69 | + | |
| 70 | + &:hover { | |
| 71 | + background-color: transparent; | |
| 72 | + } | |
| 73 | + .@{ant-prefix-cls}-collapse-header { | |
| 74 | + padding: 7px 0 !important; | |
| 75 | + } | |
| 76 | + } | |
| 77 | + } | |
| 78 | + | |
| 79 | + &-input { | |
| 80 | + box-sizing: border-box; | |
| 81 | + margin: 0; | |
| 82 | + font-variant: tabular-nums; | |
| 83 | + list-style: none; | |
| 84 | + font-feature-settings: 'tnum', 'tnum'; | |
| 85 | + position: relative; | |
| 86 | + display: inline-block; | |
| 87 | + width: 100%; | |
| 88 | + height: 32px; | |
| 89 | + min-width: 0; | |
| 90 | + padding: 4px 32px 4px 4px; | |
| 91 | + color: rgba(0, 0, 0, 0.85); | |
| 92 | + font-size: 14px; | |
| 93 | + line-height: 1.5715; | |
| 94 | + background-color: #fff; | |
| 95 | + background-image: none; | |
| 96 | + border: 1px solid #d9d9d9; | |
| 97 | + border-radius: 4px; | |
| 98 | + transition: all 0.3s; | |
| 99 | + | |
| 100 | + &:hover { | |
| 101 | + border-color: @B8; | |
| 102 | + } | |
| 103 | + | |
| 104 | + &__content { | |
| 105 | + display: inline-flex; | |
| 106 | + color: @N9; | |
| 107 | + font-size: 14px; | |
| 108 | + | |
| 109 | + &-item { | |
| 110 | + margin-right: 4px; | |
| 111 | + display: flex; | |
| 112 | + align-items: center; | |
| 113 | + | |
| 114 | + &__icon { | |
| 115 | + width: 14px; | |
| 116 | + height: 14px; | |
| 117 | + font-size: 14px; | |
| 118 | + line-height: 14px; | |
| 119 | + // color: @N7; | |
| 120 | + margin-right: 4px; | |
| 121 | + display: inline-block; | |
| 122 | + border-radius: 50%; | |
| 123 | + // overflow: hidden; | |
| 124 | + // border: 1px solid @N6; | |
| 125 | + display: flex; | |
| 126 | + align-items: center; | |
| 127 | + justify-content: center; | |
| 128 | + | |
| 129 | + > img { | |
| 130 | + width: inherit; | |
| 131 | + height: inherit; | |
| 132 | + } | |
| 133 | + } | |
| 134 | + | |
| 135 | + &__arrow { | |
| 136 | + display: inline-flex; | |
| 137 | + align-items: center; | |
| 138 | + color: @N6; | |
| 139 | + } | |
| 140 | + } | |
| 141 | + } | |
| 142 | + | |
| 143 | + &__suffix { | |
| 144 | + position: absolute; | |
| 145 | + right: 10px; | |
| 146 | + top: 50%; | |
| 147 | + transform: translateY(-50%); | |
| 148 | + } | |
| 149 | + } | |
| 150 | +} | |
| 151 | + | |
| 152 | +.qx-node-select-dropdown { | |
| 153 | + > .@{ant-prefix-cls}-collapse { | |
| 154 | + > .@{ant-prefix-cls}-collapse-item { | |
| 155 | + > .@{ant-prefix-cls}-collapse-content { | |
| 156 | + padding-right: 7px !important; | |
| 157 | + } | |
| 158 | + } | |
| 159 | + } | |
| 160 | +} | ... | ... |
src/qx-flow-node-selector/index.tsx
0 → 100644
| 1 | +import { ControlOutlined } from '@ant-design/icons'; | |
| 2 | +import { QxWidgetIcon } from '@qx/common'; | |
| 3 | +import { Collapse, Dropdown, Empty, Tag } from 'antd'; | |
| 4 | +import cls from 'classnames'; | |
| 5 | +import { cloneDeep } from 'lodash-es'; | |
| 6 | +import React, { useEffect, useMemo, useState } from 'react'; | |
| 7 | +import { QxBaseIcon } from '../qx-base-icon'; | |
| 8 | +import { request } from '../utils'; | |
| 9 | +import './index.less'; | |
| 10 | +// import type { FiledType } from '@/interface'; | |
| 11 | +// import type { INode } from '@qx/flow'; | |
| 12 | + | |
| 13 | +const getAppsFields = (params: string[], appId = 'default') => { | |
| 14 | + return request.post(`/qx-apaas-lowcode/app/${appId}/fields`, { | |
| 15 | + data: params, | |
| 16 | + }); | |
| 17 | +}; | |
| 18 | + | |
| 19 | +export const getNodesMap = ( | |
| 20 | + nodes: INode[], | |
| 21 | + map: Record<string, INode> = {}, | |
| 22 | +) => { | |
| 23 | + if (!nodes) return {}; | |
| 24 | + for (let i = 0; i < nodes.length; i++) { | |
| 25 | + const node = nodes[i]; | |
| 26 | + if (!map[node.id]) { | |
| 27 | + map[node.id] = node; | |
| 28 | + } | |
| 29 | + | |
| 30 | + if (node.children && Array.isArray(node.children)) { | |
| 31 | + getNodesMap(node.children, map); | |
| 32 | + } | |
| 33 | + } | |
| 34 | + | |
| 35 | + return map; | |
| 36 | +}; | |
| 37 | + | |
| 38 | +export const getParentNodes = ( | |
| 39 | + node?: INode, | |
| 40 | + treeNodes?: INode[], | |
| 41 | + parentNode: INode[] = [], | |
| 42 | + allNodes = getNodesMap(treeNodes!), | |
| 43 | +) => { | |
| 44 | + if (!node || !treeNodes) return []; | |
| 45 | + if (node.previousId) { | |
| 46 | + parentNode.push(allNodes[node.previousId]); | |
| 47 | + getParentNodes(allNodes[node.previousId], treeNodes, parentNode, allNodes); | |
| 48 | + } | |
| 49 | + | |
| 50 | + return parentNode; | |
| 51 | +}; | |
| 52 | + | |
| 53 | +export enum FileTypeMap { | |
| 54 | + 'STRING' = '文本', | |
| 55 | + 'NUMBER' = '数字', | |
| 56 | + 'BOOL' = '布尔', | |
| 57 | + 'TIME' = '日期', | |
| 58 | + 'OBJECT' = '对象', | |
| 59 | + 'ARRAY' = '数组', | |
| 60 | + 'FORM' = '表单', | |
| 61 | + 'USER' = '人员', | |
| 62 | + 'ORG' = '部门', | |
| 63 | + 'FILE' = '文件', | |
| 64 | + 'PIC' = '图片', | |
| 65 | +} | |
| 66 | + | |
| 67 | +interface NodeFieldDisPlay { | |
| 68 | + node?: INode; | |
| 69 | + nodes?: INode[]; | |
| 70 | + limitTypes?: string[]; | |
| 71 | +} | |
| 72 | + | |
| 73 | +const icon = (icon: any) => { | |
| 74 | + if (icon?.$$typeof) { | |
| 75 | + return icon; | |
| 76 | + } | |
| 77 | + if (typeof icon !== 'string' && icon) { | |
| 78 | + return <QxBaseIcon type={icon.props.type} />; | |
| 79 | + } | |
| 80 | + | |
| 81 | + return <img src={icon} />; | |
| 82 | +}; | |
| 83 | + | |
| 84 | +export const useNodeFieldDisplay = ({ | |
| 85 | + node, | |
| 86 | + nodes, | |
| 87 | + limitTypes, | |
| 88 | +}: NodeFieldDisPlay) => { | |
| 89 | + const sourceParentNodes = | |
| 90 | + getParentNodes(node, nodes).filter( | |
| 91 | + (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 | + } | |
| 131 | + | |
| 132 | + return getEffectiveNodes(targetParentNodes); | |
| 133 | + }, [limitTypes, sourceParentNodes]); | |
| 134 | + | |
| 135 | + const getId = (val?: string) => { | |
| 136 | + if (!val) return; | |
| 137 | + const startIndex = val.indexOf('|') + 1; | |
| 138 | + const endIndex = val.indexOf('}'); | |
| 139 | + if (startIndex < endIndex) { | |
| 140 | + return val.substring(startIndex, endIndex); | |
| 141 | + } | |
| 142 | + return null; | |
| 143 | + }; | |
| 144 | + | |
| 145 | + const genDisplayDom = (value: string) => { | |
| 146 | + const itemId = getId(value); | |
| 147 | + if (!itemId) return; | |
| 148 | + let displayConfig: any[] = []; | |
| 149 | + let n = true; | |
| 150 | + let index = 0; | |
| 151 | + while (n && index <= 20) { | |
| 152 | + displayConfig = []; | |
| 153 | + const curNode = optionalNodes[index] || {}; | |
| 154 | + displayConfig.push({ | |
| 155 | + title: curNode.name, | |
| 156 | + icon: curNode.icon, | |
| 157 | + ...(optionalNodes[index] || {}), | |
| 158 | + }); | |
| 159 | + // eslint-disable-next-line @typescript-eslint/no-use-before-define | |
| 160 | + recursionNodeResult(curNode.data?.result); | |
| 161 | + index++; | |
| 162 | + } | |
| 163 | + | |
| 164 | + function recursionNodeResult(result: FiledType[], idx = 1) { | |
| 165 | + if (Array.isArray(result)) { | |
| 166 | + for (let i = 0; i < result.length; i++) { | |
| 167 | + const item = result[i]; | |
| 168 | + if (!n) return; | |
| 169 | + | |
| 170 | + displayConfig.splice(idx, 1, item); | |
| 171 | + displayConfig = displayConfig.slice(0, idx + 1); | |
| 172 | + | |
| 173 | + if (itemId === item.id) { | |
| 174 | + n = false; | |
| 175 | + return; | |
| 176 | + } | |
| 177 | + | |
| 178 | + if (Array.isArray(item.child)) { | |
| 179 | + recursionNodeResult(item.child, idx + 1); | |
| 180 | + } | |
| 181 | + } | |
| 182 | + } else { | |
| 183 | + n = false; | |
| 184 | + } | |
| 185 | + } | |
| 186 | + | |
| 187 | + return ( | |
| 188 | + <> | |
| 189 | + {displayConfig?.map((item, idx) => ( | |
| 190 | + <div | |
| 191 | + key={idx} | |
| 192 | + className='qx-node-select-input__content-item' | |
| 193 | + > | |
| 194 | + {item.icon && ( | |
| 195 | + <span | |
| 196 | + className='qx-node-select-input__content-item__icon' | |
| 197 | + > | |
| 198 | + {icon(item.icon)} | |
| 199 | + </span> | |
| 200 | + )} | |
| 201 | + <span | |
| 202 | + className='qx-node-select-input__content-item__text' | |
| 203 | + > | |
| 204 | + {item.type && | |
| 205 | + FileTypeMap[item.type] && | |
| 206 | + !item.icon && | |
| 207 | + `[${FileTypeMap[item.type]}]`} | |
| 208 | + {item.title} | |
| 209 | + </span> | |
| 210 | + {idx !== displayConfig.length - 1 && ( | |
| 211 | + <span | |
| 212 | + className='qx-node-select-input__content-item__arrow' | |
| 213 | + > | |
| 214 | + <svg | |
| 215 | + xmlns="http://www.w3.org/2000/svg" | |
| 216 | + width="1em" | |
| 217 | + height="1em" | |
| 218 | + fill="currentColor" | |
| 219 | + > | |
| 220 | + <path d="M5.80469 13.6423L4.86188 12.6995L9.57592 7.98548L4.86188 3.27143L5.80469 2.32863L10.9901 7.51403C10.9901 7.51406 10.9901 7.51407 10.5187 7.98548L10.9901 7.51403L11.4615 7.98548L5.80469 13.6423Z" /> | |
| 221 | + </svg> | |
| 222 | + </span> | |
| 223 | + )} | |
| 224 | + </div> | |
| 225 | + ))} | |
| 226 | + </> | |
| 227 | + ); | |
| 228 | + }; | |
| 229 | + | |
| 230 | + return { | |
| 231 | + genDisplayDom, | |
| 232 | + optionalNodes, | |
| 233 | + }; | |
| 234 | +}; | |
| 235 | + | |
| 236 | +const SelectItem = (props: any) => { | |
| 237 | + if (props.type === 'FORM') { | |
| 238 | + return ( | |
| 239 | + <div className={cls('qx-node-select-item', 'qx-node-select-item__group')}> | |
| 240 | + <Collapse | |
| 241 | + ghost | |
| 242 | + expandIconPosition="end" | |
| 243 | + items={[ | |
| 244 | + { | |
| 245 | + label: ( | |
| 246 | + <span> | |
| 247 | + {/* @ts-ignore */} | |
| 248 | + {`[${FileTypeMap[props.type]}]`} | |
| 249 | + {props.title} | |
| 250 | + </span> | |
| 251 | + ), | |
| 252 | + key: props.id, | |
| 253 | + children: props.child?.map((item: any, idx: number) => { | |
| 254 | + return ( | |
| 255 | + <SelectItem | |
| 256 | + key={item.code || idx} | |
| 257 | + {...item} | |
| 258 | + onClick={props.onClick} | |
| 259 | + /> | |
| 260 | + ); | |
| 261 | + }), | |
| 262 | + }, | |
| 263 | + ]} | |
| 264 | + /> | |
| 265 | + </div> | |
| 266 | + ); | |
| 267 | + } | |
| 268 | + | |
| 269 | + if (!props.child) { | |
| 270 | + return ( | |
| 271 | + <div | |
| 272 | + className={cls('qx-node-select-item')} | |
| 273 | + onClick={() => props.onClick(props)} | |
| 274 | + > | |
| 275 | + {/* @ts-ignore */} | |
| 276 | + {props.icon ? props.icon : `[${FileTypeMap[props.type]}]`} | |
| 277 | + {props.title} | |
| 278 | + </div> | |
| 279 | + ); | |
| 280 | + } | |
| 281 | + | |
| 282 | + return ( | |
| 283 | + <div className={cls('qx-node-select-item', 'qx-node-select-item__group')}> | |
| 284 | + <Collapse | |
| 285 | + ghost | |
| 286 | + expandIconPosition="end" | |
| 287 | + items={[ | |
| 288 | + { | |
| 289 | + label: ( | |
| 290 | + <span> | |
| 291 | + {/* @ts-ignore */} | |
| 292 | + {`[${FileTypeMap[props.type]}]`} | |
| 293 | + {props.title} | |
| 294 | + </span> | |
| 295 | + ), | |
| 296 | + key: props.id, | |
| 297 | + children: props.child?.map((item: any, idx: number) => { | |
| 298 | + return ( | |
| 299 | + <SelectItem | |
| 300 | + key={item.code || idx} | |
| 301 | + {...item} | |
| 302 | + onClick={props.onClick} | |
| 303 | + /> | |
| 304 | + ); | |
| 305 | + }), | |
| 306 | + }, | |
| 307 | + ]} | |
| 308 | + /> | |
| 309 | + </div> | |
| 310 | + ); | |
| 311 | +}; | |
| 312 | + | |
| 313 | +export const QxFlowNodeFieldSelector: React.FC<NodeFieldSelectProps> = ( | |
| 314 | + props, | |
| 315 | +) => { | |
| 316 | + const { mode = 'select' } = props; | |
| 317 | + | |
| 318 | + const [visible, setVisible] = useState(false); | |
| 319 | + | |
| 320 | + const [inputDisplay, setInputDisplay] = useState<React.ReactNode>(); | |
| 321 | + | |
| 322 | + const { optionalNodes, genDisplayDom } = useNodeFieldDisplay(props); | |
| 323 | + | |
| 324 | + const getOptions = () => { | |
| 325 | + if (!optionalNodes.length) { | |
| 326 | + return <Empty />; | |
| 327 | + } | |
| 328 | + return optionalNodes.map((node) => ({ | |
| 329 | + label: ( | |
| 330 | + <div className={cls('qx-node-select-dropdown-header')}> | |
| 331 | + <span className={cls('qx-node-select-dropdown-header__icon')}> | |
| 332 | + {icon(node.icon)} | |
| 333 | + </span> | |
| 334 | + {node.name} | |
| 335 | + </div> | |
| 336 | + ), | |
| 337 | + key: node.id, | |
| 338 | + children: Array.isArray(node.data?.result) | |
| 339 | + ? (node.data.result as FiledType[])?.map((item) => { | |
| 340 | + return ( | |
| 341 | + <SelectItem | |
| 342 | + key={item.id} | |
| 343 | + {...item} | |
| 344 | + onClick={(value: FiledType) => { | |
| 345 | + // eslint-disable-next-line @typescript-eslint/no-use-before-define | |
| 346 | + handleItemClick(node.id, value || item); | |
| 347 | + }} | |
| 348 | + /> | |
| 349 | + ); | |
| 350 | + }) | |
| 351 | + : [], | |
| 352 | + })); | |
| 353 | + }; | |
| 354 | + | |
| 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 | + const handleItemClick = (nodeKey: string, item: any) => { | |
| 446 | + const newValue = '${' + `${nodeKey}|${item.id}` + '}'; | |
| 447 | + props.onChange?.(newValue, item); | |
| 448 | + if (!props.children) { | |
| 449 | + renderInputDisplay(newValue); | |
| 450 | + } | |
| 451 | + setVisible(false); | |
| 452 | + }; | |
| 453 | + | |
| 454 | + useEffect(() => { | |
| 455 | + handleGetAppsFields(); | |
| 456 | + }, []); | |
| 457 | + | |
| 458 | + useEffect(() => { | |
| 459 | + setVisible(props.open ?? false); | |
| 460 | + }, [props.open]); | |
| 461 | + | |
| 462 | + return ( | |
| 463 | + <div className={cls('qx-node-select')}> | |
| 464 | + <Dropdown | |
| 465 | + trigger={['click']} | |
| 466 | + overlayStyle={{ width: `${props?.width}px` }} | |
| 467 | + overlayClassName={cls('qx-node-select-dropdown')} | |
| 468 | + open={visible} | |
| 469 | + dropdownRender={() => ( | |
| 470 | + <Collapse ghost expandIconPosition="end" items={getOptions()} /> | |
| 471 | + )} | |
| 472 | + onOpenChange={(open) => { | |
| 473 | + if (mode === 'select') { | |
| 474 | + setVisible(open); | |
| 475 | + } | |
| 476 | + }} | |
| 477 | + > | |
| 478 | + {props.children ? ( | |
| 479 | + props.children | |
| 480 | + ) : ( | |
| 481 | + <div className={cls('qx-node-select-input')}> | |
| 482 | + {inputDisplay} | |
| 483 | + {mode === 'variable' && ( | |
| 484 | + <span | |
| 485 | + className="qx-node-select-input__suffix" | |
| 486 | + onClick={() => setVisible(!visible)} | |
| 487 | + > | |
| 488 | + <ControlOutlined /> | |
| 489 | + </span> | |
| 490 | + )} | |
| 491 | + </div> | |
| 492 | + )} | |
| 493 | + </Dropdown> | |
| 494 | + </div> | |
| 495 | + ); | |
| 496 | +}; | |
| 497 | + | |
| 498 | +export interface NodeFieldSelectProps { | |
| 499 | + node: INode; | |
| 500 | + nodes: INode[]; | |
| 501 | + onChange?: (val: any, opt?: FiledType) => void; | |
| 502 | + value?: string; | |
| 503 | + children?: React.ReactNode; | |
| 504 | + limitTypes?: string[]; | |
| 505 | + width?: number; | |
| 506 | + mode?: 'select' | 'variable'; | |
| 507 | + open?: boolean; | |
| 508 | +} | |
| 509 | + | |
| 510 | +export interface FiledType { | |
| 511 | + type: string; | |
| 512 | + id: string; | |
| 513 | + title: string; | |
| 514 | + code: string; | |
| 515 | + valueOpt?: string; | |
| 516 | + mappingValues?: any[]; | |
| 517 | + detailValues?: any; | |
| 518 | + condition?: any; | |
| 519 | + child?: FiledType[]; | |
| 520 | + qxProps?: { | |
| 521 | + formId?: string; | |
| 522 | + }; | |
| 523 | + [key: string]: any; | |
| 524 | +} | |
| 525 | + | |
| 526 | +export interface INode { | |
| 527 | + id: string; | |
| 528 | + type: string; | |
| 529 | + name: string; | |
| 530 | + data?: any; | |
| 531 | + children?: INode[]; | |
| 532 | + path?: string[]; | |
| 533 | + configuring?: boolean; | |
| 534 | + validateStatusError?: boolean; | |
| 535 | + next?: string[]; | |
| 536 | + tools?: string[] | React.FC<any>[]; | |
| 537 | + debuggerError?: boolean; | |
| 538 | + debuggerSuccess?: boolean; | |
| 539 | + [key: string]: any; | |
| 540 | +} | ... | ... |
src/qx-widget-icon/index.md
0 → 100644
| 1 | +--- | |
| 2 | +nav: | |
| 3 | + path: /component | |
| 4 | + title: 组件 | |
| 5 | + order: 1 | |
| 6 | +group: | |
| 7 | + path: /common | |
| 8 | + title: 表单字段图标 | |
| 9 | + order: 0 | |
| 10 | +--- | |
| 11 | + | |
| 12 | +## QxWidgetIcon 表单字段图标 | |
| 13 | + | |
| 14 | +### 表单字段图标 | |
| 15 | + | |
| 16 | +```tsx | |
| 17 | +import { QxWidgetIcon } from '@qx/common'; | |
| 18 | + | |
| 19 | +export default () => { | |
| 20 | + return <QxWidgetIcon widgetName="qxInput" />; | |
| 21 | +}; | |
| 22 | +``` | ... | ... |
src/qx-widget-icon/index.tsx
0 → 100644
| 1 | +import { QxBaseIcon } from '../qx-base-icon'; | |
| 2 | + | |
| 3 | +export const QxWidgetIcon = ({ widgetName }: { widgetName: string }) => { | |
| 4 | + let iconType: string = ''; | |
| 5 | + switch (widgetName) { | |
| 6 | + case 'qxInput': | |
| 7 | + iconType = 'icon-field-text'; | |
| 8 | + break; | |
| 9 | + case 'qxNumber': | |
| 10 | + iconType = 'icon-field-num'; | |
| 11 | + break; | |
| 12 | + case 'dateTime': | |
| 13 | + case 'qxDatetime': | |
| 14 | + iconType = 'icon-field-datetime'; | |
| 15 | + break; | |
| 16 | + case 'qxTime': | |
| 17 | + iconType = 'icon-field-time'; | |
| 18 | + break; | |
| 19 | + case 'qxSwitch': | |
| 20 | + iconType = 'icon-field-boolean'; | |
| 21 | + break; | |
| 22 | + case 'qxSelect': | |
| 23 | + iconType = 'icon-field-select'; | |
| 24 | + break; | |
| 25 | + case 'qxMultiSelect': | |
| 26 | + iconType = 'icon-field-multi-select'; | |
| 27 | + break; | |
| 28 | + case 'qxMobile': | |
| 29 | + iconType = 'icon-field-mobile'; | |
| 30 | + break; | |
| 31 | + case 'qxMoney': | |
| 32 | + iconType = 'icon-field-finance'; | |
| 33 | + break; | |
| 34 | + case 'qxEmail': | |
| 35 | + iconType = 'icon-field-email'; | |
| 36 | + break; | |
| 37 | + case 'qxPercent': | |
| 38 | + iconType = 'icon-field-percent'; | |
| 39 | + break; | |
| 40 | + case 'qxUpload': | |
| 41 | + iconType = 'icon-field-file'; | |
| 42 | + break; | |
| 43 | + case 'qxUploadImage': | |
| 44 | + iconType = 'icon-field-img'; | |
| 45 | + break; | |
| 46 | + case 'qxAddress': | |
| 47 | + iconType = 'icon-field-address'; | |
| 48 | + break; | |
| 49 | + case 'qxRichText': | |
| 50 | + iconType = 'icon-field-richtext'; | |
| 51 | + break; | |
| 52 | + case 'qxLocation': | |
| 53 | + iconType = 'icon-field-location'; | |
| 54 | + break; | |
| 55 | + case 'orgSelector': | |
| 56 | + iconType = 'icon-field-department'; | |
| 57 | + break; | |
| 58 | + case 'userSelector': | |
| 59 | + iconType = 'icon-field-user'; | |
| 60 | + break; | |
| 61 | + case 'createdBy': | |
| 62 | + case 'created_by': | |
| 63 | + iconType = 'icon-field-created-by'; | |
| 64 | + break; | |
| 65 | + case 'createdAt': | |
| 66 | + case 'created_at': | |
| 67 | + iconType = 'icon-field-created-at'; | |
| 68 | + break; | |
| 69 | + case 'updatedBy': | |
| 70 | + case 'updated_by': | |
| 71 | + iconType = 'icon-field-updated-by'; | |
| 72 | + break; | |
| 73 | + case 'updatedAt': | |
| 74 | + case 'updated_at': | |
| 75 | + iconType = 'icon-field-updated-at'; | |
| 76 | + break; | |
| 77 | + case 'qxBizNo': | |
| 78 | + iconType = 'icon-field-no'; | |
| 79 | + break; | |
| 80 | + case 'relSelector': | |
| 81 | + iconType = 'icon-field-rel'; | |
| 82 | + break; | |
| 83 | + case 'relField': | |
| 84 | + iconType = 'icon-field-ref'; | |
| 85 | + break; | |
| 86 | + case 'subform': | |
| 87 | + case 'table': | |
| 88 | + iconType = 'icon-field-subform'; | |
| 89 | + break; | |
| 90 | + case 'qxTree': | |
| 91 | + iconType = 'icon-field-tree'; | |
| 92 | + break; | |
| 93 | + case 'qxFormula': | |
| 94 | + iconType = 'icon-field-formula'; | |
| 95 | + break; | |
| 96 | + case 'qxDivider': | |
| 97 | + iconType = 'icon-field-divider'; | |
| 98 | + break; | |
| 99 | + case 'qxRemark': | |
| 100 | + iconType = 'icon-field-remark'; | |
| 101 | + break; | |
| 102 | + case 'qxEmbed': | |
| 103 | + iconType = 'icon-field-embed '; | |
| 104 | + break; | |
| 105 | + case 'qxTabs': | |
| 106 | + iconType = 'icon-editor_tab'; | |
| 107 | + break; | |
| 108 | + case 'qxLayout': | |
| 109 | + iconType = 'icon-editor_grid'; | |
| 110 | + break; | |
| 111 | + case 'simple': | |
| 112 | + iconType = 'icon-editor_layout'; | |
| 113 | + break; | |
| 114 | + case 'tabC': | |
| 115 | + iconType = 'icon-editor_tab'; | |
| 116 | + break; | |
| 117 | + case 'layout': | |
| 118 | + iconType = 'icon-editor_grid'; | |
| 119 | + break; | |
| 120 | + default: | |
| 121 | + iconType = 'icon-field-text'; | |
| 122 | + break; | |
| 123 | + } | |
| 124 | + return <QxBaseIcon type={iconType} />; | |
| 125 | +}; | ... | ... |