kn-cli 1.0.107 → 1.0.109
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/package.json +2 -1
- package/package.json +1 -1
- package/templates/template_admin/cli.config.js +1 -0
- package/templates/template_admin/public/src/_mixin.less +38 -0
- package/templates/template_admin/public/src/_reset.less +0 -7
- package/templates/template_admin/public/src/assets/images/permission/403.png +0 -0
- package/templates/template_admin/public/src/assets/images/permission/404.png +0 -0
- package/templates/template_admin/public/src/assets/images/permission/503.png +0 -0
- package/templates/template_admin/public/src/components/antd/index.jsx +145 -0
- package/templates/template_admin/public/src/components/antd/tooltip/detail/index.jsx +70 -0
- package/templates/template_admin/public/src/components/antd/tooltip/detail/index.less +12 -0
- package/templates/template_admin/public/src/components/antd/tooltip/index.jsx +69 -0
- package/templates/template_admin/public/src/components/antd/tooltip/index.less +28 -0
- package/templates/template_admin/public/src/components/auth/index.jsx +60 -3
- package/templates/template_admin/public/src/components/auth/navCheck.jsx +27 -0
- package/templates/template_admin/public/src/components/button/index.jsx +17 -0
- package/templates/template_admin/public/src/components/debug/index.jsx +1 -1
- package/templates/template_admin/public/src/components/error/index.jsx +39 -0
- package/templates/template_admin/public/src/components/image/index.jsx +1 -1
- package/templates/template_admin/public/src/components/image/preview.jsx +1 -1
- package/templates/template_admin/public/src/components/layout/provider/index.jsx +2 -2
- package/templates/template_admin/public/src/components/leftMenu/index.jsx +31 -6
- package/templates/template_admin/public/src/components/menuIcon/index.jsx +33 -0
- package/templates/template_admin/public/src/components/menuIcon/index.less +49 -0
- package/templates/template_admin/public/src/components/react/index.jsx +7 -0
- package/templates/template_admin/public/src/components/select/defaultServicesSelect/index.jsx +182 -0
- package/templates/template_admin/public/src/components/select/dictSelect/index.jsx +84 -0
- package/templates/template_admin/public/src/components/select/index.jsx +7 -0
- package/templates/template_admin/public/src/components/select/useSelectList.jsx +217 -0
- package/templates/template_admin/public/src/components/table/index.jsx +1 -1
- package/templates/template_admin/public/src/components/text/index.jsx +1 -1
- package/templates/template_admin/public/src/components/topMenu/index.jsx +6 -1
- package/templates/template_admin/public/src/components/topMenu/index.less +10 -1
- package/templates/template_admin/public/src/components/topMenu/topBar/index.jsx +6 -1
- package/templates/template_admin/public/src/components/topMenu/topBar/index.less +9 -0
- package/templates/template_admin/public/src/config.js +28 -0
- package/templates/template_admin/public/src/dictionary/dictionary.js +289 -0
- package/templates/template_admin/public/src/dictionary/index.js +22 -126
- package/templates/template_admin/public/src/hooks/useRouteMenu.jsx +25 -3
- package/templates/template_admin/public/src/hooks/useThrottole.jsx +68 -0
- package/templates/template_admin/public/src/index.jsx +33 -15
- package/templates/template_admin/public/src/menuConfig.jsx +152 -0
- package/templates/template_admin/public/src/pages/auth/user/create/index.jsx +1 -9
- package/templates/template_admin/public/src/pages/auth/user/dialog/index.jsx +1 -1
- package/templates/template_admin/public/src/pages/auth/user/index.jsx +3 -60
- package/templates/template_admin/public/src/pages/components/select/user.jsx +18 -0
- package/templates/template_admin/public/src/pages/demo/page1.jsx +21 -0
- package/templates/template_admin/public/src/pages/demo/page2.jsx +21 -0
- package/templates/template_admin/public/src/pages/demo/page3.jsx +21 -0
- package/templates/template_admin/public/src/pages/error/403.jsx +15 -0
- package/templates/template_admin/public/src/pages/error/404.jsx +15 -0
- package/templates/template_admin/public/src/pages/error/503.jsx +15 -0
- package/templates/template_admin/public/src/pages/error/permission.jsx +40 -0
- package/templates/template_admin/public/src/pages/error/permission.less +16 -0
- package/templates/template_admin/public/src/pages/home.jsx +15 -4
- package/templates/template_admin/public/src/pages/login/index.jsx +3 -2
- package/templates/template_admin/public/src/pages/pageTemplate.jsx +28 -0
- package/templates/template_admin/public/src/provider/app.jsx +86 -55
- package/templates/template_admin/public/src/provider/menu.jsx +75 -108
- package/templates/template_admin/public/src/route.jsx +55 -35
- package/templates/template_admin/public/src/services/index.js +28 -4
- package/templates/template_admin/public/src/services/socket/index.jsx +1 -1
- package/templates/template_admin/public/src/utils/storage.js +30 -0
- package/templates/template_admin/webpack.api.js +24 -0
- package/templates/template_admin/public/src/pages/components/select/account/index.jsx +0 -114
- package/templates/template_admin/public/src/pages/components/select/device/index.jsx +0 -83
- package/templates/template_admin/public/src/pages/components/select/groupUser/index.jsx +0 -172
- package/templates/template_admin/public/src/pages/components/select/user/index.jsx +0 -119
|
@@ -8,6 +8,7 @@ import ProviderMenu from '@/provider/menu';
|
|
|
8
8
|
import imgSlogan from '@/assets/images/nav/slogan.png';
|
|
9
9
|
|
|
10
10
|
import TopBar from './topBar';
|
|
11
|
+
import {DEBUG_ENV} from '@/config';
|
|
11
12
|
|
|
12
13
|
// @ts-ignore
|
|
13
14
|
import styles from './index.less';
|
|
@@ -20,6 +21,10 @@ const TopSlogan=()=>{
|
|
|
20
21
|
return (
|
|
21
22
|
<div className={styles.TopMenuSlogan} onClick={onHome}>
|
|
22
23
|
<img src={imgSlogan} />
|
|
24
|
+
{
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
DEBUG_ENV!='prod'?<span className={styles.version}>V{APP_VERSION}{DEBUG_ENV}</span>:<></>
|
|
27
|
+
}
|
|
23
28
|
</div>
|
|
24
29
|
)
|
|
25
30
|
}
|
|
@@ -79,7 +84,7 @@ const TopMenu=(props)=>{
|
|
|
79
84
|
data-checked={active}
|
|
80
85
|
onClick={onClickMenuItem.bind(this,menu)}
|
|
81
86
|
>
|
|
82
|
-
<span>{label}</span>
|
|
87
|
+
<span><a href={'/#'+menu.url}>{label}</a></span>
|
|
83
88
|
{/* 未读标记 */}
|
|
84
89
|
<div className={styles.messageWrap}>
|
|
85
90
|
{msgCount>0?<i className={styles.iconUnread}/>:''}
|
|
@@ -13,6 +13,15 @@
|
|
|
13
13
|
img{
|
|
14
14
|
width: 73px;
|
|
15
15
|
}
|
|
16
|
+
.version{
|
|
17
|
+
font-size: 12px;
|
|
18
|
+
font-weight:700;
|
|
19
|
+
color:white;
|
|
20
|
+
background-color: rgba(255,255,255,.16);
|
|
21
|
+
padding:2px 4px;
|
|
22
|
+
border-radius: 2px;
|
|
23
|
+
margin-left: 4px;
|
|
24
|
+
}
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
.topMenu{
|
|
@@ -44,7 +53,7 @@
|
|
|
44
53
|
font-size: 14px;
|
|
45
54
|
color:#fff;
|
|
46
55
|
background-color: transparent;
|
|
47
|
-
span{
|
|
56
|
+
a,span{
|
|
48
57
|
font-weight: inherit;
|
|
49
58
|
font-size: inherit;
|
|
50
59
|
color:inherit;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
2
|
import React, { useRef, useState } from 'react';
|
|
3
3
|
// @ts-ignore
|
|
4
|
-
import { Dropdown,message } from 'antd'
|
|
4
|
+
import { Dropdown,message } from '@/components/antd'
|
|
5
5
|
// @ts-ignore
|
|
6
6
|
import { LogoutOutlined } from '@ant-design/icons';
|
|
7
7
|
// @ts-ignore
|
|
@@ -56,6 +56,11 @@ const TopBar=()=>{
|
|
|
56
56
|
key:'user',
|
|
57
57
|
label:<span className={styles.userMenuItem}>Hi,{app?.user?.realName||'用户'}</span>
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
key:'version',
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
label:<span className={styles.userMenuItem}><hgroup className={styles.version} ><span>版本</span><span>V{APP_VERSION}</span></hgroup></span>
|
|
63
|
+
},
|
|
59
64
|
{
|
|
60
65
|
key:'logout',
|
|
61
66
|
label:<span onClick={onAvatarClick.bind(this,'logout')} className={styles.userMenuItem}><LogoutOutlined />退出登录</span>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
// 权限调试开关
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
export const AUTH_DEBUG_OPEN=BUILD_ENV=='prod'?false:true;
|
|
6
|
+
// 菜单权限调试开关
|
|
7
|
+
export const AUTH_ROUTE_DEBUG_OPEN=false;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// 当前你需要模拟调试哪个环境下的数据
|
|
11
|
+
export const DEBUG_ENV='local';
|
|
12
|
+
// export const DEBUG_ENV='dev';
|
|
13
|
+
// export const DEBUG_ENV='pre';
|
|
14
|
+
// export const DEBUG_ENV='local';
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const DEBUG_API_HOST_CONFIG={
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
local:API_HOST,// 本地调试
|
|
21
|
+
dev:'/devapi/api',
|
|
22
|
+
pre:'/preapi/api',
|
|
23
|
+
prod:'/prodapi/api',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 配置本地调试时api调用的接口地址,
|
|
27
|
+
export const DEBUG_API_HOST=DEBUG_API_HOST_CONFIG[DEBUG_ENV]
|
|
28
|
+
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
|
|
2
|
+
import React,{ useState, useMemo, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @template [T=object]
|
|
7
|
+
* @callback Api
|
|
8
|
+
* @param {Object} params - 调用接口用到的参数
|
|
9
|
+
* @returns {Promise<T>}
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef DictionaryItem
|
|
15
|
+
* 字典数据的结构
|
|
16
|
+
* @property {string} id - 数据唯一ID
|
|
17
|
+
* @property {string} name - 数据唯一id对应的别名
|
|
18
|
+
* @property {string} label - 展示给用户看的文字
|
|
19
|
+
* @property {boolean} [disabled] - 是否禁用
|
|
20
|
+
* @property {object} [data] - 原始数据
|
|
21
|
+
* @property {string} [subLabel] - 副标题
|
|
22
|
+
* @property {string} [type] - 是不是多选框
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef RenderOptions
|
|
28
|
+
* @property {(item:DictionaryItem)=>JSX.Element} [onRender] - 渲染拦截器
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @typedef CreateOptions
|
|
33
|
+
* @property {DictionaryItem[]} [types] - 字典数据列表
|
|
34
|
+
* @property {string} [idKey='id'] - id的字段名
|
|
35
|
+
* @property {string} [nameKey='name'] - id的字段名
|
|
36
|
+
* @property {string} [labelKey='label'] - id的字段名
|
|
37
|
+
* @property {(item:DictionaryItem)=>JSX.Element} [onRender] - 渲染Item的拦截器
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @typedef GetOptionsProps
|
|
43
|
+
* @property {object} props
|
|
44
|
+
* @property {(item:DictionaryItem)=>boolean} [props.onFilter] - 数据唯一id对应的别名
|
|
45
|
+
* @property {(item:DictionaryItem)=>boolean} [props.onDisabled] - 数据唯一id对应的别名
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @typedef RenderOptionsProps
|
|
50
|
+
* @property {object} props
|
|
51
|
+
* @property {DictionaryItem[]} [props.options] - 数据唯一id对应的别名
|
|
52
|
+
* @property {JSX.Element} [props.OptionComponent] - 数据唯一id对应的别名
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @typedef EnumResult
|
|
59
|
+
* @property {DictionaryItem[]} types - 字典数据列表
|
|
60
|
+
* @property {(labelOrName:string)=>string} [getId] - 搜索字典项中,label或name匹配labelOrName的项目,返回其id的值
|
|
61
|
+
* @property {(id:string)=>string} [getName] - 匹配id复合的对象,返回其name的值
|
|
62
|
+
* @property {(id:string)=>string} [getLabel] - 匹配id复合的对象,返回其label的值
|
|
63
|
+
* @property {(idOrNameOrLabel:string)=>DictionaryItem} [getItem] - 匹配id,label,name只要符合的返回对象
|
|
64
|
+
* @property {(props?:GetOptionsProps)=>DictionaryItem[]} [getOptions] - 获取选项列表
|
|
65
|
+
* @property {(props?:RenderOptions)=>JSX.Element[]} [render] - 触发渲染
|
|
66
|
+
*
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @typedef CreateApiDictionaryOptions
|
|
72
|
+
* @property {Api} [api] - 用于获取字典列表的接口
|
|
73
|
+
* @property {(request:object)=>object} [beforeApi] - (request:object)=>object 接口调用前的参数拦截器
|
|
74
|
+
* @property {(response:object)=>object} [afterApi] - (reponse:object)=>object[] 接口调用后的拦截器
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @typedef {CreateOptions & CreateApiDictionaryOptions} CreateDictionaryOptions
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @typedef CreateDictoryResult
|
|
83
|
+
* @property {()=>boolean} isReady - 是否加载完毕
|
|
84
|
+
* @property {()=>void} reload - 重新加载
|
|
85
|
+
*
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @typedef {CreateDictoryResult & EnumResult} UseDictionaryResult
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
const DEFAULT_CONFIG={
|
|
94
|
+
beforeApi:null,
|
|
95
|
+
afterApi:null,
|
|
96
|
+
idKey:'id',
|
|
97
|
+
nameKey:'name',
|
|
98
|
+
labelKey:'label'
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @function
|
|
104
|
+
* @description 全局设置SelectOption和RadioOption
|
|
105
|
+
* @param {Object} params
|
|
106
|
+
*
|
|
107
|
+
* @returns {void}
|
|
108
|
+
*/
|
|
109
|
+
export const SetConfig = ({beforeApi,afterApi,idKey,nameKey,labelKey})=>{
|
|
110
|
+
if(beforeApi)DEFAULT_CONFIG.beforeApi = beforeApi;
|
|
111
|
+
if(afterApi)DEFAULT_CONFIG.afterApi = afterApi;
|
|
112
|
+
if(idKey)DEFAULT_CONFIG.idKey = idKey;
|
|
113
|
+
if(nameKey)DEFAULT_CONFIG.nameKey = nameKey;
|
|
114
|
+
if(labelKey)DEFAULT_CONFIG.labelKey = labelKey;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 创建一个静态的字典
|
|
120
|
+
* @param {CreateOptions} props
|
|
121
|
+
* @returns {EnumResult}
|
|
122
|
+
*/
|
|
123
|
+
export const createEnum=props=>{
|
|
124
|
+
const {
|
|
125
|
+
idKey = DEFAULT_CONFIG.idKey,
|
|
126
|
+
nameKey = DEFAULT_CONFIG.nameKey,
|
|
127
|
+
labelKey = DEFAULT_CONFIG.labelKey,
|
|
128
|
+
types,
|
|
129
|
+
onRender
|
|
130
|
+
} = props;
|
|
131
|
+
|
|
132
|
+
const idMap={};
|
|
133
|
+
const labelMap={};
|
|
134
|
+
const nameMap={};
|
|
135
|
+
|
|
136
|
+
if(types){
|
|
137
|
+
types.forEach(item=>{
|
|
138
|
+
idMap[''+item[idKey]] = item;
|
|
139
|
+
labelMap[''+item[labelKey]] = item;
|
|
140
|
+
nameMap[''+item[nameKey]] = item;
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const getLabel = (id) => {
|
|
145
|
+
let key = ''+id;
|
|
146
|
+
if(!types)return '';
|
|
147
|
+
if(idMap[key]){
|
|
148
|
+
return idMap[key][labelKey]
|
|
149
|
+
}
|
|
150
|
+
return '';
|
|
151
|
+
};
|
|
152
|
+
const getName = (id) => {
|
|
153
|
+
let key = ''+id;
|
|
154
|
+
if(!types)return '';
|
|
155
|
+
if(idMap[key]){
|
|
156
|
+
return idMap[key][nameKey]
|
|
157
|
+
}
|
|
158
|
+
return '';
|
|
159
|
+
};
|
|
160
|
+
const getId = (labelOrName) => {
|
|
161
|
+
let key = ''+labelOrName;
|
|
162
|
+
if(!types)return '';
|
|
163
|
+
if(nameMap[key]){
|
|
164
|
+
return nameMap[key][idKey]
|
|
165
|
+
}
|
|
166
|
+
if(labelMap[key]){
|
|
167
|
+
return labelMap[key][idKey]
|
|
168
|
+
}
|
|
169
|
+
return '';
|
|
170
|
+
};
|
|
171
|
+
const getItem=(idOrNameOrLabel)=>{
|
|
172
|
+
let key = ''+idOrNameOrLabel;
|
|
173
|
+
if(!types)return null;
|
|
174
|
+
if(idMap[key]){
|
|
175
|
+
return idMap[key]
|
|
176
|
+
}
|
|
177
|
+
if(nameMap[key]){
|
|
178
|
+
return nameMap[key]
|
|
179
|
+
}
|
|
180
|
+
if(labelMap[key]){
|
|
181
|
+
return labelMap[key]
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
};
|
|
185
|
+
const getOptions=(props)=>{
|
|
186
|
+
const {onFilter,onDisabled}=props;
|
|
187
|
+
let req=[];
|
|
188
|
+
if(!types)return req;
|
|
189
|
+
types.forEach(item=>{
|
|
190
|
+
let show=true;
|
|
191
|
+
let disabled=false;
|
|
192
|
+
|
|
193
|
+
if(onFilter){
|
|
194
|
+
show = onFilter(item);
|
|
195
|
+
}
|
|
196
|
+
if(onDisabled){
|
|
197
|
+
disabled = onDisabled(item);
|
|
198
|
+
}
|
|
199
|
+
if(show){
|
|
200
|
+
req.push({
|
|
201
|
+
...item,
|
|
202
|
+
disabled:disabled,
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
return req;
|
|
207
|
+
}
|
|
208
|
+
const render=(props)=>{
|
|
209
|
+
const _onRender = props?.onRender || onRender;
|
|
210
|
+
let req=[];
|
|
211
|
+
if(!_onRender)return req;
|
|
212
|
+
types.forEach(item=>{
|
|
213
|
+
if(_onRender){
|
|
214
|
+
let component=_onRender(item);
|
|
215
|
+
if(component){
|
|
216
|
+
req.push(component);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
return req;
|
|
221
|
+
}
|
|
222
|
+
return { types, getLabel, getId, getName,getItem,getOptions,render };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @function
|
|
228
|
+
* @description 创建字典hooks工具
|
|
229
|
+
* @param {CreateDictionaryOptions} options
|
|
230
|
+
*
|
|
231
|
+
* @returns {()=>UseDictionaryResult}
|
|
232
|
+
*/
|
|
233
|
+
export const createDictionary=options=>{
|
|
234
|
+
const {
|
|
235
|
+
api,
|
|
236
|
+
beforeApi = DEFAULT_CONFIG.beforeApi,
|
|
237
|
+
afterApi = DEFAULT_CONFIG.afterApi,
|
|
238
|
+
} = options;
|
|
239
|
+
const defaultTypes = options.types || null;
|
|
240
|
+
return ()=>{
|
|
241
|
+
/**
|
|
242
|
+
* @type {[EnumResult,React.Dispatch<React.SetStateAction<EnumResult>>]}
|
|
243
|
+
*/
|
|
244
|
+
const [enumItem, setEnumItem] = useState(()=>{
|
|
245
|
+
if(!api)return createEnum({...options,types:defaultTypes||[]})
|
|
246
|
+
return {types:null}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
const init = async () => {
|
|
250
|
+
if(!api)return;
|
|
251
|
+
let params={};
|
|
252
|
+
let items=[];
|
|
253
|
+
if(beforeApi){
|
|
254
|
+
params = beforeApi();
|
|
255
|
+
}
|
|
256
|
+
let ret = await api(params);
|
|
257
|
+
if(afterApi){
|
|
258
|
+
items = afterApi(ret);
|
|
259
|
+
}else{
|
|
260
|
+
if (+ret?.code === 0) {
|
|
261
|
+
items = ret.data.body;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
let value=createEnum({...options,types:items||[]});
|
|
265
|
+
setEnumItem(value);
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const isReady = () => {
|
|
269
|
+
return enumItem?.types !== null;
|
|
270
|
+
};
|
|
271
|
+
const reload = () => {
|
|
272
|
+
init();
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
useEffect(() => {
|
|
276
|
+
init();
|
|
277
|
+
}, [api,beforeApi,afterApi]);
|
|
278
|
+
|
|
279
|
+
const actions = useMemo(() => {
|
|
280
|
+
return { isReady, reload,...enumItem };
|
|
281
|
+
}, [enumItem]);
|
|
282
|
+
|
|
283
|
+
return actions;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
@@ -1,135 +1,29 @@
|
|
|
1
1
|
|
|
2
2
|
// @ts-ignore
|
|
3
3
|
import React from 'react';
|
|
4
|
-
// @ts-ignore
|
|
5
|
-
import {useDictionary} from 'kn-hooks';
|
|
6
4
|
|
|
5
|
+
import { Select,Radio } from '@/components/antd';
|
|
7
6
|
// @ts-ignore
|
|
8
|
-
import {
|
|
9
|
-
|
|
7
|
+
import { createDictionary,SetConfig } from './dictionary';
|
|
10
8
|
|
|
11
9
|
|
|
12
|
-
/**
|
|
13
|
-
* @typedef DictionaryItem
|
|
14
|
-
* 字典数据的结构
|
|
15
|
-
* @property {string} id - 数据唯一ID
|
|
16
|
-
* @property {string} name - 数据唯一id对应的别名
|
|
17
|
-
* @property {string} label - 展示给用户看的文字
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @typedef UseDictionaryResult
|
|
23
|
-
* @property {DictionaryItem[]} types - 字典数据列表
|
|
24
|
-
* @property {ReactDOM[]} selectOptions - 供Antd渲染\<Select\>的列表
|
|
25
|
-
* @property {ReactDOM[]} radioOptions - 供Antd渲染\<Radio\>的列表
|
|
26
|
-
* @property {function} getId - (labelOrName:string)=>string,搜索字典项中,label或name匹配labelOrName的项目,返回其id的值
|
|
27
|
-
* @property {function} getName - (id:string)=>string,搜索字典项中,id匹配id的项目,返回其name的值
|
|
28
|
-
* @property {function} getLabel - (id:string)=>string,搜索字典项中,id匹配id的项目,返回其label的值
|
|
29
|
-
* @property {function} reload - ()=>void,重新调用字典接口刷新字典列表
|
|
30
|
-
*
|
|
31
|
-
*/
|
|
32
10
|
|
|
33
|
-
|
|
34
|
-
* @callback UseDictionary
|
|
35
|
-
* @returns {UseDictionaryResult}
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @typedef Dictionary
|
|
41
|
-
* @property {DictionaryItem[]} list - 字典数据列表
|
|
42
|
-
* @property {(labelOrName:string)=>string|number} getId - (labelOrName:string)=>string,搜索字典项中,label或name匹配labelOrName的项目,返回其id的值
|
|
43
|
-
* @property {(idOrLabel:string|number)=>string} getName - (id:string)=>string,搜索字典项中,id匹配id的项目,返回其name的值
|
|
44
|
-
* @property {(idOrName:string|number)=>string} getLabel - (id:string)=>string,搜索字典项中,id匹配id的项目,返回其label的值
|
|
45
|
-
* @property {(text:string|number)=>DictionaryItem|null} getItem - 匹配text为id\name\label中任何一个的对象
|
|
46
|
-
* @property {JSX.Element[]} [selectOptions] - antd-select渲染成员
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// export const SelectOption=(props)=>{
|
|
53
|
-
// const {value}=props;
|
|
54
|
-
// const name = props['data-keyname'];
|
|
55
|
-
// const onClick=(e)=>{
|
|
56
|
-
// ShowToast(`点击option name=${name},value=${value},label=${props.children}`)
|
|
57
|
-
// if(props.onClick)props.onClick();
|
|
58
|
-
// }
|
|
59
|
-
// // @ts-ignore
|
|
60
|
-
// return <hgroup onClick={onClick} key={value} name={name} value={value}>{props.children}</hgroup>
|
|
61
|
-
// }
|
|
62
|
-
|
|
63
|
-
useDictionary.SetConfig({SelectOption:Select.Option,RadioOption:Radio})
|
|
11
|
+
const BeforeApi=()=>{
|
|
64
12
|
|
|
13
|
+
}
|
|
14
|
+
const AfterApi=()=>{
|
|
65
15
|
|
|
66
|
-
/**
|
|
67
|
-
*
|
|
68
|
-
* @param {DictionaryItem[]|[]} list
|
|
69
|
-
* @returns {Dictionary}
|
|
70
|
-
*/
|
|
71
|
-
const createDictionary=(list)=>{
|
|
72
|
-
const getId=(nameOrLabel)=>{
|
|
73
|
-
for(let i=0;i<list.length;i++){
|
|
74
|
-
if(list[i].label == nameOrLabel || list[i].name == nameOrLabel){
|
|
75
|
-
return list[i].id;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
const getLabel=(nameOrId)=>{
|
|
81
|
-
for(let i=0;i<list.length;i++){
|
|
82
|
-
if(list[i].id == nameOrId || list[i].name == nameOrId){
|
|
83
|
-
return list[i].label;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
const getName=(idOrLabel)=>{
|
|
89
|
-
for(let i=0;i<list.length;i++){
|
|
90
|
-
if(list[i].id == idOrLabel || list[i].label == idOrLabel){
|
|
91
|
-
return list[i].name;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
const getItem=(idOrNameOrLabel)=>{
|
|
97
|
-
for(let i=0;i<list.length;i++){
|
|
98
|
-
if(list[i].id == idOrNameOrLabel || list[i].label == idOrNameOrLabel || list[i].name== idOrNameOrLabel ){
|
|
99
|
-
return list[i];
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const selectOptions = list.map(item=>{
|
|
106
|
-
return <Select.Option value={item.id} >{item.label}</Select.Option>
|
|
107
|
-
})
|
|
108
|
-
return {
|
|
109
|
-
getId,getLabel,getName,getItem,list,selectOptions
|
|
110
|
-
}
|
|
111
16
|
}
|
|
112
17
|
|
|
18
|
+
SetConfig({
|
|
19
|
+
beforeApi:BeforeApi,
|
|
20
|
+
afterApi:AfterApi,
|
|
21
|
+
})
|
|
113
22
|
|
|
114
|
-
/**
|
|
115
|
-
* 用户枚举数据
|
|
116
|
-
* @type UseDictionary
|
|
117
|
-
*/
|
|
118
|
-
// export const useUserEnum=useDictionary.createDictionary({
|
|
119
|
-
// beforeApi: () => ({
|
|
120
|
-
// status: 1 // 筛选已启用的数据
|
|
121
|
-
// }),
|
|
122
|
-
// api: USER_ENUM,
|
|
123
|
-
// labelKey: 'name',
|
|
124
|
-
// afterApi: res => {
|
|
125
|
-
// let list=[];
|
|
126
|
-
// if(res?.code===0) {
|
|
127
|
-
// list=res?.data||[];
|
|
128
|
-
// }
|
|
129
|
-
// return list;
|
|
130
|
-
// }
|
|
131
|
-
// })
|
|
132
23
|
|
|
24
|
+
export const onRenderSelectItem=(item)=>{
|
|
25
|
+
return <Select.Option key={item.id} data={item}>{item.label}</Select.Option>
|
|
26
|
+
}
|
|
133
27
|
|
|
134
28
|
/**
|
|
135
29
|
* 消息已读状态的
|
|
@@ -141,18 +35,20 @@ export const DictMessageStatus=[
|
|
|
141
35
|
|
|
142
36
|
/**
|
|
143
37
|
* 消息已读状态
|
|
144
|
-
* @type UseDictionary
|
|
145
38
|
*/
|
|
146
|
-
export const useMessageStatus=
|
|
147
|
-
|
|
39
|
+
export const useMessageStatus= createDictionary({
|
|
40
|
+
types: DictMessageStatus,
|
|
41
|
+
onRender:onRenderSelectItem
|
|
148
42
|
});
|
|
149
43
|
|
|
150
44
|
|
|
151
45
|
/**
|
|
152
46
|
* 用户状态
|
|
153
47
|
*/
|
|
154
|
-
export const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
48
|
+
export const useState= createDictionary({
|
|
49
|
+
types:[
|
|
50
|
+
{label:'启用',id:'1',name:'open'},
|
|
51
|
+
{label:'禁用',id:'0',name:'disabled'},
|
|
52
|
+
{label:'离职',id:'2',name:'out'},
|
|
53
|
+
]
|
|
54
|
+
});
|
|
@@ -6,6 +6,7 @@ import React,{ useRef, useState} from 'react';
|
|
|
6
6
|
import { matchPath } from 'react-router-dom';
|
|
7
7
|
|
|
8
8
|
import {CONSOLE_LOG} from '@/utils';
|
|
9
|
+
import { AUTH_ROUTE_DEBUG_OPEN } from '@/config';
|
|
9
10
|
|
|
10
11
|
const MODULE_NAME='useRouteMenu';
|
|
11
12
|
|
|
@@ -61,11 +62,11 @@ const MODULE_NAME='useRouteMenu';
|
|
|
61
62
|
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
const useRouteMenu=()=>{
|
|
65
|
+
const useRouteMenu=(props)=>{
|
|
65
66
|
/**
|
|
66
67
|
* @type [RouteMenuItem[], React.Dispatch<React.SetStateAction<RouteMenuItem[]>>]
|
|
67
68
|
*/
|
|
68
|
-
const [source,setSource]= useState([]);
|
|
69
|
+
const [source,setSource]= useState(props?.source||[]);
|
|
69
70
|
|
|
70
71
|
/**
|
|
71
72
|
* @type React.MutableRefObject<number>
|
|
@@ -134,6 +135,10 @@ const useRouteMenu=()=>{
|
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
}
|
|
138
|
+
|
|
139
|
+
if(AUTH_ROUTE_DEBUG_OPEN){
|
|
140
|
+
auth=true;
|
|
141
|
+
}
|
|
137
142
|
// 隐藏的菜单
|
|
138
143
|
if(menu.hideMenu){
|
|
139
144
|
auth=false;
|
|
@@ -172,6 +177,23 @@ const useRouteMenu=()=>{
|
|
|
172
177
|
return list
|
|
173
178
|
}
|
|
174
179
|
|
|
180
|
+
const getMatchMenu=(pathname,menu=source)=>{
|
|
181
|
+
for(let i=0;i<menu.length;i++){
|
|
182
|
+
const _menu = menu[i];
|
|
183
|
+
if( matchPath(_menu.routeTemplate||_menu.url, pathname) ){
|
|
184
|
+
return _menu;
|
|
185
|
+
}
|
|
186
|
+
if(_menu.children){
|
|
187
|
+
let req = getMatchMenu(pathname,_menu.children);
|
|
188
|
+
if(req){
|
|
189
|
+
return req;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
|
|
175
197
|
/**
|
|
176
198
|
* 计算pathname路由路径下的菜单路径
|
|
177
199
|
* @param {string} pathname - 需要匹配的路由路径
|
|
@@ -234,7 +256,7 @@ const useRouteMenu=()=>{
|
|
|
234
256
|
}
|
|
235
257
|
|
|
236
258
|
|
|
237
|
-
return {setSourceMap,getOpenMenus,getMenu,source,findMenuData,setMenuConfig}
|
|
259
|
+
return {setSourceMap,getOpenMenus,getMenu,source,findMenuData,setMenuConfig,getMatchMenu}
|
|
238
260
|
}
|
|
239
261
|
|
|
240
262
|
export default useRouteMenu;
|