vue3-admin-gpt 1.0.0

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 (118) hide show
  1. package/.env.development +14 -0
  2. package/.env.production +14 -0
  3. package/LICENSE +21 -0
  4. package/README.en.md +106 -0
  5. package/README.md +104 -0
  6. package/build-zip.cjs +53 -0
  7. package/cli.js +110 -0
  8. package/jsconfig.json +9 -0
  9. package/package.json +92 -0
  10. package/public/index.html +20 -0
  11. package/public/robots.txt +2 -0
  12. package/rspack.config.js +282 -0
  13. package/rspack.js +162 -0
  14. package/src/App.vue +9 -0
  15. package/src/api/icon.js +9 -0
  16. package/src/api/router.js +9 -0
  17. package/src/api/table.js +25 -0
  18. package/src/api/tree.js +9 -0
  19. package/src/api/user.js +34 -0
  20. package/src/assets/error_images/401.png +0 -0
  21. package/src/assets/error_images/404.png +0 -0
  22. package/src/assets/error_images/cloud.png +0 -0
  23. package/src/assets/login_images/background.jpg +0 -0
  24. package/src/assets/logo.png +0 -0
  25. package/src/assets/qr_logo/lqr_logo.png +0 -0
  26. package/src/assets/vuejs-fill.svg +4 -0
  27. package/src/components/VabPageHeader/index.vue +133 -0
  28. package/src/config/index.js +7 -0
  29. package/src/config/net.config.js +20 -0
  30. package/src/config/permission.js +136 -0
  31. package/src/config/setting.config.js +62 -0
  32. package/src/config/settings.js +6 -0
  33. package/src/config/theme.config.js +14 -0
  34. package/src/layouts/EmptyLayout.vue +3 -0
  35. package/src/layouts/components/VabAppMain/index.vue +109 -0
  36. package/src/layouts/components/VabAvatar/index.vue +255 -0
  37. package/src/layouts/components/VabBreadcrumb/index.vue +61 -0
  38. package/src/layouts/components/VabFullScreen/index.vue +61 -0
  39. package/src/layouts/components/VabLogo/index.vue +94 -0
  40. package/src/layouts/components/VabNav/index.vue +176 -0
  41. package/src/layouts/components/VabSide/components/VabMenuItem.vue +80 -0
  42. package/src/layouts/components/VabSide/components/VabSideItem.vue +100 -0
  43. package/src/layouts/components/VabSide/components/VabSubmenu.vue +56 -0
  44. package/src/layouts/components/VabSide/index.vue +123 -0
  45. package/src/layouts/components/VabTabs/index.vue +500 -0
  46. package/src/layouts/components/VabTheme/index.vue +603 -0
  47. package/src/layouts/components/VabTop/index.vue +286 -0
  48. package/src/layouts/export.js +29 -0
  49. package/src/layouts/index.vue +339 -0
  50. package/src/main.js +40 -0
  51. package/src/plugins/echarts.js +4 -0
  52. package/src/plugins/index.js +44 -0
  53. package/src/plugins/support.js +16 -0
  54. package/src/router/index.js +400 -0
  55. package/src/store/index.js +26 -0
  56. package/src/store/modules/errorLog.js +27 -0
  57. package/src/store/modules/routes.js +60 -0
  58. package/src/store/modules/settings.js +73 -0
  59. package/src/store/modules/table.js +22 -0
  60. package/src/store/modules/tabsBar.js +109 -0
  61. package/src/store/modules/user.js +131 -0
  62. package/src/styles/element-variables.scss +13 -0
  63. package/src/styles/loading.scss +345 -0
  64. package/src/styles/nav-icons.scss +52 -0
  65. package/src/styles/normalize.scss +353 -0
  66. package/src/styles/spinner/dots.css +68 -0
  67. package/src/styles/spinner/gauge.css +104 -0
  68. package/src/styles/spinner/inner-circles.css +51 -0
  69. package/src/styles/spinner/plus.css +341 -0
  70. package/src/styles/themes/default.scss +1 -0
  71. package/src/styles/transition.scss +18 -0
  72. package/src/styles/vab.scss +476 -0
  73. package/src/styles/variables.scss +69 -0
  74. package/src/utils/accessToken.js +56 -0
  75. package/src/utils/eventBus.js +8 -0
  76. package/src/utils/handleRoutes.js +100 -0
  77. package/src/utils/index.js +231 -0
  78. package/src/utils/message.js +67 -0
  79. package/src/utils/pageTitle.js +11 -0
  80. package/src/utils/password.js +43 -0
  81. package/src/utils/permission.js +19 -0
  82. package/src/utils/request.js +187 -0
  83. package/src/utils/static.js +81 -0
  84. package/src/utils/vab.js +218 -0
  85. package/src/utils/validate.js +48 -0
  86. package/src/views/401.vue +302 -0
  87. package/src/views/404.vue +302 -0
  88. package/src/views/demo/index.vue +591 -0
  89. package/src/views/index/index.vue +1489 -0
  90. package/src/views/login/index.vue +456 -0
  91. package/src/views/register/index.vue +524 -0
  92. package/src/views/vab/calendar.vue +488 -0
  93. package/src/views/vab/campaign.vue +1006 -0
  94. package/src/views/vab/chart.vue +189 -0
  95. package/src/views/vab/customer.vue +666 -0
  96. package/src/views/vab/editor.vue +84 -0
  97. package/src/views/vab/form.vue +151 -0
  98. package/src/views/vab/help.vue +390 -0
  99. package/src/views/vab/icon.vue +113 -0
  100. package/src/views/vab/knowledge.vue +820 -0
  101. package/src/views/vab/nested/menu1/menu2/menu3.vue +29 -0
  102. package/src/views/vab/nested/menu1/menu2.vue +33 -0
  103. package/src/views/vab/nested/menu1.vue +33 -0
  104. package/src/views/vab/nested.vue +97 -0
  105. package/src/views/vab/notification.vue +416 -0
  106. package/src/views/vab/order.vue +507 -0
  107. package/src/views/vab/permissions.vue +214 -0
  108. package/src/views/vab/product.vue +724 -0
  109. package/src/views/vab/project.vue +559 -0
  110. package/src/views/vab/settings.vue +319 -0
  111. package/src/views/vab/statistics.vue +431 -0
  112. package/src/views/vab/table.vue +110 -0
  113. package/src/views/vab/task.vue +613 -0
  114. package/src/views/vab/team.vue +662 -0
  115. package/src/views/vab/tree.vue +44 -0
  116. package/src/views/vab/upload.vue +180 -0
  117. package/src/views/vab/vue3Demo/index.vue +103 -0
  118. package/src/views/vab/workflow.vue +863 -0
@@ -0,0 +1,1489 @@
1
+ <template>
2
+ <div class="index-container">
3
+ <el-row :gutter="20">
4
+ <el-col :lg="6" :md="12" :sm="24" :xl="6" :xs="24">
5
+ <el-card shadow="never">
6
+ <template #header>
7
+ <span>访问量</span>
8
+ </template>
9
+ <div class="chart-container">
10
+ <div class="chart-header">
11
+ <div class="chart-title">
12
+ <span>今日访问趋势</span>
13
+ </div>
14
+ <div class="chart-stats">
15
+ <div class="stat-item">
16
+ <div class="stat-value">{{ config1.endVal }}</div>
17
+ <div class="stat-label">总访问量</div>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <div class="chart-content">
22
+ <vab-chart autoresize :option="fwl" />
23
+ </div>
24
+ <div class="chart-footer">
25
+ <div class="trend-info">
26
+ <div class="trend-item">
27
+ <el-icon class="trend-up"><ArrowUp /></el-icon>
28
+ <span class="trend-text">较昨日增长 12.5%</span>
29
+ </div>
30
+ <div class="trend-item">
31
+ <el-icon class="trend-icon"><User /></el-icon>
32
+ <span class="trend-text">活跃用户 2.3K</span>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ </el-card>
38
+ </el-col>
39
+ <el-col :lg="6" :md="12" :sm="24" :xl="6" :xs="24">
40
+ <el-card shadow="never">
41
+ <template #header>
42
+ <span>授权数</span>
43
+ </template>
44
+ <div class="chart-container">
45
+ <div class="chart-header">
46
+ <div class="chart-title">
47
+ <span>授权统计</span>
48
+ </div>
49
+ <div class="chart-stats">
50
+ <div class="stat-item">
51
+ <div class="stat-value">{{ config2.endVal }}</div>
52
+ <div class="stat-label">总授权数</div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ <div class="chart-content">
57
+ <vab-chart autoresize :option="sqs" />
58
+ </div>
59
+ <div class="chart-footer">
60
+ <div class="trend-info">
61
+ <div class="trend-item">
62
+ <el-icon class="trend-up"><ArrowUp /></el-icon>
63
+ <span class="trend-text">较昨日增长 8.3%</span>
64
+ </div>
65
+ <div class="trend-item">
66
+ <el-icon class="trend-icon"><Clock /></el-icon>
67
+ <span class="trend-text">今日新增 156</span>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ </div>
72
+ </el-card>
73
+ </el-col>
74
+ <el-col :lg="6" :md="12" :sm="24" :xl="6" :xs="24">
75
+ <el-card shadow="never">
76
+ <template #header>
77
+ <span>用户活跃度</span>
78
+ </template>
79
+ <div class="chart-container">
80
+ <div class="chart-header">
81
+ <div class="chart-title">
82
+ <span>用户活跃统计</span>
83
+ </div>
84
+ <div class="chart-stats">
85
+ <div class="stat-item">
86
+ <div class="stat-value">{{ config3.endVal }}</div>
87
+ <div class="stat-label">活跃用户</div>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ <div class="chart-content">
92
+ <vab-chart autoresize :option="userActivity" />
93
+ </div>
94
+ <div class="chart-footer">
95
+ <div class="trend-info">
96
+ <div class="trend-item">
97
+ <el-icon class="trend-up"><ArrowUp /></el-icon>
98
+ <span class="trend-text">较昨日增长 15.2%</span>
99
+ </div>
100
+ <div class="trend-item">
101
+ <el-icon class="trend-icon"><Clock /></el-icon>
102
+ <span class="trend-text">在线时长 2.5h</span>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </el-card>
108
+ </el-col>
109
+ <el-col :lg="6" :md="12" :sm="24" :xl="6" :xs="24">
110
+ <el-card shadow="never">
111
+ <template #header>
112
+ <span>系统性能</span>
113
+ </template>
114
+ <div class="chart-container">
115
+ <div class="chart-header">
116
+ <div class="chart-title">
117
+ <span>性能监控</span>
118
+ </div>
119
+ <div class="chart-stats">
120
+ <div class="stat-item">
121
+ <div class="stat-value">98.5%</div>
122
+ <div class="stat-label">系统可用性</div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ <div class="chart-content">
127
+ <vab-chart autoresize :option="systemPerformance" />
128
+ </div>
129
+ <div class="chart-footer">
130
+ <div class="trend-info">
131
+ <div class="trend-item">
132
+ <el-icon class="trend-up"><CheckCircle /></el-icon>
133
+ <span class="trend-text">运行正常</span>
134
+ </div>
135
+ <div class="trend-item">
136
+ <el-icon class="trend-icon"><Monitor /></el-icon>
137
+ <span class="trend-text">响应时间 120ms</span>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </el-card>
143
+ </el-col>
144
+
145
+ <el-col :lg="24" :md="24" :sm="24" :xl="24" :xs="24">
146
+ <el-card class="card" shadow="never">
147
+ <div slot="header">
148
+ <span>依赖信息</span>
149
+ <!-- <div style="float: right">部署时间:{{ updateTime }}</div> -->
150
+ </div>
151
+ <!-- rspack -->
152
+ <div class="rspack-info">
153
+ <div class="rspack-item">
154
+ <div class="rspack-name">Rspack版本</div>
155
+ <div class="rspack-version">{{ devDependencies["rspack"] }}</div>
156
+ </div>
157
+ </div>
158
+
159
+ <div class="dependency-content">
160
+ <div class="dependency-grid">
161
+ <div class="dependency-item">
162
+ <div class="dependency-info">
163
+ <div class="dependency-name">Vue版本</div>
164
+ <div class="dependency-version">
165
+ {{ dependencies["vue"] }}
166
+ </div>
167
+ </div>
168
+ </div>
169
+
170
+ <div class="dependency-item">
171
+ <div class="dependency-info">
172
+ <div class="dependency-name">Vuex版本</div>
173
+ <div class="dependency-version">
174
+ {{ dependencies["vuex"] }}
175
+ </div>
176
+ </div>
177
+ </div>
178
+
179
+ <div class="dependency-item">
180
+ <div class="dependency-info">
181
+ <div class="dependency-name">Vue Router</div>
182
+ <div class="dependency-version">
183
+ {{ dependencies["vue-router"] }}
184
+ </div>
185
+ </div>
186
+ </div>
187
+
188
+ <div class="dependency-item">
189
+ <div class="dependency-info">
190
+ <div class="dependency-name">Element Plus</div>
191
+ <div class="dependency-version">
192
+ {{ dependencies["element-plus"] }}
193
+ </div>
194
+ </div>
195
+ </div>
196
+
197
+ <div class="dependency-item">
198
+ <div class="dependency-info">
199
+ <div class="dependency-name">Axios版本</div>
200
+ <div class="dependency-version">
201
+ {{ dependencies["axios"] }}
202
+ </div>
203
+ </div>
204
+ </div>
205
+
206
+ <div class="dependency-item">
207
+ <div class="dependency-info">
208
+ <div class="dependency-name">Sass版本</div>
209
+ <div class="dependency-version">
210
+ {{ devDependencies["sass"] }}
211
+ </div>
212
+ </div>
213
+ </div>
214
+ </div>
215
+
216
+ <div class="system-info">
217
+ <div class="info-header">
218
+ <vab-icon :icon="['fas', 'info-circle']" />
219
+ <span>系统信息</span>
220
+ </div>
221
+ <div class="info-content">
222
+ <div class="info-item">
223
+ <span class="info-label">构建时间:</span>
224
+ <span class="info-value">{{ updateTime || "未知" }}</span>
225
+ </div>
226
+ <div class="info-item">
227
+ <span class="info-label">运行环境:</span>
228
+ <span class="info-value">{{ nodeEnv }}</span>
229
+ </div>
230
+ <div class="info-item">
231
+ <span class="info-label">用户代理:</span>
232
+ <span class="info-value">{{ userAgent }}</span>
233
+ </div>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ </el-card>
238
+ </el-col>
239
+ </el-row>
240
+ </div>
241
+ </template>
242
+
243
+ <script>
244
+ import VabChart from "@/plugins/echarts";
245
+ import { dependencies, devDependencies } from "../../../package.json";
246
+ import { random } from "lodash-es";
247
+ import {
248
+ View,
249
+ ArrowUp,
250
+ User,
251
+ Clock,
252
+ Monitor,
253
+ Bell,
254
+ Reading,
255
+ Present,
256
+ Mug,
257
+ Grid,
258
+ VideoPlay,
259
+ More,
260
+ Promotion,
261
+ Picture,
262
+ } from "@element-plus/icons-vue";
263
+
264
+ export default {
265
+ name: "Index",
266
+ components: {
267
+ VabChart,
268
+ View,
269
+ ArrowUp,
270
+ User,
271
+ Clock,
272
+ Monitor,
273
+ Bell,
274
+ Reading,
275
+ Present,
276
+ Mug,
277
+ Grid,
278
+ VideoPlay,
279
+ More,
280
+ Promotion,
281
+ Picture,
282
+ },
283
+ data() {
284
+ return {
285
+ timer: 0,
286
+ updateTime: process.env.VUE_APP_UPDATE_TIME,
287
+ nodeEnv: process.env.NODE_ENV,
288
+ dependencies: dependencies,
289
+ devDependencies: devDependencies,
290
+ config1: {
291
+ startVal: 0,
292
+ endVal: random(20000, 60000),
293
+ decimals: 0,
294
+ prefix: "",
295
+ suffix: "",
296
+ separator: ",",
297
+ duration: 8000,
298
+ },
299
+ config2: {
300
+ startVal: 0,
301
+ endVal: random(1000, 20000),
302
+ decimals: 0,
303
+ prefix: "",
304
+ suffix: "",
305
+ separator: ",",
306
+ duration: 8000,
307
+ },
308
+ config3: {
309
+ startVal: 0,
310
+ endVal: random(1000, 20000),
311
+ decimals: 0,
312
+ prefix: "",
313
+ suffix: "",
314
+ separator: ",",
315
+ duration: 8000,
316
+ },
317
+
318
+ //访问量
319
+ fwl: {
320
+ color: ["#409EFF", "#8B5CF6", "#A855F7", "#C084FC", "#E879F9"],
321
+ backgroundColor: "transparent",
322
+ grid: {
323
+ top: "15%",
324
+ left: "3%",
325
+ right: "4%",
326
+ bottom: "15%",
327
+ containLabel: true,
328
+ },
329
+ xAxis: [
330
+ {
331
+ type: "category",
332
+ boundaryGap: false,
333
+ data: [],
334
+ axisTick: {
335
+ show: false,
336
+ },
337
+ axisLine: {
338
+ lineStyle: {
339
+ color: "#E4E7ED",
340
+ },
341
+ },
342
+ axisLabel: {
343
+ color: "#909399",
344
+ fontSize: 11,
345
+ },
346
+ },
347
+ ],
348
+ yAxis: [
349
+ {
350
+ type: "value",
351
+ axisTick: {
352
+ show: false,
353
+ },
354
+ axisLine: {
355
+ show: false,
356
+ },
357
+ axisLabel: {
358
+ color: "#909399",
359
+ fontSize: 11,
360
+ },
361
+ splitLine: {
362
+ lineStyle: {
363
+ color: "#F5F7FA",
364
+ type: "dashed",
365
+ },
366
+ },
367
+ },
368
+ ],
369
+ series: [
370
+ {
371
+ name: "访问量",
372
+ type: "line",
373
+ data: [],
374
+ smooth: true,
375
+ symbol: "circle",
376
+ symbolSize: 6,
377
+ lineStyle: {
378
+ width: 3,
379
+ color: {
380
+ type: "linear",
381
+ x: 0,
382
+ y: 0,
383
+ x2: 0,
384
+ y2: 1,
385
+ colorStops: [
386
+ { offset: 0, color: "#409EFF" },
387
+ { offset: 1, color: "#8B5CF6" },
388
+ ],
389
+ },
390
+ },
391
+ itemStyle: {
392
+ color: "#409EFF",
393
+ borderWidth: 2,
394
+ borderColor: "#fff",
395
+ },
396
+ areaStyle: {
397
+ color: {
398
+ type: "linear",
399
+ x: 0,
400
+ y: 0,
401
+ x2: 0,
402
+ y2: 1,
403
+ colorStops: [
404
+ { offset: 0, color: "rgba(64, 158, 255, 0.3)" },
405
+ { offset: 1, color: "rgba(139, 92, 246, 0.1)" },
406
+ ],
407
+ },
408
+ },
409
+ },
410
+ ],
411
+ },
412
+ //授权数
413
+ sqs: {
414
+ color: ["#409EFF", "#8B5CF6", "#A855F7", "#C084FC", "#E879F9"],
415
+ backgroundColor: "transparent",
416
+ grid: {
417
+ top: "15%",
418
+ left: "3%",
419
+ right: "4%",
420
+ bottom: "15%",
421
+ containLabel: true,
422
+ },
423
+ xAxis: [
424
+ {
425
+ type: "category",
426
+ data: ["0时", "4时", "8时", "12时", "16时", "20时", "24时"],
427
+ axisTick: {
428
+ show: false,
429
+ },
430
+ axisLine: {
431
+ lineStyle: {
432
+ color: "#E4E7ED",
433
+ },
434
+ },
435
+ axisLabel: {
436
+ color: "#909399",
437
+ fontSize: 11,
438
+ },
439
+ },
440
+ ],
441
+ yAxis: [
442
+ {
443
+ type: "value",
444
+ axisTick: {
445
+ show: false,
446
+ },
447
+ axisLine: {
448
+ show: false,
449
+ },
450
+ axisLabel: {
451
+ color: "#909399",
452
+ fontSize: 11,
453
+ },
454
+ splitLine: {
455
+ lineStyle: {
456
+ color: "#F5F7FA",
457
+ type: "dashed",
458
+ },
459
+ },
460
+ },
461
+ ],
462
+ series: [
463
+ {
464
+ name: "授权数",
465
+ type: "bar",
466
+ barWidth: "60%",
467
+ data: [10, 52, 20, 33, 39, 33, 22],
468
+ itemStyle: {
469
+ color: {
470
+ type: "linear",
471
+ x: 0,
472
+ y: 0,
473
+ x2: 0,
474
+ y2: 1,
475
+ colorStops: [
476
+ { offset: 0, color: "#409EFF" },
477
+ { offset: 1, color: "#8B5CF6" },
478
+ ],
479
+ },
480
+ borderRadius: [6, 6, 0, 0],
481
+ shadowColor: "rgba(64, 158, 255, 0.3)",
482
+ shadowBlur: 10,
483
+ shadowOffsetX: 0,
484
+ shadowOffsetY: 5,
485
+ },
486
+ emphasis: {
487
+ itemStyle: {
488
+ color: {
489
+ type: "linear",
490
+ x: 0,
491
+ y: 0,
492
+ x2: 0,
493
+ y2: 1,
494
+ colorStops: [
495
+ { offset: 0, color: "#409EFF" },
496
+ { offset: 1, color: "#7C3AED" },
497
+ ],
498
+ },
499
+ shadowBlur: 15,
500
+ shadowColor: "rgba(64, 158, 255, 0.5)"
501
+ },
502
+ },
503
+ },
504
+ ],
505
+ },
506
+
507
+ //用户活跃度
508
+ userActivity: {
509
+ color: ["#409EFF", "#8B5CF6", "#A855F7", "#C084FC", "#E879F9"],
510
+ backgroundColor: "transparent",
511
+ grid: {
512
+ top: "15%",
513
+ left: "3%",
514
+ right: "4%",
515
+ bottom: "15%",
516
+ containLabel: true,
517
+ },
518
+ xAxis: [
519
+ {
520
+ type: "category",
521
+ data: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
522
+ axisTick: {
523
+ show: false,
524
+ },
525
+ axisLine: {
526
+ lineStyle: {
527
+ color: "#E4E7ED",
528
+ },
529
+ },
530
+ axisLabel: {
531
+ color: "#909399",
532
+ fontSize: 11,
533
+ },
534
+ },
535
+ ],
536
+ yAxis: [
537
+ {
538
+ type: "value",
539
+ axisTick: {
540
+ show: false,
541
+ },
542
+ axisLine: {
543
+ show: false,
544
+ },
545
+ axisLabel: {
546
+ color: "#909399",
547
+ fontSize: 11,
548
+ },
549
+ splitLine: {
550
+ lineStyle: {
551
+ color: "#F5F7FA",
552
+ type: "dashed",
553
+ },
554
+ },
555
+ },
556
+ ],
557
+ series: [
558
+ {
559
+ name: "活跃用户",
560
+ type: "line",
561
+ data: [1200, 1350, 1100, 1400, 1600, 1800, 1500],
562
+ smooth: true,
563
+ symbol: "circle",
564
+ symbolSize: 6,
565
+ lineStyle: {
566
+ width: 3,
567
+ color: "#409EFF",
568
+ },
569
+ itemStyle: {
570
+ color: "#409EFF",
571
+ borderWidth: 2,
572
+ borderColor: "#fff",
573
+ },
574
+ areaStyle: {
575
+ color: {
576
+ type: "linear",
577
+ x: 0,
578
+ y: 0,
579
+ x2: 0,
580
+ y2: 1,
581
+ colorStops: [
582
+ { offset: 0, color: "rgba(103, 122, 228, 0.3)" },
583
+ { offset: 1, color: "rgba(103, 122, 228, 0.1)" },
584
+ ],
585
+ },
586
+ },
587
+ },
588
+ ],
589
+ },
590
+
591
+ //系统性能
592
+ systemPerformance: {
593
+ color: ["#409EFF", "#8B5CF6", "#A855F7", "#C084FC"],
594
+ backgroundColor: "transparent",
595
+ grid: {
596
+ top: "15%",
597
+ left: "3%",
598
+ right: "4%",
599
+ bottom: "15%",
600
+ containLabel: true,
601
+ },
602
+ xAxis: [
603
+ {
604
+ type: "category",
605
+ data: ["CPU", "内存", "磁盘", "网络"],
606
+ axisTick: {
607
+ show: false,
608
+ },
609
+ axisLine: {
610
+ lineStyle: {
611
+ color: "#E4E7ED",
612
+ },
613
+ },
614
+ axisLabel: {
615
+ color: "#909399",
616
+ fontSize: 11,
617
+ },
618
+ },
619
+ ],
620
+ yAxis: [
621
+ {
622
+ type: "value",
623
+ max: 100,
624
+ axisTick: {
625
+ show: false,
626
+ },
627
+ axisLine: {
628
+ show: false,
629
+ },
630
+ axisLabel: {
631
+ color: "#909399",
632
+ fontSize: 11,
633
+ formatter: "{value}%",
634
+ },
635
+ splitLine: {
636
+ lineStyle: {
637
+ color: "#F5F7FA",
638
+ type: "dashed",
639
+ },
640
+ },
641
+ },
642
+ ],
643
+ series: [
644
+ {
645
+ name: "使用率",
646
+ type: "bar",
647
+ data: [45, 62, 38, 28],
648
+ barWidth: "50%",
649
+ itemStyle: {
650
+ color: function (params) {
651
+ const colors = ["#409EFF", "#8B5CF6", "#A855F7", "#C084FC"];
652
+ return colors[params.dataIndex];
653
+ },
654
+ borderRadius: [4, 4, 0, 0],
655
+ },
656
+ label: {
657
+ show: true,
658
+ position: "top",
659
+ formatter: "{c}%",
660
+ color: "#2c3e50",
661
+ fontSize: 12,
662
+ },
663
+ },
664
+ ],
665
+ },
666
+
667
+ //更新日志
668
+ reverse: true,
669
+ activities: [],
670
+ noticeList: [],
671
+ //其他信息
672
+ userAgent: navigator.userAgent,
673
+ };
674
+ },
675
+ created() {
676
+ this.fetchData();
677
+ const now = new Date();
678
+ const oneDay = 3600 * 1000 * 24;
679
+ const date = [];
680
+ const data = [];
681
+
682
+ const addData = (shift) => {
683
+ const dateStr = [
684
+ now.getFullYear(),
685
+ now.getMonth() + 1,
686
+ now.getDate(),
687
+ ].join("/");
688
+ date.push(dateStr);
689
+ data.push(random(20000, 60000));
690
+
691
+ if (shift) {
692
+ date.shift();
693
+ data.shift();
694
+ }
695
+
696
+ now.setTime(now.getTime() + oneDay);
697
+ };
698
+
699
+ for (let i = 1; i < 6; i++) {
700
+ addData();
701
+ }
702
+ addData(true);
703
+ this.fwl.xAxis[0].data = date;
704
+ this.fwl.series[0].data = data;
705
+ this.timer = setInterval(() => {
706
+ addData(true);
707
+ this.fwl.xAxis[0].data = date;
708
+ this.fwl.series[0].data = data;
709
+ }, 3000);
710
+ },
711
+ beforeDestroy() {
712
+ clearInterval(this.timer);
713
+ },
714
+ mounted() {
715
+ let base = +new Date(2020, 1, 1);
716
+ let oneDay = 24 * 3600 * 1000;
717
+ let date = [];
718
+
719
+ let data = [random(20000, 60000)];
720
+ let now = new Date(base);
721
+
722
+ const addData = (shift) => {
723
+ now = [now.getFullYear(), now.getMonth() + 1, now.getDate()].join("/");
724
+ date.push(now);
725
+ data.push(random(20000, 60000));
726
+
727
+ if (shift) {
728
+ date.shift();
729
+ data.shift();
730
+ }
731
+
732
+ now = new Date(+new Date(now) + oneDay);
733
+ };
734
+
735
+ for (let i = 1; i < 6; i++) {
736
+ addData();
737
+ }
738
+ addData(true);
739
+ this.fwl.xAxis[0].data = date;
740
+ this.fwl.series[0].data = data;
741
+ this.timer = setInterval(() => {
742
+ addData(true);
743
+ this.fwl.xAxis[0].data = date;
744
+ this.fwl.series[0].data = data;
745
+ }, 3000);
746
+ },
747
+ methods: {
748
+ handleClick(e) {
749
+ this.$baseMessage(`点击了${e.name},这里可以写跳转`);
750
+ },
751
+ handleZrClick() {},
752
+ handleChangeTheme() {
753
+ // 不再使用事件总线
754
+ // this.$baseEventBus.$emit('theme')
755
+ // 直接打开主题设置
756
+ this.drawerVisible = true;
757
+ },
758
+ async fetchData() {
759
+ // 使用 mock 数据替代 API 调用
760
+ this.noticeList = [
761
+ { id: 1, title: '欢迎使用 Vue3 Admin 脚手架', content: '这是一个基于 Vue 3 + Element Plus + Rspack 的后台管理系统模板', date: new Date().toLocaleDateString() },
762
+ { id: 2, title: '快速开始', content: '运行 npm run serve:rspack 即可启动开发服务器', date: new Date().toLocaleDateString() },
763
+ { id: 3, title: '功能特性', content: '支持多主题切换、响应式设计、完善的权限管理等功能', date: new Date().toLocaleDateString() },
764
+ ];
765
+ },
766
+ handleIconClick(item) {
767
+ if (item.link) {
768
+ window.open(item.link, "_blank");
769
+ }
770
+ },
771
+ getIconDescription(title) {
772
+ const descriptions = {
773
+ 视频播放器: "支持多种格式的视频播放",
774
+ 表格: "功能强大的数据表格组件",
775
+ 源码: "开源项目源码下载",
776
+ 书籍: "技术文档和教程",
777
+ 公告: "系统公告和通知",
778
+ 礼物: "免费资源和福利",
779
+ 公平的世界: "开源社区贡献",
780
+ 休息一下: "放松心情,享受生活",
781
+ };
782
+ return descriptions[title] || "功能模块";
783
+ },
784
+ getRandomViews() {
785
+ return `${random(100, 999)}K`;
786
+ },
787
+ getRandomLikes() {
788
+ return `${random(10, 99)}K`;
789
+ },
790
+ // 将FontAwesome图标名称转换为Element Plus图标组件
791
+ getIconComponent(iconName) {
792
+ // 映射FontAwesome图标名称到Element Plus图标
793
+ const iconMap = {
794
+ video: "VideoPlay",
795
+ table: "Grid",
796
+ code: "Promotion",
797
+ book: "Reading",
798
+ bullhorn: "Bell",
799
+ gift: "Present",
800
+ coffee: "Mug",
801
+ eye: "View",
802
+ heart: "Heart",
803
+ "arrow-up": "ArrowUp",
804
+ users: "User",
805
+ clock: "Clock",
806
+ "check-circle": "CheckCircle",
807
+ server: "Monitor",
808
+ // 添加更多映射...
809
+ };
810
+
811
+ // 获取映射的组件名或使用默认图标
812
+ return iconMap[iconName] || "More";
813
+ },
814
+ },
815
+ };
816
+ </script>
817
+ <style lang="scss" scoped>
818
+ .index-container {
819
+ padding: 0 !important;
820
+ margin: 0 !important;
821
+ background: #f5f7f8 !important;
822
+
823
+ :deep() {
824
+ .el-alert {
825
+ padding: $base-padding;
826
+
827
+ &--info.is-light {
828
+ min-height: 82px;
829
+ padding: $base-padding;
830
+ margin-bottom: 15px;
831
+ color: #909399;
832
+ background-color: $base-color-white;
833
+ border: 1px solid #ebeef5;
834
+ font-size: 14px !important;
835
+ * {
836
+ font-size: 14px !important;
837
+ }
838
+ }
839
+ }
840
+
841
+ .el-card__body {
842
+ .echarts {
843
+ width: 100%;
844
+ height: 115px;
845
+ }
846
+ }
847
+ }
848
+
849
+ .card {
850
+ height: 600px;
851
+ display: flex;
852
+ flex-direction: column;
853
+
854
+ :deep() {
855
+ .el-card__body {
856
+ flex: 1;
857
+ display: flex;
858
+ flex-direction: column;
859
+ overflow: hidden;
860
+
861
+ .echarts {
862
+ width: 100%;
863
+ height: 305px;
864
+ }
865
+ }
866
+ }
867
+
868
+ .dependency-content {
869
+ height: 100%;
870
+ display: flex;
871
+ flex-direction: column;
872
+ overflow-y: auto;
873
+
874
+ .dependency-grid {
875
+ display: grid;
876
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
877
+ gap: 15px;
878
+ margin-bottom: 25px;
879
+ flex-shrink: 0;
880
+
881
+ .dependency-item {
882
+ display: flex;
883
+ align-items: center;
884
+ padding: 15px;
885
+ background: #f8f9fa;
886
+ border: 1px solid #e9ecef;
887
+ border-radius: 8px;
888
+ transition: all 0.3s ease;
889
+
890
+ &:hover {
891
+ transform: translateY(-2px);
892
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
893
+ background: #ffffff;
894
+ }
895
+
896
+ .dependency-info {
897
+ flex: 1;
898
+ text-align: center;
899
+
900
+ .dependency-name {
901
+ font-size: 0.9rem;
902
+ color: #6c757d;
903
+ margin-bottom: 6px;
904
+ font-weight: 500;
905
+ }
906
+
907
+ .dependency-version {
908
+ font-size: 1.1rem;
909
+ color: #2c3e50;
910
+ font-weight: 600;
911
+ }
912
+ }
913
+ }
914
+ }
915
+
916
+ .system-info {
917
+ background: #f8f9fa;
918
+ border: 1px solid #e9ecef;
919
+ border-radius: 8px;
920
+ padding: 20px;
921
+ flex-shrink: 0;
922
+
923
+ .info-header {
924
+ display: flex;
925
+ align-items: center;
926
+ margin-bottom: 15px;
927
+ padding-bottom: 10px;
928
+ border-bottom: 2px solid #dee2e6;
929
+
930
+ .vab-icon {
931
+ color: #409EFF;
932
+ margin-right: 3px;
933
+ font-size: 1.1rem;
934
+ }
935
+
936
+ span {
937
+ font-size: 1.1rem;
938
+ font-weight: 600;
939
+ color: #2c3e50;
940
+ }
941
+ }
942
+
943
+ .info-content {
944
+ .info-item {
945
+ display: flex;
946
+ justify-content: space-between;
947
+ align-items: center;
948
+ padding: 8px 0;
949
+ border-bottom: 1px solid #f1f3f4;
950
+
951
+ &:last-child {
952
+ border-bottom: none;
953
+ }
954
+
955
+ .info-label {
956
+ color: #6c757d;
957
+ font-weight: 500;
958
+ font-size: 0.9rem;
959
+ }
960
+
961
+ .info-value {
962
+ color: #2c3e50;
963
+ font-weight: 600;
964
+ font-size: 0.9rem;
965
+ max-width: 60%;
966
+ text-align: right;
967
+ word-break: break-all;
968
+ }
969
+ }
970
+ }
971
+ }
972
+ }
973
+ }
974
+
975
+ .bottom {
976
+ padding-top: 20px;
977
+ margin-top: 5px;
978
+ color: #595959;
979
+ text-align: left;
980
+ border-top: 1px solid $base-border-color;
981
+ }
982
+
983
+ .table {
984
+ width: 100%;
985
+ color: #666;
986
+ border-collapse: collapse;
987
+ background-color: #fff;
988
+
989
+ td {
990
+ position: relative;
991
+ min-height: 20px;
992
+ padding: 9px 15px;
993
+ font-size: 14px;
994
+ line-height: 20px;
995
+ border: 1px solid #e6e6e6;
996
+
997
+ &:nth-child(odd) {
998
+ width: 20%;
999
+ text-align: right;
1000
+ background-color: #f7f7f7;
1001
+ }
1002
+ }
1003
+ }
1004
+
1005
+ .icon-panel {
1006
+ height: 117px;
1007
+ text-align: center;
1008
+ cursor: pointer;
1009
+
1010
+ svg {
1011
+ font-size: 40px;
1012
+ }
1013
+
1014
+ p {
1015
+ margin-top: 10px;
1016
+ }
1017
+ }
1018
+
1019
+ .bottom-btn {
1020
+ button {
1021
+ margin: 5px 10px 15px 0;
1022
+ }
1023
+ }
1024
+
1025
+ // 高级信息卡片样式
1026
+ .advanced-info-card {
1027
+ height: 600px;
1028
+ overflow: hidden;
1029
+
1030
+ .advanced-content {
1031
+ height: 100%;
1032
+ padding: 30px 25px;
1033
+ background: #ffffff;
1034
+ display: flex;
1035
+ flex-direction: column;
1036
+ overflow-y: auto;
1037
+
1038
+ .logo-section {
1039
+ text-align: center;
1040
+ margin-bottom: 30px;
1041
+ flex-shrink: 0;
1042
+
1043
+ .logo-container {
1044
+ position: relative;
1045
+ display: inline-block;
1046
+ margin-bottom: 20px;
1047
+
1048
+ .advanced-logo {
1049
+ font-size: 120px;
1050
+ position: relative;
1051
+ z-index: 2;
1052
+ }
1053
+
1054
+ .logo-glow {
1055
+ position: absolute;
1056
+ top: 50%;
1057
+ left: 50%;
1058
+ transform: translate(-50%, -50%);
1059
+ width: 140px;
1060
+ height: 140px;
1061
+ background: radial-gradient(
1062
+ circle,
1063
+ rgba(64, 158, 255, 0.1) 0%,
1064
+ transparent 70%
1065
+ );
1066
+ border-radius: 50%;
1067
+ animation: pulse 2s ease-in-out infinite;
1068
+ }
1069
+ }
1070
+
1071
+ .project-title {
1072
+ font-size: 2rem;
1073
+ font-weight: 700;
1074
+ color: #2c3e50;
1075
+ margin: 0 0 10px 0;
1076
+ }
1077
+
1078
+ .project-description {
1079
+ color: #7f8c8d;
1080
+ font-size: 1rem;
1081
+ margin: 0;
1082
+ }
1083
+ }
1084
+
1085
+ .stats-section {
1086
+ display: flex;
1087
+ justify-content: space-around;
1088
+ margin-bottom: 30px;
1089
+ padding: 20px;
1090
+ background: #f8f9fa;
1091
+ flex-shrink: 0;
1092
+
1093
+ .stat-card {
1094
+ text-align: center;
1095
+ padding: 15px;
1096
+ transition: all 0.3s ease;
1097
+
1098
+ .stat-icon {
1099
+ width: 50px;
1100
+ height: 50px;
1101
+ background: linear-gradient(45deg, #409EFF, #8b5cf6);
1102
+ border-radius: 12px;
1103
+ display: flex;
1104
+ align-items: center;
1105
+ justify-content: center;
1106
+ margin: 0 auto 10px;
1107
+ color: white;
1108
+ font-size: 1.2rem;
1109
+ }
1110
+
1111
+ .stat-info {
1112
+ .stat-number {
1113
+ font-size: 1.5rem;
1114
+ font-weight: 700;
1115
+ color: #2c3e50;
1116
+ margin-bottom: 5px;
1117
+ }
1118
+
1119
+ .stat-label {
1120
+ font-size: 0.9rem;
1121
+ color: #7f8c8d;
1122
+ }
1123
+ }
1124
+ }
1125
+ }
1126
+
1127
+ .action-section {
1128
+ flex: 1;
1129
+ overflow-y: auto;
1130
+
1131
+ .action-group {
1132
+ margin-bottom: 25px;
1133
+
1134
+ &:last-child {
1135
+ margin-bottom: 0;
1136
+ }
1137
+
1138
+ .action-title {
1139
+ font-size: 1.1rem;
1140
+ font-weight: 600;
1141
+ color: #2c3e50;
1142
+ margin: 0 0 15px 0;
1143
+ padding-bottom: 8px;
1144
+ border-bottom: 2px solid #ecf0f1;
1145
+ }
1146
+
1147
+ .action-buttons {
1148
+ display: flex;
1149
+ flex-wrap: wrap;
1150
+ gap: 15px;
1151
+
1152
+ .action-btn {
1153
+ flex: 1;
1154
+ min-width: 200px;
1155
+ height: 45px;
1156
+ border-radius: 10px;
1157
+ font-weight: 600;
1158
+ transition: all 0.3s ease;
1159
+ display: flex;
1160
+ align-items: center;
1161
+ justify-content: center;
1162
+ gap: 8px;
1163
+
1164
+ &:hover {
1165
+ transform: translateY(-2px);
1166
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
1167
+ }
1168
+
1169
+ &.primary-btn {
1170
+ background: #409EFF;
1171
+ border: none;
1172
+ color: white;
1173
+
1174
+ &:hover {
1175
+ background: #5a67d8;
1176
+ }
1177
+ }
1178
+
1179
+ &.premium-btn {
1180
+ background: linear-gradient(45deg, #f093fb, #f5576c);
1181
+ border: none;
1182
+ color: white;
1183
+
1184
+ &:hover {
1185
+ background: linear-gradient(45deg, #e085e7, #e54b5f);
1186
+ }
1187
+ }
1188
+ }
1189
+
1190
+ .premium-card {
1191
+ flex: 1;
1192
+ min-width: 180px;
1193
+ background: linear-gradient(135deg, #409EFF 0%, #8b5cf6 100%);
1194
+ border-radius: 15px;
1195
+ padding: 20px;
1196
+ cursor: pointer;
1197
+ transition: all 0.3s ease;
1198
+ position: relative;
1199
+ overflow: hidden;
1200
+ color: white;
1201
+ border: none;
1202
+
1203
+ &:hover {
1204
+ transform: translateY(-5px);
1205
+ box-shadow: 0 10px 25px rgba(103, 122, 228, 0.3);
1206
+ }
1207
+
1208
+ &.featured {
1209
+ background: linear-gradient(135deg, #e6a23c 0%, #f56c6c 100%);
1210
+
1211
+ &:hover {
1212
+ box-shadow: 0 10px 25px rgba(230, 162, 60, 0.3);
1213
+ }
1214
+
1215
+ .premium-badge {
1216
+ background: rgba(255, 255, 255, 0.2);
1217
+ color: #fff;
1218
+ }
1219
+ }
1220
+
1221
+ .premium-header {
1222
+ display: flex;
1223
+ justify-content: space-between;
1224
+ align-items: center;
1225
+ margin-bottom: 15px;
1226
+
1227
+ .premium-icon {
1228
+ font-size: 1.5rem;
1229
+ color: rgba(255, 255, 255, 0.9);
1230
+ }
1231
+
1232
+ .premium-badge {
1233
+ background: rgba(255, 255, 255, 0.2);
1234
+ color: rgba(255, 255, 255, 0.9);
1235
+ padding: 4px 8px;
1236
+ border-radius: 12px;
1237
+ font-size: 0.7rem;
1238
+ font-weight: 600;
1239
+ letter-spacing: 0.5px;
1240
+ }
1241
+ }
1242
+
1243
+ .premium-content {
1244
+ .premium-title {
1245
+ font-size: 1.1rem;
1246
+ font-weight: 700;
1247
+ margin-bottom: 8px;
1248
+ color: white;
1249
+ }
1250
+
1251
+ .premium-price {
1252
+ font-size: 1.3rem;
1253
+ font-weight: 800;
1254
+ margin-bottom: 5px;
1255
+ color: white;
1256
+ }
1257
+ }
1258
+ }
1259
+ }
1260
+ }
1261
+ }
1262
+ }
1263
+ }
1264
+
1265
+ // 图表容器高级样式
1266
+ .chart-container {
1267
+ height: 200px;
1268
+ display: flex;
1269
+ flex-direction: column;
1270
+
1271
+ .chart-header {
1272
+ display: flex;
1273
+ justify-content: space-between;
1274
+ align-items: center;
1275
+ margin-bottom: 15px;
1276
+ padding-bottom: 10px;
1277
+ border-bottom: 1px solid #f0f0f0;
1278
+ flex-shrink: 0;
1279
+
1280
+ .chart-title {
1281
+ display: flex;
1282
+ align-items: center;
1283
+ font-size: 1rem;
1284
+ font-weight: 600;
1285
+ color: #2c3e50;
1286
+
1287
+ .vab-icon {
1288
+ color: #409EFF;
1289
+ margin-right: 3px;
1290
+ font-size: 1.1rem;
1291
+ }
1292
+ }
1293
+
1294
+ .chart-stats {
1295
+ .stat-item {
1296
+ text-align: right;
1297
+
1298
+ .stat-value {
1299
+ font-size: 1.5rem;
1300
+ font-weight: 700;
1301
+ color: #2c3e50;
1302
+ line-height: 1;
1303
+ }
1304
+
1305
+ .stat-label {
1306
+ font-size: 0.8rem;
1307
+ color: #7f8c8d;
1308
+ margin-top: 2px;
1309
+ }
1310
+ }
1311
+ }
1312
+ }
1313
+
1314
+ .chart-content {
1315
+ flex: 1;
1316
+ margin-bottom: 15px;
1317
+ min-height: 0;
1318
+
1319
+ .echarts {
1320
+ height: 100% !important;
1321
+ min-height: 120px;
1322
+ }
1323
+ }
1324
+
1325
+ .chart-footer {
1326
+ flex-shrink: 0;
1327
+
1328
+ .trend-info {
1329
+ display: flex;
1330
+ justify-content: space-between;
1331
+ align-items: center;
1332
+
1333
+ .trend-item {
1334
+ display: flex;
1335
+ align-items: center;
1336
+ font-size: 0.85rem;
1337
+
1338
+ .trend-up {
1339
+ color: #8b5cf6;
1340
+ margin-right: 3px;
1341
+ font-size: 0.8rem;
1342
+ }
1343
+
1344
+ .trend-icon {
1345
+ color: #409EFF;
1346
+ margin-right: 3px;
1347
+ font-size: 0.8rem;
1348
+ }
1349
+
1350
+ .trend-text {
1351
+ color: #7f8c8d;
1352
+ }
1353
+ }
1354
+ }
1355
+ }
1356
+ }
1357
+
1358
+ // 图表卡片固定高度
1359
+ .el-card {
1360
+ height: 280px;
1361
+ display: flex;
1362
+ flex-direction: column;
1363
+
1364
+ :deep() {
1365
+ .el-card__body {
1366
+ flex: 1;
1367
+ display: flex;
1368
+ flex-direction: column;
1369
+ overflow: hidden;
1370
+ }
1371
+ }
1372
+ }
1373
+
1374
+ // 高级信息卡片和依赖信息卡片不受影响
1375
+ .advanced-info-card,
1376
+ .card {
1377
+ height: auto !important;
1378
+ }
1379
+
1380
+ // 图标卡片高级样式
1381
+ .icon-card {
1382
+ height: 200px;
1383
+ display: flex;
1384
+ flex-direction: column;
1385
+
1386
+ .icon-container {
1387
+ height: 100%;
1388
+ display: flex;
1389
+ flex-direction: column;
1390
+ cursor: pointer;
1391
+ transition: all 0.3s ease;
1392
+
1393
+ &:hover {
1394
+ transform: translateY(-3px);
1395
+ }
1396
+
1397
+ .icon-header {
1398
+ text-align: center;
1399
+ margin-bottom: 15px;
1400
+ flex-shrink: 0;
1401
+
1402
+ .icon-wrapper {
1403
+ width: 60px;
1404
+ height: 60px;
1405
+ border-radius: 15px;
1406
+ display: flex;
1407
+ align-items: center;
1408
+ justify-content: center;
1409
+ margin: 0 auto 12px;
1410
+ color: white;
1411
+ font-size: 1.5rem;
1412
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
1413
+ transition: all 0.3s ease;
1414
+
1415
+ &:hover {
1416
+ transform: scale(1.1);
1417
+ }
1418
+ }
1419
+
1420
+ .icon-title {
1421
+ font-size: 1rem;
1422
+ font-weight: 600;
1423
+ color: #2c3e50;
1424
+ margin: 0;
1425
+ }
1426
+ }
1427
+
1428
+ .icon-content {
1429
+ flex: 1;
1430
+ margin-bottom: 15px;
1431
+ min-height: 0;
1432
+
1433
+ .icon-description {
1434
+ font-size: 0.85rem;
1435
+ color: #7f8c8d;
1436
+ text-align: center;
1437
+ line-height: 1.4;
1438
+ padding: 0 10px;
1439
+ height: 100%;
1440
+ display: flex;
1441
+ align-items: center;
1442
+ justify-content: center;
1443
+ }
1444
+ }
1445
+
1446
+ .icon-footer {
1447
+ flex-shrink: 0;
1448
+
1449
+ .icon-stats {
1450
+ display: flex;
1451
+ justify-content: space-around;
1452
+ align-items: center;
1453
+ padding: 10px 0;
1454
+ border-top: 1px solid #f0f0f0;
1455
+
1456
+ .stat-item {
1457
+ display: flex;
1458
+ align-items: center;
1459
+ font-size: 0.8rem;
1460
+ color: #7f8c8d;
1461
+
1462
+ .vab-icon {
1463
+ margin-right: 3px;
1464
+ font-size: 0.7rem;
1465
+ }
1466
+
1467
+ span {
1468
+ font-weight: 500;
1469
+ }
1470
+ }
1471
+ }
1472
+ }
1473
+ }
1474
+ }
1475
+ }
1476
+
1477
+ // 动画
1478
+ @keyframes pulse {
1479
+ 0%,
1480
+ 100% {
1481
+ opacity: 0.5;
1482
+ transform: translate(-50%, -50%) scale(1);
1483
+ }
1484
+ 50% {
1485
+ opacity: 0.8;
1486
+ transform: translate(-50%, -50%) scale(1.1);
1487
+ }
1488
+ }
1489
+ </style>