xto-fronted 0.4.62 → 0.4.65

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 (59) hide show
  1. package/dist/assets/404-ByYjFnhI.js +1 -0
  2. package/dist/assets/404-sqW80Hc-.css +1 -0
  3. package/dist/assets/_plugin-vue_export-helper-DlAUqK2U.js +1 -0
  4. package/dist/assets/index-BBhC8PX4.js +1 -0
  5. package/dist/assets/index-BOEFG4lP.css +1 -0
  6. package/dist/assets/index-BRR97dc6.js +1 -0
  7. package/dist/assets/index-BihVoviB.js +1 -0
  8. package/dist/assets/index-BrvR0Fn_.css +1 -0
  9. package/dist/assets/index-C4ZCZoPp.js +1 -0
  10. package/dist/assets/index-CUh_s55Z.css +1 -0
  11. package/dist/assets/index-D0OnMilp.js +1 -0
  12. package/dist/assets/index-D9wlAuR_.js +1 -0
  13. package/dist/assets/index-DPkO-STg.js +1 -0
  14. package/dist/assets/index-DawJb02s.css +1 -0
  15. package/dist/assets/index-DiHSZ6SJ.js +2 -0
  16. package/dist/assets/index-GDP-IkXE.css +1 -0
  17. package/dist/assets/index-PfV8pzQz.css +1 -0
  18. package/dist/assets/index-Swfu6yvD.css +1 -0
  19. package/dist/assets/vendor-42ANG6Sg.js +6 -0
  20. package/dist/assets/vite-Dw-pgLOX.js +1 -0
  21. package/dist/assets/vue-vendor-Br-l7wbK.js +29 -0
  22. package/dist/assets/xto-base-C-IBqjVs.js +1 -0
  23. package/dist/assets/xto-base-C6eqMPdO.css +1 -0
  24. package/dist/assets/xto-business--V1F5Gwb.css +1 -0
  25. package/dist/assets/xto-core-DZK7Cyg0.js +1 -0
  26. package/dist/assets/xto-data-BFpiDgJi.js +1 -0
  27. package/dist/assets/xto-data-CnAQAQH2.css +1 -0
  28. package/dist/assets/xto-feedback-B2M02fn3.js +1 -0
  29. package/dist/assets/xto-feedback-ByaS-C7_.css +1 -0
  30. package/dist/assets/xto-form-CrsyAjyr.css +1 -0
  31. package/dist/assets/xto-form-NRjKKNcY.js +1 -0
  32. package/dist/assets/xto-layout-D1stVnJI.css +1 -0
  33. package/dist/assets/xto-navigation-BuRQVoD8.css +1 -0
  34. package/dist/assets/xto-navigation-qLRTxo68.js +1 -0
  35. package/dist/components/Layout/SidebarMenuItem.vue.d.ts +5 -0
  36. package/dist/index-2tvOdd6w.js +372 -0
  37. package/dist/index-BRQBannD.js +345 -0
  38. package/dist/index-BbeWpCd3.js +345 -0
  39. package/dist/index-BjEnT8WQ.js +372 -0
  40. package/dist/index-Bt5ocakb.js +475 -0
  41. package/dist/index-CLiJcB9v.js +142 -0
  42. package/dist/index-CmajGrKA.js +142 -0
  43. package/dist/index-CsRhLwmR.js +475 -0
  44. package/dist/index-DCuKNBck.js +3153 -0
  45. package/dist/index-logKl0VM.js +3144 -0
  46. package/dist/index.es.js +1 -1
  47. package/dist/index.html +28 -0
  48. package/dist/index.umd.js +1 -1
  49. package/dist/style.css +1 -1
  50. package/dist/utils/request.d.ts +1 -0
  51. package/package.json +87 -86
  52. package/src/assets/styles/index.scss +235 -235
  53. package/src/components/Layout/Header.vue +1012 -1012
  54. package/src/components/Layout/Sidebar.vue +4 -152
  55. package/src/components/Layout/SidebarMenuItem.vue +158 -0
  56. package/src/style.scss +13 -13
  57. package/src/utils/request.ts +5 -0
  58. package/src/views/error/403.vue +56 -56
  59. package/src/views/error/404.vue +56 -56
@@ -5,8 +5,9 @@ import { useMenuStore } from '@/stores/menu'
5
5
  import { useUserStore } from '@/stores/user'
6
6
  import { useAuthStore } from '@/stores/auth'
7
7
  import { useAppStore } from '@/stores/app'
8
- import { Menu, MenuItem, SubMenu } from '@xto/navigation'
9
- import { Button, Icon } from '@xto/base'
8
+ import { Menu } from '@xto/navigation'
9
+ import { Button } from '@xto/base'
10
+ import SidebarMenuItem from './SidebarMenuItem.vue'
10
11
 
11
12
  // Props
12
13
  const props = withDefaults(defineProps<{
@@ -51,87 +52,6 @@ const handleLogout = () => {
51
52
  menuStore.clearMenu()
52
53
  router.push('/login')
53
54
  }
54
-
55
- // 已知的图标名称列表(来自 @xto/base/icons.ts)
56
- const knownIcons = new Set([
57
- 'arrow-up', 'arrow-down', 'arrow-left', 'arrow-right',
58
- 'caret-down', 'caret-right', 'plus', 'minus', 'close', 'check',
59
- 'edit', 'delete', 'copy', 'download', 'upload', 'refresh', 'search',
60
- 'filter', 'more', 'setting', 'share', 'loading', 'info', 'success',
61
- 'warning', 'error', 'question', 'user', 'user-add', 'user-group',
62
- 'logout', 'login', 'file', 'folder', 'folder-open', 'document',
63
- 'image', 'video', 'music', 'camera', 'mail', 'phone', 'chat',
64
- 'bell', 'message', 'eye', 'eye-off', 'calendar', 'clock', 'history',
65
- 'timer', 'location', 'map', 'globe', 'star', 'heart', 'thumb-up',
66
- 'link', 'external-link', 'lock', 'unlock', 'key', 'home', 'menu',
67
- 'menu-fold', 'menu-unfold', 'sidebar-fold', 'sidebar-expand',
68
- 'sidebar-left', 'dashboard', 'chart', 'chart-pie', 'chart-line',
69
- 'report', 'analytics', 'system', 'permission', 'role', 'user-manage',
70
- 'log', 'notification', 'app', 'list', 'grid', 'fullscreen',
71
- 'fullscreen-exit', 'zoom-in', 'zoom-out', 'print', 'bookmark',
72
- 'tag', 'code', 'terminal', 'database', 'server', 'cloud', 'gift',
73
- 'moon', 'sun', 'theme', 'skin'
74
- ])
75
-
76
- // 获取菜单图标名称
77
- const getMenuIcon = (icon?: string): string => {
78
- // 无图标时返回空
79
- if (!icon || icon === '') return ''
80
-
81
- // 处理 tineco-ui 的图标类名(如 tineco-icon-home)
82
- if (icon.startsWith('tineco-icon-')) {
83
- const iconName = icon.replace('tineco-icon-', '')
84
- // 常见的 tineco icon 映射
85
- const tinecoIconMap: Record<string, string> = {
86
- home: 'home',
87
- dashboard: 'dashboard',
88
- system: 'system',
89
- user: 'user',
90
- role: 'role',
91
- menu: 'list',
92
- setting: 'setting',
93
- file: 'file',
94
- folder: 'folder',
95
- chart: 'chart',
96
- report: 'report',
97
- analytics: 'analytics'
98
- }
99
- return tinecoIconMap[iconName] || iconName
100
- }
101
-
102
- // 常见业务图标映射
103
- const iconMap: Record<string, string> = {
104
- dashboard: 'dashboard',
105
- system: 'system',
106
- user: 'user',
107
- role: 'role',
108
- menu: 'list',
109
- setting: 'setting',
110
- home: 'home',
111
- chart: 'chart',
112
- report: 'report',
113
- analytics: 'analytics',
114
- permission: 'permission',
115
- log: 'log',
116
- notification: 'notification',
117
- app: 'app',
118
- list: 'list',
119
- grid: 'grid'
120
- }
121
-
122
- return iconMap[icon] || icon
123
- }
124
-
125
- // 获取菜单名称第一个字
126
- const getFirstChar = (name?: string): string => {
127
- if (!name) return ''
128
- return name.charAt(0)
129
- }
130
-
131
- // 判断图标是否存在
132
- const iconExists = (iconName: string): boolean => {
133
- return knownIcons.has(iconName)
134
- }
135
55
  </script>
136
56
 
137
57
  <template>
@@ -155,41 +75,7 @@ const iconExists = (iconName: string): boolean => {
155
75
  @select="handleMenuSelect"
156
76
  >
157
77
  <template v-for="menu in displayMenuList" :key="menu.menuUrl">
158
- <!-- 有子菜单 -->
159
- <SubMenu v-if="menu.children && menu.children.length > 0" :index="menu.menuUrl">
160
- <template #title>
161
- <span class="sidebar__menu-content">
162
- <span v-if="menu.menuName !== '首页'" class="sidebar__menu-icon">
163
- <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
164
- <span v-else class="sidebar__menu-char">{{ getFirstChar(menu.menuName) }}</span>
165
- </span>
166
- <span class="sidebar__menu-text">{{ menu.menuName }}</span>
167
- </span>
168
- </template>
169
- <MenuItem
170
- v-for="child in menu.children"
171
- :key="child.menuUrl"
172
- :index="child.menuUrl"
173
- >
174
- <span class="sidebar__menu-content">
175
- <span class="sidebar__menu-icon">
176
- <Icon v-if="iconExists(getMenuIcon(child.icon))" :name="getMenuIcon(child.icon)" :size="16" />
177
- <span v-else class="sidebar__menu-char">{{ getFirstChar(child.menuName) }}</span>
178
- </span>
179
- <span class="sidebar__menu-text">{{ child.menuName }}</span>
180
- </span>
181
- </MenuItem>
182
- </SubMenu>
183
- <!-- 无子菜单 -->
184
- <MenuItem v-else :index="menu.menuUrl">
185
- <span class="sidebar__menu-content">
186
- <span v-if="menu.menuName !== '首页'" class="sidebar__menu-icon">
187
- <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
188
- <span v-else class="sidebar__menu-char">{{ getFirstChar(menu.menuName) }}</span>
189
- </span>
190
- <span class="sidebar__menu-text">{{ menu.menuName }}</span>
191
- </span>
192
- </MenuItem>
78
+ <SidebarMenuItem :menu="menu" />
193
79
  </template>
194
80
  </Menu>
195
81
 
@@ -245,40 +131,6 @@ const iconExists = (iconName: string): boolean => {
245
131
  overflow-y: auto;
246
132
  }
247
133
 
248
- &__menu-content {
249
- display: inline-flex;
250
- align-items: center;
251
- line-height: 1;
252
- }
253
-
254
- &__menu-text {
255
- flex: 1;
256
- line-height: 1;
257
- }
258
-
259
- &__menu-icon {
260
- display: inline-flex;
261
- align-items: center;
262
- justify-content: center;
263
- width: 16px;
264
- height: 16px;
265
- margin-right: 8px;
266
- flex-shrink: 0;
267
- }
268
-
269
- &__menu-char {
270
- display: inline-flex;
271
- align-items: center;
272
- justify-content: center;
273
- width: 16px;
274
- height: 16px;
275
- font-size: 12px;
276
- font-weight: 600;
277
- color: var(--color-primary);
278
- background-color: var(--color-primary-light-8);
279
- border-radius: 4px;
280
- }
281
-
282
134
  &__user {
283
135
  padding: 10px;
284
136
  border-top: 1px solid var(--color-border-lighter);
@@ -0,0 +1,158 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { MenuItem, SubMenu } from '@xto/navigation'
4
+ import { Icon } from '@xto/base'
5
+
6
+ // Props
7
+ const props = defineProps<{
8
+ menu: any
9
+ }>()
10
+
11
+ // 已知的图标名称列表
12
+ const knownIcons = new Set([
13
+ 'arrow-up', 'arrow-down', 'arrow-left', 'arrow-right',
14
+ 'caret-down', 'caret-right', 'plus', 'minus', 'close', 'check',
15
+ 'edit', 'delete', 'copy', 'download', 'upload', 'refresh', 'search',
16
+ 'filter', 'more', 'setting', 'share', 'loading', 'info', 'success',
17
+ 'warning', 'error', 'question', 'user', 'user-add', 'user-group',
18
+ 'logout', 'login', 'file', 'folder', 'folder-open', 'document',
19
+ 'image', 'video', 'music', 'camera', 'mail', 'phone', 'chat',
20
+ 'bell', 'message', 'eye', 'eye-off', 'calendar', 'clock', 'history',
21
+ 'timer', 'location', 'map', 'globe', 'star', 'heart', 'thumb-up',
22
+ 'link', 'external-link', 'lock', 'unlock', 'key', 'home', 'menu',
23
+ 'menu-fold', 'menu-unfold', 'sidebar-fold', 'sidebar-expand',
24
+ 'sidebar-left', 'dashboard', 'chart', 'chart-pie', 'chart-line',
25
+ 'report', 'analytics', 'system', 'permission', 'role', 'user-manage',
26
+ 'log', 'notification', 'app', 'list', 'grid', 'fullscreen',
27
+ 'fullscreen-exit', 'zoom-in', 'zoom-out', 'print', 'bookmark',
28
+ 'tag', 'code', 'terminal', 'database', 'server', 'cloud', 'gift',
29
+ 'moon', 'sun', 'theme', 'skin'
30
+ ])
31
+
32
+ // 获取菜单图标名称
33
+ const getMenuIcon = (icon?: string): string => {
34
+ if (!icon || icon === '') return ''
35
+
36
+ if (icon.startsWith('tineco-icon-')) {
37
+ const iconName = icon.replace('tineco-icon-', '')
38
+ const tinecoIconMap: Record<string, string> = {
39
+ home: 'home',
40
+ dashboard: 'dashboard',
41
+ system: 'system',
42
+ user: 'user',
43
+ role: 'role',
44
+ menu: 'list',
45
+ setting: 'setting',
46
+ file: 'file',
47
+ folder: 'folder',
48
+ chart: 'chart',
49
+ report: 'report',
50
+ analytics: 'analytics'
51
+ }
52
+ return tinecoIconMap[iconName] || iconName
53
+ }
54
+
55
+ const iconMap: Record<string, string> = {
56
+ dashboard: 'dashboard',
57
+ system: 'system',
58
+ user: 'user',
59
+ role: 'role',
60
+ menu: 'list',
61
+ setting: 'setting',
62
+ home: 'home',
63
+ chart: 'chart',
64
+ report: 'report',
65
+ analytics: 'analytics',
66
+ permission: 'permission',
67
+ log: 'log',
68
+ notification: 'notification',
69
+ app: 'app',
70
+ list: 'list',
71
+ grid: 'grid'
72
+ }
73
+
74
+ return iconMap[icon] || icon
75
+ }
76
+
77
+ // 获取菜单名称第一个字
78
+ const getFirstChar = (name?: string): string => {
79
+ if (!name) return ''
80
+ return name.charAt(0)
81
+ }
82
+
83
+ // 判断图标是否存在
84
+ const iconExists = (iconName: string): boolean => {
85
+ return knownIcons.has(iconName)
86
+ }
87
+
88
+ // 是否有子菜单
89
+ const hasChildren = computed(() => {
90
+ return props.menu.children && props.menu.children.length > 0
91
+ })
92
+ </script>
93
+
94
+ <template>
95
+ <!-- 有子菜单 -->
96
+ <SubMenu v-if="hasChildren" :index="menu.menuUrl">
97
+ <template #title>
98
+ <span class="menu-item__content">
99
+ <span class="menu-item__icon">
100
+ <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
101
+ <span v-else class="menu-item__char">{{ getFirstChar(menu.menuName) }}</span>
102
+ </span>
103
+ <span class="menu-item__text">{{ menu.menuName }}</span>
104
+ </span>
105
+ </template>
106
+ <!-- 递归渲染子菜单 -->
107
+ <template v-for="child in menu.children" :key="child.menuUrl">
108
+ <SidebarMenuItem :menu="child" />
109
+ </template>
110
+ </SubMenu>
111
+
112
+ <!-- 无子菜单 -->
113
+ <MenuItem v-else :index="menu.menuUrl">
114
+ <span class="menu-item__content">
115
+ <span v-if="menu.menuName !== '首页'" class="menu-item__icon">
116
+ <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
117
+ <span v-else class="menu-item__char">{{ getFirstChar(menu.menuName) }}</span>
118
+ </span>
119
+ <span class="menu-item__text">{{ menu.menuName }}</span>
120
+ </span>
121
+ </MenuItem>
122
+ </template>
123
+
124
+ <style lang="scss" scoped>
125
+ .menu-item__content {
126
+ display: inline-flex;
127
+ align-items: center;
128
+ line-height: 1;
129
+ }
130
+
131
+ .menu-item__text {
132
+ flex: 1;
133
+ line-height: 1;
134
+ }
135
+
136
+ .menu-item__icon {
137
+ display: inline-flex;
138
+ align-items: center;
139
+ justify-content: center;
140
+ width: 16px;
141
+ height: 16px;
142
+ margin-right: 8px;
143
+ flex-shrink: 0;
144
+ }
145
+
146
+ .menu-item__char {
147
+ display: inline-flex;
148
+ align-items: center;
149
+ justify-content: center;
150
+ width: 16px;
151
+ height: 16px;
152
+ font-size: 12px;
153
+ font-weight: 600;
154
+ color: var(--color-primary);
155
+ background-color: var(--color-primary-light-8);
156
+ border-radius: 4px;
157
+ }
158
+ </style>
package/src/style.scss CHANGED
@@ -1,14 +1,14 @@
1
- /**
2
- * xto-fronted 样式入口
3
- * 组件样式已包含在各自的 Vue 组件中(scoped)
4
- */
5
-
6
- /* 导入全局样式(包含灰色模式、暗黑模式等) */
7
- @import './assets/styles/index.scss';
8
-
9
- /* 全局样式变量(可选) */
10
- :root {
11
- --bg-color: #ffffff;
12
- --bg-color-page: #f5f7fa;
13
- --color-border-lighter: #e4e7ed;
1
+ /**
2
+ * xto-fronted 样式入口
3
+ * 组件样式已包含在各自的 Vue 组件中(scoped)
4
+ */
5
+
6
+ /* 导入全局样式(包含灰色模式、暗黑模式等) */
7
+ @import './assets/styles/index.scss';
8
+
9
+ /* 全局样式变量(可选) */
10
+ :root {
11
+ --bg-color: #ffffff;
12
+ --bg-color-page: #f5f7fa;
13
+ --color-border-lighter: #e4e7ed;
14
14
  }
@@ -119,6 +119,11 @@ export const http = {
119
119
 
120
120
  delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
121
121
  return request.delete(url, config)
122
+ },
123
+
124
+ // 文件下载 - 返回 Blob 对象
125
+ download(url: string, config?: AxiosRequestConfig): Promise<Blob> {
126
+ return request.get(url, { ...config, responseType: 'blob' })
122
127
  }
123
128
  }
124
129
 
@@ -1,57 +1,57 @@
1
- <script setup lang="ts">
2
- import { useRouter } from 'vue-router'
3
- import { Button } from '@xto/base'
4
-
5
- const router = useRouter()
6
-
7
- const goBack = () => {
8
- router.push('/')
9
- }
10
- </script>
11
-
12
- <template>
13
- <div class="error-page">
14
- <div class="error-page__content">
15
- <div class="error-page__code">403</div>
16
- <div class="error-page__title">无访问权限</div>
17
- <div class="error-page__desc">抱歉,您没有权限访问此页面</div>
18
- <Button type="primary" @click="goBack">返回首页</Button>
19
- </div>
20
- </div>
21
- </template>
22
-
23
- <style lang="scss" scoped>
24
- .error-page {
25
- width: 100%;
26
- height: 100%;
27
- display: flex;
28
- align-items: center;
29
- justify-content: center;
30
- background-color: var(--bg-color-page);
31
-
32
- &__content {
33
- text-align: center;
34
- }
35
-
36
- &__code {
37
- font-size: 120px;
38
- font-weight: 600;
39
- color: var(--color-warning);
40
- line-height: 1;
41
- margin-bottom: 20px;
42
- }
43
-
44
- &__title {
45
- font-size: 24px;
46
- font-weight: 500;
47
- color: var(--color-text-primary);
48
- margin-bottom: 10px;
49
- }
50
-
51
- &__desc {
52
- font-size: 14px;
53
- color: var(--color-text-secondary);
54
- margin-bottom: 30px;
55
- }
56
- }
1
+ <script setup lang="ts">
2
+ import { useRouter } from 'vue-router'
3
+ import { Button } from '@xto/base'
4
+
5
+ const router = useRouter()
6
+
7
+ const goBack = () => {
8
+ router.push('/')
9
+ }
10
+ </script>
11
+
12
+ <template>
13
+ <div class="error-page">
14
+ <div class="error-page__content">
15
+ <div class="error-page__code">403</div>
16
+ <div class="error-page__title">无访问权限</div>
17
+ <div class="error-page__desc">抱歉,您没有权限访问此页面</div>
18
+ <Button type="primary" @click="goBack">返回首页</Button>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <style lang="scss" scoped>
24
+ .error-page {
25
+ width: 100%;
26
+ height: 100%;
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ background-color: var(--bg-color-page);
31
+
32
+ &__content {
33
+ text-align: center;
34
+ }
35
+
36
+ &__code {
37
+ font-size: 120px;
38
+ font-weight: 600;
39
+ color: var(--color-warning);
40
+ line-height: 1;
41
+ margin-bottom: 20px;
42
+ }
43
+
44
+ &__title {
45
+ font-size: 24px;
46
+ font-weight: 500;
47
+ color: var(--color-text-primary);
48
+ margin-bottom: 10px;
49
+ }
50
+
51
+ &__desc {
52
+ font-size: 14px;
53
+ color: var(--color-text-secondary);
54
+ margin-bottom: 30px;
55
+ }
56
+ }
57
57
  </style>
@@ -1,57 +1,57 @@
1
- <script setup lang="ts">
2
- import { useRouter } from 'vue-router'
3
- import { Button } from '@xto/base'
4
-
5
- const router = useRouter()
6
-
7
- const goBack = () => {
8
- router.push('/')
9
- }
10
- </script>
11
-
12
- <template>
13
- <div class="error-page">
14
- <div class="error-page__content">
15
- <div class="error-page__code">404</div>
16
- <div class="error-page__title">页面不存在</div>
17
- <div class="error-page__desc">抱歉,您访问的页面不存在或已被删除</div>
18
- <Button type="primary" @click="goBack">返回首页</Button>
19
- </div>
20
- </div>
21
- </template>
22
-
23
- <style lang="scss" scoped>
24
- .error-page {
25
- width: 100%;
26
- height: 100%;
27
- display: flex;
28
- align-items: center;
29
- justify-content: center;
30
- background-color: var(--bg-color-page);
31
-
32
- &__content {
33
- text-align: center;
34
- }
35
-
36
- &__code {
37
- font-size: 120px;
38
- font-weight: 600;
39
- color: var(--color-primary);
40
- line-height: 1;
41
- margin-bottom: 20px;
42
- }
43
-
44
- &__title {
45
- font-size: 24px;
46
- font-weight: 500;
47
- color: var(--color-text-primary);
48
- margin-bottom: 10px;
49
- }
50
-
51
- &__desc {
52
- font-size: 14px;
53
- color: var(--color-text-secondary);
54
- margin-bottom: 30px;
55
- }
56
- }
1
+ <script setup lang="ts">
2
+ import { useRouter } from 'vue-router'
3
+ import { Button } from '@xto/base'
4
+
5
+ const router = useRouter()
6
+
7
+ const goBack = () => {
8
+ router.push('/')
9
+ }
10
+ </script>
11
+
12
+ <template>
13
+ <div class="error-page">
14
+ <div class="error-page__content">
15
+ <div class="error-page__code">404</div>
16
+ <div class="error-page__title">页面不存在</div>
17
+ <div class="error-page__desc">抱歉,您访问的页面不存在或已被删除</div>
18
+ <Button type="primary" @click="goBack">返回首页</Button>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <style lang="scss" scoped>
24
+ .error-page {
25
+ width: 100%;
26
+ height: 100%;
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ background-color: var(--bg-color-page);
31
+
32
+ &__content {
33
+ text-align: center;
34
+ }
35
+
36
+ &__code {
37
+ font-size: 120px;
38
+ font-weight: 600;
39
+ color: var(--color-primary);
40
+ line-height: 1;
41
+ margin-bottom: 20px;
42
+ }
43
+
44
+ &__title {
45
+ font-size: 24px;
46
+ font-weight: 500;
47
+ color: var(--color-text-primary);
48
+ margin-bottom: 10px;
49
+ }
50
+
51
+ &__desc {
52
+ font-size: 14px;
53
+ color: var(--color-text-secondary);
54
+ margin-bottom: 30px;
55
+ }
56
+ }
57
57
  </style>