更新Swaggers API

This commit is contained in:
Alex Yang
2025-12-16 20:38:29 +08:00
parent c16e147931
commit b67a0fad8e
15 changed files with 10138 additions and 247 deletions

View File

@@ -33,6 +33,203 @@
}
],
"paths": {
"/login": {
"post": {
"summary": "用户登录",
"description": "使用用户名和密码登录DNS服务器API。",
"tags": ["auth"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"username": {"type": "string", "description": "用户名"},
"password": {"type": "string", "description": "密码"}
}
},
"example": {
"username": "admin",
"password": "admin"
}
}
}
},
"responses": {
"200": {
"description": "登录成功",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {
"status": "success",
"message": "登录成功"
}
}
}
},
"400": {
"description": "请求参数错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "无效的请求体"
}
}
}
},
"401": {
"description": "用户名或密码错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "用户名或密码错误"
}
}
}
}
}
}
},
"/logout": {
"post": {
"summary": "用户注销",
"description": "注销当前登录的用户会话。",
"tags": ["auth"],
"responses": {
"200": {
"description": "注销成功",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {
"status": "success",
"message": "注销成功"
}
}
}
}
}
}
},
"/change-password": {
"post": {
"summary": "修改密码",
"description": "修改当前登录用户的密码。",
"tags": ["auth"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"currentPassword": {"type": "string", "description": "当前密码"},
"newPassword": {"type": "string", "description": "新密码"}
}
},
"example": {
"currentPassword": "admin",
"newPassword": "newpassword"
}
}
}
},
"responses": {
"200": {
"description": "密码修改成功",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {
"status": "success",
"message": "密码修改成功"
}
}
}
},
"400": {
"description": "请求参数错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "无效的请求体"
}
}
}
},
"401": {
"description": "当前密码错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "当前密码错误"
}
}
}
},
"500": {
"description": "服务器内部错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {
"error": "保存密码失败"
}
}
}
}
}
}
},
"/stats": {
"get": {
"summary": "获取系统统计信息",
@@ -58,7 +255,11 @@
"TotalResponseTime": {"type": "number", "description": "总响应时间(毫秒)"},
"QueryTypes": {"type": "object", "description": "查询类型统计"},
"SourceIPs": {"type": "object", "description": "来源IP统计"},
"CpuUsage": {"type": "number", "description": "CPU使用率(百分比)"}
"CpuUsage": {"type": "number", "description": "CPU使用率(百分比)"},
"DNSSECQueries": {"type": "integer", "description": "DNSSEC查询次数"},
"DNSSECSuccess": {"type": "integer", "description": "DNSSEC成功次数"},
"DNSSECFailed": {"type": "integer", "description": "DNSSEC失败次数"},
"DNSSECEnabled": {"type": "boolean", "description": "是否启用DNSSEC"}
}
},
"shield": {"type": "object", "description": "Shield统计信息"},
@@ -66,6 +267,11 @@
"activeIPs": {"type": "integer", "description": "活跃IP数量"},
"avgResponseTime": {"type": "number", "description": "平均响应时间(毫秒)"},
"cpuUsage": {"type": "number", "description": "CPU使用率(百分比)"},
"dnssecEnabled": {"type": "boolean", "description": "是否启用DNSSEC"},
"dnssecQueries": {"type": "integer", "description": "DNSSEC查询次数"},
"dnssecSuccess": {"type": "integer", "description": "DNSSEC成功次数"},
"dnssecFailed": {"type": "integer", "description": "DNSSEC失败次数"},
"dnssecUsage": {"type": "number", "description": "DNSSEC使用率(百分比)"},
"time": {"type": "string", "description": "统计时间"}
}
},
@@ -82,13 +288,22 @@
"TotalResponseTime": 15625,
"QueryTypes": {"A": 850, "AAAA": 250, "CNAME": 150},
"SourceIPs": {"192.168.1.100": 500, "192.168.1.101": 750},
"CpuUsage": 0.15
"CpuUsage": 0.15,
"DNSSECQueries": 500,
"DNSSECSuccess": 480,
"DNSSECFailed": 20,
"DNSSECEnabled": true
},
"shield": {},
"topQueryType": "A",
"activeIPs": 2,
"avgResponseTime": 12.5,
"cpuUsage": 0.15,
"dnssecEnabled": true,
"dnssecQueries": 500,
"dnssecSuccess": 480,
"dnssecFailed": 20,
"dnssecUsage": 40.0,
"time": "2023-07-15T14:30:45Z"
}
}
@@ -274,20 +489,16 @@
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"hour": {"type": "string", "description": "小时"},
"queries": {"type": "integer", "description": "查询次数"},
"blocked": {"type": "integer", "description": "被阻止次数"}
}
"type": "object",
"properties": {
"labels": {"type": "array", "items": {"type": "string"}, "description": "小时标签"},
"data": {"type": "array", "items": {"type": "integer"}, "description": "查询次数数据"}
}
},
"example": [
{"hour": "00", "queries": 120, "blocked": 20},
{"hour": "01", "queries": 90, "blocked": 15}
]
"example": {
"labels": ["15:00", "16:00", "17:00"],
"data": [120, 90, 150]
}
}
}
}
@@ -305,20 +516,16 @@
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {"type": "string", "description": "日期"},
"queries": {"type": "integer", "description": "查询次数"},
"blocked": {"type": "integer", "description": "被阻止次数"}
}
"type": "object",
"properties": {
"labels": {"type": "array", "items": {"type": "string"}, "description": "日期标签"},
"data": {"type": "array", "items": {"type": "integer"}, "description": "查询次数数据"}
}
},
"example": [
{"date": "2023-07-09", "queries": 2500, "blocked": 450},
{"date": "2023-07-10", "queries": 2700, "blocked": 480}
]
"example": {
"labels": ["01-02", "01-03", "01-04"],
"data": [2500, 2700, 2300]
}
}
}
}
@@ -336,20 +543,16 @@
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {"type": "string", "description": "日期"},
"queries": {"type": "integer", "description": "查询次数"},
"blocked": {"type": "integer", "description": "被阻止次数"}
}
"type": "object",
"properties": {
"labels": {"type": "array", "items": {"type": "string"}, "description": "日期标签"},
"data": {"type": "array", "items": {"type": "integer"}, "description": "查询次数数据"}
}
},
"example": [
{"date": "2023-06-15", "queries": 2500, "blocked": 450},
{"date": "2023-06-16", "queries": 2700, "blocked": 480}
]
"example": {
"labels": ["01-01", "01-02", "01-03"],
"data": [2500, 2700, 2300]
}
}
}
}
@@ -387,30 +590,157 @@
}
}
},
"/shield": {
"/logs/stats": {
"get": {
"summary": "获取Shield配置",
"description": "获取Shield的完整配置信息包括启用状态、规则等。",
"tags": ["shield"],
"summary": "获取日志统计信息",
"description": "获取DNS查询日志的统计信息。",
"tags": ["logs"],
"responses": {
"200": {
"description": "成功获取配置信息",
"description": "成功获取日志统计信息",
"content": {
"application/json": {
"schema": {
"type": "object",
"description": "日志统计信息"}
}
}
}
}
}
},
"/logs/query": {
"get": {
"summary": "查询日志",
"description": "根据条件查询DNS查询日志。",
"tags": ["logs"],
"parameters": [
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"default": 100
},
"description": "返回结果数量限制"
},
{
"name": "offset",
"in": "query",
"schema": {
"type": "integer",
"default": 0
},
"description": "结果偏移量"
},
{
"name": "sort",
"in": "query",
"schema": {
"type": "string"
},
"description": "排序字段"
},
{
"name": "direction",
"in": "query",
"schema": {
"type": "string"
},
"description": "排序方向"
},
{
"name": "result",
"in": "query",
"schema": {
"type": "string"
},
"description": "查询结果过滤"
},
{
"name": "search",
"in": "query",
"schema": {
"type": "string"
},
"description": "搜索关键词"
}
],
"responses": {
"200": {
"description": "成功查询日志",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"description": "日志条目"
}
}
}
}
}
}
}
},
"/logs/count": {
"get": {
"summary": "获取日志总数",
"description": "获取DNS查询日志的总数。",
"tags": ["logs"],
"responses": {
"200": {
"description": "成功获取日志总数",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"enabled": {"type": "boolean", "description": "是否启用Shield"},
"rulesCount": {"type": "integer", "description": "规则数量"},
"lastUpdate": {"type": "string", "description": "最后更新时间"},
"blacklists": {"type": "array", "description": "黑名单列表", "items": {"type": "object"}}
"count": {"type": "integer", "description": "日志总数"}
}
},
"example": {
"enabled": true,
"rulesCount": 5000,
"lastUpdate": "2023-07-15T10:00:00Z",
"blacklists": []
"count": 1000
}
}
}
}
}
}
},
"/shield": {
"get": {
"summary": "获取Shield配置和统计信息",
"description": "获取Shield的配置信息和规则统计包括更新间隔、屏蔽方法、黑名单数量等。",
"tags": ["shield"],
"responses": {
"200": {
"description": "成功获取配置和统计信息",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"updateInterval": {"type": "integer", "description": "更新间隔(秒)"},
"blockMethod": {"type": "string", "description": "屏蔽方法"},
"blacklistCount": {"type": "integer", "description": "黑名单数量"},
"domainRulesCount": {"type": "integer", "description": "域名规则数量"},
"domainExceptionsCount": {"type": "integer", "description": "域名例外规则数量"},
"regexRulesCount": {"type": "integer", "description": "正则规则数量"},
"regexExceptionsCount": {"type": "integer", "description": "正则例外规则数量"},
"hostsRulesCount": {"type": "integer", "description": "Hosts规则数量"}
}
},
"example": {
"updateInterval": 3600,
"blockMethod": "NXDOMAIN",
"blacklistCount": 4,
"domainRulesCount": 1000,
"domainExceptionsCount": 100,
"regexRulesCount": 50,
"regexExceptionsCount": 10,
"hostsRulesCount": 200
}
}
}
@@ -432,8 +762,8 @@
}
},
"post": {
"summary": "更新Shield配置",
"description": "更新Shield的全局配置信息。",
"summary": "添加屏蔽规则",
"description": "添加新的屏蔽规则到Shield。",
"tags": ["shield"],
"requestBody": {
"required": true,
@@ -442,20 +772,18 @@
"schema": {
"type": "object",
"properties": {
"enabled": {"type": "boolean", "description": "是否启用Shield"},
"updateInterval": {"type": "integer", "description": "更新间隔(秒)"}
"rule": {"type": "string", "description": "屏蔽规则"}
}
},
"example": {
"enabled": true,
"updateInterval": 3600
"rule": "example.com"
}
}
}
},
"responses": {
"200": {
"description": "成功更新配置",
"description": "成功添加规则",
"content": {
"application/json": {
"schema": {
@@ -492,19 +820,35 @@
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {"error": "更新配置失败"}
"example": {"error": "添加规则失败"}
}
}
}
}
},
"put": {
"summary": "重启Shield",
"description": "重新加载和应用Shield规则。",
"delete": {
"summary": "删除屏蔽规则",
"description": "从Shield中删除指定的屏蔽规则。",
"tags": ["shield"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"rule": {"type": "string", "description": "要删除的屏蔽规则"}
}
},
"example": {
"rule": "example.com"
}
}
}
},
"responses": {
"200": {
"description": "成功重启Shield",
"description": "成功删除规则",
"content": {
"application/json": {
"schema": {
@@ -517,6 +861,20 @@
}
}
},
"400": {
"description": "请求参数错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {"error": "参数格式错误"}
}
}
},
"500": {
"description": "服务器内部错误",
"content": {
@@ -527,7 +885,46 @@
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {"error": "重启失败"}
"example": {"error": "删除规则失败"}
}
}
}
}
},
"put": {
"summary": "重新加载规则",
"description": "重新加载和应用Shield规则。",
"tags": ["shield"],
"responses": {
"200": {
"description": "成功重新加载规则",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {
"status": "success",
"message": "规则重新加载成功"
}
}
}
},
"500": {
"description": "服务器内部错误",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {"error": "重新加载规则失败"}
}
}
}
@@ -1139,7 +1536,7 @@
"/status": {
"get": {
"summary": "获取服务器状态",
"description": "获取DNS服务器的状态信息。",
"description": "获取DNS服务器的状态信息,包括查询统计、运行时间等。",
"tags": ["server"],
"responses": {
"200": {
@@ -1150,14 +1547,32 @@
"type": "object",
"properties": {
"status": {"type": "string", "description": "服务器状态"},
"uptime": {"type": "integer", "description": "运行时间(秒)"},
"version": {"type": "string", "description": "服务器版本"}
"queries": {"type": "integer", "description": "总查询次数"},
"blocked": {"type": "integer", "description": "被阻止的查询次数"},
"allowed": {"type": "integer", "description": "允许的查询次数"},
"errors": {"type": "integer", "description": "错误查询次数"},
"lastQuery": {"type": "string", "description": "最近一次查询时间"},
"avgResponseTime": {"type": "number", "description": "平均响应时间(毫秒)"},
"activeIPs": {"type": "integer", "description": "活跃IP数量"},
"startTime": {"type": "string", "description": "服务器启动时间"},
"uptime": {"type": "integer", "description": "运行时间(毫秒)"},
"cpuUsage": {"type": "number", "description": "CPU使用率(百分比)"},
"timestamp": {"type": "string", "description": "当前时间"}
}
},
"example": {
"status": "running",
"uptime": 3600,
"version": "1.0.0"
"queries": 1250,
"blocked": 230,
"allowed": 1020,
"errors": 0,
"lastQuery": "2023-07-15T14:30:45Z",
"avgResponseTime": 12.5,
"activeIPs": 2,
"startTime": "2023-07-15T10:00:00Z",
"uptime": 16200000,
"cpuUsage": 0.15,
"timestamp": "2023-07-15T14:30:45Z"
}
}
}
@@ -1168,7 +1583,7 @@
"/config": {
"get": {
"summary": "获取服务器配置",
"description": "获取DNS服务器的配置信息。",
"description": "获取DNS服务器的配置信息包括Shield配置。",
"tags": ["server"],
"responses": {
"200": {
@@ -1178,13 +1593,30 @@
"schema": {
"type": "object",
"properties": {
"port": {"type": "integer", "description": "服务器端口"},
"logLevel": {"type": "string", "description": "日志级别"}
"shield": {
"type": "object",
"properties": {
"blockMethod": {"type": "string", "description": "屏蔽方法"},
"customBlockIP": {"type": "string", "description": "自定义屏蔽IP"},
"blacklists": {"type": "array", "description": "黑名单列表", "items": {"type": "object"}},
"updateInterval": {"type": "integer", "description": "更新间隔(秒)"}
}
}
}
},
"example": {
"port": 53,
"logLevel": "info"
"shield": {
"blockMethod": "NXDOMAIN",
"customBlockIP": "",
"blacklists": [
{
"name": "AdGuard DNS filter",
"url": "https://example.com/ads.txt",
"enabled": true
}
],
"updateInterval": 3600
}
}
}
}
@@ -1193,7 +1625,7 @@
},
"post": {
"summary": "更新服务器配置",
"description": "更新DNS服务器的配置信息。",
"description": "更新DNS服务器的配置信息包括Shield配置。",
"tags": ["server"],
"requestBody": {
"required": true,
@@ -1202,13 +1634,30 @@
"schema": {
"type": "object",
"properties": {
"port": {"type": "integer", "description": "服务器端口"},
"logLevel": {"type": "string", "description": "日志级别"}
"shield": {
"type": "object",
"properties": {
"blockMethod": {"type": "string", "description": "屏蔽方法"},
"customBlockIP": {"type": "string", "description": "自定义屏蔽IP"},
"blacklists": {"type": "array", "description": "黑名单列表", "items": {"type": "object"}},
"updateInterval": {"type": "integer", "description": "更新间隔(秒)"}
}
}
}
},
"example": {
"port": 53,
"logLevel": "info"
"shield": {
"blockMethod": "NXDOMAIN",
"customBlockIP": "",
"blacklists": [
{
"name": "AdGuard DNS filter",
"url": "https://example.com/ads.txt",
"enabled": true
}
],
"updateInterval": 3600
}
}
}
}
@@ -1221,10 +1670,14 @@
"schema": {
"type": "object",
"properties": {
"status": {"type": "string", "description": "操作状态"}
"success": {"type": "boolean", "description": "是否成功"},
"message": {"type": "string", "description": "操作信息"}
}
},
"example": {"status": "success"}
"example": {
"success": true,
"message": "配置已更新"
}
}
}
},
@@ -1238,7 +1691,9 @@
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {"error": "参数格式错误"}
"example": {
"error": "无效的请求体"
}
}
}
},
@@ -1252,7 +1707,9 @@
"error": {"type": "string", "description": "错误信息"}
}
},
"example": {"error": "更新配置失败"}
"example": {
"error": "保存配置失败"
}
}
}
}
@@ -1298,6 +1755,10 @@
}
},
"tags": [
{
"name": "auth",
"description": "认证相关API"
},
{
"name": "stats",
"description": "统计相关API"
@@ -1309,6 +1770,10 @@
{
"name": "server",
"description": "服务器相关API"
},
{
"name": "logs",
"description": "日志相关API"
}
]
};

View File

@@ -334,6 +334,42 @@
</div>
</div>
<!-- DNSSEC使用率卡片 -->
<div class="bg-white rounded-lg p-4 card-shadow relative overflow-hidden">
<!-- 颜色蒙版 -->
<div class="absolute -bottom-8 -right-8 w-24 h-24 rounded-full bg-primary opacity-10"></div>
<div class="relative z-10">
<div class="flex items-center justify-between mb-4">
<h3 class="text-gray-500 font-medium">DNSSEC使用率</h3>
<div class="p-2 rounded-full bg-primary/10 text-primary">
<i class="fa fa-lock"></i>
</div>
</div>
<div class="mb-2">
<div class="flex items-end justify-between">
<p class="text-3xl font-bold" id="dnssec-usage">0%</p>
<span class="text-primary text-sm flex items-center">
<i class="fa fa-check mr-1"></i>
<span id="dnssec-status">已禁用</span>
</span>
</div>
</div>
<div class="flex items-center space-x-4 text-xs text-gray-500">
<div class="flex items-center">
<span class="w-2 h-2 bg-green-500 rounded-full mr-1"></span>
<span>成功: <span id="dnssec-success">0</span></span>
</div>
<div class="flex items-center">
<span class="w-2 h-2 bg-red-500 rounded-full mr-1"></span>
<span>失败: <span id="dnssec-failed">0</span></span>
</div>
<div class="flex items-center">
<span class="w-2 h-2 bg-blue-500 rounded-full mr-1"></span>
<span>总查询: <span id="dnssec-queries">0</span></span>
</div>
</div>
</div>
</div>
</div>

View File

@@ -12,6 +12,12 @@ let dashboardWsReconnectTimer = null;
let statCardCharts = {};
// 存储统计卡片历史数据
let statCardHistoryData = {};
// 存储仪表盘历史数据,用于计算趋势
window.dashboardHistoryData = window.dashboardHistoryData || {
prevResponseTime: null,
prevActiveIPs: null,
prevTopQueryTypeCount: null
};
// 引入颜色配置文件
const COLOR_CONFIG = window.COLOR_CONFIG || {};
@@ -192,14 +198,42 @@ function processRealTimeData(stats) {
if (document.getElementById('top-query-type')) {
const queryType = stats.topQueryType || '---';
document.getElementById('top-query-type').textContent = queryType;
const queryPercentElem = document.getElementById('query-type-percentage');
if (queryPercentElem) {
queryPercentElem.textContent = '• ---';
queryPercentElem.className = 'text-sm flex items-center text-gray-500';
// 计算查询类型趋势
let queryPercent = '---';
let trendClass = 'text-gray-400';
let trendIcon = '---';
if (stats.topQueryTypeCount !== undefined && stats.topQueryTypeCount !== null) {
// 存储当前值用于下次计算趋势
const prevTopQueryTypeCount = window.dashboardHistoryData.prevTopQueryTypeCount || stats.topQueryTypeCount;
window.dashboardHistoryData.prevTopQueryTypeCount = stats.topQueryTypeCount;
// 计算变化百分比
if (prevTopQueryTypeCount > 0) {
const changePercent = ((stats.topQueryTypeCount - prevTopQueryTypeCount) / prevTopQueryTypeCount) * 100;
queryPercent = Math.abs(changePercent).toFixed(1) + '%';
// 设置趋势图标和颜色
if (changePercent > 0) {
trendIcon = '↑';
trendClass = 'text-primary';
} else if (changePercent < 0) {
trendIcon = '↓';
trendClass = 'text-secondary';
} else {
trendIcon = '•';
trendClass = 'text-gray-500';
}
}
}
queryPercentElem.textContent = trendIcon + ' ' + queryPercent;
queryPercentElem.className = `text-sm flex items-center ${trendClass}`;
}
document.getElementById('top-query-type').textContent = queryType;
}
if (document.getElementById('active-ips')) {
@@ -984,6 +1018,60 @@ function updateStatsCards(stats) {
animateValue('error-queries', errorQueries);
animateValue('active-ips', activeIPs);
// DNSSEC相关数据
let dnssecEnabled = false, dnssecQueries = 0, dnssecSuccess = 0, dnssecFailed = 0, dnssecUsage = 0;
// 检查DNSSEC数据
if (stats) {
// 优先使用顶层字段
dnssecEnabled = stats.dnssecEnabled || false;
dnssecQueries = stats.dnssecQueries || 0;
dnssecSuccess = stats.dnssecSuccess || 0;
dnssecFailed = stats.dnssecFailed || 0;
dnssecUsage = stats.dnssecUsage || 0;
// 如果dns对象存在优先使用其中的数据
if (stats.dns) {
dnssecEnabled = stats.dns.DNSSECEnabled || dnssecEnabled;
dnssecQueries = stats.dns.DNSSECQueries || dnssecQueries;
dnssecSuccess = stats.dns.DNSSECSuccess || dnssecSuccess;
dnssecFailed = stats.dns.DNSSECFailed || dnssecFailed;
}
// 如果没有直接提供使用率,计算使用率
if (dnssecUsage === 0 && totalQueries > 0) {
dnssecUsage = (dnssecQueries / totalQueries) * 100;
}
}
// 更新DNSSEC统计卡片
const dnssecUsageElement = document.getElementById('dnssec-usage');
const dnssecStatusElement = document.getElementById('dnssec-status');
const dnssecSuccessElement = document.getElementById('dnssec-success');
const dnssecFailedElement = document.getElementById('dnssec-failed');
const dnssecQueriesElement = document.getElementById('dnssec-queries');
if (dnssecUsageElement) {
dnssecUsageElement.textContent = `${Math.round(dnssecUsage)}%`;
}
if (dnssecStatusElement) {
dnssecStatusElement.textContent = dnssecEnabled ? '已启用' : '已禁用';
dnssecStatusElement.className = `text-sm flex items-center ${dnssecEnabled ? 'text-success' : 'text-danger'}`;
}
if (dnssecSuccessElement) {
dnssecSuccessElement.textContent = formatNumber(dnssecSuccess);
}
if (dnssecFailedElement) {
dnssecFailedElement.textContent = formatNumber(dnssecFailed);
}
if (dnssecQueriesElement) {
dnssecQueriesElement.textContent = formatNumber(dnssecQueries);
}
// 直接更新文本和百分比,移除动画效果
const topQueryTypeElement = document.getElementById('top-query-type');
const queryTypePercentageElement = document.getElementById('query-type-percentage');
@@ -1223,7 +1311,7 @@ function updateTopDomainsTable(domains) {
<div class="flex-1 min-w-0">
<div class="flex items-center">
<span class="w-6 h-6 flex items-center justify-center rounded-full bg-success/10 text-success text-xs font-medium mr-3">${i + 1}</span>
<span class="font-medium truncate">${domain.name}</span>
<span class="font-medium truncate">${domain.name}${domain.dnssec ? ' <i class="fa fa-lock text-green-500"></i>' : ''}</span>
</div>
</div>
<span class="ml-4 flex-shrink-0 font-semibold text-success">${formatNumber(domain.count)}</span>

View File

@@ -399,7 +399,7 @@ function updateLogsTable(logs) {
</td>
<td class="py-3 px-4 text-sm">
<div class="font-medium">${log.Domain}</div>
<div class="text-xs text-gray-500 mt-1">类型: ${log.QueryType}, <span class="${statusClass}">${statusText}</span>, <span class="${cacheStatusClass}">${log.FromCache ? '缓存' : '实时'}</span></div>
<div class="text-xs text-gray-500 mt-1">类型: ${log.QueryType}, <span class="${statusClass}">${statusText}</span>, <span class="${cacheStatusClass}">${log.FromCache ? '缓存' : '实时'}</span>${log.DNSSEC ? ', <span class="text-green-500"><i class="fa fa-lock"></i> DNSSEC</span>' : ''}${log.EDNS ? ', <span class="text-blue-500"><i class="fa fa-exchange"></i> EDNS</span>' : ''}</div>
</td>
<td class="py-3 px-4 text-sm">${log.ResponseTime}ms</td>
<td class="py-3 px-4 text-sm text-gray-500">${log.BlockRule || '-'}</td>