befly-admin-ui 1.10.18 → 1.11.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 (39) hide show
  1. package/README.md +2 -1
  2. package/components/detailPanel.vue +0 -1
  3. package/components/pageDialog.vue +0 -1
  4. package/components/pageTableDetail.vue +1 -1
  5. package/layouts/default.vue +1 -2
  6. package/package.json +2 -2
  7. package/styles/dashboardCard.scss +228 -0
  8. package/views/config/dict/components/edit.vue +1 -1
  9. package/views/config/dict/index.vue +1 -2
  10. package/views/config/dictType/components/edit.vue +1 -1
  11. package/views/config/dictType/index.vue +0 -2
  12. package/views/config/system/components/edit.vue +1 -1
  13. package/views/config/system/index.vue +0 -2
  14. package/views/index/components/environmentInfo.vue +65 -81
  15. package/views/index/components/projectStats.vue +392 -0
  16. package/views/index/components/serviceStatus.vue +28 -105
  17. package/views/index/components/systemOverview.vue +41 -1157
  18. package/views/index/components/systemResources.vue +35 -94
  19. package/views/index/index.vue +10 -7
  20. package/views/log/email/index.vue +1 -2
  21. package/views/log/error/index.vue +1 -2
  22. package/views/log/login/index.vue +0 -1
  23. package/views/log/operate/index.vue +0 -1
  24. package/views/login_1/index.vue +1 -2
  25. package/views/people/admin/components/edit.vue +0 -6
  26. package/views/people/admin/index.vue +0 -2
  27. package/views/permission/api/index.vue +1 -2
  28. package/views/permission/menu/index.vue +1 -1
  29. package/views/permission/role/components/api.vue +1 -2
  30. package/views/permission/role/components/edit.vue +0 -6
  31. package/views/permission/role/components/menu.vue +1 -2
  32. package/views/permission/role/index.vue +0 -2
  33. package/views/resource/gallery/index.vue +1 -2
  34. package/views/index/components/addonList.vue +0 -140
  35. package/views/index/components/operationLogs.vue +0 -120
  36. package/views/index/components/performanceMetrics.vue +0 -223
  37. package/views/index/components/quickActions.vue +0 -30
  38. package/views/index/components/systemNotifications.vue +0 -139
  39. package/views/index/components/userInfo.vue +0 -188
@@ -5,35 +5,46 @@
5
5
  <h2>系统资源</h2>
6
6
  </div>
7
7
  <div class="section-content">
8
- <div class="resource-compact-list">
9
- <div class="resource-compact-item">
10
- <div class="resource-compact-header">
11
- <span class="resource-label">CPU</span>
12
- <span class="resource-value">{{ $Data.systemResources.cpu.usage }}%</span>
13
- <span class="resource-desc">{{ $Data.systemResources.cpu.cores }}核心</span>
8
+ <t-row :gutter="[16, 16]" class="dashboard-card-row">
9
+ <t-col :span="2" class="dashboard-card-col">
10
+ <div class="dashboard-card">
11
+ <div class="dashboard-card-content">
12
+ <span class="dashboard-card-label">CPU</span>
13
+ <div class="dashboard-card-value-row">
14
+ <span class="dashboard-card-main dashboard-card-main--muted">{{ $Data.systemResources.cpu.cores }}核心</span>
15
+ <span class="dashboard-card-accent">{{ $Data.systemResources.cpu.usage }}%</span>
16
+ </div>
17
+ </div>
14
18
  </div>
15
- </div>
16
- <div class="resource-compact-item">
17
- <div class="resource-compact-header">
18
- <span class="resource-label">内存</span>
19
- <span class="resource-value">{{ $Data.systemResources.memory.percentage }}%</span>
20
- <span class="resource-desc">{{ $Data.systemResources.memory.used }}GB / {{ $Data.systemResources.memory.total }}GB</span>
19
+ </t-col>
20
+ <t-col :span="2" class="dashboard-card-col">
21
+ <div class="dashboard-card">
22
+ <div class="dashboard-card-content">
23
+ <span class="dashboard-card-label">内存</span>
24
+ <div class="dashboard-card-value-row">
25
+ <span class="dashboard-card-main dashboard-card-main--muted">{{ $Data.systemResources.memory.used }}GB / {{ $Data.systemResources.memory.total }}GB</span>
26
+ <span class="dashboard-card-accent">{{ $Data.systemResources.memory.percentage }}%</span>
27
+ </div>
28
+ </div>
21
29
  </div>
22
- </div>
23
- <div class="resource-compact-item">
24
- <div class="resource-compact-header">
25
- <span class="resource-label">磁盘</span>
26
- <span class="resource-value">{{ $Data.systemResources.disk.percentage }}%</span>
27
- <span class="resource-desc">{{ $Data.systemResources.disk.used }}GB / {{ $Data.systemResources.disk.total }}GB</span>
30
+ </t-col>
31
+ <t-col :span="2" class="dashboard-card-col">
32
+ <div class="dashboard-card">
33
+ <div class="dashboard-card-content">
34
+ <span class="dashboard-card-label">磁盘</span>
35
+ <div class="dashboard-card-value-row">
36
+ <span class="dashboard-card-main dashboard-card-main--muted">{{ $Data.systemResources.disk.used }}GB / {{ $Data.systemResources.disk.total }}GB</span>
37
+ <span class="dashboard-card-accent">{{ $Data.systemResources.disk.percentage }}%</span>
38
+ </div>
39
+ </div>
28
40
  </div>
29
- </div>
30
- </div>
41
+ </t-col>
42
+ </t-row>
31
43
  </div>
32
44
  </div>
33
45
  </template>
34
46
 
35
47
  <script setup>
36
- import { ChartIcon } from "tdesign-icons-vue-next";
37
48
  import { reactive } from "vue";
38
49
 
39
50
  import { $Http } from "@/plugins/http.js";
@@ -62,79 +73,9 @@ $Method.fetchData();
62
73
  </script>
63
74
 
64
75
  <style scoped lang="scss">
65
- .resource-compact-list {
66
- display: grid;
67
- grid-template-columns: repeat(3, minmax(0, 1fr));
68
- gap: 10px;
76
+ @use "../../../styles/dashboardCard.scss" as dashboardCard;
69
77
 
70
- .resource-compact-item {
71
- display: flex;
72
- flex-direction: column;
73
- justify-content: center;
74
- min-width: 0;
75
- min-height: 92px;
76
- padding: 14px;
77
- border-radius: 8px;
78
- border: 1px solid rgba(0, 0, 0, 0.06);
79
- background: linear-gradient(180deg, rgba(var(--primary-color-rgb), 0.018), rgba(255, 255, 255, 0.96));
80
- transition: all 0.2s ease;
81
-
82
- &:hover {
83
- background: rgba(var(--primary-color-rgb), 0.05);
84
- border-color: var(--primary-color);
85
- box-shadow: 0 8px 18px rgba(31, 35, 41, 0.08);
86
- }
87
-
88
- .resource-compact-header {
89
- display: flex;
90
- align-items: baseline;
91
- flex-wrap: wrap;
92
- gap: 10px;
93
- row-gap: 4px;
94
-
95
- .resource-label {
96
- font-size: 14px;
97
- font-weight: 600;
98
- color: var(--text-secondary);
99
- min-width: 36px;
100
- line-height: 1.2;
101
- }
102
-
103
- .resource-value {
104
- font-size: 22px;
105
- font-weight: 700;
106
- line-height: 1.1;
107
- letter-spacing: -0.3px;
108
- font-variant-numeric: tabular-nums;
109
- color: var(--primary-color);
110
- min-width: 48px;
111
- }
112
-
113
- .resource-desc {
114
- font-size: 12px;
115
- color: var(--text-placeholder);
116
- flex: 0 0 100%;
117
- width: 100%;
118
- margin-top: 2px;
119
- padding-left: 0;
120
- line-height: 1.3;
121
- min-width: 0;
122
- word-break: break-word;
123
- }
124
- }
125
- }
126
- }
127
-
128
- @media (max-width: 1200px) {
129
- .resource-compact-list {
130
- grid-template-columns: 1fr;
131
- }
132
- }
133
-
134
- @media (max-width: 640px) {
135
- .resource-compact-list {
136
- grid-template-columns: 1fr;
137
- gap: var(--spacing-sm);
138
- }
78
+ .dashboard-card-row {
79
+ @include dashboardCard.dashboardCardStandard();
139
80
  }
140
81
  </style>
@@ -1,27 +1,30 @@
1
1
  <template>
2
2
  <div class="dashboard-container">
3
- <!-- 第一行:系统概览(全宽) -->
4
3
  <div class="dashboard-row full-width">
5
4
  <SystemOverview />
6
5
  </div>
7
6
 
8
- <!-- 第二行:服务状态 + 系统资源 -->
9
- <div class="dashboard-row two-columns">
7
+ <div class="dashboard-row full-width">
10
8
  <ServiceStatus />
9
+ </div>
10
+
11
+ <div class="dashboard-row full-width">
11
12
  <SystemResources />
12
13
  </div>
13
14
 
14
- <!-- 第三行:性能指标 + 环境信息 -->
15
- <div class="dashboard-row two-columns">
16
- <PerformanceMetrics />
15
+ <div class="dashboard-row full-width">
17
16
  <EnvironmentInfo />
18
17
  </div>
18
+
19
+ <div class="dashboard-row full-width">
20
+ <ProjectStats />
21
+ </div>
19
22
  </div>
20
23
  </template>
21
24
 
22
25
  <script setup>
23
26
  import EnvironmentInfo from "./components/environmentInfo.vue";
24
- import PerformanceMetrics from "./components/performanceMetrics.vue";
27
+ import ProjectStats from "./components/projectStats.vue";
25
28
  import ServiceStatus from "./components/serviceStatus.vue";
26
29
  import SystemOverview from "./components/systemOverview.vue";
27
30
  import SystemResources from "./components/systemResources.vue";
@@ -74,8 +74,7 @@ import DetailPanel from "befly-admin-ui/components/detailPanel.vue";
74
74
  import PageDialog from "befly-admin-ui/components/pageDialog.vue";
75
75
  import PageTableDetail from "befly-admin-ui/components/pageTableDetail.vue";
76
76
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
77
- import { CheckCircleIcon, SendIcon } from "tdesign-icons-vue-next";
78
- import { Button as TButton, Form as TForm, FormItem as TFormItem, Input as TInput, MessagePlugin, Tag as TTag, Textarea as TTextarea } from "tdesign-vue-next";
77
+ import { MessagePlugin } from "tdesign-vue-next";
79
78
  import { reactive } from "vue";
80
79
 
81
80
  import { $Http } from "@/plugins/http.js";
@@ -94,8 +94,7 @@
94
94
  import DetailPanel from "befly-admin-ui/components/detailPanel.vue";
95
95
  import PageTableDetail from "befly-admin-ui/components/pageTableDetail.vue";
96
96
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
97
- import { SearchIcon } from "tdesign-icons-vue-next";
98
- import { Button as TButton, Input as TInput, MessagePlugin, Option as TOption, Select as TSelect, Tag as TTag } from "tdesign-vue-next";
97
+ import { MessagePlugin } from "tdesign-vue-next";
99
98
  import { reactive } from "vue";
100
99
 
101
100
  const $Data = reactive({
@@ -34,7 +34,6 @@
34
34
  import DetailPanel from "befly-admin-ui/components/detailPanel.vue";
35
35
  import PageTableDetail from "befly-admin-ui/components/pageTableDetail.vue";
36
36
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
37
- import { Tag as TTag } from "tdesign-vue-next";
38
37
  import { reactive } from "vue";
39
38
 
40
39
  // 响应式数据
@@ -57,7 +57,6 @@
57
57
  import DetailPanel from "befly-admin-ui/components/detailPanel.vue";
58
58
  import PageTableDetail from "befly-admin-ui/components/pageTableDetail.vue";
59
59
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
60
- import { Option as TOption, Select as TSelect, Tag as TTag } from "tdesign-vue-next";
61
60
  import { reactive } from "vue";
62
61
 
63
62
  // 响应式数据
@@ -75,8 +75,7 @@
75
75
 
76
76
  <script setup>
77
77
  import { hashPassword } from "befly-admin-ui/utils/hashPassword";
78
- import { LockOnIcon, UserIcon } from "tdesign-icons-vue-next";
79
- import { Form as TForm, FormItem as TFormItem, Input as TInput, Button as TButton, Checkbox as TCheckbox, InputAdornment as TInputAdornment, Select as TSelect, Option as TOption, MessagePlugin } from "tdesign-vue-next";
78
+ import { MessagePlugin } from "tdesign-vue-next";
80
79
  import { reactive } from "vue";
81
80
  import { useRouter } from "vue-router";
82
81
 
@@ -30,12 +30,6 @@ import { fieldClear } from "befly-admin-ui/utils/fieldClear";
30
30
  import { hashPassword } from "befly-admin-ui/utils/hashPassword";
31
31
  import {
32
32
  //
33
- Form as TForm,
34
- FormItem as TFormItem,
35
- Input as TInput,
36
- Select as TSelect,
37
- RadioGroup as TRadioGroup,
38
- Radio as TRadio,
39
33
  MessagePlugin
40
34
  } from "tdesign-vue-next";
41
35
  import { computed, reactive } from "vue";
@@ -42,8 +42,6 @@
42
42
  <script setup>
43
43
  import PageTableDetail from "befly-admin-ui/components/pageTableDetail.vue";
44
44
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
45
- import { AddIcon, ChevronDownIcon, DeleteIcon, EditIcon } from "tdesign-icons-vue-next";
46
- import { Button as TButton, Dropdown as TDropdown, DropdownItem as TDropdownItem, DropdownMenu as TDropdownMenu, Tag as TTag } from "tdesign-vue-next";
47
45
  import { reactive } from "vue";
48
46
 
49
47
  import EditDialog from "./components/edit.vue";
@@ -54,8 +54,7 @@
54
54
  <script setup>
55
55
  import DetailPanel from "befly-admin-ui/components/detailPanel.vue";
56
56
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
57
- import { SearchIcon } from "tdesign-icons-vue-next";
58
- import { Table as TTable, Tag as TTag, Input as TInput, MessagePlugin } from "tdesign-vue-next";
57
+ import { MessagePlugin } from "tdesign-vue-next";
59
58
  import { reactive } from "vue";
60
59
 
61
60
  import { $Http } from "@/plugins/http.js";
@@ -32,7 +32,7 @@
32
32
  import DetailPanel from "befly-admin-ui/components/detailPanel.vue";
33
33
  import { arrayToTree } from "befly-admin-ui/utils/arrayToTree";
34
34
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
35
- import { Table as TTable, Tag as TTag, MessagePlugin } from "tdesign-vue-next";
35
+ import { MessagePlugin } from "tdesign-vue-next";
36
36
  import { reactive } from "vue";
37
37
 
38
38
  import { $Http } from "@/plugins/http.js";
@@ -33,8 +33,7 @@
33
33
 
34
34
  <script setup>
35
35
  import PageDialog from "befly-admin-ui/components/pageDialog.vue";
36
- import { SearchIcon } from "tdesign-icons-vue-next";
37
- import { Input as TInput, CheckboxGroup as TCheckboxGroup, Checkbox as TCheckbox, MessagePlugin } from "tdesign-vue-next";
36
+ import { MessagePlugin } from "tdesign-vue-next";
38
37
  import { computed, reactive } from "vue";
39
38
 
40
39
  import { $Http } from "@/plugins/http.js";
@@ -40,12 +40,6 @@ import PageDialog from "befly-admin-ui/components/pageDialog.vue";
40
40
  import { fieldClear } from "befly-admin-ui/utils/fieldClear";
41
41
  import {
42
42
  //
43
- Form as TForm,
44
- FormItem as TFormItem,
45
- Input as TInput,
46
- InputNumber as TInputNumber,
47
- RadioGroup as TRadioGroup,
48
- Radio as TRadio,
49
43
  MessagePlugin
50
44
  } from "tdesign-vue-next";
51
45
  import { computed, reactive, ref } from "vue";
@@ -35,8 +35,7 @@
35
35
  <script setup>
36
36
  import PageDialog from "befly-admin-ui/components/pageDialog.vue";
37
37
  import { arrayToTree } from "befly-admin-ui/utils/arrayToTree";
38
- import { SearchIcon } from "tdesign-icons-vue-next";
39
- import { CheckboxGroup as TCheckboxGroup, Checkbox as TCheckbox, Input as TInput, MessagePlugin } from "tdesign-vue-next";
38
+ import { MessagePlugin } from "tdesign-vue-next";
40
39
  import { computed, reactive } from "vue";
41
40
 
42
41
  import { $Http } from "@/plugins/http.js";
@@ -65,8 +65,6 @@
65
65
  <script setup>
66
66
  import PageTableDetail from "befly-admin-ui/components/pageTableDetail.vue";
67
67
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
68
- import { AddIcon, ChevronDownIcon, CodeIcon, DeleteIcon, EditIcon, SettingIcon } from "tdesign-icons-vue-next";
69
- import { Button as TButton, Dropdown as TDropdown, DropdownItem as TDropdownItem, DropdownMenu as TDropdownMenu, Tag as TTag } from "tdesign-vue-next";
70
68
  import { reactive } from "vue";
71
69
 
72
70
  import ApiDialog from "./components/api.vue";
@@ -79,8 +79,7 @@
79
79
  import DetailPanel from "befly-admin-ui/components/detailPanel.vue";
80
80
  import PageTableDetail from "befly-admin-ui/components/pageTableDetail.vue";
81
81
  import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
82
- import { SearchIcon, UploadIcon } from "tdesign-icons-vue-next";
83
- import { Button as TButton, Image as TImage, Input as TInput, MessagePlugin, Tag as TTag, Upload as TUpload } from "tdesign-vue-next";
82
+ import { MessagePlugin } from "tdesign-vue-next";
84
83
  import { reactive } from "vue";
85
84
 
86
85
  import { $Config } from "@/plugins/config.js";
@@ -1,140 +0,0 @@
1
- <template>
2
- <div class="section-block">
3
- <div class="section-header flex items-center gap-2">
4
- <MenuIcon />
5
- <h2>已安装插件</h2>
6
- </div>
7
- <div class="section-content">
8
- <div class="addon-list">
9
- <div v-for="addon in $Data.addonList" :key="addon.name" class="addon-item">
10
- <div class="addon-icon">
11
- <SystemStorageIcon />
12
- </div>
13
- <div class="addon-info">
14
- <div class="addon-title">
15
- <span class="addon-name">{{ addon.title }}</span>
16
- <t-tag type="success" size="small">{{ addon.version }}</t-tag>
17
- </div>
18
- <div class="addon-desc">{{ addon.description }}</div>
19
- </div>
20
- </div>
21
- </div>
22
- </div>
23
- </div>
24
- </template>
25
-
26
- <script setup>
27
- import { MenuIcon, SystemStorageIcon } from "tdesign-icons-vue-next";
28
- import { Tag as TTag } from "tdesign-vue-next";
29
- import { reactive } from "vue";
30
-
31
- import { $Http } from "@/plugins/http.js";
32
-
33
- // 组件内部数据
34
- const $Data = reactive({
35
- addonList: []
36
- });
37
-
38
- const $Method = {
39
- fetchData: async function () {
40
- try {
41
- const res = await $Http("/core/dashboard/addonList", {}, [""]);
42
- $Data.addonList.splice(0, $Data.addonList.length, ...res.data);
43
- } catch (_error) {
44
- // 静默失败:不阻断页面展示
45
- }
46
- }
47
- };
48
-
49
- $Method.fetchData();
50
- </script>
51
-
52
- <style scoped lang="scss">
53
- .addon-list {
54
- display: flex;
55
- flex-direction: column;
56
- gap: 8px;
57
-
58
- .addon-item {
59
- position: relative;
60
- background: var(--bg-color-container);
61
- border: 1px solid var(--border-color);
62
- border-left: 3px solid var(--primary-color);
63
- border-radius: var(--border-radius-small);
64
- padding: 10px 12px;
65
- display: flex;
66
- align-items: center;
67
- gap: 10px;
68
- transition: all 0.3s;
69
-
70
- &:hover {
71
- border-left-color: var(--success-color);
72
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
73
- transform: translateY(-2px);
74
- }
75
-
76
- .addon-status-badge {
77
- position: absolute;
78
- top: 8px;
79
- right: 8px;
80
- width: 8px;
81
- height: 8px;
82
- border-radius: 50%;
83
- background: var(--text-disabled);
84
- transition: all 0.3s;
85
-
86
- &::after {
87
- content: "";
88
- position: absolute;
89
- top: -2px;
90
- right: -2px;
91
- width: 8px;
92
- height: 8px;
93
- border-radius: 50%;
94
- background: var(--success-color);
95
- box-shadow: 0 0 0 2px rgba(var(--success-color-rgb), 0.2);
96
- }
97
- }
98
-
99
- .addon-icon {
100
- width: 32px;
101
- height: 32px;
102
- background: linear-gradient(135deg, var(--primary-color), #764ba2);
103
- border-radius: var(--border-radius-small);
104
- display: flex;
105
- align-items: center;
106
- justify-content: center;
107
- color: white;
108
- flex-shrink: 0;
109
- }
110
-
111
- .addon-info {
112
- flex: 1;
113
- min-width: 0;
114
- padding-right: 16px;
115
-
116
- .addon-title {
117
- display: flex;
118
- align-items: center;
119
- gap: 6px;
120
- margin-bottom: 2px;
121
-
122
- .addon-name {
123
- font-size: 14px;
124
- font-weight: 600;
125
- color: var(--text-primary);
126
- }
127
- }
128
-
129
- .addon-desc {
130
- font-size: 14px;
131
- color: var(--text-secondary);
132
- line-height: 1.3;
133
- overflow: hidden;
134
- text-overflow: ellipsis;
135
- white-space: nowrap;
136
- }
137
- }
138
- }
139
- }
140
- </style>
@@ -1,120 +0,0 @@
1
- <template>
2
- <div class="section-block">
3
- <div class="section-header flex items-center gap-2">
4
- <CodeIcon />
5
- <h2>操作日志</h2>
6
- </div>
7
- <div class="section-content">
8
- <div class="operation-table">
9
- <div class="operation-header">
10
- <span class="col-time">时间</span>
11
- <span class="col-user">操作人</span>
12
- <span class="col-action">操作</span>
13
- <span class="col-module">模块</span>
14
- <span class="col-ip">IP地址</span>
15
- <span class="col-status">状态</span>
16
- </div>
17
- <div class="operation-body">
18
- <div v-for="log in $Const.operationLogs" :key="log.id" class="operation-row">
19
- <span class="col-time">{{ $Method.formatTime(log.createdAt) }}</span>
20
- <span class="col-user">{{ log.userName }}</span>
21
- <span class="col-action">{{ log.action }}</span>
22
- <span class="col-module">{{ log.module }}</span>
23
- <span class="col-ip">{{ log.ip }}</span>
24
- <span class="col-status">
25
- <t-tag :type="log.status === 'success' ? 'success' : 'danger'" size="small">
26
- {{ log.status === "success" ? "成功" : "失败" }}
27
- </t-tag>
28
- </span>
29
- </div>
30
- </div>
31
- </div>
32
- </div>
33
- </div>
34
- </template>
35
-
36
- <script setup>
37
- import { CodeIcon } from "tdesign-icons-vue-next";
38
- import { Tag as TTag } from "tdesign-vue-next";
39
- import { reactive } from "vue";
40
-
41
- // 组件内部数据
42
- const $Const = {
43
- operationLogs: [
44
- { id: 1, userName: "管理员", action: "创建角色", module: "权限管理", ip: "192.168.1.100", status: "success", createdAt: Date.now() - 120000 },
45
- { id: 2, userName: "张三", action: "修改菜单", module: "系统设置", ip: "192.168.1.101", status: "success", createdAt: Date.now() - 900000 },
46
- { id: 3, userName: "李四", action: "删除接口", module: "接口管理", ip: "192.168.1.102", status: "failed", createdAt: Date.now() - 3600000 },
47
- { id: 4, userName: "管理员", action: "同步数据库", module: "数据库", ip: "192.168.1.100", status: "success", createdAt: Date.now() - 7200000 },
48
- { id: 5, userName: "王五", action: "登录系统", module: "系统", ip: "192.168.1.103", status: "success", createdAt: Date.now() - 10800000 }
49
- ]
50
- };
51
-
52
- const $Method = {
53
- formatTime: function (timestamp) {
54
- const date = new Date(timestamp);
55
- const month = String(date.getMonth() + 1).padStart(2, "0");
56
- const day = String(date.getDate()).padStart(2, "0");
57
- const hours = String(date.getHours()).padStart(2, "0");
58
- const minutes = String(date.getMinutes()).padStart(2, "0");
59
- return `${month}-${day} ${hours}:${minutes}`;
60
- }
61
- };
62
- </script>
63
-
64
- <style scoped lang="scss">
65
- .operation-table {
66
- .operation-header,
67
- .operation-row {
68
- display: grid;
69
- grid-template-columns: 100px 100px 1fr 120px 120px 80px;
70
- gap: 12px;
71
- align-items: center;
72
- }
73
-
74
- .operation-header {
75
- padding: 10px 12px;
76
- background: linear-gradient(135deg, rgba(var(--primary-color-rgb), 0.05) 0%, rgba(var(--primary-color-rgb), 0.02) 100%);
77
- border-radius: 6px;
78
- font-size: 14px;
79
- font-weight: 600;
80
- color: var(--text-secondary);
81
- margin-bottom: 6px;
82
- }
83
-
84
- .operation-body {
85
- display: flex;
86
- flex-direction: column;
87
- gap: 4px;
88
- }
89
-
90
- .operation-row {
91
- padding: 6px 12px;
92
- background: var(--bg-color-container);
93
- border-radius: 6px;
94
- border: 1px solid var(--border-color);
95
- font-size: 14px;
96
- transition: all 0.2s ease;
97
-
98
- &:hover {
99
- background: rgba(var(--primary-color-rgb), 0.02);
100
- border-color: rgba(var(--primary-color-rgb), 0.2);
101
- }
102
-
103
- .col-time {
104
- color: var(--text-secondary);
105
- font-size: 14px;
106
- }
107
-
108
- .col-user,
109
- .col-action,
110
- .col-module,
111
- .col-ip {
112
- color: var(--text-primary);
113
- }
114
-
115
- .col-action {
116
- font-weight: 600;
117
- }
118
- }
119
- }
120
- </style>