zant-admin 2.0.2 → 2.0.4

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 (69) hide show
  1. package/.editorconfig +6 -0
  2. package/.env.development +3 -0
  3. package/.env.production +1 -0
  4. package/.env.test +1 -0
  5. package/.gitignore +36 -0
  6. package/.prettierrc.json +9 -0
  7. package/README.en.md +461 -272
  8. package/README.md +4 -3
  9. package/bin/cli.js +1 -1
  10. package/eslint.config.js +30 -0
  11. package/index.html +13 -0
  12. package/jsconfig.json +8 -0
  13. package/package.json +11 -3
  14. package/src/App.vue +16 -16
  15. package/src/api/methods/logError.js +8 -8
  16. package/src/api/methods/logOperation.js +8 -8
  17. package/src/api/methods/login.js +6 -6
  18. package/src/api/methods/quartz.js +36 -36
  19. package/src/api/methods/region.js +16 -16
  20. package/src/api/methods/sysAccount.js +29 -29
  21. package/src/api/methods/sysDict.js +29 -29
  22. package/src/api/methods/sysDictItem.js +26 -26
  23. package/src/api/methods/sysMenu.js +42 -42
  24. package/src/api/methods/sysRole.js +35 -35
  25. package/src/api/methods/sysUser.js +25 -25
  26. package/src/api/methods/system.js +15 -15
  27. package/src/api/request.js +225 -225
  28. package/src/assets/css/zcui.css +1023 -1023
  29. package/src/components/IconPicker.vue +351 -351
  30. package/src/components/MainPage.vue +838 -838
  31. package/src/components/details/logErrorDetails.vue +58 -58
  32. package/src/components/details/logOperationDetails.vue +76 -76
  33. package/src/components/edit/QuartzEdit.vue +221 -221
  34. package/src/components/edit/SysAccountEdit.vue +185 -185
  35. package/src/components/edit/SysDictEdit.vue +116 -116
  36. package/src/components/edit/SysDictItemEdit.vue +136 -136
  37. package/src/components/edit/SysRoleEdit.vue +111 -111
  38. package/src/config/index.js +74 -74
  39. package/src/directives/permission.js +49 -49
  40. package/src/main.js +37 -37
  41. package/src/stores/config.js +43 -43
  42. package/src/stores/dict.js +33 -33
  43. package/src/stores/menu.js +81 -81
  44. package/src/stores/user.js +21 -21
  45. package/src/utils/baseEcharts.js +661 -661
  46. package/src/utils/dictTemplate.js +26 -26
  47. package/src/utils/regionUtils.js +173 -173
  48. package/src/utils/useFormCRUD.js +59 -59
  49. package/src/views/baiscstatis/center.vue +474 -474
  50. package/src/views/baiscstatis/iframePage.vue +29 -29
  51. package/src/views/baiscstatis/notFound.vue +192 -192
  52. package/src/views/console.vue +821 -821
  53. package/src/views/demo/button.vue +269 -269
  54. package/src/views/demo/importexport.vue +119 -119
  55. package/src/views/demo/region.vue +322 -322
  56. package/src/views/demo/statistics.vue +214 -214
  57. package/src/views/home.vue +6 -6
  58. package/src/views/operations/log/logError.vue +78 -78
  59. package/src/views/operations/log/logLogin.vue +66 -66
  60. package/src/views/operations/log/logOperation.vue +103 -103
  61. package/src/views/operations/log/logQuartz.vue +56 -56
  62. package/src/views/operations/quartz.vue +179 -179
  63. package/src/views/operations/serviceMonitoring.vue +134 -134
  64. package/src/views/system/sysAccount.vue +128 -128
  65. package/src/views/system/sysDict.vue +159 -159
  66. package/src/views/system/sysDictItem.vue +118 -118
  67. package/src/views/system/sysMenu.vue +225 -225
  68. package/src/views/system/sysRole.vue +207 -207
  69. package/vite.config.js +33 -0
@@ -1,821 +1,821 @@
1
- <template>
2
- <div class="console-page">
3
- <!-- 页面标题区域 -->
4
- <div class="page-header">
5
- <div class="header-content">
6
- <div class="header-title">
7
- <h1>系统控制台</h1>
8
- <p>欢迎使用系统控制台,这里可以查看系统概览和重要信息</p>
9
- </div>
10
- <div class="header-time">
11
- <div class="time-display">{{ currentTime }}</div>
12
- <div class="date-display">{{ currentDate }}</div>
13
- </div>
14
- </div>
15
- </div>
16
-
17
- <!-- 统计卡片区域 -->
18
- <div class="stats-container">
19
- <div class="stat-card" v-for="(stat, index) in statsData" :key="index">
20
- <div class="stat-icon" :style="{ background: stat.gradient }">
21
- <component :is="stat.icon" />
22
- </div>
23
- <div class="stat-content">
24
- <div class="stat-value">{{ stat.value }}</div>
25
- <div class="stat-label">{{ stat.label }}</div>
26
- <div class="stat-trend" :class="stat.trend">
27
- <component :is="stat.trendIcon" />
28
- {{ stat.change }}
29
- </div>
30
- </div>
31
- </div>
32
- </div>
33
-
34
- <!-- 主要内容区域 -->
35
- <div class="main-content">
36
- <!-- 左侧内容 -->
37
- <div class="left-content">
38
- <!-- 访问量统计图表 -->
39
- <div class="chart-container">
40
- <div class="card-header">
41
- <h3>访问量统计</h3>
42
- <div class="chart-controls">
43
- <a-radio-group v-model:value="chartPeriod" size="small">
44
- <a-radio-button value="week">本周</a-radio-button>
45
- <a-radio-button value="month">本月</a-radio-button>
46
- <a-radio-button value="year">本年</a-radio-button>
47
- </a-radio-group>
48
- </div>
49
- </div>
50
- <div class="chart-wrapper" ref="visitChartRef"></div>
51
- </div>
52
-
53
- <!-- 系统信息 -->
54
- <div class="system-info-container">
55
- <div class="card-header">
56
- <h3>系统信息</h3>
57
- </div>
58
- <div class="info-grid">
59
- <div
60
- class="info-item"
61
- v-for="(info, index) in systemInfo"
62
- :key="index"
63
- >
64
- <div class="info-label">{{ info.label }}</div>
65
- <div class="info-value">{{ info.value }}</div>
66
- <div class="info-progress" v-if="info.progress">
67
- <div
68
- class="progress-bar"
69
- :style="{ width: info.progress + '%' }"
70
- ></div>
71
- </div>
72
- </div>
73
- </div>
74
- </div>
75
- </div>
76
-
77
- <!-- 右侧内容 -->
78
- <div class="right-content">
79
- <!-- 前端项目引用 -->
80
- <div class="dependencies-container">
81
- <div class="card-header">
82
- <h3>前端项目引用</h3>
83
- </div>
84
- <div class="dependencies-list">
85
- <div
86
- class="dependency-item"
87
- v-for="(dep, index) in dependencies"
88
- :key="index"
89
- >
90
- <div class="dep-name">{{ dep.name }}</div>
91
- <div class="dep-version">{{ dep.version }}</div>
92
- </div>
93
- </div>
94
- </div>
95
-
96
- <!-- 最新通知 -->
97
- <div class="notifications-container">
98
- <div class="card-header">
99
- <h3>最新通知</h3>
100
- <a-badge :count="notifications.length" />
101
- </div>
102
- <div class="notifications-list">
103
- <div
104
- class="notification-item"
105
- v-for="(item, index) in notifications"
106
- :key="index"
107
- >
108
- <div
109
- class="notification-icon"
110
- :style="{ backgroundColor: item.color }"
111
- >
112
- {{ item.icon }}
113
- </div>
114
- <div class="notification-content">
115
- <div class="notification-title">{{ item.title }}</div>
116
- <div class="notification-desc">{{ item.description }}</div>
117
- </div>
118
- </div>
119
- </div>
120
- </div>
121
-
122
- <!-- 最近活动 -->
123
- <div class="activities-container">
124
- <div class="card-header">
125
- <h3>最近活动</h3>
126
- </div>
127
- <div class="activities-list">
128
- <div
129
- class="activity-item"
130
- v-for="(activity, index) in recentActivities"
131
- :key="index"
132
- >
133
- <ClockCircleOutlined class="activity-icon" />
134
- <div class="activity-content">{{ activity.content }}</div>
135
- </div>
136
- </div>
137
- </div>
138
- </div>
139
- </div>
140
- </div>
141
- </template>
142
-
143
- <script setup>
144
- import { ref, reactive, onMounted, onUnmounted, computed, watch } from 'vue'
145
- import * as baseEcharts from '@/utils/baseEcharts'
146
- import {
147
- UserOutlined,
148
- ShoppingCartOutlined,
149
- DollarOutlined,
150
- MessageOutlined,
151
- ClockCircleOutlined,
152
- ArrowUpOutlined,
153
- ArrowDownOutlined,
154
- } from '@ant-design/icons-vue'
155
-
156
- // 创建图表容器引用
157
- const visitChartRef = ref(null)
158
- // 图表实例
159
- let visitChart = null
160
-
161
- // 图表周期选择
162
- const chartPeriod = ref('month')
163
-
164
- // 当前时间
165
- const currentTime = ref('')
166
- const currentDate = ref('')
167
-
168
- // 统计数据
169
- const stats = reactive({
170
- userCount: 1256,
171
- orderCount: 89,
172
- revenue: '12,580',
173
- messageCount: 5,
174
- })
175
-
176
- // 统计卡片数据
177
- const statsData = computed(() => [
178
- {
179
- label: '用户总数',
180
- value: stats.userCount,
181
- icon: UserOutlined,
182
- gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
183
- trend: 'up',
184
- trendIcon: ArrowUpOutlined,
185
- change: '12.5%',
186
- },
187
- {
188
- label: '今日订单',
189
- value: stats.orderCount,
190
- icon: ShoppingCartOutlined,
191
- gradient: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
192
- trend: 'up',
193
- trendIcon: ArrowUpOutlined,
194
- change: '8.2%',
195
- },
196
- {
197
- label: '今日收入',
198
- value: `¥${stats.revenue}`,
199
- icon: DollarOutlined,
200
- gradient: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
201
- trend: 'down',
202
- trendIcon: ArrowDownOutlined,
203
- change: '3.1%',
204
- },
205
- {
206
- label: '未读消息',
207
- value: stats.messageCount,
208
- icon: MessageOutlined,
209
- gradient: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
210
- trend: 'up',
211
- trendIcon: ArrowUpOutlined,
212
- change: '2条',
213
- },
214
- ])
215
-
216
- // 系统信息
217
- const systemInfo = ref([
218
- { label: '系统版本', value: 'v1.0.0' },
219
- { label: '运行时间', value: '15天2小时' },
220
- { label: '内存使用率', value: '65%', progress: 65 },
221
- { label: 'CPU使用率', value: '23%', progress: 23 },
222
- { label: '磁盘空间', value: '85GB/120GB', progress: 70 },
223
- ])
224
-
225
- // 前端项目引用
226
- const dependencies = ref([
227
- { name: 'Vue', version: 'v3.5.13' },
228
- { name: 'Vue Router', version: 'v4.4.5' },
229
- { name: 'Pinia', version: 'v2.2.6' },
230
- { name: 'Ant Design Vue', version: 'v4.2.6' },
231
- { name: 'Ant Design Icons Vue', version: 'v7.0.1' },
232
- { name: 'ECharts', version: 'v6.0.0' },
233
- { name: 'Day.js', version: 'v1.11.13' },
234
- { name: 'Alova', version: 'v3.2.6' },
235
- { name: 'File-saver', version: 'v2.0.5' },
236
- { name: 'Vite', version: 'v7.0.6' },
237
- ])
238
-
239
- // 通知列表
240
- const notifications = ref([
241
- {
242
- title: '系统维护通知',
243
- description: '系统将于今晚23:00进行维护,预计耗时2小时',
244
- color: '#1890ff',
245
- icon: '维',
246
- },
247
- {
248
- title: '新版本发布',
249
- description: 'v1.2.0版本已发布,新增多项功能',
250
- color: '#52c41a',
251
- icon: '新',
252
- },
253
- {
254
- title: '安全提醒',
255
- description: '请及时修改默认密码,确保账户安全',
256
- color: '#faad14',
257
- icon: '安',
258
- },
259
- ])
260
-
261
- // 最近活动
262
- const recentActivities = ref([
263
- { id: 1, content: '用户张三登录系统' },
264
- { id: 2, content: '订单#20231215001创建成功' },
265
- { id: 3, content: '报表数据已更新' },
266
- { id: 4, content: '系统备份完成' },
267
- ])
268
-
269
- // 更新时间函数
270
- const updateDateTime = () => {
271
- const now = new Date()
272
-
273
- // 更新时间
274
- currentTime.value = now.toLocaleTimeString('zh-CN', {
275
- hour: '2-digit',
276
- minute: '2-digit',
277
- second: '2-digit',
278
- })
279
-
280
- // 更新日期
281
- currentDate.value = now.toLocaleDateString('zh-CN', {
282
- year: 'numeric',
283
- month: 'long',
284
- day: 'numeric',
285
- weekday: 'long',
286
- })
287
- }
288
-
289
- // 初始化图表
290
- const initChart = () => {
291
- // 使用 baseEcharts 工具初始化折线图
292
- visitChart = baseEcharts.initLineChart(visitChartRef.value, '访问量')
293
-
294
- // 根据选择的周期获取不同的数据
295
- const getChartData = () => {
296
- switch (chartPeriod.value) {
297
- case 'week':
298
- return {
299
- xAxis: {
300
- data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
301
- },
302
- series: [
303
- {
304
- name: '访问量',
305
- data: [320, 450, 380, 420, 580, 620, 590],
306
- },
307
- {
308
- name: '独立访客',
309
- data: [220, 320, 280, 350, 480, 520, 490],
310
- },
311
- ],
312
- }
313
- case 'month':
314
- return {
315
- xAxis: {
316
- data: Array.from({ length: 30 }, (_, i) => `${i + 1}日`),
317
- },
318
- series: [
319
- {
320
- name: '访问量',
321
- data: Array.from(
322
- { length: 30 },
323
- () => Math.floor(Math.random() * 1000) + 500,
324
- ),
325
- },
326
- {
327
- name: '独立访客',
328
- data: Array.from(
329
- { length: 30 },
330
- () => Math.floor(Math.random() * 800) + 300,
331
- ),
332
- },
333
- ],
334
- }
335
- case 'year':
336
- return {
337
- xAxis: {
338
- data: [
339
- '1月',
340
- '2月',
341
- '3月',
342
- '4月',
343
- '5月',
344
- '6月',
345
- '7月',
346
- '8月',
347
- '9月',
348
- '10月',
349
- '11月',
350
- '12月',
351
- ],
352
- },
353
- series: [
354
- {
355
- name: '访问量',
356
- data: [
357
- 820, 932, 901, 934, 1290, 1330, 1320, 1540, 1200, 1100, 1380,
358
- 1420,
359
- ],
360
- },
361
- {
362
- name: '独立访客',
363
- data: [
364
- 620, 732, 701, 734, 1090, 1130, 1120, 1340, 1000, 900, 1180,
365
- 1220,
366
- ],
367
- },
368
- ],
369
- }
370
- default:
371
- return {
372
- xAxis: { data: [] },
373
- series: [],
374
- }
375
- }
376
- }
377
-
378
- // 获取数据并更新图表
379
- const chartData = getChartData()
380
- baseEcharts.updateLineChart({
381
- chartInstance: visitChart,
382
- data: chartData,
383
- shouldShowSlider: chartData.xAxis.data.length > 12,
384
- })
385
- }
386
-
387
- // 监听图表周期变化
388
- const handlePeriodChange = () => {
389
- initChart()
390
- }
391
-
392
- onMounted(() => {
393
- updateDateTime()
394
- // 每秒更新一次时间
395
- const timer = setInterval(updateDateTime, 1000)
396
- initChart()
397
-
398
- // 模拟数据更新
399
- setTimeout(() => {
400
- stats.orderCount = 92
401
- stats.revenue = '13,200'
402
- }, 3000)
403
-
404
- // 每30秒更新一次图表数据
405
- const chartTimer = setInterval(() => {
406
- initChart()
407
- }, 30000)
408
-
409
- // 监听图表周期变化
410
- const stopWatch = watch(chartPeriod, handlePeriodChange)
411
-
412
- onUnmounted(() => {
413
- clearInterval(timer)
414
- clearInterval(chartTimer)
415
- if (stopWatch) stopWatch()
416
- // 销毁图表实例,释放资源
417
- if (visitChart) {
418
- visitChart.dispose()
419
- visitChart = null
420
- }
421
- })
422
- })
423
- </script>
424
-
425
- <style scoped>
426
- .console-page {
427
- background: #f5f7fa;
428
- min-height: 100vh;
429
- font-family:
430
- -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
431
- Arial, sans-serif;
432
- }
433
-
434
- /* 页面标题区域 */
435
- .page-header {
436
- margin-bottom: 24px;
437
- background: #fff;
438
- border-radius: 12px;
439
- padding: 24px;
440
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
441
- }
442
-
443
- .header-content {
444
- display: flex;
445
- justify-content: space-between;
446
- align-items: center;
447
- }
448
-
449
- .header-title h1 {
450
- margin: 0;
451
- font-size: 28px;
452
- font-weight: 600;
453
- color: #1f2937;
454
- }
455
-
456
- .header-title p {
457
- margin: 8px 0 0 0;
458
- color: #6b7280;
459
- font-size: 14px;
460
- }
461
-
462
- .header-time {
463
- text-align: right;
464
- }
465
-
466
- .time-display {
467
- font-size: 24px;
468
- font-weight: 600;
469
- color: #1f2937;
470
- }
471
-
472
- .date-display {
473
- font-size: 14px;
474
- color: #6b7280;
475
- margin-top: 4px;
476
- }
477
-
478
- /* 统计卡片区域 */
479
- .stats-container {
480
- display: grid;
481
- grid-template-columns: repeat(4, 1fr);
482
- gap: 20px;
483
- margin-bottom: 24px;
484
- }
485
-
486
- .stat-card {
487
- background: #fff;
488
- border-radius: 12px;
489
- padding: 24px;
490
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
491
- display: flex;
492
- align-items: center;
493
- transition:
494
- transform 0.3s ease,
495
- box-shadow 0.3s ease;
496
- }
497
-
498
- .stat-card:hover {
499
- transform: translateY(-5px);
500
- box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
501
- }
502
-
503
- .stat-icon {
504
- width: 60px;
505
- height: 60px;
506
- border-radius: 12px;
507
- display: flex;
508
- align-items: center;
509
- justify-content: center;
510
- font-size: 24px;
511
- color: white;
512
- margin-right: 16px;
513
- }
514
-
515
- .stat-content {
516
- flex: 1;
517
- }
518
-
519
- .stat-value {
520
- font-size: 28px;
521
- font-weight: 600;
522
- color: #1f2937;
523
- line-height: 1;
524
- }
525
-
526
- .stat-label {
527
- margin-top: 4px;
528
- color: #6b7280;
529
- font-size: 14px;
530
- }
531
-
532
- .stat-trend {
533
- display: flex;
534
- align-items: center;
535
- margin-top: 8px;
536
- font-size: 12px;
537
- font-weight: 500;
538
- }
539
-
540
- .stat-trend.up {
541
- color: #10b981;
542
- }
543
-
544
- .stat-trend.down {
545
- color: #ef4444;
546
- }
547
-
548
- .stat-trend svg {
549
- margin-right: 4px;
550
- }
551
-
552
- /* 主要内容区域 */
553
- .main-content {
554
- display: grid;
555
- grid-template-columns: 2fr 1fr;
556
- gap: 24px;
557
- }
558
-
559
- /* 卡片标题样式 */
560
- .card-header {
561
- display: flex;
562
- justify-content: space-between;
563
- align-items: center;
564
- margin-bottom: 16px;
565
- }
566
-
567
- .card-header h3 {
568
- margin: 0;
569
- font-size: 18px;
570
- font-weight: 600;
571
- color: #1f2937;
572
- }
573
-
574
- /* 左侧内容 */
575
- .left-content {
576
- display: flex;
577
- flex-direction: column;
578
- gap: 24px;
579
- }
580
-
581
- /* 图表容器 */
582
- .chart-container {
583
- background: #fff;
584
- border-radius: 12px;
585
- padding: 24px;
586
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
587
- }
588
-
589
- .chart-wrapper {
590
- height: 300px;
591
- width: 100%;
592
- }
593
-
594
- /* 系统信息容器 */
595
- .system-info-container {
596
- background: #fff;
597
- border-radius: 12px;
598
- padding: 24px;
599
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
600
- }
601
-
602
- .info-grid {
603
- display: grid;
604
- grid-template-columns: repeat(2, 1fr);
605
- gap: 16px;
606
- }
607
-
608
- .info-item {
609
- padding: 12px;
610
- border-radius: 8px;
611
- background: #f9fafb;
612
- }
613
-
614
- .info-label {
615
- font-size: 12px;
616
- color: #6b7280;
617
- margin-bottom: 4px;
618
- }
619
-
620
- .info-value {
621
- font-size: 16px;
622
- font-weight: 600;
623
- color: #1f2937;
624
- margin-bottom: 8px;
625
- }
626
-
627
- .info-progress {
628
- height: 4px;
629
- background: #e5e7eb;
630
- border-radius: 2px;
631
- overflow: hidden;
632
- }
633
-
634
- .progress-bar {
635
- height: 100%;
636
- background: linear-gradient(90deg, #3b82f6, #1d4ed8);
637
- border-radius: 2px;
638
- transition: width 1s ease;
639
- }
640
-
641
- /* 右侧内容 */
642
- .right-content {
643
- display: flex;
644
- flex-direction: column;
645
- gap: 24px;
646
- }
647
-
648
- /* 依赖信息容器 */
649
- .dependencies-container {
650
- background: #fff;
651
- border-radius: 12px;
652
- padding: 24px;
653
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
654
- }
655
-
656
- .dependencies-list {
657
- display: grid;
658
- grid-template-columns: repeat(2, 1fr);
659
- gap: 12px;
660
- max-height: 300px;
661
- overflow-y: auto;
662
- }
663
-
664
- .dependency-item {
665
- display: flex;
666
- justify-content: space-between;
667
- align-items: center;
668
- padding: 8px 12px;
669
- border-radius: 6px;
670
- background: #f9fafb;
671
- transition: background 0.2s ease;
672
- }
673
-
674
- .dependency-item:hover {
675
- background: #f3f4f6;
676
- }
677
-
678
- .dep-name {
679
- font-size: 14px;
680
- color: #4b5563;
681
- }
682
-
683
- .dep-version {
684
- font-size: 12px;
685
- color: #6b7280;
686
- background: #e5e7eb;
687
- padding: 2px 6px;
688
- border-radius: 4px;
689
- }
690
-
691
- /* 通知容器 */
692
- .notifications-container {
693
- background: #fff;
694
- border-radius: 12px;
695
- padding: 24px;
696
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
697
- }
698
-
699
- .notifications-list {
700
- display: flex;
701
- flex-direction: column;
702
- gap: 12px;
703
- }
704
-
705
- .notification-item {
706
- display: flex;
707
- align-items: flex-start;
708
- padding: 12px;
709
- border-radius: 8px;
710
- background: #f9fafb;
711
- transition: background 0.2s ease;
712
- }
713
-
714
- .notification-item:hover {
715
- background: #f3f4f6;
716
- }
717
-
718
- .notification-icon {
719
- width: 32px;
720
- height: 32px;
721
- border-radius: 50%;
722
- display: flex;
723
- align-items: center;
724
- justify-content: center;
725
- color: white;
726
- font-size: 14px;
727
- margin-right: 12px;
728
- flex-shrink: 0;
729
- }
730
-
731
- .notification-content {
732
- flex: 1;
733
- }
734
-
735
- .notification-title {
736
- font-size: 14px;
737
- font-weight: 500;
738
- color: #1f2937;
739
- margin-bottom: 4px;
740
- }
741
-
742
- .notification-desc {
743
- font-size: 12px;
744
- color: #6b7280;
745
- }
746
-
747
- /* 活动容器 */
748
- .activities-container {
749
- background: #fff;
750
- border-radius: 12px;
751
- padding: 24px;
752
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
753
- }
754
-
755
- .activities-list {
756
- display: flex;
757
- flex-direction: column;
758
- gap: 12px;
759
- }
760
-
761
- .activity-item {
762
- display: flex;
763
- align-items: center;
764
- padding: 8px 0;
765
- border-bottom: 1px solid #f3f4f6;
766
- }
767
-
768
- .activity-item:last-child {
769
- border-bottom: none;
770
- }
771
-
772
- .activity-icon {
773
- color: #6b7280;
774
- margin-right: 12px;
775
- font-size: 14px;
776
- }
777
-
778
- .activity-content {
779
- font-size: 14px;
780
- color: #4b5563;
781
- }
782
-
783
- /* 响应式设计 */
784
- @media (max-width: 1200px) {
785
- .main-content {
786
- grid-template-columns: 1fr;
787
- }
788
-
789
- .stats-container {
790
- grid-template-columns: repeat(2, 1fr);
791
- }
792
- }
793
-
794
- @media (max-width: 768px) {
795
- .console-page {
796
- padding: 16px;
797
- }
798
-
799
- .header-content {
800
- flex-direction: column;
801
- align-items: flex-start;
802
- }
803
-
804
- .header-time {
805
- text-align: left;
806
- margin-top: 12px;
807
- }
808
-
809
- .stats-container {
810
- grid-template-columns: 1fr;
811
- }
812
-
813
- .info-grid {
814
- grid-template-columns: 1fr;
815
- }
816
-
817
- .dependencies-list {
818
- grid-template-columns: 1fr;
819
- }
820
- }
821
- </style>
1
+ <template>
2
+ <div class="console-page">
3
+ <!-- 页面标题区域 -->
4
+ <div class="page-header">
5
+ <div class="header-content">
6
+ <div class="header-title">
7
+ <h1>系统控制台</h1>
8
+ <p>欢迎使用系统控制台,这里可以查看系统概览和重要信息</p>
9
+ </div>
10
+ <div class="header-time">
11
+ <div class="time-display">{{ currentTime }}</div>
12
+ <div class="date-display">{{ currentDate }}</div>
13
+ </div>
14
+ </div>
15
+ </div>
16
+
17
+ <!-- 统计卡片区域 -->
18
+ <div class="stats-container">
19
+ <div class="stat-card" v-for="(stat, index) in statsData" :key="index">
20
+ <div class="stat-icon" :style="{ background: stat.gradient }">
21
+ <component :is="stat.icon" />
22
+ </div>
23
+ <div class="stat-content">
24
+ <div class="stat-value">{{ stat.value }}</div>
25
+ <div class="stat-label">{{ stat.label }}</div>
26
+ <div class="stat-trend" :class="stat.trend">
27
+ <component :is="stat.trendIcon" />
28
+ {{ stat.change }}
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <!-- 主要内容区域 -->
35
+ <div class="main-content">
36
+ <!-- 左侧内容 -->
37
+ <div class="left-content">
38
+ <!-- 访问量统计图表 -->
39
+ <div class="chart-container">
40
+ <div class="card-header">
41
+ <h3>访问量统计</h3>
42
+ <div class="chart-controls">
43
+ <a-radio-group v-model:value="chartPeriod" size="small">
44
+ <a-radio-button value="week">本周</a-radio-button>
45
+ <a-radio-button value="month">本月</a-radio-button>
46
+ <a-radio-button value="year">本年</a-radio-button>
47
+ </a-radio-group>
48
+ </div>
49
+ </div>
50
+ <div class="chart-wrapper" ref="visitChartRef"></div>
51
+ </div>
52
+
53
+ <!-- 系统信息 -->
54
+ <div class="system-info-container">
55
+ <div class="card-header">
56
+ <h3>系统信息</h3>
57
+ </div>
58
+ <div class="info-grid">
59
+ <div
60
+ class="info-item"
61
+ v-for="(info, index) in systemInfo"
62
+ :key="index"
63
+ >
64
+ <div class="info-label">{{ info.label }}</div>
65
+ <div class="info-value">{{ info.value }}</div>
66
+ <div class="info-progress" v-if="info.progress">
67
+ <div
68
+ class="progress-bar"
69
+ :style="{ width: info.progress + '%' }"
70
+ ></div>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+
77
+ <!-- 右侧内容 -->
78
+ <div class="right-content">
79
+ <!-- 前端项目引用 -->
80
+ <div class="dependencies-container">
81
+ <div class="card-header">
82
+ <h3>前端项目引用</h3>
83
+ </div>
84
+ <div class="dependencies-list">
85
+ <div
86
+ class="dependency-item"
87
+ v-for="(dep, index) in dependencies"
88
+ :key="index"
89
+ >
90
+ <div class="dep-name">{{ dep.name }}</div>
91
+ <div class="dep-version">{{ dep.version }}</div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+
96
+ <!-- 最新通知 -->
97
+ <div class="notifications-container">
98
+ <div class="card-header">
99
+ <h3>最新通知</h3>
100
+ <a-badge :count="notifications.length" />
101
+ </div>
102
+ <div class="notifications-list">
103
+ <div
104
+ class="notification-item"
105
+ v-for="(item, index) in notifications"
106
+ :key="index"
107
+ >
108
+ <div
109
+ class="notification-icon"
110
+ :style="{ backgroundColor: item.color }"
111
+ >
112
+ {{ item.icon }}
113
+ </div>
114
+ <div class="notification-content">
115
+ <div class="notification-title">{{ item.title }}</div>
116
+ <div class="notification-desc">{{ item.description }}</div>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- 最近活动 -->
123
+ <div class="activities-container">
124
+ <div class="card-header">
125
+ <h3>最近活动</h3>
126
+ </div>
127
+ <div class="activities-list">
128
+ <div
129
+ class="activity-item"
130
+ v-for="(activity, index) in recentActivities"
131
+ :key="index"
132
+ >
133
+ <ClockCircleOutlined class="activity-icon" />
134
+ <div class="activity-content">{{ activity.content }}</div>
135
+ </div>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </template>
142
+
143
+ <script setup>
144
+ import { ref, reactive, onMounted, onUnmounted, computed, watch } from 'vue'
145
+ import * as baseEcharts from '@/utils/baseEcharts'
146
+ import {
147
+ UserOutlined,
148
+ ShoppingCartOutlined,
149
+ DollarOutlined,
150
+ MessageOutlined,
151
+ ClockCircleOutlined,
152
+ ArrowUpOutlined,
153
+ ArrowDownOutlined,
154
+ } from '@ant-design/icons-vue'
155
+
156
+ // 创建图表容器引用
157
+ const visitChartRef = ref(null)
158
+ // 图表实例
159
+ let visitChart = null
160
+
161
+ // 图表周期选择
162
+ const chartPeriod = ref('month')
163
+
164
+ // 当前时间
165
+ const currentTime = ref('')
166
+ const currentDate = ref('')
167
+
168
+ // 统计数据
169
+ const stats = reactive({
170
+ userCount: 1256,
171
+ orderCount: 89,
172
+ revenue: '12,580',
173
+ messageCount: 5,
174
+ })
175
+
176
+ // 统计卡片数据
177
+ const statsData = computed(() => [
178
+ {
179
+ label: '用户总数',
180
+ value: stats.userCount,
181
+ icon: UserOutlined,
182
+ gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
183
+ trend: 'up',
184
+ trendIcon: ArrowUpOutlined,
185
+ change: '12.5%',
186
+ },
187
+ {
188
+ label: '今日订单',
189
+ value: stats.orderCount,
190
+ icon: ShoppingCartOutlined,
191
+ gradient: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
192
+ trend: 'up',
193
+ trendIcon: ArrowUpOutlined,
194
+ change: '8.2%',
195
+ },
196
+ {
197
+ label: '今日收入',
198
+ value: `¥${stats.revenue}`,
199
+ icon: DollarOutlined,
200
+ gradient: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
201
+ trend: 'down',
202
+ trendIcon: ArrowDownOutlined,
203
+ change: '3.1%',
204
+ },
205
+ {
206
+ label: '未读消息',
207
+ value: stats.messageCount,
208
+ icon: MessageOutlined,
209
+ gradient: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
210
+ trend: 'up',
211
+ trendIcon: ArrowUpOutlined,
212
+ change: '2条',
213
+ },
214
+ ])
215
+
216
+ // 系统信息
217
+ const systemInfo = ref([
218
+ { label: '系统版本', value: 'v1.0.0' },
219
+ { label: '运行时间', value: '15天2小时' },
220
+ { label: '内存使用率', value: '65%', progress: 65 },
221
+ { label: 'CPU使用率', value: '23%', progress: 23 },
222
+ { label: '磁盘空间', value: '85GB/120GB', progress: 70 },
223
+ ])
224
+
225
+ // 前端项目引用
226
+ const dependencies = ref([
227
+ { name: 'Vue', version: 'v3.5.13' },
228
+ { name: 'Vue Router', version: 'v4.4.5' },
229
+ { name: 'Pinia', version: 'v2.2.6' },
230
+ { name: 'Ant Design Vue', version: 'v4.2.6' },
231
+ { name: 'Ant Design Icons Vue', version: 'v7.0.1' },
232
+ { name: 'ECharts', version: 'v6.0.0' },
233
+ { name: 'Day.js', version: 'v1.11.13' },
234
+ { name: 'Alova', version: 'v3.2.6' },
235
+ { name: 'File-saver', version: 'v2.0.5' },
236
+ { name: 'Vite', version: 'v7.0.6' },
237
+ ])
238
+
239
+ // 通知列表
240
+ const notifications = ref([
241
+ {
242
+ title: '系统维护通知',
243
+ description: '系统将于今晚23:00进行维护,预计耗时2小时',
244
+ color: '#1890ff',
245
+ icon: '维',
246
+ },
247
+ {
248
+ title: '新版本发布',
249
+ description: 'v1.2.0版本已发布,新增多项功能',
250
+ color: '#52c41a',
251
+ icon: '新',
252
+ },
253
+ {
254
+ title: '安全提醒',
255
+ description: '请及时修改默认密码,确保账户安全',
256
+ color: '#faad14',
257
+ icon: '安',
258
+ },
259
+ ])
260
+
261
+ // 最近活动
262
+ const recentActivities = ref([
263
+ { id: 1, content: '用户张三登录系统' },
264
+ { id: 2, content: '订单#20231215001创建成功' },
265
+ { id: 3, content: '报表数据已更新' },
266
+ { id: 4, content: '系统备份完成' },
267
+ ])
268
+
269
+ // 更新时间函数
270
+ const updateDateTime = () => {
271
+ const now = new Date()
272
+
273
+ // 更新时间
274
+ currentTime.value = now.toLocaleTimeString('zh-CN', {
275
+ hour: '2-digit',
276
+ minute: '2-digit',
277
+ second: '2-digit',
278
+ })
279
+
280
+ // 更新日期
281
+ currentDate.value = now.toLocaleDateString('zh-CN', {
282
+ year: 'numeric',
283
+ month: 'long',
284
+ day: 'numeric',
285
+ weekday: 'long',
286
+ })
287
+ }
288
+
289
+ // 初始化图表
290
+ const initChart = () => {
291
+ // 使用 baseEcharts 工具初始化折线图
292
+ visitChart = baseEcharts.initLineChart(visitChartRef.value, '访问量')
293
+
294
+ // 根据选择的周期获取不同的数据
295
+ const getChartData = () => {
296
+ switch (chartPeriod.value) {
297
+ case 'week':
298
+ return {
299
+ xAxis: {
300
+ data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
301
+ },
302
+ series: [
303
+ {
304
+ name: '访问量',
305
+ data: [320, 450, 380, 420, 580, 620, 590],
306
+ },
307
+ {
308
+ name: '独立访客',
309
+ data: [220, 320, 280, 350, 480, 520, 490],
310
+ },
311
+ ],
312
+ }
313
+ case 'month':
314
+ return {
315
+ xAxis: {
316
+ data: Array.from({ length: 30 }, (_, i) => `${i + 1}日`),
317
+ },
318
+ series: [
319
+ {
320
+ name: '访问量',
321
+ data: Array.from(
322
+ { length: 30 },
323
+ () => Math.floor(Math.random() * 1000) + 500,
324
+ ),
325
+ },
326
+ {
327
+ name: '独立访客',
328
+ data: Array.from(
329
+ { length: 30 },
330
+ () => Math.floor(Math.random() * 800) + 300,
331
+ ),
332
+ },
333
+ ],
334
+ }
335
+ case 'year':
336
+ return {
337
+ xAxis: {
338
+ data: [
339
+ '1月',
340
+ '2月',
341
+ '3月',
342
+ '4月',
343
+ '5月',
344
+ '6月',
345
+ '7月',
346
+ '8月',
347
+ '9月',
348
+ '10月',
349
+ '11月',
350
+ '12月',
351
+ ],
352
+ },
353
+ series: [
354
+ {
355
+ name: '访问量',
356
+ data: [
357
+ 820, 932, 901, 934, 1290, 1330, 1320, 1540, 1200, 1100, 1380,
358
+ 1420,
359
+ ],
360
+ },
361
+ {
362
+ name: '独立访客',
363
+ data: [
364
+ 620, 732, 701, 734, 1090, 1130, 1120, 1340, 1000, 900, 1180,
365
+ 1220,
366
+ ],
367
+ },
368
+ ],
369
+ }
370
+ default:
371
+ return {
372
+ xAxis: { data: [] },
373
+ series: [],
374
+ }
375
+ }
376
+ }
377
+
378
+ // 获取数据并更新图表
379
+ const chartData = getChartData()
380
+ baseEcharts.updateLineChart({
381
+ chartInstance: visitChart,
382
+ data: chartData,
383
+ shouldShowSlider: chartData.xAxis.data.length > 12,
384
+ })
385
+ }
386
+
387
+ // 监听图表周期变化
388
+ const handlePeriodChange = () => {
389
+ initChart()
390
+ }
391
+
392
+ onMounted(() => {
393
+ updateDateTime()
394
+ // 每秒更新一次时间
395
+ const timer = setInterval(updateDateTime, 1000)
396
+ initChart()
397
+
398
+ // 模拟数据更新
399
+ setTimeout(() => {
400
+ stats.orderCount = 92
401
+ stats.revenue = '13,200'
402
+ }, 3000)
403
+
404
+ // 每30秒更新一次图表数据
405
+ const chartTimer = setInterval(() => {
406
+ initChart()
407
+ }, 30000)
408
+
409
+ // 监听图表周期变化
410
+ const stopWatch = watch(chartPeriod, handlePeriodChange)
411
+
412
+ onUnmounted(() => {
413
+ clearInterval(timer)
414
+ clearInterval(chartTimer)
415
+ if (stopWatch) stopWatch()
416
+ // 销毁图表实例,释放资源
417
+ if (visitChart) {
418
+ visitChart.dispose()
419
+ visitChart = null
420
+ }
421
+ })
422
+ })
423
+ </script>
424
+
425
+ <style scoped>
426
+ .console-page {
427
+ background: #f5f7fa;
428
+ min-height: 100vh;
429
+ font-family:
430
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
431
+ Arial, sans-serif;
432
+ }
433
+
434
+ /* 页面标题区域 */
435
+ .page-header {
436
+ margin-bottom: 24px;
437
+ background: #fff;
438
+ border-radius: 12px;
439
+ padding: 24px;
440
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
441
+ }
442
+
443
+ .header-content {
444
+ display: flex;
445
+ justify-content: space-between;
446
+ align-items: center;
447
+ }
448
+
449
+ .header-title h1 {
450
+ margin: 0;
451
+ font-size: 28px;
452
+ font-weight: 600;
453
+ color: #1f2937;
454
+ }
455
+
456
+ .header-title p {
457
+ margin: 8px 0 0 0;
458
+ color: #6b7280;
459
+ font-size: 14px;
460
+ }
461
+
462
+ .header-time {
463
+ text-align: right;
464
+ }
465
+
466
+ .time-display {
467
+ font-size: 24px;
468
+ font-weight: 600;
469
+ color: #1f2937;
470
+ }
471
+
472
+ .date-display {
473
+ font-size: 14px;
474
+ color: #6b7280;
475
+ margin-top: 4px;
476
+ }
477
+
478
+ /* 统计卡片区域 */
479
+ .stats-container {
480
+ display: grid;
481
+ grid-template-columns: repeat(4, 1fr);
482
+ gap: 20px;
483
+ margin-bottom: 24px;
484
+ }
485
+
486
+ .stat-card {
487
+ background: #fff;
488
+ border-radius: 12px;
489
+ padding: 24px;
490
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
491
+ display: flex;
492
+ align-items: center;
493
+ transition:
494
+ transform 0.3s ease,
495
+ box-shadow 0.3s ease;
496
+ }
497
+
498
+ .stat-card:hover {
499
+ transform: translateY(-5px);
500
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
501
+ }
502
+
503
+ .stat-icon {
504
+ width: 60px;
505
+ height: 60px;
506
+ border-radius: 12px;
507
+ display: flex;
508
+ align-items: center;
509
+ justify-content: center;
510
+ font-size: 24px;
511
+ color: white;
512
+ margin-right: 16px;
513
+ }
514
+
515
+ .stat-content {
516
+ flex: 1;
517
+ }
518
+
519
+ .stat-value {
520
+ font-size: 28px;
521
+ font-weight: 600;
522
+ color: #1f2937;
523
+ line-height: 1;
524
+ }
525
+
526
+ .stat-label {
527
+ margin-top: 4px;
528
+ color: #6b7280;
529
+ font-size: 14px;
530
+ }
531
+
532
+ .stat-trend {
533
+ display: flex;
534
+ align-items: center;
535
+ margin-top: 8px;
536
+ font-size: 12px;
537
+ font-weight: 500;
538
+ }
539
+
540
+ .stat-trend.up {
541
+ color: #10b981;
542
+ }
543
+
544
+ .stat-trend.down {
545
+ color: #ef4444;
546
+ }
547
+
548
+ .stat-trend svg {
549
+ margin-right: 4px;
550
+ }
551
+
552
+ /* 主要内容区域 */
553
+ .main-content {
554
+ display: grid;
555
+ grid-template-columns: 2fr 1fr;
556
+ gap: 24px;
557
+ }
558
+
559
+ /* 卡片标题样式 */
560
+ .card-header {
561
+ display: flex;
562
+ justify-content: space-between;
563
+ align-items: center;
564
+ margin-bottom: 16px;
565
+ }
566
+
567
+ .card-header h3 {
568
+ margin: 0;
569
+ font-size: 18px;
570
+ font-weight: 600;
571
+ color: #1f2937;
572
+ }
573
+
574
+ /* 左侧内容 */
575
+ .left-content {
576
+ display: flex;
577
+ flex-direction: column;
578
+ gap: 24px;
579
+ }
580
+
581
+ /* 图表容器 */
582
+ .chart-container {
583
+ background: #fff;
584
+ border-radius: 12px;
585
+ padding: 24px;
586
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
587
+ }
588
+
589
+ .chart-wrapper {
590
+ height: 300px;
591
+ width: 100%;
592
+ }
593
+
594
+ /* 系统信息容器 */
595
+ .system-info-container {
596
+ background: #fff;
597
+ border-radius: 12px;
598
+ padding: 24px;
599
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
600
+ }
601
+
602
+ .info-grid {
603
+ display: grid;
604
+ grid-template-columns: repeat(2, 1fr);
605
+ gap: 16px;
606
+ }
607
+
608
+ .info-item {
609
+ padding: 12px;
610
+ border-radius: 8px;
611
+ background: #f9fafb;
612
+ }
613
+
614
+ .info-label {
615
+ font-size: 12px;
616
+ color: #6b7280;
617
+ margin-bottom: 4px;
618
+ }
619
+
620
+ .info-value {
621
+ font-size: 16px;
622
+ font-weight: 600;
623
+ color: #1f2937;
624
+ margin-bottom: 8px;
625
+ }
626
+
627
+ .info-progress {
628
+ height: 4px;
629
+ background: #e5e7eb;
630
+ border-radius: 2px;
631
+ overflow: hidden;
632
+ }
633
+
634
+ .progress-bar {
635
+ height: 100%;
636
+ background: linear-gradient(90deg, #3b82f6, #1d4ed8);
637
+ border-radius: 2px;
638
+ transition: width 1s ease;
639
+ }
640
+
641
+ /* 右侧内容 */
642
+ .right-content {
643
+ display: flex;
644
+ flex-direction: column;
645
+ gap: 24px;
646
+ }
647
+
648
+ /* 依赖信息容器 */
649
+ .dependencies-container {
650
+ background: #fff;
651
+ border-radius: 12px;
652
+ padding: 24px;
653
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
654
+ }
655
+
656
+ .dependencies-list {
657
+ display: grid;
658
+ grid-template-columns: repeat(2, 1fr);
659
+ gap: 12px;
660
+ max-height: 300px;
661
+ overflow-y: auto;
662
+ }
663
+
664
+ .dependency-item {
665
+ display: flex;
666
+ justify-content: space-between;
667
+ align-items: center;
668
+ padding: 8px 12px;
669
+ border-radius: 6px;
670
+ background: #f9fafb;
671
+ transition: background 0.2s ease;
672
+ }
673
+
674
+ .dependency-item:hover {
675
+ background: #f3f4f6;
676
+ }
677
+
678
+ .dep-name {
679
+ font-size: 14px;
680
+ color: #4b5563;
681
+ }
682
+
683
+ .dep-version {
684
+ font-size: 12px;
685
+ color: #6b7280;
686
+ background: #e5e7eb;
687
+ padding: 2px 6px;
688
+ border-radius: 4px;
689
+ }
690
+
691
+ /* 通知容器 */
692
+ .notifications-container {
693
+ background: #fff;
694
+ border-radius: 12px;
695
+ padding: 24px;
696
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
697
+ }
698
+
699
+ .notifications-list {
700
+ display: flex;
701
+ flex-direction: column;
702
+ gap: 12px;
703
+ }
704
+
705
+ .notification-item {
706
+ display: flex;
707
+ align-items: flex-start;
708
+ padding: 12px;
709
+ border-radius: 8px;
710
+ background: #f9fafb;
711
+ transition: background 0.2s ease;
712
+ }
713
+
714
+ .notification-item:hover {
715
+ background: #f3f4f6;
716
+ }
717
+
718
+ .notification-icon {
719
+ width: 32px;
720
+ height: 32px;
721
+ border-radius: 50%;
722
+ display: flex;
723
+ align-items: center;
724
+ justify-content: center;
725
+ color: white;
726
+ font-size: 14px;
727
+ margin-right: 12px;
728
+ flex-shrink: 0;
729
+ }
730
+
731
+ .notification-content {
732
+ flex: 1;
733
+ }
734
+
735
+ .notification-title {
736
+ font-size: 14px;
737
+ font-weight: 500;
738
+ color: #1f2937;
739
+ margin-bottom: 4px;
740
+ }
741
+
742
+ .notification-desc {
743
+ font-size: 12px;
744
+ color: #6b7280;
745
+ }
746
+
747
+ /* 活动容器 */
748
+ .activities-container {
749
+ background: #fff;
750
+ border-radius: 12px;
751
+ padding: 24px;
752
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
753
+ }
754
+
755
+ .activities-list {
756
+ display: flex;
757
+ flex-direction: column;
758
+ gap: 12px;
759
+ }
760
+
761
+ .activity-item {
762
+ display: flex;
763
+ align-items: center;
764
+ padding: 8px 0;
765
+ border-bottom: 1px solid #f3f4f6;
766
+ }
767
+
768
+ .activity-item:last-child {
769
+ border-bottom: none;
770
+ }
771
+
772
+ .activity-icon {
773
+ color: #6b7280;
774
+ margin-right: 12px;
775
+ font-size: 14px;
776
+ }
777
+
778
+ .activity-content {
779
+ font-size: 14px;
780
+ color: #4b5563;
781
+ }
782
+
783
+ /* 响应式设计 */
784
+ @media (max-width: 1200px) {
785
+ .main-content {
786
+ grid-template-columns: 1fr;
787
+ }
788
+
789
+ .stats-container {
790
+ grid-template-columns: repeat(2, 1fr);
791
+ }
792
+ }
793
+
794
+ @media (max-width: 768px) {
795
+ .console-page {
796
+ padding: 16px;
797
+ }
798
+
799
+ .header-content {
800
+ flex-direction: column;
801
+ align-items: flex-start;
802
+ }
803
+
804
+ .header-time {
805
+ text-align: left;
806
+ margin-top: 12px;
807
+ }
808
+
809
+ .stats-container {
810
+ grid-template-columns: 1fr;
811
+ }
812
+
813
+ .info-grid {
814
+ grid-template-columns: 1fr;
815
+ }
816
+
817
+ .dependencies-list {
818
+ grid-template-columns: 1fr;
819
+ }
820
+ }
821
+ </style>