xto-fronted 0.4.7 → 0.4.9
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 +7 -7
- package/.env.production +7 -7
- package/dist/assets/403-AFBQifUI.js +1 -0
- package/dist/assets/403-BHEXXbt2.css +1 -0
- package/dist/assets/404-Ct_A1n7S.css +1 -0
- package/dist/assets/404-WFvpcD2_.js +1 -0
- package/dist/assets/_plugin-vue_export-helper-DlAUqK2U.js +1 -0
- package/dist/assets/index-1juADvYN.js +2 -0
- package/dist/assets/index-4-QoJAgA.css +1 -0
- package/dist/assets/index-B-sX4Ru0.js +1 -0
- package/dist/assets/index-BHwEwbkp.js +1 -0
- package/dist/assets/index-BMcziU5a.css +1 -0
- package/dist/assets/index-BRR97dc6.js +1 -0
- package/dist/assets/index-BTsRosKu.js +1 -0
- package/dist/assets/index-BZA0ksjx.css +1 -0
- package/dist/assets/index-BpV_8nl0.js +1 -0
- package/dist/assets/index-BvzhR4zp.js +1 -0
- package/dist/assets/index-CUh_s55Z.css +1 -0
- package/dist/assets/index-CVjdnIgR.css +1 -0
- package/dist/assets/index-CYq57-zj.js +1 -0
- package/dist/assets/index-CZAlkDIC.css +1 -0
- package/dist/assets/index-CkL3sVAQ.js +2 -0
- package/dist/assets/index-CtrKVYJb.css +1 -0
- package/dist/assets/index-Cz2P_bsS.js +1 -0
- package/dist/assets/index-D9wlAuR_.js +1 -0
- package/dist/assets/index-DawJb02s.css +1 -0
- package/dist/assets/index-DfFR6NLf.js +1 -0
- package/dist/assets/index-Do3gMkWw.js +2 -0
- package/dist/assets/index-DwVgMO8e.js +1 -0
- package/dist/assets/index-GDP-IkXE.css +1 -0
- package/dist/assets/index-Iaz1ZzPC.js +2 -0
- package/dist/assets/index-PfV8pzQz.css +1 -0
- package/dist/assets/index-Swfu6yvD.css +1 -0
- package/dist/assets/index-Te8_PRgJ.js +1 -0
- package/dist/assets/index-WyZ91RLx.css +1 -0
- package/dist/assets/index-tFYRoFdE.js +1 -0
- package/dist/assets/vendor-42ANG6Sg.js +6 -0
- package/dist/assets/vite-Dw-pgLOX.js +1 -0
- package/dist/assets/vue-vendor-Br-l7wbK.js +29 -0
- package/dist/assets/xto-base-C-IBqjVs.js +1 -0
- package/dist/assets/xto-base-C6eqMPdO.css +1 -0
- package/dist/assets/xto-business--V1F5Gwb.css +1 -0
- package/dist/assets/xto-core-DZK7Cyg0.js +1 -0
- package/dist/assets/xto-data-BFpiDgJi.js +1 -0
- package/dist/assets/xto-data-CnAQAQH2.css +1 -0
- package/dist/assets/xto-feedback-B7ipsTfz.js +1 -0
- package/dist/assets/xto-feedback-DBwJzoTj.css +1 -0
- package/dist/assets/xto-form-CrsyAjyr.css +1 -0
- package/dist/assets/xto-form-NRjKKNcY.js +1 -0
- package/dist/assets/xto-layout-BqU8RuWL.css +1 -0
- package/dist/assets/xto-navigation-BiSaXPfr.js +1 -0
- package/dist/assets/xto-navigation-C1cnSL2E.css +1 -0
- package/dist/assets/xto-navigation-CBPg4dCc.css +1 -0
- package/dist/assets/xto-navigation-CKabFu9d.js +1 -0
- package/dist/index.html +28 -0
- package/package.json +85 -85
- package/src/api/auth.ts +25 -25
- package/src/api/system.ts +66 -66
- package/src/assets/styles/_dark.scss +524 -406
- package/src/assets/styles/index.scss +8 -0
- package/src/components/Layout/Header.vue +968 -973
- package/src/components/Layout/Sidebar.vue +283 -273
- package/src/components/Layout/TopMenu.vue +186 -0
- package/src/components/Layout/index.vue +60 -3
- package/src/composables/useApp.ts +61 -61
- package/src/composables/useAuth.ts +16 -16
- package/src/directives/permission.ts +27 -27
- package/src/env.d.ts +18 -18
- package/src/index.ts +47 -47
- package/src/router/dynamicRoutes.ts +162 -162
- package/src/router/guards.ts +128 -128
- package/src/router/index.ts +79 -79
- package/src/stores/auth.ts +65 -65
- package/src/stores/menu.ts +48 -48
- package/src/stores/user.ts +50 -50
- package/src/types/api.d.ts +80 -80
- package/src/utils/auth.ts +99 -99
- package/src/utils/config.ts +80 -80
- package/src/utils/permission.ts +32 -32
- package/src/utils/request.ts +124 -124
- package/src/views/login/index.vue +194 -194
- package/vite.config.ts +135 -135
package/src/utils/auth.ts
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Token 管理
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { local } from './storage'
|
|
6
|
-
|
|
7
|
-
const TOKEN_KEY = 'token'
|
|
8
|
-
const TOKEN_TYPE_KEY = 'token_type'
|
|
9
|
-
const REFRESH_TOKEN_KEY = 'refresh_token'
|
|
10
|
-
const TOKEN_EXPIRE_KEY = 'expires_time'
|
|
11
|
-
const REFRESH_TIME_KEY = 'refresh_time'
|
|
12
|
-
const CODE_KEY = 'code'
|
|
13
|
-
|
|
14
|
-
export interface TokenInfo {
|
|
15
|
-
access_token: string
|
|
16
|
-
token_type: string
|
|
17
|
-
refresh_token: string
|
|
18
|
-
expires_time: number
|
|
19
|
-
refresh_time: number
|
|
20
|
-
code?: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const getToken = (): string | null => {
|
|
24
|
-
return local.get<string>(TOKEN_KEY)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const setToken = (token: string): void => {
|
|
28
|
-
local.set(TOKEN_KEY, token)
|
|
29
|
-
}
|
|
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
|
-
|
|
39
|
-
export const getRefreshToken = (): string | null => {
|
|
40
|
-
return local.get<string>(REFRESH_TOKEN_KEY)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export const setRefreshToken = (refreshToken: string): void => {
|
|
44
|
-
local.set(REFRESH_TOKEN_KEY, refreshToken)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export const getTokenExpire = (): number | null => {
|
|
48
|
-
return local.get<number>(TOKEN_EXPIRE_KEY)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export const setTokenExpire = (expireTime: number): void => {
|
|
52
|
-
local.set(TOKEN_EXPIRE_KEY, expireTime)
|
|
53
|
-
}
|
|
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
|
-
|
|
71
|
-
export const setTokenInfo = (info: TokenInfo): void => {
|
|
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
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export const clearToken = (): void => {
|
|
83
|
-
local.remove(TOKEN_KEY)
|
|
84
|
-
local.remove(TOKEN_TYPE_KEY)
|
|
85
|
-
local.remove(REFRESH_TOKEN_KEY)
|
|
86
|
-
local.remove(TOKEN_EXPIRE_KEY)
|
|
87
|
-
local.remove(REFRESH_TIME_KEY)
|
|
88
|
-
local.remove(CODE_KEY)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export const isTokenExpired = (): boolean => {
|
|
92
|
-
const expireTime = getTokenExpire()
|
|
93
|
-
if (!expireTime) return true
|
|
94
|
-
return Date.now() > expireTime
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export const hasToken = (): boolean => {
|
|
98
|
-
const token = getToken()
|
|
99
|
-
return !!token && !isTokenExpired()
|
|
1
|
+
/**
|
|
2
|
+
* Token 管理
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { local } from './storage'
|
|
6
|
+
|
|
7
|
+
const TOKEN_KEY = 'token'
|
|
8
|
+
const TOKEN_TYPE_KEY = 'token_type'
|
|
9
|
+
const REFRESH_TOKEN_KEY = 'refresh_token'
|
|
10
|
+
const TOKEN_EXPIRE_KEY = 'expires_time'
|
|
11
|
+
const REFRESH_TIME_KEY = 'refresh_time'
|
|
12
|
+
const CODE_KEY = 'code'
|
|
13
|
+
|
|
14
|
+
export interface TokenInfo {
|
|
15
|
+
access_token: string
|
|
16
|
+
token_type: string
|
|
17
|
+
refresh_token: string
|
|
18
|
+
expires_time: number
|
|
19
|
+
refresh_time: number
|
|
20
|
+
code?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const getToken = (): string | null => {
|
|
24
|
+
return local.get<string>(TOKEN_KEY)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const setToken = (token: string): void => {
|
|
28
|
+
local.set(TOKEN_KEY, token)
|
|
29
|
+
}
|
|
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
|
+
|
|
39
|
+
export const getRefreshToken = (): string | null => {
|
|
40
|
+
return local.get<string>(REFRESH_TOKEN_KEY)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const setRefreshToken = (refreshToken: string): void => {
|
|
44
|
+
local.set(REFRESH_TOKEN_KEY, refreshToken)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const getTokenExpire = (): number | null => {
|
|
48
|
+
return local.get<number>(TOKEN_EXPIRE_KEY)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const setTokenExpire = (expireTime: number): void => {
|
|
52
|
+
local.set(TOKEN_EXPIRE_KEY, expireTime)
|
|
53
|
+
}
|
|
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
|
+
|
|
71
|
+
export const setTokenInfo = (info: TokenInfo): void => {
|
|
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
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const clearToken = (): void => {
|
|
83
|
+
local.remove(TOKEN_KEY)
|
|
84
|
+
local.remove(TOKEN_TYPE_KEY)
|
|
85
|
+
local.remove(REFRESH_TOKEN_KEY)
|
|
86
|
+
local.remove(TOKEN_EXPIRE_KEY)
|
|
87
|
+
local.remove(REFRESH_TIME_KEY)
|
|
88
|
+
local.remove(CODE_KEY)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const isTokenExpired = (): boolean => {
|
|
92
|
+
const expireTime = getTokenExpire()
|
|
93
|
+
if (!expireTime) return true
|
|
94
|
+
return Date.now() > expireTime
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const hasToken = (): boolean => {
|
|
98
|
+
const token = getToken()
|
|
99
|
+
return !!token && !isTokenExpired()
|
|
100
100
|
}
|
package/src/utils/config.ts
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 应用配置(动态设置,避免 import.meta.env 静态替换)
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { ref } from 'vue'
|
|
6
|
-
|
|
7
|
-
// 配置状态
|
|
8
|
-
const appId = ref<string>('')
|
|
9
|
-
const clientId = ref<string>('')
|
|
10
|
-
const apiBaseUrl = ref<string>('')
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* 初始化应用配置
|
|
14
|
-
* 在项目入口文件(main.ts)中调用此函数设置配置
|
|
15
|
-
*/
|
|
16
|
-
export function initAppConfig(config: {
|
|
17
|
-
appId?: string
|
|
18
|
-
clientId?: string
|
|
19
|
-
apiBaseUrl?: string
|
|
20
|
-
}) {
|
|
21
|
-
if (config.appId) {
|
|
22
|
-
appId.value = config.appId
|
|
23
|
-
}
|
|
24
|
-
if (config.clientId) {
|
|
25
|
-
clientId.value = config.clientId
|
|
26
|
-
}
|
|
27
|
-
if (config.apiBaseUrl) {
|
|
28
|
-
apiBaseUrl.value = config.apiBaseUrl
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* 获取 AppId
|
|
34
|
-
* 优先使用动态配置,其次使用环境变量
|
|
35
|
-
*/
|
|
36
|
-
export function getAppId(): string {
|
|
37
|
-
if (appId.value) {
|
|
38
|
-
return appId.value
|
|
39
|
-
}
|
|
40
|
-
// 尝试从环境变量获取(使用方项目构建时会注入)
|
|
41
|
-
try {
|
|
42
|
-
return import.meta.env.VITE_APP_ID || ''
|
|
43
|
-
} catch {
|
|
44
|
-
return ''
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* 获取 ClientId
|
|
50
|
-
*/
|
|
51
|
-
export function getClientId(): string {
|
|
52
|
-
if (clientId.value) {
|
|
53
|
-
return clientId.value
|
|
54
|
-
}
|
|
55
|
-
try {
|
|
56
|
-
return import.meta.env.VITE_APP_CLIENT_ID || ''
|
|
57
|
-
} catch {
|
|
58
|
-
return ''
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 获取 API 基础路径
|
|
64
|
-
*/
|
|
65
|
-
export function getApiBaseUrl(): string {
|
|
66
|
-
if (apiBaseUrl.value) {
|
|
67
|
-
return apiBaseUrl.value
|
|
68
|
-
}
|
|
69
|
-
try {
|
|
70
|
-
return import.meta.env.VITE_API_BASE_URL || ''
|
|
71
|
-
} catch {
|
|
72
|
-
return ''
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// 导出响应式引用(供特殊场景直接使用)
|
|
77
|
-
export const appConfig = {
|
|
78
|
-
appId,
|
|
79
|
-
clientId,
|
|
80
|
-
apiBaseUrl
|
|
1
|
+
/**
|
|
2
|
+
* 应用配置(动态设置,避免 import.meta.env 静态替换)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { ref } from 'vue'
|
|
6
|
+
|
|
7
|
+
// 配置状态
|
|
8
|
+
const appId = ref<string>('')
|
|
9
|
+
const clientId = ref<string>('')
|
|
10
|
+
const apiBaseUrl = ref<string>('')
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 初始化应用配置
|
|
14
|
+
* 在项目入口文件(main.ts)中调用此函数设置配置
|
|
15
|
+
*/
|
|
16
|
+
export function initAppConfig(config: {
|
|
17
|
+
appId?: string
|
|
18
|
+
clientId?: string
|
|
19
|
+
apiBaseUrl?: string
|
|
20
|
+
}) {
|
|
21
|
+
if (config.appId) {
|
|
22
|
+
appId.value = config.appId
|
|
23
|
+
}
|
|
24
|
+
if (config.clientId) {
|
|
25
|
+
clientId.value = config.clientId
|
|
26
|
+
}
|
|
27
|
+
if (config.apiBaseUrl) {
|
|
28
|
+
apiBaseUrl.value = config.apiBaseUrl
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 获取 AppId
|
|
34
|
+
* 优先使用动态配置,其次使用环境变量
|
|
35
|
+
*/
|
|
36
|
+
export function getAppId(): string {
|
|
37
|
+
if (appId.value) {
|
|
38
|
+
return appId.value
|
|
39
|
+
}
|
|
40
|
+
// 尝试从环境变量获取(使用方项目构建时会注入)
|
|
41
|
+
try {
|
|
42
|
+
return import.meta.env.VITE_APP_ID || ''
|
|
43
|
+
} catch {
|
|
44
|
+
return ''
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 获取 ClientId
|
|
50
|
+
*/
|
|
51
|
+
export function getClientId(): string {
|
|
52
|
+
if (clientId.value) {
|
|
53
|
+
return clientId.value
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
return import.meta.env.VITE_APP_CLIENT_ID || ''
|
|
57
|
+
} catch {
|
|
58
|
+
return ''
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 获取 API 基础路径
|
|
64
|
+
*/
|
|
65
|
+
export function getApiBaseUrl(): string {
|
|
66
|
+
if (apiBaseUrl.value) {
|
|
67
|
+
return apiBaseUrl.value
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
return import.meta.env.VITE_API_BASE_URL || ''
|
|
71
|
+
} catch {
|
|
72
|
+
return ''
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 导出响应式引用(供特殊场景直接使用)
|
|
77
|
+
export const appConfig = {
|
|
78
|
+
appId,
|
|
79
|
+
clientId,
|
|
80
|
+
apiBaseUrl
|
|
81
81
|
}
|
package/src/utils/permission.ts
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 权限工具函数
|
|
3
|
-
* 注意:tineco-ui 不支持 permissions 和 roles 字段,这些函数暂时返回登录状态
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useUserStore } from '@/stores/user'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 检查是否有权限
|
|
10
|
-
* @param _permission 权限标识(暂不使用)
|
|
11
|
-
*/
|
|
12
|
-
export function hasPermission(_permission: string | string[]): boolean {
|
|
13
|
-
const userStore = useUserStore()
|
|
14
|
-
// tineco-ui 不支持 permissions 字段,暂时返回已登录状态
|
|
15
|
-
return userStore.isLoggedIn
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 检查是否有角色
|
|
20
|
-
* @param _role 角色标识(暂不使用)
|
|
21
|
-
*/
|
|
22
|
-
export function hasRole(_role: string | string[]): boolean {
|
|
23
|
-
const userStore = useUserStore()
|
|
24
|
-
// tineco-ui 不支持 roles 字段,暂时返回已登录状态
|
|
25
|
-
return userStore.isLoggedIn
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 检查是否是管理员
|
|
30
|
-
*/
|
|
31
|
-
export function isAdmin(): boolean {
|
|
32
|
-
return true // tineco-ui 不支持 roles 字段,暂时返回 true
|
|
1
|
+
/**
|
|
2
|
+
* 权限工具函数
|
|
3
|
+
* 注意:tineco-ui 不支持 permissions 和 roles 字段,这些函数暂时返回登录状态
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useUserStore } from '@/stores/user'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 检查是否有权限
|
|
10
|
+
* @param _permission 权限标识(暂不使用)
|
|
11
|
+
*/
|
|
12
|
+
export function hasPermission(_permission: string | string[]): boolean {
|
|
13
|
+
const userStore = useUserStore()
|
|
14
|
+
// tineco-ui 不支持 permissions 字段,暂时返回已登录状态
|
|
15
|
+
return userStore.isLoggedIn
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 检查是否有角色
|
|
20
|
+
* @param _role 角色标识(暂不使用)
|
|
21
|
+
*/
|
|
22
|
+
export function hasRole(_role: string | string[]): boolean {
|
|
23
|
+
const userStore = useUserStore()
|
|
24
|
+
// tineco-ui 不支持 roles 字段,暂时返回已登录状态
|
|
25
|
+
return userStore.isLoggedIn
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 检查是否是管理员
|
|
30
|
+
*/
|
|
31
|
+
export function isAdmin(): boolean {
|
|
32
|
+
return true // tineco-ui 不支持 roles 字段,暂时返回 true
|
|
33
33
|
}
|
package/src/utils/request.ts
CHANGED
|
@@ -1,125 +1,125 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Axios 请求封装
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
|
|
6
|
-
import { getToken, getTokenType, clearToken } from './auth'
|
|
7
|
-
import { Message } from '@xto/feedback'
|
|
8
|
-
|
|
9
|
-
// 响应数据接口(Euler 框架 Result 格式)
|
|
10
|
-
export interface ApiResponse<T = unknown> {
|
|
11
|
-
code: number
|
|
12
|
-
data: T
|
|
13
|
-
message: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// 分页参数(Euler 框架格式)
|
|
17
|
-
export interface PageParams {
|
|
18
|
-
pageNo: number
|
|
19
|
-
pageSize: number
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// 分页响应(Euler 框架格式)
|
|
23
|
-
export interface PageResponse<T> {
|
|
24
|
-
records: T[]
|
|
25
|
-
total: number
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// 创建 axios 实例
|
|
29
|
-
const createRequest = (): AxiosInstance => {
|
|
30
|
-
const instance = axios.create({
|
|
31
|
-
baseURL: import.meta.env.VITE_API_BASE_URL,
|
|
32
|
-
timeout: 30000,
|
|
33
|
-
headers: {
|
|
34
|
-
'Content-Type': 'application/json'
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
// 请求拦截器
|
|
39
|
-
instance.interceptors.request.use(
|
|
40
|
-
(config: InternalAxiosRequestConfig) => {
|
|
41
|
-
const token = getToken()
|
|
42
|
-
const tokenType = getTokenType() || 'Bearer'
|
|
43
|
-
if (token) {
|
|
44
|
-
config.headers.Authorization = `${tokenType} ${token}`
|
|
45
|
-
}
|
|
46
|
-
return config
|
|
47
|
-
},
|
|
48
|
-
(error) => {
|
|
49
|
-
return Promise.reject(error)
|
|
50
|
-
}
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
// 响应拦截器
|
|
54
|
-
instance.interceptors.response.use(
|
|
55
|
-
(response: AxiosResponse<ApiResponse>) => {
|
|
56
|
-
const { data } = response
|
|
57
|
-
|
|
58
|
-
// Euler 框架返回 Result 包装格式,成功时直接返回 data.data 中的实际数据
|
|
59
|
-
if (data.code === 200 || data.code === 0) {
|
|
60
|
-
return data.data as any
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// 业务错误
|
|
64
|
-
Message.error(data.message || '请求失败')
|
|
65
|
-
return Promise.reject(new Error(data.message || '请求失败'))
|
|
66
|
-
},
|
|
67
|
-
(error) => {
|
|
68
|
-
const { response } = error
|
|
69
|
-
|
|
70
|
-
if (response) {
|
|
71
|
-
switch (response.status) {
|
|
72
|
-
case 401:
|
|
73
|
-
Message.error('登录已过期,请重新登录')
|
|
74
|
-
clearToken()
|
|
75
|
-
window.location.href = '/login'
|
|
76
|
-
break
|
|
77
|
-
case 403:
|
|
78
|
-
Message.error('没有权限访问')
|
|
79
|
-
break
|
|
80
|
-
case 404:
|
|
81
|
-
Message.error('请求资源不存在')
|
|
82
|
-
break
|
|
83
|
-
case 500:
|
|
84
|
-
Message.error('服务器错误')
|
|
85
|
-
break
|
|
86
|
-
default:
|
|
87
|
-
Message.error(response.data?.message || '请求失败')
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
Message.error('网络连接失败')
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return Promise.reject(error)
|
|
94
|
-
}
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
return instance
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const request = createRequest()
|
|
101
|
-
|
|
102
|
-
// 请求方法 - 直接返回实际数据,无需手动解包
|
|
103
|
-
export const http = {
|
|
104
|
-
get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
|
|
105
|
-
return request.get(url, config)
|
|
106
|
-
},
|
|
107
|
-
|
|
108
|
-
post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
|
|
109
|
-
return request.post(url, data, config)
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
|
|
113
|
-
return request.put(url, data, config)
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
|
|
117
|
-
return request.patch(url, data, config)
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
|
|
121
|
-
return request.delete(url, config)
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Axios 请求封装
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
|
|
6
|
+
import { getToken, getTokenType, clearToken } from './auth'
|
|
7
|
+
import { Message } from '@xto/feedback'
|
|
8
|
+
|
|
9
|
+
// 响应数据接口(Euler 框架 Result 格式)
|
|
10
|
+
export interface ApiResponse<T = unknown> {
|
|
11
|
+
code: number
|
|
12
|
+
data: T
|
|
13
|
+
message: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 分页参数(Euler 框架格式)
|
|
17
|
+
export interface PageParams {
|
|
18
|
+
pageNo: number
|
|
19
|
+
pageSize: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 分页响应(Euler 框架格式)
|
|
23
|
+
export interface PageResponse<T> {
|
|
24
|
+
records: T[]
|
|
25
|
+
total: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 创建 axios 实例
|
|
29
|
+
const createRequest = (): AxiosInstance => {
|
|
30
|
+
const instance = axios.create({
|
|
31
|
+
baseURL: import.meta.env.VITE_API_BASE_URL,
|
|
32
|
+
timeout: 30000,
|
|
33
|
+
headers: {
|
|
34
|
+
'Content-Type': 'application/json'
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// 请求拦截器
|
|
39
|
+
instance.interceptors.request.use(
|
|
40
|
+
(config: InternalAxiosRequestConfig) => {
|
|
41
|
+
const token = getToken()
|
|
42
|
+
const tokenType = getTokenType() || 'Bearer'
|
|
43
|
+
if (token) {
|
|
44
|
+
config.headers.Authorization = `${tokenType} ${token}`
|
|
45
|
+
}
|
|
46
|
+
return config
|
|
47
|
+
},
|
|
48
|
+
(error) => {
|
|
49
|
+
return Promise.reject(error)
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
// 响应拦截器
|
|
54
|
+
instance.interceptors.response.use(
|
|
55
|
+
(response: AxiosResponse<ApiResponse>) => {
|
|
56
|
+
const { data } = response
|
|
57
|
+
|
|
58
|
+
// Euler 框架返回 Result 包装格式,成功时直接返回 data.data 中的实际数据
|
|
59
|
+
if (data.code === 200 || data.code === 0) {
|
|
60
|
+
return data.data as any
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 业务错误
|
|
64
|
+
Message.error(data.message || '请求失败')
|
|
65
|
+
return Promise.reject(new Error(data.message || '请求失败'))
|
|
66
|
+
},
|
|
67
|
+
(error) => {
|
|
68
|
+
const { response } = error
|
|
69
|
+
|
|
70
|
+
if (response) {
|
|
71
|
+
switch (response.status) {
|
|
72
|
+
case 401:
|
|
73
|
+
Message.error('登录已过期,请重新登录')
|
|
74
|
+
clearToken()
|
|
75
|
+
window.location.href = '/login'
|
|
76
|
+
break
|
|
77
|
+
case 403:
|
|
78
|
+
Message.error('没有权限访问')
|
|
79
|
+
break
|
|
80
|
+
case 404:
|
|
81
|
+
Message.error('请求资源不存在')
|
|
82
|
+
break
|
|
83
|
+
case 500:
|
|
84
|
+
Message.error('服务器错误')
|
|
85
|
+
break
|
|
86
|
+
default:
|
|
87
|
+
Message.error(response.data?.message || '请求失败')
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
Message.error('网络连接失败')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return Promise.reject(error)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
return instance
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const request = createRequest()
|
|
101
|
+
|
|
102
|
+
// 请求方法 - 直接返回实际数据,无需手动解包
|
|
103
|
+
export const http = {
|
|
104
|
+
get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
|
|
105
|
+
return request.get(url, config)
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
|
|
109
|
+
return request.post(url, data, config)
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
|
|
113
|
+
return request.put(url, data, config)
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
|
|
117
|
+
return request.patch(url, data, config)
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
|
|
121
|
+
return request.delete(url, config)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
125
|
export default request
|