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
@@ -0,0 +1,186 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { useRoute, useRouter } from 'vue-router'
4
+ import { useMenuStore } from '@/stores/menu'
5
+ import { useAppStore } from '@/stores/app'
6
+ import { Menu, MenuItem, SubMenu } from '@xto/navigation'
7
+ import { Icon } from '@xto/base'
8
+
9
+ const route = useRoute()
10
+ const router = useRouter()
11
+ const menuStore = useMenuStore()
12
+ const appStore = useAppStore()
13
+
14
+ const activeMenu = computed(() => route.path)
15
+
16
+ // 菜单主题相关
17
+ const menuBgColor = computed(() => appStore.isDark ? '#1d1e1f' : '#fff')
18
+ const menuTextColor = computed(() => appStore.isDark ? '#cfd3dc' : '#303133')
19
+ const menuActiveTextColor = computed(() => '#409eff')
20
+
21
+ // 菜单选择
22
+ const handleMenuSelect = (index: string) => {
23
+ if (index && index !== route.path) {
24
+ router.push(index)
25
+ }
26
+ }
27
+
28
+ // 已知的图标名称列表
29
+ const knownIcons = new Set([
30
+ 'arrow-up', 'arrow-down', 'arrow-left', 'arrow-right',
31
+ 'caret-down', 'caret-right', 'plus', 'minus', 'close', 'check',
32
+ 'edit', 'delete', 'copy', 'download', 'upload', 'refresh', 'search',
33
+ 'filter', 'more', 'setting', 'share', 'loading', 'info', 'success',
34
+ 'warning', 'error', 'question', 'user', 'user-add', 'user-group',
35
+ 'logout', 'login', 'file', 'folder', 'folder-open', 'document',
36
+ 'image', 'video', 'music', 'camera', 'mail', 'phone', 'chat',
37
+ 'bell', 'message', 'eye', 'eye-off', 'calendar', 'clock', 'history',
38
+ 'timer', 'location', 'map', 'globe', 'star', 'heart', 'thumb-up',
39
+ 'link', 'external-link', 'lock', 'unlock', 'key', 'home', 'menu',
40
+ 'menu-fold', 'menu-unfold', 'sidebar-fold', 'sidebar-expand',
41
+ 'sidebar-left', 'dashboard', 'chart', 'chart-pie', 'chart-line',
42
+ 'report', 'analytics', 'system', 'permission', 'role', 'user-manage',
43
+ 'log', 'notification', 'app', 'list', 'grid', 'fullscreen',
44
+ 'fullscreen-exit', 'zoom-in', 'zoom-out', 'print', 'bookmark',
45
+ 'tag', 'code', 'terminal', 'database', 'server', 'cloud', 'gift',
46
+ 'moon', 'sun', 'theme', 'skin'
47
+ ])
48
+
49
+ // 获取菜单图标名称
50
+ const getMenuIcon = (icon?: string): string => {
51
+ if (!icon || icon === '') return ''
52
+
53
+ if (icon.startsWith('tineco-icon-')) {
54
+ const iconName = icon.replace('tineco-icon-', '')
55
+ const tinecoIconMap: Record<string, string> = {
56
+ home: 'home',
57
+ dashboard: 'dashboard',
58
+ system: 'system',
59
+ user: 'user',
60
+ role: 'role',
61
+ menu: 'list',
62
+ setting: 'setting',
63
+ file: 'file',
64
+ folder: 'folder',
65
+ chart: 'chart',
66
+ report: 'report',
67
+ analytics: 'analytics'
68
+ }
69
+ return tinecoIconMap[iconName] || iconName
70
+ }
71
+
72
+ const iconMap: Record<string, string> = {
73
+ dashboard: 'dashboard',
74
+ system: 'system',
75
+ user: 'user',
76
+ role: 'role',
77
+ menu: 'list',
78
+ setting: 'setting',
79
+ home: 'home',
80
+ chart: 'chart',
81
+ report: 'report',
82
+ analytics: 'analytics',
83
+ permission: 'permission',
84
+ log: 'log',
85
+ notification: 'notification',
86
+ app: 'app',
87
+ list: 'list',
88
+ grid: 'grid'
89
+ }
90
+
91
+ return iconMap[icon] || icon
92
+ }
93
+
94
+ const getFirstChar = (name?: string): string => {
95
+ if (!name) return ''
96
+ return name.charAt(0)
97
+ }
98
+
99
+ const iconExists = (iconName: string): boolean => {
100
+ return knownIcons.has(iconName)
101
+ }
102
+ </script>
103
+
104
+ <template>
105
+ <div class="top-menu">
106
+ <Menu
107
+ :default-active="activeMenu"
108
+ mode="horizontal"
109
+ :background-color="menuBgColor"
110
+ :text-color="menuTextColor"
111
+ :active-text-color="menuActiveTextColor"
112
+ class="top-menu__menu"
113
+ @select="handleMenuSelect"
114
+ >
115
+ <template v-for="menu in menuStore.menuList" :key="menu.menuUrl">
116
+ <!-- 有子菜单 -->
117
+ <SubMenu v-if="menu.children && menu.children.length > 0" :index="menu.menuUrl">
118
+ <template #title>
119
+ <span class="top-menu__menu-icon">
120
+ <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
121
+ <span v-else class="top-menu__menu-char">{{ getFirstChar(menu.menuName) }}</span>
122
+ </span>
123
+ <span>{{ menu.menuName }}</span>
124
+ </template>
125
+ <MenuItem
126
+ v-for="child in menu.children"
127
+ :key="child.menuUrl"
128
+ :index="child.menuUrl"
129
+ >
130
+ <span class="top-menu__menu-icon">
131
+ <Icon v-if="iconExists(getMenuIcon(child.icon))" :name="getMenuIcon(child.icon)" :size="16" />
132
+ <span v-else class="top-menu__menu-char">{{ getFirstChar(child.menuName) }}</span>
133
+ </span>
134
+ <span>{{ child.menuName }}</span>
135
+ </MenuItem>
136
+ </SubMenu>
137
+ <!-- 无子菜单 -->
138
+ <MenuItem v-else :index="menu.menuUrl">
139
+ <span class="top-menu__menu-icon">
140
+ <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
141
+ <span v-else class="top-menu__menu-char">{{ getFirstChar(menu.menuName) }}</span>
142
+ </span>
143
+ <span>{{ menu.menuName }}</span>
144
+ </MenuItem>
145
+ </template>
146
+ </Menu>
147
+ </div>
148
+ </template>
149
+
150
+ <style lang="scss" scoped>
151
+ .top-menu {
152
+ width: 100%;
153
+ height: 100%;
154
+ display: flex;
155
+ align-items: center;
156
+ padding: 0 20px;
157
+
158
+ &__menu {
159
+ flex: 1;
160
+ border-bottom: none;
161
+ height: 100%;
162
+ }
163
+
164
+ &__menu-icon {
165
+ display: inline-flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ width: 16px;
169
+ height: 16px;
170
+ margin-right: 8px;
171
+ }
172
+
173
+ &__menu-char {
174
+ display: inline-flex;
175
+ align-items: center;
176
+ justify-content: center;
177
+ width: 16px;
178
+ height: 16px;
179
+ font-size: 12px;
180
+ font-weight: 600;
181
+ color: var(--color-primary);
182
+ background-color: var(--color-primary-light-8);
183
+ border-radius: 4px;
184
+ }
185
+ }
186
+ </style>
@@ -1,21 +1,48 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
3
  import { useAppStore } from '@/stores/app'
4
+ import { useMenuStore } from '@/stores/menu'
4
5
  import Sidebar from './Sidebar.vue'
5
6
  import Header from './Header.vue'
7
+ import TopMenu from './TopMenu.vue'
6
8
 
7
9
  const appStore = useAppStore()
10
+ const menuStore = useMenuStore()
8
11
 
9
12
  const sidebarWidth = computed(() =>
10
13
  appStore.isCollapsed ? '64px' : '210px'
11
14
  )
15
+
16
+ // 布局模式
17
+ const layoutMode = computed(() => appStore.layout)
18
+
19
+ // 是否显示左侧菜单
20
+ const showSidebar = computed(() => layoutMode.value === 'sidebar' || layoutMode.value === 'mix')
21
+
22
+ // 是否显示顶部菜单
23
+ const showTopMenu = computed(() => layoutMode.value === 'top')
24
+
25
+ // 混合模式下只显示当前顶部菜单的子菜单
26
+ const mixSubMenus = computed(() => {
27
+ if (layoutMode.value !== 'mix') return menuStore.menuList
28
+ // 混合模式需要根据顶部选中的菜单显示子菜单
29
+ // 这里暂时返回全部菜单,后续可根据实际需求调整
30
+ return menuStore.menuList
31
+ })
12
32
  </script>
13
33
 
14
34
  <template>
15
- <div class="layout">
16
- <aside class="layout__aside" :style="{ width: sidebarWidth }">
17
- <Sidebar />
35
+ <div class="layout" :class="`layout--${layoutMode}`">
36
+ <!-- 左侧菜单布局 -->
37
+ <aside v-if="showSidebar" class="layout__aside" :style="{ width: sidebarWidth }">
38
+ <Sidebar :menu-list="layoutMode === 'mix' ? mixSubMenus : menuStore.menuList" />
18
39
  </aside>
40
+
41
+ <!-- 顶部菜单布局 -->
42
+ <div v-if="showTopMenu" class="layout__top-menu">
43
+ <TopMenu />
44
+ </div>
45
+
19
46
  <div class="layout__main">
20
47
  <header class="layout__header">
21
48
  <Header />
@@ -33,6 +60,29 @@ const sidebarWidth = computed(() =>
33
60
  width: 100%;
34
61
  height: 100%;
35
62
 
63
+ // 左侧菜单模式
64
+ &--sidebar {
65
+ flex-direction: row;
66
+ }
67
+
68
+ // 顶部菜单模式
69
+ &--top {
70
+ flex-direction: column;
71
+
72
+ .layout__aside {
73
+ display: none;
74
+ }
75
+
76
+ .layout__main {
77
+ flex: 1;
78
+ }
79
+ }
80
+
81
+ // 混合菜单模式
82
+ &--mix {
83
+ flex-direction: row;
84
+ }
85
+
36
86
  &__aside {
37
87
  transition: width 0.3s;
38
88
  overflow: hidden;
@@ -40,6 +90,13 @@ const sidebarWidth = computed(() =>
40
90
  height: 100%;
41
91
  }
42
92
 
93
+ &__top-menu {
94
+ width: 100%;
95
+ height: 50px;
96
+ background-color: var(--bg-color);
97
+ border-bottom: 1px solid var(--color-border-lighter);
98
+ }
99
+
43
100
  &__main {
44
101
  flex: 1;
45
102
  display: flex;
@@ -1,62 +1,62 @@
1
- /**
2
- * 应用组合函数
3
- * 提供应用级别的状态和方法
4
- */
5
-
6
- import { computed } from 'vue'
7
- import { useAppStore } from '@/stores/app'
8
- import { useUserStore } from '@/stores/user'
9
- import { useAuthStore } from '@/stores/auth'
10
-
11
- /**
12
- * 应用级别组合函数
13
- * @returns 应用状态和方法
14
- */
15
- export function useApp() {
16
- const appStore = useAppStore()
17
- const userStore = useUserStore()
18
- const authStore = useAuthStore()
19
-
20
- // 用户名
21
- const userName = computed(() => userStore.userName || '')
22
-
23
- // 用户信息
24
- const userInfo = computed(() => userStore.userInfo)
25
-
26
- // 应用名称
27
- const appName = computed(() => appStore.appName)
28
-
29
- // 是否已登录
30
- const isLoggedIn = computed(() => authStore.isLoggedIn)
31
-
32
- // 主题相关
33
- const isDark = computed(() => appStore.isDark)
34
- const theme = computed(() => appStore.theme)
35
-
36
- // 布局相关
37
- const isCollapsed = computed(() => appStore.isCollapsed)
38
- const layout = computed(() => appStore.layout)
39
-
40
- // 切换主题
41
- const toggleTheme = () => {
42
- appStore.toggleTheme()
43
- }
44
-
45
- // 切换菜单折叠
46
- const toggleCollapse = () => {
47
- appStore.toggleCollapse()
48
- }
49
-
50
- return {
51
- userName,
52
- userInfo,
53
- appName,
54
- isLoggedIn,
55
- isDark,
56
- theme,
57
- isCollapsed,
58
- layout,
59
- toggleTheme,
60
- toggleCollapse
61
- }
1
+ /**
2
+ * 应用组合函数
3
+ * 提供应用级别的状态和方法
4
+ */
5
+
6
+ import { computed } from 'vue'
7
+ import { useAppStore } from '@/stores/app'
8
+ import { useUserStore } from '@/stores/user'
9
+ import { useAuthStore } from '@/stores/auth'
10
+
11
+ /**
12
+ * 应用级别组合函数
13
+ * @returns 应用状态和方法
14
+ */
15
+ export function useApp() {
16
+ const appStore = useAppStore()
17
+ const userStore = useUserStore()
18
+ const authStore = useAuthStore()
19
+
20
+ // 用户名
21
+ const userName = computed(() => userStore.userName || '')
22
+
23
+ // 用户信息
24
+ const userInfo = computed(() => userStore.userInfo)
25
+
26
+ // 应用名称
27
+ const appName = computed(() => appStore.appName)
28
+
29
+ // 是否已登录
30
+ const isLoggedIn = computed(() => authStore.isLoggedIn)
31
+
32
+ // 主题相关
33
+ const isDark = computed(() => appStore.isDark)
34
+ const theme = computed(() => appStore.theme)
35
+
36
+ // 布局相关
37
+ const isCollapsed = computed(() => appStore.isCollapsed)
38
+ const layout = computed(() => appStore.layout)
39
+
40
+ // 切换主题
41
+ const toggleTheme = () => {
42
+ appStore.toggleTheme()
43
+ }
44
+
45
+ // 切换菜单折叠
46
+ const toggleCollapse = () => {
47
+ appStore.toggleCollapse()
48
+ }
49
+
50
+ return {
51
+ userName,
52
+ userInfo,
53
+ appName,
54
+ isLoggedIn,
55
+ isDark,
56
+ theme,
57
+ isCollapsed,
58
+ layout,
59
+ toggleTheme,
60
+ toggleCollapse
61
+ }
62
62
  }
@@ -1,17 +1,17 @@
1
- /**
2
- * 权限组合函数
3
- */
4
-
5
- import { computed } from 'vue'
6
- import { useUserStore } from '@/stores/user'
7
-
8
- export function useAuth() {
9
- const userStore = useUserStore()
10
-
11
- // 是否已登录
12
- const isLoggedIn = computed(() => userStore.isLoggedIn)
13
-
14
- return {
15
- isLoggedIn
16
- }
1
+ /**
2
+ * 权限组合函数
3
+ */
4
+
5
+ import { computed } from 'vue'
6
+ import { useUserStore } from '@/stores/user'
7
+
8
+ export function useAuth() {
9
+ const userStore = useUserStore()
10
+
11
+ // 是否已登录
12
+ const isLoggedIn = computed(() => userStore.isLoggedIn)
13
+
14
+ return {
15
+ isLoggedIn
16
+ }
17
17
  }
@@ -1,28 +1,28 @@
1
- /**
2
- * 权限指令
3
- * v-permission="['user:edit']" 或 v-permission="'user:edit'"
4
- * 注意:tineco-ui 不支持 permissions 字段,此指令暂时只检查登录状态
5
- */
6
-
7
- import type { Directive, DirectiveBinding } from 'vue'
8
- import { useUserStore } from '@/stores/user'
9
-
10
- const permission: Directive = {
11
- mounted(el: HTMLElement, _binding: DirectiveBinding<string | string[]>) {
12
- const userStore = useUserStore()
13
-
14
- // 如果没有登录,移除元素
15
- if (!userStore.isLoggedIn) {
16
- el.parentNode?.removeChild(el)
17
- }
18
-
19
- // 注意:tineco-ui 不支持 permissions 字段,此指令暂时不做权限判断
20
- }
21
- }
22
-
23
- export default permission
24
-
25
- // 注册指令
26
- export function setupPermissionDirective(app: any) {
27
- app.directive('permission', permission)
1
+ /**
2
+ * 权限指令
3
+ * v-permission="['user:edit']" 或 v-permission="'user:edit'"
4
+ * 注意:tineco-ui 不支持 permissions 字段,此指令暂时只检查登录状态
5
+ */
6
+
7
+ import type { Directive, DirectiveBinding } from 'vue'
8
+ import { useUserStore } from '@/stores/user'
9
+
10
+ const permission: Directive = {
11
+ mounted(el: HTMLElement, _binding: DirectiveBinding<string | string[]>) {
12
+ const userStore = useUserStore()
13
+
14
+ // 如果没有登录,移除元素
15
+ if (!userStore.isLoggedIn) {
16
+ el.parentNode?.removeChild(el)
17
+ }
18
+
19
+ // 注意:tineco-ui 不支持 permissions 字段,此指令暂时不做权限判断
20
+ }
21
+ }
22
+
23
+ export default permission
24
+
25
+ // 注册指令
26
+ export function setupPermissionDirective(app: any) {
27
+ app.directive('permission', permission)
28
28
  }
package/src/env.d.ts CHANGED
@@ -1,19 +1,19 @@
1
- /// <reference types="vite/client" />
2
-
3
- declare module '*.vue' {
4
- import type { DefineComponent } from 'vue'
5
- const component: DefineComponent<{}, {}, any>
6
- export default component
7
- }
8
-
9
- interface ImportMetaEnv {
10
- readonly VITE_APP_TITLE: string
11
- readonly VITE_API_BASE_URL: string
12
- readonly VITE_USE_MOCK: string
13
- readonly VITE_APP_ID: string
14
- readonly VITE_APP_CLIENT_ID: string
15
- }
16
-
17
- interface ImportMeta {
18
- readonly env: ImportMetaEnv
1
+ /// <reference types="vite/client" />
2
+
3
+ declare module '*.vue' {
4
+ import type { DefineComponent } from 'vue'
5
+ const component: DefineComponent<{}, {}, any>
6
+ export default component
7
+ }
8
+
9
+ interface ImportMetaEnv {
10
+ readonly VITE_APP_TITLE: string
11
+ readonly VITE_API_BASE_URL: string
12
+ readonly VITE_USE_MOCK: string
13
+ readonly VITE_APP_ID: string
14
+ readonly VITE_APP_CLIENT_ID: string
15
+ }
16
+
17
+ interface ImportMeta {
18
+ readonly env: ImportMetaEnv
19
19
  }
package/src/index.ts CHANGED
@@ -1,48 +1,48 @@
1
- // 组件
2
- export { default as Layout } from './components/Layout/index.vue'
3
- export { default as Header } from './components/Layout/Header.vue'
4
- export { default as Sidebar } from './components/Layout/Sidebar.vue'
5
- export { default as Tabs } from './components/Layout/Tabs.vue'
6
- export { default as Footer } from './components/Layout/Footer.vue'
7
-
8
- // 错误页面组件
9
- export { default as Login } from './views/login/index.vue'
10
- export { default as NotFound } from './views/error/404.vue'
11
- export { default as Forbidden } from './views/error/403.vue'
12
-
13
- // 组合式函数
14
- export * from './composables/useApp'
15
- export * from './composables/useAuth'
16
- export * from './composables/useForm'
17
- export * from './composables/useTable'
18
-
19
- // 工具函数
20
- export * from './utils/auth'
21
- export * from './utils/permission'
22
- export * from './utils/request'
23
- export * from './utils/storage'
24
- export * from './utils/config'
25
-
26
- // Store
27
- export * from './stores/app'
28
- export * from './stores/auth'
29
- export * from './stores/menu'
30
- export * from './stores/user'
31
-
32
- // 路由
33
- export { default as router, resetRouter } from './router'
34
- export * from './router/staticRoutes'
35
- export * from './router/dynamicRoutes'
36
- export { createLayoutRoute, createRouter } from './router/layoutRoute'
37
- export { setupRouterGuards } from './router/guards'
38
-
39
- // API
40
- export * from './api/auth'
41
- export * from './api/system'
42
- export * from './api/user'
43
-
44
- // 枚举
45
- export * from './enums'
46
-
47
- // 指令
1
+ // 组件
2
+ export { default as Layout } from './components/Layout/index.vue'
3
+ export { default as Header } from './components/Layout/Header.vue'
4
+ export { default as Sidebar } from './components/Layout/Sidebar.vue'
5
+ export { default as Tabs } from './components/Layout/Tabs.vue'
6
+ export { default as Footer } from './components/Layout/Footer.vue'
7
+
8
+ // 错误页面组件
9
+ export { default as Login } from './views/login/index.vue'
10
+ export { default as NotFound } from './views/error/404.vue'
11
+ export { default as Forbidden } from './views/error/403.vue'
12
+
13
+ // 组合式函数
14
+ export * from './composables/useApp'
15
+ export * from './composables/useAuth'
16
+ export * from './composables/useForm'
17
+ export * from './composables/useTable'
18
+
19
+ // 工具函数
20
+ export * from './utils/auth'
21
+ export * from './utils/permission'
22
+ export * from './utils/request'
23
+ export * from './utils/storage'
24
+ export * from './utils/config'
25
+
26
+ // Store
27
+ export * from './stores/app'
28
+ export * from './stores/auth'
29
+ export * from './stores/menu'
30
+ export * from './stores/user'
31
+
32
+ // 路由
33
+ export { default as router, resetRouter } from './router'
34
+ export * from './router/staticRoutes'
35
+ export * from './router/dynamicRoutes'
36
+ export { createLayoutRoute, createRouter } from './router/layoutRoute'
37
+ export { setupRouterGuards } from './router/guards'
38
+
39
+ // API
40
+ export * from './api/auth'
41
+ export * from './api/system'
42
+ export * from './api/user'
43
+
44
+ // 枚举
45
+ export * from './enums'
46
+
47
+ // 指令
48
48
  export { default as permissionDirective } from './directives/permission'