kn-cli 1.0.46 → 1.0.48
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/build/cli.config.js +3 -0
- package/build/webpack.config.js +61 -74
- package/package.json +1 -1
- package/readme.md +10 -0
- package/templates/template_admin/cli.config.js +3 -0
- package/templates/template_admin/package.json +1 -0
- package/templates/template_admin/public/src/components/Menu/index.jsx +10 -1
- package/templates/template_admin/public/src/components/TopMenu/index.jsx +43 -4
- package/templates/template_app/cli.config.js +3 -0
- package/templates/template_app/package.json +1 -0
- package/templates/template_app/public/src/hooks/index.jsx +4 -7
- package/templates/template_app/public/src/mock/user.js +5 -7
- package/templates/template_app/public/src/pages/dictionary/index.jsx +30 -0
- package/templates/template_app/public/src/pages/dictionary/index.less +22 -0
- package/templates/template_app/public/src/pages/index.jsx +7 -70
- package/templates/template_app/public/src/pages/list/index.jsx +81 -0
- package/templates/template_app/public/src/pages/list/index.less +22 -0
- package/templates/template_app/public/src/route.jsx +8 -0
- package/templates/template_app/public/src/hooks/useNextPage.jsx +0 -89
- package/templates/template_app/public/src/hooks/useSearch.jsx +0 -137
package/build/cli.config.js
CHANGED
|
@@ -6,6 +6,9 @@ module.exports = {
|
|
|
6
6
|
javascriptEnabled:false,//是否开启less js
|
|
7
7
|
},
|
|
8
8
|
version:'1.0',
|
|
9
|
+
// rules:{
|
|
10
|
+
// compileNpmPackage:['kn-hooks'],//需要参与编译的npm包
|
|
11
|
+
// },
|
|
9
12
|
// https:true,//是否使用https本地调试
|
|
10
13
|
// pxtorem:false,//默认:true,开启px转rem模式
|
|
11
14
|
// site_root_path:'/dist/',// 默认:'',站点根目录
|
package/build/webpack.config.js
CHANGED
|
@@ -110,88 +110,58 @@ if(!hashMode){
|
|
|
110
110
|
////////////// OUTPUT-END ///////////////
|
|
111
111
|
|
|
112
112
|
/////////////// RULES ////////////////
|
|
113
|
+
|
|
114
|
+
const LOADER_JS=[
|
|
115
|
+
{
|
|
116
|
+
loader: 'babel-loader',
|
|
117
|
+
options: {
|
|
118
|
+
presets: [
|
|
119
|
+
'@babel/preset-react',
|
|
120
|
+
[
|
|
121
|
+
'@babel/preset-env',
|
|
122
|
+
{
|
|
123
|
+
targets: devMode
|
|
124
|
+
? { chrome: '90' }
|
|
125
|
+
: {
|
|
126
|
+
chrome: '40',
|
|
127
|
+
ie: '11',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
],
|
|
132
|
+
plugins: [
|
|
133
|
+
['@babel/plugin-transform-runtime', { corejs: 3 }],
|
|
134
|
+
'@babel/plugin-proposal-optional-chaining',
|
|
135
|
+
'@babel/plugin-proposal-nullish-coalescing-operator',
|
|
136
|
+
['@babel/plugin-proposal-decorators', { legacy: true }],
|
|
137
|
+
['@babel/plugin-proposal-private-methods', { loose: true }],
|
|
138
|
+
['@babel/plugin-proposal-class-properties', { loose: true }],
|
|
139
|
+
// ["import", {
|
|
140
|
+
// style: false,//"css",
|
|
141
|
+
// libraryName: "kn-hooks" ,
|
|
142
|
+
// libraryDirectory:"src",
|
|
143
|
+
// camel2DashComponentName:false,
|
|
144
|
+
// }],
|
|
145
|
+
// ["import", {
|
|
146
|
+
// style: true,//"css",
|
|
147
|
+
// libraryDirectory:"",
|
|
148
|
+
// libraryName: "antd" ,
|
|
149
|
+
// }]
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
]
|
|
154
|
+
|
|
113
155
|
const rules= [
|
|
114
156
|
{
|
|
115
157
|
test: /\.js[x]?$/,
|
|
116
158
|
exclude: /node_modules/,
|
|
117
|
-
use:
|
|
118
|
-
{
|
|
119
|
-
loader: 'babel-loader',
|
|
120
|
-
options: {
|
|
121
|
-
presets: [
|
|
122
|
-
'@babel/preset-react',
|
|
123
|
-
[
|
|
124
|
-
'@babel/preset-env',
|
|
125
|
-
{
|
|
126
|
-
targets: devMode
|
|
127
|
-
? { chrome: '90' }
|
|
128
|
-
: {
|
|
129
|
-
chrome: '40',
|
|
130
|
-
ie: '11',
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
],
|
|
134
|
-
],
|
|
135
|
-
plugins: [
|
|
136
|
-
['@babel/plugin-transform-runtime', { corejs: 3 }],
|
|
137
|
-
'@babel/plugin-proposal-optional-chaining',
|
|
138
|
-
'@babel/plugin-proposal-nullish-coalescing-operator',
|
|
139
|
-
['@babel/plugin-proposal-decorators', { legacy: true }],
|
|
140
|
-
['@babel/plugin-proposal-private-methods', { loose: true }],
|
|
141
|
-
['@babel/plugin-proposal-class-properties', { loose: true }],
|
|
142
|
-
// ["import", {
|
|
143
|
-
// style: false,//"css",
|
|
144
|
-
// libraryName: "kn-hooks" ,
|
|
145
|
-
// libraryDirectory:"src",
|
|
146
|
-
// camel2DashComponentName:false,
|
|
147
|
-
// }],
|
|
148
|
-
// ["import", {
|
|
149
|
-
// style: true,//"css",
|
|
150
|
-
// libraryDirectory:"",
|
|
151
|
-
// libraryName: "antd" ,
|
|
152
|
-
// }]
|
|
153
|
-
],
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
],
|
|
159
|
+
use: LOADER_JS,
|
|
157
160
|
},
|
|
158
161
|
// {
|
|
159
162
|
// test: /\.json$/,
|
|
160
163
|
// use: 'json-loader'
|
|
161
164
|
// },
|
|
162
|
-
{
|
|
163
|
-
test: /\.js[x]?$/,
|
|
164
|
-
include: /kn-hooks/,
|
|
165
|
-
use: [
|
|
166
|
-
{
|
|
167
|
-
loader: 'babel-loader',
|
|
168
|
-
options: {
|
|
169
|
-
presets: [
|
|
170
|
-
'@babel/preset-react',
|
|
171
|
-
[
|
|
172
|
-
'@babel/preset-env',
|
|
173
|
-
{
|
|
174
|
-
targets: devMode
|
|
175
|
-
? { chrome: '80' }
|
|
176
|
-
: {
|
|
177
|
-
chrome: '40',
|
|
178
|
-
ie: '11',
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
],
|
|
183
|
-
plugins: [
|
|
184
|
-
['@babel/plugin-transform-runtime', { corejs: 3 }],
|
|
185
|
-
'@babel/plugin-proposal-optional-chaining',
|
|
186
|
-
'@babel/plugin-proposal-nullish-coalescing-operator',
|
|
187
|
-
['@babel/plugin-proposal-decorators', { legacy: true }],
|
|
188
|
-
['@babel/plugin-proposal-private-methods', { loose: true }],
|
|
189
|
-
['@babel/plugin-proposal-class-properties', { loose: true }],
|
|
190
|
-
],
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
],
|
|
194
|
-
},
|
|
195
165
|
{
|
|
196
166
|
test: /\.(jpg|png|gif|svg)$/,
|
|
197
167
|
loader: 'url-loader',
|
|
@@ -291,6 +261,16 @@ if(support_sass){
|
|
|
291
261
|
],
|
|
292
262
|
})
|
|
293
263
|
}
|
|
264
|
+
if(CLI_CONFIG.rules){
|
|
265
|
+
if(CLI_CONFIG.rules.compileNpmPackage){
|
|
266
|
+
let JS_LIST= CLI_CONFIG.rules.compileNpmPackage.join('|');
|
|
267
|
+
rules.push({
|
|
268
|
+
test: /\.js[x]?$/,
|
|
269
|
+
include: new RegExp(`(${JS_LIST})`),
|
|
270
|
+
use: LOADER_JS
|
|
271
|
+
},)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
294
274
|
////////////// RULES-END ///////////////
|
|
295
275
|
|
|
296
276
|
|
|
@@ -320,6 +300,13 @@ if(jsSplitMode){
|
|
|
320
300
|
}
|
|
321
301
|
optimization.splitChunks= {
|
|
322
302
|
cacheGroups: {
|
|
303
|
+
knHooks:{
|
|
304
|
+
test: /(kn-hooks)/,
|
|
305
|
+
priority: 10220,
|
|
306
|
+
name: 'kn-hooks',
|
|
307
|
+
chunks: 'all',
|
|
308
|
+
enforce: true,
|
|
309
|
+
},
|
|
323
310
|
react: {
|
|
324
311
|
test: /(react)/,
|
|
325
312
|
priority: 100,
|
|
@@ -381,7 +368,7 @@ const plugins= [
|
|
|
381
368
|
|
|
382
369
|
|
|
383
370
|
if(indexHtml){
|
|
384
|
-
const shareJs = jsSplitMode?['react-bundle', 'modules-bundle', 'default-bundle', 'styles-bundle']:[];
|
|
371
|
+
const shareJs = jsSplitMode?['react-bundle', 'modules-bundle', 'default-bundle', 'styles-bundle','kn-hooks']:[];
|
|
385
372
|
if(jsSplitMode===true || jsSplitMode?.runtime !== false){
|
|
386
373
|
shareJs.splice(0,0,'runtime');
|
|
387
374
|
}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -62,10 +62,20 @@ module.exports = {
|
|
|
62
62
|
// }
|
|
63
63
|
// pxtorem:false,//默认:true,开启px转rem模式
|
|
64
64
|
// https:true,//是否使用https本地调试
|
|
65
|
+
// rules:{
|
|
66
|
+
// compileNpmPackage:['kn-hooks'],//需要参与编译的npm包
|
|
67
|
+
// },
|
|
65
68
|
};
|
|
66
69
|
```
|
|
67
70
|
|
|
68
71
|
# 更新日志
|
|
72
|
+
* 1.0.48
|
|
73
|
+
1. cli.config增加rules:{compileNpmPackage:[]}配置,用于配置一些需要参与编译的npm包
|
|
74
|
+
2. 更新app及后管项目的模板
|
|
75
|
+
|
|
76
|
+
* 1.0.47
|
|
77
|
+
后管模板工程对菜单路由的隐藏子路由控制方法
|
|
78
|
+
|
|
69
79
|
* 1.0.46
|
|
70
80
|
模板工程下增加jsconfig.json用于解决配置资源根目录别名后vscode无法快捷定位文件
|
|
71
81
|
|
|
@@ -62,10 +62,19 @@ const LeftMenu=(props)=>{
|
|
|
62
62
|
let groupKeys=[];
|
|
63
63
|
for(let key in menuList){
|
|
64
64
|
const menuItem = menuList[key];
|
|
65
|
-
const {path,routeTemplate}= menuItem.source;
|
|
65
|
+
const {path,routeTemplate,subRoute}= menuItem.source;
|
|
66
66
|
if(path){
|
|
67
67
|
let fn = matchPath;
|
|
68
68
|
let match= fn(routeTemplate||path,curRoute.pathname);
|
|
69
|
+
if(!match&&subRoute){
|
|
70
|
+
match= subRoute.some(sub=>{
|
|
71
|
+
let subMatch= fn(sub.routeTemplate||sub.path,curRoute.pathname);
|
|
72
|
+
if(subMatch){
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
})
|
|
77
|
+
}
|
|
69
78
|
if(match){
|
|
70
79
|
groupKeys = menuItem.routepath?menuItem.routepath.split('-'):'';
|
|
71
80
|
}
|
|
@@ -11,7 +11,22 @@ import styles from './index.less';
|
|
|
11
11
|
import {GET_MENU} from '@/services/auth';
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* 菜单下的隐藏子路由集
|
|
16
|
+
* 当这些隐藏子路由打开的时候,导航栏的选中菜单会显示被匹配的这个子菜单
|
|
17
|
+
*/
|
|
18
|
+
const SUB_MENU_CONFIG=[
|
|
19
|
+
{
|
|
20
|
+
path:'/video',//匹配菜单路由是/video的菜单
|
|
21
|
+
// routeTemplate:''匹配某个模板菜单的模板
|
|
22
|
+
subRoute:[
|
|
23
|
+
{
|
|
24
|
+
path:'/video/detail',//将video/detail这个路由匹配给菜单/video
|
|
25
|
+
// routeTemplate:''//也可以将某个路由模板匹配给某个菜单
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
]
|
|
15
30
|
|
|
16
31
|
/**
|
|
17
32
|
* 顶部导航栏
|
|
@@ -66,17 +81,31 @@ const TopMenu=(props)=>{
|
|
|
66
81
|
return item;
|
|
67
82
|
}
|
|
68
83
|
|
|
84
|
+
const getSubConfig=(menu)=>{
|
|
85
|
+
const {url,routeTemplate}= menu;
|
|
86
|
+
for(let i=0;i<SUB_MENU_CONFIG.length;i++){
|
|
87
|
+
let sub= SUB_MENU_CONFIG[i];
|
|
88
|
+
if(routeTemplate&&sub.routeTemplate&&routeTemplate==sub.routeTemplate){
|
|
89
|
+
return sub.subRoute;
|
|
90
|
+
}
|
|
91
|
+
if(url&&sub.path&&url==sub.path){
|
|
92
|
+
return sub.subRoute;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
69
97
|
const transServicesMenuChildren=(menu)=>{
|
|
70
98
|
let req=[];
|
|
71
99
|
for(let i=0;i<menu.length;i++){
|
|
72
100
|
let item= menu[i];
|
|
73
|
-
const {url:path,name:label,icon,children:menus}= item;
|
|
101
|
+
const {url:path,name:label,icon,children:menus,routeTemplate}= item;
|
|
74
102
|
let children;
|
|
75
103
|
if(menus&&menus.length>0){
|
|
76
104
|
children= transServicesMenuChildren(menus);
|
|
77
105
|
}
|
|
106
|
+
let subRoute= getSubConfig(item);
|
|
78
107
|
req.push({
|
|
79
|
-
path,label,icon,children
|
|
108
|
+
path,label,icon,children,routeTemplate,subRoute
|
|
80
109
|
})
|
|
81
110
|
}
|
|
82
111
|
return req;
|
|
@@ -111,10 +140,20 @@ const TopMenu=(props)=>{
|
|
|
111
140
|
}
|
|
112
141
|
|
|
113
142
|
const GET_ROUTE_MENU=(menu)=>{
|
|
114
|
-
const {routeTemplate,path} = menu;
|
|
143
|
+
const {routeTemplate,path,subRoute} = menu;
|
|
115
144
|
const children = menu.children||menu.menus||null;
|
|
116
145
|
if(routeTemplate||path){
|
|
117
146
|
let match= matchPath(routeTemplate||path,curRoute.pathname);
|
|
147
|
+
if(!match&&subRoute){
|
|
148
|
+
match= subRoute.some(sub=>{
|
|
149
|
+
let subMatch= matchPath(sub.routeTemplate||sub.path,curRoute.pathname);
|
|
150
|
+
if(subMatch){
|
|
151
|
+
console.log(`match sub route: ${sub.routeTemplate||sub.path} -> ${curRoute.pathname}` )
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
});
|
|
156
|
+
}
|
|
118
157
|
if(match){
|
|
119
158
|
console.log(`match route: ${routeTemplate||path} -> ${curRoute.pathname}` )
|
|
120
159
|
return true;
|
|
@@ -3,16 +3,13 @@
|
|
|
3
3
|
import useImageLoader from './useImageLoader';
|
|
4
4
|
import useDelay from './useDelay';
|
|
5
5
|
import usePreload from './usePreload';
|
|
6
|
-
import useSearch from './useSearch';
|
|
7
|
-
import useUpdate from './useUpdate';
|
|
8
|
-
import useNextPage from './useNextPage';
|
|
9
6
|
import useLoading from './useLoading';
|
|
7
|
+
import {usePagination} from 'kn-hooks';
|
|
8
|
+
|
|
10
9
|
export {
|
|
10
|
+
usePagination,
|
|
11
11
|
useImageLoader,
|
|
12
12
|
useDelay,
|
|
13
13
|
usePreload,
|
|
14
|
-
|
|
15
|
-
useUpdate,
|
|
16
|
-
useNextPage,
|
|
17
|
-
useLoading
|
|
14
|
+
useLoading,
|
|
18
15
|
}
|
|
@@ -33,13 +33,11 @@ async function GET_USER_LIST(req,res){
|
|
|
33
33
|
}
|
|
34
34
|
return {
|
|
35
35
|
code:0,
|
|
36
|
-
data:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
total:MAX_TOTAL
|
|
42
|
-
}
|
|
36
|
+
data:data,
|
|
37
|
+
page:{
|
|
38
|
+
current:current,
|
|
39
|
+
pageSize:pageSize,
|
|
40
|
+
total:MAX_TOTAL
|
|
43
41
|
}
|
|
44
42
|
}
|
|
45
43
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useEffect, useState, useRef } from 'react';
|
|
2
|
+
import {List} from 'antd-mobile';
|
|
3
|
+
import {useUserType} from '@/dictionary';
|
|
4
|
+
import ShowToast from '@/components/Toast';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import styles from './index.less';
|
|
8
|
+
|
|
9
|
+
const Page = () => {
|
|
10
|
+
const emUserType= useUserType();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<section id="wall" className={styles.wall}>
|
|
14
|
+
<List header='字典'>
|
|
15
|
+
{
|
|
16
|
+
emUserType.isReady()&&emUserType.getList().map(item=>{
|
|
17
|
+
return <List.Item key={item.key} data-value={item.value} onClick={ (e)=>{
|
|
18
|
+
let value = e.currentTarget.getAttribute('data-value');
|
|
19
|
+
let item = emUserType.getData({id:value});
|
|
20
|
+
ShowToast(`${JSON.stringify(item)}`)
|
|
21
|
+
}}>{item.label}</List.Item>
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
</List>
|
|
25
|
+
|
|
26
|
+
</section>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default Page;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
.wall{
|
|
3
|
+
width: 100%;
|
|
4
|
+
height: 100%;
|
|
5
|
+
overflow-y: auto;
|
|
6
|
+
}
|
|
7
|
+
.wrap{
|
|
8
|
+
height:100%;
|
|
9
|
+
width:100%;
|
|
10
|
+
}
|
|
11
|
+
.item{
|
|
12
|
+
font-size: 40px;
|
|
13
|
+
}
|
|
14
|
+
.tips{
|
|
15
|
+
font-size: 36px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.btnGroup{
|
|
19
|
+
:global(.adm-button ){
|
|
20
|
+
margin-bottom: 24px;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {PullToRefresh ,
|
|
3
|
-
import {
|
|
4
|
-
import {GET_USER_LIST} from '@/services/user';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {PullToRefresh ,List} from 'antd-mobile';
|
|
3
|
+
import {useLoading} from '@/hooks';
|
|
5
4
|
import { useParams, useSearchParams,useNavigate } from 'react-router-dom';
|
|
6
5
|
|
|
7
6
|
import ProviderApp from '@/provider/app';
|
|
8
7
|
import moment from 'moment';
|
|
9
8
|
import ShowToast from '@/components/Toast';
|
|
10
|
-
import {useUserType} from '@/dictionary';
|
|
11
9
|
import {AuthShow} from '@/components/Auth';
|
|
12
10
|
|
|
13
11
|
import styles from './index.less';
|
|
@@ -17,54 +15,9 @@ const Page = () => {
|
|
|
17
15
|
const providerApp = ProviderApp.useContainer();
|
|
18
16
|
const query = useParams();
|
|
19
17
|
const [search] = useSearchParams();
|
|
20
|
-
const request = useNextPage({
|
|
21
|
-
service:GET_USER_LIST,
|
|
22
|
-
})
|
|
23
|
-
const [list,setList]= useState([]);
|
|
24
18
|
const loading = useLoading();
|
|
25
19
|
const loadingCanTouch = useLoading({canTouch:true});
|
|
26
20
|
|
|
27
|
-
const emUserType= useUserType();
|
|
28
|
-
|
|
29
|
-
useEffect(()=>{
|
|
30
|
-
let ret=[];
|
|
31
|
-
request?.data?.forEach(page=>{
|
|
32
|
-
try{
|
|
33
|
-
ret = [...ret,...page];
|
|
34
|
-
}catch(ex){
|
|
35
|
-
console.error(ex)
|
|
36
|
-
debugger;
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
setList(ret);
|
|
40
|
-
|
|
41
|
-
},[request.data])
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const onReset= async ()=>{
|
|
45
|
-
return request.reset();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const onNextPage= async ()=>{
|
|
49
|
-
if(loading.loading>0){
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
loading.setLoading(true)
|
|
53
|
-
let dom = document.querySelector('#wall');
|
|
54
|
-
dom.scrollTop-=200;
|
|
55
|
-
await request.nextPage();
|
|
56
|
-
loading.setLoading(false)
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
const refresh=async ()=>{
|
|
60
|
-
loading.setLoading(true)
|
|
61
|
-
await request.refresh();
|
|
62
|
-
loading.setLoading(false);
|
|
63
|
-
}
|
|
64
|
-
useEffect(()=>{
|
|
65
|
-
refresh();
|
|
66
|
-
},[]);
|
|
67
|
-
|
|
68
21
|
return (
|
|
69
22
|
<section id="wall" className={styles.wall}>
|
|
70
23
|
<PullToRefresh className={styles.wrap}
|
|
@@ -134,31 +87,15 @@ const Page = () => {
|
|
|
134
87
|
loadingCanTouch.setLoading(false);
|
|
135
88
|
}}>打开全局loading-持续3秒(不阻止交互)</List.Item>
|
|
136
89
|
</List>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
emUserType.isReady()&&emUserType.getList().map(item=>{
|
|
141
|
-
return <List.Item key={item.key} data-value={item.value} onClick={ (e)=>{
|
|
142
|
-
let value = e.currentTarget.getAttribute('data-value');
|
|
143
|
-
let item = emUserType.getData({id:value});
|
|
144
|
-
ShowToast(`${JSON.stringify(item)}`)
|
|
145
|
-
}}>{item.label}</List.Item>
|
|
146
|
-
})
|
|
147
|
-
}
|
|
90
|
+
<List header='UI组件'>
|
|
91
|
+
<List.Item key='scrollList' onClick={()=>{navigate('/list')}}>下拉刷新及滚动加载</List.Item>
|
|
148
92
|
</List>
|
|
149
93
|
|
|
150
|
-
<List header='
|
|
151
|
-
{
|
|
152
|
-
list.map((item,idx)=>{
|
|
153
|
-
return (
|
|
154
|
-
<List.Item key={item.name}>{item.name}-{item.resetCount}</List.Item>
|
|
155
|
-
)
|
|
156
|
-
})
|
|
157
|
-
}
|
|
94
|
+
<List header='其它'>
|
|
95
|
+
<List.Item key='dictionary' onClick={()=>{navigate('/dictionary')}}>字典</List.Item>
|
|
158
96
|
</List>
|
|
159
97
|
|
|
160
98
|
</PullToRefresh>
|
|
161
|
-
<InfiniteScroll threshold={40} loadMore={onNextPage} hasMore={request.pagination.more} />
|
|
162
99
|
|
|
163
100
|
</section>
|
|
164
101
|
)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React, { useEffect, useState, useRef } from 'react';
|
|
2
|
+
import {PullToRefresh ,InfiniteScroll,List} from 'antd-mobile';
|
|
3
|
+
import {usePagination,useLoading} from '@/hooks';
|
|
4
|
+
import {GET_USER_LIST} from '@/services/user';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import styles from './index.less';
|
|
8
|
+
|
|
9
|
+
const Page = () => {
|
|
10
|
+
const request = usePagination({
|
|
11
|
+
service:GET_USER_LIST,
|
|
12
|
+
})
|
|
13
|
+
const [list,setList]= useState([]);
|
|
14
|
+
const loading = useLoading();
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
useEffect(()=>{
|
|
18
|
+
let ret=[];
|
|
19
|
+
request?.data?.forEach(page=>{
|
|
20
|
+
try{
|
|
21
|
+
ret = [...ret,...page];
|
|
22
|
+
}catch(ex){
|
|
23
|
+
console.error(ex)
|
|
24
|
+
debugger;
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
setList(ret);
|
|
28
|
+
|
|
29
|
+
},[request.data])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
const onReset= async ()=>{
|
|
33
|
+
return request.reset();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const onNextPage= async ()=>{
|
|
37
|
+
if(loading.loading>0){
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
loading.setLoading(true)
|
|
41
|
+
let dom = document.querySelector('#wall');
|
|
42
|
+
dom.scrollTop-=200;
|
|
43
|
+
await request.nextPage();
|
|
44
|
+
loading.setLoading(false)
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
const refresh=async ()=>{
|
|
48
|
+
loading.setLoading(true)
|
|
49
|
+
await request.update();
|
|
50
|
+
loading.setLoading(false);
|
|
51
|
+
}
|
|
52
|
+
useEffect(()=>{
|
|
53
|
+
refresh();
|
|
54
|
+
},[]);
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<section id="wall" className={styles.wall}>
|
|
58
|
+
<PullToRefresh className={styles.wrap}
|
|
59
|
+
onRefresh={async () => {
|
|
60
|
+
await onReset();
|
|
61
|
+
return true;
|
|
62
|
+
}}
|
|
63
|
+
>
|
|
64
|
+
<List header='下拉刷新,滚动加载案例'>
|
|
65
|
+
{
|
|
66
|
+
list.map((item,idx)=>{
|
|
67
|
+
return (
|
|
68
|
+
<List.Item key={item.name}>{item.name}-{item.resetCount}</List.Item>
|
|
69
|
+
)
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
</List>
|
|
73
|
+
|
|
74
|
+
</PullToRefresh>
|
|
75
|
+
<InfiniteScroll threshold={40} loadMore={onNextPage} hasMore={request.pagination.more} />
|
|
76
|
+
|
|
77
|
+
</section>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default Page;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
.wall{
|
|
3
|
+
width: 100%;
|
|
4
|
+
height: 100%;
|
|
5
|
+
overflow-y: auto;
|
|
6
|
+
}
|
|
7
|
+
.wrap{
|
|
8
|
+
height:100%;
|
|
9
|
+
width:100%;
|
|
10
|
+
}
|
|
11
|
+
.item{
|
|
12
|
+
font-size: 40px;
|
|
13
|
+
}
|
|
14
|
+
.tips{
|
|
15
|
+
font-size: 36px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.btnGroup{
|
|
19
|
+
:global(.adm-button ){
|
|
20
|
+
margin-bottom: 24px;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -3,6 +3,10 @@ import { Routes, Route, Navigate} from 'react-router-dom';
|
|
|
3
3
|
import Home from '@/pages/index.jsx';
|
|
4
4
|
import Login from '@/pages/login';
|
|
5
5
|
import User from '@/pages/user';
|
|
6
|
+
import List from '@/pages/list';
|
|
7
|
+
import Dictionary from '@/pages/dictionary';
|
|
8
|
+
|
|
9
|
+
|
|
6
10
|
import {LayoutApp,LayoutProvider} from '@/components/Layout';
|
|
7
11
|
import {AuthLogin} from '@/components/Auth';
|
|
8
12
|
export const RouteList = (
|
|
@@ -13,6 +17,10 @@ export const RouteList = (
|
|
|
13
17
|
<Route path='/' element={<Navigate to='/demo/1001?type=test&name=demo' />} />
|
|
14
18
|
<Route path='/demo/:id' element={<Home />} />
|
|
15
19
|
<Route path='/user' element={<AuthLogin><User /></AuthLogin>} />
|
|
20
|
+
<Route path='/list' element={<List />} />
|
|
21
|
+
<Route path='/dictionary' element={<Dictionary />} />
|
|
22
|
+
|
|
23
|
+
|
|
16
24
|
</Route>
|
|
17
25
|
<Route path='/login' element={<Login />} />
|
|
18
26
|
</Route>
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { useState,useRef } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const DEFAULT_PAGE_SIZE=20;
|
|
5
|
-
const DEFAULT_PAGE_CURRENT=1;
|
|
6
|
-
|
|
7
|
-
const useNextPage=(props)=>{
|
|
8
|
-
const [search,setSearch] = useState(props.initSearch||{});
|
|
9
|
-
const [service] = useState(()=>props.service);
|
|
10
|
-
const [beforeService] = useState(()=>props.beforeService);
|
|
11
|
-
const [pagination,setPagination] = useState(()=>{
|
|
12
|
-
let temp = {
|
|
13
|
-
current:DEFAULT_PAGE_CURRENT,
|
|
14
|
-
pageSize:DEFAULT_PAGE_SIZE,
|
|
15
|
-
total:0,
|
|
16
|
-
startIdx:0,
|
|
17
|
-
more:false,
|
|
18
|
-
...props.pagination
|
|
19
|
-
};
|
|
20
|
-
temp.startIdx = (temp.current-1)*temp.pageSize;
|
|
21
|
-
return temp;
|
|
22
|
-
});
|
|
23
|
-
const resetCount = useRef(0);
|
|
24
|
-
const [data,setData] = useState([]);
|
|
25
|
-
|
|
26
|
-
const reset= async ()=>{
|
|
27
|
-
resetCount.current++;
|
|
28
|
-
let page = {...pagination};
|
|
29
|
-
page.current =1;
|
|
30
|
-
return refresh({pageValue:page})
|
|
31
|
-
}
|
|
32
|
-
const nextPage= async ()=>{
|
|
33
|
-
if(!pagination.more){
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
let page = {...pagination};
|
|
37
|
-
page.current= +page.current+1;
|
|
38
|
-
return refresh({pageValue:page})
|
|
39
|
-
}
|
|
40
|
-
const refresh= async ({searchValue,pageValue}={})=>{
|
|
41
|
-
searchValue = searchValue || search;
|
|
42
|
-
pageValue = pageValue || pagination;
|
|
43
|
-
searchValue = {...search,...searchValue};
|
|
44
|
-
pageValue = {...pagination,...pageValue};
|
|
45
|
-
|
|
46
|
-
const {current,pageSize} = pageValue;
|
|
47
|
-
let params = {...searchValue,current:current,pageSize:pageSize};
|
|
48
|
-
if(beforeService)params=beforeService(params);
|
|
49
|
-
if(!params)return;
|
|
50
|
-
|
|
51
|
-
setSearch(searchValue);
|
|
52
|
-
|
|
53
|
-
let ret = await service(params);
|
|
54
|
-
if(ret?.code==0){
|
|
55
|
-
const {page} = ret.data;
|
|
56
|
-
const current= +(page.pageNum||DEFAULT_PAGE_CURRENT);
|
|
57
|
-
const pageSize= +(page.pageSize||DEFAULT_PAGE_SIZE);
|
|
58
|
-
const total= +page.total;
|
|
59
|
-
const startIdx= (current-1)*pageSize;
|
|
60
|
-
const more = current*pageSize<total;
|
|
61
|
-
setPagination({
|
|
62
|
-
current,pageSize,total,startIdx,more
|
|
63
|
-
})
|
|
64
|
-
if(ret.data.list){
|
|
65
|
-
ret.data.list.map(item=>{
|
|
66
|
-
item.resetCount = resetCount.current;
|
|
67
|
-
})
|
|
68
|
-
let newData = current==1?[]:data;
|
|
69
|
-
newData[current-1] = ret.data.list;
|
|
70
|
-
setData([...newData])
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return ret;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
pagination,
|
|
79
|
-
search,
|
|
80
|
-
setSearch,
|
|
81
|
-
refresh,
|
|
82
|
-
reset,
|
|
83
|
-
nextPage,
|
|
84
|
-
data,
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export default useNextPage;
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { useRef,useState,useMemo, useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 管理表格数据的查询搜索及分页
|
|
5
|
-
*/
|
|
6
|
-
const useSearch=(props)=>{
|
|
7
|
-
const [search,setSearch] = useState(props.initSearch||{});
|
|
8
|
-
const [service] = useState(()=>props.service);
|
|
9
|
-
const [beforeSearch] = useState(()=>props.beforeSearch);
|
|
10
|
-
const [beforeService] = useState(()=>props.beforeService);
|
|
11
|
-
|
|
12
|
-
const [pagination,setPagination] = useState(()=>{
|
|
13
|
-
let temp = {current:1,pageSize:10,total:0,startIdx:0,...props.pagination};
|
|
14
|
-
temp.startIdx = (temp.current-1)*temp.pageSize;
|
|
15
|
-
return temp;
|
|
16
|
-
});
|
|
17
|
-
const [updateData] = useState(()=>props.updateData);
|
|
18
|
-
const [orderInfo,setOrderInfo]=useState({});
|
|
19
|
-
|
|
20
|
-
const onPaginationChange=async (pageInfo,sorterInfo)=>{
|
|
21
|
-
let {current,pageSize} = pagination;
|
|
22
|
-
let orderValue=orderInfo;
|
|
23
|
-
if(pageInfo){
|
|
24
|
-
current = pageInfo.current;
|
|
25
|
-
pageSize = pageInfo.pageSize;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if(sorterInfo){
|
|
29
|
-
const {field,order}= sorterInfo;
|
|
30
|
-
if(field){
|
|
31
|
-
if(order){
|
|
32
|
-
orderInfo[field] = order;
|
|
33
|
-
}else{
|
|
34
|
-
delete orderInfo[field];
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
orderValue = orderInfo;
|
|
38
|
-
setOrderInfo({...orderInfo});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
let searchValue = await getSearchValue();
|
|
43
|
-
refresh({
|
|
44
|
-
searchValue,
|
|
45
|
-
pageValue:{pageSize,current},
|
|
46
|
-
orderValue});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const onSorter=async (sorter)=>{
|
|
50
|
-
const {field,order}= sorter;
|
|
51
|
-
if(field){
|
|
52
|
-
if(order){
|
|
53
|
-
orderInfo[field] = order;
|
|
54
|
-
}else{
|
|
55
|
-
delete orderInfo[field];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
setOrderInfo({...orderInfo});
|
|
59
|
-
console.log(`${JSON.stringify(orderInfo)}`);
|
|
60
|
-
refresh();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const getSearchValue=async ()=>{
|
|
67
|
-
let value={};
|
|
68
|
-
value = search;
|
|
69
|
-
|
|
70
|
-
if(beforeSearch){
|
|
71
|
-
value = beforeSearch(value);
|
|
72
|
-
}
|
|
73
|
-
return value;
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
const btnSearch=async ()=>{
|
|
77
|
-
let value = await getSearchValue();
|
|
78
|
-
if(value){
|
|
79
|
-
refresh({searchValue:value});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
const btnReset=()=>{
|
|
83
|
-
formRef.resetFields();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const refresh= async ({searchValue,pageValue,orderValue}={})=>{
|
|
87
|
-
searchValue = searchValue || search;
|
|
88
|
-
pageValue = pageValue || pagination;
|
|
89
|
-
|
|
90
|
-
// 排序暂无
|
|
91
|
-
// orderValue = orderValue || orderInfo;
|
|
92
|
-
// let order=[];
|
|
93
|
-
// if(orderValue){
|
|
94
|
-
// Object.keys(orderValue).map(name=>{
|
|
95
|
-
// if(orderValue[name]==='ascend'){
|
|
96
|
-
// order.push(`${name}`);
|
|
97
|
-
// }else if(orderValue[name]==='descend'){
|
|
98
|
-
// order.push(`-${name}`);
|
|
99
|
-
// }
|
|
100
|
-
// })
|
|
101
|
-
// }
|
|
102
|
-
|
|
103
|
-
let {current,pageSize} = pageValue;
|
|
104
|
-
let params = {...searchValue,page:current,pageSize:pageSize};
|
|
105
|
-
if(beforeService)params=beforeService(params);
|
|
106
|
-
if(!params)return;
|
|
107
|
-
let ret = await service(params);
|
|
108
|
-
if(ret?.code==0){
|
|
109
|
-
const {page} = ret.data;
|
|
110
|
-
setPagination({
|
|
111
|
-
current:page.pageNum||1,
|
|
112
|
-
pageSize:page.pageSize||10,
|
|
113
|
-
total:page.total,
|
|
114
|
-
startIdx:(page.page-1)*page.pageSize
|
|
115
|
-
})
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if(updateData)updateData(ret);
|
|
119
|
-
return ret;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return {
|
|
124
|
-
onPaginationChange,
|
|
125
|
-
pagination,
|
|
126
|
-
btnSearch,
|
|
127
|
-
search,
|
|
128
|
-
setSearch,
|
|
129
|
-
refresh,
|
|
130
|
-
btnReset,
|
|
131
|
-
onSorter
|
|
132
|
-
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export default useSearch;
|