@hw-component/form 0.0.9-beta-v21 → 1.0.0
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/es/DialogForm/modal.d.ts +4 -3
- package/lib/DialogForm/modal.d.ts +4 -3
- package/package.json +1 -1
- package/src/Layout.tsx +61 -0
- package/src/app.tsx +33 -0
- package/src/components/Cascader/index.tsx +31 -0
- package/src/components/CheckboxGroup/CheckBox/index.tsx +38 -0
- package/src/components/CheckboxGroup/hooks.ts +105 -0
- package/src/components/CheckboxGroup/index.tsx +85 -0
- package/src/components/CheckboxGroup/modal.ts +17 -0
- package/src/components/DialogForm/DrawerForm/Footer.tsx +20 -0
- package/src/components/DialogForm/DrawerForm/Title.tsx +12 -0
- package/src/components/DialogForm/DrawerForm/index.tsx +110 -0
- package/src/components/DialogForm/ModalForm.tsx +91 -0
- package/src/components/DialogForm/hooks.ts +122 -0
- package/src/components/DialogForm/modal.ts +45 -0
- package/src/components/Form/Context/FormConfigProvider.tsx +38 -0
- package/src/components/Form/Context/index.tsx +14 -0
- package/src/components/Form/FormItem/BasicItem.tsx +95 -0
- package/src/components/Form/FormItem/Helper.tsx +25 -0
- package/src/components/Form/FormItem/RegularFormItem.tsx +13 -0
- package/src/components/Form/FormItem/UpFormItem.tsx +21 -0
- package/src/components/Form/FormItem/hooks.tsx +54 -0
- package/src/components/Form/FormItem/index.tsx +8 -0
- package/src/components/Form/HFormConnect.tsx +74 -0
- package/src/components/Form/InitSet.tsx +10 -0
- package/src/components/Form/Label.tsx +50 -0
- package/src/components/Form/config.ts +58 -0
- package/src/components/Form/hooks/index.ts +114 -0
- package/src/components/Form/hooks/useDefaultRender.tsx +45 -0
- package/src/components/Form/hooks/useHForm.ts +182 -0
- package/src/components/Form/hooks/useInitConfigData.tsx +194 -0
- package/src/components/Form/index.less +54 -0
- package/src/components/Form/index.tsx +113 -0
- package/src/components/Form/modal.ts +206 -0
- package/src/components/Input/ButtonInput.tsx +47 -0
- package/src/components/Input/ColorInput/Picker.tsx +18 -0
- package/src/components/Input/ColorInput/data.ts +102 -0
- package/src/components/Input/ColorInput/index.less +10 -0
- package/src/components/Input/ColorInput/index.tsx +58 -0
- package/src/components/Input/InputNumber.tsx +5 -0
- package/src/components/Input/SelectInput.tsx +75 -0
- package/src/components/Input/TrimInput.tsx +26 -0
- package/src/components/Input/VerificationCodeInput.tsx +74 -0
- package/src/components/Input/defaultConfig.ts +8 -0
- package/src/components/Input/index.tsx +26 -0
- package/src/components/Input/modal.ts +40 -0
- package/src/components/PageHandler/ErrorComponent.tsx +20 -0
- package/src/components/PageHandler/LoadingComponent.tsx +9 -0
- package/src/components/PageHandler/index.tsx +14 -0
- package/src/components/PageHandler/modal.ts +6 -0
- package/src/components/RadioGroup/index.tsx +45 -0
- package/src/components/Select/components/AllSelect.tsx +54 -0
- package/src/components/Select/components/CheckBoxOption.tsx +14 -0
- package/src/components/Select/components/DropdownComponent.tsx +36 -0
- package/src/components/Select/components/NoFindItem.tsx +7 -0
- package/src/components/Select/components/NotFoundContent.tsx +25 -0
- package/src/components/Select/defaultConfig.tsx +23 -0
- package/src/components/Select/hooks/changeHooks.tsx +159 -0
- package/src/components/Select/hooks/norHooks.ts +85 -0
- package/src/components/Select/index.less +22 -0
- package/src/components/Select/index.tsx +126 -0
- package/src/components/Select/modal.ts +36 -0
- package/src/components/Select/utils.ts +18 -0
- package/src/components/Submit/components.tsx +57 -0
- package/src/components/Submit/hooks.ts +31 -0
- package/src/components/Submit/index.tsx +33 -0
- package/src/components/Switch/index.tsx +77 -0
- package/src/components/TDPicker/RangePicker.tsx +109 -0
- package/src/components/TDPicker/TimePicker.tsx +29 -0
- package/src/components/TDPicker/hooks.ts +150 -0
- package/src/components/TDPicker/index.tsx +33 -0
- package/src/components/TDPicker/modal.ts +48 -0
- package/src/components/TextArea/TrimTextArea.tsx +30 -0
- package/src/components/TextArea/index.tsx +8 -0
- package/src/components/Upload/Btn.tsx +24 -0
- package/src/components/Upload/MediaTypeEle/TypeEle.tsx +26 -0
- package/src/components/Upload/MediaTypeEle/index.tsx +34 -0
- package/src/components/Upload/Preview/index.tsx +14 -0
- package/src/components/Upload/UrlUpload/index.tsx +104 -0
- package/src/components/Upload/enums.ts +5 -0
- package/src/components/Upload/hooks/change.ts +79 -0
- package/src/components/Upload/hooks/customRequest.ts +87 -0
- package/src/components/Upload/hooks/propsMaker.ts +20 -0
- package/src/components/Upload/index.tsx +119 -0
- package/src/components/Upload/modal.ts +33 -0
- package/src/components/Upload/util.ts +27 -0
- package/src/components/config.ts +47 -0
- package/src/components/hooks/index.ts +53 -0
- package/src/components/index.tsx +37 -0
- package/src/components/modal.ts +20 -0
- package/src/components/styles/index.less +3 -0
- package/src/components/styles/local.less +1 -0
- package/src/components/typings.d.ts +11 -0
- package/src/index.less +20 -0
- package/src/index.tsx +12 -0
- package/src/pages/Checkbox/index.tsx +14 -0
- package/src/pages/DatePicker/index.tsx +33 -0
- package/src/pages/DrawerForm/index.tsx +145 -0
- package/src/pages/Form/index.tsx +172 -0
- package/src/pages/Input/index.tsx +30 -0
- package/src/pages/ModalForm/index.tsx +195 -0
- package/src/pages/Radio/index.tsx +18 -0
- package/src/pages/Select/index.tsx +63 -0
- package/src/pages/Switch/index.tsx +18 -0
- package/src/pages/Upload/index.tsx +14 -0
- package/src/routes.tsx +80 -0
- package/.husky/pre-commit +0 -4
- package/.idea/hw-component-form.iml +0 -12
- package/.idea/inspectionProfiles/Project_Default.xml +0 -7
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Button, Row, Space, Typography } from "antd";
|
|
2
|
+
import { ExclamationCircleOutlined } from "@ant-design/icons";
|
|
3
|
+
import type { IHPageHandler } from "./modal";
|
|
4
|
+
|
|
5
|
+
const { Text } = Typography;
|
|
6
|
+
export default ({ error, reload }: IHPageHandler) => {
|
|
7
|
+
return (
|
|
8
|
+
<Row justify={"center"} align={"middle"} style={{ height: 125 }}>
|
|
9
|
+
<Space align={"center"} direction={"vertical"}>
|
|
10
|
+
<Text type={"danger"}>
|
|
11
|
+
<ExclamationCircleOutlined size={24} />
|
|
12
|
+
</Text>
|
|
13
|
+
<Text type={"danger"}>{error?.message}</Text>
|
|
14
|
+
<Button type="primary" size={"small"} onClick={reload}>
|
|
15
|
+
重新加载
|
|
16
|
+
</Button>
|
|
17
|
+
</Space>
|
|
18
|
+
</Row>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Loading from "./LoadingComponent";
|
|
3
|
+
import ErrorComponent from "./ErrorComponent";
|
|
4
|
+
import type { IHPageHandler } from "./modal";
|
|
5
|
+
const Index: React.FC<IHPageHandler> = ({ error, data, reload, children }) => {
|
|
6
|
+
if (error) {
|
|
7
|
+
return <ErrorComponent error={error} reload={reload} />;
|
|
8
|
+
}
|
|
9
|
+
if (data) {
|
|
10
|
+
return <>{children}</>;
|
|
11
|
+
}
|
|
12
|
+
return <Loading />;
|
|
13
|
+
};
|
|
14
|
+
export default Index;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Radio } from "antd";
|
|
2
|
+
import type { SelectProps, RadioGroupProps } from "antd/es";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { useMatchConfigProps } from "../hooks";
|
|
5
|
+
|
|
6
|
+
export interface HRadioGroupProps
|
|
7
|
+
extends Omit<RadioGroupProps, "onChange" | "options"> {
|
|
8
|
+
onChange?: (value: any) => void;
|
|
9
|
+
fieldNames?: SelectProps["fieldNames"];
|
|
10
|
+
options?: (Record<string, any> | string | number)[];
|
|
11
|
+
}
|
|
12
|
+
export default ({
|
|
13
|
+
value,
|
|
14
|
+
options,
|
|
15
|
+
onChange,
|
|
16
|
+
fieldNames: propsFieldNames,
|
|
17
|
+
...props
|
|
18
|
+
}: HRadioGroupProps) => {
|
|
19
|
+
const { fieldNames = {} } = useMatchConfigProps({
|
|
20
|
+
fieldNames: propsFieldNames,
|
|
21
|
+
});
|
|
22
|
+
const relOptions = useMemo(() => {
|
|
23
|
+
return options?.map((item) => {
|
|
24
|
+
const type = typeof item;
|
|
25
|
+
if (type === "string" || type === "number") {
|
|
26
|
+
return item;
|
|
27
|
+
}
|
|
28
|
+
const { label: labelKey = "", value: valueKey = "" } = fieldNames;
|
|
29
|
+
return {
|
|
30
|
+
label: item[labelKey],
|
|
31
|
+
value: item[valueKey],
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}, [options, fieldNames]);
|
|
35
|
+
return (
|
|
36
|
+
<Radio.Group
|
|
37
|
+
options={relOptions as RadioGroupProps["options"]}
|
|
38
|
+
value={value}
|
|
39
|
+
onChange={(e) => {
|
|
40
|
+
onChange?.(e.target.value);
|
|
41
|
+
}}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { HSelectProps } from "@/components/Select/modal";
|
|
2
|
+
import { Checkbox, Space } from "antd";
|
|
3
|
+
import { itemOpProvider } from "../utils";
|
|
4
|
+
import { useClassName } from "../../hooks";
|
|
5
|
+
import React from "react";
|
|
6
|
+
|
|
7
|
+
interface IProps extends HSelectProps {
|
|
8
|
+
checked?: boolean;
|
|
9
|
+
}
|
|
10
|
+
const useRootClassName = (checked: boolean) => {
|
|
11
|
+
const norClassNames = ["select-item", "select-item-option"];
|
|
12
|
+
return checked
|
|
13
|
+
? [...norClassNames, "select-item-option-selected"]
|
|
14
|
+
: norClassNames;
|
|
15
|
+
};
|
|
16
|
+
const Index: React.FC<IProps> = ({
|
|
17
|
+
allSelect,
|
|
18
|
+
mode,
|
|
19
|
+
onChange,
|
|
20
|
+
value,
|
|
21
|
+
serviceSearch,
|
|
22
|
+
options,
|
|
23
|
+
fieldNames = {},
|
|
24
|
+
children,
|
|
25
|
+
}) => {
|
|
26
|
+
const opLen = options?.length || 0;
|
|
27
|
+
const checked = (value as any[])?.length >= opLen;
|
|
28
|
+
const classNames = useRootClassName(checked);
|
|
29
|
+
const optionsClassName = useClassName(classNames);
|
|
30
|
+
const allCheckBox = useClassName("hw-all-check-box");
|
|
31
|
+
const change = () => {
|
|
32
|
+
if (!checked) {
|
|
33
|
+
const subItemOps = itemOpProvider(options, fieldNames);
|
|
34
|
+
onChange?.(options, subItemOps);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
onChange?.([], []);
|
|
38
|
+
};
|
|
39
|
+
if (!allSelect || mode !== "multiple" || serviceSearch) {
|
|
40
|
+
return <>{children}</>;
|
|
41
|
+
}
|
|
42
|
+
return (
|
|
43
|
+
<div className={allCheckBox}>
|
|
44
|
+
<div className={optionsClassName} onClick={change}>
|
|
45
|
+
<Space>
|
|
46
|
+
<Checkbox checked={checked} />
|
|
47
|
+
全部
|
|
48
|
+
</Space>
|
|
49
|
+
</div>
|
|
50
|
+
{children}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
export default Index;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Space, Checkbox } from "antd";
|
|
2
|
+
import React from "react";
|
|
3
|
+
interface ICheckBoxOptionProps {
|
|
4
|
+
label?: React.ReactNode;
|
|
5
|
+
checked: boolean;
|
|
6
|
+
}
|
|
7
|
+
export default ({ label, checked }: ICheckBoxOptionProps) => {
|
|
8
|
+
return (
|
|
9
|
+
<Space>
|
|
10
|
+
<Checkbox checked={checked} />
|
|
11
|
+
{label}
|
|
12
|
+
</Space>
|
|
13
|
+
);
|
|
14
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Spin, Row, Space, Typography } from "antd";
|
|
3
|
+
import NotFoundContent from "./NotFoundContent";
|
|
4
|
+
|
|
5
|
+
interface IProps {
|
|
6
|
+
loading?: boolean;
|
|
7
|
+
options?: any[];
|
|
8
|
+
error?: Error;
|
|
9
|
+
reload: VoidFunction;
|
|
10
|
+
}
|
|
11
|
+
const { Text } = Typography;
|
|
12
|
+
const Index: React.FC<IProps> = ({
|
|
13
|
+
loading,
|
|
14
|
+
error,
|
|
15
|
+
options = [],
|
|
16
|
+
reload,
|
|
17
|
+
children,
|
|
18
|
+
}) => {
|
|
19
|
+
const len = options?.length;
|
|
20
|
+
if (loading && len === 0) {
|
|
21
|
+
return (
|
|
22
|
+
<Row style={{ height: 125 }} justify="center" align={"middle"}>
|
|
23
|
+
<Space direction={"vertical"} align={"center"}>
|
|
24
|
+
<Spin />
|
|
25
|
+
<Text type={"secondary"}>拼命加载中...</Text>
|
|
26
|
+
</Space>
|
|
27
|
+
</Row>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
if (error && len === 0) {
|
|
31
|
+
return <NotFoundContent error={error} reload={reload} />;
|
|
32
|
+
}
|
|
33
|
+
return <>{children}</>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default Index;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Empty, Row, Space, Typography, Button } from "antd";
|
|
2
|
+
import { ExclamationCircleOutlined } from "@ant-design/icons";
|
|
3
|
+
const { Text } = Typography;
|
|
4
|
+
interface IProps {
|
|
5
|
+
error?: Error;
|
|
6
|
+
reload: VoidFunction;
|
|
7
|
+
}
|
|
8
|
+
export default ({ error, reload }: IProps) => {
|
|
9
|
+
if (error) {
|
|
10
|
+
return (
|
|
11
|
+
<Row justify={"center"} align={"middle"} style={{ height: 125 }}>
|
|
12
|
+
<Space align={"center"} direction={"vertical"}>
|
|
13
|
+
<Text type={"danger"}>
|
|
14
|
+
<ExclamationCircleOutlined size={24} />
|
|
15
|
+
</Text>
|
|
16
|
+
<Text type={"danger"}>{error.message}</Text>
|
|
17
|
+
<Button type="primary" size={"small"} onClick={reload}>
|
|
18
|
+
重新加载
|
|
19
|
+
</Button>
|
|
20
|
+
</Space>
|
|
21
|
+
</Row>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />;
|
|
25
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import CheckBoxOption from "./components/CheckBoxOption";
|
|
2
|
+
import NoFindItem from "./components/NoFindItem";
|
|
3
|
+
import type { HSelectProps } from "@/components/Select/modal";
|
|
4
|
+
|
|
5
|
+
export const defaultModeConfig: HSelectProps["modeConfig"] = {
|
|
6
|
+
multiple: {
|
|
7
|
+
icon: null,
|
|
8
|
+
render: (item, value) => {
|
|
9
|
+
const checkVal = value?.map((itemVal) => {
|
|
10
|
+
return itemVal.value;
|
|
11
|
+
});
|
|
12
|
+
const newVal = checkVal || [];
|
|
13
|
+
const checked = newVal.indexOf(item.value) !== -1;
|
|
14
|
+
return <CheckBoxOption label={item.label} checked={checked} />;
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const defaultSelectConfig = {
|
|
20
|
+
noMatchItemRender: () => {
|
|
21
|
+
return <NoFindItem label={"选项被删除,请重新选择"} />;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
OptionType,
|
|
3
|
+
PartialHSelectProps,
|
|
4
|
+
} from "@/components/Select/modal";
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import type { FilterDataModal } from "@/components/Select/modal";
|
|
7
|
+
import { itemOpProvider } from "../utils";
|
|
8
|
+
|
|
9
|
+
const single = ({ options, value, noMatchItemRender }: PartialHSelectProps) => {
|
|
10
|
+
const newOptions = options || [];
|
|
11
|
+
const index = newOptions.findIndex((item) => {
|
|
12
|
+
return item.value === value;
|
|
13
|
+
});
|
|
14
|
+
if (index !== -1) {
|
|
15
|
+
const { label } = newOptions[index];
|
|
16
|
+
return {
|
|
17
|
+
value,
|
|
18
|
+
label,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
value,
|
|
23
|
+
label: noMatchItemRender?.({ value }) || value,
|
|
24
|
+
};
|
|
25
|
+
}; //单选模式
|
|
26
|
+
const findNewValInOldVal = (val, oldVal?: any[]) => {
|
|
27
|
+
if (!oldVal) {
|
|
28
|
+
return -1;
|
|
29
|
+
}
|
|
30
|
+
return oldVal.findIndex((item) => {
|
|
31
|
+
return item.value === val;
|
|
32
|
+
});
|
|
33
|
+
}; //查询新增的 value
|
|
34
|
+
const sourceDataProvider = (
|
|
35
|
+
{ options, value }: PartialHSelectProps,
|
|
36
|
+
oldVal?: any[]
|
|
37
|
+
) => {
|
|
38
|
+
const oldData: FilterDataModal[] = [];
|
|
39
|
+
const newData: FilterDataModal[] = [];
|
|
40
|
+
value.forEach((item, i) => {
|
|
41
|
+
const index = findNewValInOldVal(item, oldVal);
|
|
42
|
+
if (index === -1) {
|
|
43
|
+
newData.push({
|
|
44
|
+
value: item,
|
|
45
|
+
index: i,
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const newVal = oldVal?.[index];
|
|
50
|
+
oldData.push({
|
|
51
|
+
...newVal,
|
|
52
|
+
index: i,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
oldData,
|
|
57
|
+
newData,
|
|
58
|
+
};
|
|
59
|
+
}; //创建新旧数据
|
|
60
|
+
const resultProvider = (
|
|
61
|
+
newData: FilterDataModal[],
|
|
62
|
+
oldData: FilterDataModal[],
|
|
63
|
+
value: any[]
|
|
64
|
+
) => {
|
|
65
|
+
const newResult = new Array(value.length);
|
|
66
|
+
oldData.forEach((item) => {
|
|
67
|
+
const { index, ...val } = item;
|
|
68
|
+
newResult[index] = {
|
|
69
|
+
...val,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
newData.forEach((item) => {
|
|
73
|
+
const { index, ...val } = item;
|
|
74
|
+
newResult[index] = {
|
|
75
|
+
...val,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
return newResult;
|
|
79
|
+
};
|
|
80
|
+
const multiple = (
|
|
81
|
+
{ options, value, noMatchItemRender }: PartialHSelectProps,
|
|
82
|
+
oldVal?: any[]
|
|
83
|
+
) => {
|
|
84
|
+
const { newData, oldData } = sourceDataProvider({ options, value }, oldVal);
|
|
85
|
+
const newMatchVal = newData.map((item) => {
|
|
86
|
+
const { value: itemVal, index } = item;
|
|
87
|
+
const newItem = single({ options, value: itemVal, noMatchItemRender });
|
|
88
|
+
return {
|
|
89
|
+
...newItem,
|
|
90
|
+
index,
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
return resultProvider(newMatchVal, oldData, value);
|
|
94
|
+
}; //多选
|
|
95
|
+
const tag = ({ options, value }: PartialHSelectProps, oldVal?: any[]) => {
|
|
96
|
+
const { newData, oldData } = sourceDataProvider({ options, value }, oldVal);
|
|
97
|
+
return resultProvider(newData, oldData, value);
|
|
98
|
+
}; //tags模式
|
|
99
|
+
const matchNotFind = (
|
|
100
|
+
{ options, value, mode, noMatchItemRender }: PartialHSelectProps,
|
|
101
|
+
oldVale?: OptionType[]
|
|
102
|
+
) => {
|
|
103
|
+
if (!mode) {
|
|
104
|
+
return single({ options, value, noMatchItemRender });
|
|
105
|
+
}
|
|
106
|
+
if (mode === "multiple") {
|
|
107
|
+
return multiple({ options, value, noMatchItemRender }, oldVale) || [];
|
|
108
|
+
}
|
|
109
|
+
return tag({ options, value }, oldVale);
|
|
110
|
+
}; //不匹配
|
|
111
|
+
export const useValueChange = (params: PartialHSelectProps) => {
|
|
112
|
+
const {
|
|
113
|
+
labelInValue,
|
|
114
|
+
onChange,
|
|
115
|
+
value,
|
|
116
|
+
options,
|
|
117
|
+
mode,
|
|
118
|
+
noMatchItemRender,
|
|
119
|
+
fieldNames = {},
|
|
120
|
+
} = params;
|
|
121
|
+
const [val, setVal] = useState<any>();
|
|
122
|
+
|
|
123
|
+
const change = (changeVal, itemOps) => {
|
|
124
|
+
if (!onChange) {
|
|
125
|
+
setVal(changeVal);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (!changeVal) {
|
|
129
|
+
onChange(changeVal, itemOps);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
let newChangeVal = changeVal.value;
|
|
133
|
+
if (labelInValue) {
|
|
134
|
+
newChangeVal = changeVal;
|
|
135
|
+
}
|
|
136
|
+
if (Array.isArray(changeVal)) {
|
|
137
|
+
newChangeVal = changeVal.map((item) => {
|
|
138
|
+
return item.value;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
const subItemOps = itemOpProvider(itemOps, fieldNames);
|
|
142
|
+
onChange(newChangeVal, subItemOps);
|
|
143
|
+
};
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
if (mode === "tags" || value === null || value === undefined) {
|
|
146
|
+
setVal(value);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (options) {
|
|
150
|
+
setVal((oldVale) => {
|
|
151
|
+
return matchNotFind(params, oldVale);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}, [value, options, mode, noMatchItemRender]);
|
|
155
|
+
return {
|
|
156
|
+
val,
|
|
157
|
+
change,
|
|
158
|
+
};
|
|
159
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
OptionType,
|
|
4
|
+
PartialHSelectProps,
|
|
5
|
+
} from "@/components/Select/modal";
|
|
6
|
+
import { useRequest } from "ahooks";
|
|
7
|
+
import { useFormContext } from "../../Form/Context";
|
|
8
|
+
|
|
9
|
+
interface ParamsModal {
|
|
10
|
+
options?: OptionType[];
|
|
11
|
+
params?: any;
|
|
12
|
+
}
|
|
13
|
+
export const useOptionReq = ({
|
|
14
|
+
manual,
|
|
15
|
+
request,
|
|
16
|
+
options,
|
|
17
|
+
serviceSearch,
|
|
18
|
+
showSearch,
|
|
19
|
+
onSearch: propsOnSearch,
|
|
20
|
+
dispatch = {},
|
|
21
|
+
}: PartialHSelectProps) => {
|
|
22
|
+
const { manual: dispatchManual } = dispatch;
|
|
23
|
+
const { form } = useFormContext();
|
|
24
|
+
const [data, setData] = useState<OptionType[] | undefined>();
|
|
25
|
+
const { run, loading, error } = useRequest(
|
|
26
|
+
async (requestParams = {}) => {
|
|
27
|
+
const { params = {}, values, type = "init" } = requestParams;
|
|
28
|
+
const formData = values || form?.getFieldsValue();
|
|
29
|
+
if (type === "init") {
|
|
30
|
+
setData(undefined);
|
|
31
|
+
}
|
|
32
|
+
if (request) {
|
|
33
|
+
return request(params, formData);
|
|
34
|
+
}
|
|
35
|
+
return Promise.resolve(options);
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
manual: dispatchManual === false ? true : manual,
|
|
39
|
+
debounceInterval: 300,
|
|
40
|
+
onSuccess: (resultData) => {
|
|
41
|
+
setData(resultData);
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
const reload = ({ options: changeOpts, params }: ParamsModal) => {
|
|
46
|
+
if (changeOpts) {
|
|
47
|
+
return setData(changeOpts);
|
|
48
|
+
}
|
|
49
|
+
return run({ params });
|
|
50
|
+
};
|
|
51
|
+
const onSearch = (inputValue: string) => {
|
|
52
|
+
if (!serviceSearch) {
|
|
53
|
+
propsOnSearch?.(inputValue);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
run({ params: { inputValue } });
|
|
57
|
+
};
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (options) {
|
|
60
|
+
setData(options);
|
|
61
|
+
}
|
|
62
|
+
}, [options]);
|
|
63
|
+
const mathShowSearch = showSearch || serviceSearch;
|
|
64
|
+
return {
|
|
65
|
+
run,
|
|
66
|
+
loading,
|
|
67
|
+
error,
|
|
68
|
+
data,
|
|
69
|
+
onSearch: mathShowSearch ? onSearch : propsOnSearch,
|
|
70
|
+
mathShowSearch: showSearch || serviceSearch,
|
|
71
|
+
reload,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const useFilterOption = ({
|
|
76
|
+
filterOption,
|
|
77
|
+
serviceSearch,
|
|
78
|
+
}: PartialHSelectProps) => {
|
|
79
|
+
if (serviceSearch) {
|
|
80
|
+
return () => {
|
|
81
|
+
return true;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return filterOption;
|
|
85
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@import "../styles/local.less";
|
|
2
|
+
@all-check-box: ~"@{ant-prefix}-hw-all-check-box";
|
|
3
|
+
|
|
4
|
+
.@{all-check-box} {
|
|
5
|
+
.@{ant-prefix}-select-item-option-active:not(
|
|
6
|
+
.@{ant-prefix}-select-item-option-disabled
|
|
7
|
+
) {
|
|
8
|
+
background-color: transparent;
|
|
9
|
+
}
|
|
10
|
+
.@{ant-prefix}-select-item-option-selected:not(
|
|
11
|
+
.@{ant-prefix}-select-item-option-disabled
|
|
12
|
+
) {
|
|
13
|
+
background-color: #e6f7ff;
|
|
14
|
+
}
|
|
15
|
+
.@{ant-prefix}-select-item-option:not(
|
|
16
|
+
.@{ant-prefix}-select-item-option-selected
|
|
17
|
+
) {
|
|
18
|
+
&:hover {
|
|
19
|
+
background-color: #f5f5f5;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Select } from "antd";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { useFilterOption, useOptionReq } from "./hooks/norHooks";
|
|
4
|
+
import { useValueChange } from "./hooks/changeHooks";
|
|
5
|
+
import type { HSelectProps } from "./modal";
|
|
6
|
+
import { defaultModeConfig, defaultSelectConfig } from "./defaultConfig";
|
|
7
|
+
import DropdownComponent from "./components/DropdownComponent";
|
|
8
|
+
import AllSelect from "./components/AllSelect";
|
|
9
|
+
import { useChangeOptions, useMatchConfigProps } from "../hooks";
|
|
10
|
+
import HFormConnect from "../Form/HFormConnect";
|
|
11
|
+
const { Option } = Select;
|
|
12
|
+
|
|
13
|
+
const Index: React.FC<HSelectProps> = ({
|
|
14
|
+
style = { width: "100%" },
|
|
15
|
+
mode,
|
|
16
|
+
options,
|
|
17
|
+
modeConfig = defaultModeConfig,
|
|
18
|
+
value,
|
|
19
|
+
onChange,
|
|
20
|
+
fieldNames: propsFieldNames,
|
|
21
|
+
request,
|
|
22
|
+
manual,
|
|
23
|
+
optionLabelProp = "label",
|
|
24
|
+
filterProvider,
|
|
25
|
+
optionFilterProp = "filterLabel",
|
|
26
|
+
serviceSearch,
|
|
27
|
+
onSearch: propsOnSearch,
|
|
28
|
+
filterOption,
|
|
29
|
+
showSearch,
|
|
30
|
+
labelInValue,
|
|
31
|
+
noMatchItemRender = defaultSelectConfig.noMatchItemRender,
|
|
32
|
+
allSelect,
|
|
33
|
+
addDispatchListener,
|
|
34
|
+
addFormat,
|
|
35
|
+
dispatch,
|
|
36
|
+
...props
|
|
37
|
+
}) => {
|
|
38
|
+
const { icon, render } = modeConfig?.[mode || ""] || {};
|
|
39
|
+
const { fieldNames } = useMatchConfigProps({ fieldNames: propsFieldNames });
|
|
40
|
+
const selfFilterOption = useFilterOption({ filterOption, serviceSearch });
|
|
41
|
+
const {
|
|
42
|
+
run,
|
|
43
|
+
loading,
|
|
44
|
+
data: resultData,
|
|
45
|
+
error,
|
|
46
|
+
onSearch,
|
|
47
|
+
mathShowSearch,
|
|
48
|
+
reload,
|
|
49
|
+
} = useOptionReq({
|
|
50
|
+
options,
|
|
51
|
+
manual,
|
|
52
|
+
fieldNames,
|
|
53
|
+
request,
|
|
54
|
+
serviceSearch,
|
|
55
|
+
showSearch,
|
|
56
|
+
onSearch: propsOnSearch,
|
|
57
|
+
dispatch,
|
|
58
|
+
}); //options
|
|
59
|
+
|
|
60
|
+
const data = useChangeOptions({ options: resultData, fieldNames });
|
|
61
|
+
const { val, change } = useValueChange({
|
|
62
|
+
labelInValue,
|
|
63
|
+
onChange,
|
|
64
|
+
value,
|
|
65
|
+
options: data,
|
|
66
|
+
mode,
|
|
67
|
+
noMatchItemRender,
|
|
68
|
+
fieldNames,
|
|
69
|
+
});
|
|
70
|
+
addDispatchListener?.("reload", reload);
|
|
71
|
+
return (
|
|
72
|
+
<Select
|
|
73
|
+
style={style}
|
|
74
|
+
mode={mode}
|
|
75
|
+
loading={loading}
|
|
76
|
+
value={val}
|
|
77
|
+
onSearch={onSearch}
|
|
78
|
+
onChange={change}
|
|
79
|
+
dropdownRender={(node) => {
|
|
80
|
+
return (
|
|
81
|
+
<DropdownComponent
|
|
82
|
+
loading={loading}
|
|
83
|
+
reload={run}
|
|
84
|
+
error={error}
|
|
85
|
+
options={data}
|
|
86
|
+
>
|
|
87
|
+
<AllSelect
|
|
88
|
+
allSelect={allSelect}
|
|
89
|
+
options={data}
|
|
90
|
+
mode={mode}
|
|
91
|
+
value={val}
|
|
92
|
+
onChange={change}
|
|
93
|
+
>
|
|
94
|
+
{node}
|
|
95
|
+
</AllSelect>
|
|
96
|
+
</DropdownComponent> //全选
|
|
97
|
+
);
|
|
98
|
+
}}
|
|
99
|
+
optionLabelProp={optionLabelProp}
|
|
100
|
+
menuItemSelectedIcon={icon}
|
|
101
|
+
optionFilterProp={optionFilterProp}
|
|
102
|
+
filterOption={selfFilterOption}
|
|
103
|
+
showSearch={mathShowSearch}
|
|
104
|
+
labelInValue={true}
|
|
105
|
+
{...props}
|
|
106
|
+
>
|
|
107
|
+
{data?.map((item) => {
|
|
108
|
+
const { value: optionValue, label } = item;
|
|
109
|
+
const result = filterProvider?.(item) || label;
|
|
110
|
+
const filter = { [optionFilterProp]: result };
|
|
111
|
+
return (
|
|
112
|
+
<Option
|
|
113
|
+
value={optionValue}
|
|
114
|
+
key={optionValue}
|
|
115
|
+
label={label}
|
|
116
|
+
mode={mode}
|
|
117
|
+
{...filter}
|
|
118
|
+
>
|
|
119
|
+
{render ? render(item, val) : label}
|
|
120
|
+
</Option>
|
|
121
|
+
);
|
|
122
|
+
})}
|
|
123
|
+
</Select>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
export default HFormConnect(Index);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { SelectProps } from "antd";
|
|
2
|
+
import type React from "react";
|
|
3
|
+
import type { PromiseFnResult } from "../modal";
|
|
4
|
+
import type { addFormatItemModal ,argsFn,DispatchModal} from "../Form/modal";
|
|
5
|
+
export type OptionType = Record<string, any>;
|
|
6
|
+
export type PartialHSelectProps = Partial<HSelectProps>;
|
|
7
|
+
export type RenderFn = (data: OptionType) => React.ReactNode;
|
|
8
|
+
|
|
9
|
+
interface ModeConfigItem {
|
|
10
|
+
icon?: React.ReactNode | null; //自定义多选时当前选中的条目图标
|
|
11
|
+
render?: (item: OptionType, value: any[]) => React.ReactNode; //options内容
|
|
12
|
+
}
|
|
13
|
+
export interface ModeConfig {
|
|
14
|
+
multiple?: ModeConfigItem;
|
|
15
|
+
tags?: ModeConfigItem;
|
|
16
|
+
}
|
|
17
|
+
export interface HSelectProps
|
|
18
|
+
extends Omit<SelectProps, "options" | "placeholder"> {
|
|
19
|
+
style?: React.CSSProperties;
|
|
20
|
+
request?: PromiseFnResult<any, OptionType[]>;
|
|
21
|
+
manual?: boolean;
|
|
22
|
+
modeConfig?: ModeConfig;
|
|
23
|
+
filterProvider?: (item: any) => string; //筛选字段默认为label
|
|
24
|
+
serviceSearch?: boolean; //服务端搜索
|
|
25
|
+
options?: OptionType[];
|
|
26
|
+
noMatchItemRender?: RenderFn; //没有数据
|
|
27
|
+
allSelect?: boolean; //显示全选
|
|
28
|
+
addDispatchListener?: (key: string, fn: argsFn) => void;
|
|
29
|
+
addFormat?: (format: Record<string, addFormatItemModal>) => void;
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
dispatch?: DispatchModal;
|
|
32
|
+
}
|
|
33
|
+
export interface FilterDataModal {
|
|
34
|
+
value: any;
|
|
35
|
+
index: number;
|
|
36
|
+
}
|