befly-admin-ui 1.8.26 → 1.8.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/pageDialog.vue +0 -1
- package/package.json +2 -2
- package/views/index/components/environmentInfo.vue +33 -11
- package/views/index/components/performanceMetrics.vue +49 -37
- package/views/index/components/serviceStatus.vue +39 -62
- package/views/index/components/systemOverview.vue +1037 -128
- package/views/index/components/systemResources.vue +51 -24
- package/views/index/index.vue +53 -9
- package/views/log/error/index.vue +319 -0
- package/views/log/visit/index.vue +700 -0
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
19
19
|
|
|
20
20
|
import { Button as TButton, Dialog as TDialog, Popconfirm as TPopconfirm } from "tdesign-vue-next";
|
|
21
|
-
import "tdesign-vue-next/es/dialog/style/index.css";
|
|
22
21
|
|
|
23
22
|
defineOptions({
|
|
24
23
|
inheritAttrs: false
|
package/package.json
CHANGED
|
@@ -66,36 +66,58 @@ fetchData();
|
|
|
66
66
|
<style scoped lang="scss">
|
|
67
67
|
.env-grid-compact {
|
|
68
68
|
display: grid;
|
|
69
|
-
grid-template-columns: repeat(
|
|
69
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
70
70
|
gap: 10px;
|
|
71
71
|
|
|
72
72
|
.env-compact-item {
|
|
73
73
|
display: flex;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
flex-direction: column;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
align-items: flex-start;
|
|
77
|
+
min-width: 0;
|
|
78
|
+
min-height: 92px;
|
|
79
|
+
gap: 4px;
|
|
80
|
+
padding: 14px;
|
|
81
|
+
background: linear-gradient(180deg, rgba(var(--primary-color-rgb), 0.018), rgba(255, 255, 255, 0.96));
|
|
82
|
+
border-radius: 8px;
|
|
83
|
+
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
80
84
|
transition: all 0.2s ease;
|
|
81
85
|
|
|
82
86
|
&:hover {
|
|
83
|
-
background: rgba(var(--primary-color-rgb), 0.
|
|
84
|
-
border-color:
|
|
87
|
+
background: rgba(var(--primary-color-rgb), 0.05);
|
|
88
|
+
border-color: var(--primary-color);
|
|
89
|
+
box-shadow: 0 8px 18px rgba(31, 35, 41, 0.08);
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
.env-label {
|
|
88
|
-
font-size:
|
|
93
|
+
font-size: 12px;
|
|
89
94
|
color: var(--text-secondary);
|
|
90
95
|
font-weight: 500;
|
|
96
|
+
line-height: 1.2;
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
.env-value {
|
|
94
100
|
font-size: 14px;
|
|
95
101
|
color: var(--text-primary);
|
|
96
102
|
font-weight: 600;
|
|
97
|
-
|
|
103
|
+
line-height: 1.35;
|
|
104
|
+
text-align: left;
|
|
105
|
+
min-width: 0;
|
|
106
|
+
width: 100%;
|
|
107
|
+
word-break: break-word;
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
110
|
}
|
|
111
|
+
|
|
112
|
+
@media (max-width: 1200px) {
|
|
113
|
+
.env-grid-compact {
|
|
114
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@media (max-width: 640px) {
|
|
119
|
+
.env-grid-compact {
|
|
120
|
+
grid-template-columns: 1fr;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
101
123
|
</style>
|
|
@@ -7,36 +7,24 @@
|
|
|
7
7
|
<div class="section-content">
|
|
8
8
|
<div class="performance-grid">
|
|
9
9
|
<div class="perf-metric">
|
|
10
|
-
<div class="perf-icon">
|
|
11
|
-
<TimeIcon />
|
|
12
|
-
</div>
|
|
13
10
|
<div class="perf-info">
|
|
14
11
|
<div class="perf-label">平均响应</div>
|
|
15
12
|
<div class="perf-value">{{ performanceMetrics.avgResponseTime }}ms</div>
|
|
16
13
|
</div>
|
|
17
14
|
</div>
|
|
18
15
|
<div class="perf-metric">
|
|
19
|
-
<div class="perf-icon">
|
|
20
|
-
<TrendingUpIcon />
|
|
21
|
-
</div>
|
|
22
16
|
<div class="perf-info">
|
|
23
17
|
<div class="perf-label">QPS</div>
|
|
24
18
|
<div class="perf-value">{{ performanceMetrics.qps }}/s</div>
|
|
25
19
|
</div>
|
|
26
20
|
</div>
|
|
27
21
|
<div class="perf-metric">
|
|
28
|
-
<div class="perf-icon">
|
|
29
|
-
<ErrorCircleIcon />
|
|
30
|
-
</div>
|
|
31
22
|
<div class="perf-info">
|
|
32
23
|
<div class="perf-label">错误率</div>
|
|
33
24
|
<div class="perf-value">{{ performanceMetrics.errorRate }}%</div>
|
|
34
25
|
</div>
|
|
35
26
|
</div>
|
|
36
27
|
<div class="perf-metric">
|
|
37
|
-
<div class="perf-icon">
|
|
38
|
-
<ChartIcon />
|
|
39
|
-
</div>
|
|
40
28
|
<div class="perf-info">
|
|
41
29
|
<div class="perf-label">活跃连接</div>
|
|
42
30
|
<div class="perf-value">{{ performanceMetrics.activeConnections }}</div>
|
|
@@ -54,7 +42,7 @@
|
|
|
54
42
|
|
|
55
43
|
<script setup>
|
|
56
44
|
import { reactive } from "vue";
|
|
57
|
-
import { ChartIcon,
|
|
45
|
+
import { ChartIcon, ErrorTriangleIcon } from "tdesign-icons-vue-next";
|
|
58
46
|
import { $Http } from "@/plugins/http";
|
|
59
47
|
|
|
60
48
|
// 组件内部数据
|
|
@@ -82,61 +70,85 @@ fetchData();
|
|
|
82
70
|
<style scoped lang="scss">
|
|
83
71
|
.performance-grid {
|
|
84
72
|
display: grid;
|
|
85
|
-
grid-template-columns: repeat(4, 1fr);
|
|
86
|
-
gap:
|
|
87
|
-
margin-bottom:
|
|
73
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
74
|
+
gap: 10px;
|
|
75
|
+
margin-bottom: 8px;
|
|
88
76
|
|
|
89
77
|
.perf-metric {
|
|
90
78
|
display: flex;
|
|
91
|
-
align-items:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
border:
|
|
79
|
+
align-items: flex-start;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
min-height: 92px;
|
|
82
|
+
padding: 14px;
|
|
83
|
+
background: linear-gradient(180deg, rgba(var(--primary-color-rgb), 0.018), rgba(255, 255, 255, 0.96));
|
|
84
|
+
border-radius: 8px;
|
|
85
|
+
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
97
86
|
transition: all 0.2s;
|
|
98
87
|
|
|
99
88
|
&:hover {
|
|
100
89
|
background: rgba(var(--primary-color-rgb), 0.05);
|
|
101
90
|
border-color: var(--primary-color);
|
|
91
|
+
box-shadow: 0 8px 18px rgba(31, 35, 41, 0.08);
|
|
102
92
|
}
|
|
103
93
|
|
|
104
|
-
.perf-
|
|
94
|
+
.perf-info {
|
|
105
95
|
display: flex;
|
|
106
|
-
|
|
96
|
+
flex-direction: column;
|
|
107
97
|
justify-content: center;
|
|
108
|
-
|
|
109
|
-
height: 36px;
|
|
110
|
-
border-radius: var(--border-radius-small);
|
|
111
|
-
background: linear-gradient(135deg, rgba(0, 168, 112, 0.1) 0%, rgba(0, 168, 112, 0.05) 100%);
|
|
112
|
-
color: var(--success-color);
|
|
113
|
-
flex-shrink: 0;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.perf-info {
|
|
98
|
+
gap: 4px;
|
|
117
99
|
flex: 1;
|
|
100
|
+
width: 100%;
|
|
101
|
+
min-width: 0;
|
|
118
102
|
|
|
119
103
|
.perf-label {
|
|
120
|
-
font-size:
|
|
104
|
+
font-size: 12px;
|
|
121
105
|
color: var(--text-secondary);
|
|
122
|
-
|
|
106
|
+
line-height: 1.2;
|
|
123
107
|
}
|
|
124
108
|
|
|
125
109
|
.perf-value {
|
|
126
|
-
font-size:
|
|
110
|
+
font-size: 22px;
|
|
127
111
|
font-weight: 700;
|
|
112
|
+
line-height: 1.1;
|
|
113
|
+
letter-spacing: -0.3px;
|
|
114
|
+
font-variant-numeric: tabular-nums;
|
|
128
115
|
color: var(--primary-color);
|
|
129
116
|
}
|
|
130
117
|
}
|
|
131
118
|
}
|
|
132
119
|
}
|
|
133
120
|
|
|
121
|
+
@media (max-width: 1200px) {
|
|
122
|
+
.performance-grid {
|
|
123
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.perf-slowest {
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: flex-start;
|
|
130
|
+
gap: 6px;
|
|
131
|
+
padding: 8px 10px;
|
|
132
|
+
background: rgba(var(--warning-color-rgb), 0.05);
|
|
133
|
+
border-radius: 8px;
|
|
134
|
+
border: 1px solid rgba(var(--warning-color-rgb), 0.2);
|
|
135
|
+
font-size: 12px;
|
|
136
|
+
color: var(--warning-color);
|
|
137
|
+
word-break: break-word;
|
|
138
|
+
}
|
|
139
|
+
|
|
134
140
|
.warning-tip {
|
|
135
141
|
padding: var(--spacing-sm) var(--spacing-md);
|
|
136
142
|
background: rgba(var(--warning-color-rgb), 0.05);
|
|
137
143
|
border-radius: var(--border-radius-small);
|
|
138
144
|
border: 1px solid rgba(var(--warning-color-rgb), 0.2);
|
|
139
|
-
font-size:
|
|
145
|
+
font-size: 14px;
|
|
140
146
|
color: var(--warning-color);
|
|
141
147
|
}
|
|
148
|
+
|
|
149
|
+
@media (max-width: 640px) {
|
|
150
|
+
.performance-grid {
|
|
151
|
+
grid-template-columns: 1fr;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
142
154
|
</style>
|
|
@@ -7,14 +7,6 @@
|
|
|
7
7
|
<div class="section-content">
|
|
8
8
|
<div class="config-grid">
|
|
9
9
|
<div v-for="service in services" :key="service.name" class="config-card" :class="`config-${service.status}`">
|
|
10
|
-
<div class="config-icon">
|
|
11
|
-
<DataBaseIcon v-if="service.name === '数据库'" style="width: 20px; height: 20px" />
|
|
12
|
-
<LightingCircleIcon v-else-if="service.name === 'Redis'" style="width: 20px; height: 20px" />
|
|
13
|
-
<HardDiskStorageIcon v-else-if="service.name === '文件系统'" style="width: 20px; height: 20px" />
|
|
14
|
-
<MailIcon v-else-if="service.name === '邮件服务'" style="width: 20px; height: 20px" />
|
|
15
|
-
<CloudIcon v-else-if="service.name === 'OSS存储'" style="width: 20px; height: 20px" />
|
|
16
|
-
<CircleIcon v-else style="width: 20px; height: 20px" />
|
|
17
|
-
</div>
|
|
18
10
|
<div class="config-info">
|
|
19
11
|
<div class="config-name">{{ service.name }}</div>
|
|
20
12
|
<div class="config-status">
|
|
@@ -22,12 +14,6 @@
|
|
|
22
14
|
<span v-if="service.responseTime && service.responseTime !== '-'" class="latency">{{ service.responseTime }}</span>
|
|
23
15
|
</div>
|
|
24
16
|
</div>
|
|
25
|
-
<div class="config-badge">
|
|
26
|
-
<CheckCircleIcon v-if="service.status === 'running'" style="width: 32px; height: 32px" />
|
|
27
|
-
<CloseCircleIcon v-else-if="service.status === 'stopped'" style="width: 32px; height: 32px" />
|
|
28
|
-
<ErrorCircleIcon v-else-if="service.status === 'unconfigured'" style="width: 32px; height: 32px" />
|
|
29
|
-
<CircleIcon v-else style="width: 32px; height: 32px" />
|
|
30
|
-
</div>
|
|
31
17
|
</div>
|
|
32
18
|
</div>
|
|
33
19
|
</div>
|
|
@@ -36,7 +22,7 @@
|
|
|
36
22
|
|
|
37
23
|
<script setup>
|
|
38
24
|
import { reactive } from "vue";
|
|
39
|
-
import { CheckCircleIcon
|
|
25
|
+
import { CheckCircleIcon } from "tdesign-icons-vue-next";
|
|
40
26
|
import { $Http } from "@/plugins/http";
|
|
41
27
|
|
|
42
28
|
// 组件内部数据
|
|
@@ -46,7 +32,8 @@ const services = reactive([]);
|
|
|
46
32
|
const fetchData = async () => {
|
|
47
33
|
try {
|
|
48
34
|
const res = await $Http("/core/dashboard/serviceStatus", {}, [""]);
|
|
49
|
-
|
|
35
|
+
const nextServices = Array.isArray(res.data?.services) ? res.data.services.filter((service) => service?.name !== "OSS存储") : [];
|
|
36
|
+
services.splice(0, services.length, ...nextServices);
|
|
50
37
|
} catch (_error) {
|
|
51
38
|
// 静默失败:不阻断页面展示
|
|
52
39
|
}
|
|
@@ -68,17 +55,18 @@ const getStatusText = (status) => {
|
|
|
68
55
|
<style scoped lang="scss">
|
|
69
56
|
.config-grid {
|
|
70
57
|
display: grid;
|
|
71
|
-
grid-template-columns: repeat(
|
|
58
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
72
59
|
gap: 10px;
|
|
73
60
|
|
|
74
61
|
.config-card {
|
|
75
|
-
background: rgba(var(--primary-color-rgb), 0.
|
|
76
|
-
border: 1px solid
|
|
77
|
-
border-radius:
|
|
78
|
-
padding:
|
|
62
|
+
background: linear-gradient(180deg, rgba(var(--primary-color-rgb), 0.018), rgba(255, 255, 255, 0.96));
|
|
63
|
+
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
64
|
+
border-radius: 8px;
|
|
65
|
+
padding: 14px;
|
|
79
66
|
display: flex;
|
|
80
|
-
align-items:
|
|
81
|
-
|
|
67
|
+
align-items: flex-start;
|
|
68
|
+
justify-content: center;
|
|
69
|
+
min-height: 92px;
|
|
82
70
|
position: relative;
|
|
83
71
|
overflow: hidden;
|
|
84
72
|
transition: all 0.3s;
|
|
@@ -87,57 +75,46 @@ const getStatusText = (status) => {
|
|
|
87
75
|
background: rgba(var(--primary-color-rgb), 0.05);
|
|
88
76
|
border-color: var(--primary-color);
|
|
89
77
|
transform: translateY(-2px);
|
|
90
|
-
box-shadow: 0
|
|
78
|
+
box-shadow: 0 8px 18px rgba(31, 35, 41, 0.08);
|
|
91
79
|
}
|
|
92
80
|
|
|
93
|
-
.config-
|
|
94
|
-
width: 40px;
|
|
95
|
-
height: 40px;
|
|
81
|
+
.config-info {
|
|
96
82
|
display: flex;
|
|
97
|
-
|
|
83
|
+
flex-direction: column;
|
|
98
84
|
justify-content: center;
|
|
99
|
-
|
|
100
|
-
flex-shrink: 0;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.config-info {
|
|
85
|
+
gap: 4px;
|
|
104
86
|
flex: 1;
|
|
87
|
+
width: 100%;
|
|
105
88
|
min-width: 0;
|
|
106
89
|
|
|
107
90
|
.config-name {
|
|
108
91
|
font-size: 14px;
|
|
109
92
|
font-weight: 600;
|
|
110
|
-
|
|
93
|
+
line-height: 1.2;
|
|
111
94
|
}
|
|
112
95
|
|
|
113
96
|
.config-status {
|
|
114
|
-
font-size:
|
|
97
|
+
font-size: 12px;
|
|
115
98
|
display: flex;
|
|
116
|
-
align-items:
|
|
99
|
+
align-items: baseline;
|
|
100
|
+
flex-wrap: wrap;
|
|
117
101
|
gap: 4px;
|
|
102
|
+
line-height: 1.2;
|
|
103
|
+
color: var(--text-secondary);
|
|
118
104
|
|
|
119
105
|
.latency {
|
|
120
106
|
margin-left: 4px;
|
|
121
|
-
|
|
107
|
+
font-size: 14px;
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
line-height: 1.1;
|
|
110
|
+
font-variant-numeric: tabular-nums;
|
|
111
|
+
color: var(--primary-color);
|
|
122
112
|
}
|
|
123
113
|
}
|
|
124
114
|
}
|
|
125
115
|
|
|
126
|
-
.config-badge {
|
|
127
|
-
position: absolute;
|
|
128
|
-
top: 6px;
|
|
129
|
-
right: 6px;
|
|
130
|
-
opacity: 0.2;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
116
|
&.config-running {
|
|
134
117
|
border-color: var(--success-color);
|
|
135
|
-
background: linear-gradient(135deg, rgba(82, 196, 26, 0.05), white);
|
|
136
|
-
|
|
137
|
-
.config-icon {
|
|
138
|
-
background: rgba(82, 196, 26, 0.1);
|
|
139
|
-
color: var(--success-color);
|
|
140
|
-
}
|
|
141
118
|
|
|
142
119
|
.config-name {
|
|
143
120
|
color: var(--success-color);
|
|
@@ -146,12 +123,6 @@ const getStatusText = (status) => {
|
|
|
146
123
|
|
|
147
124
|
&.config-unconfigured {
|
|
148
125
|
border-color: var(--warning-color);
|
|
149
|
-
background: linear-gradient(135deg, rgba(250, 173, 20, 0.05), white);
|
|
150
|
-
|
|
151
|
-
.config-icon {
|
|
152
|
-
background: rgba(250, 173, 20, 0.1);
|
|
153
|
-
color: var(--warning-color);
|
|
154
|
-
}
|
|
155
126
|
|
|
156
127
|
.config-name {
|
|
157
128
|
color: var(--warning-color);
|
|
@@ -160,12 +131,6 @@ const getStatusText = (status) => {
|
|
|
160
131
|
|
|
161
132
|
&.config-stopped {
|
|
162
133
|
border-color: var(--error-color);
|
|
163
|
-
background: linear-gradient(135deg, rgba(255, 77, 79, 0.05), white);
|
|
164
|
-
|
|
165
|
-
.config-icon {
|
|
166
|
-
background: rgba(255, 77, 79, 0.1);
|
|
167
|
-
color: var(--error-color);
|
|
168
|
-
}
|
|
169
134
|
|
|
170
135
|
.config-name {
|
|
171
136
|
color: var(--error-color);
|
|
@@ -173,4 +138,16 @@ const getStatusText = (status) => {
|
|
|
173
138
|
}
|
|
174
139
|
}
|
|
175
140
|
}
|
|
141
|
+
|
|
142
|
+
@media (max-width: 1200px) {
|
|
143
|
+
.config-grid {
|
|
144
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@media (max-width: 640px) {
|
|
149
|
+
.config-grid {
|
|
150
|
+
grid-template-columns: 1fr;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
176
153
|
</style>
|