@mi-avalon/libs 0.0.22 → 0.0.24
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/dist/components/MForm/MFormItemConst.d.ts +25 -0
- package/dist/components/MForm/MFormItemConst.js +69 -0
- package/dist/components/MForm/index.d.ts +9 -0
- package/dist/components/MForm/index.js +48 -0
- package/dist/components/MForm/type.d.ts +178 -0
- package/dist/components/MForm/type.js +18 -0
- package/dist/components/MSearch/index.d.ts +26 -0
- package/dist/components/MSearch/index.js +68 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.js +3 -3
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/useFuncRequest.d.ts +16 -0
- package/dist/hooks/useFuncRequest.js +67 -0
- package/dist/hooks/useInterval.d.ts +8 -0
- package/dist/hooks/useInterval.js +30 -0
- package/dist/hooks/usePagination.d.ts +42 -0
- package/dist/hooks/usePagination.js +124 -0
- package/dist/hooks/useQuery.d.ts +3 -0
- package/dist/hooks/useQuery.js +6 -0
- package/dist/hooks/useReactive.d.ts +2 -0
- package/dist/hooks/useReactive.js +20 -0
- package/dist/hooks/useTimeout.d.ts +8 -0
- package/dist/hooks/useTimeout.js +30 -0
- package/dist/hooks/useVirtualList.d.ts +75 -0
- package/dist/hooks/useVirtualList.js +121 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +2033 -671
- package/dist/index.js +1 -1
- package/dist/index.umd.js +73 -11
- package/dist/style.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type IMFormCascaderItem, type IMFormCheckBoxGroupItem, type IMFormDatePickerItem, type IMFormInputItem, type IMFormInputNumItem, type IMFormItem, type IMFormMentionsItem, type IMFormRadioGroupItem, type IMFormRangePickerItem, type IMFormSelectItem, type IMFormTextItem, type IMFormTreeSelectItem, type IMFormUploadItem } from './type';
|
|
2
|
+
export declare class MFormItemConst {
|
|
3
|
+
static readonly labelCol: {
|
|
4
|
+
span: number;
|
|
5
|
+
};
|
|
6
|
+
static readonly wrapperCol: {
|
|
7
|
+
span: number;
|
|
8
|
+
};
|
|
9
|
+
static readonly defaultRowGutter = 24;
|
|
10
|
+
static getDefaultArrayPlaceholder(item: IMFormItem): [string, string];
|
|
11
|
+
static getDefaultPlaceholder(item: IMFormItem): string;
|
|
12
|
+
static input: (item: IMFormInputItem) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
static password: (item: IMFormInputItem) => import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
static text: (item: IMFormTextItem) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
static inputNumber: (item: IMFormInputNumItem) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
static datePicker: (item: IMFormDatePickerItem) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
static rangePicker: (item: IMFormRangePickerItem) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
static select: (item: IMFormSelectItem) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
static radio: (item: IMFormRadioGroupItem) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
static checkbox: (item: IMFormCheckBoxGroupItem) => import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
static upload: (item: IMFormUploadItem) => import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
static mentions: (item: IMFormMentionsItem) => import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
static cascader: (item: IMFormCascaderItem) => import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
static treeSelect: (item: IMFormTreeSelectItem) => import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { UploadOutlined } from '@ant-design/icons';
|
|
3
|
+
import { Button, Cascader, Checkbox, DatePicker, Input, InputNumber, Mentions, Radio, Select, TreeSelect, Upload, } from 'antd';
|
|
4
|
+
import { MFormItemTypeEnum, } from './type';
|
|
5
|
+
const { RangePicker } = DatePicker;
|
|
6
|
+
export class MFormItemConst {
|
|
7
|
+
static labelCol = { span: 7 };
|
|
8
|
+
static wrapperCol = { span: 17 };
|
|
9
|
+
static defaultRowGutter = 24;
|
|
10
|
+
static getDefaultArrayPlaceholder(item) {
|
|
11
|
+
let placeholder;
|
|
12
|
+
switch (item.type) {
|
|
13
|
+
case 'rangePicker':
|
|
14
|
+
placeholder = ['开始时间', '结束时间'];
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
return placeholder;
|
|
18
|
+
}
|
|
19
|
+
static getDefaultPlaceholder(item) {
|
|
20
|
+
let placeholder;
|
|
21
|
+
switch (item.type) {
|
|
22
|
+
case MFormItemTypeEnum.Input:
|
|
23
|
+
case MFormItemTypeEnum.Password:
|
|
24
|
+
case MFormItemTypeEnum.InputNumber:
|
|
25
|
+
case MFormItemTypeEnum.Text:
|
|
26
|
+
case MFormItemTypeEnum.Mentions:
|
|
27
|
+
placeholder = `请输入${item.label}`;
|
|
28
|
+
break;
|
|
29
|
+
case MFormItemTypeEnum.Select:
|
|
30
|
+
case MFormItemTypeEnum.Checkbox:
|
|
31
|
+
case MFormItemTypeEnum.Radio:
|
|
32
|
+
case MFormItemTypeEnum.DatePicker:
|
|
33
|
+
case MFormItemTypeEnum.RangePicker:
|
|
34
|
+
case MFormItemTypeEnum.Cascader:
|
|
35
|
+
case MFormItemTypeEnum.Upload:
|
|
36
|
+
case MFormItemTypeEnum.TreeSelect:
|
|
37
|
+
placeholder = `请选择${item.label}`;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
return placeholder;
|
|
41
|
+
}
|
|
42
|
+
static input = (item) => (_jsx(Input, { disabled: item.disabled, maxLength: item.maxLength, ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
43
|
+
static password = (item) => (_jsx(Input.Password, { disabled: item.disabled, ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
44
|
+
static text = (item) => (_jsx(Input.TextArea, { disabled: item.disabled, maxLength: item.maxLength, ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
45
|
+
static inputNumber = (item) => (_jsx(InputNumber, { disabled: item.disabled, maxLength: item.maxLength, ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
46
|
+
static datePicker = (item) => (_jsx(DatePicker, { disabled: item.disabled, ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
47
|
+
static rangePicker = (item) => (_jsx(RangePicker, { disabled: item.disabled, ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultArrayPlaceholder(item) }));
|
|
48
|
+
static select = (item) => {
|
|
49
|
+
return (_jsx(Select, { ...item.props, disabled: item.disabled, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
50
|
+
};
|
|
51
|
+
static radio = (item) => {
|
|
52
|
+
return _jsx(Radio.Group, { disabled: item.disabled, ...item.props });
|
|
53
|
+
};
|
|
54
|
+
static checkbox = (item) => {
|
|
55
|
+
return _jsx(Checkbox.Group, { disabled: item.disabled, ...item.props });
|
|
56
|
+
};
|
|
57
|
+
static upload = (item) => {
|
|
58
|
+
return (_jsx(Upload, { defaultFileList: item.initialValue, ...item.props, children: item.children || (_jsxs(Button, { children: [_jsx(UploadOutlined, {}), " \u70B9\u51FB\u4E0A\u4F20"] })) }));
|
|
59
|
+
};
|
|
60
|
+
static mentions = (item) => {
|
|
61
|
+
return (_jsx(Mentions, { ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
62
|
+
};
|
|
63
|
+
static cascader = (item) => {
|
|
64
|
+
return (_jsx(Cascader, { ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
65
|
+
};
|
|
66
|
+
static treeSelect = (item) => {
|
|
67
|
+
return (_jsx(TreeSelect, { ...item.props, placeholder: item.placeholder || MFormItemConst.getDefaultPlaceholder(item) }));
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import './index.scss';
|
|
2
|
+
import type { IMFormProps } from './type';
|
|
3
|
+
declare function MForm(props: IMFormProps): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
declare namespace MForm {
|
|
5
|
+
var displayName: string;
|
|
6
|
+
}
|
|
7
|
+
export default MForm;
|
|
8
|
+
export * from './MFormItemConst';
|
|
9
|
+
export * from './type';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* 表单组件
|
|
4
|
+
*/
|
|
5
|
+
import { Col, Form, Row } from 'antd';
|
|
6
|
+
import { getClassName } from '../../utils';
|
|
7
|
+
import { CompThemeProvider } from '../ThemeContext';
|
|
8
|
+
import './index.scss';
|
|
9
|
+
import { MFormItemConst } from './MFormItemConst';
|
|
10
|
+
const classname = (n = '') => {
|
|
11
|
+
const cn = 'm-form';
|
|
12
|
+
return getClassName(cn, n);
|
|
13
|
+
};
|
|
14
|
+
function MForm(props) {
|
|
15
|
+
const { formProps, formItems = [], column = 1, form, itemLayout, formRowProps } = props;
|
|
16
|
+
const renderItem = (item, form) => {
|
|
17
|
+
if (item.render) {
|
|
18
|
+
return item.render(form);
|
|
19
|
+
}
|
|
20
|
+
const func = MFormItemConst[item.type];
|
|
21
|
+
if (item && item.type && func) {
|
|
22
|
+
const renderFunc = func;
|
|
23
|
+
return renderFunc(item);
|
|
24
|
+
}
|
|
25
|
+
return _jsx("div", { className: 'error-message', children: "Invalid form item configuration" });
|
|
26
|
+
};
|
|
27
|
+
const renderFormItem = (item) => {
|
|
28
|
+
const { show = true } = item;
|
|
29
|
+
if (!show)
|
|
30
|
+
return null;
|
|
31
|
+
const rules = [...(item.rules || [])];
|
|
32
|
+
if (item.required) {
|
|
33
|
+
rules.push({ required: true, message: item.required });
|
|
34
|
+
}
|
|
35
|
+
const formItemLayout = {
|
|
36
|
+
labelCol: MFormItemConst.labelCol,
|
|
37
|
+
wrapperCol: MFormItemConst.wrapperCol,
|
|
38
|
+
...itemLayout,
|
|
39
|
+
...item.itemLayout,
|
|
40
|
+
};
|
|
41
|
+
return (_jsx(Col, { span: item.span || 24 / column, children: _jsx("div", { className: classname('item-wrapper'), children: _jsx(Form.Item, { label: item.label, name: item.id, rules: rules, initialValue: item.initialValue, ...formItemLayout, ...item.formItemProps, children: renderItem(item, form) }) }) }, `col-${item.id}`));
|
|
42
|
+
};
|
|
43
|
+
return (_jsx(CompThemeProvider, { children: _jsx(Form, { form: form, ...formProps, className: `${classname()} ${formProps?.className}`, children: _jsx(Row, { gutter: MFormItemConst.defaultRowGutter, ...formRowProps, className: `${classname('grid')} ${formRowProps?.className}`, children: formItems.map(e => renderFormItem(e)) }) }) }));
|
|
44
|
+
}
|
|
45
|
+
MForm.displayName = 'MForm';
|
|
46
|
+
export default MForm;
|
|
47
|
+
export * from './MFormItemConst';
|
|
48
|
+
export * from './type';
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { type CascaderAutoProps, Checkbox, DatePicker, type FormInstance, type FormItemProps, type FormProps, type FormRule, Input, type InputNumberProps, type InputProps, type MentionsProps, type RadioGroupProps, type RowProps, type SelectProps, type TreeSelectProps, type UploadProps } from 'antd';
|
|
2
|
+
import type { ReactElement } from 'react';
|
|
3
|
+
type CheckboxGroupProps = React.ComponentProps<typeof Checkbox.Group>;
|
|
4
|
+
type RangePickerProps = React.ComponentProps<typeof DatePicker.RangePicker>;
|
|
5
|
+
type DatePickerProps = React.ComponentProps<typeof DatePicker>;
|
|
6
|
+
type TextAreaProps = React.ComponentProps<typeof Input.TextArea>;
|
|
7
|
+
export declare enum MFormItemTypeEnum {
|
|
8
|
+
Input = "input",
|
|
9
|
+
InputNumber = "inputNumber",
|
|
10
|
+
Text = "text",
|
|
11
|
+
Password = "password",
|
|
12
|
+
Radio = "radio",
|
|
13
|
+
Select = "select",
|
|
14
|
+
Checkbox = "checkbox",
|
|
15
|
+
DatePicker = "datePicker",
|
|
16
|
+
RangePicker = "rangePicker",
|
|
17
|
+
Upload = "upload",
|
|
18
|
+
Mentions = "mentions",
|
|
19
|
+
Cascader = "cascader",
|
|
20
|
+
TreeSelect = "treeSelect"
|
|
21
|
+
}
|
|
22
|
+
export declare type MFormItemLayout = {
|
|
23
|
+
span?: number;
|
|
24
|
+
offset?: number;
|
|
25
|
+
};
|
|
26
|
+
export interface IMFormProps {
|
|
27
|
+
/**
|
|
28
|
+
* 一行显示几个label 默认1个, 其他:2, 3, 4
|
|
29
|
+
*/
|
|
30
|
+
column?: 1 | 2 | 3 | 4;
|
|
31
|
+
/**
|
|
32
|
+
* 需要的数据: [ { label: ...,id: ..., required: ..., type: ..., ... }, ... ]
|
|
33
|
+
*/
|
|
34
|
+
formItems: IMFormItem[];
|
|
35
|
+
/**
|
|
36
|
+
* Antd const [form] = useForm()
|
|
37
|
+
*/
|
|
38
|
+
form?: FormInstance;
|
|
39
|
+
/**
|
|
40
|
+
* 表单其他属性
|
|
41
|
+
*/
|
|
42
|
+
formProps?: FormProps;
|
|
43
|
+
/**
|
|
44
|
+
* 全局 MFormItem layout, 默认为 {labelCol:{span: 7}, wrapperCol: {span: 7}}
|
|
45
|
+
* @type {{labelCol: MFormItemLayout, wrapperCol: MFormItemLayout}}
|
|
46
|
+
* @memberof MFormItem
|
|
47
|
+
*/
|
|
48
|
+
itemLayout?: {
|
|
49
|
+
labelCol?: MFormItemLayout;
|
|
50
|
+
wrapperCol?: MFormItemLayout;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Antd Row 的其他属性
|
|
54
|
+
*/
|
|
55
|
+
formRowProps?: RowProps;
|
|
56
|
+
}
|
|
57
|
+
export interface IMFormBaseItem {
|
|
58
|
+
/**
|
|
59
|
+
* 属性名
|
|
60
|
+
*/
|
|
61
|
+
id: string;
|
|
62
|
+
/**
|
|
63
|
+
* label名称
|
|
64
|
+
*/
|
|
65
|
+
label: string;
|
|
66
|
+
/**
|
|
67
|
+
* 组件是否禁用
|
|
68
|
+
*/
|
|
69
|
+
disabled?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* form类型 FORM_TYPE
|
|
72
|
+
*/
|
|
73
|
+
type?: MFormItemTypeEnum;
|
|
74
|
+
/**
|
|
75
|
+
* 初始值
|
|
76
|
+
*/
|
|
77
|
+
initialValue?: any;
|
|
78
|
+
/**
|
|
79
|
+
* rules required的验证消息, 不填写则不验证
|
|
80
|
+
*/
|
|
81
|
+
required?: string;
|
|
82
|
+
/**
|
|
83
|
+
* rule-max, 正则,验证消息
|
|
84
|
+
*/
|
|
85
|
+
rules?: FormRule[];
|
|
86
|
+
/**
|
|
87
|
+
* 自定义form
|
|
88
|
+
*/
|
|
89
|
+
render?: (form?: FormInstance) => ReactElement;
|
|
90
|
+
/**
|
|
91
|
+
* Antd MForm.Item 的其他属性
|
|
92
|
+
*/
|
|
93
|
+
formItemProps?: FormItemProps;
|
|
94
|
+
/**
|
|
95
|
+
* MFormItem layout, 默认为 {labelCol:{span: 7}, wrapperCol: {span: 7}}
|
|
96
|
+
* @type {{labelCol: MFormItemLayout, wrapperCol: MFormItemLayout}}
|
|
97
|
+
* @memberof MFormItem
|
|
98
|
+
*/
|
|
99
|
+
itemLayout?: {
|
|
100
|
+
labelCol?: MFormItemLayout;
|
|
101
|
+
wrapperCol?: MFormItemLayout;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* 当前表单占据行的宽度 1-24 默认 24 / column
|
|
105
|
+
*/
|
|
106
|
+
span?: number;
|
|
107
|
+
/**
|
|
108
|
+
* 是否显示当前组件 默认显示
|
|
109
|
+
*/
|
|
110
|
+
show?: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* item组件的其他属性
|
|
113
|
+
*/
|
|
114
|
+
props?: any;
|
|
115
|
+
}
|
|
116
|
+
export interface IMFormInputItem extends IMFormBaseItem {
|
|
117
|
+
type: MFormItemTypeEnum.Input | MFormItemTypeEnum.Password;
|
|
118
|
+
props?: InputProps;
|
|
119
|
+
placeholder?: string;
|
|
120
|
+
maxLength?: number;
|
|
121
|
+
}
|
|
122
|
+
export interface IMFormInputNumItem extends IMFormBaseItem {
|
|
123
|
+
type: MFormItemTypeEnum.InputNumber;
|
|
124
|
+
props?: InputNumberProps;
|
|
125
|
+
placeholder?: string;
|
|
126
|
+
maxLength?: number;
|
|
127
|
+
}
|
|
128
|
+
export interface IMFormTextItem extends IMFormBaseItem {
|
|
129
|
+
type: MFormItemTypeEnum.Text;
|
|
130
|
+
props?: TextAreaProps;
|
|
131
|
+
placeholder?: string;
|
|
132
|
+
maxLength?: number;
|
|
133
|
+
}
|
|
134
|
+
export interface IMFormRadioGroupItem extends IMFormBaseItem {
|
|
135
|
+
type: MFormItemTypeEnum.Radio;
|
|
136
|
+
props?: RadioGroupProps;
|
|
137
|
+
}
|
|
138
|
+
export interface IMFormCheckBoxGroupItem extends IMFormBaseItem {
|
|
139
|
+
type: MFormItemTypeEnum.Checkbox;
|
|
140
|
+
props?: CheckboxGroupProps;
|
|
141
|
+
}
|
|
142
|
+
export interface IMFormSelectItem<T = any> extends IMFormBaseItem {
|
|
143
|
+
type: MFormItemTypeEnum.Select;
|
|
144
|
+
placeholder?: string;
|
|
145
|
+
props?: SelectProps<T>;
|
|
146
|
+
}
|
|
147
|
+
export interface IMFormDatePickerItem extends IMFormBaseItem {
|
|
148
|
+
type: MFormItemTypeEnum.DatePicker;
|
|
149
|
+
placeholder?: string;
|
|
150
|
+
props?: DatePickerProps;
|
|
151
|
+
}
|
|
152
|
+
export interface IMFormRangePickerItem extends IMFormBaseItem {
|
|
153
|
+
type: MFormItemTypeEnum.RangePicker;
|
|
154
|
+
placeholder?: [string, string];
|
|
155
|
+
props?: RangePickerProps;
|
|
156
|
+
}
|
|
157
|
+
export interface IMFormUploadItem extends IMFormBaseItem {
|
|
158
|
+
type: MFormItemTypeEnum.Upload;
|
|
159
|
+
children?: ReactElement;
|
|
160
|
+
props?: UploadProps;
|
|
161
|
+
}
|
|
162
|
+
export interface IMFormMentionsItem extends IMFormBaseItem {
|
|
163
|
+
type: MFormItemTypeEnum.Mentions;
|
|
164
|
+
placeholder?: string;
|
|
165
|
+
props?: MentionsProps;
|
|
166
|
+
}
|
|
167
|
+
export interface IMFormCascaderItem extends IMFormBaseItem {
|
|
168
|
+
type: MFormItemTypeEnum.Cascader;
|
|
169
|
+
placeholder?: string;
|
|
170
|
+
props?: CascaderAutoProps;
|
|
171
|
+
}
|
|
172
|
+
export interface IMFormTreeSelectItem extends IMFormBaseItem {
|
|
173
|
+
type: MFormItemTypeEnum.TreeSelect;
|
|
174
|
+
placeholder?: string;
|
|
175
|
+
props?: TreeSelectProps;
|
|
176
|
+
}
|
|
177
|
+
export type IMFormItem = IMFormInputItem | IMFormInputNumItem | IMFormSelectItem | IMFormCheckBoxGroupItem | IMFormRadioGroupItem | IMFormTextItem | IMFormDatePickerItem | IMFormRangePickerItem | IMFormUploadItem | IMFormMentionsItem | IMFormCascaderItem | IMFormTreeSelectItem;
|
|
178
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export var MFormItemTypeEnum;
|
|
2
|
+
(function (MFormItemTypeEnum) {
|
|
3
|
+
MFormItemTypeEnum["Input"] = "input";
|
|
4
|
+
MFormItemTypeEnum["InputNumber"] = "inputNumber";
|
|
5
|
+
MFormItemTypeEnum["Text"] = "text";
|
|
6
|
+
MFormItemTypeEnum["Password"] = "password";
|
|
7
|
+
MFormItemTypeEnum["Radio"] = "radio";
|
|
8
|
+
MFormItemTypeEnum["Select"] = "select";
|
|
9
|
+
MFormItemTypeEnum["Checkbox"] = "checkbox";
|
|
10
|
+
MFormItemTypeEnum["DatePicker"] = "datePicker";
|
|
11
|
+
MFormItemTypeEnum["RangePicker"] = "rangePicker";
|
|
12
|
+
MFormItemTypeEnum["Upload"] = "upload";
|
|
13
|
+
MFormItemTypeEnum["Mentions"] = "mentions";
|
|
14
|
+
MFormItemTypeEnum["Cascader"] = "cascader";
|
|
15
|
+
MFormItemTypeEnum["TreeSelect"] = "treeSelect";
|
|
16
|
+
// Slider = 'slider',
|
|
17
|
+
})(MFormItemTypeEnum || (MFormItemTypeEnum = {}));
|
|
18
|
+
// | IMFormSliderItem;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ButtonProps } from 'antd';
|
|
2
|
+
import { FormInstance } from 'antd/lib';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { IMFormItem } from '../MForm';
|
|
5
|
+
import './index.scss';
|
|
6
|
+
export interface IMSearchProps {
|
|
7
|
+
form?: FormInstance;
|
|
8
|
+
/**
|
|
9
|
+
* 需要的数据: [ { label: ...,id: ..., required: ..., type: ..., }, ... ]
|
|
10
|
+
*/
|
|
11
|
+
searchItems: IMFormItem[];
|
|
12
|
+
className?: string;
|
|
13
|
+
/**
|
|
14
|
+
* 搜索按钮 params返回form表单的数据
|
|
15
|
+
*/
|
|
16
|
+
onSearch?: (params: any, isReset: boolean) => any;
|
|
17
|
+
/**
|
|
18
|
+
* 搜索项默认展开,不填写默认false
|
|
19
|
+
*/
|
|
20
|
+
defaultShowAll?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* 自定义按钮
|
|
23
|
+
*/
|
|
24
|
+
customButtons?: ButtonProps[];
|
|
25
|
+
}
|
|
26
|
+
export declare const MSearch: React.FC<IMSearchProps>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons';
|
|
3
|
+
import { Button, Card, Form } from 'antd';
|
|
4
|
+
import { useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { getClassName, removeNull } from '../../utils';
|
|
6
|
+
import MForm from '../MForm';
|
|
7
|
+
import { CompThemeProvider } from '../ThemeContext';
|
|
8
|
+
import './index.scss';
|
|
9
|
+
const ENTER_KEY_CODE = 13; // 回车键的值为13
|
|
10
|
+
const classname = (n = '') => {
|
|
11
|
+
const cn = 'm-search';
|
|
12
|
+
return getClassName(cn, n);
|
|
13
|
+
};
|
|
14
|
+
export const MSearch = props => {
|
|
15
|
+
const { className, searchItems = [], onSearch, defaultShowAll = false, customButtons = [], form: propsForm, } = props;
|
|
16
|
+
const [showAll, setShowAll] = useState(defaultShowAll);
|
|
17
|
+
const [curForm] = Form.useForm();
|
|
18
|
+
const searchWrap = useRef(null);
|
|
19
|
+
const form = propsForm ?? curForm;
|
|
20
|
+
// 键盘按下事件处理
|
|
21
|
+
const onEnterKeySearch = (keyObj) => {
|
|
22
|
+
const { keyCode } = keyObj;
|
|
23
|
+
if (keyCode === ENTER_KEY_CODE) {
|
|
24
|
+
search();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
// 添加和移除事件监听
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const currentWrap = searchWrap.current;
|
|
30
|
+
currentWrap?.addEventListener('keydown', onEnterKeySearch);
|
|
31
|
+
return () => {
|
|
32
|
+
currentWrap?.removeEventListener('keydown', onEnterKeySearch);
|
|
33
|
+
};
|
|
34
|
+
}, []);
|
|
35
|
+
// 重置表单
|
|
36
|
+
const reset = () => {
|
|
37
|
+
form?.resetFields();
|
|
38
|
+
search(true);
|
|
39
|
+
};
|
|
40
|
+
// 搜索函数
|
|
41
|
+
const search = (isReset = false) => {
|
|
42
|
+
form?.validateFields().then(values => {
|
|
43
|
+
removeNull(values);
|
|
44
|
+
onSearch?.(values, isReset);
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
// 渲染搜索按钮
|
|
48
|
+
const renderSearchButtons = () => {
|
|
49
|
+
const hasMore = searchItems.length > 2;
|
|
50
|
+
return (_jsxs("div", { className: classname('btn-wrapper'), children: [customButtons?.length > 0 ? (_jsx(_Fragment, { children: customButtons.map((buttonProps, index) => (_jsx(Button, { className: classname('btn'), ...buttonProps, children: buttonProps.children }, `custom-btn-${index}`))) })) : (_jsxs(_Fragment, { children: [_jsx(Button, { className: classname('btn btn-reset'), onClick: reset, children: "\u91CD\u7F6E" }), _jsx(Button, { className: classname('btn btn-search'), onClick: () => search(), type: 'primary', children: "\u641C\u7D22" })] })), hasMore && (_jsxs("div", { className: classname('btn btn-collapse'), onClick: () => setShowAll(!showAll), children: [_jsx("span", { children: showAll ? '收起' : '展开' }), showAll ? _jsx(CaretUpOutlined, {}) : _jsx(CaretDownOutlined, {})] }))] }));
|
|
51
|
+
};
|
|
52
|
+
// 处理搜索项显示/隐藏
|
|
53
|
+
const processedSearchItems = searchItems.map((item, idx) => {
|
|
54
|
+
const newItem = { ...item };
|
|
55
|
+
if (searchItems.length > 2 && idx >= 2 && !showAll) {
|
|
56
|
+
newItem.formItemProps = {
|
|
57
|
+
...item.formItemProps,
|
|
58
|
+
style: {
|
|
59
|
+
...item.formItemProps?.style,
|
|
60
|
+
display: 'none',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return newItem;
|
|
65
|
+
});
|
|
66
|
+
const hasMore = searchItems.length > 2;
|
|
67
|
+
return (_jsx(CompThemeProvider, { children: _jsx("div", { className: `${classname('')} ${showAll ? '' : classname('collapsed')} ${className || ''}`, ref: searchWrap, children: _jsxs(Card, { children: [_jsxs("div", { className: classname('form'), children: [_jsx(MForm, { form: form, formItems: processedSearchItems, column: 3 }), (!hasMore || (hasMore && !showAll)) && renderSearchButtons()] }), hasMore && showAll && _jsx("div", { className: classname('footer'), children: renderSearchButtons() })] }) }) }));
|
|
68
|
+
};
|
package/dist/components/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export * from './ItemsRow';
|
|
2
2
|
export * from './MBreadcrumb';
|
|
3
3
|
export * from './MDescriptions';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
export * from './MForm';
|
|
5
|
+
export { default as MForm } from './MForm';
|
|
6
6
|
// export * from './MiModal';
|
|
7
|
-
|
|
7
|
+
export * from './MSearch';
|
|
8
8
|
export * from './MTable';
|
|
9
9
|
export * from './ThemeContext';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
|
|
2
|
+
export type UseFuncRequestOptions<T extends (...args: any[]) => Promise<any>> = {
|
|
3
|
+
autoRunArgs?: Parameters<T>;
|
|
4
|
+
onBefore?: (...args: Parameters<T>) => boolean | Promise<boolean>;
|
|
5
|
+
onSuccess?: (data: UnwrapPromise<ReturnType<T>>) => void | Promise<void>;
|
|
6
|
+
onError?: (error: Error) => void | Promise<void>;
|
|
7
|
+
onFinally?: () => void | Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare function useFuncRequest<T extends (...args: any[]) => Promise<any>>(asyncFunc: T, options?: UseFuncRequestOptions<T>): {
|
|
10
|
+
run: (...args: Parameters<T>) => Promise<any>;
|
|
11
|
+
cancel: () => void;
|
|
12
|
+
loading: boolean;
|
|
13
|
+
error: Error | null;
|
|
14
|
+
data: UnwrapPromise<ReturnType<T>> | null;
|
|
15
|
+
};
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
export function useFuncRequest(
|
|
3
|
+
// 异步函数
|
|
4
|
+
asyncFunc,
|
|
5
|
+
// 配置项
|
|
6
|
+
options) {
|
|
7
|
+
const [loading, setLoading] = useState(false);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
const [data, setData] = useState(null);
|
|
10
|
+
const abortControllerRef = useRef(undefined);
|
|
11
|
+
const requestIdRef = useRef(0);
|
|
12
|
+
const cancel = () => {
|
|
13
|
+
abortControllerRef.current?.abort();
|
|
14
|
+
setLoading(false);
|
|
15
|
+
setError(null);
|
|
16
|
+
};
|
|
17
|
+
const run = async (...args) => {
|
|
18
|
+
const currentRequestId = ++requestIdRef.current;
|
|
19
|
+
cancel();
|
|
20
|
+
const abortController = new AbortController();
|
|
21
|
+
abortControllerRef.current = abortController;
|
|
22
|
+
try {
|
|
23
|
+
setLoading(true);
|
|
24
|
+
setError(null);
|
|
25
|
+
if (options?.onBefore) {
|
|
26
|
+
const beforeRes = await options?.onBefore?.(...args);
|
|
27
|
+
if (!beforeRes) {
|
|
28
|
+
cancel();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// 安全传递 AbortSignal
|
|
33
|
+
const funcArgs = args.length >= asyncFunc.length
|
|
34
|
+
? args
|
|
35
|
+
: [...args, { signal: abortController.signal }];
|
|
36
|
+
const res = await asyncFunc(...funcArgs);
|
|
37
|
+
if (!abortController.signal.aborted &&
|
|
38
|
+
currentRequestId === requestIdRef.current) {
|
|
39
|
+
setData(res);
|
|
40
|
+
await options?.onSuccess?.(res);
|
|
41
|
+
}
|
|
42
|
+
return res;
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
if (!abortController.signal.aborted &&
|
|
46
|
+
currentRequestId === requestIdRef.current) {
|
|
47
|
+
setError(err);
|
|
48
|
+
await options?.onError?.(err);
|
|
49
|
+
}
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
if (!abortController.signal.aborted &&
|
|
54
|
+
currentRequestId === requestIdRef.current) {
|
|
55
|
+
setLoading(false);
|
|
56
|
+
await options?.onFinally?.();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (options?.autoRunArgs) {
|
|
62
|
+
run(...options.autoRunArgs).catch(() => { });
|
|
63
|
+
}
|
|
64
|
+
return cancel;
|
|
65
|
+
}, [JSON.stringify(options?.autoRunArgs)]);
|
|
66
|
+
return { run, cancel, loading, error, data };
|
|
67
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
function useInterval(callback, delay, immediate = false) {
|
|
3
|
+
const timerRef = useRef(undefined);
|
|
4
|
+
const savedCallback = useRef(callback);
|
|
5
|
+
// Update callback ref if callback changes
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
savedCallback.current = callback;
|
|
8
|
+
}, [callback]);
|
|
9
|
+
const clear = useCallback(() => {
|
|
10
|
+
if (timerRef.current) {
|
|
11
|
+
clearInterval(timerRef.current);
|
|
12
|
+
timerRef.current = undefined;
|
|
13
|
+
}
|
|
14
|
+
}, []);
|
|
15
|
+
const start = useCallback(() => {
|
|
16
|
+
clear();
|
|
17
|
+
if (delay !== null && delay !== undefined) {
|
|
18
|
+
timerRef.current = setInterval(() => savedCallback.current(), delay);
|
|
19
|
+
}
|
|
20
|
+
}, [delay, clear]);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (immediate) {
|
|
23
|
+
savedCallback.current();
|
|
24
|
+
}
|
|
25
|
+
start();
|
|
26
|
+
return clear;
|
|
27
|
+
}, [delay, start, clear, immediate]);
|
|
28
|
+
return { start, clear, isRunning: !!timerRef.current };
|
|
29
|
+
}
|
|
30
|
+
export { useInterval };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
interface IPaginationProps {
|
|
2
|
+
current: number;
|
|
3
|
+
pageSize: number;
|
|
4
|
+
total: number;
|
|
5
|
+
onChange: (page: number, pageSize: number) => Promise<void>;
|
|
6
|
+
onShowSizeChange: (size: number, current: number) => Promise<void>;
|
|
7
|
+
showTotal?: (t: number) => React.ReactNode;
|
|
8
|
+
showQuickJumper?: boolean;
|
|
9
|
+
showSizeChanger?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface PaginationResult<T> {
|
|
12
|
+
tableProps: {
|
|
13
|
+
loading?: boolean;
|
|
14
|
+
dataSource: T[];
|
|
15
|
+
};
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
dataSource: T[];
|
|
18
|
+
paginationProps: IPaginationProps;
|
|
19
|
+
isFirstComplete: boolean;
|
|
20
|
+
refresh: (resetPage?: boolean) => Promise<void>;
|
|
21
|
+
debounceRefresh: (resetPage?: boolean) => void;
|
|
22
|
+
setDataSource: (data: T[]) => void;
|
|
23
|
+
}
|
|
24
|
+
interface IServerParams {
|
|
25
|
+
offset: number;
|
|
26
|
+
limit: number;
|
|
27
|
+
current: number;
|
|
28
|
+
}
|
|
29
|
+
type IInfoBack<T> = {
|
|
30
|
+
dataSource: T[];
|
|
31
|
+
total: number;
|
|
32
|
+
};
|
|
33
|
+
type IInfoServer<T> = (params: IServerParams) => IInfoBack<T> | Promise<IInfoBack<T>>;
|
|
34
|
+
interface IInfoOption<T> {
|
|
35
|
+
isReady?: boolean;
|
|
36
|
+
dataSource?: T[];
|
|
37
|
+
current?: number;
|
|
38
|
+
pageSize?: number;
|
|
39
|
+
}
|
|
40
|
+
export declare const usePagination: <T>(server: IInfoServer<T>, deps?: any[], // 依赖条件 数据更新默认执行server
|
|
41
|
+
option?: IInfoOption<T>) => PaginationResult<T>;
|
|
42
|
+
export {};
|