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.
Files changed (82) hide show
  1. package/.env.development +7 -7
  2. package/.env.production +7 -7
  3. package/dist/assets/403-AFBQifUI.js +1 -0
  4. package/dist/assets/403-BHEXXbt2.css +1 -0
  5. package/dist/assets/404-Ct_A1n7S.css +1 -0
  6. package/dist/assets/404-WFvpcD2_.js +1 -0
  7. package/dist/assets/_plugin-vue_export-helper-DlAUqK2U.js +1 -0
  8. package/dist/assets/index-1juADvYN.js +2 -0
  9. package/dist/assets/index-4-QoJAgA.css +1 -0
  10. package/dist/assets/index-B-sX4Ru0.js +1 -0
  11. package/dist/assets/index-BHwEwbkp.js +1 -0
  12. package/dist/assets/index-BMcziU5a.css +1 -0
  13. package/dist/assets/index-BRR97dc6.js +1 -0
  14. package/dist/assets/index-BTsRosKu.js +1 -0
  15. package/dist/assets/index-BZA0ksjx.css +1 -0
  16. package/dist/assets/index-BpV_8nl0.js +1 -0
  17. package/dist/assets/index-BvzhR4zp.js +1 -0
  18. package/dist/assets/index-CUh_s55Z.css +1 -0
  19. package/dist/assets/index-CVjdnIgR.css +1 -0
  20. package/dist/assets/index-CYq57-zj.js +1 -0
  21. package/dist/assets/index-CZAlkDIC.css +1 -0
  22. package/dist/assets/index-CkL3sVAQ.js +2 -0
  23. package/dist/assets/index-CtrKVYJb.css +1 -0
  24. package/dist/assets/index-Cz2P_bsS.js +1 -0
  25. package/dist/assets/index-D9wlAuR_.js +1 -0
  26. package/dist/assets/index-DawJb02s.css +1 -0
  27. package/dist/assets/index-DfFR6NLf.js +1 -0
  28. package/dist/assets/index-Do3gMkWw.js +2 -0
  29. package/dist/assets/index-DwVgMO8e.js +1 -0
  30. package/dist/assets/index-GDP-IkXE.css +1 -0
  31. package/dist/assets/index-Iaz1ZzPC.js +2 -0
  32. package/dist/assets/index-PfV8pzQz.css +1 -0
  33. package/dist/assets/index-Swfu6yvD.css +1 -0
  34. package/dist/assets/index-Te8_PRgJ.js +1 -0
  35. package/dist/assets/index-WyZ91RLx.css +1 -0
  36. package/dist/assets/index-tFYRoFdE.js +1 -0
  37. package/dist/assets/vendor-42ANG6Sg.js +6 -0
  38. package/dist/assets/vite-Dw-pgLOX.js +1 -0
  39. package/dist/assets/vue-vendor-Br-l7wbK.js +29 -0
  40. package/dist/assets/xto-base-C-IBqjVs.js +1 -0
  41. package/dist/assets/xto-base-C6eqMPdO.css +1 -0
  42. package/dist/assets/xto-business--V1F5Gwb.css +1 -0
  43. package/dist/assets/xto-core-DZK7Cyg0.js +1 -0
  44. package/dist/assets/xto-data-BFpiDgJi.js +1 -0
  45. package/dist/assets/xto-data-CnAQAQH2.css +1 -0
  46. package/dist/assets/xto-feedback-B7ipsTfz.js +1 -0
  47. package/dist/assets/xto-feedback-DBwJzoTj.css +1 -0
  48. package/dist/assets/xto-form-CrsyAjyr.css +1 -0
  49. package/dist/assets/xto-form-NRjKKNcY.js +1 -0
  50. package/dist/assets/xto-layout-BqU8RuWL.css +1 -0
  51. package/dist/assets/xto-navigation-BiSaXPfr.js +1 -0
  52. package/dist/assets/xto-navigation-C1cnSL2E.css +1 -0
  53. package/dist/assets/xto-navigation-CBPg4dCc.css +1 -0
  54. package/dist/assets/xto-navigation-CKabFu9d.js +1 -0
  55. package/dist/index.html +28 -0
  56. package/package.json +85 -85
  57. package/src/api/auth.ts +25 -25
  58. package/src/api/system.ts +66 -66
  59. package/src/assets/styles/_dark.scss +524 -406
  60. package/src/assets/styles/index.scss +8 -0
  61. package/src/components/Layout/Header.vue +968 -973
  62. package/src/components/Layout/Sidebar.vue +283 -273
  63. package/src/components/Layout/TopMenu.vue +186 -0
  64. package/src/components/Layout/index.vue +60 -3
  65. package/src/composables/useApp.ts +61 -61
  66. package/src/composables/useAuth.ts +16 -16
  67. package/src/directives/permission.ts +27 -27
  68. package/src/env.d.ts +18 -18
  69. package/src/index.ts +47 -47
  70. package/src/router/dynamicRoutes.ts +162 -162
  71. package/src/router/guards.ts +128 -128
  72. package/src/router/index.ts +79 -79
  73. package/src/stores/auth.ts +65 -65
  74. package/src/stores/menu.ts +48 -48
  75. package/src/stores/user.ts +50 -50
  76. package/src/types/api.d.ts +80 -80
  77. package/src/utils/auth.ts +99 -99
  78. package/src/utils/config.ts +80 -80
  79. package/src/utils/permission.ts +32 -32
  80. package/src/utils/request.ts +124 -124
  81. package/src/views/login/index.vue +194 -194
  82. package/vite.config.ts +135 -135
@@ -1,163 +1,163 @@
1
- /**
2
- * 动态路由模板
3
- */
4
-
5
- import type { RouteRecordRaw } from 'vue-router'
6
-
7
- // 布局路由(包含默认子路由)
8
- export const layoutRoute: RouteRecordRaw = {
9
- path: '/',
10
- name: 'Layout',
11
- component: () => import('@/components/Layout/index.vue'),
12
- redirect: '/dashboard',
13
- children: [
14
- {
15
- path: '/dashboard',
16
- name: 'Dashboard',
17
- component: () => import('@/views/dashboard/index.vue'),
18
- meta: {
19
- title: '仪表盘',
20
- icon: 'dashboard',
21
- keepAlive: true,
22
- affix: true
23
- }
24
- },
25
- {
26
- path: '/system/user',
27
- name: 'SystemUser',
28
- component: () => import('@/views/system/user/index.vue'),
29
- meta: {
30
- title: '用户管理',
31
- icon: 'user',
32
- keepAlive: true
33
- }
34
- },
35
- {
36
- path: '/system/role',
37
- name: 'SystemRole',
38
- component: () => import('@/views/system/role/index.vue'),
39
- meta: {
40
- title: '角色管理',
41
- icon: 'role',
42
- keepAlive: true
43
- }
44
- },
45
- {
46
- path: '/system/menu',
47
- name: 'SystemMenu',
48
- component: () => import('@/views/system/menu/index.vue'),
49
- meta: {
50
- title: '菜单管理',
51
- icon: 'menu',
52
- keepAlive: true
53
- }
54
- }
55
- ]
56
- }
57
-
58
- // 默认路由(用于开发,后续由后端返回)
59
- export const defaultDynamicRoutes: RouteRecordRaw[] = [
60
- {
61
- path: '/dashboard',
62
- name: 'Dashboard',
63
- component: () => import('@/views/dashboard/index.vue'),
64
- meta: {
65
- title: '仪表盘',
66
- icon: 'dashboard',
67
- keepAlive: true,
68
- affix: true
69
- }
70
- },
71
- {
72
- path: '/system',
73
- name: 'System',
74
- redirect: '/system/user',
75
- meta: {
76
- title: '系统管理',
77
- icon: 'setting'
78
- },
79
- children: [
80
- {
81
- path: 'user',
82
- name: 'SystemUser',
83
- component: () => import('@/views/system/user/index.vue'),
84
- meta: {
85
- title: '用户管理',
86
- icon: 'user',
87
- keepAlive: true
88
- }
89
- },
90
- {
91
- path: 'role',
92
- name: 'SystemRole',
93
- component: () => import('@/views/system/role/index.vue'),
94
- meta: {
95
- title: '角色管理',
96
- icon: 'role',
97
- keepAlive: true
98
- }
99
- },
100
- {
101
- path: 'menu',
102
- name: 'SystemMenu',
103
- component: () => import('@/views/system/menu/index.vue'),
104
- meta: {
105
- title: '菜单管理',
106
- icon: 'menu',
107
- keepAlive: true
108
- }
109
- }
110
- ]
111
- }
112
- ]
113
-
114
- // Mock 菜单数据(参考 tineco-ui 格式)
115
- export const mockMenuData = [
116
- {
117
- menuCode: 'dashboard',
118
- menuName: '仪表盘',
119
- menuUrl: '/dashboard',
120
- icon: 'dashboard',
121
- closable: true,
122
- isDefault: true,
123
- isOut: false
124
- },
125
- {
126
- menuCode: 'system',
127
- menuName: '系统管理',
128
- menuUrl: '/system',
129
- icon: 'setting',
130
- closable: false,
131
- isDefault: false,
132
- isOut: false,
133
- children: [
134
- {
135
- menuCode: 'system_user',
136
- menuName: '用户管理',
137
- menuUrl: '/system/user',
138
- icon: 'user',
139
- closable: true,
140
- isDefault: false,
141
- isOut: false
142
- },
143
- {
144
- menuCode: 'system_role',
145
- menuName: '角色管理',
146
- menuUrl: '/system/role',
147
- icon: 'role',
148
- closable: true,
149
- isDefault: false,
150
- isOut: false
151
- },
152
- {
153
- menuCode: 'system_menu',
154
- menuName: '菜单管理',
155
- menuUrl: '/system/menu',
156
- icon: 'menu',
157
- closable: true,
158
- isDefault: false,
159
- isOut: false
160
- }
161
- ]
162
- }
1
+ /**
2
+ * 动态路由模板
3
+ */
4
+
5
+ import type { RouteRecordRaw } from 'vue-router'
6
+
7
+ // 布局路由(包含默认子路由)
8
+ export const layoutRoute: RouteRecordRaw = {
9
+ path: '/',
10
+ name: 'Layout',
11
+ component: () => import('@/components/Layout/index.vue'),
12
+ redirect: '/dashboard',
13
+ children: [
14
+ {
15
+ path: '/dashboard',
16
+ name: 'Dashboard',
17
+ component: () => import('@/views/dashboard/index.vue'),
18
+ meta: {
19
+ title: '仪表盘',
20
+ icon: 'dashboard',
21
+ keepAlive: true,
22
+ affix: true
23
+ }
24
+ },
25
+ {
26
+ path: '/system/user',
27
+ name: 'SystemUser',
28
+ component: () => import('@/views/system/user/index.vue'),
29
+ meta: {
30
+ title: '用户管理',
31
+ icon: 'user',
32
+ keepAlive: true
33
+ }
34
+ },
35
+ {
36
+ path: '/system/role',
37
+ name: 'SystemRole',
38
+ component: () => import('@/views/system/role/index.vue'),
39
+ meta: {
40
+ title: '角色管理',
41
+ icon: 'role',
42
+ keepAlive: true
43
+ }
44
+ },
45
+ {
46
+ path: '/system/menu',
47
+ name: 'SystemMenu',
48
+ component: () => import('@/views/system/menu/index.vue'),
49
+ meta: {
50
+ title: '菜单管理',
51
+ icon: 'menu',
52
+ keepAlive: true
53
+ }
54
+ }
55
+ ]
56
+ }
57
+
58
+ // 默认路由(用于开发,后续由后端返回)
59
+ export const defaultDynamicRoutes: RouteRecordRaw[] = [
60
+ {
61
+ path: '/dashboard',
62
+ name: 'Dashboard',
63
+ component: () => import('@/views/dashboard/index.vue'),
64
+ meta: {
65
+ title: '仪表盘',
66
+ icon: 'dashboard',
67
+ keepAlive: true,
68
+ affix: true
69
+ }
70
+ },
71
+ {
72
+ path: '/system',
73
+ name: 'System',
74
+ redirect: '/system/user',
75
+ meta: {
76
+ title: '系统管理',
77
+ icon: 'setting'
78
+ },
79
+ children: [
80
+ {
81
+ path: 'user',
82
+ name: 'SystemUser',
83
+ component: () => import('@/views/system/user/index.vue'),
84
+ meta: {
85
+ title: '用户管理',
86
+ icon: 'user',
87
+ keepAlive: true
88
+ }
89
+ },
90
+ {
91
+ path: 'role',
92
+ name: 'SystemRole',
93
+ component: () => import('@/views/system/role/index.vue'),
94
+ meta: {
95
+ title: '角色管理',
96
+ icon: 'role',
97
+ keepAlive: true
98
+ }
99
+ },
100
+ {
101
+ path: 'menu',
102
+ name: 'SystemMenu',
103
+ component: () => import('@/views/system/menu/index.vue'),
104
+ meta: {
105
+ title: '菜单管理',
106
+ icon: 'menu',
107
+ keepAlive: true
108
+ }
109
+ }
110
+ ]
111
+ }
112
+ ]
113
+
114
+ // Mock 菜单数据(参考 tineco-ui 格式)
115
+ export const mockMenuData = [
116
+ {
117
+ menuCode: 'dashboard',
118
+ menuName: '仪表盘',
119
+ menuUrl: '/dashboard',
120
+ icon: 'dashboard',
121
+ closable: true,
122
+ isDefault: true,
123
+ isOut: false
124
+ },
125
+ {
126
+ menuCode: 'system',
127
+ menuName: '系统管理',
128
+ menuUrl: '/system',
129
+ icon: 'setting',
130
+ closable: false,
131
+ isDefault: false,
132
+ isOut: false,
133
+ children: [
134
+ {
135
+ menuCode: 'system_user',
136
+ menuName: '用户管理',
137
+ menuUrl: '/system/user',
138
+ icon: 'user',
139
+ closable: true,
140
+ isDefault: false,
141
+ isOut: false
142
+ },
143
+ {
144
+ menuCode: 'system_role',
145
+ menuName: '角色管理',
146
+ menuUrl: '/system/role',
147
+ icon: 'role',
148
+ closable: true,
149
+ isDefault: false,
150
+ isOut: false
151
+ },
152
+ {
153
+ menuCode: 'system_menu',
154
+ menuName: '菜单管理',
155
+ menuUrl: '/system/menu',
156
+ icon: 'menu',
157
+ closable: true,
158
+ isDefault: false,
159
+ isOut: false
160
+ }
161
+ ]
162
+ }
163
163
  ]
@@ -1,129 +1,129 @@
1
- /**
2
- * 路由守卫设置
3
- */
4
-
5
- import type { Router } from 'vue-router'
6
- import { getToken } from '@/utils/auth'
7
- import { useUserStore } from '@/stores/user'
8
- import { useMenuStore } from '@/stores/menu'
9
- import { useAppStore } from '@/stores/app'
10
- import { getUserInfo } from '@/api/auth'
11
- import { getMenuTree } from '@/api/system'
12
-
13
- // 白名单路由
14
- const defaultWhiteList = ['/login', '/404', '/403']
15
-
16
- interface RouterGuardOptions {
17
- // 白名单路由
18
- whiteList?: string[]
19
- // 登录页路径
20
- loginPath?: string
21
- // 首页路径
22
- homePath?: string
23
- // 应用ID
24
- appId?: string
25
- // 获取用户信息的回调(可选,默认调用 API)
26
- fetchUserInfo?: () => Promise<any>
27
- // 获取菜单的回调(可选,默认调用 API)
28
- fetchMenu?: () => Promise<any>
29
- // 登录成功后的回调
30
- onLoginSuccess?: () => void
31
- }
32
-
33
- /**
34
- * 设置路由守卫
35
- * @param router 路由实例
36
- * @param options 配置选项
37
- */
38
- export function setupRouterGuards(router: Router, options: RouterGuardOptions = {}) {
39
- const whiteList = options.whiteList || defaultWhiteList
40
- const loginPath = options.loginPath || '/login'
41
- const homePath = options.homePath || '/'
42
-
43
- router.beforeEach(async (to, _from, next) => {
44
- const appStore = useAppStore()
45
- const userStore = useUserStore()
46
- const menuStore = useMenuStore()
47
-
48
- // 初始化主题
49
- appStore.initTheme()
50
-
51
- // 检查是否有 token
52
- const token = getToken()
53
-
54
- if (token) {
55
- // 已登录
56
- if (to.path === loginPath) {
57
- // 已登录访问登录页,跳转到首页
58
- next({ path: homePath })
59
- } else {
60
- // 检查是否已获取用户信息
61
- if (userStore.isLoggedIn) {
62
- // 已有用户信息,直接放行
63
- // 添加缓存页面
64
- if (to.name && to.meta.keepAlive) {
65
- appStore.addCachedView(to.name as string)
66
- }
67
- next()
68
- } else {
69
- // 尝试获取用户信息
70
- try {
71
- // 获取用户信息
72
- if (options.fetchUserInfo) {
73
- const userInfo = await options.fetchUserInfo()
74
- userStore.setUserInfo(userInfo)
75
- } else {
76
- const userInfo = await getUserInfo()
77
- userStore.setUserInfo(userInfo)
78
- }
79
-
80
- // 获取菜单
81
- if (options.fetchMenu) {
82
- const menuList = await options.fetchMenu()
83
- menuStore.setMenuList(menuList)
84
- } else {
85
- const menuList = await getMenuTree(options.appId)
86
- menuStore.setMenuList(menuList)
87
- }
88
-
89
- // 登录成功回调
90
- if (options.onLoginSuccess) {
91
- options.onLoginSuccess()
92
- }
93
-
94
- // 添加缓存页面
95
- if (to.name && to.meta.keepAlive) {
96
- appStore.addCachedView(to.name as string)
97
- }
98
-
99
- // 重新导航到目标路由,确保动态路由已添加
100
- next({ ...to, replace: true })
101
- } catch (error) {
102
- // 获取用户信息失败,清除 token 并跳转到登录页
103
- console.error('获取用户信息失败:', error)
104
- userStore.clearUserInfo()
105
- menuStore.clearMenu()
106
- // 清除 token
107
- localStorage.removeItem('token')
108
- localStorage.removeItem('token_type')
109
- localStorage.removeItem('refresh_token')
110
- next({ path: loginPath, query: { redirect: to.fullPath } })
111
- }
112
- }
113
- }
114
- } else {
115
- // 未登录
116
- if (whiteList.includes(to.path)) {
117
- // 在白名单中,直接放行
118
- next()
119
- } else {
120
- // 不在白名单中,跳转到登录页
121
- next({ path: loginPath, query: { redirect: to.fullPath } })
122
- }
123
- }
124
- })
125
-
126
- router.afterEach(() => {
127
- // 可以在这里添加进度条结束等
128
- })
1
+ /**
2
+ * 路由守卫设置
3
+ */
4
+
5
+ import type { Router } from 'vue-router'
6
+ import { getToken } from '@/utils/auth'
7
+ import { useUserStore } from '@/stores/user'
8
+ import { useMenuStore } from '@/stores/menu'
9
+ import { useAppStore } from '@/stores/app'
10
+ import { getUserInfo } from '@/api/auth'
11
+ import { getMenuTree } from '@/api/system'
12
+
13
+ // 白名单路由
14
+ const defaultWhiteList = ['/login', '/404', '/403']
15
+
16
+ interface RouterGuardOptions {
17
+ // 白名单路由
18
+ whiteList?: string[]
19
+ // 登录页路径
20
+ loginPath?: string
21
+ // 首页路径
22
+ homePath?: string
23
+ // 应用ID
24
+ appId?: string
25
+ // 获取用户信息的回调(可选,默认调用 API)
26
+ fetchUserInfo?: () => Promise<any>
27
+ // 获取菜单的回调(可选,默认调用 API)
28
+ fetchMenu?: () => Promise<any>
29
+ // 登录成功后的回调
30
+ onLoginSuccess?: () => void
31
+ }
32
+
33
+ /**
34
+ * 设置路由守卫
35
+ * @param router 路由实例
36
+ * @param options 配置选项
37
+ */
38
+ export function setupRouterGuards(router: Router, options: RouterGuardOptions = {}) {
39
+ const whiteList = options.whiteList || defaultWhiteList
40
+ const loginPath = options.loginPath || '/login'
41
+ const homePath = options.homePath || '/'
42
+
43
+ router.beforeEach(async (to, _from, next) => {
44
+ const appStore = useAppStore()
45
+ const userStore = useUserStore()
46
+ const menuStore = useMenuStore()
47
+
48
+ // 初始化主题
49
+ appStore.initTheme()
50
+
51
+ // 检查是否有 token
52
+ const token = getToken()
53
+
54
+ if (token) {
55
+ // 已登录
56
+ if (to.path === loginPath) {
57
+ // 已登录访问登录页,跳转到首页
58
+ next({ path: homePath })
59
+ } else {
60
+ // 检查是否已获取用户信息
61
+ if (userStore.isLoggedIn) {
62
+ // 已有用户信息,直接放行
63
+ // 添加缓存页面
64
+ if (to.name && to.meta.keepAlive) {
65
+ appStore.addCachedView(to.name as string)
66
+ }
67
+ next()
68
+ } else {
69
+ // 尝试获取用户信息
70
+ try {
71
+ // 获取用户信息
72
+ if (options.fetchUserInfo) {
73
+ const userInfo = await options.fetchUserInfo()
74
+ userStore.setUserInfo(userInfo)
75
+ } else {
76
+ const userInfo = await getUserInfo()
77
+ userStore.setUserInfo(userInfo)
78
+ }
79
+
80
+ // 获取菜单
81
+ if (options.fetchMenu) {
82
+ const menuList = await options.fetchMenu()
83
+ menuStore.setMenuList(menuList)
84
+ } else {
85
+ const menuList = await getMenuTree(options.appId)
86
+ menuStore.setMenuList(menuList)
87
+ }
88
+
89
+ // 登录成功回调
90
+ if (options.onLoginSuccess) {
91
+ options.onLoginSuccess()
92
+ }
93
+
94
+ // 添加缓存页面
95
+ if (to.name && to.meta.keepAlive) {
96
+ appStore.addCachedView(to.name as string)
97
+ }
98
+
99
+ // 重新导航到目标路由,确保动态路由已添加
100
+ next({ ...to, replace: true })
101
+ } catch (error) {
102
+ // 获取用户信息失败,清除 token 并跳转到登录页
103
+ console.error('获取用户信息失败:', error)
104
+ userStore.clearUserInfo()
105
+ menuStore.clearMenu()
106
+ // 清除 token
107
+ localStorage.removeItem('token')
108
+ localStorage.removeItem('token_type')
109
+ localStorage.removeItem('refresh_token')
110
+ next({ path: loginPath, query: { redirect: to.fullPath } })
111
+ }
112
+ }
113
+ }
114
+ } else {
115
+ // 未登录
116
+ if (whiteList.includes(to.path)) {
117
+ // 在白名单中,直接放行
118
+ next()
119
+ } else {
120
+ // 不在白名单中,跳转到登录页
121
+ next({ path: loginPath, query: { redirect: to.fullPath } })
122
+ }
123
+ }
124
+ })
125
+
126
+ router.afterEach(() => {
127
+ // 可以在这里添加进度条结束等
128
+ })
129
129
  }