xto-fronted 0.4.89 → 0.4.91
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/dist/assets/404-Bq0LY5Cd.js +1 -0
- package/dist/assets/404-Cw_4ZCL6.css +1 -0
- package/dist/assets/{index-BDgOY6Rp.js → index-7ZZxpSfk.js} +1 -1
- package/dist/assets/index-BJUe8VUp.js +1 -0
- package/dist/assets/{index-Bz0BgZQ1.js → index-BlOR_ICg.js} +1 -1
- package/dist/assets/index-BlRslYYI.css +1 -0
- package/dist/assets/index-BudArKxR.css +1 -0
- package/dist/assets/{index-CwRA10ac.js → index-BzbOWBCV.js} +1 -1
- package/dist/assets/index-CFhWBbxk.css +1 -0
- package/dist/assets/{index-CfpZmcpk.css → index-CH6aTfYg.css} +1 -1
- package/dist/assets/{index-BIoRANs0.js → index-CT5f37nN.js} +1 -1
- package/dist/assets/index-Ce-kjtEM.js +2 -0
- package/dist/assets/{index-t-2Y0KhA.css → index-Cpew6d-v.css} +1 -1
- package/dist/assets/index-DkkuYBgT.css +1 -0
- package/dist/assets/index-vfvEFrCH.css +1 -0
- package/dist/assets/{index-CwJSA85U.js → index-wVLLAoVp.js} +1 -1
- package/dist/assets/vendor-DZmPBJ9d.js +16 -0
- package/dist/assets/vue-vendor-DjmFuEnG.js +29 -0
- package/dist/assets/{xto-base-PwLGsxxb.js → xto-base-B5HYOo6i.js} +1 -1
- package/dist/assets/{xto-core-CtL4zKiV.js → xto-core-DZYp_YAR.js} +1 -1
- package/dist/assets/{xto-data-bCXQa7fT.js → xto-data-ogck6x_i.js} +1 -1
- package/dist/assets/{xto-feedback-CPydp0kn.js → xto-feedback-C0-6cAL6.js} +1 -1
- package/dist/assets/{xto-form-bywohdAf.js → xto-form-IDg_78Vf.js} +1 -1
- package/dist/assets/{xto-navigation-Bbdpine9.js → xto-navigation-CPYLzfu7.js} +1 -1
- package/dist/index.html +9 -9
- package/package.json +91 -91
- package/src/App.vue +48 -48
- package/src/assets/styles/_dark.scss +639 -572
- package/src/assets/styles/_root.scss +183 -183
- package/src/assets/styles/_variables.scss +69 -69
- package/src/assets/styles/index.scss +460 -460
- package/src/components/Layout/Sidebar.vue +198 -198
- package/src/components/Layout/TopMenu.vue +1170 -1170
- package/src/components/Layout/index.vue +192 -192
- package/src/directives/permission.ts +12 -3
- package/src/index.ts +100 -100
- package/src/router/layoutRoute.ts +59 -59
- package/src/stores/menu.ts +64 -3
- package/src/types/json-bigint.d.ts +18 -18
- package/src/utils/permission.ts +12 -5
- package/src/utils/request.ts +184 -164
- package/src/views/dashboard/index.vue +545 -545
- package/src/views/error/403.vue +251 -251
- package/src/views/error/404.vue +253 -253
- package/src/views/login/index.vue +586 -586
- package/src/views/system/menu/index.vue +690 -690
- package/src/views/system/role/index.vue +583 -583
- package/src/views/system/user/index.vue +655 -655
- package/dist/App.vue.d.ts +0 -2
- package/dist/api/auth.d.ts +0 -8
- package/dist/api/system.d.ts +0 -16
- package/dist/api/user.d.ts +0 -13
- package/dist/assets/404-C9Uh6Uu-.css +0 -1
- package/dist/assets/404-zjGLLssH.js +0 -1
- package/dist/assets/index-B5xc4gQB.css +0 -1
- package/dist/assets/index-CAdztNsv.css +0 -1
- package/dist/assets/index-CCXrcISf.css +0 -1
- package/dist/assets/index-D8NDxq9d.js +0 -1
- package/dist/assets/index-DEB6-Iv_.js +0 -2
- package/dist/assets/index-DM4Ezclc.css +0 -1
- package/dist/assets/index-DYv7nImj.css +0 -1
- package/dist/assets/vendor-CUVPinTg.js +0 -13
- package/dist/assets/vue-vendor-DeJXJVbN.js +0 -29
- package/dist/components/Layout/Footer.vue.d.ts +0 -2
- package/dist/components/Layout/Header.vue.d.ts +0 -5
- package/dist/components/Layout/MixTopMenu.vue.d.ts +0 -5
- package/dist/components/Layout/Sidebar.vue.d.ts +0 -11
- package/dist/components/Layout/SidebarMenuItem.vue.d.ts +0 -5
- package/dist/components/Layout/Tabs.vue.d.ts +0 -2
- package/dist/components/Layout/TopMenu.vue.d.ts +0 -5
- package/dist/components/Layout/index.vue.d.ts +0 -2
- package/dist/composables/useApp.d.ts +0 -29
- package/dist/composables/useAuth.d.ts +0 -6
- package/dist/composables/useForm.d.ts +0 -20
- package/dist/composables/useI18n.d.ts +0 -30
- package/dist/composables/useTable.d.ts +0 -29
- package/dist/directives/permission.d.ts +0 -4
- package/dist/enums/index.d.ts +0 -32
- package/dist/index-BRvi9qW-.js +0 -515
- package/dist/index-BVGW4DDQ.js +0 -189
- package/dist/index-Bmf0YbVq.js +0 -189
- package/dist/index-C2-a5KSQ.js +0 -4233
- package/dist/index-CeZ0CSSs.js +0 -641
- package/dist/index-D25KzR0I.js +0 -479
- package/dist/index-DEYOivza.js +0 -641
- package/dist/index-DReodgBw.js +0 -4233
- package/dist/index-DjERNRXX.js +0 -515
- package/dist/index-gBlRG4kk.js +0 -479
- package/dist/index.d.ts +0 -59
- package/dist/index.es.js +0 -94
- package/dist/index.umd.js +0 -8
- package/dist/main.d.ts +0 -0
- package/dist/router/dynamicRoutes.d.ts +0 -30
- package/dist/router/guards.d.ts +0 -17
- package/dist/router/index.d.ts +0 -6
- package/dist/router/layoutRoute.d.ts +0 -22
- package/dist/router/staticRoutes.d.ts +0 -2
- package/dist/stores/app.d.ts +0 -93
- package/dist/stores/auth.d.ts +0 -41
- package/dist/stores/index.d.ts +0 -10
- package/dist/stores/locale.d.ts +0 -42
- package/dist/stores/menu.d.ts +0 -77
- package/dist/stores/user.d.ts +0 -92
- package/dist/style.css +0 -1
- package/dist/utils/auth.d.ts +0 -27
- package/dist/utils/config.d.ts +0 -30
- package/dist/utils/permission.d.ts +0 -18
- package/dist/utils/request.d.ts +0 -24
- package/dist/utils/storage.d.ts +0 -24
- package/dist/views/dashboard/index.vue.d.ts +0 -2
- package/dist/views/error/403.vue.d.ts +0 -2
- package/dist/views/error/404.vue.d.ts +0 -2
- package/dist/views/login/index.vue.d.ts +0 -4
- package/dist/views/system/menu/index.vue.d.ts +0 -4
- package/dist/views/system/role/index.vue.d.ts +0 -4
- package/dist/views/system/user/index.vue.d.ts +0 -4
|
@@ -1,193 +1,193 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
3
|
-
import { useAppStore } from '@/stores/app'
|
|
4
|
-
import { useMenuStore } from '@/stores/menu'
|
|
5
|
-
import Sidebar from './Sidebar.vue'
|
|
6
|
-
import Header from './Header.vue'
|
|
7
|
-
import TopMenu from './TopMenu.vue'
|
|
8
|
-
import MixTopMenu from './MixTopMenu.vue'
|
|
9
|
-
|
|
10
|
-
const appStore = useAppStore()
|
|
11
|
-
const menuStore = useMenuStore()
|
|
12
|
-
|
|
13
|
-
const sidebarWidth = computed(() =>
|
|
14
|
-
appStore.isCollapsed ? '64px' : '210px'
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
// 布局模式
|
|
18
|
-
const layoutMode = computed(() => appStore.layout)
|
|
19
|
-
|
|
20
|
-
// 是否显示混合模式(mix模式)
|
|
21
|
-
const isMixMode = computed(() => layoutMode.value === 'mix')
|
|
22
|
-
|
|
23
|
-
// 左侧菜单数据
|
|
24
|
-
// sidebar模式:显示全部菜单
|
|
25
|
-
// mix模式:显示当前选中一级菜单的子菜单
|
|
26
|
-
const sidebarMenuList = computed(() => {
|
|
27
|
-
if (layoutMode.value === 'sidebar') {
|
|
28
|
-
return menuStore.menuList
|
|
29
|
-
} else if (layoutMode.value === 'mix') {
|
|
30
|
-
// mix模式下显示当前选中一级菜单的子菜单
|
|
31
|
-
return appStore.mixSubMenus
|
|
32
|
-
}
|
|
33
|
-
return []
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
// mix模式下是否显示左侧菜单(有子菜单时才显示)
|
|
37
|
-
const showMixSidebar = computed(() => {
|
|
38
|
-
if (!isMixMode.value) return false
|
|
39
|
-
return sidebarMenuList.value.length > 0
|
|
40
|
-
})
|
|
41
|
-
</script>
|
|
42
|
-
|
|
43
|
-
<template>
|
|
44
|
-
<!-- sidebar模式:左侧菜单 + 顶部Header + 主内容 -->
|
|
45
|
-
<div v-if="layoutMode === 'sidebar'" class="layout layout--sidebar">
|
|
46
|
-
<aside class="layout__aside" :style="{ width: sidebarWidth }">
|
|
47
|
-
<Sidebar :menu-list="sidebarMenuList" :show-logo="true" :show-user="true" />
|
|
48
|
-
</aside>
|
|
49
|
-
<div class="layout__main">
|
|
50
|
-
<header class="layout__header">
|
|
51
|
-
<Header />
|
|
52
|
-
</header>
|
|
53
|
-
<main class="layout__content">
|
|
54
|
-
<router-view />
|
|
55
|
-
</main>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
|
|
59
|
-
<!-- top模式:顶部菜单 + 主内容 -->
|
|
60
|
-
<div v-if="layoutMode === 'top'" class="layout layout--top">
|
|
61
|
-
<div class="layout__top-menu">
|
|
62
|
-
<TopMenu />
|
|
63
|
-
</div>
|
|
64
|
-
<div class="layout__main">
|
|
65
|
-
<main class="layout__content">
|
|
66
|
-
<router-view />
|
|
67
|
-
</main>
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
<!-- mix模式:顶部一级菜单 + (左侧子菜单 + 主内容) -->
|
|
72
|
-
<div v-if="layoutMode === 'mix'" class="layout layout--mix">
|
|
73
|
-
<!-- 顶部一级菜单 -->
|
|
74
|
-
<div class="layout__mix-top-menu">
|
|
75
|
-
<MixTopMenu />
|
|
76
|
-
</div>
|
|
77
|
-
<!-- 下方:左侧子菜单 + 主内容 -->
|
|
78
|
-
<div class="layout__mix-body">
|
|
79
|
-
<aside v-if="showMixSidebar" class="layout__aside" :style="{ width: sidebarWidth }">
|
|
80
|
-
<Sidebar :menu-list="sidebarMenuList" :show-logo="false" :show-user="false" />
|
|
81
|
-
</aside>
|
|
82
|
-
<main class="layout__content">
|
|
83
|
-
<router-view />
|
|
84
|
-
</main>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
</template>
|
|
88
|
-
|
|
89
|
-
<style lang="scss" scoped>
|
|
90
|
-
.layout {
|
|
91
|
-
display: flex;
|
|
92
|
-
width: 100%;
|
|
93
|
-
height: 100%;
|
|
94
|
-
|
|
95
|
-
// 左侧菜单模式
|
|
96
|
-
&--sidebar {
|
|
97
|
-
flex-direction: row;
|
|
98
|
-
|
|
99
|
-
.layout__aside {
|
|
100
|
-
height: 100%;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.layout__main {
|
|
104
|
-
flex: 1;
|
|
105
|
-
display: flex;
|
|
106
|
-
flex-direction: column;
|
|
107
|
-
height: 100%;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// 顶部菜单模式
|
|
112
|
-
&--top {
|
|
113
|
-
flex-direction: column;
|
|
114
|
-
|
|
115
|
-
.layout__main {
|
|
116
|
-
flex: 1;
|
|
117
|
-
display: flex;
|
|
118
|
-
flex-direction: column;
|
|
119
|
-
height: calc(100% - 50px);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.layout__content {
|
|
123
|
-
flex: 1;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// 混合菜单模式
|
|
128
|
-
&--mix {
|
|
129
|
-
flex-direction: column;
|
|
130
|
-
|
|
131
|
-
.layout__mix-top-menu {
|
|
132
|
-
width: 100%;
|
|
133
|
-
height: 50px;
|
|
134
|
-
background-color: var(--bg-color);
|
|
135
|
-
border-bottom: 1px solid var(--color-border-lighter);
|
|
136
|
-
flex-shrink: 0;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.layout__mix-body {
|
|
140
|
-
flex: 1;
|
|
141
|
-
display: flex;
|
|
142
|
-
flex-direction: row;
|
|
143
|
-
height: calc(100% - 50px);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
&__aside {
|
|
148
|
-
transition: width 0.3s;
|
|
149
|
-
overflow: hidden;
|
|
150
|
-
flex-shrink: 0;
|
|
151
|
-
height: 100%;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
&__top-menu {
|
|
155
|
-
width: 100%;
|
|
156
|
-
height: 50px;
|
|
157
|
-
box-sizing: border-box;
|
|
158
|
-
background-color: var(--bg-color);
|
|
159
|
-
border-bottom: 1px solid var(--color-border-lighter);
|
|
160
|
-
flex-shrink: 0;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
&__mix-top-menu {
|
|
164
|
-
width: 100%;
|
|
165
|
-
height: 50px;
|
|
166
|
-
box-sizing: border-box;
|
|
167
|
-
flex-shrink: 0;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
&__main {
|
|
171
|
-
flex: 1;
|
|
172
|
-
display: flex;
|
|
173
|
-
flex-direction: column;
|
|
174
|
-
overflow: hidden;
|
|
175
|
-
height: 100%;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
&__header {
|
|
179
|
-
height: 50px;
|
|
180
|
-
box-sizing: border-box;
|
|
181
|
-
background-color: var(--bg-color);
|
|
182
|
-
border-bottom: 1px solid var(--color-border-lighter);
|
|
183
|
-
flex-shrink: 0;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
&__content {
|
|
187
|
-
flex: 1;
|
|
188
|
-
overflow: auto;
|
|
189
|
-
background-color: var(--bg-color-page);
|
|
190
|
-
padding: 0;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useAppStore } from '@/stores/app'
|
|
4
|
+
import { useMenuStore } from '@/stores/menu'
|
|
5
|
+
import Sidebar from './Sidebar.vue'
|
|
6
|
+
import Header from './Header.vue'
|
|
7
|
+
import TopMenu from './TopMenu.vue'
|
|
8
|
+
import MixTopMenu from './MixTopMenu.vue'
|
|
9
|
+
|
|
10
|
+
const appStore = useAppStore()
|
|
11
|
+
const menuStore = useMenuStore()
|
|
12
|
+
|
|
13
|
+
const sidebarWidth = computed(() =>
|
|
14
|
+
appStore.isCollapsed ? '64px' : '210px'
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
// 布局模式
|
|
18
|
+
const layoutMode = computed(() => appStore.layout)
|
|
19
|
+
|
|
20
|
+
// 是否显示混合模式(mix模式)
|
|
21
|
+
const isMixMode = computed(() => layoutMode.value === 'mix')
|
|
22
|
+
|
|
23
|
+
// 左侧菜单数据
|
|
24
|
+
// sidebar模式:显示全部菜单
|
|
25
|
+
// mix模式:显示当前选中一级菜单的子菜单
|
|
26
|
+
const sidebarMenuList = computed(() => {
|
|
27
|
+
if (layoutMode.value === 'sidebar') {
|
|
28
|
+
return menuStore.menuList
|
|
29
|
+
} else if (layoutMode.value === 'mix') {
|
|
30
|
+
// mix模式下显示当前选中一级菜单的子菜单
|
|
31
|
+
return appStore.mixSubMenus
|
|
32
|
+
}
|
|
33
|
+
return []
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// mix模式下是否显示左侧菜单(有子菜单时才显示)
|
|
37
|
+
const showMixSidebar = computed(() => {
|
|
38
|
+
if (!isMixMode.value) return false
|
|
39
|
+
return sidebarMenuList.value.length > 0
|
|
40
|
+
})
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<!-- sidebar模式:左侧菜单 + 顶部Header + 主内容 -->
|
|
45
|
+
<div v-if="layoutMode === 'sidebar'" class="layout layout--sidebar">
|
|
46
|
+
<aside class="layout__aside" :style="{ width: sidebarWidth }">
|
|
47
|
+
<Sidebar :menu-list="sidebarMenuList" :show-logo="true" :show-user="true" />
|
|
48
|
+
</aside>
|
|
49
|
+
<div class="layout__main">
|
|
50
|
+
<header class="layout__header">
|
|
51
|
+
<Header />
|
|
52
|
+
</header>
|
|
53
|
+
<main class="layout__content">
|
|
54
|
+
<router-view />
|
|
55
|
+
</main>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<!-- top模式:顶部菜单 + 主内容 -->
|
|
60
|
+
<div v-if="layoutMode === 'top'" class="layout layout--top">
|
|
61
|
+
<div class="layout__top-menu">
|
|
62
|
+
<TopMenu />
|
|
63
|
+
</div>
|
|
64
|
+
<div class="layout__main">
|
|
65
|
+
<main class="layout__content">
|
|
66
|
+
<router-view />
|
|
67
|
+
</main>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<!-- mix模式:顶部一级菜单 + (左侧子菜单 + 主内容) -->
|
|
72
|
+
<div v-if="layoutMode === 'mix'" class="layout layout--mix">
|
|
73
|
+
<!-- 顶部一级菜单 -->
|
|
74
|
+
<div class="layout__mix-top-menu">
|
|
75
|
+
<MixTopMenu />
|
|
76
|
+
</div>
|
|
77
|
+
<!-- 下方:左侧子菜单 + 主内容 -->
|
|
78
|
+
<div class="layout__mix-body">
|
|
79
|
+
<aside v-if="showMixSidebar" class="layout__aside" :style="{ width: sidebarWidth }">
|
|
80
|
+
<Sidebar :menu-list="sidebarMenuList" :show-logo="false" :show-user="false" />
|
|
81
|
+
</aside>
|
|
82
|
+
<main class="layout__content">
|
|
83
|
+
<router-view />
|
|
84
|
+
</main>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</template>
|
|
88
|
+
|
|
89
|
+
<style lang="scss" scoped>
|
|
90
|
+
.layout {
|
|
91
|
+
display: flex;
|
|
92
|
+
width: 100%;
|
|
93
|
+
height: 100%;
|
|
94
|
+
|
|
95
|
+
// 左侧菜单模式
|
|
96
|
+
&--sidebar {
|
|
97
|
+
flex-direction: row;
|
|
98
|
+
|
|
99
|
+
.layout__aside {
|
|
100
|
+
height: 100%;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.layout__main {
|
|
104
|
+
flex: 1;
|
|
105
|
+
display: flex;
|
|
106
|
+
flex-direction: column;
|
|
107
|
+
height: 100%;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 顶部菜单模式
|
|
112
|
+
&--top {
|
|
113
|
+
flex-direction: column;
|
|
114
|
+
|
|
115
|
+
.layout__main {
|
|
116
|
+
flex: 1;
|
|
117
|
+
display: flex;
|
|
118
|
+
flex-direction: column;
|
|
119
|
+
height: calc(100% - 50px);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.layout__content {
|
|
123
|
+
flex: 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 混合菜单模式
|
|
128
|
+
&--mix {
|
|
129
|
+
flex-direction: column;
|
|
130
|
+
|
|
131
|
+
.layout__mix-top-menu {
|
|
132
|
+
width: 100%;
|
|
133
|
+
height: 50px;
|
|
134
|
+
background-color: var(--bg-color);
|
|
135
|
+
border-bottom: 1px solid var(--color-border-lighter);
|
|
136
|
+
flex-shrink: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.layout__mix-body {
|
|
140
|
+
flex: 1;
|
|
141
|
+
display: flex;
|
|
142
|
+
flex-direction: row;
|
|
143
|
+
height: calc(100% - 50px);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
&__aside {
|
|
148
|
+
transition: width 0.3s;
|
|
149
|
+
overflow: hidden;
|
|
150
|
+
flex-shrink: 0;
|
|
151
|
+
height: 100%;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
&__top-menu {
|
|
155
|
+
width: 100%;
|
|
156
|
+
height: 50px;
|
|
157
|
+
box-sizing: border-box;
|
|
158
|
+
background-color: var(--bg-color);
|
|
159
|
+
border-bottom: 1px solid var(--color-border-lighter);
|
|
160
|
+
flex-shrink: 0;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
&__mix-top-menu {
|
|
164
|
+
width: 100%;
|
|
165
|
+
height: 50px;
|
|
166
|
+
box-sizing: border-box;
|
|
167
|
+
flex-shrink: 0;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
&__main {
|
|
171
|
+
flex: 1;
|
|
172
|
+
display: flex;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
overflow: hidden;
|
|
175
|
+
height: 100%;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
&__header {
|
|
179
|
+
height: 50px;
|
|
180
|
+
box-sizing: border-box;
|
|
181
|
+
background-color: var(--bg-color);
|
|
182
|
+
border-bottom: 1px solid var(--color-border-lighter);
|
|
183
|
+
flex-shrink: 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
&__content {
|
|
187
|
+
flex: 1;
|
|
188
|
+
overflow: auto;
|
|
189
|
+
background-color: var(--bg-color-page);
|
|
190
|
+
padding: 0;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
193
|
</style>
|
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 权限指令
|
|
3
3
|
* v-permission="['user:edit']" 或 v-permission="'user:edit'"
|
|
4
|
-
* 注意:tineco-ui 不支持 permissions 字段,此指令暂时只检查登录状态
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
import type { Directive, DirectiveBinding } from 'vue'
|
|
8
7
|
import { useUserStore } from '@/stores/user'
|
|
8
|
+
import { useMenuStore } from '@/stores/menu'
|
|
9
9
|
|
|
10
10
|
const permission: Directive = {
|
|
11
|
-
mounted(el: HTMLElement,
|
|
11
|
+
mounted(el: HTMLElement, binding: DirectiveBinding<string | string[]>) {
|
|
12
12
|
const userStore = useUserStore()
|
|
13
|
+
const menuStore = useMenuStore()
|
|
13
14
|
|
|
14
15
|
// 如果没有登录,移除元素
|
|
15
16
|
if (!userStore.isLoggedIn) {
|
|
16
17
|
el.parentNode?.removeChild(el)
|
|
18
|
+
return
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
//
|
|
21
|
+
// 获取权限标识
|
|
22
|
+
const value = binding.value
|
|
23
|
+
const permissions = Array.isArray(value) ? value : [value]
|
|
24
|
+
|
|
25
|
+
// 检查是否有权限
|
|
26
|
+
if (!menuStore.hasPermission(permissions)) {
|
|
27
|
+
el.parentNode?.removeChild(el)
|
|
28
|
+
}
|
|
20
29
|
}
|
|
21
30
|
}
|
|
22
31
|
|
package/src/index.ts
CHANGED
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
// 样式
|
|
2
|
-
import './style.scss'
|
|
3
|
-
|
|
4
|
-
// 配置
|
|
5
|
-
import { initAppConfig, getAppId, getClientId, getApiBaseUrl } from './utils/config'
|
|
6
|
-
import type { LocaleCode } from '@xto/core/locale'
|
|
7
|
-
|
|
8
|
-
// XtoConfig 类型定义
|
|
9
|
-
export interface XtoConfig {
|
|
10
|
-
appName?: string
|
|
11
|
-
appId?: string
|
|
12
|
-
clientId?: string
|
|
13
|
-
apiBaseUrl?: string
|
|
14
|
-
indexPath?: string
|
|
15
|
-
loginPath?: string
|
|
16
|
-
locale?: LocaleCode
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* 初始化 XTO 应用
|
|
21
|
-
* 在项目入口文件中调用此函数设置应用配置
|
|
22
|
-
* @param config 应用配置
|
|
23
|
-
*/
|
|
24
|
-
export function createXtoApp(config: Partial<XtoConfig>) {
|
|
25
|
-
initAppConfig({
|
|
26
|
-
appId: config.appId,
|
|
27
|
-
clientId: config.clientId,
|
|
28
|
-
apiBaseUrl: config.apiBaseUrl
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
// 设置初始语言(如果提供)
|
|
32
|
-
if (config.locale) {
|
|
33
|
-
import('./stores/locale').then(({ useLocaleStore }) => {
|
|
34
|
-
const localeStore = useLocaleStore()
|
|
35
|
-
localeStore.changeLocale(config.locale!)
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
config: {
|
|
41
|
-
appName: config.appName || 'XTO App',
|
|
42
|
-
appId: getAppId(),
|
|
43
|
-
clientId: getClientId(),
|
|
44
|
-
apiBaseUrl: getApiBaseUrl(),
|
|
45
|
-
indexPath: config.indexPath || '/dashboard',
|
|
46
|
-
loginPath: config.loginPath || '/login',
|
|
47
|
-
locale: config.locale || 'zh-CN'
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 组件
|
|
53
|
-
export { default as Layout } from './components/Layout/index.vue'
|
|
54
|
-
export { default as Header } from './components/Layout/Header.vue'
|
|
55
|
-
export { default as Sidebar } from './components/Layout/Sidebar.vue'
|
|
56
|
-
export { default as Tabs } from './components/Layout/Tabs.vue'
|
|
57
|
-
export { default as Footer } from './components/Layout/Footer.vue'
|
|
58
|
-
|
|
59
|
-
// 错误页面组件
|
|
60
|
-
export { default as Login } from './views/login/index.vue'
|
|
61
|
-
export { default as NotFound } from './views/error/404.vue'
|
|
62
|
-
export { default as Forbidden } from './views/error/403.vue'
|
|
63
|
-
|
|
64
|
-
// 组合式函数
|
|
65
|
-
export * from './composables/useApp'
|
|
66
|
-
export * from './composables/useAuth'
|
|
67
|
-
export * from './composables/useForm'
|
|
68
|
-
export * from './composables/useTable'
|
|
69
|
-
export * from './composables/useI18n'
|
|
70
|
-
|
|
71
|
-
// 工具函数
|
|
72
|
-
export * from './utils/auth'
|
|
73
|
-
export * from './utils/permission'
|
|
74
|
-
export * from './utils/request'
|
|
75
|
-
export * from './utils/storage'
|
|
76
|
-
export * from './utils/config'
|
|
77
|
-
|
|
78
|
-
// Store
|
|
79
|
-
export * from './stores/app'
|
|
80
|
-
export * from './stores/auth'
|
|
81
|
-
export * from './stores/menu'
|
|
82
|
-
export * from './stores/user'
|
|
83
|
-
export * from './stores/locale'
|
|
84
|
-
|
|
85
|
-
// 路由
|
|
86
|
-
export { default as router, resetRouter } from './router'
|
|
87
|
-
export * from './router/staticRoutes'
|
|
88
|
-
export * from './router/dynamicRoutes'
|
|
89
|
-
export { createLayoutRoute, createRouter } from './router/layoutRoute'
|
|
90
|
-
export { setupRouterGuards } from './router/guards'
|
|
91
|
-
|
|
92
|
-
// API
|
|
93
|
-
export * from './api/auth'
|
|
94
|
-
export * from './api/system'
|
|
95
|
-
export * from './api/user'
|
|
96
|
-
|
|
97
|
-
// 枚举
|
|
98
|
-
export * from './enums'
|
|
99
|
-
|
|
100
|
-
// 指令
|
|
1
|
+
// 样式
|
|
2
|
+
import './style.scss'
|
|
3
|
+
|
|
4
|
+
// 配置
|
|
5
|
+
import { initAppConfig, getAppId, getClientId, getApiBaseUrl } from './utils/config'
|
|
6
|
+
import type { LocaleCode } from '@xto/core/locale'
|
|
7
|
+
|
|
8
|
+
// XtoConfig 类型定义
|
|
9
|
+
export interface XtoConfig {
|
|
10
|
+
appName?: string
|
|
11
|
+
appId?: string
|
|
12
|
+
clientId?: string
|
|
13
|
+
apiBaseUrl?: string
|
|
14
|
+
indexPath?: string
|
|
15
|
+
loginPath?: string
|
|
16
|
+
locale?: LocaleCode
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 初始化 XTO 应用
|
|
21
|
+
* 在项目入口文件中调用此函数设置应用配置
|
|
22
|
+
* @param config 应用配置
|
|
23
|
+
*/
|
|
24
|
+
export function createXtoApp(config: Partial<XtoConfig>) {
|
|
25
|
+
initAppConfig({
|
|
26
|
+
appId: config.appId,
|
|
27
|
+
clientId: config.clientId,
|
|
28
|
+
apiBaseUrl: config.apiBaseUrl
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// 设置初始语言(如果提供)
|
|
32
|
+
if (config.locale) {
|
|
33
|
+
import('./stores/locale').then(({ useLocaleStore }) => {
|
|
34
|
+
const localeStore = useLocaleStore()
|
|
35
|
+
localeStore.changeLocale(config.locale!)
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
config: {
|
|
41
|
+
appName: config.appName || 'XTO App',
|
|
42
|
+
appId: getAppId(),
|
|
43
|
+
clientId: getClientId(),
|
|
44
|
+
apiBaseUrl: getApiBaseUrl(),
|
|
45
|
+
indexPath: config.indexPath || '/dashboard',
|
|
46
|
+
loginPath: config.loginPath || '/login',
|
|
47
|
+
locale: config.locale || 'zh-CN'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 组件
|
|
53
|
+
export { default as Layout } from './components/Layout/index.vue'
|
|
54
|
+
export { default as Header } from './components/Layout/Header.vue'
|
|
55
|
+
export { default as Sidebar } from './components/Layout/Sidebar.vue'
|
|
56
|
+
export { default as Tabs } from './components/Layout/Tabs.vue'
|
|
57
|
+
export { default as Footer } from './components/Layout/Footer.vue'
|
|
58
|
+
|
|
59
|
+
// 错误页面组件
|
|
60
|
+
export { default as Login } from './views/login/index.vue'
|
|
61
|
+
export { default as NotFound } from './views/error/404.vue'
|
|
62
|
+
export { default as Forbidden } from './views/error/403.vue'
|
|
63
|
+
|
|
64
|
+
// 组合式函数
|
|
65
|
+
export * from './composables/useApp'
|
|
66
|
+
export * from './composables/useAuth'
|
|
67
|
+
export * from './composables/useForm'
|
|
68
|
+
export * from './composables/useTable'
|
|
69
|
+
export * from './composables/useI18n'
|
|
70
|
+
|
|
71
|
+
// 工具函数
|
|
72
|
+
export * from './utils/auth'
|
|
73
|
+
export * from './utils/permission'
|
|
74
|
+
export * from './utils/request'
|
|
75
|
+
export * from './utils/storage'
|
|
76
|
+
export * from './utils/config'
|
|
77
|
+
|
|
78
|
+
// Store
|
|
79
|
+
export * from './stores/app'
|
|
80
|
+
export * from './stores/auth'
|
|
81
|
+
export * from './stores/menu'
|
|
82
|
+
export * from './stores/user'
|
|
83
|
+
export * from './stores/locale'
|
|
84
|
+
|
|
85
|
+
// 路由
|
|
86
|
+
export { default as router, resetRouter } from './router'
|
|
87
|
+
export * from './router/staticRoutes'
|
|
88
|
+
export * from './router/dynamicRoutes'
|
|
89
|
+
export { createLayoutRoute, createRouter } from './router/layoutRoute'
|
|
90
|
+
export { setupRouterGuards } from './router/guards'
|
|
91
|
+
|
|
92
|
+
// API
|
|
93
|
+
export * from './api/auth'
|
|
94
|
+
export * from './api/system'
|
|
95
|
+
export * from './api/user'
|
|
96
|
+
|
|
97
|
+
// 枚举
|
|
98
|
+
export * from './enums'
|
|
99
|
+
|
|
100
|
+
// 指令
|
|
101
101
|
export { default as permissionDirective } from './directives/permission'
|