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.
- package/dist/assets/index-4-QoJAgA.css +1 -0
- package/dist/assets/index-BHwEwbkp.js +1 -0
- package/dist/assets/{index-Te8_PRgJ.js → index-BTsRosKu.js} +1 -1
- package/dist/assets/index-CZAlkDIC.css +1 -0
- package/dist/assets/{index-1juADvYN.js → index-Do3gMkWw.js} +2 -2
- package/dist/index.html +2 -2
- package/package.json +4 -4
- package/src/assets/styles/_dark.scss +118 -0
- package/src/assets/styles/index.scss +8 -0
- package/src/components/Layout/Header.vue +0 -5
- package/src/components/Layout/Sidebar.vue +11 -1
- package/src/components/Layout/TopMenu.vue +186 -0
- package/src/components/Layout/index.vue +120 -443
- package/vite.config.ts +1 -1
- 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/index-B-sX4Ru0.js +0 -1
- package/dist/assets/index-BMcziU5a.css +0 -1
- package/dist/assets/index-BZA0ksjx.css +0 -1
- package/dist/assets/index-BvzhR4zp.js +0 -1
- package/dist/assets/index-CVjdnIgR.css +0 -1
- package/dist/assets/index-CYq57-zj.js +0 -1
- package/dist/assets/index-CkL3sVAQ.js +0 -2
- package/dist/assets/index-CtrKVYJb.css +0 -1
- package/dist/assets/index-DfFR6NLf.js +0 -1
- package/dist/assets/index-Iaz1ZzPC.js +0 -2
- package/dist/assets/index-WyZ91RLx.css +0 -1
- package/dist/assets/index-tFYRoFdE.js +0 -1
- package/dist/assets/xto-navigation-CBPg4dCc.css +0 -1
- package/dist/assets/xto-navigation-CKabFu9d.js +0 -1
- package/dist/components/Layout/Footer.vue.d.ts +0 -2
- package/dist/components/Layout/Header.vue.d.ts +0 -5
- package/dist/components/Layout/Sidebar.vue.d.ts +0 -2
- package/dist/components/Layout/Tabs.vue.d.ts +0 -2
- 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/useTable.d.ts +0 -29
- package/dist/directives/permission.d.ts +0 -4
- package/dist/enums/index.d.ts +0 -32
- package/dist/index-54irhCHL.js +0 -1830
- package/dist/index-BzRf1eoJ.js +0 -372
- package/dist/index-DH4aoCZb.js +0 -142
- package/dist/index-Kqa7iZ9E.js +0 -475
- package/dist/index-pxkZlvBw.js +0 -345
- package/dist/index.d.ts +0 -31
- package/dist/index.es.js +0 -91
- package/dist/index.umd.js +0 -1
- 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 -18
- package/dist/router/staticRoutes.d.ts +0 -3
- package/dist/stores/app.d.ts +0 -87
- package/dist/stores/auth.d.ts +0 -41
- package/dist/stores/index.d.ts +0 -9
- 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 -23
- 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,444 +1,121 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
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
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;
|
package/dist/api/auth.d.ts
DELETED
|
@@ -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
|
-
}>;
|
package/dist/api/system.d.ts
DELETED
|
@@ -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>;
|
package/dist/api/user.d.ts
DELETED
|
@@ -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)}
|