Skip to content

Commit 65b82b7

Browse files
committed
Update.
1 parent 6ffb093 commit 65b82b7

File tree

4 files changed

+102
-86
lines changed

4 files changed

+102
-86
lines changed

cmd/dashboard/controller/api_v1.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (v *apiV1) serverList(c *gin.Context) {
7878
if ce, ok := listCache[cacheKey]; ok && time.Since(ce.ts) <= 500*time.Millisecond {
7979
payload := ce.data
8080
listCacheMu.Unlock()
81-
WriteJSONPayload(c, 200, payload)
81+
WriteJSONPayload(c, 200, payload)
8282
return
8383
}
8484
listCacheMu.Unlock()
@@ -122,7 +122,7 @@ func (v *apiV1) serverDetails(c *gin.Context) {
122122
if ce, ok := listCache[cacheKey]; ok && time.Since(ce.ts) <= 500*time.Millisecond {
123123
payload := ce.data
124124
listCacheMu.Unlock()
125-
WriteJSONPayload(c, 200, payload)
125+
WriteJSONPayload(c, 200, payload)
126126
return
127127
}
128128
listCacheMu.Unlock()

cmd/dashboard/controller/common_page.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,9 @@ func (cp *commonPage) network(c *gin.Context) {
426426
go func(monitorID uint64) {
427427
sem <- struct{}{}
428428
defer func() { <-sem }()
429+
// 提升上限到6000条,覆盖更高采样频率(~15s采样≈5760),确保完整24小时窗口
429430
hs, err := monitorOps.GetMonitorHistoriesByServerAndMonitorRangeReverseLimit(
430-
id, monitorID, startTime, endTime, 1000,
431+
id, monitorID, startTime, endTime, 6000,
431432
)
432433
resultChan <- monitorResult{histories: hs, err: err}
433434
}(m.ID)

cmd/dashboard/controller/controller.go

Lines changed: 77 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -632,95 +632,95 @@ func buildTrafficData() []map[string]interface{} {
632632
var trafficData []map[string]interface{}
633633

634634
for cycleID, stats := range statsStore {
635-
// 查找对应的Alert规则,用于获取周期设置
636-
var alert *model.AlertRule
637-
for _, a := range singleton.Alerts {
638-
if a.ID == cycleID {
639-
alert = a
640-
break
641-
}
635+
// 查找对应的Alert规则,用于获取周期设置
636+
var alert *model.AlertRule
637+
for _, a := range singleton.Alerts {
638+
if a.ID == cycleID {
639+
alert = a
640+
break
642641
}
642+
}
643643

644-
// 如果找不到Alert规则,跳过此项
645-
if alert == nil {
646-
continue
647-
}
644+
// 如果找不到Alert规则,跳过此项
645+
if alert == nil {
646+
continue
647+
}
648648

649-
// 找到与流量相关的Rule
650-
var flowRule *model.Rule
651-
for i := range alert.Rules {
652-
if alert.Rules[i].IsTransferDurationRule() {
653-
flowRule = &alert.Rules[i]
654-
break
655-
}
649+
// 找到与流量相关的Rule
650+
var flowRule *model.Rule
651+
for i := range alert.Rules {
652+
if alert.Rules[i].IsTransferDurationRule() {
653+
flowRule = &alert.Rules[i]
654+
break
656655
}
656+
}
657657

658-
// 如果没有流量相关规则,跳过
659-
if flowRule == nil {
660-
continue
661-
}
658+
// 如果没有流量相关规则,跳过
659+
if flowRule == nil {
660+
continue
661+
}
662662

663-
// 确保周期开始和结束时间正确设置
664-
from := flowRule.GetTransferDurationStart()
665-
to := flowRule.GetTransferDurationEnd()
666-
667-
// 更新stats中的周期时间,确保与规则一致
668-
stats.From = from
669-
stats.To = to
670-
stats.Max = uint64(flowRule.Max)
671-
stats.Name = alert.Name
672-
673-
// 在读锁外部异步更新周期信息,避免死锁
674-
go updateCycleStatsInfo(cycleID, from, to, uint64(flowRule.Max), alert.Name)
675-
676-
// 生成流量数据条目
677-
for serverID, transfer := range stats.Transfer {
678-
serverName := ""
679-
if stats.ServerName != nil {
680-
if name, exists := stats.ServerName[serverID]; exists {
681-
serverName = name
682-
}
683-
}
663+
// 确保周期开始和结束时间正确设置
664+
from := flowRule.GetTransferDurationStart()
665+
to := flowRule.GetTransferDurationEnd()
684666

685-
// 如果没有名称,尝试从ServerList获取
686-
if serverName == "" {
687-
singleton.ServerLock.RLock()
688-
if server := singleton.ServerList[serverID]; server != nil {
689-
serverName = server.Name
690-
}
691-
singleton.ServerLock.RUnlock()
692-
}
667+
// 更新stats中的周期时间,确保与规则一致
668+
stats.From = from
669+
stats.To = to
670+
stats.Max = uint64(flowRule.Max)
671+
stats.Name = alert.Name
672+
673+
// 在读锁外部异步更新周期信息,避免死锁
674+
go updateCycleStatsInfo(cycleID, from, to, uint64(flowRule.Max), alert.Name)
693675

694-
// 计算使用百分比
695-
usedPercent := float64(0)
696-
if stats.Max > 0 {
697-
usedPercent = (float64(transfer) / float64(stats.Max)) * 100
698-
usedPercent = math.Max(0, math.Min(100, usedPercent)) // 限制在0-100范围
676+
// 生成流量数据条目
677+
for serverID, transfer := range stats.Transfer {
678+
serverName := ""
679+
if stats.ServerName != nil {
680+
if name, exists := stats.ServerName[serverID]; exists {
681+
serverName = name
699682
}
683+
}
700684

701-
// 获取周期单位和开始时间,用于前端展示
702-
cycleUnit := flowRule.CycleUnit
703-
704-
// 构建完整的流量数据项,包含周期信息
705-
trafficItem := map[string]interface{}{
706-
"server_id": serverID,
707-
"server_name": serverName,
708-
"max_bytes": stats.Max,
709-
"used_bytes": transfer,
710-
"max_formatted": formatBytes(stats.Max),
711-
"used_formatted": formatBytes(transfer),
712-
"used_percent": math.Round(usedPercent*100) / 100,
713-
"cycle_name": stats.Name,
714-
"cycle_id": strconv.FormatUint(cycleID, 10),
715-
"cycle_start": stats.From.Format(time.RFC3339),
716-
"cycle_end": stats.To.Format(time.RFC3339),
717-
"cycle_unit": cycleUnit,
718-
"cycle_interval": flowRule.CycleInterval,
719-
"is_bytes_source": true,
720-
"now": time.Now().Unix() * 1000,
685+
// 如果没有名称,尝试从ServerList获取
686+
if serverName == "" {
687+
singleton.ServerLock.RLock()
688+
if server := singleton.ServerList[serverID]; server != nil {
689+
serverName = server.Name
721690
}
691+
singleton.ServerLock.RUnlock()
692+
}
693+
694+
// 计算使用百分比
695+
usedPercent := float64(0)
696+
if stats.Max > 0 {
697+
usedPercent = (float64(transfer) / float64(stats.Max)) * 100
698+
usedPercent = math.Max(0, math.Min(100, usedPercent)) // 限制在0-100范围
699+
}
700+
701+
// 获取周期单位和开始时间,用于前端展示
702+
cycleUnit := flowRule.CycleUnit
703+
704+
// 构建完整的流量数据项,包含周期信息
705+
trafficItem := map[string]interface{}{
706+
"server_id": serverID,
707+
"server_name": serverName,
708+
"max_bytes": stats.Max,
709+
"used_bytes": transfer,
710+
"max_formatted": formatBytes(stats.Max),
711+
"used_formatted": formatBytes(transfer),
712+
"used_percent": math.Round(usedPercent*100) / 100,
713+
"cycle_name": stats.Name,
714+
"cycle_id": strconv.FormatUint(cycleID, 10),
715+
"cycle_start": stats.From.Format(time.RFC3339),
716+
"cycle_end": stats.To.Format(time.RFC3339),
717+
"cycle_unit": cycleUnit,
718+
"cycle_interval": flowRule.CycleInterval,
719+
"is_bytes_source": true,
720+
"now": time.Now().Unix() * 1000,
721+
}
722722

723-
trafficData = append(trafficData, trafficItem)
723+
trafficData = append(trafficData, trafficItem)
724724
}
725725
}
726726

resource/template/theme-default/network.html

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
resizeTimer: null,
9595
tooltipTimer: null,
9696
monitorConfigsLoaded: false,
97+
loadedFromAPI: false,
9798
timeRange: '24h', // 默认显示24小时
9899
currentServerId: null, // 当前选中的服务器ID
99100
hoverTipLabel: '' // 悬停在自定义按钮时的临时 tooltip 文本
@@ -347,16 +348,28 @@
347348

348349
// 优化初始化序列,先加载监控配置
349350
this.$nextTick(() => {
350-
// 先渲染图表
351-
this.renderChart();
351+
// 先渲染图表
352+
this.renderChart();
352353

353354
// 先加载监控配置,然后再处理数据
354355
loadMonitorConfigs().always(() => {
355356
this.monitorConfigsLoaded = true;
356357

358+
// 将当前选中服务器默认设置为列表中的第一个,确保后续切换时间范围触发 API 拉取
359+
if (!this.currentServerId && Array.isArray(this.servers) && this.servers.length > 0 && this.servers[0] && this.servers[0].ID) {
360+
this.currentServerId = this.servers[0].ID;
361+
}
362+
357363
// 然后加载数据,避免阻塞UI,默认显示24小时数据
358364
setTimeout(() => {
365+
// 首屏先用预取数据渲染
359366
this.filterInitialDataByTimeRange(this.timeRange);
367+
// 再异步用后端完整窗口刷新一次
368+
if (this.currentServerId) {
369+
this.getMonitorHistory(this.currentServerId, this.timeRange)
370+
.then((monitorInfo) => { this.parseMonitorInfo(monitorInfo); })
371+
.catch(() => { /* 保留预取数据 */ });
372+
}
360373
}, 50);
361374
});
362375
});
@@ -523,6 +536,7 @@
523536
redirectNetwork(id) {
524537
// 保存当前选中的服务器ID
525538
this.currentServerId = id;
539+
this.loadedFromAPI = false;
526540

527541
// 性能优化:显示加载状态,避免用户等待
528542
// 临时关闭 tooltip,避免渲染过程中 HTML tooltip 触发 innerHTML 报错
@@ -609,6 +623,9 @@
609623
return;
610624
}
611625

626+
// 成功解析后,认为已使用后端返回数据
627+
this.loadedFromAPI = true;
628+
612629
// 固定图例顺序:按监测点名称(升序)排序,PC/移动端一致
613630
const displayData = processedData.slice().sort((a, b) => {
614631
const an = (a.monitor_name || '').toString();
@@ -895,10 +912,7 @@
895912
}
896913
},
897914
switchTimeRange(range) {
898-
// 如果时间范围没有变化,直接返回
899-
if (this.timeRange === range) {
900-
return;
901-
}
915+
// 即使与当前时间范围相同也触发刷新,确保不使用首屏的有限预取数据
902916

903917
this.timeRange = range;
904918

@@ -986,6 +1000,7 @@
9861000
},
9871001
filterInitialDataByTimeRange(range) {
9881002
// 根据时间范围过滤初始数据
1003+
this.loadedFromAPI = false; // 预取数据不算后端完整数据
9891004
const now = Date.now();
9901005
const timeLimit = range === '24h' ? 24 * 60 * 60 * 1000 : 72 * 60 * 60 * 1000; // 改为72小时
9911006
const cutoffTime = now - timeLimit;

0 commit comments

Comments
 (0)