diff --git a/luci-app-mosdns/Makefile b/luci-app-mosdns/Makefile index c09b8afad..b3be1173c 100644 --- a/luci-app-mosdns/Makefile +++ b/luci-app-mosdns/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-mosdns PKG_VERSION:=1.7.14 -PKG_RELEASE:=23 +PKG_RELEASE:=24 LUCI_TITLE:=LuCI Support for mosdns LUCI_PKGARCH:=all diff --git a/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js index af115c9f6..0f0895d7f 100644 --- a/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js +++ b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js @@ -160,8 +160,18 @@ const injectStyles = () => { '.btn-allow:hover { background: #059669 !important; color: #fff !important; }', '.btn-block { background: rgba(239, 68, 68, 0.12) !important; color: #dc2626 !important; border: 1px solid rgba(239, 68, 68, 0.3) !important; }', '.btn-block:hover { background: #dc2626 !important; color: #fff !important; }', + '.mosdns-pagination-bar { display: flex !important; justify-content: space-between !important; align-items: center !important; margin-top: 0.5rem !important; padding: 0.75rem 0.5rem 0.25rem 0.5rem !important; border-top: 1px solid var(--border-color-medium, rgba(125,125,125,0.15)) !important; flex-wrap: wrap !important; gap: 0.5rem !important; box-sizing: border-box !important; width: 100% !important; }', + '.mosdns-pagination-bar::after, .mosdns-pagination-bar::before { display: none !important; content: none !important; }', + '.mosdns-pagination-info { display: inline-flex !important; align-items: center !important; font-size: 0.85rem !important; opacity: 0.85 !important; }', + '.mosdns-pagination-btns { display: flex !important; gap: 0.5rem !important; margin-left: auto !important; }', + '.mosdns-page-input { height: 24px !important; line-height: 22px !important; text-align: center !important; font-size: 0.82rem !important; font-weight: 600 !important; padding: 0 4px !important; margin: 0 4px !important; border: 1px solid rgba(125,125,125,0.3) !important; border-radius: 4px !important; background: var(--cbi-section-bg, #fff) !important; color: inherit !important; display: inline-block !important; vertical-align: middle !important; box-sizing: border-box !important; transition: all 0.2s ease !important; }', + '.mosdns-page-input:focus { border-color: #3b82f6 !important; box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25) !important; outline: none !important; }', + '.mosdns-page-input::-webkit-outer-spin-button, .mosdns-page-input::-webkit-inner-spin-button { -webkit-appearance: none !important; margin: 0 !important; }', + '.mosdns-page-input[type=number] { -moz-appearance: textfield !important; }', '@keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }', '@media (prefers-color-scheme: dark) {', + ' .mosdns-pagination-bar { border-top-color: rgba(255,255,255,0.08) !important; }', + ' .mosdns-page-input { background: rgba(255,255,255,0.06) !important; border-color: rgba(255,255,255,0.18) !important; color: #fff !important; }', ' .mosdns-stat-card, .mosdns-rank-panel, .mosdns-modal-meta-item, .mosdns-answer-row { background: rgba(255,255,255,0.03); border-color: rgba(255,255,255,0.08); box-shadow: none; }', ' .mosdns-sparkline-tooltip { background: #1e242b; border-color: rgba(255,255,255,0.15); box-shadow: 0 4px 12px rgba(0,0,0,0.5); }', ' .mosdns-log-row:hover { background: rgba(255,255,255,0.04); }', @@ -864,7 +874,7 @@ const renderLogsTable = logsData => { E('td', { class: 'td col-time', style: 'font-size: 0.82rem; opacity: 0.7; white-space: nowrap;' }, formatTimestamp(item.timestamp)), E('td', { class: 'td col-client mosdns-mono', - style: 'font-size: 0.82rem; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;', + style: 'font-size: 0.82rem; max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;', title: clientInfo.title }, clientInfo.display), E('td', { class: 'td col-domain', style: 'max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;', title: item.domain || '-' }, [ @@ -887,47 +897,99 @@ const renderLogsTable = logsData => { ])); } - return E('div', {}, [ - E('table', { class: 'table cbi-section-table mosdns-table', style: 'margin-top: 0.25rem;' }, [ - E('tr', { class: 'tr table-titles' }, [ - E('th', { class: 'th col-time', style: 'width: 85px;' }, _('Time')), - E('th', { class: 'th col-client', style: 'width: 125px;' }, _('Client IP')), - E('th', { class: 'th col-domain' }, _('Domain & Record')), - E('th', { class: 'th col-status', style: 'width: 90px;' }, _('Status')), - E('th', { class: 'th col-answers' }, _('Answers')), - E('th', { class: 'th col-latency', style: 'width: 80px; text-align: right;' }, _('Elapsed')) - ]), - ...rows - ]), + const inputWidth = Math.max(46, (String(totalPages).length * 8 + 18)) + 'px'; + const pageInput = E('input', { + type: 'number', + class: 'cbi-input-text mosdns-page-input', + min: 1, + max: totalPages, + value: pageIdx + 1, + style: `width: ${inputWidth};`, + title: _('Enter page number and press Enter to jump') + }); - E('div', { style: 'display: flex; justify-content: space-between; align-items: center; margin-top: 0.75rem;' }, [ - E('span', { style: 'font-size: 0.85rem; opacity: 0.7;' }, _('Page %d / %d (%d entries)').format(pageIdx + 1, totalPages, total)), - E('div', { style: 'display: flex; gap: 0.5rem;' }, [ - E('button', { - class: 'btn cbi-button cbi-button-action', - disabled: pageIdx === 0 ? 'disabled' : null, - click: () => { - if (pageIdx > 0) { - pageIdx--; - updateLiveStatusBadge(); - refreshLogs(); + const doJump = () => { + const val = parseInt(pageInput.value, 10); + if (isNaN(val)) { + pageInput.value = pageIdx + 1; + return; + } + const targetPage = Math.max(1, Math.min(totalPages, val)); + pageInput.value = targetPage; + if (targetPage - 1 !== pageIdx) { + pageIdx = targetPage - 1; + updateLiveStatusBadge(); + refreshLogs(); + } + }; + + pageInput.addEventListener('keydown', ev => { + if (ev.key === 'Enter') { + ev.preventDefault(); + pageInput.blur(); + } + }); + + pageInput.addEventListener('focus', () => { + pageInput.select(); + }); + + pageInput.addEventListener('blur', () => { + doJump(); + }); + + const pageParts = _('Page %d / %d (%d entries)').format(999999, totalPages, total).split('999999'); + const paginationLabel = E('div', { + class: 'mosdns-pagination-info' + }, [ + pageParts[0] || '', + pageInput, + pageParts[1] || '' + ]); + + return E('div', {}, [ + E('table', { class: 'table cbi-section-table mosdns-table', style: 'margin-top: 0.25rem; margin-bottom: 0;' }, [ + E('tr', { class: 'tr table-titles' }, [ + E('th', { class: 'th col-time', style: 'width: 85px;' }, _('Time')), + E('th', { class: 'th col-client', style: 'width: 125px;' }, _('Client IP')), + E('th', { class: 'th col-domain' }, _('Domain & Record')), + E('th', { class: 'th col-status', style: 'width: 90px;' }, _('Status')), + E('th', { class: 'th col-answers' }, _('Answers')), + E('th', { class: 'th col-latency', style: 'width: 95px; text-align: right;' }, _('Elapsed')) + ]), + ...rows + ]), + + E('div', { + class: 'mosdns-pagination-bar' + }, [ + paginationLabel, + E('div', { class: 'mosdns-pagination-btns' }, [ + E('button', { + class: 'btn cbi-button cbi-button-action', + disabled: pageIdx === 0 ? 'disabled' : null, + click: () => { + if (pageIdx > 0) { + pageIdx--; + updateLiveStatusBadge(); + refreshLogs(); + } } - } - }, _('Previous')), - E('button', { - class: 'btn cbi-button cbi-button-action', - disabled: (pageIdx + 1) >= totalPages ? 'disabled' : null, - click: () => { - if ((pageIdx + 1) < totalPages) { - pageIdx++; - updateLiveStatusBadge(); - refreshLogs(); + }, _('Previous')), + E('button', { + class: 'btn cbi-button cbi-button-action', + disabled: (pageIdx + 1) >= totalPages ? 'disabled' : null, + click: () => { + if ((pageIdx + 1) < totalPages) { + pageIdx++; + updateLiveStatusBadge(); + refreshLogs(); + } } - } - }, _('Next')) + }, _('Next')) + ]) ]) - ]) - ]); + ]); }; const pollScheduler = async () => { diff --git a/luci-app-mosdns/po/templates/mosdns.pot b/luci-app-mosdns/po/templates/mosdns.pot index 2f3541862..8dca73187 100644 --- a/luci-app-mosdns/po/templates/mosdns.pot +++ b/luci-app-mosdns/po/templates/mosdns.pot @@ -17,19 +17,19 @@ msgstr "" msgid "API Options" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:718 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:728 msgid "Add domain to the blocklist to block DNS resolution:" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:717 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:727 msgid "Add domain to the whitelist to permit DNS resolution:" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:710 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:720 msgid "Add to Blocklist" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:710 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:720 msgid "Add to Whitelist" msgstr "" @@ -90,7 +90,7 @@ msgstr "" msgid "Aliyun Public DNS (DNS over QUIC)" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1026 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1088 msgid "All Queries" msgstr "" @@ -99,8 +99,8 @@ msgstr "" msgid "Another update is already in progress." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:805 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:897 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:815 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:957 msgid "Answers" msgstr "" @@ -108,7 +108,7 @@ msgstr "" msgid "Apple domains optimization" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1053 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1115 msgid "" "Are you sure you want to clear all real-time query logs and top rankings?" msgstr "" @@ -127,11 +127,11 @@ msgid "" "rules through scheduled tasks." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:478 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:488 msgid "Average Processing Time" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:538 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:548 msgid "Avg Processing" msgstr "" @@ -155,8 +155,8 @@ msgid "" msgstr "" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/rules.js:31 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:633 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:635 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:643 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:645 msgid "Block Lists" msgstr "" @@ -164,11 +164,11 @@ msgstr "" msgid "Block PTR" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1027 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1089 msgid "Blocked Only" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:456 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:466 msgid "Blocked by Filters" msgstr "" @@ -190,16 +190,16 @@ msgstr "" msgid "Cache Prefetching" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1028 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1090 msgid "Cached Only" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:467 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:477 msgid "Cached Queries" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:730 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1058 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:740 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1120 msgid "Cancel" msgstr "" @@ -229,7 +229,7 @@ msgstr "" msgid "Cisco Public DNS (208.67.222.222)" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1078 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1140 msgid "Clear" msgstr "" @@ -237,22 +237,22 @@ msgstr "" msgid "Clear logs" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1049 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1052 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1111 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1114 msgid "Clear query logs" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:861 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:878 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:871 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:888 msgid "Click to view full details" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:787 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:894 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:797 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:954 msgid "Client IP" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:832 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:842 #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/update.js:35 msgid "Close" msgstr "" @@ -292,7 +292,7 @@ msgstr "" msgid "Configuration Editor" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:734 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:744 msgid "Confirm" msgstr "" @@ -330,7 +330,7 @@ msgstr "" msgid "DNS Forward" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:444 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:454 msgid "DNS Queries Total" msgstr "" @@ -374,20 +374,20 @@ msgstr "" msgid "DoH/TCP/DoT Connection Multiplexing idle timeout (default 30 seconds)" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:895 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:955 msgid "Domain & Record" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:627 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:655 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:637 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:665 msgid "Domain name cannot be empty." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:720 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:730 msgid "Domain:" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:898 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:958 msgid "Elapsed" msgstr "" @@ -425,6 +425,10 @@ msgstr "" msgid "Enabled" msgstr "" +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:908 +msgid "Enter page number and press Enter to jump" +msgstr "" + #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:505 msgid "Enter the GeoIP.dat category to be exported, Allow add multiple tags" msgstr "" @@ -478,7 +482,7 @@ msgstr "" msgid "Failed to clean logs." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1072 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1134 msgid "Failed to clear query logs:" msgstr "" @@ -486,15 +490,15 @@ msgstr "" msgid "Failed to start update." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:970 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1032 msgid "Failed to update query logs:" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:699 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:709 msgid "Failed to update rule file: %s" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1044 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1106 msgid "First Page / Resume" msgstr "" @@ -595,10 +599,10 @@ msgstr "" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:410 msgid "" -"IPv4 CIDR: https://www.cloudflare.com/ips-v4
IPv6 CIDR: https://www." -"cloudflare.com/ips-v6" +"IPv4 CIDR: https://www.cloudflare.com/ips-v4
IPv6 CIDR: https://www.cloudflare.com/ips-" +"v6" msgstr "" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:190 @@ -621,7 +625,7 @@ msgstr "" msgid "Info" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:828 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:838 msgid "Intercept" msgstr "" @@ -631,7 +635,7 @@ msgid "" "seconds)." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:479 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:489 msgid "Latency" msgstr "" @@ -716,12 +720,12 @@ msgstr "" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:33 #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:106 #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/logs.js:70 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1094 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1156 #: luci-app-mosdns/root/usr/share/luci/menu.d/luci-app-mosdns.json:3 msgid "MosDNS" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:510 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:520 msgid "" "MosDNS API is unreachable. Please ensure MosDNS is running and stats_api " "plugin is enabled." @@ -739,15 +743,15 @@ msgstr "" msgid "Netflix, Disney+, Hulu and streaming media rules list will use this DNS" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:927 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:989 msgid "Next" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:768 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:778 msgid "No DNS answer records returned." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:560 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:570 msgid "No data available" msgstr "" @@ -755,19 +759,19 @@ msgstr "" msgid "No log data." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:886 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:896 msgid "No query log entries found." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:904 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:941 msgid "Page %d / %d (%d entries)" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:438 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:448 msgid "Per-query speed" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:821 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:831 msgid "Permit" msgstr "" @@ -802,7 +806,7 @@ msgstr "" msgid "Prevent DNS Leaks" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:916 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:978 msgid "Previous" msgstr "" @@ -821,7 +825,7 @@ msgstr "" msgid "Quad9 Public DNS (9.9.9.9)" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:811 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:821 msgid "Query Log Details" msgstr "" @@ -831,7 +835,7 @@ msgid "" "consume more memory)" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1067 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1129 msgid "Query logs cleared successfully." msgstr "" @@ -839,7 +843,7 @@ msgstr "" msgid "RUNNING" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1098 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1160 msgid "Real-time Query Logs" msgstr "" @@ -869,7 +873,7 @@ msgstr "" msgid "Ring Buffer Capacity" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:799 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:809 msgid "Rule Hit" msgstr "" @@ -889,7 +893,7 @@ msgstr "" msgid "Save the cache locally and reload the cache dump on the next startup" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1015 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1077 msgid "Search domain or client IP..." msgstr "" @@ -901,7 +905,7 @@ msgstr "" msgid "Starting update..." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1094 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1156 #: luci-app-mosdns/root/usr/share/luci/menu.d/luci-app-mosdns.json:38 msgid "Statistics" msgstr "" @@ -910,7 +914,7 @@ msgstr "" msgid "Stats Dump" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:896 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:956 msgid "Status" msgstr "" @@ -930,7 +934,7 @@ msgstr "" msgid "TCP/DoT Connection Multiplexing" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:723 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:733 msgid "Target file: %s (supports domain matching rules)" msgstr "" @@ -966,20 +970,20 @@ msgid "" "content in yaml format." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:791 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:893 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:801 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:953 msgid "Time" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:599 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:609 msgid "Top Blocked Domains" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:606 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:616 msgid "Top Clients" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:592 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:602 msgid "Top Queried Domains" msgstr "" @@ -1029,7 +1033,7 @@ msgstr "" msgid "Updating Database..." msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:795 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:805 msgid "Upstream" msgstr "" @@ -1051,8 +1055,8 @@ msgid "" msgstr "" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/rules.js:23 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:633 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:635 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:643 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:645 msgid "White Lists" msgstr "" @@ -1070,15 +1074,15 @@ msgstr "" msgid "https://gh-proxy.com" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:427 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:540 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:437 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:550 msgid "● Live" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:223 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:233 msgid "● Live Auto-refresh" msgstr "" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:227 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:237 msgid "❚❚ Paused (Page %d)" msgstr "" diff --git a/luci-app-mosdns/po/zh_Hans/mosdns.po b/luci-app-mosdns/po/zh_Hans/mosdns.po index cf02030da..e81e9e87a 100644 --- a/luci-app-mosdns/po/zh_Hans/mosdns.po +++ b/luci-app-mosdns/po/zh_Hans/mosdns.po @@ -27,19 +27,19 @@ msgstr "API 监听端口" msgid "API Options" msgstr "API 选项" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:718 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:728 msgid "Add domain to the blocklist to block DNS resolution:" msgstr "将域名添加到黑名单以拦截 DNS 解析:" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:717 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:727 msgid "Add domain to the whitelist to permit DNS resolution:" msgstr "将域名添加到白名单以放行 DNS 解析:" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:710 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:720 msgid "Add to Blocklist" msgstr "添加到黑名单" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:710 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:720 msgid "Add to Whitelist" msgstr "添加到白名单" @@ -105,7 +105,7 @@ msgstr "阿里云公共 DNS(DNS over HTTPS)" msgid "Aliyun Public DNS (DNS over QUIC)" msgstr "阿里云公共 DNS(DNS over QUIC)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1026 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1088 msgid "All Queries" msgstr "所有查询" @@ -114,8 +114,8 @@ msgstr "所有查询" msgid "Another update is already in progress." msgstr "另一个更新正在进行中。" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:805 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:897 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:815 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:957 msgid "Answers" msgstr "应答结果" @@ -123,7 +123,7 @@ msgstr "应答结果" msgid "Apple domains optimization" msgstr "Apple 域名解析优化" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1053 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1115 msgid "" "Are you sure you want to clear all real-time query logs and top rankings?" msgstr "确定要清空所有实时查询日志和排行数据吗?" @@ -142,11 +142,11 @@ msgid "" "rules through scheduled tasks." msgstr "通过定时任务自动更新 GeoIP 和 GeoSite 数据库以及广告过滤规则。" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:478 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:488 msgid "Average Processing Time" msgstr "平均延迟" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:538 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:548 msgid "Avg Processing" msgstr "平均处理" @@ -172,8 +172,8 @@ msgstr "" "解析。" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/rules.js:31 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:633 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:635 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:643 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:645 msgid "Block Lists" msgstr "黑名单" @@ -181,11 +181,11 @@ msgstr "黑名单" msgid "Block PTR" msgstr "PTR 黑名单" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1027 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1089 msgid "Blocked Only" msgstr "仅拦截" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:456 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:466 msgid "Blocked by Filters" msgstr "拦截总数" @@ -207,16 +207,16 @@ msgstr "自动保存缓存" msgid "Cache Prefetching" msgstr "缓存预取" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1028 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1090 msgid "Cached Only" msgstr "仅缓存" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:467 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:477 msgid "Cached Queries" msgstr "缓存命中" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:730 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1058 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:740 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1120 msgid "Cancel" msgstr "取消" @@ -246,7 +246,7 @@ msgstr "思科公共 DNS(208.67.220.220)" msgid "Cisco Public DNS (208.67.222.222)" msgstr "思科公共 DNS(208.67.222.222)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1078 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1140 msgid "Clear" msgstr "清空" @@ -254,22 +254,22 @@ msgstr "清空" msgid "Clear logs" msgstr "清空日志" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1049 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1052 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1111 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1114 msgid "Clear query logs" msgstr "清除查询日志" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:861 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:878 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:871 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:888 msgid "Click to view full details" msgstr "点击查看完整详情" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:787 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:894 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:797 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:954 msgid "Client IP" msgstr "客户端 IP" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:832 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:842 #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/update.js:35 msgid "Close" msgstr "关闭" @@ -309,7 +309,7 @@ msgstr "配置文件" msgid "Configuration Editor" msgstr "配置编辑器" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:734 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:744 msgid "Confirm" msgstr "确认" @@ -348,7 +348,7 @@ msgstr "DNS 缓存大小" msgid "DNS Forward" msgstr "DNS 转发" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:444 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:454 msgid "DNS Queries Total" msgstr "DNS 查询总数" @@ -393,20 +393,20 @@ msgstr "" msgid "DoH/TCP/DoT Connection Multiplexing idle timeout (default 30 seconds)" msgstr "DoH/TCP/DoT 连接复用空闲保持时间(默认 30 秒)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:895 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:955 msgid "Domain & Record" msgstr "域名与类型" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:627 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:655 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:637 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:665 msgid "Domain name cannot be empty." msgstr "域名不能为空" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:720 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:730 msgid "Domain:" msgstr "域名:" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:898 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:958 msgid "Elapsed" msgstr "耗时" @@ -444,6 +444,10 @@ msgstr "启用此选项 fallback 策略会强制转发到远程 DNS" msgid "Enabled" msgstr "启用" +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:908 +msgid "Enter page number and press Enter to jump" +msgstr "输入页码并按回车跳转" + #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:505 msgid "Enter the GeoIP.dat category to be exported, Allow add multiple tags" msgstr "输入需要导出的 GeoIP.dat 类别条目,允许添加多个标签" @@ -497,7 +501,7 @@ msgstr "导出目录:/var/mosdns" msgid "Failed to clean logs." msgstr "清理日志失败:%s" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1072 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1134 msgid "Failed to clear query logs:" msgstr "清除查询日志失败:" @@ -505,15 +509,15 @@ msgstr "清除查询日志失败:" msgid "Failed to start update." msgstr "启动更新失败" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:970 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1032 msgid "Failed to update query logs:" msgstr "更新查询日志失败:" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:699 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:709 msgid "Failed to update rule file: %s" msgstr "更新规则文件失败: %s" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1044 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1106 msgid "First Page / Resume" msgstr "重置并恢复" @@ -614,15 +618,15 @@ msgstr "IP 地址" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:410 msgid "" -"IPv4 CIDR: https://www.cloudflare.com/ips-v4
IPv6 CIDR: https://www." -"cloudflare.com/ips-v6" +"IPv4 CIDR: https://www.cloudflare.com/ips-v4
IPv6 CIDR: https://www.cloudflare.com/ips-" +"v6" msgstr "" -"IPv4 CIDR: https://www.cloudflare.com/ips-v4
IPv6 CIDR: https://www." -"cloudflare.com/ips-v6" +"IPv4 CIDR: https://www.cloudflare.com/ips-v4
IPv6 CIDR: https://www.cloudflare.com/ips-" +"v6" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:190 msgid "" @@ -644,7 +648,7 @@ msgstr "空闲超时" msgid "Info" msgstr "信息" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:828 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:838 msgid "Intercept" msgstr "拦截" @@ -654,7 +658,7 @@ msgid "" "seconds)." msgstr "后台线程扫描缓存以进行预取的时间间隔(单位:秒)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:479 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:489 msgid "Latency" msgstr "延迟" @@ -742,12 +746,12 @@ msgstr "修改 DNS 应答结果的最小 TTL 值 (秒),0 表示不修改" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:33 #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:106 #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/logs.js:70 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1094 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1156 #: luci-app-mosdns/root/usr/share/luci/menu.d/luci-app-mosdns.json:3 msgid "MosDNS" msgstr "MosDNS" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:510 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:520 msgid "" "MosDNS API is unreachable. Please ensure MosDNS is running and stats_api " "plugin is enabled." @@ -767,15 +771,15 @@ msgstr "未运行" msgid "Netflix, Disney+, Hulu and streaming media rules list will use this DNS" msgstr "自定义 Netflix、Disney+、Hulu 以及 “流媒体” 规则列表的 DNS 服务器" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:927 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:989 msgid "Next" msgstr "下一页" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:768 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:778 msgid "No DNS answer records returned." msgstr "无 DNS 应答记录" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:560 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:570 msgid "No data available" msgstr "暂无数据" @@ -783,19 +787,19 @@ msgstr "暂无数据" msgid "No log data." msgstr "无日志数据。" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:886 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:896 msgid "No query log entries found." msgstr "未找到查询日志记录。" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:904 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:941 msgid "Page %d / %d (%d entries)" msgstr "第 %d / %d 页(%d 条记录)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:438 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:448 msgid "Per-query speed" msgstr "单次查询速度" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:821 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:831 msgid "Permit" msgstr "放行" @@ -832,7 +836,7 @@ msgstr "当剩余 TTL 小于此值(秒)时触发预取" msgid "Prevent DNS Leaks" msgstr "防止 DNS 泄漏" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:916 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:978 msgid "Previous" msgstr "上一页" @@ -851,7 +855,7 @@ msgstr "Quad9 公共 DNS(149.112.112.112)" msgid "Quad9 Public DNS (9.9.9.9)" msgstr "Quad9 公共 DNS(9.9.9.9)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:811 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:821 msgid "Query Log Details" msgstr "查询日志详情" @@ -861,7 +865,7 @@ msgid "" "consume more memory)" msgstr "查询日志环形缓冲区容量(FIFO 覆盖,默认 2000,数值越大占用内存越多)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1067 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1129 msgid "Query logs cleared successfully." msgstr "查询日志清除成功。" @@ -869,7 +873,7 @@ msgstr "查询日志清除成功。" msgid "RUNNING" msgstr "运行中" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1098 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1160 msgid "Real-time Query Logs" msgstr "实时查询日志" @@ -901,7 +905,7 @@ msgstr "远程 DNS 服务器" msgid "Ring Buffer Capacity" msgstr "环形缓冲区容量" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:799 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:809 msgid "Rule Hit" msgstr "命中规则" @@ -921,7 +925,7 @@ msgstr "保存统计数据与查询日志在本地,并在下次启动时重新 msgid "Save the cache locally and reload the cache dump on the next startup" msgstr "保存缓存到本地文件,以供下次启动时重新载入使用" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1015 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1077 msgid "Search domain or client IP..." msgstr "搜索域名或客户端 IP..." @@ -933,7 +937,7 @@ msgstr "设置日志文件的最大容量(单位:MB)。" msgid "Starting update..." msgstr "正在启动更新..." -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1094 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:1156 #: luci-app-mosdns/root/usr/share/luci/menu.d/luci-app-mosdns.json:38 msgid "Statistics" msgstr "统计" @@ -942,7 +946,7 @@ msgstr "统计" msgid "Stats Dump" msgstr "自动保存统计" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:896 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:956 msgid "Status" msgstr "状态" @@ -962,7 +966,7 @@ msgstr "支持本地文件,例如:file:///var/mosdns/example.txt" msgid "TCP/DoT Connection Multiplexing" msgstr "TCP/DoT 连接复用" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:723 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:733 msgid "Target file: %s (supports domain matching rules)" msgstr "目标文件: %s (支持域名匹配规则)" @@ -1002,20 +1006,20 @@ msgstr "" "这是文件 “/etc/mosdns/config_custom.yaml” 的内容,您的 MosDNS 配置将从此文件" "生成。仅接受 yaml 格式的配置内容。" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:791 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:893 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:801 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:953 msgid "Time" msgstr "时间" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:599 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:609 msgid "Top Blocked Domains" msgstr "拦截域名 (Top 10)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:606 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:616 msgid "Top Clients" msgstr "活跃客户端 (Top 10)" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:592 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:602 msgid "Top Queried Domains" msgstr "查询域名 (Top 10)" @@ -1065,7 +1069,7 @@ msgstr "更新成功" msgid "Updating Database..." msgstr "更新数据库..." -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:795 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:805 msgid "Upstream" msgstr "上游服务器" @@ -1091,8 +1095,8 @@ msgstr "" "则)" #: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/rules.js:23 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:633 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:635 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:643 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:645 msgid "White Lists" msgstr "白名单" @@ -1110,24 +1114,15 @@ msgstr "信风公共 DNS(114.114.115.115)" msgid "https://gh-proxy.com" msgstr "https://gh-proxy.com" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:427 -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:540 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:437 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:550 msgid "● Live" msgstr "● 实时" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:223 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:233 msgid "● Live Auto-refresh" msgstr "● 实时刷新" -#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:227 +#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/statistics.js:237 msgid "❚❚ Paused (Page %d)" msgstr "❚❚ 暂停 (第 %d 页)" - -#~ msgid "Action" -#~ msgstr "操作" - -#~ msgid "Add %s to Blocklist" -#~ msgstr "将 %s 添加到黑名单" - -#~ msgid "Add %s to Whitelist" -#~ msgstr "将 %s 添加到白名单" diff --git a/mosdns/Makefile b/mosdns/Makefile index 3d8374d31..0affaa6c1 100644 --- a/mosdns/Makefile +++ b/mosdns/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mosdns PKG_VERSION:=5.3.4 -PKG_RELEASE:=21 +PKG_RELEASE:=22 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/IrineSistiana/mosdns/tar.gz/v$(PKG_VERSION)? diff --git a/mosdns/patches/226-fix-stats_api-do-not-mark-upstream-queries-without-a.patch b/mosdns/patches/226-fix-stats_api-do-not-mark-upstream-queries-without-a.patch new file mode 100644 index 000000000..c2e080f96 --- /dev/null +++ b/mosdns/patches/226-fix-stats_api-do-not-mark-upstream-queries-without-a.patch @@ -0,0 +1,172 @@ +From 5cb5430d8f942b317e02c2ec4e9383fe12857fb2 Mon Sep 17 00:00:00 2001 +From: sbwml +Date: Sat, 12 Sep 2026 00:32:03 +0800 +Subject: [PATCH] fix(stats_api): do not mark upstream queries without answers + as blocked + +Signed-off-by: sbwml +--- + plugin/executable/stats_api/stats_api.go | 8 +- + plugin/executable/stats_api/stats_api_test.go | 122 ++++++++++++++++++ + 2 files changed, 128 insertions(+), 2 deletions(-) + +--- a/plugin/executable/stats_api/stats_api.go ++++ b/plugin/executable/stats_api/stats_api.go +@@ -975,6 +975,8 @@ func (s *StatsAPI) Exec(ctx context.Cont + s.cachedQueries.Add(1) + } + ++ hasUpstream := isCached || qCtx.UpstreamSelected != nil ++ + r := qCtx.R() + var status string + var answers []AnswerDTO +@@ -982,7 +984,9 @@ func (s *StatsAPI) Exec(ctx context.Cont + + if r == nil { + status = "DROPPED" +- isBlocked = true ++ if !hasUpstream { ++ isBlocked = true ++ } + } else { + if rcodeStr, ok := dns.RcodeToString[r.Rcode]; ok { + status = rcodeStr +@@ -990,7 +994,7 @@ func (s *StatsAPI) Exec(ctx context.Cont + status = fmt.Sprintf("RCODE%d", r.Rcode) + } + +- if (r.Rcode == dns.RcodeNameError || r.Rcode == dns.RcodeRefused) && qQuestion.Qtype != dns.TypeHTTPS { ++ if !hasUpstream && (r.Rcode == dns.RcodeNameError || r.Rcode == dns.RcodeRefused) && qQuestion.Qtype != dns.TypeHTTPS { + isBlocked = true + } + +--- a/plugin/executable/stats_api/stats_api_test.go ++++ b/plugin/executable/stats_api/stats_api_test.go +@@ -712,4 +712,126 @@ func TestStatsAPIExecWithHostsAndArbitra + } + } + ++func TestStatsAPINoAnswerUpstreamAndBlocked(t *testing.T) { ++ s := NewStatsAPI(&Args{Capacity: 100}, zap.NewNop()) + ++ // Case 1: Upstream returns NXDOMAIN (no answers) -> NOT blocked ++ q1 := new(dns.Msg) ++ q1.SetQuestion("apps.itunes-nocookie.com.", dns.TypeA) ++ qCtx1 := query_context.NewContext(q1) ++ qCtx1.SetUpstreamSelected("https://doh.pub/dns-query", "DoH", "remote", "forward_remote") ++ ++ execUpstreamNX := sequence.ExecutableFunc(func(ctx context.Context, qCtx *query_context.Context) error { ++ resp := new(dns.Msg) ++ resp.SetReply(qCtx.Q()) ++ resp.Rcode = dns.RcodeNameError ++ qCtx.SetResponse(resp) ++ return nil ++ }) ++ ++ walker1 := sequence.NewChainWalker([]*sequence.ChainNode{{E: execUpstreamNX}}, nil) ++ if err := s.Exec(context.Background(), qCtx1, walker1); err != nil { ++ t.Fatalf("Exec failed: %v", err) ++ } ++ if s.blockedQueries.Load() != 0 { ++ t.Errorf("expected blockedQueries 0, got %d", s.blockedQueries.Load()) ++ } ++ _, logs1 := s.ringBuffer.QueryLogs(1, 0, "", "all") ++ if len(logs1) != 1 || logs1[0].IsBlocked || logs1[0].Status != "NXDOMAIN" || logs1[0].Upstream != "https://doh.pub/dns-query" { ++ t.Errorf("expected unblocked NXDOMAIN upstream log, got %+v", logs1) ++ } ++ ++ // Case 2: Cache returns NXDOMAIN (no answers) -> NOT blocked ++ q2 := new(dns.Msg) ++ q2.SetQuestion("cached-nx.example.com.", dns.TypeA) ++ qCtx2 := query_context.NewContext(q2) ++ qCtx2.SetCacheState(true, false, 300, 300) ++ ++ execCacheNX := sequence.ExecutableFunc(func(ctx context.Context, qCtx *query_context.Context) error { ++ resp := new(dns.Msg) ++ resp.SetReply(qCtx.Q()) ++ resp.Rcode = dns.RcodeNameError ++ qCtx.SetResponse(resp) ++ return nil ++ }) ++ ++ walker2 := sequence.NewChainWalker([]*sequence.ChainNode{{E: execCacheNX}}, nil) ++ if err := s.Exec(context.Background(), qCtx2, walker2); err != nil { ++ t.Fatalf("Exec failed: %v", err) ++ } ++ if s.blockedQueries.Load() != 0 { ++ t.Errorf("expected blockedQueries 0, got %d", s.blockedQueries.Load()) ++ } ++ _, logs2 := s.ringBuffer.QueryLogs(1, 0, "", "all") ++ if len(logs2) != 1 || logs2[0].IsBlocked || logs2[0].Status != "NXDOMAIN" || logs2[0].Upstream != "cache" { ++ t.Errorf("expected unblocked NXDOMAIN cache log, got %+v", logs2) ++ } ++ ++ // Case 3: Local reject (no upstream, NXDOMAIN) -> IS blocked ++ q3 := new(dns.Msg) ++ q3.SetQuestion("ad.reject.com.", dns.TypeA) ++ qCtx3 := query_context.NewContext(q3) ++ ++ execLocalReject := sequence.ExecutableFunc(func(ctx context.Context, qCtx *query_context.Context) error { ++ resp := new(dns.Msg) ++ resp.SetReply(qCtx.Q()) ++ resp.Rcode = dns.RcodeNameError ++ qCtx.SetResponse(resp) ++ return nil ++ }) ++ ++ walker3 := sequence.NewChainWalker([]*sequence.ChainNode{{E: execLocalReject}}, nil) ++ if err := s.Exec(context.Background(), qCtx3, walker3); err != nil { ++ t.Fatalf("Exec failed: %v", err) ++ } ++ if s.blockedQueries.Load() != 1 { ++ t.Errorf("expected blockedQueries 1, got %d", s.blockedQueries.Load()) ++ } ++ _, logs3 := s.ringBuffer.QueryLogs(1, 0, "", "all") ++ if len(logs3) != 1 || !logs3[0].IsBlocked { ++ t.Errorf("expected blocked log, got %+v", logs3) ++ } ++ ++ // Case 4: Upstream dropped (r == nil with upstream) -> NOT blocked ++ q4 := new(dns.Msg) ++ q4.SetQuestion("timeout.example.com.", dns.TypeA) ++ qCtx4 := query_context.NewContext(q4) ++ qCtx4.SetUpstreamSelected("8.8.8.8:53", "UDP", "remote", "forward_remote") ++ ++ execUpstreamDrop := sequence.ExecutableFunc(func(ctx context.Context, qCtx *query_context.Context) error { ++ return nil ++ }) ++ ++ walker4 := sequence.NewChainWalker([]*sequence.ChainNode{{E: execUpstreamDrop}}, nil) ++ if err := s.Exec(context.Background(), qCtx4, walker4); err != nil { ++ t.Fatalf("Exec failed: %v", err) ++ } ++ if s.blockedQueries.Load() != 1 { // Still 1 from case 3 ++ t.Errorf("expected blockedQueries to remain 1, got %d", s.blockedQueries.Load()) ++ } ++ _, logs4 := s.ringBuffer.QueryLogs(1, 0, "", "all") ++ if len(logs4) != 1 || logs4[0].IsBlocked || logs4[0].Status != "DROPPED" { ++ t.Errorf("expected unblocked DROPPED log, got %+v", logs4) ++ } ++ ++ // Case 5: Local drop (r == nil without upstream) -> IS blocked ++ q5 := new(dns.Msg) ++ q5.SetQuestion("local.drop.com.", dns.TypeA) ++ qCtx5 := query_context.NewContext(q5) ++ ++ execLocalDrop := sequence.ExecutableFunc(func(ctx context.Context, qCtx *query_context.Context) error { ++ return nil ++ }) ++ ++ walker5 := sequence.NewChainWalker([]*sequence.ChainNode{{E: execLocalDrop}}, nil) ++ if err := s.Exec(context.Background(), qCtx5, walker5); err != nil { ++ t.Fatalf("Exec failed: %v", err) ++ } ++ if s.blockedQueries.Load() != 2 { ++ t.Errorf("expected blockedQueries 2, got %d", s.blockedQueries.Load()) ++ } ++ _, logs5 := s.ringBuffer.QueryLogs(1, 0, "", "all") ++ if len(logs5) != 1 || !logs5[0].IsBlocked || logs5[0].Status != "DROPPED" { ++ t.Errorf("expected blocked DROPPED log, got %+v", logs5) ++ } ++}