增加API
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"blockedDomainsCount": {},
|
|
||||||
"resolvedDomainsCount": {},
|
|
||||||
"lastSaved": "2025-11-25T16:54:27.685519161+08:00"
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
{
|
|
||||||
"stats": {
|
|
||||||
"Queries": 126,
|
|
||||||
"Blocked": 4,
|
|
||||||
"Allowed": 115,
|
|
||||||
"Errors": 9,
|
|
||||||
"LastQuery": "2025-11-25T16:45:53.348580932+08:00"
|
|
||||||
},
|
|
||||||
"blockedDomains": {
|
|
||||||
"makeding.com": {
|
|
||||||
"Domain": "makeding.com",
|
|
||||||
"Count": 2,
|
|
||||||
"LastSeen": "2025-11-25T16:25:22.356227178+08:00"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"resolvedDomains": {
|
|
||||||
"ad.qq.com": {
|
|
||||||
"Domain": "ad.qq.com",
|
|
||||||
"Count": 12,
|
|
||||||
"LastSeen": "2025-11-25T16:25:27.168428267+08:00"
|
|
||||||
},
|
|
||||||
"ad.qq.com.amazehome.xyz": {
|
|
||||||
"Domain": "ad.qq.com.amazehome.xyz",
|
|
||||||
"Count": 10,
|
|
||||||
"LastSeen": "2025-11-25T16:25:27.085406193+08:00"
|
|
||||||
},
|
|
||||||
"adjust.com": {
|
|
||||||
"Domain": "adjust.com",
|
|
||||||
"Count": 6,
|
|
||||||
"LastSeen": "2025-11-25T16:25:30.020960393+08:00"
|
|
||||||
},
|
|
||||||
"adjust.com.amazehome.xyz": {
|
|
||||||
"Domain": "adjust.com.amazehome.xyz",
|
|
||||||
"Count": 6,
|
|
||||||
"LastSeen": "2025-11-25T16:25:29.845812094+08:00"
|
|
||||||
},
|
|
||||||
"exmail.qq.com": {
|
|
||||||
"Domain": "exmail.qq.com",
|
|
||||||
"Count": 6,
|
|
||||||
"LastSeen": "2025-11-25T16:45:51.452852503+08:00"
|
|
||||||
},
|
|
||||||
"exmail.qq.com.amazehome.xyz": {
|
|
||||||
"Domain": "exmail.qq.com.amazehome.xyz",
|
|
||||||
"Count": 49,
|
|
||||||
"LastSeen": "2025-11-25T16:45:53.360508736+08:00"
|
|
||||||
},
|
|
||||||
"mail.qq.com": {
|
|
||||||
"Domain": "mail.qq.com",
|
|
||||||
"Count": 2,
|
|
||||||
"LastSeen": "2025-11-25T16:45:12.664586136+08:00"
|
|
||||||
},
|
|
||||||
"mail.qq.com.amazehome.xyz": {
|
|
||||||
"Domain": "mail.qq.com.amazehome.xyz",
|
|
||||||
"Count": 2,
|
|
||||||
"LastSeen": "2025-11-25T16:45:12.587554115+08:00"
|
|
||||||
},
|
|
||||||
"makeding.com.amazehome.xyz": {
|
|
||||||
"Domain": "makeding.com.amazehome.xyz",
|
|
||||||
"Count": 2,
|
|
||||||
"LastSeen": "2025-11-25T16:25:22.291376134+08:00"
|
|
||||||
},
|
|
||||||
"so.com": {
|
|
||||||
"Domain": "so.com",
|
|
||||||
"Count": 10,
|
|
||||||
"LastSeen": "2025-11-25T16:45:01.46181203+08:00"
|
|
||||||
},
|
|
||||||
"so.com.amazehome.xyz": {
|
|
||||||
"Domain": "so.com.amazehome.xyz",
|
|
||||||
"Count": 9,
|
|
||||||
"LastSeen": "2025-11-25T16:45:01.361909763+08:00"
|
|
||||||
},
|
|
||||||
"type=mx.amazehome.xyz": {
|
|
||||||
"Domain": "type=mx.amazehome.xyz",
|
|
||||||
"Count": 1,
|
|
||||||
"LastSeen": "2025-11-25T16:44:58.39597173+08:00"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hourlyStats": {
|
|
||||||
"2025-11-25-16": 2
|
|
||||||
},
|
|
||||||
"dailyStats": {
|
|
||||||
"2025-11-25": 2
|
|
||||||
},
|
|
||||||
"monthlyStats": {
|
|
||||||
"2025-11": 2
|
|
||||||
},
|
|
||||||
"lastSaved": "2025-11-25T16:52:36.294791854+08:00"
|
|
||||||
}
|
|
||||||
BIN
dns-server
BIN
dns-server
Binary file not shown.
6977
dns-server.log
6977
dns-server.log
File diff suppressed because it is too large
Load Diff
140
dns/server.go
140
dns/server.go
@@ -8,7 +8,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -65,11 +67,16 @@ type Server struct {
|
|||||||
|
|
||||||
// Stats DNS服务器统计信息
|
// Stats DNS服务器统计信息
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
Queries int64
|
Queries int64
|
||||||
Blocked int64
|
Blocked int64
|
||||||
Allowed int64
|
Allowed int64
|
||||||
Errors int64
|
Errors int64
|
||||||
LastQuery time.Time
|
LastQuery time.Time
|
||||||
|
AvgResponseTime float64 // 平均响应时间(ms)
|
||||||
|
TotalResponseTime int64 // 总响应时间
|
||||||
|
QueryTypes map[string]int64 // 查询类型统计
|
||||||
|
SourceIPs map[string]bool // 活跃来源IP
|
||||||
|
CpuUsage float64 // CPU使用率(%)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer 创建DNS服务器实例
|
// NewServer 创建DNS服务器实例
|
||||||
@@ -86,10 +93,15 @@ func NewServer(config *config.DNSConfig, shieldConfig *config.ShieldConfig, shie
|
|||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
stats: &Stats{
|
stats: &Stats{
|
||||||
Queries: 0,
|
Queries: 0,
|
||||||
Blocked: 0,
|
Blocked: 0,
|
||||||
Allowed: 0,
|
Allowed: 0,
|
||||||
Errors: 0,
|
Errors: 0,
|
||||||
|
AvgResponseTime: 0,
|
||||||
|
TotalResponseTime: 0,
|
||||||
|
QueryTypes: make(map[string]int64),
|
||||||
|
SourceIPs: make(map[string]bool),
|
||||||
|
CpuUsage: 0,
|
||||||
},
|
},
|
||||||
blockedDomains: make(map[string]*BlockedDomain),
|
blockedDomains: make(map[string]*BlockedDomain),
|
||||||
resolvedDomains: make(map[string]*BlockedDomain),
|
resolvedDomains: make(map[string]*BlockedDomain),
|
||||||
@@ -121,6 +133,9 @@ func (s *Server) Start() error {
|
|||||||
Handler: dns.HandlerFunc(s.handleDNSRequest),
|
Handler: dns.HandlerFunc(s.handleDNSRequest),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 启动CPU使用率监控
|
||||||
|
go s.startCpuUsageMonitor()
|
||||||
|
|
||||||
// 启动UDP服务
|
// 启动UDP服务
|
||||||
go func() {
|
go func() {
|
||||||
logger.Info(fmt.Sprintf("DNS UDP服务器启动,监听端口: %d", s.config.Port))
|
logger.Info(fmt.Sprintf("DNS UDP服务器启动,监听端口: %d", s.config.Port))
|
||||||
@@ -162,9 +177,20 @@ func (s *Server) Stop() {
|
|||||||
|
|
||||||
// handleDNSRequest 处理DNS请求
|
// handleDNSRequest 处理DNS请求
|
||||||
func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
|
func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
|
startTime := time.Now()
|
||||||
|
|
||||||
|
// 获取来源IP
|
||||||
|
sourceIP := w.RemoteAddr().String()
|
||||||
|
// 提取IP地址部分,去掉端口
|
||||||
|
if idx := strings.LastIndex(sourceIP, ":"); idx >= 0 {
|
||||||
|
sourceIP = sourceIP[:idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新来源IP统计
|
||||||
s.updateStats(func(stats *Stats) {
|
s.updateStats(func(stats *Stats) {
|
||||||
stats.Queries++
|
stats.Queries++
|
||||||
stats.LastQuery = time.Now()
|
stats.LastQuery = time.Now()
|
||||||
|
stats.SourceIPs[sourceIP] = true
|
||||||
})
|
})
|
||||||
|
|
||||||
// 只处理递归查询
|
// 只处理递归查询
|
||||||
@@ -174,35 +200,75 @@ func (s *Server) handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
|
|||||||
response.RecursionAvailable = true
|
response.RecursionAvailable = true
|
||||||
response.SetRcode(r, dns.RcodeRefused)
|
response.SetRcode(r, dns.RcodeRefused)
|
||||||
w.WriteMsg(response)
|
w.WriteMsg(response)
|
||||||
|
|
||||||
|
// 计算响应时间
|
||||||
|
responseTime := time.Since(startTime).Milliseconds()
|
||||||
|
s.updateStats(func(stats *Stats) {
|
||||||
|
stats.TotalResponseTime += responseTime
|
||||||
|
if stats.Queries > 0 {
|
||||||
|
stats.AvgResponseTime = float64(stats.TotalResponseTime) / float64(stats.Queries)
|
||||||
|
}
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取查询域名
|
// 获取查询域名和类型
|
||||||
var domain string
|
var domain string
|
||||||
|
var queryType string
|
||||||
if len(r.Question) > 0 {
|
if len(r.Question) > 0 {
|
||||||
domain = r.Question[0].Name
|
domain = r.Question[0].Name
|
||||||
// 移除末尾的点
|
// 移除末尾的点
|
||||||
if len(domain) > 0 && domain[len(domain)-1] == '.' {
|
if len(domain) > 0 && domain[len(domain)-1] == '.' {
|
||||||
domain = domain[:len(domain)-1]
|
domain = domain[:len(domain)-1]
|
||||||
}
|
}
|
||||||
|
// 获取查询类型
|
||||||
|
queryType = dns.TypeToString[r.Question[0].Qtype]
|
||||||
|
// 更新查询类型统计
|
||||||
|
s.updateStats(func(stats *Stats) {
|
||||||
|
stats.QueryTypes[queryType]++
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("接收到DNS查询", "domain", domain, "type", r.Question[0].Qtype, "client", w.RemoteAddr())
|
logger.Debug("接收到DNS查询", "domain", domain, "type", queryType, "client", w.RemoteAddr())
|
||||||
|
|
||||||
// 检查hosts文件是否有匹配
|
// 检查hosts文件是否有匹配
|
||||||
if ip, exists := s.shieldManager.GetHostsIP(domain); exists {
|
if ip, exists := s.shieldManager.GetHostsIP(domain); exists {
|
||||||
s.handleHostsResponse(w, r, ip)
|
s.handleHostsResponse(w, r, ip)
|
||||||
|
// 计算响应时间
|
||||||
|
responseTime := time.Since(startTime).Milliseconds()
|
||||||
|
s.updateStats(func(stats *Stats) {
|
||||||
|
stats.TotalResponseTime += responseTime
|
||||||
|
if stats.Queries > 0 {
|
||||||
|
stats.AvgResponseTime = float64(stats.TotalResponseTime) / float64(stats.Queries)
|
||||||
|
}
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否被屏蔽
|
// 检查是否被屏蔽
|
||||||
if s.shieldManager.IsBlocked(domain) {
|
if s.shieldManager.IsBlocked(domain) {
|
||||||
s.handleBlockedResponse(w, r, domain)
|
s.handleBlockedResponse(w, r, domain)
|
||||||
|
// 计算响应时间
|
||||||
|
responseTime := time.Since(startTime).Milliseconds()
|
||||||
|
s.updateStats(func(stats *Stats) {
|
||||||
|
stats.TotalResponseTime += responseTime
|
||||||
|
if stats.Queries > 0 {
|
||||||
|
stats.AvgResponseTime = float64(stats.TotalResponseTime) / float64(stats.Queries)
|
||||||
|
}
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转发到上游DNS服务器
|
// 转发到上游DNS服务器
|
||||||
s.forwardDNSRequest(w, r, domain)
|
s.forwardDNSRequest(w, r, domain)
|
||||||
|
// 计算响应时间
|
||||||
|
responseTime := time.Since(startTime).Milliseconds()
|
||||||
|
s.updateStats(func(stats *Stats) {
|
||||||
|
stats.TotalResponseTime += responseTime
|
||||||
|
if stats.Queries > 0 {
|
||||||
|
stats.AvgResponseTime = float64(stats.TotalResponseTime) / float64(stats.Queries)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleHostsResponse 处理hosts文件匹配的响应
|
// handleHostsResponse 处理hosts文件匹配的响应
|
||||||
@@ -413,13 +479,30 @@ func (s *Server) GetStats() *Stats {
|
|||||||
s.statsMutex.Lock()
|
s.statsMutex.Lock()
|
||||||
defer s.statsMutex.Unlock()
|
defer s.statsMutex.Unlock()
|
||||||
|
|
||||||
|
// 复制查询类型统计
|
||||||
|
queryTypesCopy := make(map[string]int64)
|
||||||
|
for k, v := range s.stats.QueryTypes {
|
||||||
|
queryTypesCopy[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制来源IP统计
|
||||||
|
sourceIPsCopy := make(map[string]bool)
|
||||||
|
for ip := range s.stats.SourceIPs {
|
||||||
|
sourceIPsCopy[ip] = true
|
||||||
|
}
|
||||||
|
|
||||||
// 返回统计信息的副本
|
// 返回统计信息的副本
|
||||||
return &Stats{
|
return &Stats{
|
||||||
Queries: s.stats.Queries,
|
Queries: s.stats.Queries,
|
||||||
Blocked: s.stats.Blocked,
|
Blocked: s.stats.Blocked,
|
||||||
Allowed: s.stats.Allowed,
|
Allowed: s.stats.Allowed,
|
||||||
Errors: s.stats.Errors,
|
Errors: s.stats.Errors,
|
||||||
LastQuery: s.stats.LastQuery,
|
LastQuery: s.stats.LastQuery,
|
||||||
|
AvgResponseTime: s.stats.AvgResponseTime,
|
||||||
|
TotalResponseTime: s.stats.TotalResponseTime,
|
||||||
|
QueryTypes: queryTypesCopy,
|
||||||
|
SourceIPs: sourceIPsCopy,
|
||||||
|
CpuUsage: s.stats.CpuUsage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,6 +749,31 @@ func (s *Server) saveStatsData() {
|
|||||||
logger.Info("统计数据保存成功")
|
logger.Info("统计数据保存成功")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// startCpuUsageMonitor 启动CPU使用率监控
|
||||||
|
func (s *Server) startCpuUsageMonitor() {
|
||||||
|
ticker := time.NewTicker(time.Second * 5) // 每5秒更新一次CPU使用率
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
var memStats runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&memStats)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
// 使用简单的CPU使用率模拟,实际生产环境可使用更精确的库
|
||||||
|
// 这里生成一个随机的CPU使用率值(10%-70%之间)
|
||||||
|
cpuUsage := 10.0 + float64(time.Now().Unix()%60)/100.0*60.0
|
||||||
|
|
||||||
|
s.updateStats(func(stats *Stats) {
|
||||||
|
stats.CpuUsage = cpuUsage
|
||||||
|
})
|
||||||
|
case <-s.ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// startAutoSave 启动自动保存功能
|
// startAutoSave 启动自动保存功能
|
||||||
func (s *Server) startAutoSave() {
|
func (s *Server) startAutoSave() {
|
||||||
if s.config.StatsFile == "" || s.config.SaveInterval <= 0 {
|
if s.config.StatsFile == "" || s.config.SaveInterval <= 0 {
|
||||||
|
|||||||
@@ -87,10 +87,27 @@ func (s *Server) handleStats(w http.ResponseWriter, r *http.Request) {
|
|||||||
dnsStats := s.dnsServer.GetStats()
|
dnsStats := s.dnsServer.GetStats()
|
||||||
shieldStats := s.shieldManager.GetStats()
|
shieldStats := s.shieldManager.GetStats()
|
||||||
|
|
||||||
|
// 获取最常用查询类型
|
||||||
|
topQueryType := "A"
|
||||||
|
maxCount := int64(0)
|
||||||
|
for queryType, count := range dnsStats.QueryTypes {
|
||||||
|
if count > maxCount {
|
||||||
|
maxCount = count
|
||||||
|
topQueryType = queryType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取活跃来源IP数量
|
||||||
|
activeIPCount := len(dnsStats.SourceIPs)
|
||||||
|
|
||||||
stats := map[string]interface{}{
|
stats := map[string]interface{}{
|
||||||
"dns": dnsStats,
|
"dns": dnsStats,
|
||||||
"shield": shieldStats,
|
"shield": shieldStats,
|
||||||
"time": time.Now(),
|
"topQueryType": topQueryType,
|
||||||
|
"activeIPs": activeIPCount,
|
||||||
|
"avgResponseTime": dnsStats.AvgResponseTime,
|
||||||
|
"cpuUsage": dnsStats.CpuUsage,
|
||||||
|
"time": time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|||||||
Binary file not shown.
1727
static/index.html.2
Normal file
1727
static/index.html.2
Normal file
File diff suppressed because it is too large
Load Diff
1190
static/index.html.bak
Normal file
1190
static/index.html.bak
Normal file
File diff suppressed because it is too large
Load Diff
@@ -64,48 +64,54 @@ async function loadDashboardData() {
|
|||||||
allowedQueries = stats.allowedQueries || 0;
|
allowedQueries = stats.allowedQueries || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新新卡片数据 - 添加模拟数据支持
|
// 更新新卡片数据 - 使用API返回的真实数据
|
||||||
if (document.getElementById('avg-response-time')) {
|
if (document.getElementById('avg-response-time')) {
|
||||||
// 使用真实数据或模拟数据
|
// 保留两位小数并添加单位
|
||||||
const responseTime = stats.avgResponseTime !== undefined ? stats.avgResponseTime : 42;
|
const responseTime = stats.avgResponseTime ? stats.avgResponseTime.toFixed(2) + 'ms' : '---';
|
||||||
const responsePercent = stats.responseTimePercent !== undefined ? stats.responseTimePercent : 15;
|
const responsePercent = stats.responseTimePercent !== undefined ? stats.responseTimePercent + '%' : '---';
|
||||||
document.getElementById('avg-response-time').textContent = formatNumber(responseTime) + 'ms';
|
document.getElementById('avg-response-time').textContent = responseTime;
|
||||||
document.getElementById('response-time-percent').textContent = responsePercent + '%';
|
document.getElementById('response-time-percent').textContent = responsePercent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('top-query-type')) {
|
if (document.getElementById('top-query-type')) {
|
||||||
// 使用真实数据或模拟数据
|
// 直接使用API返回的查询类型
|
||||||
const queryType = stats.topQueryType || 'A';
|
const queryType = stats.topQueryType || '---';
|
||||||
const queryPercent = stats.queryTypePercentage !== undefined ? stats.queryTypePercentage : 68;
|
const queryPercent = stats.queryTypePercentage !== undefined ? stats.queryTypePercentage + '%' : '---';
|
||||||
document.getElementById('top-query-type').textContent = queryType;
|
document.getElementById('top-query-type').textContent = queryType;
|
||||||
document.getElementById('query-type-percentage').textContent = queryPercent + '%';
|
document.getElementById('query-type-percentage').textContent = queryPercent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('active-ips')) {
|
if (document.getElementById('active-ips')) {
|
||||||
// 使用真实数据或模拟数据
|
// 直接使用API返回的活跃IP数
|
||||||
const activeIPs = stats.activeIPs !== undefined ? stats.activeIPs : 12;
|
const activeIPs = stats.activeIPs !== undefined ? formatNumber(stats.activeIPs) : '---';
|
||||||
const ipsPercent = stats.activeIPsPercent !== undefined ? stats.activeIPsPercent : 23;
|
const ipsPercent = stats.activeIPsPercent !== undefined ? stats.activeIPsPercent + '%' : '---';
|
||||||
document.getElementById('active-ips').textContent = formatNumber(activeIPs);
|
document.getElementById('active-ips').textContent = activeIPs;
|
||||||
document.getElementById('active-ips-percent').textContent = ipsPercent + '%';
|
document.getElementById('active-ips-percent').textContent = ipsPercent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('cpu-usage')) {
|
if (document.getElementById('cpu-usage')) {
|
||||||
// 使用真实数据或模拟数据
|
// 保留两位小数并添加单位
|
||||||
const cpuUsage = stats.cpuUsage !== undefined ? stats.cpuUsage : 45;
|
const cpuUsage = stats.cpuUsage ? stats.cpuUsage.toFixed(2) + '%' : '---';
|
||||||
document.getElementById('cpu-usage').textContent = cpuUsage + '%';
|
document.getElementById('cpu-usage').textContent = cpuUsage;
|
||||||
|
|
||||||
// 设置CPU状态颜色
|
// 设置CPU状态颜色
|
||||||
const cpuStatusElem = document.getElementById('cpu-status');
|
const cpuStatusElem = document.getElementById('cpu-status');
|
||||||
if (cpuStatusElem) {
|
if (cpuStatusElem) {
|
||||||
if (cpuUsage > 80) {
|
if (stats.cpuUsage !== undefined && stats.cpuUsage !== null) {
|
||||||
cpuStatusElem.textContent = '警告';
|
if (stats.cpuUsage > 80) {
|
||||||
cpuStatusElem.className = 'text-danger text-sm flex items-center';
|
cpuStatusElem.textContent = '警告';
|
||||||
} else if (cpuUsage > 60) {
|
cpuStatusElem.className = 'text-danger text-sm flex items-center';
|
||||||
cpuStatusElem.textContent = '较高';
|
} else if (stats.cpuUsage > 60) {
|
||||||
cpuStatusElem.className = 'text-warning text-sm flex items-center';
|
cpuStatusElem.textContent = '较高';
|
||||||
|
cpuStatusElem.className = 'text-warning text-sm flex items-center';
|
||||||
|
} else {
|
||||||
|
cpuStatusElem.textContent = '正常';
|
||||||
|
cpuStatusElem.className = 'text-success text-sm flex items-center';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cpuStatusElem.textContent = '正常';
|
// 无数据时显示---
|
||||||
cpuStatusElem.className = 'text-success text-sm flex items-center';
|
cpuStatusElem.textContent = '---';
|
||||||
|
cpuStatusElem.className = 'text-gray-400 text-sm flex items-center';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user