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,80 +1,80 @@
1
- /**
2
- * 路由配置
3
- */
4
-
5
- import { createRouter, createWebHistory } from 'vue-router'
6
- import { staticRoutes, errorRoute } from './staticRoutes'
7
- import { layoutRoute } from './dynamicRoutes'
8
- import { hasToken } from '@/utils/auth'
9
- import { getAppId } from '@/utils/config'
10
- import { useUserStore } from '@/stores/user'
11
- import { useMenuStore } from '@/stores/menu'
12
- import { useAppStore } from '@/stores/app'
13
- import { mockMenuData } from './dynamicRoutes'
14
-
15
- const router = createRouter({
16
- history: createWebHistory(),
17
- routes: [...staticRoutes, layoutRoute, errorRoute],
18
- scrollBehavior: () => ({ left: 0, top: 0 })
19
- })
20
-
21
- // 白名单路由
22
- const whiteList = ['/login', '/404', '/403']
23
-
24
- // 路由守卫
25
- router.beforeEach(async (to, _from, next) => {
26
- const appStore = useAppStore()
27
-
28
- // 初始化主题
29
- appStore.initTheme()
30
-
31
- // 已登录
32
- if (hasToken()) {
33
- if (to.path === '/login') {
34
- // 已登录,跳转到首页
35
- next({ path: '/' })
36
- } else {
37
- // 设置用户信息(如果未设置)
38
- const userStore = useUserStore()
39
- if (!userStore.isLoggedIn) {
40
- userStore.setUserInfo({
41
- appId: getAppId(),
42
- userId: '1',
43
- userName: '管理员',
44
- departmentName: '技术部',
45
- email: 'admin@example.com',
46
- mobilePhone: '13800138000',
47
- positionName: '管理员',
48
- avatar: ''
49
- })
50
-
51
- // 设置菜单
52
- const menuStore = useMenuStore()
53
- menuStore.setMenuList(mockMenuData)
54
- }
55
-
56
- // 添加缓存页面
57
- if (to.name && to.meta.keepAlive) {
58
- appStore.addCachedView(to.name as string)
59
- }
60
- next()
61
- }
62
- } else {
63
- // 未登录
64
- if (whiteList.includes(to.path)) {
65
- next()
66
- } else {
67
- next('/login')
68
- }
69
- }
70
- })
71
-
72
- export function resetRouter() {
73
- const newRouter = createRouter({
74
- history: createWebHistory(),
75
- routes: [...staticRoutes, layoutRoute, errorRoute]
76
- })
77
- ;(router as any).matcher = (newRouter as any).matcher
78
- }
79
-
1
+ /**
2
+ * 路由配置
3
+ */
4
+
5
+ import { createRouter, createWebHistory } from 'vue-router'
6
+ import { staticRoutes, errorRoute } from './staticRoutes'
7
+ import { layoutRoute } from './dynamicRoutes'
8
+ import { hasToken } from '@/utils/auth'
9
+ import { getAppId } from '@/utils/config'
10
+ import { useUserStore } from '@/stores/user'
11
+ import { useMenuStore } from '@/stores/menu'
12
+ import { useAppStore } from '@/stores/app'
13
+ import { mockMenuData } from './dynamicRoutes'
14
+
15
+ const router = createRouter({
16
+ history: createWebHistory(),
17
+ routes: [...staticRoutes, layoutRoute, errorRoute],
18
+ scrollBehavior: () => ({ left: 0, top: 0 })
19
+ })
20
+
21
+ // 白名单路由
22
+ const whiteList = ['/login', '/404', '/403']
23
+
24
+ // 路由守卫
25
+ router.beforeEach(async (to, _from, next) => {
26
+ const appStore = useAppStore()
27
+
28
+ // 初始化主题
29
+ appStore.initTheme()
30
+
31
+ // 已登录
32
+ if (hasToken()) {
33
+ if (to.path === '/login') {
34
+ // 已登录,跳转到首页
35
+ next({ path: '/' })
36
+ } else {
37
+ // 设置用户信息(如果未设置)
38
+ const userStore = useUserStore()
39
+ if (!userStore.isLoggedIn) {
40
+ userStore.setUserInfo({
41
+ appId: getAppId(),
42
+ userId: '1',
43
+ userName: '管理员',
44
+ departmentName: '技术部',
45
+ email: 'admin@example.com',
46
+ mobilePhone: '13800138000',
47
+ positionName: '管理员',
48
+ avatar: ''
49
+ })
50
+
51
+ // 设置菜单
52
+ const menuStore = useMenuStore()
53
+ menuStore.setMenuList(mockMenuData)
54
+ }
55
+
56
+ // 添加缓存页面
57
+ if (to.name && to.meta.keepAlive) {
58
+ appStore.addCachedView(to.name as string)
59
+ }
60
+ next()
61
+ }
62
+ } else {
63
+ // 未登录
64
+ if (whiteList.includes(to.path)) {
65
+ next()
66
+ } else {
67
+ next('/login')
68
+ }
69
+ }
70
+ })
71
+
72
+ export function resetRouter() {
73
+ const newRouter = createRouter({
74
+ history: createWebHistory(),
75
+ routes: [...staticRoutes, layoutRoute, errorRoute]
76
+ })
77
+ ;(router as any).matcher = (newRouter as any).matcher
78
+ }
79
+
80
80
  export default router
@@ -1,66 +1,66 @@
1
- /**
2
- * 认证状态
3
- */
4
-
5
- import { defineStore } from 'pinia'
6
- import { ref, computed } from 'vue'
7
- import { getToken, clearToken, setTokenInfo, hasToken, type TokenInfo } from '@/utils/auth'
8
-
9
- export const useAuthStore = defineStore('auth', () => {
10
- // 状态
11
- const token = ref<string | null>(getToken())
12
- const isLoggedIn = computed(() => hasToken())
13
-
14
- // 应用配置
15
- const baseUrl = ref<string>('')
16
- const appId = ref<string>('')
17
- const clientId = ref<string>('')
18
- const loginPath = ref<string>('/login')
19
-
20
- // 设置 token(参考 tineco-ui)
21
- const login = (tokenInfo: TokenInfo) => {
22
- token.value = tokenInfo.access_token
23
- setTokenInfo(tokenInfo)
24
- }
25
-
26
- // 登出
27
- const logout = () => {
28
- token.value = null
29
- clearToken()
30
- }
31
-
32
- // 设置 API 基础路径
33
- const setBaseUrl = (url: string) => {
34
- baseUrl.value = url
35
- }
36
-
37
- // 设置应用 ID
38
- const setAppId = (id: string) => {
39
- appId.value = id
40
- }
41
-
42
- // 设置客户端 ID
43
- const setClientId = (id: string) => {
44
- clientId.value = id
45
- }
46
-
47
- // 设置登录页路径
48
- const setLoginPath = (path: string) => {
49
- loginPath.value = path
50
- }
51
-
52
- return {
53
- token,
54
- isLoggedIn,
55
- baseUrl,
56
- appId,
57
- clientId,
58
- loginPath,
59
- login,
60
- logout,
61
- setBaseUrl,
62
- setAppId,
63
- setClientId,
64
- setLoginPath
65
- }
1
+ /**
2
+ * 认证状态
3
+ */
4
+
5
+ import { defineStore } from 'pinia'
6
+ import { ref, computed } from 'vue'
7
+ import { getToken, clearToken, setTokenInfo, hasToken, type TokenInfo } from '@/utils/auth'
8
+
9
+ export const useAuthStore = defineStore('auth', () => {
10
+ // 状态
11
+ const token = ref<string | null>(getToken())
12
+ const isLoggedIn = computed(() => hasToken())
13
+
14
+ // 应用配置
15
+ const baseUrl = ref<string>('')
16
+ const appId = ref<string>('')
17
+ const clientId = ref<string>('')
18
+ const loginPath = ref<string>('/login')
19
+
20
+ // 设置 token(参考 tineco-ui)
21
+ const login = (tokenInfo: TokenInfo) => {
22
+ token.value = tokenInfo.access_token
23
+ setTokenInfo(tokenInfo)
24
+ }
25
+
26
+ // 登出
27
+ const logout = () => {
28
+ token.value = null
29
+ clearToken()
30
+ }
31
+
32
+ // 设置 API 基础路径
33
+ const setBaseUrl = (url: string) => {
34
+ baseUrl.value = url
35
+ }
36
+
37
+ // 设置应用 ID
38
+ const setAppId = (id: string) => {
39
+ appId.value = id
40
+ }
41
+
42
+ // 设置客户端 ID
43
+ const setClientId = (id: string) => {
44
+ clientId.value = id
45
+ }
46
+
47
+ // 设置登录页路径
48
+ const setLoginPath = (path: string) => {
49
+ loginPath.value = path
50
+ }
51
+
52
+ return {
53
+ token,
54
+ isLoggedIn,
55
+ baseUrl,
56
+ appId,
57
+ clientId,
58
+ loginPath,
59
+ login,
60
+ logout,
61
+ setBaseUrl,
62
+ setAppId,
63
+ setClientId,
64
+ setLoginPath
65
+ }
66
66
  })
@@ -1,49 +1,49 @@
1
- /**
2
- * 菜单状态
3
- */
4
-
5
- import { defineStore } from 'pinia'
6
- import { ref, computed } from 'vue'
7
- import type { MenuItem } from '@/types/api'
8
- import { local } from '@/utils/storage'
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
- }
22
-
23
- export const useMenuStore = defineStore('menu', () => {
24
- // 状态
25
- const menuList = ref<MenuItem[]>(local.get<MenuItem[]>(MENU_LIST_KEY) || [])
26
-
27
- // 计算属性
28
- const hasMenu = computed(() => menuList.value.length > 0)
29
-
30
- // 设置菜单
31
- const setMenuList = (menus: MenuItem[]) => {
32
- // 添加首页菜单到开头
33
- menuList.value = [indexMenu, ...menus]
34
- local.set(MENU_LIST_KEY, menuList.value)
35
- }
36
-
37
- // 清除菜单
38
- const clearMenu = () => {
39
- menuList.value = []
40
- local.remove(MENU_LIST_KEY)
41
- }
42
-
43
- return {
44
- menuList,
45
- hasMenu,
46
- setMenuList,
47
- clearMenu
48
- }
1
+ /**
2
+ * 菜单状态
3
+ */
4
+
5
+ import { defineStore } from 'pinia'
6
+ import { ref, computed } from 'vue'
7
+ import type { MenuItem } from '@/types/api'
8
+ import { local } from '@/utils/storage'
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
+ }
22
+
23
+ export const useMenuStore = defineStore('menu', () => {
24
+ // 状态
25
+ const menuList = ref<MenuItem[]>(local.get<MenuItem[]>(MENU_LIST_KEY) || [])
26
+
27
+ // 计算属性
28
+ const hasMenu = computed(() => menuList.value.length > 0)
29
+
30
+ // 设置菜单
31
+ const setMenuList = (menus: MenuItem[]) => {
32
+ // 添加首页菜单到开头
33
+ menuList.value = [indexMenu, ...menus]
34
+ local.set(MENU_LIST_KEY, menuList.value)
35
+ }
36
+
37
+ // 清除菜单
38
+ const clearMenu = () => {
39
+ menuList.value = []
40
+ local.remove(MENU_LIST_KEY)
41
+ }
42
+
43
+ return {
44
+ menuList,
45
+ hasMenu,
46
+ setMenuList,
47
+ clearMenu
48
+ }
49
49
  })
@@ -1,51 +1,51 @@
1
- /**
2
- * 用户状态
3
- */
4
-
5
- import { defineStore } from 'pinia'
6
- import { ref, computed } from 'vue'
7
- import type { UserInfo } from '@/types/api'
8
- import { local } from '@/utils/storage'
9
-
10
- const USER_INFO_KEY = 'user_info'
11
-
12
- export const useUserStore = defineStore('user', () => {
13
- // 状态
14
- const userInfo = ref<UserInfo | null>(local.get<UserInfo>(USER_INFO_KEY))
15
-
16
- // 计算属性
17
- const isLoggedIn = computed(() => !!userInfo.value)
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 || '')
24
- const avatar = computed(() => userInfo.value?.avatar || '')
25
-
26
- // 设置用户信息
27
- const setUserInfo = (info: UserInfo) => {
28
- userInfo.value = info
29
- local.set(USER_INFO_KEY, info)
30
- }
31
-
32
- // 清除用户信息
33
- const clearUserInfo = () => {
34
- userInfo.value = null
35
- local.remove(USER_INFO_KEY)
36
- }
37
-
38
- return {
39
- userInfo,
40
- isLoggedIn,
41
- userId,
42
- userName,
43
- departmentName,
44
- email,
45
- mobilePhone,
46
- positionName,
47
- avatar,
48
- setUserInfo,
49
- clearUserInfo
50
- }
1
+ /**
2
+ * 用户状态
3
+ */
4
+
5
+ import { defineStore } from 'pinia'
6
+ import { ref, computed } from 'vue'
7
+ import type { UserInfo } from '@/types/api'
8
+ import { local } from '@/utils/storage'
9
+
10
+ const USER_INFO_KEY = 'user_info'
11
+
12
+ export const useUserStore = defineStore('user', () => {
13
+ // 状态
14
+ const userInfo = ref<UserInfo | null>(local.get<UserInfo>(USER_INFO_KEY))
15
+
16
+ // 计算属性
17
+ const isLoggedIn = computed(() => !!userInfo.value)
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 || '')
24
+ const avatar = computed(() => userInfo.value?.avatar || '')
25
+
26
+ // 设置用户信息
27
+ const setUserInfo = (info: UserInfo) => {
28
+ userInfo.value = info
29
+ local.set(USER_INFO_KEY, info)
30
+ }
31
+
32
+ // 清除用户信息
33
+ const clearUserInfo = () => {
34
+ userInfo.value = null
35
+ local.remove(USER_INFO_KEY)
36
+ }
37
+
38
+ return {
39
+ userInfo,
40
+ isLoggedIn,
41
+ userId,
42
+ userName,
43
+ departmentName,
44
+ email,
45
+ mobilePhone,
46
+ positionName,
47
+ avatar,
48
+ setUserInfo,
49
+ clearUserInfo
50
+ }
51
51
  })
@@ -1,81 +1,81 @@
1
- /**
2
- * API 通用类型定义
3
- */
4
-
5
- // 基础响应
6
- export interface ApiResponse<T = unknown> {
7
- code: number
8
- data: T
9
- message: string
10
- }
11
-
12
- // 分页请求参数
13
- export interface PageParams {
14
- page: number
15
- pageSize: number
16
- [key: string]: unknown
17
- }
18
-
19
- // 分页响应
20
- export interface PageResponse<T> {
21
- list: T[]
22
- total: number
23
- page: number
24
- pageSize: number
25
- }
26
-
27
- // 用户信息(参考 tineco-ui)
28
- export interface UserInfo {
29
- appId: string
30
- userId: string
31
- userName: string
32
- departmentName?: string
33
- email?: string
34
- mobilePhone?: string
35
- positionName?: string
36
- avatar?: string
37
- }
38
-
39
- // 登录请求参数(参考 tineco-ui)
40
- export interface LoginParams {
41
- appId: string
42
- clientId: string
43
- uid: string
44
- password: string
45
- code?: boolean
46
- }
47
-
48
- // 登录响应(参考 tineco-ui)
49
- export interface LoginResult {
50
- access_token: string
51
- token_type: string
52
- refresh_token: string
53
- expires_time: number
54
- refresh_time: number
55
- code?: string
56
- }
57
-
58
- // 菜单项(参考 tineco-ui)
59
- export interface MenuItem {
60
- menuCode: string
61
- menuName: string
62
- menuUrl: string
63
- icon?: string
64
- closable?: boolean
65
- isDefault?: boolean
66
- isOut?: boolean
67
- type?: number // 1 为按钮,其他为菜单
68
- children?: MenuItem[]
69
- }
70
-
71
- // 角色信息
72
- export interface RoleInfo {
73
- id: number | string
74
- name: string
75
- code: string
76
- description?: string
77
- status: number
78
- permissions: string[]
79
- createTime?: string
80
- updateTime?: string
1
+ /**
2
+ * API 通用类型定义
3
+ */
4
+
5
+ // 基础响应
6
+ export interface ApiResponse<T = unknown> {
7
+ code: number
8
+ data: T
9
+ message: string
10
+ }
11
+
12
+ // 分页请求参数
13
+ export interface PageParams {
14
+ page: number
15
+ pageSize: number
16
+ [key: string]: unknown
17
+ }
18
+
19
+ // 分页响应
20
+ export interface PageResponse<T> {
21
+ list: T[]
22
+ total: number
23
+ page: number
24
+ pageSize: number
25
+ }
26
+
27
+ // 用户信息(参考 tineco-ui)
28
+ export interface UserInfo {
29
+ appId: string
30
+ userId: string
31
+ userName: string
32
+ departmentName?: string
33
+ email?: string
34
+ mobilePhone?: string
35
+ positionName?: string
36
+ avatar?: string
37
+ }
38
+
39
+ // 登录请求参数(参考 tineco-ui)
40
+ export interface LoginParams {
41
+ appId: string
42
+ clientId: string
43
+ uid: string
44
+ password: string
45
+ code?: boolean
46
+ }
47
+
48
+ // 登录响应(参考 tineco-ui)
49
+ export interface LoginResult {
50
+ access_token: string
51
+ token_type: string
52
+ refresh_token: string
53
+ expires_time: number
54
+ refresh_time: number
55
+ code?: string
56
+ }
57
+
58
+ // 菜单项(参考 tineco-ui)
59
+ export interface MenuItem {
60
+ menuCode: string
61
+ menuName: string
62
+ menuUrl: string
63
+ icon?: string
64
+ closable?: boolean
65
+ isDefault?: boolean
66
+ isOut?: boolean
67
+ type?: number // 1 为按钮,其他为菜单
68
+ children?: MenuItem[]
69
+ }
70
+
71
+ // 角色信息
72
+ export interface RoleInfo {
73
+ id: number | string
74
+ name: string
75
+ code: string
76
+ description?: string
77
+ status: number
78
+ permissions: string[]
79
+ createTime?: string
80
+ updateTime?: string
81
81
  }