update 2026-08-13 00:52:18
No files matched your search
|
Before Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 319 KiB |
|
Before Width: | Height: | Size: 389 KiB |
|
After Width: | Height: | Size: 640 KiB |
|
After Width: | Height: | Size: 550 KiB |
|
After Width: | Height: | Size: 547 KiB |
|
After Width: | Height: | Size: 659 KiB |
|
After Width: | Height: | Size: 650 KiB |
@@ -10,7 +10,7 @@ LUCI_DEPENDS:=+luci-base +luci-lib-jsonc +curl +bandix
|
|||||||
|
|
||||||
PKG_MAINTAINER:=timsaya
|
PKG_MAINTAINER:=timsaya
|
||||||
|
|
||||||
PKG_VERSION:=0.12.8
|
PKG_VERSION:=0.12.9
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
include $(TOPDIR)/feeds/luci/luci.mk
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|||||||
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 149 KiB |
@@ -9,6 +9,11 @@
|
|||||||
var BANDIX_COLOR_UPLOAD = '#f97316'; // 橙色 - 上传/上行
|
var BANDIX_COLOR_UPLOAD = '#f97316'; // 橙色 - 上传/上行
|
||||||
var BANDIX_COLOR_DOWNLOAD = '#06b6d4'; // 青色 - 下载/下行
|
var BANDIX_COLOR_DOWNLOAD = '#06b6d4'; // 青色 - 下载/下行
|
||||||
|
|
||||||
|
// 远程广告配置
|
||||||
|
var BANDIX_AD_CONFIG_URL = 'https://raw.githubusercontent.com/timsaya/bandix-ads/main/ads.json';
|
||||||
|
var BANDIX_AD_DEFAULT_REFRESH_INTERVAL = 3600;
|
||||||
|
var BANDIX_AD_RETRY_INTERVAL = 900;
|
||||||
|
|
||||||
// 悬浮框背景色定义
|
// 悬浮框背景色定义
|
||||||
var BANDIX_TOOLTIP_BG_OPENWRT2020_LIGHT = '#ffffff'; // OpenWrt 2020 浅色主题悬浮框背景
|
var BANDIX_TOOLTIP_BG_OPENWRT2020_LIGHT = '#ffffff'; // OpenWrt 2020 浅色主题悬浮框背景
|
||||||
var BANDIX_TOOLTIP_BG_OPENWRT2020_DARK = '#2a2a2a'; // OpenWrt 2020 深色主题悬浮框背景
|
var BANDIX_TOOLTIP_BG_OPENWRT2020_DARK = '#2a2a2a'; // OpenWrt 2020 深色主题悬浮框背景
|
||||||
@@ -556,6 +561,117 @@ return view.extend({
|
|||||||
background-color: rgba(239, 68, 68, 0.2);
|
background-color: rgba(239, 68, 68, 0.2);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bandix-ad-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(var(--bandix-ad-count, 6), minmax(112px, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
margin: 12px 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-slot {
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-width: 112px;
|
||||||
|
padding: 0;
|
||||||
|
aspect-ratio: 3 / 1;
|
||||||
|
border: 1px solid rgba(107, 114, 128, 0.35);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: linear-gradient(135deg, rgba(225, 37, 27, 0.08), rgba(107, 114, 128, 0.04));
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: inherit;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: border-color 0.2s ease, transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-slot:not(.bandix-ad-disabled):hover,
|
||||||
|
.bandix-ad-slot:not(.bandix-ad-disabled):focus-visible {
|
||||||
|
border-color: rgba(225, 37, 27, 0.75);
|
||||||
|
box-shadow: 0 4px 12px rgba(225, 37, 27, 0.12);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-label {
|
||||||
|
align-self: flex-start;
|
||||||
|
padding: 1px 5px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: rgba(225, 37, 27, 0.88);
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 0.5625rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-copy {
|
||||||
|
align-self: stretch;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 6px 4px 6px 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 3px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-title {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.25;
|
||||||
|
text-align: left;
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-media {
|
||||||
|
align-self: stretch;
|
||||||
|
flex: 0 0 33.333333%;
|
||||||
|
min-width: 0;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-image {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-placeholder {
|
||||||
|
flex: 0 0 33.333333%;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
align-self: stretch;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 3px;
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
color: #e1251b;
|
||||||
|
font-size: 0.625rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.2;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 移动端隐藏版本信息和更新徽章 */
|
/* 移动端隐藏版本信息和更新徽章 */
|
||||||
@@ -563,6 +679,26 @@ return view.extend({
|
|||||||
.bandix-version-wrapper {
|
.bandix-version-wrapper {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bandix-ad-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-slot {
|
||||||
|
flex: 0 0 180px;
|
||||||
|
min-width: 180px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-copy {
|
||||||
|
padding-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-ad-title {
|
||||||
|
font-size: 0.625rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.device-mode-group {
|
.device-mode-group {
|
||||||
@@ -2820,6 +2956,25 @@ return view.extend({
|
|||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
// 广告数据从公开仓库动态加载
|
||||||
|
E('div', {
|
||||||
|
'class': 'bandix-ad-row',
|
||||||
|
'id': 'bandix-ad-row',
|
||||||
|
'aria-label': _('Advertising spaces')
|
||||||
|
}, [1, 2, 3, 4, 5, 6].map(function (index) {
|
||||||
|
return E('div', {
|
||||||
|
'class': 'bandix-ad-slot bandix-ad-disabled',
|
||||||
|
'data-ad-slot': String(index),
|
||||||
|
'aria-disabled': 'true'
|
||||||
|
}, [
|
||||||
|
E('div', { 'class': 'bandix-ad-copy' }, [
|
||||||
|
E('span', { 'class': 'bandix-ad-label' }, _('AD')),
|
||||||
|
E('span', { 'class': 'bandix-ad-title' }, _('Advertising space') + ' ' + index)
|
||||||
|
]),
|
||||||
|
E('span', { 'class': 'bandix-ad-placeholder' }, _('Advertising space'))
|
||||||
|
]);
|
||||||
|
})),
|
||||||
|
|
||||||
// 警告提示(包含在线设备数)
|
// 警告提示(包含在线设备数)
|
||||||
E('div', {
|
E('div', {
|
||||||
'class': 'bandix-alert' + (getThemeType() === 'wide' ? ' wide-theme' : '')
|
'class': 'bandix-alert' + (getThemeType() === 'wide' ? ' wide-theme' : '')
|
||||||
@@ -2975,7 +3130,8 @@ return view.extend({
|
|||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
E('div', { 'class': 'usage-ranking-query-presets' }, [
|
E('div', { 'class': 'usage-ranking-query-presets' }, [
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'today' }, _('Today')),
|
E('button', { 'class': 'cbi-button cbi-button-positive', 'data-preset': 'today' }, _('Today')),
|
||||||
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'yesterday' }, _('Yesterday')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'thisweek' }, _('This Week')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'thisweek' }, _('This Week')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'lastweek' }, _('Last Week')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'lastweek' }, _('Last Week')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'thismonth' }, _('This Month')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'thismonth' }, _('This Month')),
|
||||||
@@ -2983,7 +3139,7 @@ return view.extend({
|
|||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '7days' }, _('Last 7 Days')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '7days' }, _('Last 7 Days')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '30days' }, _('Last 30 Days')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '30days' }, _('Last 30 Days')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '90days' }, _('Last 90 Days')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '90days' }, _('Last 90 Days')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-positive', 'data-preset': '1year' }, _('Last Year'))
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '1year' }, _('Last Year'))
|
||||||
]),
|
]),
|
||||||
E('div', { 'class': 'usage-ranking-timeline', 'id': 'usage-ranking-timeline' }, [
|
E('div', { 'class': 'usage-ranking-timeline', 'id': 'usage-ranking-timeline' }, [
|
||||||
E('div', { 'class': 'usage-ranking-timeline-range', 'id': 'usage-ranking-timeline-range' })
|
E('div', { 'class': 'usage-ranking-timeline-range', 'id': 'usage-ranking-timeline-range' })
|
||||||
@@ -3047,7 +3203,8 @@ return view.extend({
|
|||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
E('div', { 'class': 'usage-ranking-query-presets' }, [
|
E('div', { 'class': 'usage-ranking-query-presets' }, [
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'today' }, _('Today')),
|
E('button', { 'class': 'cbi-button cbi-button-positive', 'data-preset': 'today' }, _('Today')),
|
||||||
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'yesterday' }, _('Yesterday')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'thisweek' }, _('This Week')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'thisweek' }, _('This Week')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'lastweek' }, _('Last Week')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'lastweek' }, _('Last Week')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'thismonth' }, _('This Month')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': 'thismonth' }, _('This Month')),
|
||||||
@@ -3055,7 +3212,7 @@ return view.extend({
|
|||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '7days' }, _('Last 7 Days')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '7days' }, _('Last 7 Days')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '30days' }, _('Last 30 Days')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '30days' }, _('Last 30 Days')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '90days' }, _('Last 90 Days')),
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '90days' }, _('Last 90 Days')),
|
||||||
E('button', { 'class': 'cbi-button cbi-button-positive', 'data-preset': '1year' }, _('Last Year'))
|
E('button', { 'class': 'cbi-button cbi-button-neutral', 'data-preset': '1year' }, _('Last Year'))
|
||||||
]),
|
]),
|
||||||
E('div', { 'class': 'usage-ranking-timeline', 'id': 'traffic-increments-timeline' }, [
|
E('div', { 'class': 'usage-ranking-timeline', 'id': 'traffic-increments-timeline' }, [
|
||||||
E('div', { 'class': 'usage-ranking-timeline-range', 'id': 'traffic-increments-timeline-range' })
|
E('div', { 'class': 'usage-ranking-timeline-range', 'id': 'traffic-increments-timeline-range' })
|
||||||
@@ -7504,7 +7661,6 @@ return view.extend({
|
|||||||
updateDeviceData();
|
updateDeviceData();
|
||||||
refreshWhitelistStatus();
|
refreshWhitelistStatus();
|
||||||
fetchAllScheduleRules();
|
fetchAllScheduleRules();
|
||||||
updateTrafficStatistics();
|
|
||||||
|
|
||||||
// 初始化时间范围查询功能
|
// 初始化时间范围查询功能
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
@@ -7631,6 +7787,12 @@ return view.extend({
|
|||||||
startDate = new Date(today);
|
startDate = new Date(today);
|
||||||
endDate = new Date(today);
|
endDate = new Date(today);
|
||||||
break;
|
break;
|
||||||
|
case 'yesterday':
|
||||||
|
var yesterdayDate = new Date(today);
|
||||||
|
yesterdayDate.setDate(yesterdayDate.getDate() - 1);
|
||||||
|
startDate = new Date(yesterdayDate);
|
||||||
|
endDate = new Date(yesterdayDate);
|
||||||
|
break;
|
||||||
case 'thisweek':
|
case 'thisweek':
|
||||||
// 本周:周一到今天
|
// 本周:周一到今天
|
||||||
var dayOfWeek = today.getDay(); // 0=周日, 1=周一, ..., 6=周六
|
var dayOfWeek = today.getDay(); // 0=周日, 1=周一, ..., 6=周六
|
||||||
@@ -7724,18 +7886,16 @@ return view.extend({
|
|||||||
// 重置按钮
|
// 重置按钮
|
||||||
if (resetBtn) {
|
if (resetBtn) {
|
||||||
resetBtn.addEventListener('click', function () {
|
resetBtn.addEventListener('click', function () {
|
||||||
var oneYearAgo = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate());
|
setDateRange(today, today, 'today');
|
||||||
setDateRange(oneYearAgo, today, '1year');
|
|
||||||
queryData();
|
queryData();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化:默认选择最近一年
|
// 初始化:默认选择今天
|
||||||
var oneYearAgo = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate());
|
setDateRange(today, today, 'today');
|
||||||
setDateRange(oneYearAgo, today, '1year');
|
|
||||||
|
|
||||||
// 设置初始时间范围并自动加载数据(结束时间为当天的 23:59:59)
|
// 设置初始时间范围并自动加载数据(结束时间为当天的 23:59:59)
|
||||||
var startMs = oneYearAgo.getTime();
|
var startMs = todayMs;
|
||||||
var endToday = new Date(today);
|
var endToday = new Date(today);
|
||||||
endToday.setHours(23, 59, 59, 999);
|
endToday.setHours(23, 59, 59, 999);
|
||||||
var endMs = endToday.getTime();
|
var endMs = endToday.getTime();
|
||||||
@@ -7896,6 +8056,12 @@ return view.extend({
|
|||||||
startDate = new Date(today);
|
startDate = new Date(today);
|
||||||
endDate = new Date(today);
|
endDate = new Date(today);
|
||||||
break;
|
break;
|
||||||
|
case 'yesterday':
|
||||||
|
var yesterdayDate = new Date(today);
|
||||||
|
yesterdayDate.setDate(yesterdayDate.getDate() - 1);
|
||||||
|
startDate = new Date(yesterdayDate);
|
||||||
|
endDate = new Date(yesterdayDate);
|
||||||
|
break;
|
||||||
case 'thisweek':
|
case 'thisweek':
|
||||||
var dayOfWeek = today.getDay();
|
var dayOfWeek = today.getDay();
|
||||||
var mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
|
var mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
|
||||||
@@ -7952,15 +8118,13 @@ return view.extend({
|
|||||||
// 重置按钮
|
// 重置按钮
|
||||||
if (resetBtn) {
|
if (resetBtn) {
|
||||||
resetBtn.addEventListener('click', function () {
|
resetBtn.addEventListener('click', function () {
|
||||||
var oneYearAgo = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate());
|
setDateRange(today, today, 'today');
|
||||||
setDateRange(oneYearAgo, today, '1year');
|
|
||||||
queryData();
|
queryData();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化:默认选择最近一年
|
// 初始化:默认选择今天
|
||||||
var oneYearAgo = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate());
|
setDateRange(today, today, 'today');
|
||||||
setDateRange(oneYearAgo, today, '1year');
|
|
||||||
|
|
||||||
startDateInput.addEventListener('change', function () {
|
startDateInput.addEventListener('change', function () {
|
||||||
updateTimeline(this.value, endDateInput.value);
|
updateTimeline(this.value, endDateInput.value);
|
||||||
@@ -7971,7 +8135,7 @@ return view.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 设置初始时间范围并自动加载数据(不显示 loading)
|
// 设置初始时间范围并自动加载数据(不显示 loading)
|
||||||
var startMs = oneYearAgo.getTime();
|
var startMs = todayMs;
|
||||||
var endToday = new Date(today);
|
var endToday = new Date(today);
|
||||||
endToday.setHours(23, 59, 59, 999);
|
endToday.setHours(23, 59, 59, 999);
|
||||||
var endMs = endToday.getTime();
|
var endMs = endToday.getTime();
|
||||||
@@ -7983,6 +8147,205 @@ return view.extend({
|
|||||||
updateTrafficIncrements(startMs, endMs, null, null);
|
updateTrafficIncrements(startMs, endMs, null, null);
|
||||||
}, 700);
|
}, 700);
|
||||||
|
|
||||||
|
// 异步加载远程广告(不阻塞主流程)
|
||||||
|
(function () {
|
||||||
|
var refreshTimer = null;
|
||||||
|
|
||||||
|
function resolveHttpsUrl(value, baseUrl) {
|
||||||
|
if (typeof value !== 'string' || !value) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var resolved = new URL(value, baseUrl);
|
||||||
|
return resolved.protocol === 'https:' ? resolved.href : null;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleRefresh(seconds) {
|
||||||
|
var interval = Number(seconds);
|
||||||
|
if (!Number.isFinite(interval)) interval = BANDIX_AD_DEFAULT_REFRESH_INTERVAL;
|
||||||
|
interval = Math.max(300, Math.min(86400, interval));
|
||||||
|
|
||||||
|
if (refreshTimer !== null) window.clearTimeout(refreshTimer);
|
||||||
|
refreshTimer = window.setTimeout(loadAdvertisements, interval * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeAdvertisementLocale(value) {
|
||||||
|
if (typeof value !== 'string') return '';
|
||||||
|
|
||||||
|
var locale = value.trim().replace(/_/g, '-').toLowerCase();
|
||||||
|
if (!locale || locale === 'auto' || locale === 'und') return '';
|
||||||
|
|
||||||
|
if (locale === 'zh' || locale === 'zh-cn' || locale === 'zh-sg' || locale === 'zh-hans') {
|
||||||
|
return 'zh-hans';
|
||||||
|
}
|
||||||
|
if (locale === 'zh-tw' || locale === 'zh-hk' || locale === 'zh-mo' || locale === 'zh-hant') {
|
||||||
|
return 'zh-hant';
|
||||||
|
}
|
||||||
|
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAdvertisementLocale() {
|
||||||
|
var candidates = [];
|
||||||
|
if (L.env) candidates.push(L.env.lang || L.env.language || '');
|
||||||
|
var htmlLanguage = document.documentElement.getAttribute('lang');
|
||||||
|
if (htmlLanguage) candidates.push(htmlLanguage);
|
||||||
|
if (window.navigator) candidates.push(window.navigator.language || '');
|
||||||
|
|
||||||
|
for (var i = 0; i < candidates.length; i++) {
|
||||||
|
var locale = normalizeAdvertisementLocale(candidates[i]);
|
||||||
|
if (locale) return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectLocalizedAdvertisements(config) {
|
||||||
|
// 兼容旧版单语言配置,方便两个仓库分开部署
|
||||||
|
if (config.version === 1 && Array.isArray(config.ads)) {
|
||||||
|
return { locale: 'legacy', ads: config.ads };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.version !== 2 || !config.locales || typeof config.locales !== 'object') {
|
||||||
|
throw new Error('Invalid advertising configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentLocale = getAdvertisementLocale();
|
||||||
|
var defaultLocale = normalizeAdvertisementLocale(config.default_locale);
|
||||||
|
var localeCandidates = [];
|
||||||
|
|
||||||
|
if (currentLocale) {
|
||||||
|
localeCandidates.push(currentLocale);
|
||||||
|
var separatorIndex = currentLocale.indexOf('-');
|
||||||
|
if (separatorIndex > 0) localeCandidates.push(currentLocale.substring(0, separatorIndex));
|
||||||
|
}
|
||||||
|
if (defaultLocale) localeCandidates.push(defaultLocale);
|
||||||
|
|
||||||
|
for (var i = 0; i < localeCandidates.length; i++) {
|
||||||
|
var candidate = localeCandidates[i];
|
||||||
|
if (Object.prototype.hasOwnProperty.call(config.locales, candidate) &&
|
||||||
|
Array.isArray(config.locales[candidate])) {
|
||||||
|
return { locale: candidate, ads: config.locales[candidate] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('No advertising locale is available');
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAdvertisements(config) {
|
||||||
|
var adRow = document.getElementById('bandix-ad-row');
|
||||||
|
if (!adRow || !config) {
|
||||||
|
throw new Error('Invalid advertising configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
var selection = selectLocalizedAdvertisements(config);
|
||||||
|
adRow.setAttribute('data-ad-locale', selection.locale);
|
||||||
|
|
||||||
|
var ads = selection.ads.slice(0, 6).map(function (ad, index) {
|
||||||
|
if (!ad || typeof ad !== 'object') ad = {};
|
||||||
|
|
||||||
|
var href = resolveHttpsUrl(ad.href, BANDIX_AD_CONFIG_URL);
|
||||||
|
var image = resolveHttpsUrl(ad.image, BANDIX_AD_CONFIG_URL);
|
||||||
|
var title = typeof ad.title === 'string' ? ad.title.trim() : _('Advertising space') + ' ' + (index + 1);
|
||||||
|
if (!title) title = _('Advertising space') + ' ' + (index + 1);
|
||||||
|
var alt = typeof ad.alt === 'string' ? ad.alt.trim() : title;
|
||||||
|
|
||||||
|
return {
|
||||||
|
enabled: ad.enabled === true && href !== null,
|
||||||
|
href: href,
|
||||||
|
image: image,
|
||||||
|
title: title,
|
||||||
|
alt: alt || title
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
while (ads.length < 6) {
|
||||||
|
ads.push({
|
||||||
|
enabled: false,
|
||||||
|
href: null,
|
||||||
|
image: null,
|
||||||
|
title: _('Advertising space') + ' ' + (ads.length + 1),
|
||||||
|
alt: _('Advertising space')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
while (adRow.firstChild) adRow.removeChild(adRow.firstChild);
|
||||||
|
|
||||||
|
ads.forEach(function (ad, index) {
|
||||||
|
var tagName = ad.enabled ? 'a' : 'div';
|
||||||
|
var attributes = {
|
||||||
|
'class': 'bandix-ad-slot' + (ad.enabled ? '' : ' bandix-ad-disabled'),
|
||||||
|
'data-ad-slot': String(index + 1),
|
||||||
|
'title': ad.title
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ad.enabled) {
|
||||||
|
attributes.href = ad.href;
|
||||||
|
attributes.target = '_blank';
|
||||||
|
attributes.rel = 'noopener noreferrer sponsored';
|
||||||
|
} else {
|
||||||
|
attributes['aria-disabled'] = 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
var content = [E('div', { 'class': 'bandix-ad-copy' }, [
|
||||||
|
E('span', { 'class': 'bandix-ad-label' }, _('AD')),
|
||||||
|
E('span', { 'class': 'bandix-ad-title' }, ad.title)
|
||||||
|
])];
|
||||||
|
if (ad.enabled && ad.image) {
|
||||||
|
content.push(E('div', { 'class': 'bandix-ad-media' }, [
|
||||||
|
E('img', {
|
||||||
|
'class': 'bandix-ad-image',
|
||||||
|
'src': ad.image,
|
||||||
|
'alt': ad.alt,
|
||||||
|
'loading': 'lazy',
|
||||||
|
'referrerpolicy': 'no-referrer'
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
} else {
|
||||||
|
content.push(E('span', { 'class': 'bandix-ad-placeholder' }, _('Advertising space')));
|
||||||
|
}
|
||||||
|
|
||||||
|
adRow.appendChild(E(tagName, attributes, content));
|
||||||
|
});
|
||||||
|
|
||||||
|
adRow.style.setProperty('--bandix-ad-count', '6');
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadAdvertisements() {
|
||||||
|
var adRow = document.getElementById('bandix-ad-row');
|
||||||
|
if (!adRow) return;
|
||||||
|
|
||||||
|
if (typeof window.fetch !== 'function') {
|
||||||
|
console.debug('Failed to load advertisements: Fetch API is unavailable');
|
||||||
|
scheduleRefresh(BANDIX_AD_RETRY_INTERVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var separator = BANDIX_AD_CONFIG_URL.indexOf('?') === -1 ? '?' : '&';
|
||||||
|
var configUrl = BANDIX_AD_CONFIG_URL + separator + '_=' + Date.now();
|
||||||
|
|
||||||
|
window.fetch(configUrl, {
|
||||||
|
method: 'GET',
|
||||||
|
mode: 'cors',
|
||||||
|
credentials: 'omit',
|
||||||
|
cache: 'no-store'
|
||||||
|
}).then(function (response) {
|
||||||
|
if (!response.ok) throw new Error('HTTP ' + response.status);
|
||||||
|
return response.json();
|
||||||
|
}).then(function (config) {
|
||||||
|
renderAdvertisements(config);
|
||||||
|
scheduleRefresh(config.refresh_interval);
|
||||||
|
}).catch(function (err) {
|
||||||
|
console.debug('Failed to load advertisements:', err);
|
||||||
|
scheduleRefresh(BANDIX_AD_RETRY_INTERVAL);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setTimeout(loadAdvertisements, 200);
|
||||||
|
})();
|
||||||
|
|
||||||
// 异步加载版本信息(不阻塞主流程)
|
// 异步加载版本信息(不阻塞主流程)
|
||||||
(function () {
|
(function () {
|
||||||
// 延迟执行,确保页面先完成初始化
|
// 延迟执行,确保页面先完成初始化
|
||||||
|
|||||||
@@ -673,6 +673,46 @@ return view.extend({
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 支持作者(基本设置的最后一项)
|
||||||
|
var alipayImage = L.resource('bandix/donate/alipay.jpg');
|
||||||
|
var wechatImage = L.resource('bandix/donate/wechat-pay.png');
|
||||||
|
|
||||||
|
function donationCard(title, imageUrl, altText, dotClass) {
|
||||||
|
return E('div', { 'class': 'bandix-donation-card' }, [
|
||||||
|
E('h4', { 'class': 'bandix-donation-card-title' }, [
|
||||||
|
E('span', { 'class': 'bandix-donation-dot ' + dotClass }),
|
||||||
|
title
|
||||||
|
]),
|
||||||
|
E('a', {
|
||||||
|
'class': 'bandix-donation-image-link',
|
||||||
|
'href': imageUrl,
|
||||||
|
'target': '_blank',
|
||||||
|
'rel': 'noopener noreferrer',
|
||||||
|
'title': altText
|
||||||
|
}, [
|
||||||
|
E('img', {
|
||||||
|
'class': 'bandix-donation-image',
|
||||||
|
'src': imageUrl,
|
||||||
|
'alt': altText,
|
||||||
|
'loading': 'lazy'
|
||||||
|
})
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
o = s.option(form.DummyValue, '_donation_qr_codes', _('Support the Author'));
|
||||||
|
o.renderWidget = function () {
|
||||||
|
return E('div', { 'class': 'bandix-donation-content' }, [
|
||||||
|
E('p', { 'class': 'bandix-donation-description' },
|
||||||
|
_('If Bandix is useful to you, you can support its continued development.')),
|
||||||
|
E('div', { 'class': 'bandix-donation-grid' }, [
|
||||||
|
donationCard(_('Alipay'), alipayImage, _('Scan with Alipay to support'), 'bandix-donation-dot-alipay'),
|
||||||
|
donationCard(_('WeChat Pay'), wechatImage, _('Scan with WeChat Pay to support'), 'bandix-donation-dot-wechat')
|
||||||
|
]),
|
||||||
|
E('p', { 'class': 'bandix-donation-note' }, _('Donations are voluntary. Thank you for supporting Bandix.'))
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
// 2. 流量监控设置部分 (traffic)
|
// 2. 流量监控设置部分 (traffic)
|
||||||
s = m.section(form.NamedSection, 'traffic', 'traffic', _('Traffic Monitor Settings'));
|
s = m.section(form.NamedSection, 'traffic', 'traffic', _('Traffic Monitor Settings'));
|
||||||
s.description = _('Configure traffic monitoring related parameters');
|
s.description = _('Configure traffic monitoring related parameters');
|
||||||
@@ -826,6 +866,98 @@ return view.extend({
|
|||||||
// 将 view 实例关联到 form map,以便在 cfgvalue 中访问
|
// 将 view 实例关联到 form map,以便在 cfgvalue 中访问
|
||||||
m.view = this;
|
m.view = this;
|
||||||
|
|
||||||
return m.render();
|
return m.render().then(function (mapEl) {
|
||||||
|
var oldStyle = document.getElementById('bandix-donation-styles');
|
||||||
|
if (oldStyle && oldStyle.parentNode) oldStyle.parentNode.removeChild(oldStyle);
|
||||||
|
|
||||||
|
document.head.appendChild(E('style', { 'id': 'bandix-donation-styles' }, `
|
||||||
|
.bandix-donation-content {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-description {
|
||||||
|
margin: 0 auto 18px;
|
||||||
|
max-width: 620px;
|
||||||
|
opacity: 0.72;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(220px, 280px));
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-card {
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid rgba(107, 114, 128, 0.3);
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(107, 114, 128, 0.04);
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-card:hover {
|
||||||
|
border-color: rgba(59, 130, 246, 0.55);
|
||||||
|
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.1);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-card-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 7px;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-dot {
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-dot-alipay {
|
||||||
|
background: #1677ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-dot-wechat {
|
||||||
|
background: #07c160;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-image-link {
|
||||||
|
display: block;
|
||||||
|
border-radius: 7px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #ffffff;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-image {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandix-donation-note {
|
||||||
|
margin: 14px 0 0;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
opacity: 0.58;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.bandix-donation-grid {
|
||||||
|
grid-template-columns: minmax(200px, 280px);
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`));
|
||||||
|
|
||||||
|
return mapEl;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1112,6 +1112,30 @@ msgstr "Restablecer"
|
|||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "Hoy"
|
msgstr "Hoy"
|
||||||
|
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "Ayer"
|
||||||
|
|
||||||
|
msgid "Support the Author"
|
||||||
|
msgstr "Apoyar al autor"
|
||||||
|
|
||||||
|
msgid "If Bandix is useful to you, you can support its continued development."
|
||||||
|
msgstr "Si Bandix te resulta útil, puedes apoyar su desarrollo continuo."
|
||||||
|
|
||||||
|
msgid "Alipay"
|
||||||
|
msgstr "Alipay"
|
||||||
|
|
||||||
|
msgid "Scan with Alipay to support"
|
||||||
|
msgstr "Escanea con Alipay para apoyar"
|
||||||
|
|
||||||
|
msgid "WeChat Pay"
|
||||||
|
msgstr "WeChat Pay"
|
||||||
|
|
||||||
|
msgid "Scan with WeChat Pay to support"
|
||||||
|
msgstr "Escanea con WeChat Pay para apoyar"
|
||||||
|
|
||||||
|
msgid "Donations are voluntary. Thank you for supporting Bandix."
|
||||||
|
msgstr "Las donaciones son voluntarias. Gracias por apoyar a Bandix."
|
||||||
|
|
||||||
msgid "This Week"
|
msgid "This Week"
|
||||||
msgstr "Esta Semana"
|
msgstr "Esta Semana"
|
||||||
|
|
||||||
|
|||||||
@@ -1112,6 +1112,30 @@ msgstr "Réinitialiser"
|
|||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "Aujourd'hui"
|
msgstr "Aujourd'hui"
|
||||||
|
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "Hier"
|
||||||
|
|
||||||
|
msgid "Support the Author"
|
||||||
|
msgstr "Soutenir l’auteur"
|
||||||
|
|
||||||
|
msgid "If Bandix is useful to you, you can support its continued development."
|
||||||
|
msgstr "Si Bandix vous est utile, vous pouvez soutenir la poursuite de son développement."
|
||||||
|
|
||||||
|
msgid "Alipay"
|
||||||
|
msgstr "Alipay"
|
||||||
|
|
||||||
|
msgid "Scan with Alipay to support"
|
||||||
|
msgstr "Scannez avec Alipay pour nous soutenir"
|
||||||
|
|
||||||
|
msgid "WeChat Pay"
|
||||||
|
msgstr "WeChat Pay"
|
||||||
|
|
||||||
|
msgid "Scan with WeChat Pay to support"
|
||||||
|
msgstr "Scannez avec WeChat Pay pour nous soutenir"
|
||||||
|
|
||||||
|
msgid "Donations are voluntary. Thank you for supporting Bandix."
|
||||||
|
msgstr "Les dons sont facultatifs. Merci de soutenir Bandix."
|
||||||
|
|
||||||
msgid "This Week"
|
msgid "This Week"
|
||||||
msgstr "Cette Semaine"
|
msgstr "Cette Semaine"
|
||||||
|
|
||||||
|
|||||||
@@ -1112,6 +1112,30 @@ msgstr "リセット"
|
|||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "今日"
|
msgstr "今日"
|
||||||
|
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "昨日"
|
||||||
|
|
||||||
|
msgid "Support the Author"
|
||||||
|
msgstr "作者を支援"
|
||||||
|
|
||||||
|
msgid "If Bandix is useful to you, you can support its continued development."
|
||||||
|
msgstr "Bandix が役に立った場合は、継続的な開発をご支援いただけます。"
|
||||||
|
|
||||||
|
msgid "Alipay"
|
||||||
|
msgstr "Alipay"
|
||||||
|
|
||||||
|
msgid "Scan with Alipay to support"
|
||||||
|
msgstr "Alipay でスキャンして支援"
|
||||||
|
|
||||||
|
msgid "WeChat Pay"
|
||||||
|
msgstr "WeChat Pay"
|
||||||
|
|
||||||
|
msgid "Scan with WeChat Pay to support"
|
||||||
|
msgstr "WeChat Pay でスキャンして支援"
|
||||||
|
|
||||||
|
msgid "Donations are voluntary. Thank you for supporting Bandix."
|
||||||
|
msgstr "寄付は任意です。Bandix をご支援いただきありがとうございます。"
|
||||||
|
|
||||||
msgid "This Week"
|
msgid "This Week"
|
||||||
msgstr "今週"
|
msgstr "今週"
|
||||||
|
|
||||||
|
|||||||
@@ -1112,6 +1112,30 @@ msgstr "Resetuj"
|
|||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "Dzisiaj"
|
msgstr "Dzisiaj"
|
||||||
|
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "Wczoraj"
|
||||||
|
|
||||||
|
msgid "Support the Author"
|
||||||
|
msgstr "Wesprzyj autora"
|
||||||
|
|
||||||
|
msgid "If Bandix is useful to you, you can support its continued development."
|
||||||
|
msgstr "Jeśli Bandix jest dla Ciebie przydatny, możesz wesprzeć jego dalszy rozwój."
|
||||||
|
|
||||||
|
msgid "Alipay"
|
||||||
|
msgstr "Alipay"
|
||||||
|
|
||||||
|
msgid "Scan with Alipay to support"
|
||||||
|
msgstr "Zeskanuj w Alipay, aby wesprzeć"
|
||||||
|
|
||||||
|
msgid "WeChat Pay"
|
||||||
|
msgstr "WeChat Pay"
|
||||||
|
|
||||||
|
msgid "Scan with WeChat Pay to support"
|
||||||
|
msgstr "Zeskanuj w WeChat Pay, aby wesprzeć"
|
||||||
|
|
||||||
|
msgid "Donations are voluntary. Thank you for supporting Bandix."
|
||||||
|
msgstr "Darowizny są dobrowolne. Dziękujemy za wsparcie Bandix."
|
||||||
|
|
||||||
msgid "This Week"
|
msgid "This Week"
|
||||||
msgstr "Ten Tydzień"
|
msgstr "Ten Tydzień"
|
||||||
|
|
||||||
|
|||||||
@@ -1112,6 +1112,30 @@ msgstr "Сбросить"
|
|||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "Сегодня"
|
msgstr "Сегодня"
|
||||||
|
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "Вчера"
|
||||||
|
|
||||||
|
msgid "Support the Author"
|
||||||
|
msgstr "Поддержать автора"
|
||||||
|
|
||||||
|
msgid "If Bandix is useful to you, you can support its continued development."
|
||||||
|
msgstr "Если Bandix полезен вам, вы можете поддержать его дальнейшую разработку."
|
||||||
|
|
||||||
|
msgid "Alipay"
|
||||||
|
msgstr "Alipay"
|
||||||
|
|
||||||
|
msgid "Scan with Alipay to support"
|
||||||
|
msgstr "Отсканируйте в Alipay, чтобы поддержать"
|
||||||
|
|
||||||
|
msgid "WeChat Pay"
|
||||||
|
msgstr "WeChat Pay"
|
||||||
|
|
||||||
|
msgid "Scan with WeChat Pay to support"
|
||||||
|
msgstr "Отсканируйте в WeChat Pay, чтобы поддержать"
|
||||||
|
|
||||||
|
msgid "Donations are voluntary. Thank you for supporting Bandix."
|
||||||
|
msgstr "Пожертвования добровольны. Спасибо за поддержку Bandix."
|
||||||
|
|
||||||
msgid "This Week"
|
msgid "This Week"
|
||||||
msgstr "На этой неделе"
|
msgstr "На этой неделе"
|
||||||
|
|
||||||
|
|||||||
@@ -1094,6 +1094,15 @@ msgstr "有更新"
|
|||||||
msgid "Update available, click to go to settings"
|
msgid "Update available, click to go to settings"
|
||||||
msgstr "有更新,点击前往设置"
|
msgstr "有更新,点击前往设置"
|
||||||
|
|
||||||
|
msgid "Advertising spaces"
|
||||||
|
msgstr "广告位"
|
||||||
|
|
||||||
|
msgid "Advertising space"
|
||||||
|
msgstr "广告位"
|
||||||
|
|
||||||
|
msgid "AD"
|
||||||
|
msgstr "广告"
|
||||||
|
|
||||||
msgid "Traffic Statistics"
|
msgid "Traffic Statistics"
|
||||||
msgstr "流量统计"
|
msgstr "流量统计"
|
||||||
|
|
||||||
@@ -1115,6 +1124,30 @@ msgstr "重置"
|
|||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "今天"
|
msgstr "今天"
|
||||||
|
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "昨天"
|
||||||
|
|
||||||
|
msgid "Support the Author"
|
||||||
|
msgstr "支持作者"
|
||||||
|
|
||||||
|
msgid "If Bandix is useful to you, you can support its continued development."
|
||||||
|
msgstr "如果 Bandix 对您有帮助,您可以支持项目的持续开发。"
|
||||||
|
|
||||||
|
msgid "Alipay"
|
||||||
|
msgstr "支付宝"
|
||||||
|
|
||||||
|
msgid "Scan with Alipay to support"
|
||||||
|
msgstr "使用支付宝扫码支持"
|
||||||
|
|
||||||
|
msgid "WeChat Pay"
|
||||||
|
msgstr "微信支付"
|
||||||
|
|
||||||
|
msgid "Scan with WeChat Pay to support"
|
||||||
|
msgstr "使用微信支付扫码支持"
|
||||||
|
|
||||||
|
msgid "Donations are voluntary. Thank you for supporting Bandix."
|
||||||
|
msgstr "赞助完全自愿。感谢您对 Bandix 的支持。"
|
||||||
|
|
||||||
msgid "This Week"
|
msgid "This Week"
|
||||||
msgstr "本周"
|
msgstr "本周"
|
||||||
|
|
||||||
|
|||||||
@@ -1112,6 +1112,30 @@ msgstr "重置"
|
|||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "今天"
|
msgstr "今天"
|
||||||
|
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "昨天"
|
||||||
|
|
||||||
|
msgid "Support the Author"
|
||||||
|
msgstr "支持作者"
|
||||||
|
|
||||||
|
msgid "If Bandix is useful to you, you can support its continued development."
|
||||||
|
msgstr "如果 Bandix 對您有幫助,您可以支持專案的持續開發。"
|
||||||
|
|
||||||
|
msgid "Alipay"
|
||||||
|
msgstr "支付寶"
|
||||||
|
|
||||||
|
msgid "Scan with Alipay to support"
|
||||||
|
msgstr "使用支付寶掃碼支持"
|
||||||
|
|
||||||
|
msgid "WeChat Pay"
|
||||||
|
msgstr "微信支付"
|
||||||
|
|
||||||
|
msgid "Scan with WeChat Pay to support"
|
||||||
|
msgstr "使用微信支付掃碼支持"
|
||||||
|
|
||||||
|
msgid "Donations are voluntary. Thank you for supporting Bandix."
|
||||||
|
msgstr "贊助完全自願。感謝您對 Bandix 的支持。"
|
||||||
|
|
||||||
msgid "This Week"
|
msgid "This Week"
|
||||||
msgstr "本週"
|
msgstr "本週"
|
||||||
|
|
||||||
@@ -1255,3 +1279,12 @@ msgstr "TCX 出站錨點程式 ID"
|
|||||||
|
|
||||||
msgid "Used when tc_order is before/after. Must be a valid egress program id on the same interface."
|
msgid "Used when tc_order is before/after. Must be a valid egress program id on the same interface."
|
||||||
msgstr "當 tc_order 為 before/after 時使用。必須是同一介面上的有效出站程式 ID。"
|
msgstr "當 tc_order 為 before/after 時使用。必須是同一介面上的有效出站程式 ID。"
|
||||||
|
|
||||||
|
msgid "Advertising spaces"
|
||||||
|
msgstr "廣告位"
|
||||||
|
|
||||||
|
msgid "Advertising space"
|
||||||
|
msgstr "廣告位"
|
||||||
|
|
||||||
|
msgid "AD"
|
||||||
|
msgstr "廣告"
|
||||||