xto-fronted 0.4.8 → 0.4.10

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 (75) hide show
  1. package/dist/assets/index-4-QoJAgA.css +1 -0
  2. package/dist/assets/index-BHwEwbkp.js +1 -0
  3. package/dist/assets/{index-Te8_PRgJ.js → index-BTsRosKu.js} +1 -1
  4. package/dist/assets/index-CZAlkDIC.css +1 -0
  5. package/dist/assets/{index-1juADvYN.js → index-Do3gMkWw.js} +2 -2
  6. package/dist/index.html +2 -2
  7. package/package.json +4 -4
  8. package/src/assets/styles/_dark.scss +118 -0
  9. package/src/assets/styles/index.scss +8 -0
  10. package/src/components/Layout/Header.vue +0 -5
  11. package/src/components/Layout/Sidebar.vue +11 -1
  12. package/src/components/Layout/TopMenu.vue +186 -0
  13. package/src/components/Layout/index.vue +120 -443
  14. package/vite.config.ts +1 -1
  15. package/dist/App.vue.d.ts +0 -2
  16. package/dist/api/auth.d.ts +0 -8
  17. package/dist/api/system.d.ts +0 -16
  18. package/dist/api/user.d.ts +0 -13
  19. package/dist/assets/index-B-sX4Ru0.js +0 -1
  20. package/dist/assets/index-BMcziU5a.css +0 -1
  21. package/dist/assets/index-BZA0ksjx.css +0 -1
  22. package/dist/assets/index-BvzhR4zp.js +0 -1
  23. package/dist/assets/index-CVjdnIgR.css +0 -1
  24. package/dist/assets/index-CYq57-zj.js +0 -1
  25. package/dist/assets/index-CkL3sVAQ.js +0 -2
  26. package/dist/assets/index-CtrKVYJb.css +0 -1
  27. package/dist/assets/index-DfFR6NLf.js +0 -1
  28. package/dist/assets/index-Iaz1ZzPC.js +0 -2
  29. package/dist/assets/index-WyZ91RLx.css +0 -1
  30. package/dist/assets/index-tFYRoFdE.js +0 -1
  31. package/dist/assets/xto-navigation-CBPg4dCc.css +0 -1
  32. package/dist/assets/xto-navigation-CKabFu9d.js +0 -1
  33. package/dist/components/Layout/Footer.vue.d.ts +0 -2
  34. package/dist/components/Layout/Header.vue.d.ts +0 -5
  35. package/dist/components/Layout/Sidebar.vue.d.ts +0 -2
  36. package/dist/components/Layout/Tabs.vue.d.ts +0 -2
  37. package/dist/components/Layout/index.vue.d.ts +0 -2
  38. package/dist/composables/useApp.d.ts +0 -29
  39. package/dist/composables/useAuth.d.ts +0 -6
  40. package/dist/composables/useForm.d.ts +0 -20
  41. package/dist/composables/useTable.d.ts +0 -29
  42. package/dist/directives/permission.d.ts +0 -4
  43. package/dist/enums/index.d.ts +0 -32
  44. package/dist/index-54irhCHL.js +0 -1830
  45. package/dist/index-BzRf1eoJ.js +0 -372
  46. package/dist/index-DH4aoCZb.js +0 -142
  47. package/dist/index-Kqa7iZ9E.js +0 -475
  48. package/dist/index-pxkZlvBw.js +0 -345
  49. package/dist/index.d.ts +0 -31
  50. package/dist/index.es.js +0 -91
  51. package/dist/index.umd.js +0 -1
  52. package/dist/main.d.ts +0 -0
  53. package/dist/router/dynamicRoutes.d.ts +0 -30
  54. package/dist/router/guards.d.ts +0 -17
  55. package/dist/router/index.d.ts +0 -6
  56. package/dist/router/layoutRoute.d.ts +0 -18
  57. package/dist/router/staticRoutes.d.ts +0 -3
  58. package/dist/stores/app.d.ts +0 -87
  59. package/dist/stores/auth.d.ts +0 -41
  60. package/dist/stores/index.d.ts +0 -9
  61. package/dist/stores/menu.d.ts +0 -77
  62. package/dist/stores/user.d.ts +0 -92
  63. package/dist/style.css +0 -1
  64. package/dist/utils/auth.d.ts +0 -27
  65. package/dist/utils/config.d.ts +0 -30
  66. package/dist/utils/permission.d.ts +0 -18
  67. package/dist/utils/request.d.ts +0 -23
  68. package/dist/utils/storage.d.ts +0 -24
  69. package/dist/views/dashboard/index.vue.d.ts +0 -2
  70. package/dist/views/error/403.vue.d.ts +0 -2
  71. package/dist/views/error/404.vue.d.ts +0 -2
  72. package/dist/views/login/index.vue.d.ts +0 -4
  73. package/dist/views/system/menu/index.vue.d.ts +0 -4
  74. package/dist/views/system/role/index.vue.d.ts +0 -4
  75. package/dist/views/system/user/index.vue.d.ts +0 -4
@@ -1,444 +1,121 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import { useRoute, useRouter } from 'vue-router'
4
- import { useAppStore } from '@/stores/app'
5
- import { useMenuStore } from '@/stores/menu'
6
- import Sidebar from './Sidebar.vue'
7
- import Header from './Header.vue'
8
- import { Menu, MenuItem, SubMenu } from '@xto/navigation'
9
- import { Icon } from '@xto/base'
10
-
11
- const route = useRoute()
12
- const router = useRouter()
13
- const appStore = useAppStore()
14
- const menuStore = useMenuStore()
15
-
16
- // 菜单选择处理
17
- const handleMenuSelect = (index: string) => {
18
- if (index && index !== route.path) {
19
- router.push(index)
20
- }
21
- }
22
-
23
- // 混合布局顶部菜单选择处理
24
- const handleTopMenuSelect = (index: string) => {
25
- const selectedMenu = menuStore.menuList.find(menu => menu.menuCode === index)
26
- if (selectedMenu) {
27
- if (selectedMenu.children && selectedMenu.children.length > 0) {
28
- const firstChild = selectedMenu.children[0]
29
- if (firstChild.menuUrl && firstChild.menuUrl !== route.path) {
30
- router.push(firstChild.menuUrl)
31
- }
32
- } else if (selectedMenu.menuUrl && selectedMenu.menuUrl !== route.path) {
33
- router.push(selectedMenu.menuUrl)
34
- }
35
- }
36
- }
37
-
38
- const sidebarWidth = computed(() =>
39
- appStore.isCollapsed ? '64px' : '210px'
40
- )
41
-
42
- const currentLayout = computed(() => appStore.layout)
43
- const currentPath = computed(() => route.path)
44
-
45
- // 获取一级菜单
46
- const topLevelMenus = computed(() => {
47
- return menuStore.menuList.map(menu => ({
48
- menuCode: menu.menuCode,
49
- menuName: menu.menuName,
50
- menuUrl: menu.menuUrl,
51
- icon: menu.icon,
52
- hasChildren: menu.children && menu.children.length > 0
53
- }))
54
- })
55
-
56
- // 活动的顶部菜单
57
- const activeTopMenu = computed(() => {
58
- for (const menu of menuStore.menuList) {
59
- if (menu.menuUrl === currentPath.value) return menu.menuCode
60
- if (menu.children) {
61
- for (const child of menu.children) {
62
- if (child.menuUrl === currentPath.value) return menu.menuCode
63
- }
64
- }
65
- }
66
- return topLevelMenus.value[0]?.menuCode || ''
67
- })
68
-
69
- // 混合布局子菜单
70
- const mixSubMenus = computed(() => {
71
- if (currentLayout.value !== 'mix') return []
72
- const selectedTopMenu = menuStore.menuList.find(
73
- menu => menu.menuCode === activeTopMenu.value
74
- )
75
- return selectedTopMenu?.children || []
76
- })
77
-
78
- // 菜单主题
79
- const menuBgColor = computed(() => appStore.isDark ? '#1d1e1f' : '#fff')
80
- const menuTextColor = computed(() => appStore.isDark ? '#cfd3dc' : '#303133')
81
- const menuActiveTextColor = computed(() => '#409eff')
82
-
83
- // 图标列表
84
- const knownIcons = new Set([
85
- 'arrow-up', 'arrow-down', 'arrow-left', 'arrow-right',
86
- 'caret-down', 'caret-right', 'plus', 'minus', 'close', 'check',
87
- 'edit', 'delete', 'copy', 'download', 'upload', 'refresh', 'search',
88
- 'filter', 'more', 'setting', 'share', 'loading', 'info', 'success',
89
- 'warning', 'error', 'question', 'user', 'user-add', 'user-group',
90
- 'logout', 'login', 'file', 'folder', 'folder-open', 'document',
91
- 'image', 'video', 'music', 'camera', 'mail', 'phone', 'chat',
92
- 'bell', 'message', 'eye', 'eye-off', 'calendar', 'clock', 'history',
93
- 'timer', 'location', 'map', 'globe', 'star', 'heart', 'thumb-up',
94
- 'link', 'external-link', 'lock', 'unlock', 'key', 'home', 'menu',
95
- 'menu-fold', 'menu-unfold', 'sidebar-fold', 'sidebar-expand',
96
- 'sidebar-left', 'dashboard', 'chart', 'chart-pie', 'chart-line',
97
- 'report', 'analytics', 'system', 'permission', 'role', 'user-manage',
98
- 'log', 'notification', 'app', 'list', 'grid', 'fullscreen',
99
- 'fullscreen-exit', 'zoom-in', 'zoom-out', 'print', 'bookmark',
100
- 'tag', 'code', 'terminal', 'database', 'server', 'cloud', 'gift',
101
- 'moon', 'sun', 'theme', 'skin'
102
- ])
103
-
104
- const getMenuIcon = (icon?: string): string => {
105
- if (!icon || icon === '') return ''
106
- if (icon.startsWith('tineco-icon-')) {
107
- return icon.replace('tineco-icon-', '')
108
- }
109
- return icon
110
- }
111
-
112
- const iconExists = (iconName: string): boolean => {
113
- return knownIcons.has(iconName)
114
- }
115
-
116
- const getFirstChar = (name?: string): string => {
117
- if (!name) return ''
118
- return name.charAt(0)
119
- }
120
- </script>
121
-
122
- <template>
123
- <!-- 左侧菜单布局 -->
124
- <div v-if="currentLayout === 'sidebar'" class="layout layout--sidebar">
125
- <aside class="layout__aside" :style="{ width: sidebarWidth }">
126
- <Sidebar />
127
- </aside>
128
- <div class="layout__main">
129
- <header class="layout__header">
130
- <Header />
131
- </header>
132
- <main class="layout__content">
133
- <router-view />
134
- </main>
135
- </div>
136
- </div>
137
-
138
- <!-- 顶部菜单布局 -->
139
- <div v-else-if="currentLayout === 'top'" class="layout layout--top">
140
- <header class="layout__header-top">
141
- <div class="layout__logo">
142
- <img src="/vite.svg" alt="Logo" class="layout__logo-img" />
143
- <span class="layout__logo-text">{{ appStore.appName }}</span>
144
- </div>
145
- <Menu
146
- mode="horizontal"
147
- :default-active="activeTopMenu"
148
- class="layout__top-menu"
149
- background-color="transparent"
150
- :text-color="menuTextColor"
151
- :active-text-color="menuActiveTextColor"
152
- @select="handleMenuSelect"
153
- >
154
- <template v-for="menu in topLevelMenus" :key="menu.menuUrl">
155
- <SubMenu v-if="menu.hasChildren" :index="menu.menuCode">
156
- <template #title>
157
- <span class="layout__menu-icon">
158
- <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
159
- <span v-else class="layout__menu-char">{{ getFirstChar(menu.menuName) }}</span>
160
- </span>
161
- <span>{{ menu.menuName }}</span>
162
- </template>
163
- <MenuItem
164
- v-for="child in menuStore.menuList.find(m => m.menuCode === menu.menuCode)?.children"
165
- :key="child.menuUrl"
166
- :index="child.menuUrl"
167
- >
168
- <span>{{ child.menuName }}</span>
169
- </MenuItem>
170
- </SubMenu>
171
- <MenuItem v-else :index="menu.menuUrl">
172
- <span class="layout__menu-icon">
173
- <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
174
- <span v-else class="layout__menu-char">{{ getFirstChar(menu.menuName) }}</span>
175
- </span>
176
- <span>{{ menu.menuName }}</span>
177
- </MenuItem>
178
- </template>
179
- </Menu>
180
- <div class="layout__header-right">
181
- <Header />
182
- </div>
183
- </header>
184
- <main class="layout__content-top">
185
- <router-view />
186
- </main>
187
- </div>
188
-
189
- <!-- 混合布局 -->
190
- <div v-else-if="currentLayout === 'mix'" class="layout layout--mix">
191
- <header class="layout__header-mix">
192
- <div class="layout__logo">
193
- <img src="/vite.svg" alt="Logo" class="layout__logo-img" />
194
- <span class="layout__logo-text">{{ appStore.appName }}</span>
195
- </div>
196
- <Menu
197
- mode="horizontal"
198
- :default-active="activeTopMenu"
199
- class="layout__top-menu"
200
- background-color="transparent"
201
- :text-color="menuTextColor"
202
- :active-text-color="menuActiveTextColor"
203
- @select="handleTopMenuSelect"
204
- >
205
- <MenuItem
206
- v-for="menu in topLevelMenus"
207
- :key="menu.menuCode"
208
- :index="menu.menuCode"
209
- >
210
- <span class="layout__menu-icon">
211
- <Icon v-if="iconExists(getMenuIcon(menu.icon))" :name="getMenuIcon(menu.icon)" :size="16" />
212
- <span v-else class="layout__menu-char">{{ getFirstChar(menu.menuName) }}</span>
213
- </span>
214
- <span>{{ menu.menuName }}</span>
215
- </MenuItem>
216
- </Menu>
217
- <div class="layout__header-right">
218
- <Header />
219
- </div>
220
- </header>
221
- <div class="layout__mix-body">
222
- <aside v-if="mixSubMenus.length > 0" class="layout__mix-aside" :style="{ width: sidebarWidth }">
223
- <div class="layout__mix-sidebar">
224
- <Menu
225
- mode="vertical"
226
- :collapse="appStore.isCollapsed"
227
- :collapse-transition="false"
228
- :default-active="currentPath"
229
- :background-color="menuBgColor"
230
- :text-color="menuTextColor"
231
- :active-text-color="menuActiveTextColor"
232
- class="layout__mix-menu"
233
- @select="handleMenuSelect"
234
- >
235
- <MenuItem
236
- v-for="child in mixSubMenus"
237
- :key="child.menuUrl"
238
- :index="child.menuUrl"
239
- >
240
- <span class="layout__menu-icon">
241
- <Icon v-if="iconExists(getMenuIcon(child.icon))" :name="getMenuIcon(child.icon)" :size="16" />
242
- <span v-else class="layout__menu-char">{{ getFirstChar(child.menuName) }}</span>
243
- </span>
244
- <span>{{ child.menuName }}</span>
245
- </MenuItem>
246
- </Menu>
247
- </div>
248
- </aside>
249
- <main class="layout__content-mix">
250
- <router-view />
251
- </main>
252
- </div>
253
- </div>
254
- </template>
255
-
256
- <style lang="scss" scoped>
257
- .layout {
258
- display: flex;
259
- width: 100%;
260
- height: 100%;
261
-
262
- // 左侧菜单布局
263
- &--sidebar {
264
- flex-direction: row;
265
-
266
- .layout__aside {
267
- transition: width 0.3s;
268
- overflow: hidden;
269
- flex-shrink: 0;
270
- height: 100%;
271
- }
272
-
273
- .layout__main {
274
- flex: 1;
275
- display: flex;
276
- flex-direction: column;
277
- overflow: hidden;
278
- height: 100%;
279
- }
280
-
281
- .layout__header {
282
- height: 50px;
283
- background-color: var(--bg-color);
284
- border-bottom: 1px solid var(--color-border-lighter);
285
- flex-shrink: 0;
286
- }
287
-
288
- .layout__content {
289
- flex: 1;
290
- overflow: auto;
291
- background-color: var(--bg-color-page);
292
- }
293
- }
294
-
295
- // 顶部菜单布局
296
- &--top {
297
- flex-direction: column;
298
-
299
- .layout__header-top {
300
- height: 60px;
301
- display: flex;
302
- align-items: center;
303
- padding: 0 20px;
304
- background-color: var(--bg-color);
305
- border-bottom: 1px solid var(--color-border-lighter);
306
- flex-shrink: 0;
307
-
308
- .layout__logo {
309
- display: flex;
310
- align-items: center;
311
- gap: 10px;
312
- margin-right: 30px;
313
- }
314
-
315
- .layout__logo-img {
316
- width: 32px;
317
- height: 32px;
318
- }
319
-
320
- .layout__logo-text {
321
- font-size: 16px;
322
- font-weight: 600;
323
- color: var(--color-primary);
324
- }
325
-
326
- .layout__top-menu {
327
- flex: 1;
328
- border-bottom: none;
329
- background-color: transparent;
330
- }
331
-
332
- .layout__header-right {
333
- display: flex;
334
- align-items: center;
335
- }
336
- }
337
-
338
- .layout__content-top {
339
- flex: 1;
340
- overflow: auto;
341
- background-color: var(--bg-color-page);
342
- }
343
- }
344
-
345
- // 混合布局
346
- &--mix {
347
- flex-direction: column;
348
-
349
- .layout__header-mix {
350
- height: 60px;
351
- display: flex;
352
- align-items: center;
353
- padding: 0 20px;
354
- background-color: var(--bg-color);
355
- border-bottom: 1px solid var(--color-border-lighter);
356
- flex-shrink: 0;
357
-
358
- .layout__logo {
359
- display: flex;
360
- align-items: center;
361
- gap: 10px;
362
- margin-right: 30px;
363
- }
364
-
365
- .layout__logo-img {
366
- width: 32px;
367
- height: 32px;
368
- }
369
-
370
- .layout__logo-text {
371
- font-size: 16px;
372
- font-weight: 600;
373
- color: var(--color-primary);
374
- }
375
-
376
- .layout__top-menu {
377
- flex: 1;
378
- border-bottom: none;
379
- background-color: transparent;
380
- }
381
-
382
- .layout__header-right {
383
- display: flex;
384
- align-items: center;
385
- }
386
- }
387
-
388
- .layout__mix-body {
389
- flex: 1;
390
- display: flex;
391
- overflow: hidden;
392
-
393
- .layout__mix-aside {
394
- transition: width 0.3s;
395
- overflow: hidden;
396
- flex-shrink: 0;
397
- background-color: var(--bg-color);
398
- border-right: 1px solid var(--color-border-lighter);
399
- }
400
-
401
- .layout__mix-sidebar {
402
- height: 100%;
403
- display: flex;
404
- flex-direction: column;
405
- }
406
-
407
- .layout__mix-menu {
408
- flex: 1;
409
- border-right: none;
410
- overflow-y: auto;
411
- }
412
-
413
- .layout__content-mix {
414
- flex: 1;
415
- overflow: auto;
416
- background-color: var(--bg-color-page);
417
- }
418
- }
419
- }
420
-
421
- // 公共样式
422
- &__menu-icon {
423
- display: inline-flex;
424
- align-items: center;
425
- justify-content: center;
426
- width: 16px;
427
- height: 16px;
428
- margin-right: 8px;
429
- }
430
-
431
- &__menu-char {
432
- display: inline-flex;
433
- align-items: center;
434
- justify-content: center;
435
- width: 16px;
436
- height: 16px;
437
- font-size: 12px;
438
- font-weight: 600;
439
- color: var(--color-primary);
440
- background-color: var(--color-primary-light-8);
441
- border-radius: 4px;
442
- }
443
- }
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
+
9
+ const appStore = useAppStore()
10
+ const menuStore = useMenuStore()
11
+
12
+ const sidebarWidth = computed(() =>
13
+ appStore.isCollapsed ? '64px' : '210px'
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
+ })
32
+ </script>
33
+
34
+ <template>
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" />
39
+ </aside>
40
+
41
+ <!-- 顶部菜单布局 -->
42
+ <div v-if="showTopMenu" class="layout__top-menu">
43
+ <TopMenu />
44
+ </div>
45
+
46
+ <div class="layout__main">
47
+ <header class="layout__header">
48
+ <Header />
49
+ </header>
50
+ <main class="layout__content">
51
+ <router-view />
52
+ </main>
53
+ </div>
54
+ </div>
55
+ </template>
56
+
57
+ <style lang="scss" scoped>
58
+ .layout {
59
+ display: flex;
60
+ width: 100%;
61
+ height: 100%;
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
+
86
+ &__aside {
87
+ transition: width 0.3s;
88
+ overflow: hidden;
89
+ flex-shrink: 0;
90
+ height: 100%;
91
+ }
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
+
100
+ &__main {
101
+ flex: 1;
102
+ display: flex;
103
+ flex-direction: column;
104
+ overflow: hidden;
105
+ height: 100%;
106
+ }
107
+
108
+ &__header {
109
+ height: 50px;
110
+ background-color: var(--bg-color);
111
+ border-bottom: 1px solid var(--color-border-lighter);
112
+ flex-shrink: 0;
113
+ }
114
+
115
+ &__content {
116
+ flex: 1;
117
+ overflow: auto;
118
+ background-color: var(--bg-color-page);
119
+ }
120
+ }
444
121
  </style>
package/vite.config.ts CHANGED
@@ -49,7 +49,7 @@ export default defineConfig(({ mode }) => {
49
49
  open: true,
50
50
  proxy: {
51
51
  '/api': {
52
- target: 'http://localhost:8888',
52
+ target: env.VITE_API_BASE_URL || 'http://localhost:8080',
53
53
  changeOrigin: true,
54
54
  rewrite: (path) => path.replace(/^\/api/, '')
55
55
  }
package/dist/App.vue.d.ts DELETED
@@ -1,2 +0,0 @@
1
- declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
2
- export default _default;
@@ -1,8 +0,0 @@
1
- import { LoginParams, LoginResult, UserInfo } from '../types/api';
2
- export declare function login(data: LoginParams): Promise<LoginResult>;
3
- export declare function logout(): Promise<unknown>;
4
- export declare function getUserInfo(): Promise<UserInfo>;
5
- export declare function refreshToken(refreshToken: string): Promise<{
6
- token: string;
7
- expireTime: number;
8
- }>;
@@ -1,16 +0,0 @@
1
- import { PageParams, PageResponse } from '../utils/request';
2
- import { RoleInfo, MenuItem } from '../types/api';
3
- export declare function getRoleList(params: PageParams & {
4
- status?: number;
5
- keyword?: string;
6
- }): Promise<PageResponse<RoleInfo>>;
7
- export declare function getRoleDetail(id: string | number): Promise<RoleInfo>;
8
- export declare function createRole(data: Partial<RoleInfo>): Promise<RoleInfo>;
9
- export declare function updateRole(id: string | number, data: Partial<RoleInfo>): Promise<RoleInfo>;
10
- export declare function deleteRole(id: string | number): Promise<unknown>;
11
- export declare function updateRoleStatus(id: string | number, status: number): Promise<unknown>;
12
- export declare function getMenuList(): Promise<MenuItem[]>;
13
- export declare function getMenuTree(appId?: string): Promise<MenuItem[]>;
14
- export declare function createMenu(data: Partial<MenuItem>): Promise<MenuItem>;
15
- export declare function updateMenu(id: string | number, data: Partial<MenuItem>): Promise<MenuItem>;
16
- export declare function deleteMenu(id: string | number): Promise<unknown>;
@@ -1,13 +0,0 @@
1
- import { PageParams, PageResponse } from '../utils/request';
2
- import { UserInfo } from '../types/api';
3
- export declare function getUserList(params: PageParams & {
4
- status?: number;
5
- keyword?: string;
6
- }): Promise<PageResponse<UserInfo>>;
7
- export declare function getUserDetail(id: string | number): Promise<UserInfo>;
8
- export declare function createUser(data: Partial<UserInfo>): Promise<UserInfo>;
9
- export declare function updateUser(id: string | number, data: Partial<UserInfo>): Promise<UserInfo>;
10
- export declare function deleteUser(id: string | number): Promise<unknown>;
11
- export declare function batchDeleteUsers(ids: (string | number)[]): Promise<unknown>;
12
- export declare function updateUserStatus(id: string | number, status: number): Promise<unknown>;
13
- export declare function resetPassword(id: string | number): Promise<unknown>;
@@ -1 +0,0 @@
1
- import{d as x,o as T,c as h,a as p,B as t,C as l,u as a,I as B,k as g,P as I,Q as R,R as q,h as b}from"./vue-vendor-Br-l7wbK.js";import{_ as z}from"./vite-Dw-pgLOX.js";import{r as v,o as C}from"./xto-base-C-IBqjVs.js";import{B as j,F as c,w as y,T as P}from"./xto-form-NRjKKNcY.js";import{c as i}from"./xto-feedback-B7ipsTfz.js";import{a as U}from"./vendor-42ANG6Sg.js";import{g as L,a as N,c as A,b as D,d as E,s as F}from"./index-CkL3sVAQ.js";import{_ as K}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./xto-core-DZK7Cyg0.js";import"./xto-data-BFpiDgJi.js";import"./xto-navigation-CKabFu9d.js";/* empty css *//* empty css */const $=()=>{const s=U.create({baseURL:"/api",timeout:3e4,headers:{"Content-Type":"application/json"}});return s.interceptors.request.use(e=>{const r=L(),n=N()||"Bearer";return r&&(e.headers.Authorization=`${n} ${r}`),e},e=>Promise.reject(e)),s.interceptors.response.use(e=>{const{data:r}=e;return r.code===200||r.code===0?r.data:(i.error(r.message||"请求失败"),Promise.reject(new Error(r.message||"请求失败")))},e=>{var n;const{response:r}=e;if(r)switch(r.status){case 401:i.error("登录已过期,请重新登录"),A(),window.location.href="/login";break;case 403:i.error("没有权限访问");break;case 404:i.error("请求资源不存在");break;case 500:i.error("服务器错误");break;default:i.error(((n=r.data)==null?void 0:n.message)||"请求失败")}else i.error("网络连接失败");return Promise.reject(e)}),s},m=$(),M={get(s,e){return m.get(s,e)},post(s,e,r){return m.post(s,e,r)},put(s,e,r){return m.put(s,e,r)},patch(s,e,r){return m.patch(s,e,r)},delete(s,e){return m.delete(s,e)}};function Q(s){return M.post("/user/v1.0/login/by-domain",s)}const X={class:"login"},G={class:"login__container"},H=x({__name:"index",setup(s){const e=I(),r=R(),n=g(!1),_=g(!1),u=B({uid:"",password:""}),V={uid:[{required:!0,message:"请输入用户名",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"},{min:6,message:"密码长度至少6位",trigger:"blur"}]},w=g(),k=async()=>{var f;try{await((f=w.value)==null?void 0:f.validate()),n.value=!0;const o=await Q({appId:E(),clientId:D(),uid:u.uid,password:u.password,code:!0});F(o),i.success("登录成功");const d=r.query.redirect||"/";e.push(d)}catch(o){console.error("登录失败:",o)}finally{n.value=!1}};return(f,o)=>(T(),h("div",X,[p("div",G,[o[5]||(o[5]=p("div",{class:"login__header"},[p("img",{src:z,alt:"Logo",class:"login__logo"}),p("h1",{class:"login__title"},"Xto Demo"),p("p",{class:"login__subtitle"},"后台管理系统")],-1)),t(a(j),{ref_key:"formRef",ref:w,model:u,rules:V,class:"login__form","label-width":"0"},{default:l(()=>[t(a(c),{prop:"uid"},{default:l(()=>[t(a(y),{modelValue:u.uid,"onUpdate:modelValue":o[0]||(o[0]=d=>u.uid=d),placeholder:"用户名",size:"large"},{prefix:l(()=>[t(a(v),{name:"user",size:18})]),_:1},8,["modelValue"])]),_:1}),t(a(c),{prop:"password"},{default:l(()=>[t(a(y),{modelValue:u.password,"onUpdate:modelValue":o[1]||(o[1]=d=>u.password=d),type:"password",placeholder:"密码",size:"large","show-password":"",onKeyup:q(k,["enter"])},{prefix:l(()=>[t(a(v),{name:"lock",size:18})]),_:1},8,["modelValue"])]),_:1}),t(a(c),null,{default:l(()=>[t(a(P),{modelValue:_.value,"onUpdate:modelValue":o[2]||(o[2]=d=>_.value=d)},{default:l(()=>[...o[3]||(o[3]=[b("记住我",-1)])]),_:1},8,["modelValue"])]),_:1}),t(a(c),null,{default:l(()=>[t(a(C),{type:"primary",size:"large",loading:n.value,class:"login__submit",onClick:k},{default:l(()=>[...o[4]||(o[4]=[b(" 登录 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"]),o[6]||(o[6]=p("div",{class:"login__footer"},[p("p",null,"请输入您的用户名和密码")],-1))])]))}}),ne=K(H,[["__scopeId","data-v-6e75b294"]]);export{ne as default};
@@ -1 +0,0 @@
1
- .app{width:100%;height:100%;background-color:var(--bg-color-page);transition:background-color .3s}:root{--color-primary: #409eff;--color-primary-light-3: #79bbff;--color-primary-light-5: #a0cfff;--color-primary-light-7: #c6e2ff;--color-primary-light-8: #d9ecff;--color-primary-light-9: #ecf5ff;--color-primary-dark-2: #337ecc;--color-success: #67c23a;--color-success-light: #e1f3d8;--color-success-dark: #529b2e;--color-warning: #e6a23c;--color-warning-light: #fdf6ec;--color-warning-dark: #b88230;--color-danger: #f56c6c;--color-danger-light: #fde2e2;--color-danger-dark: #c45656;--color-info: #909399;--color-info-light: #f4f4f5;--color-info-dark: #73767a;--color-text-primary: #303133;--color-text-regular: #606266;--color-text-secondary: #909399;--color-text-placeholder: #a8abb2;--color-text-disabled: #c0c4cc;--color-border: #dcdfe6;--color-border-light: #e4e7ed;--color-border-lighter: #ebeef5;--color-border-extra-light: #f2f6fc;--color-border-dark: #d4d7de;--color-fill: #f5f7fa;--color-fill-light: #fafafa;--color-fill-lighter: #fafcff;--color-fill-blank: #ffffff;--bg-color: #ffffff;--bg-color-page: #f2f3f5;--bg-color-overlay: #ffffff;--box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);--box-shadow-light: 0 2px 8px 0 rgba(0, 0, 0, .06);--box-shadow-lighter: 0 1px 4px 0 rgba(0, 0, 0, .04);--box-shadow-dark: 0 4px 16px 0 rgba(0, 0, 0, .12);--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-size-base: 14px;--font-size-small: 12px;--font-size-large: 16px;--font-size-extra-large: 18px;--border-radius-base: 4px;--border-radius-small: 2px;--border-radius-large: 8px;--border-radius-round: 20px;--border-radius-circle: 50%;--spacing-xs: 4px;--spacing-sm: 8px;--spacing-md: 16px;--spacing-lg: 24px;--spacing-xl: 32px;--component-size-large: 40px;--component-size-default: 32px;--component-size-small: 24px;--transition-duration: .3s;--transition-duration-fast: .2s;--transition-duration-slow: .5s;--z-index-dropdown: 1000;--z-index-sticky: 1020;--z-index-fixed: 1030;--z-index-modal-backdrop: 1040;--z-index-modal: 1050;--z-index-popover: 1060;--z-index-tooltip: 1070;--sidebar-width: 210px;--sidebar-collapsed-width: 64px;--header-height: 50px;--tabs-height: 40px;--footer-height: 30px}.dark{--color-text-primary: #e5eaf3;--color-text-regular: #cfd3dc;--color-text-secondary: #a3a6ad;--color-text-placeholder: #8d9095;--color-text-disabled: #6c6e72;--color-border: #4c4d4f;--color-border-light: #414243;--color-border-lighter: #363637;--color-border-extra-light: #2b2b2c;--color-border-dark: #58585b;--color-fill: #303030;--color-fill-light: #262727;--color-fill-lighter: #1d1d1d;--color-fill-blank: #141414;--bg-color: #1d1e1f;--bg-color-page: #0a0a0a;--bg-color-overlay: #1d1e1f;--box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .3);--box-shadow-light: 0 2px 8px 0 rgba(0, 0, 0, .24);--box-shadow-lighter: 0 1px 4px 0 rgba(0, 0, 0, .2);--box-shadow-dark: 0 4px 16px 0 rgba(0, 0, 0, .36)}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{width:100%;height:100%;font-size:var(--font-size-base);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{width:100%;height:100%;font-family:var(--font-family);font-size:var(--font-size-base);line-height:1.5;color:var(--color-text-primary);background-color:var(--bg-color-page)}#app{width:100%;height:100%}a{color:var(--color-primary);text-decoration:none;cursor:pointer;transition:color var(--transition-duration-fast)}a:hover{color:var(--color-primary-light-3)}ul,ol{list-style:none}img{max-width:100%;height:auto;vertical-align:middle}button{cursor:pointer;font-family:inherit;font-size:inherit;border:none;background:none;outline:none}button:disabled{cursor:not-allowed}input,textarea,select{font-family:inherit;font-size:inherit;outline:none}table{border-collapse:collapse;border-spacing:0}h1,h2,h3,h4,h5,h6{margin:0;font-weight:500;color:var(--color-text-primary)}p{margin:0}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background-color:var(--color-fill-light);border-radius:3px}::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background-color:var(--color-text-secondary)}::selection{background-color:var(--color-primary-light-8);color:var(--color-primary)}.fade-enter-active,.fade-leave-active{transition:opacity var(--transition-duration)}.fade-enter-from,.fade-leave-to{opacity:0}.fade-scale-enter-active,.fade-scale-leave-active{transition:all var(--transition-duration)}.fade-scale-enter-from,.fade-scale-leave-to{opacity:0;transform:scale(.9)}.fade-transform-enter-active,.fade-transform-leave-active{transition:all var(--transition-duration-fast)}.fade-transform-enter-from{opacity:0;transform:translate(-10px)}.fade-transform-leave-to{opacity:0;transform:translate(10px)}.slide-down-enter-active,.slide-down-leave-active{transition:all var(--transition-duration)}.slide-down-enter-from,.slide-down-leave-to{opacity:0;transform:translateY(-20px)}.slide-up-enter-active,.slide-up-leave-active{transition:all var(--transition-duration)}.slide-up-enter-from,.slide-up-leave-to{opacity:0;transform:translateY(20px)}.slide-left-enter-active,.slide-left-leave-active{transition:all var(--transition-duration)}.slide-left-enter-from,.slide-left-leave-to{opacity:0;transform:translate(20px)}.slide-right-enter-active,.slide-right-leave-active{transition:all var(--transition-duration)}.slide-right-enter-from,.slide-right-leave-to{opacity:0;transform:translate(-20px)}.zoom-enter-active,.zoom-leave-active{transition:all var(--transition-duration)}.zoom-enter-from,.zoom-leave-to{opacity:0;transform:scale(.5)}.list-enter-active,.list-leave-active{transition:all var(--transition-duration)}.list-enter-from,.list-leave-to{opacity:0;transform:translateY(30px)}.collapse-transition{transition:width var(--transition-duration),padding var(--transition-duration)}.dark .sidebar,.dark .layout__aside{background-color:#1d1e1f}.dark .sidebar{border-right:1px solid #363637}.dark .sidebar__search-results{background-color:#1d1e1f;border-color:#363637}.dark .sidebar__search-item:hover{background-color:#262727}.dark .sidebar__search-item-title{color:#cfd3dc}.dark .sidebar__search-item-parent{color:#a3a6ad}.dark .sidebar__logo{border-bottom-color:#363637}.dark .sidebar__user{border-top-color:#363637}.dark .sidebar__user-name{color:#cfd3dc}.dark .sidebar__user-role{color:#a3a6ad}.dark .x-menu{background-color:#1d1e1f!important;border-color:#363637;color:#cfd3dc}.dark .x-menu.x-menu--vertical{border-right-color:#363637}.dark .x-menu.x-menu--horizontal{border-bottom-color:#363637}.dark .x-menu-item{color:#cfd3dc!important}.dark .x-menu-item:hover{background-color:#262727!important}.dark .x-menu-item.is-active{color:#409eff!important;background-color:#409eff1a!important}.dark .x-menu-item.is-active:before{background-color:#409eff}.dark .x-sub-menu__title{color:#cfd3dc!important}.dark .x-sub-menu__title:hover{background-color:#262727!important}.dark .x-sub-menu__menu{background-color:#1d1e1f!important;border:1px solid #363637;box-shadow:0 2px 12px #00000080}.dark .x-sub-menu__arrow{color:#a3a6ad}.dark .x-sub-menu.is-opened>.x-sub-menu__title{background-color:#262727!important}.dark .x-sub-menu.is-active>.x-sub-menu__title{color:#409eff!important}.dark .layout__menu-char{background-color:#409eff33;color:#79bbff}.dark .header{background-color:#1d1e1f;border-bottom-color:#363637}.dark .header__collapse{color:#cfd3dc}.dark .header__breadcrumb{color:#a3a6ad}.dark .header__user-name{color:#cfd3dc}.dark .header__user-arrow{color:#a3a6ad}.dark .header__action:hover,.dark .header__user-trigger:hover{background-color:#262727}.dark .header__dropdown{background-color:#1d1e1f;border:1px solid #363637;box-shadow:0 2px 12px #00000080}.dark .header__dropdown-name{color:#e5eaf3}.dark .header__dropdown-role{color:#a3a6ad}.dark .header__dropdown-divider{background-color:#363637}.dark .header__dropdown-item{color:#cfd3dc}.dark .header__dropdown-item:hover{background-color:#262727;color:#e5eaf3}.dark .x-button.x-button--default{background-color:#1d1e1f;border-color:#4c4d4f;color:#cfd3dc}.dark .x-button.x-button--default:hover{border-color:#409eff;color:#409eff}.dark .x-button.x-button--text{color:#409eff}.dark .x-form-item__label{color:#cfd3dc}.dark .x-form-item__error{color:#f56c6c}.dark .x-input{background-color:#1d1e1f;border-color:#4c4d4f}.dark .x-input.is-focus{border-color:#409eff}.dark .x-input .x-input__inner{background-color:transparent;color:#e5eaf3}.dark .x-input .x-input__inner::placeholder{color:#6c6e72}.dark .x-input .x-input__suffix,.dark .x-input .x-input__prefix{color:#a3a6ad}.dark .x-select{background-color:#1d1e1f;border-color:#4c4d4f}.dark .x-card{background-color:#1d1e1f;border-color:#363637}.dark .x-card__header{border-bottom-color:#363637;color:#e5eaf3}.dark .data-table th{background-color:#262727;color:#cfd3dc;border-bottom-color:#363637}.dark .data-table td{border-bottom-color:#363637;color:#cfd3dc}.dark .data-table tr:hover td{background-color:#262727}.dark .x-modal__wrapper{background-color:#000000b3}.dark .x-modal__container{background-color:#1d1e1f;border:1px solid #363637}.dark .x-modal__header{border-bottom-color:#363637;color:#e5eaf3}.dark .x-modal__footer{border-top-color:#363637}.dark .x-message{background-color:#1d1e1f;border:1px solid #363637}.dark .x-tag.x-tag--primary{background-color:#409eff33;color:#79bbff;border-color:#409eff4d}.dark .x-tag.x-tag--success{background-color:#67c23a33;color:#95d475;border-color:#67c23a4d}.dark .x-tag.x-tag--warning{background-color:#e6a23c33;color:#eebe77;border-color:#e6a23c4d}.dark .x-tag.x-tag--danger{background-color:#f56c6c33;color:#fab6b6;border-color:#f56c6c4d}.dark .x-tag.x-tag--info{background-color:#90939933;color:#c0c4cc;border-color:#9093994d}.dark .x-switch{background-color:#4c4d4f}.dark .x-switch.is-checked{background-color:#409eff}.dark .x-pagination{color:#cfd3dc}.dark .x-pagination__item{background-color:#1d1e1f;border-color:#4c4d4f;color:#cfd3dc}.dark .x-pagination__item:hover{color:#409eff}.dark .x-pagination__item.is-active{background-color:#409eff;border-color:#409eff;color:#fff}.dark .login{background:linear-gradient(135deg,#1a1a2e,#16213e)}.dark .login__container{background-color:#1d1e1f;border:1px solid #363637}.dark .login__title{color:#409eff}.dark .login__subtitle{color:#a3a6ad}.dark .login__footer{color:#6c6e72}.dark .stat-card__title{color:#a3a6ad}.dark .quick-link{background-color:#262727}.dark .quick-link:hover{background-color:#409eff1a}.dark .quick-link__title{color:#cfd3dc}.dark .activity-item{border-bottom-color:#363637}.dark .activity-item__action{color:#cfd3dc}.dark .search-card,.dark .table-card,.dark .x-popconfirm{background-color:#1d1e1f;border:1px solid #363637}.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-ellipsis-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.flex{display:flex}.flex-center{display:flex;align-items:center;justify-content:center}.flex-between{display:flex;align-items:center;justify-content:space-between}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-primary{color:var(--color-primary)}.text-success{color:var(--color-success)}.text-warning{color:var(--color-warning)}.text-danger{color:var(--color-danger)}.text-info{color:var(--color-info)}.bg-primary{background-color:var(--color-primary)}.bg-success{background-color:var(--color-success)}.bg-warning{background-color:var(--color-warning)}.bg-danger{background-color:var(--color-danger)}.mt-10{margin-top:10px}.mt-20{margin-top:20px}.mb-10{margin-bottom:10px}.mb-20{margin-bottom:20px}.ml-10{margin-left:10px}.mr-10{margin-right:10px}.p-10{padding:10px}.p-20{padding:20px}.card{background-color:var(--bg-color);border-radius:var(--border-radius-base);box-shadow:var(--box-shadow-light);padding:var(--spacing-md)}.page-container{padding:var(--spacing-md);min-height:100%}.search-bar{display:flex;flex-wrap:wrap;gap:var(--spacing-sm);margin-bottom:var(--spacing-md)}.toolbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-md)}.table-container{background-color:var(--bg-color);border-radius:var(--border-radius-base);padding:var(--spacing-md)}.pagination-container{display:flex;justify-content:flex-end;margin-top:var(--spacing-md)}