xto-fronted 0.4.2 → 0.4.4
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/.env.development +5 -1
- package/.env.production +5 -1
- package/dist/composables/useApp.d.ts +7 -10
- package/dist/composables/useAuth.d.ts +0 -3
- package/dist/index-C6Nm0r9k.js +475 -0
- package/dist/index-DFXuyPge.js +1627 -0
- package/dist/index-Do1CBqg8.js +345 -0
- package/dist/index-Jb4VMHIS.js +142 -0
- package/dist/index-TrLCW5xL.js +372 -0
- package/dist/index.es.js +66 -60
- package/dist/index.umd.js +1 -1
- package/dist/router/dynamicRoutes.d.ts +18 -22
- package/dist/router/guards.d.ts +1 -0
- package/dist/stores/auth.d.ts +5 -19
- package/dist/stores/menu.d.ts +43 -74
- package/dist/stores/user.d.ts +63 -84
- package/dist/style.css +1 -1
- package/dist/utils/auth.d.ts +12 -3
- package/dist/utils/permission.d.ts +5 -4
- package/package.json +1 -1
- package/src/components/Layout/Header.vue +5 -5
- package/src/components/Layout/Sidebar.vue +18 -12
- package/src/composables/useApp.ts +1 -1
- package/src/composables/useAuth.ts +0 -28
- package/src/directives/permission.ts +6 -16
- package/src/router/dynamicRoutes.ts +31 -31
- package/src/router/guards.ts +6 -10
- package/src/router/index.ts +7 -9
- package/src/stores/auth.ts +4 -4
- package/src/stores/menu.ts +19 -50
- package/src/stores/user.ts +18 -40
- package/src/types/api.d.ts +24 -29
- package/src/utils/auth.ts +45 -7
- package/src/utils/permission.ts +10 -19
- package/src/utils/request.ts +4 -3
|
@@ -1,32 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 权限指令
|
|
3
3
|
* v-permission="['user:edit']" 或 v-permission="'user:edit'"
|
|
4
|
+
* 注意:tineco-ui 不支持 permissions 字段,此指令暂时只检查登录状态
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import type { Directive, DirectiveBinding } from 'vue'
|
|
7
8
|
import { useUserStore } from '@/stores/user'
|
|
8
9
|
|
|
9
10
|
const permission: Directive = {
|
|
10
|
-
mounted(el: HTMLElement,
|
|
11
|
+
mounted(el: HTMLElement, _binding: DirectiveBinding<string | string[]>) {
|
|
11
12
|
const userStore = useUserStore()
|
|
12
|
-
const { value } = binding
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const permissions = userStore.permissions
|
|
17
|
-
|
|
18
|
-
// 判断是否有权限
|
|
19
|
-
let hasPermission = false
|
|
20
|
-
if (Array.isArray(value)) {
|
|
21
|
-
hasPermission = value.some(p => permissions.includes(p) || permissions.includes('*'))
|
|
22
|
-
} else {
|
|
23
|
-
hasPermission = permissions.includes(value) || permissions.includes('*')
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// 没有权限则移除元素
|
|
27
|
-
if (!hasPermission) {
|
|
14
|
+
// 如果没有登录,移除元素
|
|
15
|
+
if (!userStore.isLoggedIn) {
|
|
28
16
|
el.parentNode?.removeChild(el)
|
|
29
17
|
}
|
|
18
|
+
|
|
19
|
+
// 注意:tineco-ui 不支持 permissions 字段,此指令暂时不做权限判断
|
|
30
20
|
}
|
|
31
21
|
}
|
|
32
22
|
|
|
@@ -111,52 +111,52 @@ export const defaultDynamicRoutes: RouteRecordRaw[] = [
|
|
|
111
111
|
}
|
|
112
112
|
]
|
|
113
113
|
|
|
114
|
-
// Mock
|
|
114
|
+
// Mock 菜单数据(参考 tineco-ui 格式)
|
|
115
115
|
export const mockMenuData = [
|
|
116
116
|
{
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
component: 'dashboard/index',
|
|
117
|
+
menuCode: 'dashboard',
|
|
118
|
+
menuName: '仪表盘',
|
|
119
|
+
menuUrl: '/dashboard',
|
|
121
120
|
icon: 'dashboard',
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
closable: true,
|
|
122
|
+
isDefault: true,
|
|
123
|
+
isOut: false
|
|
125
124
|
},
|
|
126
125
|
{
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
redirect: '/system/user',
|
|
126
|
+
menuCode: 'system',
|
|
127
|
+
menuName: '系统管理',
|
|
128
|
+
menuUrl: '/system',
|
|
131
129
|
icon: 'setting',
|
|
132
|
-
|
|
130
|
+
closable: false,
|
|
131
|
+
isDefault: false,
|
|
132
|
+
isOut: false,
|
|
133
133
|
children: [
|
|
134
134
|
{
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
component: 'system/user/index',
|
|
135
|
+
menuCode: 'system_user',
|
|
136
|
+
menuName: '用户管理',
|
|
137
|
+
menuUrl: '/system/user',
|
|
139
138
|
icon: 'user',
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
closable: true,
|
|
140
|
+
isDefault: false,
|
|
141
|
+
isOut: false
|
|
142
142
|
},
|
|
143
143
|
{
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
component: 'system/role/index',
|
|
144
|
+
menuCode: 'system_role',
|
|
145
|
+
menuName: '角色管理',
|
|
146
|
+
menuUrl: '/system/role',
|
|
148
147
|
icon: 'role',
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
closable: true,
|
|
149
|
+
isDefault: false,
|
|
150
|
+
isOut: false
|
|
151
151
|
},
|
|
152
152
|
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
component: 'system/menu/index',
|
|
153
|
+
menuCode: 'system_menu',
|
|
154
|
+
menuName: '菜单管理',
|
|
155
|
+
menuUrl: '/system/menu',
|
|
157
156
|
icon: 'menu',
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
closable: true,
|
|
158
|
+
isDefault: false,
|
|
159
|
+
isOut: false
|
|
160
160
|
}
|
|
161
161
|
]
|
|
162
162
|
}
|
package/src/router/guards.ts
CHANGED
|
@@ -20,6 +20,8 @@ interface RouterGuardOptions {
|
|
|
20
20
|
loginPath?: string
|
|
21
21
|
// 首页路径
|
|
22
22
|
homePath?: string
|
|
23
|
+
// 应用ID
|
|
24
|
+
appId?: string
|
|
23
25
|
// 获取用户信息的回调(可选,默认调用 API)
|
|
24
26
|
fetchUserInfo?: () => Promise<any>
|
|
25
27
|
// 获取菜单的回调(可选,默认调用 API)
|
|
@@ -39,9 +41,6 @@ export function setupRouterGuards(router: Router, options: RouterGuardOptions =
|
|
|
39
41
|
const homePath = options.homePath || '/'
|
|
40
42
|
|
|
41
43
|
router.beforeEach(async (to, _from, next) => {
|
|
42
|
-
// 启动进度条(可选)
|
|
43
|
-
// NProgress.start()
|
|
44
|
-
|
|
45
44
|
const appStore = useAppStore()
|
|
46
45
|
const userStore = useUserStore()
|
|
47
46
|
const menuStore = useMenuStore()
|
|
@@ -57,7 +56,6 @@ export function setupRouterGuards(router: Router, options: RouterGuardOptions =
|
|
|
57
56
|
if (to.path === loginPath) {
|
|
58
57
|
// 已登录访问登录页,跳转到首页
|
|
59
58
|
next({ path: homePath })
|
|
60
|
-
// NProgress.done()
|
|
61
59
|
} else {
|
|
62
60
|
// 检查是否已获取用户信息
|
|
63
61
|
if (userStore.isLoggedIn) {
|
|
@@ -84,7 +82,7 @@ export function setupRouterGuards(router: Router, options: RouterGuardOptions =
|
|
|
84
82
|
const menuList = await options.fetchMenu()
|
|
85
83
|
menuStore.setMenuList(menuList)
|
|
86
84
|
} else {
|
|
87
|
-
const menuList = await getMenuTree()
|
|
85
|
+
const menuList = await getMenuTree(options.appId)
|
|
88
86
|
menuStore.setMenuList(menuList)
|
|
89
87
|
}
|
|
90
88
|
|
|
@@ -107,9 +105,9 @@ export function setupRouterGuards(router: Router, options: RouterGuardOptions =
|
|
|
107
105
|
menuStore.clearMenu()
|
|
108
106
|
// 清除 token
|
|
109
107
|
localStorage.removeItem('token')
|
|
110
|
-
localStorage.removeItem('
|
|
108
|
+
localStorage.removeItem('token_type')
|
|
109
|
+
localStorage.removeItem('refresh_token')
|
|
111
110
|
next({ path: loginPath, query: { redirect: to.fullPath } })
|
|
112
|
-
// NProgress.done()
|
|
113
111
|
}
|
|
114
112
|
}
|
|
115
113
|
}
|
|
@@ -121,13 +119,11 @@ export function setupRouterGuards(router: Router, options: RouterGuardOptions =
|
|
|
121
119
|
} else {
|
|
122
120
|
// 不在白名单中,跳转到登录页
|
|
123
121
|
next({ path: loginPath, query: { redirect: to.fullPath } })
|
|
124
|
-
// NProgress.done()
|
|
125
122
|
}
|
|
126
123
|
}
|
|
127
124
|
})
|
|
128
125
|
|
|
129
126
|
router.afterEach(() => {
|
|
130
|
-
//
|
|
131
|
-
// NProgress.done()
|
|
127
|
+
// 可以在这里添加进度条结束等
|
|
132
128
|
})
|
|
133
129
|
}
|
package/src/router/index.ts
CHANGED
|
@@ -37,16 +37,14 @@ router.beforeEach(async (to, _from, next) => {
|
|
|
37
37
|
const userStore = useUserStore()
|
|
38
38
|
if (!userStore.isLoggedIn) {
|
|
39
39
|
userStore.setUserInfo({
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
appId: import.meta.env.VITE_APP_ID,
|
|
41
|
+
userId: '1',
|
|
42
|
+
userName: '管理员',
|
|
43
|
+
departmentName: '技术部',
|
|
44
44
|
email: 'admin@example.com',
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
permissions: ['*'],
|
|
49
|
-
createTime: new Date().toISOString()
|
|
45
|
+
mobilePhone: '13800138000',
|
|
46
|
+
positionName: '管理员',
|
|
47
|
+
avatar: ''
|
|
50
48
|
})
|
|
51
49
|
|
|
52
50
|
// 设置菜单
|
package/src/stores/auth.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { defineStore } from 'pinia'
|
|
6
6
|
import { ref, computed } from 'vue'
|
|
7
|
-
import { getToken, clearToken, setTokenInfo, hasToken } from '@/utils/auth'
|
|
7
|
+
import { getToken, clearToken, setTokenInfo, hasToken, type TokenInfo } from '@/utils/auth'
|
|
8
8
|
|
|
9
9
|
export const useAuthStore = defineStore('auth', () => {
|
|
10
10
|
// 状态
|
|
@@ -17,9 +17,9 @@ export const useAuthStore = defineStore('auth', () => {
|
|
|
17
17
|
const clientId = ref<string>('')
|
|
18
18
|
const loginPath = ref<string>('/login')
|
|
19
19
|
|
|
20
|
-
// 设置 token
|
|
21
|
-
const login = (tokenInfo:
|
|
22
|
-
token.value = tokenInfo.
|
|
20
|
+
// 设置 token(参考 tineco-ui)
|
|
21
|
+
const login = (tokenInfo: TokenInfo) => {
|
|
22
|
+
token.value = tokenInfo.access_token
|
|
23
23
|
setTokenInfo(tokenInfo)
|
|
24
24
|
}
|
|
25
25
|
|
package/src/stores/menu.ts
CHANGED
|
@@ -4,77 +4,46 @@
|
|
|
4
4
|
|
|
5
5
|
import { defineStore } from 'pinia'
|
|
6
6
|
import { ref, computed } from 'vue'
|
|
7
|
-
import type { AppRoute } from '@/types/router'
|
|
8
7
|
import type { MenuItem } from '@/types/api'
|
|
9
8
|
import { local } from '@/utils/storage'
|
|
10
|
-
|
|
9
|
+
|
|
10
|
+
const MENU_LIST_KEY = 'menu_list'
|
|
11
|
+
|
|
12
|
+
// 首页菜单(参考 tineco-ui)
|
|
13
|
+
const indexMenu: MenuItem = {
|
|
14
|
+
menuCode: 'home',
|
|
15
|
+
menuName: '首页',
|
|
16
|
+
menuUrl: '/dashboard',
|
|
17
|
+
icon: 'home',
|
|
18
|
+
closable: false,
|
|
19
|
+
isDefault: false,
|
|
20
|
+
isOut: false
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
export const useMenuStore = defineStore('menu', () => {
|
|
13
24
|
// 状态
|
|
14
|
-
const menuList = ref<MenuItem[]>(local.get<MenuItem[]>(
|
|
25
|
+
const menuList = ref<MenuItem[]>(local.get<MenuItem[]>(MENU_LIST_KEY) || [])
|
|
15
26
|
|
|
16
27
|
// 计算属性
|
|
17
28
|
const hasMenu = computed(() => menuList.value.length > 0)
|
|
18
29
|
|
|
19
30
|
// 设置菜单
|
|
20
31
|
const setMenuList = (menus: MenuItem[]) => {
|
|
21
|
-
|
|
22
|
-
|
|
32
|
+
// 添加首页菜单到开头
|
|
33
|
+
menuList.value = [indexMenu, ...menus]
|
|
34
|
+
local.set(MENU_LIST_KEY, menuList.value)
|
|
23
35
|
}
|
|
24
36
|
|
|
25
37
|
// 清除菜单
|
|
26
38
|
const clearMenu = () => {
|
|
27
39
|
menuList.value = []
|
|
28
|
-
local.remove(
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 生成路由
|
|
32
|
-
const generateRoutes = (menus: MenuItem[]): AppRoute[] => {
|
|
33
|
-
return menus
|
|
34
|
-
.filter(menu => !menu.hidden)
|
|
35
|
-
.map(menu => {
|
|
36
|
-
const route: AppRoute = {
|
|
37
|
-
path: menu.path,
|
|
38
|
-
name: menu.name,
|
|
39
|
-
meta: {
|
|
40
|
-
title: menu.title,
|
|
41
|
-
icon: menu.icon,
|
|
42
|
-
keepAlive: menu.keepAlive,
|
|
43
|
-
hidden: menu.hidden
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (menu.redirect) {
|
|
48
|
-
route.redirect = menu.redirect
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (menu.component) {
|
|
52
|
-
// 动态导入组件
|
|
53
|
-
route.component = () => import(`@/views/${menu.component}.vue`)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (menu.children && menu.children.length > 0) {
|
|
57
|
-
route.children = generateRoutes(menu.children)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return route
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// 添加路由
|
|
65
|
-
const addRoutes = (menus: MenuItem[]) => {
|
|
66
|
-
const routes = generateRoutes(menus)
|
|
67
|
-
routes.forEach(route => {
|
|
68
|
-
router.addRoute('Layout', route as any)
|
|
69
|
-
})
|
|
40
|
+
local.remove(MENU_LIST_KEY)
|
|
70
41
|
}
|
|
71
42
|
|
|
72
43
|
return {
|
|
73
44
|
menuList,
|
|
74
45
|
hasMenu,
|
|
75
46
|
setMenuList,
|
|
76
|
-
clearMenu
|
|
77
|
-
generateRoutes,
|
|
78
|
-
addRoutes
|
|
47
|
+
clearMenu
|
|
79
48
|
}
|
|
80
49
|
})
|
package/src/stores/user.ts
CHANGED
|
@@ -7,67 +7,45 @@ import { ref, computed } from 'vue'
|
|
|
7
7
|
import type { UserInfo } from '@/types/api'
|
|
8
8
|
import { local } from '@/utils/storage'
|
|
9
9
|
|
|
10
|
+
const USER_INFO_KEY = 'user_info'
|
|
11
|
+
|
|
10
12
|
export const useUserStore = defineStore('user', () => {
|
|
11
13
|
// 状态
|
|
12
|
-
const userInfo = ref<UserInfo | null>(local.get<UserInfo>(
|
|
13
|
-
const roles = ref<string[]>(local.get<string[]>('roles') || [])
|
|
14
|
-
const permissions = ref<string[]>(local.get<string[]>('permissions') || [])
|
|
14
|
+
const userInfo = ref<UserInfo | null>(local.get<UserInfo>(USER_INFO_KEY))
|
|
15
15
|
|
|
16
16
|
// 计算属性
|
|
17
17
|
const isLoggedIn = computed(() => !!userInfo.value)
|
|
18
|
-
const
|
|
19
|
-
const
|
|
18
|
+
const userId = computed(() => userInfo.value?.userId || '')
|
|
19
|
+
const userName = computed(() => userInfo.value?.userName || '')
|
|
20
|
+
const departmentName = computed(() => userInfo.value?.departmentName || '')
|
|
21
|
+
const email = computed(() => userInfo.value?.email || '')
|
|
22
|
+
const mobilePhone = computed(() => userInfo.value?.mobilePhone || '')
|
|
23
|
+
const positionName = computed(() => userInfo.value?.positionName || '')
|
|
20
24
|
const avatar = computed(() => userInfo.value?.avatar || '')
|
|
21
|
-
const userId = computed(() => userInfo.value?.id)
|
|
22
25
|
|
|
23
26
|
// 设置用户信息
|
|
24
27
|
const setUserInfo = (info: UserInfo) => {
|
|
25
28
|
userInfo.value = info
|
|
26
|
-
|
|
27
|
-
permissions.value = info.permissions || []
|
|
28
|
-
local.set('userInfo', info)
|
|
29
|
-
local.set('roles', info.roles || [])
|
|
30
|
-
local.set('permissions', info.permissions || [])
|
|
29
|
+
local.set(USER_INFO_KEY, info)
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
// 清除用户信息
|
|
34
33
|
const clearUserInfo = () => {
|
|
35
34
|
userInfo.value = null
|
|
36
|
-
|
|
37
|
-
permissions.value = []
|
|
38
|
-
local.remove('userInfo')
|
|
39
|
-
local.remove('roles')
|
|
40
|
-
local.remove('permissions')
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 检查权限
|
|
44
|
-
const hasPermission = (permission: string | string[]): boolean => {
|
|
45
|
-
if (Array.isArray(permission)) {
|
|
46
|
-
return permission.some(p => permissions.value.includes(p))
|
|
47
|
-
}
|
|
48
|
-
return permissions.value.includes(permission)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 检查角色
|
|
52
|
-
const hasRole = (role: string | string[]): boolean => {
|
|
53
|
-
if (Array.isArray(role)) {
|
|
54
|
-
return role.some(r => roles.value.includes(r))
|
|
55
|
-
}
|
|
56
|
-
return roles.value.includes(role)
|
|
35
|
+
local.remove(USER_INFO_KEY)
|
|
57
36
|
}
|
|
58
37
|
|
|
59
38
|
return {
|
|
60
39
|
userInfo,
|
|
61
|
-
roles,
|
|
62
|
-
permissions,
|
|
63
40
|
isLoggedIn,
|
|
64
|
-
username,
|
|
65
|
-
nickname,
|
|
66
|
-
avatar,
|
|
67
41
|
userId,
|
|
42
|
+
userName,
|
|
43
|
+
departmentName,
|
|
44
|
+
email,
|
|
45
|
+
mobilePhone,
|
|
46
|
+
positionName,
|
|
47
|
+
avatar,
|
|
68
48
|
setUserInfo,
|
|
69
|
-
clearUserInfo
|
|
70
|
-
hasPermission,
|
|
71
|
-
hasRole
|
|
49
|
+
clearUserInfo
|
|
72
50
|
}
|
|
73
51
|
})
|
package/src/types/api.d.ts
CHANGED
|
@@ -24,22 +24,19 @@ export interface PageResponse<T> {
|
|
|
24
24
|
pageSize: number
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
//
|
|
27
|
+
// 用户信息(参考 tineco-ui)
|
|
28
28
|
export interface UserInfo {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
appId: string
|
|
30
|
+
userId: string
|
|
31
|
+
userName: string
|
|
32
|
+
departmentName?: string
|
|
33
33
|
email?: string
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
permissions: string[]
|
|
38
|
-
createTime?: string
|
|
39
|
-
updateTime?: string
|
|
34
|
+
mobilePhone?: string
|
|
35
|
+
positionName?: string
|
|
36
|
+
avatar?: string
|
|
40
37
|
}
|
|
41
38
|
|
|
42
|
-
//
|
|
39
|
+
// 登录请求参数(参考 tineco-ui)
|
|
43
40
|
export interface LoginParams {
|
|
44
41
|
appId: string
|
|
45
42
|
clientId: string
|
|
@@ -48,28 +45,26 @@ export interface LoginParams {
|
|
|
48
45
|
code?: boolean
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
//
|
|
48
|
+
// 登录响应(参考 tineco-ui)
|
|
52
49
|
export interface LoginResult {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
access_token: string
|
|
51
|
+
token_type: string
|
|
52
|
+
refresh_token: string
|
|
53
|
+
expires_time: number
|
|
54
|
+
refresh_time: number
|
|
55
|
+
code?: string
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
//
|
|
58
|
+
// 菜单项(参考 tineco-ui)
|
|
60
59
|
export interface MenuItem {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
component?: string
|
|
65
|
-
redirect?: string
|
|
60
|
+
menuCode: string
|
|
61
|
+
menuName: string
|
|
62
|
+
menuUrl: string
|
|
66
63
|
icon?: string
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
order?: number
|
|
72
|
-
parentId?: number | string | null
|
|
64
|
+
closable?: boolean
|
|
65
|
+
isDefault?: boolean
|
|
66
|
+
isOut?: boolean
|
|
67
|
+
type?: number // 1 为按钮,其他为菜单
|
|
73
68
|
children?: MenuItem[]
|
|
74
69
|
}
|
|
75
70
|
|
package/src/utils/auth.ts
CHANGED
|
@@ -5,13 +5,19 @@
|
|
|
5
5
|
import { local } from './storage'
|
|
6
6
|
|
|
7
7
|
const TOKEN_KEY = 'token'
|
|
8
|
+
const TOKEN_TYPE_KEY = 'token_type'
|
|
8
9
|
const REFRESH_TOKEN_KEY = 'refresh_token'
|
|
9
|
-
const TOKEN_EXPIRE_KEY = '
|
|
10
|
+
const TOKEN_EXPIRE_KEY = 'expires_time'
|
|
11
|
+
const REFRESH_TIME_KEY = 'refresh_time'
|
|
12
|
+
const CODE_KEY = 'code'
|
|
10
13
|
|
|
11
14
|
export interface TokenInfo {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
access_token: string
|
|
16
|
+
token_type: string
|
|
17
|
+
refresh_token: string
|
|
18
|
+
expires_time: number
|
|
19
|
+
refresh_time: number
|
|
20
|
+
code?: string
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
export const getToken = (): string | null => {
|
|
@@ -22,6 +28,14 @@ export const setToken = (token: string): void => {
|
|
|
22
28
|
local.set(TOKEN_KEY, token)
|
|
23
29
|
}
|
|
24
30
|
|
|
31
|
+
export const getTokenType = (): string | null => {
|
|
32
|
+
return local.get<string>(TOKEN_TYPE_KEY)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const setTokenType = (tokenType: string): void => {
|
|
36
|
+
local.set(TOKEN_TYPE_KEY, tokenType)
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
export const getRefreshToken = (): string | null => {
|
|
26
40
|
return local.get<string>(REFRESH_TOKEN_KEY)
|
|
27
41
|
}
|
|
@@ -38,16 +52,40 @@ export const setTokenExpire = (expireTime: number): void => {
|
|
|
38
52
|
local.set(TOKEN_EXPIRE_KEY, expireTime)
|
|
39
53
|
}
|
|
40
54
|
|
|
55
|
+
export const getRefreshTime = (): number | null => {
|
|
56
|
+
return local.get<number>(REFRESH_TIME_KEY)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const setRefreshTime = (refreshTime: number): void => {
|
|
60
|
+
local.set(REFRESH_TIME_KEY, refreshTime)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const getCode = (): string | null => {
|
|
64
|
+
return local.get<string>(CODE_KEY)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const setCode = (code: string): void => {
|
|
68
|
+
local.set(CODE_KEY, code)
|
|
69
|
+
}
|
|
70
|
+
|
|
41
71
|
export const setTokenInfo = (info: TokenInfo): void => {
|
|
42
|
-
setToken(info.
|
|
43
|
-
|
|
44
|
-
|
|
72
|
+
setToken(info.access_token)
|
|
73
|
+
setTokenType(info.token_type || 'Bearer')
|
|
74
|
+
setRefreshToken(info.refresh_token)
|
|
75
|
+
setTokenExpire(info.expires_time)
|
|
76
|
+
setRefreshTime(info.refresh_time)
|
|
77
|
+
if (info.code) {
|
|
78
|
+
setCode(info.code)
|
|
79
|
+
}
|
|
45
80
|
}
|
|
46
81
|
|
|
47
82
|
export const clearToken = (): void => {
|
|
48
83
|
local.remove(TOKEN_KEY)
|
|
84
|
+
local.remove(TOKEN_TYPE_KEY)
|
|
49
85
|
local.remove(REFRESH_TOKEN_KEY)
|
|
50
86
|
local.remove(TOKEN_EXPIRE_KEY)
|
|
87
|
+
local.remove(REFRESH_TIME_KEY)
|
|
88
|
+
local.remove(CODE_KEY)
|
|
51
89
|
}
|
|
52
90
|
|
|
53
91
|
export const isTokenExpired = (): boolean => {
|
package/src/utils/permission.ts
CHANGED
|
@@ -1,42 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 权限工具函数
|
|
3
|
+
* 注意:tineco-ui 不支持 permissions 和 roles 字段,这些函数暂时返回登录状态
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
import { useUserStore } from '@/stores/user'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* 检查是否有权限
|
|
9
|
-
* @param
|
|
10
|
+
* @param _permission 权限标识(暂不使用)
|
|
10
11
|
*/
|
|
11
|
-
export function hasPermission(
|
|
12
|
+
export function hasPermission(_permission: string | string[]): boolean {
|
|
12
13
|
const userStore = useUserStore()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (Array.isArray(permission)) {
|
|
16
|
-
return permission.some(p => permissions.includes(p))
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return permissions.includes(permission)
|
|
14
|
+
// tineco-ui 不支持 permissions 字段,暂时返回已登录状态
|
|
15
|
+
return userStore.isLoggedIn
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
/**
|
|
23
19
|
* 检查是否有角色
|
|
24
|
-
* @param
|
|
20
|
+
* @param _role 角色标识(暂不使用)
|
|
25
21
|
*/
|
|
26
|
-
export function hasRole(
|
|
22
|
+
export function hasRole(_role: string | string[]): boolean {
|
|
27
23
|
const userStore = useUserStore()
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (Array.isArray(role)) {
|
|
31
|
-
return role.some(r => roles.includes(r))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return roles.includes(role)
|
|
24
|
+
// tineco-ui 不支持 roles 字段,暂时返回已登录状态
|
|
25
|
+
return userStore.isLoggedIn
|
|
35
26
|
}
|
|
36
27
|
|
|
37
28
|
/**
|
|
38
29
|
* 检查是否是管理员
|
|
39
30
|
*/
|
|
40
31
|
export function isAdmin(): boolean {
|
|
41
|
-
return
|
|
32
|
+
return true // tineco-ui 不支持 roles 字段,暂时返回 true
|
|
42
33
|
}
|
package/src/utils/request.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
|
|
6
|
-
import { getToken, clearToken } from './auth'
|
|
6
|
+
import { getToken, getTokenType, clearToken } from './auth'
|
|
7
7
|
import { Message } from '@xto/feedback'
|
|
8
8
|
|
|
9
9
|
// 响应数据接口(Euler 框架 Result 格式)
|
|
@@ -39,8 +39,9 @@ const createRequest = (): AxiosInstance => {
|
|
|
39
39
|
instance.interceptors.request.use(
|
|
40
40
|
(config: InternalAxiosRequestConfig) => {
|
|
41
41
|
const token = getToken()
|
|
42
|
+
const tokenType = getTokenType() || 'Bearer'
|
|
42
43
|
if (token) {
|
|
43
|
-
config.headers.Authorization =
|
|
44
|
+
config.headers.Authorization = `${tokenType} ${token}`
|
|
44
45
|
}
|
|
45
46
|
return config
|
|
46
47
|
},
|
|
@@ -54,7 +55,7 @@ const createRequest = (): AxiosInstance => {
|
|
|
54
55
|
(response: AxiosResponse<ApiResponse>) => {
|
|
55
56
|
const { data } = response
|
|
56
57
|
|
|
57
|
-
// Euler 框架返回 Result 包装格式,成功时直接返回 data 中的实际数据
|
|
58
|
+
// Euler 框架返回 Result 包装格式,成功时直接返回 data.data 中的实际数据
|
|
58
59
|
if (data.code === 200 || data.code === 0) {
|
|
59
60
|
return data.data as any
|
|
60
61
|
}
|