fix: 虚拟机详情监控模块
Build and Deploy Vue3 / build (push) Successful in 1m30s
Build and Deploy Vue3 / deploy (push) Successful in 17m15s

This commit is contained in:
2026-04-15 18:38:08 +08:00
parent cae1f847e4
commit f53f63e679
3 changed files with 174 additions and 78 deletions
+57 -22
View File
@@ -538,10 +538,19 @@
<div class="section-block">
<div class="section-header">
<h3 class="section-title">监控指标</h3>
<div style="display: flex; align-items: center; gap: 8px">
<el-select v-model="historyTimeRange" size="small" style="width: 120px" @change="loadHistoricalMetrics">
<el-option v-for="option in historyTimeOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap">
<el-date-picker
v-model="monitorDateRange"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
size="small"
style="width: 360px"
:shortcuts="monitorShortcuts"
@change="loadHistoricalMetrics"
/>
<span style="font-size:12px;color:#909399;white-space:nowrap">粒度: {{ currentIntervalLabel }}</span>
<el-button size="small" :icon="Refresh" @click="loadHistoricalMetrics" :loading="historicalMetricsLoading">刷新</el-button>
</div>
</div>
@@ -1657,14 +1666,44 @@ let isPageActive = false
const historicalMetricsData = ref(null)
const historicalMetricsLoading = ref(false)
const historyTimeRange = ref('1h')
const historyTimeOptions = [
{ label: '最近1分钟', value: '1m' },
{ label: '最近5分钟', value: '5m' },
{ label: '最近1小时', value: '1h' },
{ label: '最近1天', value: '1d' }
const makeDefaultRange = () => {
const now = new Date()
return [new Date(now.getTime() - 10 * 60 * 1000), now]
}
const monitorDateRange = ref(makeDefaultRange())
const monitorShortcuts = [
{ text: '最近10分钟', value: () => { const n = new Date(); return [new Date(n.getTime() - 10 * 60000), n] } },
{ text: '最近30分钟', value: () => { const n = new Date(); return [new Date(n.getTime() - 30 * 60000), n] } },
{ text: '最近1小时', value: () => { const n = new Date(); return [new Date(n.getTime() - 3600000), n] } },
{ text: '最近6小时', value: () => { const n = new Date(); return [new Date(n.getTime() - 6 * 3600000), n] } },
{ text: '最近12小时', value: () => { const n = new Date(); return [new Date(n.getTime() - 12 * 3600000), n] } },
{ text: '最近1天', value: () => { const n = new Date(); return [new Date(n.getTime() - 86400000), n] } },
{ text: '最近7天', value: () => { const n = new Date(); return [new Date(n.getTime() - 7 * 86400000), n] } },
]
function calcInterval(startTime, endTime) {
const spanMin = (endTime.getTime() - startTime.getTime()) / 60000
if (spanMin < 30) return '1m'
if (spanMin < 60) return '3m'
if (spanMin < 360) return '5m'
if (spanMin < 720) return '15m'
if (spanMin < 1440) return '30m'
if (spanMin < 4320) return '1h'
if (spanMin < 10080) return '2h'
if (spanMin < 43200) return '6h'
if (spanMin < 129600) return '12h'
return '1d'
}
const intervalLabelMap = { '1m': '1分钟', '3m': '3分钟', '5m': '5分钟', '15m': '15分钟', '30m': '30分钟', '1h': '1小时', '2h': '2小时', '6h': '6小时', '12h': '12小时', '1d': '1天' }
const currentIntervalLabel = computed(() => {
if (!monitorDateRange.value || monitorDateRange.value.length < 2) return '-'
const iv = calcInterval(new Date(monitorDateRange.value[0]), new Date(monitorDateRange.value[1]))
return intervalLabelMap[iv] || iv
})
const latestMetrics = computed(() => {
const arr = historicalMetricsData.value
if (!Array.isArray(arr) || !arr.length) return null
@@ -1704,23 +1743,19 @@ const vmMemPercent = (m) => {
const loadHistoricalMetrics = async () => {
if (!serviceId.value || !detail.value?.name) return
if (!monitorDateRange.value || monitorDateRange.value.length < 2) return
historicalMetricsLoading.value = true
try {
const now = new Date()
let startTime = new Date()
switch (historyTimeRange.value) {
case '1m': startTime.setMinutes(now.getMinutes() - 1); break
case '5m': startTime.setMinutes(now.getMinutes() - 5); break
case '1h': startTime.setHours(now.getHours() - 1); break
case '1d': startTime.setDate(now.getDate() - 1); break
}
const startTime = new Date(monitorDateRange.value[0])
const endTime = new Date(monitorDateRange.value[1])
const interval = calcInterval(startTime, endTime)
const params = {
service_id: serviceId.value,
host_id: vmHostId.value,
vm_name: detail.value.name,
start: startTime.toISOString(),
end_time: now.toISOString(),
interval: { '1m': '1m', '5m': '5m', '1h': '1h', '1d': '1d' }[historyTimeRange.value] || '5m'
end_time: endTime.toISOString(),
interval
}
const res = await getMetricsHistory(params)
const body = res?.data
@@ -1742,8 +1777,8 @@ const renderHistoricalCharts = () => {
const metrics = historicalMetricsData.value
if (!Array.isArray(metrics) || !metrics.length) return
const range = historyTimeRange.value
const showDate = range === '1d'
const spanMs = monitorDateRange.value ? (new Date(monitorDateRange.value[1]).getTime() - new Date(monitorDateRange.value[0]).getTime()) : 0
const showDate = spanMs >= 12 * 3600 * 1000
const symbolType = showDate ? 'circle' : 'none'
const labelRotate = showDate ? 45 : 0