feat(monitor): 监控时间选择器统一为相对时间+自定义范围双模式
Build and Deploy Vue3 / build (push) Successful in 2m32s
Build and Deploy Vue3 / deploy (push) Successful in 32s

- VmMonitor/VmDetail/UserVmDetail/HostDetail 四个页面统一改造
- 支持「最近」模式(动态计算时间范围)和「自定义」模式(固定日期范围)
- 每小时流量图表同步应用双模式选择器
- 移除旧的 monitorShortcuts 快捷方式

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
shiran
2026-06-03 18:28:12 +08:00
parent d01c4e2e34
commit 0829dc9ce4
4 changed files with 223 additions and 106 deletions
+71 -35
View File
@@ -402,15 +402,28 @@
<div class="section-header">
<h3 class="section-title">监控指标</h3>
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap">
<el-radio-group v-model="monitorTimeMode" size="small" @change="loadMetricsHistory">
<el-radio-button label="relative">最近</el-radio-button>
<el-radio-button label="fixed">自定义</el-radio-button>
</el-radio-group>
<el-select v-if="monitorTimeMode === 'relative'" v-model="monitorRelativeMinutes" size="small" style="width: 120px" @change="loadMetricsHistory">
<el-option label="10分钟" :value="10" />
<el-option label="30分钟" :value="30" />
<el-option label="1小时" :value="60" />
<el-option label="6小时" :value="360" />
<el-option label="12小时" :value="720" />
<el-option label="1" :value="1440" />
<el-option label="7" :value="10080" />
</el-select>
<el-date-picker
v-else
v-model="monitorDateRange"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
start-placeholder="开始"
end-placeholder="结束"
size="small"
style="width: 360px"
:shortcuts="monitorShortcuts"
style="width: 340px"
@change="loadMetricsHistory"
/>
<span style="font-size:12px;color:#909399;white-space:nowrap">粒度: {{ currentIntervalLabel }}</span>
@@ -516,16 +529,27 @@
<div class="section-block" style="margin-top:16px">
<div class="section-header">
<h3 class="section-title">每小时流量</h3>
<div style="display: flex; align-items: center; gap: 8px">
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap">
<el-radio-group v-model="trafficTimeMode" size="small" @change="loadTrafficHourly">
<el-radio-button label="relative">最近</el-radio-button>
<el-radio-button label="fixed">自定义</el-radio-button>
</el-radio-group>
<el-select v-if="trafficTimeMode === 'relative'" v-model="trafficRelativeMinutes" size="small" style="width: 120px" @change="loadTrafficHourly">
<el-option label="6小时" :value="360" />
<el-option label="12小时" :value="720" />
<el-option label="1" :value="1440" />
<el-option label="3" :value="4320" />
<el-option label="7" :value="10080" />
</el-select>
<el-date-picker
v-else
v-model="trafficHourlyRange"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
start-placeholder="开始"
end-placeholder="结束"
size="small"
style="width: 360px"
:shortcuts="monitorShortcuts"
style="width: 340px"
@change="loadTrafficHourly"
/>
<el-button size="small" :icon="Refresh" @click="loadTrafficHourly" :loading="trafficHourlyLoading">刷新</el-button>
@@ -2259,24 +2283,35 @@ const submitAddTraffic = async () => {
}
// ---- 每小时流量统计 ----
const trafficTimeMode = ref('relative')
const trafficRelativeMinutes = ref(1440)
const trafficHourlyRange = ref(null)
const trafficHourlyData = ref([])
const trafficHourlyLoading = ref(false)
const trafficHourlyChartRef = ref(null)
let trafficHourlyChart = null
const getTrafficTimeRange = () => {
if (trafficTimeMode.value === 'relative') {
const endTime = new Date()
const startTime = new Date(endTime - trafficRelativeMinutes.value * 60 * 1000)
return { startTime, endTime }
} else {
if (!trafficHourlyRange.value || trafficHourlyRange.value.length < 2) return null
return { startTime: new Date(trafficHourlyRange.value[0]), endTime: new Date(trafficHourlyRange.value[1]) }
}
}
const loadTrafficHourly = async () => {
if (!userGoodsId.value) return
if (!trafficHourlyRange.value) {
const now = new Date()
trafficHourlyRange.value = [new Date(now.getTime() - 24 * 3600 * 1000), now]
}
const range = getTrafficTimeRange()
if (!range) return
trafficHourlyLoading.value = true
try {
const res = await getUserVmTrafficHourly({
user_goods_id: userGoodsId.value,
start: new Date(trafficHourlyRange.value[0]).toISOString(),
end_time: new Date(trafficHourlyRange.value[1]).toISOString()
start: range.startTime.toISOString(),
end_time: range.endTime.toISOString()
})
const raw = res?.data?.data?.data
trafficHourlyData.value = typeof raw === 'string' ? JSON.parse(raw) : (Array.isArray(raw) ? raw : [])
@@ -2372,21 +2407,20 @@ let trafficUsedChart = null
const metricsData = ref(null)
const metricsLoading = ref(false)
const makeDefaultRange = () => {
const now = new Date()
return [new Date(now.getTime() - 10 * 60 * 1000), now]
}
const monitorDateRange = ref(makeDefaultRange())
const monitorTimeMode = ref('relative')
const monitorRelativeMinutes = ref(10)
const monitorDateRange = ref(null)
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] } },
]
const getMonitorTimeRange = () => {
if (monitorTimeMode.value === 'relative') {
const endTime = new Date()
const startTime = new Date(endTime - monitorRelativeMinutes.value * 60 * 1000)
return { startTime, endTime }
} else {
if (!monitorDateRange.value || monitorDateRange.value.length < 2) return null
return { startTime: new Date(monitorDateRange.value[0]), endTime: new Date(monitorDateRange.value[1]) }
}
}
function calcInterval(startTime, endTime) {
const spanMin = (endTime.getTime() - startTime.getTime()) / 60000
@@ -2404,8 +2438,9 @@ function calcInterval(startTime, endTime) {
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]))
const range = getMonitorTimeRange()
if (!range) return '-'
const iv = calcInterval(range.startTime, range.endTime)
return intervalLabelMap[iv] || iv
})
@@ -2450,11 +2485,11 @@ const vmMemPercent = (m) => {
const loadMetricsHistory = async () => {
if (!userGoodsId.value) return
if (!monitorDateRange.value || monitorDateRange.value.length < 2) return
const range = getMonitorTimeRange()
if (!range) return
metricsLoading.value = true
try {
const startTime = new Date(monitorDateRange.value[0])
const endTime = new Date(monitorDateRange.value[1])
const { startTime, endTime } = range
const interval = calcInterval(startTime, endTime)
const params = {
user_goods_id: userGoodsId.value,
@@ -2482,7 +2517,8 @@ const renderMetricsCharts = () => {
const metrics = metricsData.value
if (!Array.isArray(metrics) || !metrics.length) return
const spanMs = monitorDateRange.value ? (new Date(monitorDateRange.value[1]).getTime() - new Date(monitorDateRange.value[0]).getTime()) : 600000
const range = getMonitorTimeRange()
const spanMs = range ? (range.endTime.getTime() - range.startTime.getTime()) : 600000
const showDate = spanMs >= 86400000
const symbolType = metrics.length < 30 ? 'circle' : 'none'
const labelRotate = showDate ? 45 : 0
+38 -24
View File
@@ -259,15 +259,28 @@
<div class="section-header">
<h3 class="section-title">监控指标</h3>
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap">
<el-radio-group v-model="monitorTimeMode" size="small" @change="loadHistoricalMetrics">
<el-radio-button label="relative">最近</el-radio-button>
<el-radio-button label="fixed">自定义</el-radio-button>
</el-radio-group>
<el-select v-if="monitorTimeMode === 'relative'" v-model="monitorRelativeMinutes" size="small" style="width: 120px" @change="loadHistoricalMetrics">
<el-option label="10分钟" :value="10" />
<el-option label="30分钟" :value="30" />
<el-option label="1小时" :value="60" />
<el-option label="6小时" :value="360" />
<el-option label="12小时" :value="720" />
<el-option label="1天" :value="1440" />
<el-option label="7天" :value="10080" />
</el-select>
<el-date-picker
v-else
v-model="monitorDateRange"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
start-placeholder="开始"
end-placeholder="结束"
size="small"
style="width: 360px"
:shortcuts="monitorShortcuts"
style="width: 340px"
@change="loadHistoricalMetrics"
/>
<span style="font-size:12px;color:#909399;white-space:nowrap">粒度: {{ currentIntervalLabel }}</span>
@@ -1109,21 +1122,20 @@ const latestMetrics = computed(() => {
return arr[arr.length - 1]
})
const makeDefaultRange = () => {
const now = new Date()
return [new Date(now.getTime() - 10 * 60 * 1000), now]
}
const monitorDateRange = ref(makeDefaultRange())
const monitorTimeMode = ref('relative')
const monitorRelativeMinutes = ref(10)
const monitorDateRange = ref(null)
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] } },
]
const getMonitorTimeRange = () => {
if (monitorTimeMode.value === 'relative') {
const endTime = new Date()
const startTime = new Date(endTime - monitorRelativeMinutes.value * 60 * 1000)
return { startTime, endTime }
} else {
if (!monitorDateRange.value || monitorDateRange.value.length < 2) return null
return { startTime: new Date(monitorDateRange.value[0]), endTime: new Date(monitorDateRange.value[1]) }
}
}
function calcInterval(startTime, endTime) {
const spanMin = (endTime.getTime() - startTime.getTime()) / 60000
@@ -1141,18 +1153,19 @@ function calcInterval(startTime, endTime) {
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]))
const range = getMonitorTimeRange()
if (!range) return '-'
const iv = calcInterval(range.startTime, range.endTime)
return intervalLabelMap[iv] || iv
})
const loadHistoricalMetrics = async () => {
if (!serviceId.value || !hostId.value) return
if (!monitorDateRange.value || monitorDateRange.value.length < 2) return
const range = getMonitorTimeRange()
if (!range) return
historicalMetricsLoading.value = true
try {
const startTime = new Date(monitorDateRange.value[0])
const endTime = new Date(monitorDateRange.value[1])
const { startTime, endTime } = range
const interval = calcInterval(startTime, endTime)
const params = {
service_id: serviceId.value,
@@ -1192,7 +1205,8 @@ const renderHistoricalCharts = () => {
const metrics = historicalMetricsData.value
if (!Array.isArray(metrics) || !metrics.length) return
const spanMs = monitorDateRange.value ? (new Date(monitorDateRange.value[1]).getTime() - new Date(monitorDateRange.value[0]).getTime()) : 0
const range = getMonitorTimeRange()
const spanMs = range ? (range.endTime.getTime() - range.startTime.getTime()) : 0
const showDate = spanMs >= 12 * 3600 * 1000
const symbolType = spanMs >= 7 * 86400 * 1000 ? 'circle' : 'none'
const labelRotate = showDate ? 45 : 0
+71 -35
View File
@@ -594,15 +594,28 @@
<div class="section-header">
<h3 class="section-title">监控指标</h3>
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap">
<el-radio-group v-model="monitorTimeMode" size="small" @change="loadHistoricalMetrics">
<el-radio-button label="relative">最近</el-radio-button>
<el-radio-button label="fixed">自定义</el-radio-button>
</el-radio-group>
<el-select v-if="monitorTimeMode === 'relative'" v-model="monitorRelativeMinutes" size="small" style="width: 120px" @change="loadHistoricalMetrics">
<el-option label="10分钟" :value="10" />
<el-option label="30分钟" :value="30" />
<el-option label="1小时" :value="60" />
<el-option label="6小时" :value="360" />
<el-option label="12小时" :value="720" />
<el-option label="1" :value="1440" />
<el-option label="7" :value="10080" />
</el-select>
<el-date-picker
v-else
v-model="monitorDateRange"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
start-placeholder="开始"
end-placeholder="结束"
size="small"
style="width: 360px"
:shortcuts="monitorShortcuts"
style="width: 340px"
@change="loadHistoricalMetrics"
/>
<span style="font-size:12px;color:#909399;white-space:nowrap">粒度: {{ currentIntervalLabel }}</span>
@@ -708,16 +721,27 @@
<div class="section-block">
<div class="section-header">
<h3 class="section-title">每小时流量</h3>
<div style="display: flex; align-items: center; gap: 8px">
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap">
<el-radio-group v-model="trafficTimeMode" size="small" @change="loadTrafficHourly">
<el-radio-button label="relative">最近</el-radio-button>
<el-radio-button label="fixed">自定义</el-radio-button>
</el-radio-group>
<el-select v-if="trafficTimeMode === 'relative'" v-model="trafficRelativeMinutes" size="small" style="width: 120px" @change="loadTrafficHourly">
<el-option label="6小时" :value="360" />
<el-option label="12小时" :value="720" />
<el-option label="1" :value="1440" />
<el-option label="3" :value="4320" />
<el-option label="7" :value="10080" />
</el-select>
<el-date-picker
v-else
v-model="trafficHourlyRange"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
start-placeholder="开始"
end-placeholder="结束"
size="small"
style="width: 360px"
:shortcuts="monitorShortcuts"
style="width: 340px"
@change="loadTrafficHourly"
/>
<el-button size="small" :icon="Refresh" @click="loadTrafficHourly" :loading="trafficHourlyLoading">刷新</el-button>
@@ -1911,21 +1935,20 @@ let isPageActive = false
const historicalMetricsData = ref(null)
const historicalMetricsLoading = ref(false)
const makeDefaultRange = () => {
const now = new Date()
return [new Date(now.getTime() - 10 * 60 * 1000), now]
}
const monitorDateRange = ref(makeDefaultRange())
const monitorTimeMode = ref('relative')
const monitorRelativeMinutes = ref(10)
const monitorDateRange = ref(null)
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] } },
]
const getMonitorTimeRange = () => {
if (monitorTimeMode.value === 'relative') {
const endTime = new Date()
const startTime = new Date(endTime - monitorRelativeMinutes.value * 60 * 1000)
return { startTime, endTime }
} else {
if (!monitorDateRange.value || monitorDateRange.value.length < 2) return null
return { startTime: new Date(monitorDateRange.value[0]), endTime: new Date(monitorDateRange.value[1]) }
}
}
function calcInterval(startTime, endTime) {
const spanMin = (endTime.getTime() - startTime.getTime()) / 60000
@@ -1943,8 +1966,9 @@ function calcInterval(startTime, endTime) {
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]))
const range = getMonitorTimeRange()
if (!range) return '-'
const iv = calcInterval(range.startTime, range.endTime)
return intervalLabelMap[iv] || iv
})
@@ -1987,11 +2011,11 @@ const vmMemPercent = (m) => {
const loadHistoricalMetrics = async () => {
if (!serviceId.value || !detail.value?.name) return
if (!monitorDateRange.value || monitorDateRange.value.length < 2) return
const range = getMonitorTimeRange()
if (!range) return
historicalMetricsLoading.value = true
try {
const startTime = new Date(monitorDateRange.value[0])
const endTime = new Date(monitorDateRange.value[1])
const { startTime, endTime } = range
const interval = calcInterval(startTime, endTime)
const params = {
service_id: serviceId.value,
@@ -2021,7 +2045,8 @@ const renderHistoricalCharts = () => {
const metrics = historicalMetricsData.value
if (!Array.isArray(metrics) || !metrics.length) return
const spanMs = monitorDateRange.value ? (new Date(monitorDateRange.value[1]).getTime() - new Date(monitorDateRange.value[0]).getTime()) : 0
const range = getMonitorTimeRange()
const spanMs = range ? (range.endTime.getTime() - range.startTime.getTime()) : 0
const showDate = spanMs >= 12 * 3600 * 1000
const symbolType = showDate ? 'circle' : 'none'
const labelRotate = showDate ? 45 : 0
@@ -3003,26 +3028,37 @@ const handleConnectNetwork = () => {
}
// ---- 每小时流量统计 ----
const trafficTimeMode = ref('relative')
const trafficRelativeMinutes = ref(1440)
const trafficHourlyRange = ref(null)
const trafficHourlyData = ref([])
const trafficHourlyLoading = ref(false)
const trafficHourlyChartRef = ref(null)
let trafficHourlyChart = null
const getTrafficTimeRange = () => {
if (trafficTimeMode.value === 'relative') {
const endTime = new Date()
const startTime = new Date(endTime - trafficRelativeMinutes.value * 60 * 1000)
return { startTime, endTime }
} else {
if (!trafficHourlyRange.value || trafficHourlyRange.value.length < 2) return null
return { startTime: new Date(trafficHourlyRange.value[0]), endTime: new Date(trafficHourlyRange.value[1]) }
}
}
const loadTrafficHourly = async () => {
if (!serviceId.value || !detail.value?.host_id || !detail.value?.name) return
if (!trafficHourlyRange.value) {
const now = new Date()
trafficHourlyRange.value = [new Date(now.getTime() - 24 * 3600 * 1000), now]
}
const range = getTrafficTimeRange()
if (!range) return
trafficHourlyLoading.value = true
try {
const res = await getVmTrafficHourly({
service_id: serviceId.value,
host_id: detail.value.host_id,
vm_name: detail.value.name,
start: new Date(trafficHourlyRange.value[0]).toISOString(),
end_time: new Date(trafficHourlyRange.value[1]).toISOString()
start: range.startTime.toISOString(),
end_time: range.endTime.toISOString()
})
const raw = res?.data?.data?.data
trafficHourlyData.value = typeof raw === 'string' ? JSON.parse(raw) : (Array.isArray(raw) ? raw : [])
+43 -12
View File
@@ -32,19 +32,34 @@
<div class="toolbar-row">
<div class="toolbar-item">
<span class="toolbar-label">时间</span>
<el-select v-model="timeRange" style="width: 140px" @change="handleRefresh">
<el-option label="最近10分钟" :value="10" />
<el-option label="最近30分钟" :value="30" />
<el-option label="最近1小时" :value="60" />
<el-option label="最近3小时" :value="180" />
<el-option label="最近6小时" :value="360" />
<el-option label="最近12小时" :value="720" />
<el-option label="最近24小时" :value="1440" />
<el-radio-group v-model="timeMode" size="small" @change="handleRefresh">
<el-radio-button label="relative">最近</el-radio-button>
<el-radio-button label="fixed">自定义</el-radio-button>
</el-radio-group>
<el-select v-if="timeMode === 'relative'" v-model="timeRange" style="width: 130px" @change="handleRefresh">
<el-option label="10分钟" :value="10" />
<el-option label="30分钟" :value="30" />
<el-option label="1小时" :value="60" />
<el-option label="3小时" :value="180" />
<el-option label="6小时" :value="360" />
<el-option label="12小时" :value="720" />
<el-option label="24小时" :value="1440" />
</el-select>
<el-date-picker
v-else
v-model="fixedDateRange"
type="datetimerange"
range-separator=""
start-placeholder="开始"
end-placeholder="结束"
size="small"
style="width: 340px"
@change="handleRefresh"
/>
</div>
<div class="toolbar-item">
<span class="toolbar-label">自动刷新</span>
<el-select v-model="autoRefreshInterval" style="width: 120px" @change="resetAutoRefresh">
<el-select v-model="autoRefreshInterval" style="width: 110px" @change="resetAutoRefresh">
<el-option label="关闭" :value="0" />
<el-option label="10秒" :value="10" />
<el-option label="30秒" :value="30" />
@@ -91,7 +106,9 @@ const selectedMetrics = ref(['cpu', 'memory'])
const metricsLoading = ref(false)
const loaded = ref(false)
const metricsDataMap = ref({})
const timeMode = ref('relative')
const timeRange = ref(60)
const fixedDateRange = ref(null)
const autoRefreshInterval = ref(0)
let autoRefreshTimer = null
@@ -169,11 +186,23 @@ const loadVmList = async () => {
}
}
const getTimeRange = () => {
if (timeMode.value === 'relative') {
const endTime = new Date()
const startTime = new Date(endTime - timeRange.value * 60 * 1000)
return { startTime, endTime }
} else {
if (!fixedDateRange.value || fixedDateRange.value.length < 2) return null
return { startTime: new Date(fixedDateRange.value[0]), endTime: new Date(fixedDateRange.value[1]) }
}
}
const handleRefresh = async () => {
if (!selectedVms.value.length) return
const range = getTimeRange()
if (!range) { ElMessage.warning('请选择时间范围'); return }
metricsLoading.value = true
const endTime = new Date()
const startTime = new Date(endTime - timeRange.value * 60 * 1000)
const { startTime, endTime } = range
const interval = calcInterval(endTime - startTime)
const dataMap = {}
@@ -208,7 +237,9 @@ const handleRefresh = async () => {
}
const renderCharts = () => {
const showDate = timeRange.value >= 720
const range = getTimeRange()
const spanMs = range ? (range.endTime - range.startTime) : 0
const showDate = spanMs >= 12 * 3600 * 1000
const labelRotate = showDate ? 30 : 0
for (const metric of selectedMetrics.value) {