@cfmm/umi-plugins-ui-v2 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/CrudTable.tpl +3 -1
- package/dist/cjs/components/MySelect.tpl +14 -5
- package/dist/cjs/components/PermissionSelect.tpl +1 -1
- package/dist/cjs/hooks/useRouteAuth.tpl +57 -73
- package/dist/cjs/locales/enUS/pages.js +1 -1
- package/dist/cjs/locales/zhCN/pages.js +1 -1
- package/dist/esm/components/CrudTable.tpl +3 -1
- package/dist/esm/components/MySelect.tpl +14 -5
- package/dist/esm/components/PermissionSelect.tpl +1 -1
- package/dist/esm/hooks/useRouteAuth.tpl +57 -73
- package/dist/esm/locales/enUS/pages.js +1 -1
- package/dist/esm/locales/zhCN/pages.js +1 -1
- package/package.json +1 -1
|
@@ -1093,8 +1093,9 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
1093
1093
|
[rowKey]: editRow?.[rowKey],
|
|
1094
1094
|
});
|
|
1095
1095
|
if (success) {
|
|
1096
|
-
actionRef.current?.reload();
|
|
1097
1096
|
setEditRow(null);
|
|
1097
|
+
actionRef.current?.reload();
|
|
1098
|
+
updateFormRef.current?.resetFields();
|
|
1098
1099
|
}
|
|
1099
1100
|
return success;
|
|
1100
1101
|
})}
|
|
@@ -1134,6 +1135,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
1134
1135
|
actionRef.current?.reload();
|
|
1135
1136
|
setEditRow(null);
|
|
1136
1137
|
setUpdateModalOpen(false);
|
|
1138
|
+
updateFormRef.current?.resetFields();
|
|
1137
1139
|
}
|
|
1138
1140
|
return success;
|
|
1139
1141
|
})}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// This file is generated by Umi automatically
|
|
3
|
-
// DO NOT CHANGE IT MANUALLY!
|
|
4
1
|
import { Empty, Select, Spin } from 'antd';
|
|
5
2
|
import React, {
|
|
6
3
|
ForwardedRef,
|
|
@@ -19,6 +16,18 @@ import { MySelectProps } from '../types';
|
|
|
19
16
|
|
|
20
17
|
const { Option } = Select;
|
|
21
18
|
|
|
19
|
+
/** 无对象、无键,或每个键的值均为 undefined / null / 空串(含纯空白)时视为“无搜索条件” */
|
|
20
|
+
function isSearchObjectAllEmpty(obj?: { [key: string]: string | undefined }): boolean {
|
|
21
|
+
if (!obj) return true;
|
|
22
|
+
const keys = Object.keys(obj);
|
|
23
|
+
if (keys.length === 0) return true;
|
|
24
|
+
return keys.every((key) => {
|
|
25
|
+
const v = obj[key];
|
|
26
|
+
if (v === undefined || v === null) return true;
|
|
27
|
+
return String(v).trim() === '';
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
23
32
|
const {
|
|
24
33
|
readonly,
|
|
@@ -105,7 +114,7 @@ const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
|
105
114
|
setListData([]);
|
|
106
115
|
let params = showSearch ? { ...searchValue, ...otherSearchValue } : otherSearchValue;
|
|
107
116
|
// 如果显示全部,则不分页
|
|
108
|
-
params = showAllList ? params : { pageIndex: 1, pageSize
|
|
117
|
+
params = showAllList ? params : { pageIndex: 1, pageSize, ...params };
|
|
109
118
|
const response = await request(params);
|
|
110
119
|
if (response.rows && response.rows.length > 0) {
|
|
111
120
|
// 如果有搜索值,则不添加回显值
|
|
@@ -124,7 +133,7 @@ const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
|
124
133
|
};
|
|
125
134
|
|
|
126
135
|
useEffect(() => {
|
|
127
|
-
if (Array.isArray(localListData) &&
|
|
136
|
+
if (Array.isArray(localListData) && isSearchObjectAllEmpty(searchValue)) {
|
|
128
137
|
setListData(localListData);
|
|
129
138
|
return;
|
|
130
139
|
}
|
|
@@ -15,96 +15,80 @@ export const useRouteAuth = (currentUser?: CurrentUser) => {
|
|
|
15
15
|
const params = useParams();
|
|
16
16
|
const { pathname } = useLocation();
|
|
17
17
|
|
|
18
|
-
//
|
|
19
|
-
const validMenus = useMemo(() => {
|
|
20
|
-
return currentUser?.menus?.filter((item: any) => item.status === 'Y') || [];
|
|
21
|
-
}, [currentUser?.menus]);
|
|
22
|
-
|
|
23
|
-
// 缓存当前路由路径(去除参数)
|
|
18
|
+
// 当前路由路径(去除动态参数片段)
|
|
24
19
|
const currentRoutePath = useMemo(() => {
|
|
25
20
|
if (!pathname) return '';
|
|
21
|
+
const normalized = pathname.endsWith('/') ? pathname.slice(0, -1) : pathname;
|
|
26
22
|
|
|
27
|
-
//
|
|
28
|
-
|
|
23
|
+
// 过滤掉通配符 '*':React Router v6 的 catch-all 路由会把剩余路径存入 params['*'],
|
|
24
|
+
// 它不对应独立的 URL 段,计入 paramCount 会导致错误切割(如 /aaa → '')
|
|
25
|
+
const segmentParamCount = Object.keys(params || {}).filter((k) => k !== '*').length;
|
|
26
|
+
if (segmentParamCount === 0) return normalized;
|
|
29
27
|
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
return
|
|
28
|
+
const parts = normalized.split('/');
|
|
29
|
+
const sliceEnd = parts.length - segmentParamCount;
|
|
30
|
+
// 安全兜底:切割结果不能比根路径更短
|
|
31
|
+
return sliceEnd > 0 ? parts.slice(0, sliceEnd).join('/') : normalized;
|
|
34
32
|
}, [pathname, params]);
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
/**
|
|
35
|
+
* 后端按权限下发菜单,返回的即为当前用户有权访问的全部菜单(item.status === '1' || item.status === 'Y')。
|
|
36
|
+
* 无需再区分「存在性」与「权限」两份列表。
|
|
37
|
+
*/
|
|
38
|
+
const validMenus = useMemo(
|
|
39
|
+
() => currentUser?.menus?.filter((item: any) => item.status === '1' || item.status === 'Y') ?? [],
|
|
40
|
+
[currentUser?.menus],
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 路由是否在当前用户的菜单中存在。
|
|
45
|
+
* 后端已按权限过滤,此处同时表达「存在」与「有权访问」两层含义。
|
|
46
|
+
*/
|
|
37
47
|
const routeExists = useMemo(() => {
|
|
38
|
-
|
|
39
|
-
if (!currentRoutePath) return true;
|
|
40
|
-
|
|
41
|
-
// 白名单路由始终存在
|
|
42
|
-
if (whiteListRoutes.includes(currentRoutePath)) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return currentUser?.menus?.some((menu) => menu.path === currentRoutePath);
|
|
47
|
-
}, [currentRoutePath]);
|
|
48
|
-
|
|
49
|
-
// 检查当前路由是否有权限
|
|
50
|
-
const hasCurrentRouteAuth = useMemo(() => {
|
|
51
|
-
// 如果路由不存在,返回 true,让它走到404处理
|
|
52
|
-
if (!routeExists) {
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 如果没有有效菜单或路径为空,返回 true跳转到无任何权限页面
|
|
57
|
-
if (!validMenus.length || !currentRoutePath) {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 白名单路由,无需权限检查
|
|
62
|
-
if (whiteListRoutes.includes(currentRoutePath)) {
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// 检查用户是否有当前路由权限
|
|
48
|
+
if (!currentRoutePath || whiteListRoutes.includes(currentRoutePath)) return true;
|
|
67
49
|
return validMenus.some((menu) => menu.path === currentRoutePath);
|
|
68
|
-
}, [
|
|
69
|
-
|
|
70
|
-
|
|
50
|
+
}, [currentRoutePath, validMenus]);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 与 routeExists 保持一致:路由存在即有权限。
|
|
54
|
+
* 保留此字段供 getChildren 等调用方兼容,不单独计算。
|
|
55
|
+
*/
|
|
56
|
+
const hasCurrentRouteAuth = routeExists;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 检查用户状态,返回应重定向的错误页路径;null 表示状态正常无需重定向。
|
|
60
|
+
*
|
|
61
|
+
* 优先级:
|
|
62
|
+
* 401(未登录)> 400(已禁用)> 404(路由不在菜单中)> 401(无系统权限码)
|
|
63
|
+
*
|
|
64
|
+
* 后端已按权限下发菜单,路由不在菜单中即无权限,统一用 404 表达,无需单独的 403。
|
|
65
|
+
*/
|
|
71
66
|
const getUserStatusRedirect = useMemo<UserStatusRedirect | null>(() => {
|
|
72
|
-
//
|
|
73
|
-
if (!
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// 系统没有用户 -> 401
|
|
78
|
-
if (!currentUser || Object.keys(currentUser).length === 0) {
|
|
79
|
-
return '/401';
|
|
80
|
-
}
|
|
67
|
+
// 1. 用户未登录(无 userId)→ 401
|
|
68
|
+
if (!currentUser?.userId) return '/401';
|
|
69
|
+
|
|
70
|
+
// 2. 用户账号被禁用 → 400
|
|
71
|
+
if (currentUser.status?.toUpperCase() === 'N') return '/400';
|
|
81
72
|
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
73
|
+
// 3. 路由不在用户菜单中(后端未下发 = 无权限)→ 404
|
|
74
|
+
// 后端已按权限过滤,不存在即无权访问,无需额外判 403
|
|
75
|
+
if (!routeExists) return '/404';
|
|
86
76
|
|
|
87
|
-
//
|
|
88
|
-
if (!currentUser.permissions
|
|
89
|
-
return '/401';
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// 没有当前页面权限 -> 403
|
|
93
|
-
if (!hasCurrentRouteAuth) {
|
|
94
|
-
return '/403';
|
|
95
|
-
}
|
|
77
|
+
// 4. 用户无任何系统权限码 → 401
|
|
78
|
+
if (!currentUser.permissions?.length) return '/401';
|
|
96
79
|
|
|
97
|
-
return null;
|
|
98
|
-
}, [currentUser,
|
|
80
|
+
return null;
|
|
81
|
+
}, [currentUser, routeExists]);
|
|
99
82
|
|
|
100
|
-
|
|
83
|
+
/** 导航到指定异常页(避免重复跳转到当前所在页) */
|
|
101
84
|
const redirectToPage = useMemoizedFn((path: UserStatusRedirect) => {
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
// path 已含前缀 '/'(如 '/403'),直接 push,避免产生 '//403'
|
|
86
|
+
if (currentRoutePath !== path) {
|
|
87
|
+
history.push(path);
|
|
104
88
|
}
|
|
105
89
|
});
|
|
106
90
|
|
|
107
|
-
|
|
91
|
+
/** 检查指定路径是否在当前用户有效权限内 */
|
|
108
92
|
const checkPathAuth = useMemoizedFn((path: string) => {
|
|
109
93
|
return validMenus.some((menu: any) => menu.path === path);
|
|
110
94
|
});
|
|
@@ -8,7 +8,7 @@ var _default = exports.default = {
|
|
|
8
8
|
"cfmmUI.common.userDisable.title": "User Disable",
|
|
9
9
|
"cfmmUI.common.userDisable.Message": "User Has Been Disabled, Please Contact Your Administrator",
|
|
10
10
|
"cfmmUI.common.userNoPermission.title": "User No Permission",
|
|
11
|
-
"cfmmUI.common.userNoPermission.Message": "User Has No Permission, Please Contact Your Administrator",
|
|
11
|
+
"cfmmUI.common.userNoPermission.Message": "User Has No Any Permission, Please Contact Your Administrator",
|
|
12
12
|
"cfmmUI.common.UserNoPagePermission.title": "User Has No Page Permission",
|
|
13
13
|
"cfmmUI.common.UserNoPagePermission.Message": "User Has No Page Permission, Please Click The Left Menu To Switch Other Pages, Still To Contact Your Administrator",
|
|
14
14
|
"cfmmUI.common.useOtherUserLogin.title": "Use Other User Login"
|
|
@@ -8,7 +8,7 @@ var _default = exports.default = {
|
|
|
8
8
|
"cfmmUI.common.userDisable.title": "用户禁用",
|
|
9
9
|
"cfmmUI.common.userDisable.Message": "用户已被禁用,请与管理员联系",
|
|
10
10
|
"cfmmUI.common.userNoPermission.title": "用户无权限",
|
|
11
|
-
"cfmmUI.common.userNoPermission.Message": "
|
|
11
|
+
"cfmmUI.common.userNoPermission.Message": "用户无任何权限,请与管理员联系",
|
|
12
12
|
"cfmmUI.common.UserNoPagePermission.title": "用户无该页面权限",
|
|
13
13
|
"cfmmUI.common.UserNoPagePermission.Message": "用户无该页面权限,请点击左侧菜单切换其他页面,仍要访问与管理员联系",
|
|
14
14
|
"cfmmUI.common.useOtherUserLogin.title": "使用其他用户登陆"
|
|
@@ -1093,8 +1093,9 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
1093
1093
|
[rowKey]: editRow?.[rowKey],
|
|
1094
1094
|
});
|
|
1095
1095
|
if (success) {
|
|
1096
|
-
actionRef.current?.reload();
|
|
1097
1096
|
setEditRow(null);
|
|
1097
|
+
actionRef.current?.reload();
|
|
1098
|
+
updateFormRef.current?.resetFields();
|
|
1098
1099
|
}
|
|
1099
1100
|
return success;
|
|
1100
1101
|
})}
|
|
@@ -1134,6 +1135,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
1134
1135
|
actionRef.current?.reload();
|
|
1135
1136
|
setEditRow(null);
|
|
1136
1137
|
setUpdateModalOpen(false);
|
|
1138
|
+
updateFormRef.current?.resetFields();
|
|
1137
1139
|
}
|
|
1138
1140
|
return success;
|
|
1139
1141
|
})}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// This file is generated by Umi automatically
|
|
3
|
-
// DO NOT CHANGE IT MANUALLY!
|
|
4
1
|
import { Empty, Select, Spin } from 'antd';
|
|
5
2
|
import React, {
|
|
6
3
|
ForwardedRef,
|
|
@@ -19,6 +16,18 @@ import { MySelectProps } from '../types';
|
|
|
19
16
|
|
|
20
17
|
const { Option } = Select;
|
|
21
18
|
|
|
19
|
+
/** 无对象、无键,或每个键的值均为 undefined / null / 空串(含纯空白)时视为“无搜索条件” */
|
|
20
|
+
function isSearchObjectAllEmpty(obj?: { [key: string]: string | undefined }): boolean {
|
|
21
|
+
if (!obj) return true;
|
|
22
|
+
const keys = Object.keys(obj);
|
|
23
|
+
if (keys.length === 0) return true;
|
|
24
|
+
return keys.every((key) => {
|
|
25
|
+
const v = obj[key];
|
|
26
|
+
if (v === undefined || v === null) return true;
|
|
27
|
+
return String(v).trim() === '';
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
23
32
|
const {
|
|
24
33
|
readonly,
|
|
@@ -105,7 +114,7 @@ const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
|
105
114
|
setListData([]);
|
|
106
115
|
let params = showSearch ? { ...searchValue, ...otherSearchValue } : otherSearchValue;
|
|
107
116
|
// 如果显示全部,则不分页
|
|
108
|
-
params = showAllList ? params : { pageIndex: 1, pageSize
|
|
117
|
+
params = showAllList ? params : { pageIndex: 1, pageSize, ...params };
|
|
109
118
|
const response = await request(params);
|
|
110
119
|
if (response.rows && response.rows.length > 0) {
|
|
111
120
|
// 如果有搜索值,则不添加回显值
|
|
@@ -124,7 +133,7 @@ const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
|
124
133
|
};
|
|
125
134
|
|
|
126
135
|
useEffect(() => {
|
|
127
|
-
if (Array.isArray(localListData) &&
|
|
136
|
+
if (Array.isArray(localListData) && isSearchObjectAllEmpty(searchValue)) {
|
|
128
137
|
setListData(localListData);
|
|
129
138
|
return;
|
|
130
139
|
}
|
|
@@ -15,96 +15,80 @@ export const useRouteAuth = (currentUser?: CurrentUser) => {
|
|
|
15
15
|
const params = useParams();
|
|
16
16
|
const { pathname } = useLocation();
|
|
17
17
|
|
|
18
|
-
//
|
|
19
|
-
const validMenus = useMemo(() => {
|
|
20
|
-
return currentUser?.menus?.filter((item: any) => item.status === 'Y') || [];
|
|
21
|
-
}, [currentUser?.menus]);
|
|
22
|
-
|
|
23
|
-
// 缓存当前路由路径(去除参数)
|
|
18
|
+
// 当前路由路径(去除动态参数片段)
|
|
24
19
|
const currentRoutePath = useMemo(() => {
|
|
25
20
|
if (!pathname) return '';
|
|
21
|
+
const normalized = pathname.endsWith('/') ? pathname.slice(0, -1) : pathname;
|
|
26
22
|
|
|
27
|
-
//
|
|
28
|
-
|
|
23
|
+
// 过滤掉通配符 '*':React Router v6 的 catch-all 路由会把剩余路径存入 params['*'],
|
|
24
|
+
// 它不对应独立的 URL 段,计入 paramCount 会导致错误切割(如 /aaa → '')
|
|
25
|
+
const segmentParamCount = Object.keys(params || {}).filter((k) => k !== '*').length;
|
|
26
|
+
if (segmentParamCount === 0) return normalized;
|
|
29
27
|
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
return
|
|
28
|
+
const parts = normalized.split('/');
|
|
29
|
+
const sliceEnd = parts.length - segmentParamCount;
|
|
30
|
+
// 安全兜底:切割结果不能比根路径更短
|
|
31
|
+
return sliceEnd > 0 ? parts.slice(0, sliceEnd).join('/') : normalized;
|
|
34
32
|
}, [pathname, params]);
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
/**
|
|
35
|
+
* 后端按权限下发菜单,返回的即为当前用户有权访问的全部菜单(item.status === '1' || item.status === 'Y')。
|
|
36
|
+
* 无需再区分「存在性」与「权限」两份列表。
|
|
37
|
+
*/
|
|
38
|
+
const validMenus = useMemo(
|
|
39
|
+
() => currentUser?.menus?.filter((item: any) => item.status === '1' || item.status === 'Y') ?? [],
|
|
40
|
+
[currentUser?.menus],
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 路由是否在当前用户的菜单中存在。
|
|
45
|
+
* 后端已按权限过滤,此处同时表达「存在」与「有权访问」两层含义。
|
|
46
|
+
*/
|
|
37
47
|
const routeExists = useMemo(() => {
|
|
38
|
-
|
|
39
|
-
if (!currentRoutePath) return true;
|
|
40
|
-
|
|
41
|
-
// 白名单路由始终存在
|
|
42
|
-
if (whiteListRoutes.includes(currentRoutePath)) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return currentUser?.menus?.some((menu) => menu.path === currentRoutePath);
|
|
47
|
-
}, [currentRoutePath]);
|
|
48
|
-
|
|
49
|
-
// 检查当前路由是否有权限
|
|
50
|
-
const hasCurrentRouteAuth = useMemo(() => {
|
|
51
|
-
// 如果路由不存在,返回 true,让它走到404处理
|
|
52
|
-
if (!routeExists) {
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 如果没有有效菜单或路径为空,返回 true跳转到无任何权限页面
|
|
57
|
-
if (!validMenus.length || !currentRoutePath) {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 白名单路由,无需权限检查
|
|
62
|
-
if (whiteListRoutes.includes(currentRoutePath)) {
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// 检查用户是否有当前路由权限
|
|
48
|
+
if (!currentRoutePath || whiteListRoutes.includes(currentRoutePath)) return true;
|
|
67
49
|
return validMenus.some((menu) => menu.path === currentRoutePath);
|
|
68
|
-
}, [
|
|
69
|
-
|
|
70
|
-
|
|
50
|
+
}, [currentRoutePath, validMenus]);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 与 routeExists 保持一致:路由存在即有权限。
|
|
54
|
+
* 保留此字段供 getChildren 等调用方兼容,不单独计算。
|
|
55
|
+
*/
|
|
56
|
+
const hasCurrentRouteAuth = routeExists;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 检查用户状态,返回应重定向的错误页路径;null 表示状态正常无需重定向。
|
|
60
|
+
*
|
|
61
|
+
* 优先级:
|
|
62
|
+
* 401(未登录)> 400(已禁用)> 404(路由不在菜单中)> 401(无系统权限码)
|
|
63
|
+
*
|
|
64
|
+
* 后端已按权限下发菜单,路由不在菜单中即无权限,统一用 404 表达,无需单独的 403。
|
|
65
|
+
*/
|
|
71
66
|
const getUserStatusRedirect = useMemo<UserStatusRedirect | null>(() => {
|
|
72
|
-
//
|
|
73
|
-
if (!
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// 系统没有用户 -> 401
|
|
78
|
-
if (!currentUser || Object.keys(currentUser).length === 0) {
|
|
79
|
-
return '/401';
|
|
80
|
-
}
|
|
67
|
+
// 1. 用户未登录(无 userId)→ 401
|
|
68
|
+
if (!currentUser?.userId) return '/401';
|
|
69
|
+
|
|
70
|
+
// 2. 用户账号被禁用 → 400
|
|
71
|
+
if (currentUser.status?.toUpperCase() === 'N') return '/400';
|
|
81
72
|
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
73
|
+
// 3. 路由不在用户菜单中(后端未下发 = 无权限)→ 404
|
|
74
|
+
// 后端已按权限过滤,不存在即无权访问,无需额外判 403
|
|
75
|
+
if (!routeExists) return '/404';
|
|
86
76
|
|
|
87
|
-
//
|
|
88
|
-
if (!currentUser.permissions
|
|
89
|
-
return '/401';
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// 没有当前页面权限 -> 403
|
|
93
|
-
if (!hasCurrentRouteAuth) {
|
|
94
|
-
return '/403';
|
|
95
|
-
}
|
|
77
|
+
// 4. 用户无任何系统权限码 → 401
|
|
78
|
+
if (!currentUser.permissions?.length) return '/401';
|
|
96
79
|
|
|
97
|
-
return null;
|
|
98
|
-
}, [currentUser,
|
|
80
|
+
return null;
|
|
81
|
+
}, [currentUser, routeExists]);
|
|
99
82
|
|
|
100
|
-
|
|
83
|
+
/** 导航到指定异常页(避免重复跳转到当前所在页) */
|
|
101
84
|
const redirectToPage = useMemoizedFn((path: UserStatusRedirect) => {
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
// path 已含前缀 '/'(如 '/403'),直接 push,避免产生 '//403'
|
|
86
|
+
if (currentRoutePath !== path) {
|
|
87
|
+
history.push(path);
|
|
104
88
|
}
|
|
105
89
|
});
|
|
106
90
|
|
|
107
|
-
|
|
91
|
+
/** 检查指定路径是否在当前用户有效权限内 */
|
|
108
92
|
const checkPathAuth = useMemoizedFn((path: string) => {
|
|
109
93
|
return validMenus.some((menu: any) => menu.path === path);
|
|
110
94
|
});
|
|
@@ -2,7 +2,7 @@ export default {
|
|
|
2
2
|
"cfmmUI.common.userDisable.title": "User Disable",
|
|
3
3
|
"cfmmUI.common.userDisable.Message": "User Has Been Disabled, Please Contact Your Administrator",
|
|
4
4
|
"cfmmUI.common.userNoPermission.title": "User No Permission",
|
|
5
|
-
"cfmmUI.common.userNoPermission.Message": "User Has No Permission, Please Contact Your Administrator",
|
|
5
|
+
"cfmmUI.common.userNoPermission.Message": "User Has No Any Permission, Please Contact Your Administrator",
|
|
6
6
|
"cfmmUI.common.UserNoPagePermission.title": "User Has No Page Permission",
|
|
7
7
|
"cfmmUI.common.UserNoPagePermission.Message": "User Has No Page Permission, Please Click The Left Menu To Switch Other Pages, Still To Contact Your Administrator",
|
|
8
8
|
"cfmmUI.common.useOtherUserLogin.title": "Use Other User Login"
|
|
@@ -2,7 +2,7 @@ export default {
|
|
|
2
2
|
"cfmmUI.common.userDisable.title": "用户禁用",
|
|
3
3
|
"cfmmUI.common.userDisable.Message": "用户已被禁用,请与管理员联系",
|
|
4
4
|
"cfmmUI.common.userNoPermission.title": "用户无权限",
|
|
5
|
-
"cfmmUI.common.userNoPermission.Message": "
|
|
5
|
+
"cfmmUI.common.userNoPermission.Message": "用户无任何权限,请与管理员联系",
|
|
6
6
|
"cfmmUI.common.UserNoPagePermission.title": "用户无该页面权限",
|
|
7
7
|
"cfmmUI.common.UserNoPagePermission.Message": "用户无该页面权限,请点击左侧菜单切换其他页面,仍要访问与管理员联系",
|
|
8
8
|
"cfmmUI.common.useOtherUserLogin.title": "使用其他用户登陆"
|