kn-hooks 0.0.9 → 0.0.10
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/package.json +10 -2
- package/readme.md +17 -196
- package/src/index.js +7 -2
- package/src/useClipboard/index.js +30 -7
- package/src/useCounter/index.js +34 -0
- package/src/useDictionary/index.js +96 -26
- package/src/usePagination/index.js +264 -0
- package/src/usePaginationWithForm/index.js +86 -0
- package/src/useSwitch/index.js +23 -8
- package/test/useCounter/index.jsx +15 -0
- package/test/usePagination/index.jsx +119 -0
- package/test/usePaginationWithForm/index.jsx +101 -0
- package/test/useSwitch/index.jsx +2 -5
- package/src/.DS_Store +0 -0
- package/src/useAntdFormTableSearch/index.js +0 -165
- package/src/useRefSwitch/index.js +0 -15
- package/test/.DS_Store +0 -0
- package/test/useRefSwitch/index.jsx +0 -19
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kn-hooks",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "cross-env env_api=dev env_package=dev webpack-dev-server --progress",
|
|
6
6
|
"build": "cross-env env_api=prod env_package=prod webpack --config webpack.config.js",
|
|
7
7
|
"build:dev": "cross-env env_api=dev env_package=dev webpack",
|
|
8
|
-
"report": "cross-env env_api=prod env_package=prod report=true webpack --config webpack.test.config.js"
|
|
8
|
+
"report": "cross-env env_api=prod env_package=prod report=true webpack --config webpack.test.config.js",
|
|
9
|
+
"doc": "./node_modules/.bin/jsdoc src/**/*.js --configure .jsdoc.json --verbose",
|
|
10
|
+
"md": "./node_modules/.bin/jsdoc2md --plugin ./dmd/lib/index.js --files src/useRollingPagination/*.js src/useSwitch/*.js > md/api.md"
|
|
9
11
|
},
|
|
10
12
|
"main": "src/index.js",
|
|
11
13
|
"dependencies": {
|
|
@@ -32,13 +34,19 @@
|
|
|
32
34
|
"babel-plugin-import": "^1.13.3",
|
|
33
35
|
"cross-env": "7.0.3",
|
|
34
36
|
"css-loader": "3.4.2",
|
|
37
|
+
"dmd-bitbucket": "^0.1.10",
|
|
38
|
+
"dmd-plugin-example": "^0.1.0",
|
|
39
|
+
"docdash": "^2.0.1",
|
|
35
40
|
"html-webpack-plugin": "4.0.3",
|
|
41
|
+
"jsdoc": "^4.0.2",
|
|
42
|
+
"jsdoc-to-markdown": "^8.0.0",
|
|
36
43
|
"mini-css-extract-plugin": "0.9.0",
|
|
37
44
|
"react": "16.13.0",
|
|
38
45
|
"react-dom": "16.13.0",
|
|
39
46
|
"rollup": "^2.50.5",
|
|
40
47
|
"rollup-plugin-jsx": "^1.0.3",
|
|
41
48
|
"rollup-plugin-terser": "^7.0.2",
|
|
49
|
+
"taffydb": "^2.7.3",
|
|
42
50
|
"terser-webpack-plugin": "4.2.3",
|
|
43
51
|
"webpack": "4.46.0",
|
|
44
52
|
"webpack-bundle-analyzer": "3.6.1",
|
package/readme.md
CHANGED
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## 目录
|
|
4
4
|
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* [使用方法](#start)
|
|
6
|
+
* [按需打包](#package)
|
|
7
|
+
|
|
8
|
+
* API
|
|
9
|
+
* [useDictionary - 字典管理及下拉选项框渲染](md/useDictionary.md)
|
|
10
|
+
* [useSwitch - 开关控制](md/useSwitch.md)
|
|
11
|
+
* [useClipboard - 剪贴板](md/useClipboard.md)
|
|
12
|
+
* [useCounter - 计数器](md/useCounter.md)
|
|
13
|
+
* [usePagination - 分页管理](md/usePagination.md)
|
|
14
|
+
* [usePaginationWithForm - 支持Antd-From的分页管理](md/usePaginationWithForm.md)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
<a id='start'></a>
|
|
10
19
|
|
|
11
20
|
## 使用方法
|
|
12
21
|
|
|
@@ -25,200 +34,12 @@ const Index=()=>{
|
|
|
25
34
|
```
|
|
26
35
|
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
控制开关
|
|
31
|
-
|
|
32
|
-
#### Demo
|
|
33
|
-
[](https://codesandbox.io/s/useswitch-qd7dr?file=/index.js)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
#### API
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
const result:Result = useSwitch(switch?:boolean);
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
#### Params
|
|
43
|
-
|
|
44
|
-
参数|说明|类型|默认值
|
|
45
|
-
--|:--:|:--:|--:
|
|
46
|
-
?switch|默认为打开还是关闭状态|boolean|false
|
|
47
|
-
|
|
48
|
-
#### Result: Object
|
|
49
|
-
|
|
50
|
-
参数|说明|类型
|
|
51
|
-
--|:--:|--:
|
|
52
|
-
state|当前开关状态|boolean
|
|
53
|
-
count|当前开关计数器|number
|
|
54
|
-
toggle|切换开关|()=>void
|
|
55
|
-
open|打开开关|(force?: boolean)=>void
|
|
56
|
-
close|关闭开关|(force?: boolean)=>void
|
|
57
|
-
|
|
58
|
-
> 当使用open和close控制开关时为成对计数模式
|
|
59
|
-
> 每次open都会增加`开计数器`,而每次close会减少`开计数器`
|
|
60
|
-
> 当`开计数器`为0时才会真正关闭开关
|
|
61
|
-
|
|
62
|
-
##### open: (force?: boolean)=>void
|
|
63
|
-
|
|
64
|
-
参数|说明|类型|默认值
|
|
65
|
-
--|:--:|:--:|--:
|
|
66
|
-
?force|是否强制切换到打开状态|boolean|false
|
|
67
|
-
|
|
68
|
-
##### close: (force?: boolean)=>void
|
|
69
|
-
|
|
70
|
-
参数|说明|类型|默认值
|
|
71
|
-
--|:--:|:--:|--:
|
|
72
|
-
?force|是否强制切换到关闭状态|boolean|false
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
## @useRefSwitch
|
|
76
|
-
|
|
77
|
-
useSwitch的ref版本,返回的是一个useRef,使用时通过 current 来访问switch对象
|
|
78
|
-
|
|
79
|
-
```javascript
|
|
80
|
-
const loading = useRefSwitch();
|
|
81
|
-
return (
|
|
82
|
-
<p>{loading.current.state}</p>
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## @useClipboard
|
|
88
|
-
|
|
89
|
-
将字符串复制到剪贴板
|
|
90
|
-
|
|
91
|
-
#### Demo
|
|
92
|
-
|
|
93
|
-
[](https://codesandbox.io/s/useclipboard-b4ryc?file=/index.js)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
#### API
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
const result:Result = useClipboard(onSuccess?: ()=>void);
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
#### Params
|
|
103
|
-
|
|
104
|
-
参数|说明|类型|默认值
|
|
105
|
-
--|:--:|:--:|--:
|
|
106
|
-
onSuccess|默认的成功回调函数|()=>void|无
|
|
107
|
-
|
|
108
|
-
#### Result: (text,onSuccess)=>void
|
|
109
|
-
|
|
110
|
-
参数|说明|类型
|
|
111
|
-
--|:--:|--:
|
|
112
|
-
text|需要复制的字符串|string|无
|
|
113
|
-
?onSuccess|成功回调|()=>void|无
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
## @useDictionary
|
|
118
|
-
|
|
119
|
-
字典管理
|
|
120
|
-
|
|
121
|
-
#### DEMO
|
|
122
|
-
|
|
123
|
-
[](https://codesandbox.io/s/usedictionary-j7cw8?file=/index.js)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
#### API
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
const result:Result = useDictionary({
|
|
130
|
-
api:()=>Promise,
|
|
131
|
-
});
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
#### Params
|
|
135
|
-
|
|
136
|
-
参数|说明|类型|默认值
|
|
137
|
-
--|:--:|:--:|--:
|
|
138
|
-
api|获取字典数据的接口函数|()=>Promise|无
|
|
139
|
-
?beforeApi|调用接口前的钩子,用于处理传参|(params)=>any|无
|
|
140
|
-
?afterApi|调用接口后的钩子,用于处理返回结果|(params)=>TypeItem[]|无
|
|
141
|
-
?SelectOption|指定<Select.Option>对象|any|无
|
|
142
|
-
?RadioOption|指定<Radio.Button>对象|any|无
|
|
143
|
-
?idKey|字典项目中id的键值名|string|id
|
|
144
|
-
?nameKey|字典项目中name的键值名|string|name
|
|
145
|
-
?labelKey|字典项目中label的键值名|string|label
|
|
146
|
-
|
|
147
|
-
#### TypeItem-字典项数据结构
|
|
148
|
-
|
|
149
|
-
参数|说明|类型|默认值
|
|
150
|
-
--|:--:|:--:|--:
|
|
151
|
-
id|数据唯一id|string|无
|
|
152
|
-
name|数据唯一id对应的别名|string|无
|
|
153
|
-
label|展示给用户看的文字|string|无
|
|
154
|
-
|
|
155
|
-
#### Result: Object
|
|
156
|
-
|
|
157
|
-
参数|说明|类型
|
|
158
|
-
--|:--:|--:
|
|
159
|
-
types|字典项的值|TypeItem[]
|
|
160
|
-
selectOptions|供渲染<Select>的列表,Antd下用|any
|
|
161
|
-
radioOptions|供渲染<Radio>的列表,Antd下用|any
|
|
162
|
-
getId|搜索字典项中,label或name匹配labelOrName的项目,返回其id的值|(labelOrName:string)=>string
|
|
163
|
-
getName|搜索字典项中,id匹配id的项目,返回其name的值|(id:string)=>string
|
|
164
|
-
getLabel|搜索字典项中,id匹配id的项目,返回其label的值|(id:string)=>string
|
|
165
|
-
reload|重新调用字典接口刷新字典列表|()=>void
|
|
166
|
-
|
|
167
|
-
#### useDictionary.SET({SelectOption,RadioOption})=>void
|
|
168
|
-
全局指定渲染selectbox和radio的组件
|
|
169
|
-
|
|
170
|
-
参数|说明|类型
|
|
171
|
-
--|:--:|--:
|
|
172
|
-
SelectOption|对应Antd里 Select.Option|antd组件
|
|
173
|
-
RadioOption|对应Antd里 Radio.Button|antd组件
|
|
174
|
-
|
|
175
|
-
#### Example
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
import {Select,Radio} from 'antd';
|
|
179
|
-
import useDictionary from '@/useDictionary';
|
|
180
|
-
useDictionary.SET({SelectOption:Select.Option,RadioOption:Radio.Button});
|
|
181
|
-
|
|
182
|
-
const Index=()=>{
|
|
183
|
-
|
|
184
|
-
const emCity = useDictionary({
|
|
185
|
-
api:()=>{
|
|
186
|
-
return new Promise(resolve=>{
|
|
187
|
-
resolve({
|
|
188
|
-
code:0,
|
|
189
|
-
data:{
|
|
190
|
-
body:[
|
|
191
|
-
{id:1,name:'shanghai',label:'上海'},
|
|
192
|
-
{id:2,name:'beijing',label:'北京'},
|
|
193
|
-
{id:3,name:'guangzhou',label:'广州'}
|
|
194
|
-
]
|
|
195
|
-
}
|
|
196
|
-
})
|
|
197
|
-
})
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
return (
|
|
202
|
-
<section >
|
|
203
|
-
<Select defaultValue={1}>
|
|
204
|
-
{
|
|
205
|
-
emCity.selectOptions
|
|
206
|
-
}
|
|
207
|
-
</Select>
|
|
208
|
-
<p>分割线</p>
|
|
209
|
-
<Radio.Group defaultValue={1}>
|
|
210
|
-
{
|
|
211
|
-
emCity.radioOptions
|
|
212
|
-
}
|
|
213
|
-
</Radio.Group>
|
|
214
|
-
</section>
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
37
|
+
<a id='package'></a>
|
|
219
38
|
|
|
220
39
|
## 按需打包
|
|
221
40
|
|
|
41
|
+
> webpack4及以上版本无需下面配置
|
|
42
|
+
|
|
222
43
|
webpack增加`bable-plugin-import`插件,给babel plugins增加配置
|
|
223
44
|
```javascript
|
|
224
45
|
// rules: [
|
package/src/index.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import useClipboard from './useClipboard/index.js';
|
|
2
2
|
import useSwitch from './useSwitch/index.js';
|
|
3
|
-
import useRefSwitch from './useRefSwitch/index.js';
|
|
4
3
|
import useDictionary from './useDictionary/index.js';
|
|
4
|
+
import useCounter from './useCounter/index.js';
|
|
5
|
+
import usePagination from './usePagination/index.js';
|
|
6
|
+
import usePaginationWithForm from './usePaginationWithForm/index.js';
|
|
7
|
+
|
|
5
8
|
|
|
6
9
|
export {
|
|
7
10
|
useClipboard,
|
|
8
11
|
useSwitch,
|
|
9
|
-
useRefSwitch,
|
|
10
12
|
useDictionary,
|
|
13
|
+
useCounter,
|
|
14
|
+
usePagination,
|
|
15
|
+
usePaginationWithForm
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
|
|
@@ -1,17 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module useClipboard
|
|
3
|
+
*/
|
|
1
4
|
import { useState, useMemo, useEffect, useRef } from 'react';
|
|
2
5
|
import ClipboardJS from 'clipboard';
|
|
3
6
|
|
|
7
|
+
|
|
4
8
|
/**
|
|
5
9
|
* 剪贴板工具
|
|
6
|
-
* props:{
|
|
7
|
-
* onSuccess?: Function;//复制成功后的通用回调
|
|
8
|
-
* }
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* )=>void
|
|
11
|
+
* [Demo - CodeSandBox]{@link https://codesandbox.io/s/useclipboard-b4ryc?file=/index.js}
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} [props] -
|
|
14
|
+
* @param {callback} [props.onSuccess] - 成功复制到剪贴板后的回调 ()=>void
|
|
15
|
+
* @return {UseClipboardResult}
|
|
14
16
|
*
|
|
17
|
+
* @example
|
|
18
|
+
const clipboard= useClipboard();
|
|
19
|
+
const onCopy=()=>{
|
|
20
|
+
clipboard.copy('text',()=>{console.log('success')})
|
|
21
|
+
}
|
|
15
22
|
*/
|
|
16
23
|
const useClipboard = (props) => {
|
|
17
24
|
const { onSuccess } = props;
|
|
@@ -77,4 +84,20 @@ const useClipboard = (props) => {
|
|
|
77
84
|
return actions;
|
|
78
85
|
};
|
|
79
86
|
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 复制函数
|
|
90
|
+
* @typedef {callback} FunCopy
|
|
91
|
+
* @property {string} text - 需要被复制的字符串
|
|
92
|
+
* @property {callback} onCurSuccess - 复制成功的回调 ()=>void
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* UseClipboardResult返回的hook
|
|
98
|
+
* @typedef {Object} UseClipboardResult
|
|
99
|
+
* @property {FunCopy} copy - 触发复制字符串的函数
|
|
100
|
+
*
|
|
101
|
+
*/
|
|
102
|
+
|
|
80
103
|
export default useClipboard;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module useCounter
|
|
3
|
+
*/
|
|
4
|
+
import { useState, useMemo } from 'react';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 加法计数器
|
|
9
|
+
* @return {UseCounterResult}
|
|
10
|
+
* @example
|
|
11
|
+
const counter= useCounter();
|
|
12
|
+
const onAdd=()=>{counter.addCount()}
|
|
13
|
+
return <span>当前计数器:{counter.count}</span>
|
|
14
|
+
*/
|
|
15
|
+
const useCounter = () => {
|
|
16
|
+
const [count,setCount] = useState(1);
|
|
17
|
+
const action = useMemo(()=>{
|
|
18
|
+
return {
|
|
19
|
+
count,
|
|
20
|
+
addCount:()=>{setCount(v=>v+1)}
|
|
21
|
+
}
|
|
22
|
+
},[count,setCount]);
|
|
23
|
+
return action;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef UseCounterResult
|
|
28
|
+
* @property {Object} req
|
|
29
|
+
* @property {number} req.count - 当前计数器的值
|
|
30
|
+
* @property {function} req.addCount - 计数器的值+1。 ()=>void
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
export default useCounter;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module useDictionary
|
|
3
|
+
*/
|
|
1
4
|
import React,{ useState, useMemo, useEffect } from 'react';
|
|
2
5
|
|
|
3
6
|
const DEFAULT_CONFIG={
|
|
@@ -7,37 +10,62 @@ const DEFAULT_CONFIG={
|
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* 字典管理
|
|
10
|
-
* props:{
|
|
11
|
-
* api:async ()=>any, 调用字段查询的接口函数,默认返回的数据格式为{ code:0 ,data:{body:[{label:'',id:'',name:''},]}}
|
|
12
|
-
* beforeApi?: (params:any)=>any , 调用接口前的钩子,用于处理接口的参数
|
|
13
|
-
* afterApi?: (response:any)=>any[], 接口调用后的钩子,用于处理接口返回的值
|
|
14
|
-
* SelectOption?: any, 指定<Select.Option>对象是谁
|
|
15
|
-
* RadioOption?: any, 指定<Radio.Button>对象是谁
|
|
16
|
-
* idKey?: string,//字段id的key键值
|
|
17
|
-
* nameKey?: string,//字段name的key键值
|
|
18
|
-
* labelKey?: string,//字段label的key键值
|
|
19
|
-
* }
|
|
20
|
-
* 字典数据的结构为
|
|
21
|
-
* {
|
|
22
|
-
* id:'',数据唯一id
|
|
23
|
-
* name:'',数据唯一id对应的别名
|
|
24
|
-
* label:'',展示给用户看的文字
|
|
25
|
-
* }
|
|
26
13
|
*
|
|
14
|
+
* [Demo - CodeSandBox]{@link https://codesandbox.io/s/usedictionary-j7cw8?file=/index.js}
|
|
27
15
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* }
|
|
16
|
+
* @param {Object} props
|
|
17
|
+
* @param {Api} props.api - 用于获取字典列表的接口
|
|
18
|
+
* @param {string} [props.idKey='id'] - 字段id的key键值
|
|
19
|
+
* @param {string} [props.nameKey='name'] - 字段name的key键值
|
|
20
|
+
* @param {string} [props.labelKey='label'] - 字段label的key键值
|
|
21
|
+
* @param {ReactDom} [props.SelectOption] - 指定\<Select.Option\>对象是谁
|
|
22
|
+
* @param {ReactDom} [props.RadioOption] - 指定\<Radio.Button\>对象是谁
|
|
23
|
+
* @param {callback} [props.beforeApi] - (request:object)=>object 接口调用前的参数拦截器
|
|
24
|
+
* @param {callback} [props.afterApi] - (reponse:object)=>object[] 接口调用后的拦截器
|
|
37
25
|
*
|
|
38
|
-
* useDictionary.SET:({SelectOption,RadioOption})=>void,全局设置SelectOption和RadioOption
|
|
39
26
|
*
|
|
27
|
+
* @return {UseDictionaryResult}
|
|
40
28
|
*
|
|
29
|
+
* @example
|
|
30
|
+
import {Select,Radio} from 'antd';
|
|
31
|
+
import useDictionary from '@/useDictionary';
|
|
32
|
+
useDictionary.SET({SelectOption:Select.Option,RadioOption:Radio.Button});
|
|
33
|
+
|
|
34
|
+
const Index=()=>{
|
|
35
|
+
|
|
36
|
+
const emCity = useDictionary({
|
|
37
|
+
api:()=>{
|
|
38
|
+
return new Promise(resolve=>{
|
|
39
|
+
resolve({
|
|
40
|
+
code:0,
|
|
41
|
+
data:{
|
|
42
|
+
body:[
|
|
43
|
+
{id:1,name:'shanghai',label:'上海'},
|
|
44
|
+
{id:2,name:'beijing',label:'北京'},
|
|
45
|
+
{id:3,name:'guangzhou',label:'广州'}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<section >
|
|
55
|
+
<Select defaultValue={1}>
|
|
56
|
+
{
|
|
57
|
+
emCity.selectOptions
|
|
58
|
+
}
|
|
59
|
+
</Select>
|
|
60
|
+
<p>分割线</p>
|
|
61
|
+
<Radio.Group defaultValue={1}>
|
|
62
|
+
{
|
|
63
|
+
emCity.radioOptions
|
|
64
|
+
}
|
|
65
|
+
</Radio.Group>
|
|
66
|
+
</section>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
41
69
|
*/
|
|
42
70
|
const useDictionary=(props)=>{
|
|
43
71
|
|
|
@@ -153,4 +181,46 @@ export const SetConfig = ({SelectOption,RadioOption})=>{
|
|
|
153
181
|
if(RadioOption)DEFAULT_CONFIG.RadioOption = RadioOption;
|
|
154
182
|
};
|
|
155
183
|
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @typedef Api
|
|
188
|
+
* @property {Object} params - 调用接口用到的参数
|
|
189
|
+
* @returns {Object}
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* @typedef DictionaryItem
|
|
196
|
+
* 字典数据的结构
|
|
197
|
+
* @property {string} id - 数据唯一ID
|
|
198
|
+
* @property {string} name - 数据唯一id对应的别名
|
|
199
|
+
* @property {string} label - 展示给用户看的文字
|
|
200
|
+
*
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @typedef UseDictionaryResult
|
|
205
|
+
* @property {DictionaryItem[]} types - 字典数据列表
|
|
206
|
+
* @property {ReactDOM[]} selectOptions - 供Antd渲染\<Select\>的列表
|
|
207
|
+
* @property {ReactDOM[]} radioOptions - 供Antd渲染\<Radio\>的列表
|
|
208
|
+
* @property {function} getId - (labelOrName:string)=>string,搜索字典项中,label或name匹配labelOrName的项目,返回其id的值
|
|
209
|
+
* @property {function} getName - (id:string)=>string,搜索字典项中,id匹配id的项目,返回其name的值
|
|
210
|
+
* @property {function} getLabel - (id:string)=>string,搜索字典项中,id匹配id的项目,返回其label的值
|
|
211
|
+
* @property {function} reload - ()=>void,重新调用字典接口刷新字典列表
|
|
212
|
+
*
|
|
213
|
+
*/
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @function SET
|
|
217
|
+
* @description 全局设置SelectOption和RadioOption
|
|
218
|
+
*
|
|
219
|
+
* @param {Object} params
|
|
220
|
+
* @param {ReactDom} params.SelectOption - Antd的SelectOption组件
|
|
221
|
+
* @param {ReactDom} params.RadioOption - Antd的SelectOption组件
|
|
222
|
+
* @returns {void}
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
|
|
156
226
|
export default useDictionary
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @module usePagination
|
|
4
|
+
*/
|
|
5
|
+
import { useState,useMemo,useRef } from 'react';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 分页管理器
|
|
9
|
+
* @param {Object} props
|
|
10
|
+
* @param {function} props.service - 发送请求的方法,默认分页使用current和pageSize,如有特殊需求通过beforeService拦截处理
|
|
11
|
+
* @param {Pagination} [props.pagination] - 默认分页信息
|
|
12
|
+
* @version 1.0.0
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
// 移动端滚动加载案例
|
|
16
|
+
const page = usePagination({
|
|
17
|
+
service:GET_LIST,
|
|
18
|
+
pagination:{pageSize:10},
|
|
19
|
+
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
useEffect(()=>{
|
|
23
|
+
const fnFeforeService = (params)=>{
|
|
24
|
+
// 假如你这里需要变更接口字段名称的话
|
|
25
|
+
params.page=params.current;
|
|
26
|
+
params.keyword='abc';
|
|
27
|
+
return params;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const fnAfterService = (response)=>{
|
|
31
|
+
// 这里你可以翻译及二次处理你的接口字段
|
|
32
|
+
let req={
|
|
33
|
+
code:response.errorCode
|
|
34
|
+
data:response.list,
|
|
35
|
+
page:response.pageInfo
|
|
36
|
+
};
|
|
37
|
+
response.code=response;
|
|
38
|
+
return response;
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
page.addListener('beforeService',fnFeforeService);
|
|
42
|
+
page.addListener('afterService',fnAfterService);
|
|
43
|
+
return ()=>{
|
|
44
|
+
page.removeListener('beforeService',fnFeforeService);
|
|
45
|
+
page.removeListener('afterService',fnAfterService)
|
|
46
|
+
}
|
|
47
|
+
},[])
|
|
48
|
+
|
|
49
|
+
const onReset=()=>{page.reset();}
|
|
50
|
+
|
|
51
|
+
const onPageChange=()=>{
|
|
52
|
+
let value=document.querySelector('#inputPage').value;
|
|
53
|
+
page.update({pagination:{current:+value}})
|
|
54
|
+
}
|
|
55
|
+
const onNext=()=>{page.nextPage();}
|
|
56
|
+
|
|
57
|
+
const renderTable=()=>{
|
|
58
|
+
let renderData= [];
|
|
59
|
+
page?.data?.forEach(list=>{
|
|
60
|
+
renderData=[...renderData,...list];
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<ul>
|
|
65
|
+
{
|
|
66
|
+
renderData?.map((item,idx)=>{
|
|
67
|
+
return <li key={idx}>[{idx}]{item}</li>
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
</ul>
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
return (
|
|
75
|
+
<ul>
|
|
76
|
+
{renderTable()}
|
|
77
|
+
</ul>
|
|
78
|
+
)
|
|
79
|
+
*
|
|
80
|
+
* @returns {UsePaginationResult}
|
|
81
|
+
*/
|
|
82
|
+
const usePagination=(props)=>{
|
|
83
|
+
|
|
84
|
+
const {service}= props;
|
|
85
|
+
|
|
86
|
+
const DEFAULT_PAGE_SIZE=20;
|
|
87
|
+
const DEFAULT_PAGE_CURRENT=1;
|
|
88
|
+
const [pagination,setPagination] = useState({
|
|
89
|
+
current: DEFAULT_PAGE_CURRENT,
|
|
90
|
+
pageSize: props?.pagination?.pageSize??DEFAULT_PAGE_SIZE
|
|
91
|
+
});
|
|
92
|
+
const [data,setData] = useState(null);
|
|
93
|
+
const refListener= useRef({
|
|
94
|
+
beforeService:[],
|
|
95
|
+
afterService:[]
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const update= async ({pagination:_pagination,clear=false}={})=>{
|
|
99
|
+
_pagination = _pagination ?? pagination;
|
|
100
|
+
_pagination = {...pagination,..._pagination};
|
|
101
|
+
|
|
102
|
+
const {current,pageSize} = _pagination;
|
|
103
|
+
|
|
104
|
+
let params = {current,pageSize};
|
|
105
|
+
let listener=refListener.current;
|
|
106
|
+
const {beforeService} = listener;
|
|
107
|
+
if(beforeService){
|
|
108
|
+
console.log('[usePagination] beforeService',params)
|
|
109
|
+
for(let i=0;i<beforeService.length;i++){
|
|
110
|
+
params = beforeService[i](params);
|
|
111
|
+
if(typeof params?.then == 'function'){
|
|
112
|
+
params = await params;
|
|
113
|
+
}
|
|
114
|
+
if(!params){return;}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if(!params)requrn;
|
|
118
|
+
console.log('[usePagination] service',params)
|
|
119
|
+
let req = await service(params);
|
|
120
|
+
const {afterService} = listener;
|
|
121
|
+
if(afterService){
|
|
122
|
+
console.log('[usePagination] afterService',req)
|
|
123
|
+
for(let i=0;i<afterService.length;i++){
|
|
124
|
+
req = afterService[i](req);
|
|
125
|
+
if( typeof req?.then == 'function' ){
|
|
126
|
+
req = await req;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
console.log('[usePagination] response',req)
|
|
131
|
+
let response={};
|
|
132
|
+
if(req?.code==0){
|
|
133
|
+
let {page:{current,pageSize,total},data:reqData} = req;
|
|
134
|
+
current=+current;
|
|
135
|
+
pageSize=+pageSize;
|
|
136
|
+
total=+total;
|
|
137
|
+
const startIdx= (current-1)*pageSize;
|
|
138
|
+
const more = current*pageSize<total;
|
|
139
|
+
response.pagination={
|
|
140
|
+
current,pageSize,total,startIdx,more
|
|
141
|
+
};
|
|
142
|
+
setPagination(response.pagination);
|
|
143
|
+
response.data= clear?[]:(data||[]);
|
|
144
|
+
|
|
145
|
+
if(response.data.length<current){
|
|
146
|
+
for(let i=0;i<current;i++){
|
|
147
|
+
response.data[i]=response.data[i]||[];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
let pageIdx= current-1;
|
|
151
|
+
response.data[pageIdx]= response.data[pageIdx]||[];
|
|
152
|
+
response.data[pageIdx]= reqData||[];
|
|
153
|
+
response.data=[...response.data];
|
|
154
|
+
setData(response.data);
|
|
155
|
+
}else{
|
|
156
|
+
setData(data||[]);
|
|
157
|
+
}
|
|
158
|
+
return response;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const nextPage= async ()=>{
|
|
162
|
+
if(!pagination.more){
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
return update({pagination:{current:pagination.current+1}})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const reset= ()=>{
|
|
169
|
+
return update({pagination:{current:1},clear:true})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const addListener=(type,fn)=>{
|
|
173
|
+
if(!refListener.current[type]){
|
|
174
|
+
refListener.current[type]=[];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const repeat= refListener.current[type].some(callback=>{
|
|
178
|
+
if(callback==fn){return true;}
|
|
179
|
+
return false;
|
|
180
|
+
})
|
|
181
|
+
if(repeat){return;}
|
|
182
|
+
refListener.current[type].push(fn);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const removeListener=(type,fn)=>{
|
|
186
|
+
if(!refListener.current[type]){
|
|
187
|
+
refListener.current[type]=[];
|
|
188
|
+
}
|
|
189
|
+
let list = refListener.current[type];
|
|
190
|
+
for(let i=0;i<list.length;i++){
|
|
191
|
+
if(list[i] == fn){
|
|
192
|
+
list.spice(i,1);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const action= useMemo(()=>{
|
|
198
|
+
return {
|
|
199
|
+
pagination,
|
|
200
|
+
update,
|
|
201
|
+
reset,
|
|
202
|
+
nextPage,
|
|
203
|
+
data,
|
|
204
|
+
addListener,
|
|
205
|
+
removeListener
|
|
206
|
+
}
|
|
207
|
+
},[pagination,data,refListener])
|
|
208
|
+
|
|
209
|
+
return action;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* 分页信息
|
|
216
|
+
* @typedef {Object} Pagination
|
|
217
|
+
* @property {number} pageSize=20 - 分页大小
|
|
218
|
+
* @property {number} current=1 - 当前页码
|
|
219
|
+
* @property {number} total=1 - 总记录数
|
|
220
|
+
* @property {number} [startIdx=0] - 当前页面下第一条数据的序号
|
|
221
|
+
* @property {boolean} [more] - 是否还有下一页
|
|
222
|
+
*
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* 分页数据结果
|
|
228
|
+
* @typedef {Object} PageDataResult
|
|
229
|
+
* @property {Pagination} pagination - 最新分页信息
|
|
230
|
+
* @property {Object[][]} data - 分页数据集合
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* 分页查询结果
|
|
237
|
+
* @typedef {callback} FunUpdate
|
|
238
|
+
* @property {Pagination} [pagination] - 最新分页信息
|
|
239
|
+
* @property {boolean} [clear] - 是否清空数据
|
|
240
|
+
* @returns {Promise<PageDataResult>} 最新的分页数据结果
|
|
241
|
+
*/
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* usePagination的返回对象
|
|
246
|
+
* @typedef {Object} UsePaginationResult
|
|
247
|
+
* @property {Object[][]} data - 分页数据集合
|
|
248
|
+
* @property {Pagination} paginnation - 分页信息
|
|
249
|
+
* @property {FunUpdate} update - 查询方法
|
|
250
|
+
* @property {FunUpdate} next - 获取下一页数据
|
|
251
|
+
* @property {function} addListener - 监听事件 (type='beforeService'|'afterService',fn:FunListener)=>object
|
|
252
|
+
* @property {function} removeListener - 移除监听事件 (type,fn:FunListener)=>void
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* 事件监听方法
|
|
258
|
+
* @typedef {callback} FunListener
|
|
259
|
+
* @property {Object} params - 被拦截的数据对象
|
|
260
|
+
* @returns {Object|Promise<Object>} 处理完毕的数据对象或者Promise
|
|
261
|
+
*/
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
export default usePagination;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @module usePaginationWithForm
|
|
4
|
+
*/
|
|
5
|
+
import { useState, useMemo, useEffect, useRef } from 'react';
|
|
6
|
+
import usePagination from '../usePagination';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 支持Antd-Form的usePagination
|
|
11
|
+
* 作用是在查询接口前自动获取form表单内的字段,并作为接口查询参数进行查询
|
|
12
|
+
* 使用方法及参数字段参考 [usePagination]{@link usePagination.md}
|
|
13
|
+
*
|
|
14
|
+
* @param {Object} props
|
|
15
|
+
* @param {Object} props.form - Form表单的ref,在接口调用前会校验获取form表单内的数据,提交到接口参数内查询
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
const [form] = Form.useForm();
|
|
19
|
+
const page = usePaginationWithForm({
|
|
20
|
+
service:GET_LIST,
|
|
21
|
+
pagination:{pageSize:10},
|
|
22
|
+
form:form
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return(
|
|
26
|
+
<Form form={form} style={{width:'600px'}} layout="inline">
|
|
27
|
+
<Form.Item label='关键字' name='keyword' rules={[
|
|
28
|
+
{
|
|
29
|
+
max:5,
|
|
30
|
+
message:'最多5个字符'
|
|
31
|
+
}
|
|
32
|
+
]}>
|
|
33
|
+
<Input />
|
|
34
|
+
</Form.Item>
|
|
35
|
+
<Button onClick={onSearch} type='primary'>查询</Button>
|
|
36
|
+
<Button onClick={onReset} type='primary'>重置</Button>
|
|
37
|
+
</Form>
|
|
38
|
+
)
|
|
39
|
+
*/
|
|
40
|
+
const usePaginationWithForm = (props) => {
|
|
41
|
+
const {service,pagination}= props;
|
|
42
|
+
const [form] = useState(props.form);
|
|
43
|
+
const page = usePagination({service,pagination})
|
|
44
|
+
|
|
45
|
+
useEffect(()=>{
|
|
46
|
+
const fnFeforeService = async (params)=>{
|
|
47
|
+
// 假如你这里需要变更接口字段名称的话
|
|
48
|
+
const values = await getSearchValue();
|
|
49
|
+
if(!values)return;
|
|
50
|
+
params= {...params,...values}
|
|
51
|
+
return params;
|
|
52
|
+
};
|
|
53
|
+
page.addListener('beforeService',fnFeforeService);
|
|
54
|
+
return ()=>{
|
|
55
|
+
page.removeListener('beforeService',fnFeforeService);
|
|
56
|
+
}
|
|
57
|
+
},[])
|
|
58
|
+
|
|
59
|
+
const getSearchValue = async () => {
|
|
60
|
+
try {
|
|
61
|
+
let value = {};
|
|
62
|
+
if (form) {
|
|
63
|
+
value = await form.validateFields();
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
} catch (ex) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
const reset = () => {
|
|
74
|
+
if(form){
|
|
75
|
+
form.resetFields();
|
|
76
|
+
}
|
|
77
|
+
page.reset();
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
...page,
|
|
82
|
+
reset,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default usePaginationWithForm
|
package/src/useSwitch/index.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useSwitch
|
|
3
|
+
* @module useSwitch
|
|
4
|
+
*/
|
|
1
5
|
import { useState, useMemo, useRef, useEffect } from 'react';
|
|
2
6
|
|
|
3
7
|
|
|
8
|
+
|
|
4
9
|
/**
|
|
5
10
|
* 控制开关
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* count: number,当前计数器
|
|
13
|
-
* }
|
|
11
|
+
*
|
|
12
|
+
* [Demo-CodeSandbox]{@link https://codesandbox.io/s/useswitch-qd7dr?file=/index.js}
|
|
13
|
+
*
|
|
14
|
+
* @param {boolean} [props=false] - 默认的开关状态
|
|
15
|
+
* @return {UseSwitchResult}
|
|
16
|
+
*
|
|
14
17
|
*
|
|
15
18
|
*/
|
|
16
19
|
const useSwitch = (props=false) => {
|
|
@@ -62,4 +65,16 @@ const useSwitch = (props=false) => {
|
|
|
62
65
|
return {state:value,count,...actions};
|
|
63
66
|
};
|
|
64
67
|
|
|
68
|
+
/**
|
|
69
|
+
* useSwitchHookResult
|
|
70
|
+
* @typedef {Object} UseSwitchResult
|
|
71
|
+
* @property {boolean} state - 当前开关状态
|
|
72
|
+
* @property {number} count - 当前开关计数器
|
|
73
|
+
* @property {function} open - 切换至开模式 (force?:boolean)=>void
|
|
74
|
+
* @property {function} close - 切换至关模式 (force?:boolean)=>void
|
|
75
|
+
* @property {function} toggle - 切换至反向模式 ()=>void
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
|
|
65
80
|
export default useSwitch;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React,{ useState, useMemo, useEffect, useRef } from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom';
|
|
3
|
+
import useCounter from '@/useCounter';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const Index=()=>{
|
|
7
|
+
const [count,add] = useCounter();
|
|
8
|
+
return (
|
|
9
|
+
<section>
|
|
10
|
+
<h2>计数器:{count}</h2>
|
|
11
|
+
<button onClick={add}>触发增加计数器</button>
|
|
12
|
+
</section>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
ReactDOM.render(<Index />, document.getElementById('main-view'));
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import React,{ useState, useMemo, useEffect, useRef } from 'react';
|
|
2
|
+
import ReactDOM, { render } from 'react-dom';
|
|
3
|
+
import usePagination from '@/usePagination';
|
|
4
|
+
import {Pagination,Button,Input,Table} from 'antd';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const GET_LIST=(params)=>{
|
|
9
|
+
const list=[]
|
|
10
|
+
const total=200;
|
|
11
|
+
for(let i=0;i<total;i++){
|
|
12
|
+
list.push(`数据${i+1}`)
|
|
13
|
+
}
|
|
14
|
+
const {current,pageSize,...others}=params;
|
|
15
|
+
const startIdx = (current-1) * pageSize;
|
|
16
|
+
let data = list.splice(startIdx,pageSize);
|
|
17
|
+
data=data.map((item,idx)=>{
|
|
18
|
+
return {id:`第${current}页-${item}`, value:`第${current}页-${item}`,params:others}
|
|
19
|
+
})
|
|
20
|
+
return Promise.resolve({
|
|
21
|
+
code:0,
|
|
22
|
+
data,
|
|
23
|
+
page:{
|
|
24
|
+
current:current,
|
|
25
|
+
pageSize:pageSize,
|
|
26
|
+
total,
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const Index=()=>{
|
|
32
|
+
const page = usePagination({
|
|
33
|
+
service:GET_LIST,
|
|
34
|
+
pagination:{pageSize:10}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
useEffect(()=>{
|
|
39
|
+
const fnFeforeService = (params)=>{
|
|
40
|
+
// 假如你这里需要变更接口字段名称的话
|
|
41
|
+
params.beforeService='beforeService';
|
|
42
|
+
return params;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const fnAfterService = (response)=>{
|
|
46
|
+
// 这里你可以翻译及二次处理你的接口字段
|
|
47
|
+
response.message='afterService';
|
|
48
|
+
return response;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
page.addListener('beforeService',fnFeforeService);
|
|
52
|
+
page.addListener('afterService',fnAfterService);
|
|
53
|
+
page.update()
|
|
54
|
+
return ()=>{
|
|
55
|
+
page.removeListener('beforeService',fnFeforeService);
|
|
56
|
+
page.removeListener('afterService',fnAfterService)
|
|
57
|
+
}
|
|
58
|
+
},[])
|
|
59
|
+
|
|
60
|
+
const onReset=()=>{page.reset();}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
const onPageChange=(current,pageSize)=>{
|
|
64
|
+
page.update({pagination:{current,pageSize}})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const onNext=()=>{page.nextPage();}
|
|
68
|
+
|
|
69
|
+
const columns=[{
|
|
70
|
+
dataIndex:'value',
|
|
71
|
+
title:'数据值',
|
|
72
|
+
render:(_,record,idx)=>{
|
|
73
|
+
return `[${idx}]${record.value}`;
|
|
74
|
+
}
|
|
75
|
+
},{
|
|
76
|
+
dataIndex:'params',
|
|
77
|
+
title:'入参值',
|
|
78
|
+
render:(_,record,idx)=>{
|
|
79
|
+
return record.params?JSON.stringify(record.params):'-';
|
|
80
|
+
}
|
|
81
|
+
}];
|
|
82
|
+
|
|
83
|
+
const getDataSource=()=>{
|
|
84
|
+
let req=[];
|
|
85
|
+
if(page?.data && page?.data?.length>0){
|
|
86
|
+
for(let i=0;i<page.data.length;i++){
|
|
87
|
+
req= [...req,...page.data[i]];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return req;
|
|
91
|
+
}
|
|
92
|
+
return (
|
|
93
|
+
<section style={{padding:'12px'}}>
|
|
94
|
+
<section>
|
|
95
|
+
<Button onClick={onNext} type='primary'>加载下一页</Button>
|
|
96
|
+
<Button onClick={onReset} type='primary'>重置</Button>
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
<Table
|
|
100
|
+
rowKey={'id'}
|
|
101
|
+
loading={!page?.data?.length>0}
|
|
102
|
+
columns={columns}
|
|
103
|
+
dataSource={getDataSource()}
|
|
104
|
+
pagination={false}
|
|
105
|
+
/>
|
|
106
|
+
|
|
107
|
+
<Pagination
|
|
108
|
+
current={page?.pagination?.current}
|
|
109
|
+
pageSize={page?.pagination?.pageSize}
|
|
110
|
+
onChange={onPageChange}
|
|
111
|
+
total={page?.pagination?.total}
|
|
112
|
+
/>
|
|
113
|
+
|
|
114
|
+
</section>
|
|
115
|
+
|
|
116
|
+
</section>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
ReactDOM.render(<Index />, document.getElementById('main-view'));
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom';
|
|
3
|
+
import {Form,Button,Input,Table} from 'antd';
|
|
4
|
+
|
|
5
|
+
import usePaginationWithForm from '@/usePaginationWithForm';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const GET_LIST=(params)=>{
|
|
11
|
+
const list=[]
|
|
12
|
+
const total=200;
|
|
13
|
+
for(let i=0;i<total;i++){
|
|
14
|
+
list.push(`数据${i+1}`)
|
|
15
|
+
}
|
|
16
|
+
const {current,pageSize,...others}=params;
|
|
17
|
+
const startIdx = (current-1) * pageSize;
|
|
18
|
+
let data = list.splice(startIdx,pageSize);
|
|
19
|
+
data=data.map((item,idx)=>{
|
|
20
|
+
return {id:''+idx, value:`第${current}页-${item}`,params:others}
|
|
21
|
+
})
|
|
22
|
+
return Promise.resolve({
|
|
23
|
+
code:0,
|
|
24
|
+
data,
|
|
25
|
+
page:{
|
|
26
|
+
current:current,
|
|
27
|
+
pageSize:pageSize,
|
|
28
|
+
total,
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const Index=()=>{
|
|
34
|
+
|
|
35
|
+
const [form] = Form.useForm();
|
|
36
|
+
const page = usePaginationWithForm({
|
|
37
|
+
service:GET_LIST,
|
|
38
|
+
pagination:{pageSize:10},
|
|
39
|
+
form:form
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const onSearch=()=>{
|
|
44
|
+
page.update();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const onReset=()=>{page.reset();}
|
|
48
|
+
|
|
49
|
+
const onPageChange=(current,pageSize)=>{
|
|
50
|
+
page.update({pagination:{current,pageSize}})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const columns=[{
|
|
54
|
+
dataIndex:'value',
|
|
55
|
+
title:'数据值',
|
|
56
|
+
render:(_,record,idx)=>{
|
|
57
|
+
return `[${idx}]${record.value}`;
|
|
58
|
+
}
|
|
59
|
+
},{
|
|
60
|
+
dataIndex:'params',
|
|
61
|
+
title:'入参值',
|
|
62
|
+
render:(_,record,idx)=>{
|
|
63
|
+
return record.params?JSON.stringify(record.params):'-';
|
|
64
|
+
}
|
|
65
|
+
}];
|
|
66
|
+
return (
|
|
67
|
+
<section style={{padding:'12px'}}>
|
|
68
|
+
<section>
|
|
69
|
+
<Form form={form} style={{width:'600px'}} layout="inline">
|
|
70
|
+
<Form.Item label='关键字' name='keyword' rules={[
|
|
71
|
+
{
|
|
72
|
+
max:5,
|
|
73
|
+
message:'最多5个字符'
|
|
74
|
+
}
|
|
75
|
+
]}>
|
|
76
|
+
<Input />
|
|
77
|
+
</Form.Item>
|
|
78
|
+
<Button onClick={onSearch} type='primary'>查询</Button>
|
|
79
|
+
<Button onClick={onReset} type='primary'>重置</Button>
|
|
80
|
+
</Form>
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
<Table
|
|
84
|
+
rowKey={'id'}
|
|
85
|
+
loading={!page?.data?.length>0}
|
|
86
|
+
columns={columns}
|
|
87
|
+
dataSource={page?.data? page?.data[page?.pagination?.current-1]:[]}
|
|
88
|
+
pagination={{
|
|
89
|
+
current:page?.pagination?.current,
|
|
90
|
+
pageSize:page?.pagination?.pageSize,
|
|
91
|
+
total:page?.pagination?.total,
|
|
92
|
+
onChange:onPageChange
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
</section>
|
|
97
|
+
|
|
98
|
+
</section>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
ReactDOM.render(<Index />, document.getElementById('main-view'));
|
package/test/useSwitch/index.jsx
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import React,{ useState, useMemo, useEffect, useRef } from 'react';
|
|
2
2
|
import ReactDOM from 'react-dom';
|
|
3
|
-
import
|
|
3
|
+
import useSwitch from '@/useSwitch';
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const Index=()=>{
|
|
7
7
|
const loading = useSwitch(false);
|
|
8
|
-
const clip = useClipboard({onSuccess:()=>{alert('已复制到剪贴板')}});
|
|
9
8
|
return (
|
|
10
9
|
<section>
|
|
11
|
-
<h1
|
|
12
|
-
clip('4433')
|
|
13
|
-
}}>当前状态:{loading.state?"打开":"关闭"}</h1>
|
|
10
|
+
<h1>当前状态:{loading.state?"打开":"关闭"}</h1>
|
|
14
11
|
<h2>计数器:{loading.count}</h2>
|
|
15
12
|
<button onClick={()=>{loading.toggle();}}>切换</button>
|
|
16
13
|
<button onClick={()=>{loading.open();}}>打开</button>
|
package/src/.DS_Store
DELETED
|
Binary file
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { useState, useMemo, useEffect, useRef } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const useFormTableSearch = (props) => {
|
|
5
|
-
const [search] = useState(props.initSearch || {});
|
|
6
|
-
const [formRef] = useState(props.formRef);
|
|
7
|
-
const [service] = useState(() => props.service);
|
|
8
|
-
const [beforeSearch] = useState(() => props.beforeSearch);
|
|
9
|
-
const [beforeService] = useState(() => props.beforeService);
|
|
10
|
-
const [loading, setLoading] = useState(props.loading || false);
|
|
11
|
-
|
|
12
|
-
const [pagination, setPagination] = useState(() => {
|
|
13
|
-
const temp = { ...props.pagination, page: 1, pageSize: 10, total: 0, startIdx: 0 };
|
|
14
|
-
if (props.pagination) {
|
|
15
|
-
temp.startIdx = temp.pageSize * (temp.page - 1);
|
|
16
|
-
}
|
|
17
|
-
return temp;
|
|
18
|
-
});
|
|
19
|
-
const [updateData] = useState(() => props.updateData);
|
|
20
|
-
const [orderInfo, setOrderInfo] = useState({});
|
|
21
|
-
|
|
22
|
-
const getSearchValue = async () => {
|
|
23
|
-
try {
|
|
24
|
-
let value = {};
|
|
25
|
-
if (formRef) {
|
|
26
|
-
value = await formRef.validateFields();
|
|
27
|
-
} else {
|
|
28
|
-
value = search;
|
|
29
|
-
}
|
|
30
|
-
if (beforeSearch) {
|
|
31
|
-
value = beforeSearch(value);
|
|
32
|
-
}
|
|
33
|
-
return value;
|
|
34
|
-
} catch (ex) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
const formatSearchValue = async ({ searchValue, pageValue, orderValue }) => {
|
|
39
|
-
if (!searchValue) {
|
|
40
|
-
searchValue = await getSearchValue();
|
|
41
|
-
}
|
|
42
|
-
searchValue = searchValue || search;
|
|
43
|
-
pageValue = pageValue || pagination;
|
|
44
|
-
orderValue = orderValue || orderInfo;
|
|
45
|
-
const order: any[] = [];
|
|
46
|
-
if (orderValue) {
|
|
47
|
-
Object.keys(orderValue).map((name) => {
|
|
48
|
-
if (orderValue[name] === 'ascend') {
|
|
49
|
-
order.push({ [`${name}`]: 'ASC' });
|
|
50
|
-
} else if (orderValue[name] === 'descend') {
|
|
51
|
-
order.push({ [`${name}`]: 'DESC' });
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
const { page, pageSize } = pageValue;
|
|
56
|
-
let params = {
|
|
57
|
-
...searchValue,
|
|
58
|
-
page: {
|
|
59
|
-
pageNum: page,
|
|
60
|
-
pageSize: pageSize,
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
if (order && order.length > 0) {
|
|
64
|
-
params.page.orders = order;
|
|
65
|
-
}
|
|
66
|
-
if (beforeService) params = beforeService(params);
|
|
67
|
-
return params;
|
|
68
|
-
};
|
|
69
|
-
const refresh = async ({ searchValue, pageValue, orderValue }) => {
|
|
70
|
-
setLoading(true);
|
|
71
|
-
searchValue = searchValue || search;
|
|
72
|
-
pageValue = pageValue || pagination;
|
|
73
|
-
orderValue = orderValue || orderInfo;
|
|
74
|
-
|
|
75
|
-
const params = await formatSearchValue({ searchValue, pageValue, orderValue });
|
|
76
|
-
if (!params) {
|
|
77
|
-
setLoading(false);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const ret: any = await service(params);
|
|
81
|
-
|
|
82
|
-
if (ret?.data?.page) {
|
|
83
|
-
const { pageNum, pageSize: size, totalRows } = ret.data.page;
|
|
84
|
-
setPagination({
|
|
85
|
-
page: pageNum || 1,
|
|
86
|
-
pageSize: size || 10,
|
|
87
|
-
total: totalRows,
|
|
88
|
-
startIdx: (pageNum - 1) * size || 0,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (updateData) updateData(ret);
|
|
93
|
-
setLoading(false);
|
|
94
|
-
return ret;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const onPaginationChange = async (pageInfo: any, sorterInfo?: any) => {
|
|
98
|
-
let { page: current, pageSize }: any = pagination;
|
|
99
|
-
let orderValue = orderInfo;
|
|
100
|
-
if (pageInfo) {
|
|
101
|
-
current = pageInfo.current;
|
|
102
|
-
pageSize = pageInfo.pageSize;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (sorterInfo) {
|
|
106
|
-
const { field, order } = sorterInfo;
|
|
107
|
-
if (field) {
|
|
108
|
-
if (order) {
|
|
109
|
-
orderInfo[field] = order;
|
|
110
|
-
} else {
|
|
111
|
-
delete orderInfo[field];
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
orderValue = orderInfo;
|
|
115
|
-
setOrderInfo({ ...orderInfo });
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const searchValue: any = await getSearchValue();
|
|
119
|
-
|
|
120
|
-
refresh({
|
|
121
|
-
searchValue,
|
|
122
|
-
pageValue: { page: current, pageSize },
|
|
123
|
-
orderValue,
|
|
124
|
-
});
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const onSorter = async (sorter: any) => {
|
|
128
|
-
const { field, order } = sorter;
|
|
129
|
-
if (field) {
|
|
130
|
-
if (order) {
|
|
131
|
-
orderInfo[field] = order;
|
|
132
|
-
} else {
|
|
133
|
-
delete orderInfo[field];
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
setOrderInfo({ ...orderInfo });
|
|
137
|
-
console.log(`${JSON.stringify(orderInfo)}`);
|
|
138
|
-
refresh();
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const btnSearch = async () => {
|
|
142
|
-
const value: any = await getSearchValue();
|
|
143
|
-
if (value) {
|
|
144
|
-
refresh({ searchValue: value });
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const btnReset = () => {
|
|
149
|
-
formRef.resetFields();
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
return {
|
|
153
|
-
onPaginationChange,
|
|
154
|
-
pagination,
|
|
155
|
-
btnSearch,
|
|
156
|
-
search,
|
|
157
|
-
refresh,
|
|
158
|
-
btnReset,
|
|
159
|
-
onSorter,
|
|
160
|
-
loading,
|
|
161
|
-
formatSearchValue,
|
|
162
|
-
};
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
export default useFormTableSearch
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { useEffect,useRef, useMemo } from 'react';
|
|
3
|
-
import useSwitch from '../useSwitch';
|
|
4
|
-
|
|
5
|
-
const useRefSwitch=(props=false)=>{
|
|
6
|
-
const loading = useSwitch(props);
|
|
7
|
-
const ref = useRef();
|
|
8
|
-
ref.current = loading;
|
|
9
|
-
useEffect(()=>{
|
|
10
|
-
ref.current = loading;
|
|
11
|
-
},[loading]);
|
|
12
|
-
|
|
13
|
-
return useMemo(()=>ref,[]);
|
|
14
|
-
}
|
|
15
|
-
export default useRefSwitch;
|
package/test/.DS_Store
DELETED
|
Binary file
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React,{ useState, useMemo, useEffect, useRef } from 'react';
|
|
2
|
-
import ReactDOM from 'react-dom';
|
|
3
|
-
import useRefSwitch from '@/useRefSwitch';
|
|
4
|
-
|
|
5
|
-
const Index=()=>{
|
|
6
|
-
const loading = useRefSwitch(false);
|
|
7
|
-
return (
|
|
8
|
-
<section>
|
|
9
|
-
<h1>当前状态:{loading.current.state?"打开":"关闭"}</h1>
|
|
10
|
-
<h2>计数器:{loading.current.count}</h2>
|
|
11
|
-
<button onClick={()=>{loading.current.toggle();}}>切换</button>
|
|
12
|
-
<button onClick={()=>{loading.current.open();}}>打开</button>
|
|
13
|
-
<button onClick={()=>{loading.current.close();}}>关闭</button>
|
|
14
|
-
<button onClick={()=>{loading.current.open(true);}}>强制打开</button>
|
|
15
|
-
<button onClick={()=>{loading.current.close(true);}}>强制关闭</button>
|
|
16
|
-
</section>
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
ReactDOM.render(<Index />, document.getElementById('main-view'));
|