diff --git a/luci-app-bandix/Makefile b/luci-app-bandix/Makefile
index cc9e98f..33659d3 100644
--- a/luci-app-bandix/Makefile
+++ b/luci-app-bandix/Makefile
@@ -10,7 +10,7 @@ LUCI_DEPENDS:=+luci-base +luci-lib-jsonc +curl +bandix
PKG_MAINTAINER:=timsaya
-PKG_VERSION:=0.9.1
+PKG_VERSION:=0.10.0
PKG_RELEASE:=1
include $(TOPDIR)/feeds/luci/luci.mk
diff --git a/luci-app-bandix/htdocs/luci-static/resources/view/bandix/index.js b/luci-app-bandix/htdocs/luci-static/resources/view/bandix/index.js
index 39ccdf3..02eff18 100644
--- a/luci-app-bandix/htdocs/luci-static/resources/view/bandix/index.js
+++ b/luci-app-bandix/htdocs/luci-static/resources/view/bandix/index.js
@@ -148,6 +148,27 @@ var callGetMetrics = rpc.declare({
expect: {}
});
+var callGetMetricsDay = rpc.declare({
+ object: 'luci.bandix',
+ method: 'getMetricsDay',
+ params: ['mac'],
+ expect: {}
+});
+
+var callGetMetricsWeek = rpc.declare({
+ object: 'luci.bandix',
+ method: 'getMetricsWeek',
+ params: ['mac'],
+ expect: {}
+});
+
+var callGetMetricsMonth = rpc.declare({
+ object: 'luci.bandix',
+ method: 'getMetricsMonth',
+ params: ['mac'],
+ expect: {}
+});
+
// 定时限速 RPC
var callGetScheduleLimits = rpc.declare({
object: 'luci.bandix',
@@ -1017,6 +1038,94 @@ return view.extend({
display: flex;
align-items: center;
justify-content: space-between;
+ margin-bottom: 16px;
+ }
+ .history-header-left {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ }
+ .history-tabs {
+ display: inline-flex;
+ background-color: rgba(0, 0, 0, 0.04);
+ border-radius: 8px;
+ padding: 3px;
+ gap: 2px;
+ }
+ @media (prefers-color-scheme: dark) {
+ .history-tabs {
+ background-color: rgba(255, 255, 255, 0.08);
+ }
+ }
+ .history-tab {
+ padding: 6px 16px;
+ text-align: center;
+ cursor: pointer;
+ border: none;
+ background: transparent;
+ font-size: 0.8125rem;
+ font-weight: 500;
+ color: rgba(0, 0, 0, 0.65);
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+ border-radius: 6px;
+ white-space: nowrap;
+ position: relative;
+ }
+ @media (prefers-color-scheme: dark) {
+ .history-tab {
+ color: rgba(255, 255, 255, 0.65);
+ }
+ }
+ .history-tab:hover:not(.active) {
+ color: rgba(0, 0, 0, 0.85);
+ background-color: rgba(0, 0, 0, 0.06);
+ }
+ @media (prefers-color-scheme: dark) {
+ .history-tab:hover:not(.active) {
+ color: rgba(255, 255, 255, 0.85);
+ background-color: rgba(255, 255, 255, 0.12);
+ }
+ }
+ .history-tab.active {
+ background-color: #ffffff;
+ color: #3b82f6;
+ font-weight: 600;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.08);
+ }
+ @media (prefers-color-scheme: dark) {
+ .history-tab.active {
+ background-color: rgba(59, 130, 246, 0.15);
+ color: #60a5fa;
+ box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.3);
+ }
+ }
+ @media (max-width: 768px) {
+ .history-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+ }
+ .history-header-left {
+ width: 100%;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+ }
+ .history-tabs {
+ width: 100%;
+ padding: 2px;
+ }
+ .history-tab {
+ flex: 1;
+ padding: 8px 6px;
+ font-size: 0.75rem;
+ }
+ /* 移动端只显示 Realtime tab */
+ .history-tab[data-range="day"],
+ .history-tab[data-range="week"],
+ .history-tab[data-range="month"] {
+ display: none !important;
+ }
}
.history-controls {
display: flex;
@@ -1034,7 +1143,6 @@ return view.extend({
position: relative;
}
.history-legend {
- margin-left: auto;
display: flex;
align-items: center;
gap: 12px;
@@ -1452,10 +1560,19 @@ return view.extend({
// 统计卡片
E('div', { 'class': 'stats-grid', 'id': 'stats-grid' }),
- // 历史趋势卡片(无时间范围筛选)
+ // 历史趋势卡片(带时间范围 tab 切换)
E('div', { 'class': 'cbi-section', 'id': 'history-card' }, [
- E('h3', { 'class': 'history-header', 'style': 'display: flex; align-items: center; justify-content: space-between;' }, [
- E('span', {}, _('Traffic History')),
+ E('div', { 'class': 'history-header' }, [
+ E('div', { 'class': 'history-header-left' }, [
+ // E('h3', { 'style': 'margin: 0; font-size: 1rem; font-weight: 600;' }, _('Traffic History')),
+ // 时间范围 Tab 切换
+ E('div', { 'class': 'history-tabs' }, [
+ E('button', { 'class': 'history-tab active', 'data-range': 'realtime', 'id': 'history-tab-realtime' }, _('Realtime')),
+ E('button', { 'class': 'history-tab', 'data-range': 'day', 'id': 'history-tab-day' }, _('Day')),
+ E('button', { 'class': 'history-tab', 'data-range': 'week', 'id': 'history-tab-week' }, _('Week')),
+ E('button', { 'class': 'history-tab', 'data-range': 'month', 'id': 'history-tab-month' }, _('Month'))
+ ])
+ ]),
E('div', { 'class': 'history-legend' }, [
E('div', { 'class': 'legend-item' }, [
E('span', { 'class': 'legend-dot legend-up' }),
@@ -2525,14 +2642,109 @@ return view.extend({
}
function getTypeKeys(type) {
+ // 对于非实时时间范围(day/week/month),只有 WAN 数据
+ if (currentTimeRange !== 'realtime') {
+ // 所有类型都使用 WAN 数据
+ return { up: 'wide_tx_rate', down: 'wide_rx_rate' };
+ }
+
if (type === 'lan') return { up: 'local_tx_rate', down: 'local_rx_rate' };
if (type === 'wan') return { up: 'wide_tx_rate', down: 'wide_rx_rate' };
return { up: 'total_tx_rate', down: 'total_rx_rate' };
}
+ // 当前选择的时间范围
+ var currentTimeRange = localStorage.getItem('bandix_time_range') || 'realtime';
+
function fetchMetricsData(mac) {
+ // 根据选择的时间范围调用不同的接口
+ var range = currentTimeRange;
+ var callFunction;
+
+ switch (range) {
+ case 'day':
+ callFunction = callGetMetricsDay;
+ break;
+ case 'week':
+ callFunction = callGetMetricsWeek;
+ break;
+ case 'month':
+ callFunction = callGetMetricsMonth;
+ break;
+ case 'realtime':
+ default:
+ callFunction = callGetMetrics;
+ break;
+ }
+
// 通过 ubus RPC 获取,避免跨域与鉴权问题
- return callGetMetrics(mac || '').then(function (res) { return res || { metrics: [] }; });
+ return callFunction(mac || '').then(function (res) { return res || { metrics: [] }; });
+ }
+
+ // 将数组数组格式转换为对象数组格式(实时数据格式:13个字段)
+ // 输入格式: [[ts_ms, total_rx_rate, total_tx_rate, local_rx_rate, local_tx_rate, wide_rx_rate, wide_tx_rate, total_rx_bytes, total_tx_bytes, local_rx_bytes, local_tx_bytes, wide_rx_bytes, wide_tx_bytes], ...]
+ // 输出格式: [{ts_ms, total_rx_rate, total_tx_rate, ...}, ...]
+ function convertMetricsArrayToObjects(metricsArray) {
+ if (!Array.isArray(metricsArray)) {
+ return [];
+ }
+
+ return metricsArray.map(function(arr) {
+ // 检查数据格式:如果是15个字段,说明是 day/week/month 格式
+ if (arr.length >= 15) {
+ // day/week/month 格式:使用 P95 作为主要显示值
+ return {
+ ts_ms: arr[0] || 0,
+ // 使用 P95 作为主要速率显示(最有价值的指标)
+ wide_rx_rate: arr[5] || 0, // wide_rx_rate_p95
+ wide_tx_rate: arr[11] || 0, // wide_tx_rate_p95
+ // 保存所有统计信息供 tooltip 使用
+ wide_rx_rate_avg: arr[1] || 0,
+ wide_rx_rate_max: arr[2] || 0,
+ wide_rx_rate_min: arr[3] || 0,
+ wide_rx_rate_p90: arr[4] || 0,
+ wide_rx_rate_p95: arr[5] || 0,
+ wide_rx_rate_p99: arr[6] || 0,
+ wide_tx_rate_avg: arr[7] || 0,
+ wide_tx_rate_max: arr[8] || 0,
+ wide_tx_rate_min: arr[9] || 0,
+ wide_tx_rate_p90: arr[10] || 0,
+ wide_tx_rate_p95: arr[11] || 0,
+ wide_tx_rate_p99: arr[12] || 0,
+ wide_rx_bytes: arr[13] || 0,
+ wide_tx_bytes: arr[14] || 0,
+ // 标记这是聚合数据
+ is_aggregated: true,
+ // 为了兼容性,设置其他字段(day/week/month 只有 WAN 数据)
+ total_rx_rate: arr[5] || 0, // 使用 P95
+ total_tx_rate: arr[11] || 0, // 使用 P95
+ local_rx_rate: 0,
+ local_tx_rate: 0,
+ total_rx_bytes: arr[13] || 0,
+ total_tx_bytes: arr[14] || 0,
+ local_rx_bytes: 0,
+ local_tx_bytes: 0
+ };
+ } else {
+ // 实时数据格式(13个字段)
+ return {
+ ts_ms: arr[0] || 0,
+ total_rx_rate: arr[1] || 0,
+ total_tx_rate: arr[2] || 0,
+ local_rx_rate: arr[3] || 0,
+ local_tx_rate: arr[4] || 0,
+ wide_rx_rate: arr[5] || 0,
+ wide_tx_rate: arr[6] || 0,
+ total_rx_bytes: arr[7] || 0,
+ total_tx_bytes: arr[8] || 0,
+ local_rx_bytes: arr[9] || 0,
+ local_tx_bytes: arr[10] || 0,
+ wide_rx_bytes: arr[11] || 0,
+ wide_tx_bytes: arr[12] || 0,
+ is_aggregated: false
+ };
+ }
+ }).filter(function(item) { return item !== null; });
}
// 辅助函数:使用当前缩放设置绘制图表
@@ -2777,6 +2989,18 @@ return view.extend({
var ss = ('' + d.getSeconds()).padStart(2, '0');
return hh + ':' + mm + ':' + ss;
}
+
+ // 完整日期时间格式(用于聚合数据)
+ function msToFullDateTimeLabel(ts) {
+ var d = new Date(ts);
+ var year = d.getFullYear();
+ var month = ('' + (d.getMonth() + 1)).padStart(2, '0');
+ var day = ('' + d.getDate()).padStart(2, '0');
+ var hh = ('' + d.getHours()).padStart(2, '0');
+ var mm = ('' + d.getMinutes()).padStart(2, '0');
+ var ss = ('' + d.getSeconds()).padStart(2, '0');
+ return year + '-' + month + '-' + day + ' ' + hh + ':' + mm + ':' + ss;
+ }
function buildTooltipHtml(point) {
if (!point) return '';
@@ -2784,6 +3008,7 @@ return view.extend({
var typeSel = (typeof document !== 'undefined' ? document.getElementById('history-type-select') : null);
var selType = (typeSel && typeSel.value) ? typeSel.value : 'total';
var speedUnit = uci.get('bandix', 'traffic', 'speed_unit') || 'bytes';
+ var isAggregated = point.is_aggregated || false;
function row(label, val) {
lines.push('
' + label + '' + val + '
');
@@ -2815,64 +3040,99 @@ return view.extend({
return { up: 'total_tx_bytes', down: 'total_rx_bytes' };
}
- lines.push('' + msToTimeLabel(point.ts_ms) + '
');
-
- // 若选择了设备,显示设备信息
- try {
- var macSel = (typeof document !== 'undefined' ? document.getElementById('history-device-select') : null);
- var macVal = (macSel && macSel.value) ? macSel.value : '';
- if (macVal && Array.isArray(latestDevices)) {
- var dev = latestDevices.find(function(d){ return d.mac === macVal; });
- if (dev) {
- var ipv6Info = '';
- var lanIPv6 = filterLanIPv6(dev.ipv6_addresses);
- if (lanIPv6.length > 0) {
- ipv6Info = ' | IPv6: ' + lanIPv6.join(', ');
- }
- var devLabel = (dev.hostname || '-') + (dev.ip ? ' (' + dev.ip + ')' : '') + (dev.mac ? ' [' + dev.mac + ']' : '') + ipv6Info;
- lines.push('' + _('Device') + ': ' + devLabel + '
');
- }
+ // 标题:聚合数据显示完整日期时间,实时数据只显示时间
+ if (isAggregated) {
+ lines.push('' + msToFullDateTimeLabel(point.ts_ms) + '
');
+ var rangeLabel = currentTimeRange === 'day' ? _('Daily') :
+ currentTimeRange === 'week' ? _('Weekly') :
+ currentTimeRange === 'month' ? _('Monthly') : '';
+ if (rangeLabel) {
+ lines.push('' + rangeLabel + ' ' + _('Statistics') + '
');
}
- } catch (e) {}
+ } else {
+ lines.push('' + msToTimeLabel(point.ts_ms) + '
');
+ }
// 关键信息:选中类型的上下行速率(大号显示)
var kpiLabels = labelsFor(selType);
var kpiRateKeys = rateKeysFor(selType);
- lines.push(
- '' +
- '
' +
- '
' + kpiLabels.up + '
' +
- '
' + rateValue(kpiRateKeys.up) + '
' +
- '
' +
- '
' +
- '
' + kpiLabels.down + '
' +
- '
' + rateValue(kpiRateKeys.down) + '
' +
- '
' +
- '
'
- );
+
+ if (isAggregated) {
+ // 聚合数据:显示 P95 值(主要指标)
+ lines.push(
+ '' +
+ '
' +
+ '
' + _('WAN Upload') + ' (P95)
' +
+ '
' + formatByterate(point.wide_tx_rate_p95 || 0, speedUnit) + '
' +
+ '
' +
+ '
' +
+ '
' + _('WAN Download') + ' (P95)
' +
+ '
' + formatByterate(point.wide_rx_rate_p95 || 0, speedUnit) + '
' +
+ '
' +
+ '
'
+ );
+
+ // 详细统计信息
+ lines.push('');
+ lines.push('' + _('Upload Statistics') + '
');
+ row(_('Average'), formatByterate(point.wide_tx_rate_avg || 0, speedUnit));
+ row(_('Maximum'), formatByterate(point.wide_tx_rate_max || 0, speedUnit));
+ row(_('Minimum'), formatByterate(point.wide_tx_rate_min || 0, speedUnit));
+ row('P90', formatByterate(point.wide_tx_rate_p90 || 0, speedUnit));
+ row('P95', formatByterate(point.wide_tx_rate_p95 || 0, speedUnit));
+ row('P99', formatByterate(point.wide_tx_rate_p99 || 0, speedUnit));
+
+ lines.push('' + _('Download Statistics') + '
');
+ row(_('Average'), formatByterate(point.wide_rx_rate_avg || 0, speedUnit));
+ row(_('Maximum'), formatByterate(point.wide_rx_rate_max || 0, speedUnit));
+ row(_('Minimum'), formatByterate(point.wide_rx_rate_min || 0, speedUnit));
+ row('P90', formatByterate(point.wide_rx_rate_p90 || 0, speedUnit));
+ row('P95', formatByterate(point.wide_rx_rate_p95 || 0, speedUnit));
+ row('P99', formatByterate(point.wide_rx_rate_p99 || 0, speedUnit));
+
+ // 累计流量(只显示 WAN)
+ lines.push('');
+ lines.push('' + _('Cumulative Traffic') + '
');
+ row(_('WAN Uploaded'), bytesValue('wide_tx_bytes'));
+ row(_('WAN Downloaded'), bytesValue('wide_rx_bytes'));
+ } else {
+ // 实时数据:显示实时速率
+ lines.push(
+ '' +
+ '
' +
+ '
' + kpiLabels.up + '
' +
+ '
' + rateValue(kpiRateKeys.up) + '
' +
+ '
' +
+ '
' +
+ '
' + kpiLabels.down + '
' +
+ '
' + rateValue(kpiRateKeys.down) + '
' +
+ '
' +
+ '
'
+ );
- // 次要信息:其余类型的速率(精简展示)
- var otherTypes = ['total', 'lan', 'wan'].filter(function (t) { return t !== selType; });
- if (otherTypes.length) {
- lines.push('' + _('Other Rates') + '
');
- otherTypes.forEach(function (t) {
- var lbs = labelsFor(t);
- var ks = rateKeysFor(t);
- row(lbs.up, rateValue(ks.up));
- row(lbs.down, rateValue(ks.down));
- });
+ // 次要信息:其余类型的速率(精简展示)
+ var otherTypes = ['total', 'lan', 'wan'].filter(function (t) { return t !== selType; });
+ if (otherTypes.length) {
+ lines.push('' + _('Other Rates') + '
');
+ otherTypes.forEach(function (t) {
+ var lbs = labelsFor(t);
+ var ks = rateKeysFor(t);
+ row(lbs.up, rateValue(ks.up));
+ row(lbs.down, rateValue(ks.down));
+ });
+ }
+
+ // 累计:区分LAN 流量与公网
+ lines.push('');
+ lines.push('' + _('Cumulative') + '
');
+ row(_('Total Uploaded'), bytesValue('total_tx_bytes'));
+ row(_('Total Downloaded'), bytesValue('total_rx_bytes'));
+ row(_('LAN Uploaded'), bytesValue('local_tx_bytes'));
+ row(_('LAN Downloaded'), bytesValue('local_rx_bytes'));
+ row(_('WAN Uploaded'), bytesValue('wide_tx_bytes'));
+ row(_('WAN Downloaded'), bytesValue('wide_rx_bytes'));
}
- // 累计:区分LAN 流量与公网
- lines.push('');
- lines.push('' + _('Cumulative') + '
');
- row(_('Total Uploaded'), bytesValue('total_tx_bytes'));
- row(_('Total Downloaded'), bytesValue('total_rx_bytes'));
- row(_('LAN Uploaded'), bytesValue('local_tx_bytes'));
- row(_('LAN Downloaded'), bytesValue('local_rx_bytes'));
- row(_('WAN Uploaded'), bytesValue('wide_tx_bytes'));
- row(_('WAN Downloaded'), bytesValue('wide_rx_bytes'));
-
return lines.join('');
}
@@ -3236,7 +3496,9 @@ function downsampleForMobile(data, labels, upSeries, downSeries, maxPoints) {
return fetchMetricsData(mac).then(function (res) {
- var data = Array.isArray(res && res.metrics) ? res.metrics.slice() : [];
+ // 将数组数组格式转换为对象数组格式
+ var rawMetrics = res && res.metrics ? res.metrics : [];
+ var data = convertMetricsArrayToObjects(rawMetrics);
lastHistoryData = data;
var retentionBadge = document.getElementById('history-retention');
@@ -3603,14 +3865,99 @@ function downsampleForMobile(data, labels, upSeries, downSeries, maxPoints) {
});
}
- // 历史趋势:事件绑定
- (function initHistoryControls() {
+ // 历史趋势:事件绑定(延迟执行以确保 DOM 已加载)
+ function initHistoryControls() {
var typeSel = document.getElementById('history-type-select');
var devSel = document.getElementById('history-device-select');
if (typeSel) typeSel.value = 'total';
// 初始化缩放倍率显示
updateZoomLevelDisplay();
+
+ // Tab 切换事件处理
+ var tabButtons = document.querySelectorAll('.history-tab');
+
+ // 确保找到了 tab 按钮
+ if (tabButtons.length === 0) {
+ console.warn('History tab buttons not found, retrying...');
+ setTimeout(initHistoryControls, 100);
+ return;
+ }
+
+ tabButtons.forEach(function(btn) {
+ btn.addEventListener('click', function() {
+ var range = this.getAttribute('data-range');
+
+ // 更新当前选择的时间范围
+ currentTimeRange = range;
+ localStorage.setItem('bandix_time_range', range);
+
+ // 更新 tab 状态
+ tabButtons.forEach(function(b) {
+ b.classList.remove('active');
+ });
+ this.classList.add('active');
+
+ // 对于非实时时间范围,禁用 LAN 和 Total 选项(因为只有 WAN 数据)
+ if (range !== 'realtime') {
+ if (typeSel) {
+ // 如果当前选择的是 LAN 或 Total,切换到 WAN
+ if (typeSel.value === 'lan' || typeSel.value === 'total') {
+ typeSel.value = 'wan';
+ }
+ // 禁用 LAN 和 Total 选项
+ var lanOption = typeSel.querySelector('option[value="lan"]');
+ var totalOption = typeSel.querySelector('option[value="total"]');
+ if (lanOption) lanOption.disabled = true;
+ if (totalOption) totalOption.disabled = true;
+ }
+ } else {
+ // 实时模式下,启用所有选项
+ if (typeSel) {
+ var lanOption = typeSel.querySelector('option[value="lan"]');
+ var totalOption = typeSel.querySelector('option[value="total"]');
+ if (lanOption) lanOption.disabled = false;
+ if (totalOption) totalOption.disabled = false;
+ }
+ }
+
+ // 刷新历史数据
+ refreshHistory();
+ });
+ });
+
+ // 恢复之前选择的时间范围
+ var savedRange = localStorage.getItem('bandix_time_range') || 'realtime';
+
+ // 移动端强制使用 realtime
+ var screenWidth = window.innerWidth || document.documentElement.clientWidth;
+ var isMobileScreen = screenWidth <= 768;
+ if (isMobileScreen) {
+ savedRange = 'realtime';
+ currentTimeRange = 'realtime';
+ localStorage.setItem('bandix_time_range', 'realtime');
+ } else {
+ currentTimeRange = savedRange;
+ }
+
+ tabButtons.forEach(function(btn) {
+ if (btn.getAttribute('data-range') === savedRange) {
+ btn.classList.add('active');
+ // 触发一次点击以应用选项禁用逻辑
+ if (savedRange !== 'realtime' && typeSel) {
+ var lanOption = typeSel.querySelector('option[value="lan"]');
+ var totalOption = typeSel.querySelector('option[value="total"]');
+ if (lanOption) lanOption.disabled = true;
+ if (totalOption) totalOption.disabled = true;
+ if (typeSel.value === 'lan' || typeSel.value === 'total') {
+ typeSel.value = 'wan';
+ }
+ }
+ } else {
+ btn.classList.remove('active');
+ }
+ });
+
function onFilterChange() {
refreshHistory();
// 同步刷新表格(立即生效,不等轮询)
@@ -3626,12 +3973,16 @@ function downsampleForMobile(data, labels, upSeries, downSeries, maxPoints) {
// 首次加载
refreshHistory();
- })();
+ }
+
+ // 延迟执行以确保 DOM 已加载
+ setTimeout(initHistoryControls, 0);
- // 历史趋势轮询(每1秒)
+ // 历史趋势轮询(实时数据每1秒,其他时间范围每30秒)
+ // 使用 poll.add 但根据时间范围动态调整
poll.add(function () {
return refreshHistory();
- },1);
+ }, 1);
diff --git a/luci-app-bandix/htdocs/luci-static/resources/view/bandix/settings.js b/luci-app-bandix/htdocs/luci-static/resources/view/bandix/settings.js
index 54f1258..66042fc 100644
--- a/luci-app-bandix/htdocs/luci-static/resources/view/bandix/settings.js
+++ b/luci-app-bandix/htdocs/luci-static/resources/view/bandix/settings.js
@@ -3,11 +3,24 @@
'require form';
'require ui';
'require uci';
-'require fs';
+'require rpc';
// 暗色模式检测已改为使用 CSS 媒体查询 @media (prefers-color-scheme: dark)
+// 声明 RPC 调用方法
+var callClearData = rpc.declare({
+ object: 'luci.bandix',
+ method: 'clearData',
+ expect: { }
+});
+
+var callRestartService = rpc.declare({
+ object: 'luci.bandix',
+ method: 'restartService',
+ expect: { }
+});
+
return view.extend({
load: function () {
return Promise.all([
@@ -108,14 +121,78 @@ return view.extend({
return uci.get('bandix', section_id, 'data_dir') || '/usr/share/bandix';
};
- // 添加意见反馈信息
- o = s.option(form.DummyValue, 'feedback_info', _('Feedback'));
- o.href = 'https://github.com/timsaya';
- o.cfgvalue = function () {
- return 'https://github.com/timsaya';
- };
+ // 添加意见反馈信息
+ o = s.option(form.DummyValue, 'feedback_info', _('Feedback'));
+ o.href = 'https://github.com/timsaya';
+ o.cfgvalue = function () {
+ return 'https://github.com/timsaya';
+ };
- // 2. 流量监控设置部分 (traffic)
+ // 添加清空数据按钮
+ o = s.option(form.Button, 'clear_data', _('Clear Traffic Data'));
+ o.inputtitle = _('Clear Traffic Data');
+ o.inputstyle = 'reset';
+ o.onclick = function () {
+ return ui.showModal(_('Clear Traffic Data'), [
+ E('p', _('Are you sure you want to clear all traffic data? This action cannot be undone.')),
+ E('div', { 'class': 'right' }, [
+ E('button', {
+ 'class': 'btn',
+ 'click': ui.hideModal
+ }, _('Cancel')),
+ ' ',
+ E('button', {
+ 'class': 'btn cbi-button-negative',
+ 'click': function () {
+ ui.hideModal();
+ return callClearData()
+ .then(function (result) {
+ if (result && !result.success) {
+ ui.addNotification(null, E('p', _('Failed to clear traffic data: ') + (result.error || 'Unknown error')), 'error');
+ }
+ })
+ .catch(function (err) {
+ ui.addNotification(null, E('p', _('Failed to clear traffic data: ') + err.message), 'error');
+ });
+ }
+ }, _('Confirm'))
+ ])
+ ]);
+ };
+
+ // 添加重启服务按钮
+ o = s.option(form.Button, 'restart_service', _('Restart Service'));
+ o.inputtitle = _('Restart Bandix Service');
+ o.inputstyle = 'apply';
+ o.onclick = function () {
+ return ui.showModal(_('Restart Service'), [
+ E('p', _('Are you sure you want to restart the Bandix service?')),
+ E('div', { 'class': 'right' }, [
+ E('button', {
+ 'class': 'btn',
+ 'click': ui.hideModal
+ }, _('Cancel')),
+ ' ',
+ E('button', {
+ 'class': 'btn cbi-button-action',
+ 'click': function () {
+ ui.hideModal();
+ return callRestartService()
+ .then(function (result) {
+ if (result && !result.success) {
+ ui.addNotification(null, E('p', _('Failed to restart service: ') + (result.error || 'Unknown error')), 'error');
+ }
+ })
+ .catch(function (err) {
+ ui.addNotification(null, E('p', _('Failed to restart service: ') + err.message), 'error');
+ });
+ }
+ }, _('Confirm'))
+ ])
+ ]);
+ };
+
+ // 2. 流量监控设置部分 (traffic)
s = m.section(form.NamedSection, 'traffic', 'traffic', _('Traffic Monitor Settings'));
s.description = _('Configure traffic monitoring related parameters');
s.addremove = false;
@@ -147,6 +224,7 @@ return view.extend({
o.default = '0';
o.rmempty = false;
+
// 添加数据 flush 间隔(秒)
o = s.option(form.ListValue, 'traffic_flush_interval_seconds', _('Data Flush Interval'),
_('Set the interval for flushing data to disk'));
@@ -166,13 +244,10 @@ return view.extend({
// 添加历史流量周期(秒)
o = s.option(form.ListValue, 'traffic_retention_seconds', _('Traffic History Period'),
_('10 minutes interval uses about 60 KB per device'));
- o.value('60', _('1 minute'));
- o.value('300', _('5 minutes'));
o.value('600', _('10 minutes'));
o.value('900', _('15 minutes'));
- o.value('1200', _('20 minutes'));
- o.value('1500', _('25 minutes'));
o.value('1800', _('30 minutes'));
+ o.value('3600', _('1 hour'));
o.default = '600';
o.rmempty = false;
diff --git a/luci-app-bandix/po/es/bandix.po b/luci-app-bandix/po/es/bandix.po
index e965242..ff28dee 100644
--- a/luci-app-bandix/po/es/bandix.po
+++ b/luci-app-bandix/po/es/bandix.po
@@ -841,3 +841,66 @@ msgstr "Sin regla activa"
msgid "Schedule Rules"
msgstr "Reglas de limitación programada"
+
+msgid "Upload Statistics"
+msgstr "Estadísticas de subida"
+
+msgid "Download Statistics"
+msgstr "Estadísticas de descarga"
+
+msgid "Cumulative Traffic"
+msgstr "Tráfico acumulado"
+
+msgid "Daily"
+msgstr "Diario"
+
+msgid "Weekly"
+msgstr "Semanal"
+
+msgid "Monthly"
+msgstr "Mensual"
+
+msgid "Statistics"
+msgstr "Estadísticas"
+
+msgid "Average"
+msgstr "Promedio"
+
+msgid "Maximum"
+msgstr "Máximo"
+
+msgid "Minimum"
+msgstr "Mínimo"
+
+msgid "WAN Upload"
+msgstr "Subida WAN"
+
+msgid "WAN Download"
+msgstr "Descarga WAN"
+
+msgid "WAN Uploaded"
+msgstr "Subido WAN"
+
+msgid "WAN Downloaded"
+msgstr "Descargado WAN"
+
+msgid "Clear Traffic Data"
+msgstr "Borrar datos de tráfico"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "¿Está seguro de que desea borrar todos los datos de tráfico? Esta acción no se puede deshacer."
+
+msgid "Failed to clear traffic data: "
+msgstr "Error al borrar los datos de tráfico: "
+
+msgid "Restart Service"
+msgstr "Reiniciar servicio"
+
+msgid "Restart Bandix Service"
+msgstr "Reiniciar servicio Bandix"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "¿Está seguro de que desea reiniciar el servicio Bandix?"
+
+msgid "Failed to restart service: "
+msgstr "Error al reiniciar el servicio: "
diff --git a/luci-app-bandix/po/fr/bandix.po b/luci-app-bandix/po/fr/bandix.po
index 658f76c..796bbc6 100644
--- a/luci-app-bandix/po/fr/bandix.po
+++ b/luci-app-bandix/po/fr/bandix.po
@@ -840,4 +840,67 @@ msgid "No active rule"
msgstr "Aucune règle active"
msgid "Schedule Rules"
-msgstr "Règles de limitation programmée"
\ No newline at end of file
+msgstr "Règles de limitation programmée"
+
+msgid "Upload Statistics"
+msgstr "Statistiques d'envoi"
+
+msgid "Download Statistics"
+msgstr "Statistiques de téléchargement"
+
+msgid "Cumulative Traffic"
+msgstr "Trafic cumulé"
+
+msgid "Daily"
+msgstr "Quotidien"
+
+msgid "Weekly"
+msgstr "Hebdomadaire"
+
+msgid "Monthly"
+msgstr "Mensuel"
+
+msgid "Statistics"
+msgstr "Statistiques"
+
+msgid "Average"
+msgstr "Moyenne"
+
+msgid "Maximum"
+msgstr "Maximum"
+
+msgid "Minimum"
+msgstr "Minimum"
+
+msgid "WAN Upload"
+msgstr "Envoi WAN"
+
+msgid "WAN Download"
+msgstr "Téléchargement WAN"
+
+msgid "WAN Uploaded"
+msgstr "Envoyé WAN"
+
+msgid "WAN Downloaded"
+msgstr "Téléchargé WAN"
+
+msgid "Clear Traffic Data"
+msgstr "Effacer les données de trafic"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "Êtes-vous sûr de vouloir effacer toutes les données de trafic ? Cette action est irréversible."
+
+msgid "Failed to clear traffic data: "
+msgstr "Échec de l'effacement des données de trafic : "
+
+msgid "Restart Service"
+msgstr "Redémarrer le service"
+
+msgid "Restart Bandix Service"
+msgstr "Redémarrer le service Bandix"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "Êtes-vous sûr de vouloir redémarrer le service Bandix ?"
+
+msgid "Failed to restart service: "
+msgstr "Échec du redémarrage du service : "
\ No newline at end of file
diff --git a/luci-app-bandix/po/id/bandix.po b/luci-app-bandix/po/id/bandix.po
index 0c70d35..293f29d 100644
--- a/luci-app-bandix/po/id/bandix.po
+++ b/luci-app-bandix/po/id/bandix.po
@@ -841,3 +841,66 @@ msgstr "Tidak ada aturan aktif"
msgid "Schedule Rules"
msgstr "Aturan pembatasan terjadwal"
+
+msgid "Upload Statistics"
+msgstr "Statistik unggahan"
+
+msgid "Download Statistics"
+msgstr "Statistik unduhan"
+
+msgid "Cumulative Traffic"
+msgstr "Lalu lintas kumulatif"
+
+msgid "Daily"
+msgstr "Harian"
+
+msgid "Weekly"
+msgstr "Mingguan"
+
+msgid "Monthly"
+msgstr "Bulanan"
+
+msgid "Statistics"
+msgstr "Statistik"
+
+msgid "Average"
+msgstr "Rata-rata"
+
+msgid "Maximum"
+msgstr "Maksimum"
+
+msgid "Minimum"
+msgstr "Minimum"
+
+msgid "WAN Upload"
+msgstr "Unggahan WAN"
+
+msgid "WAN Download"
+msgstr "Unduhan WAN"
+
+msgid "WAN Uploaded"
+msgstr "Diunggah WAN"
+
+msgid "WAN Downloaded"
+msgstr "Diunduh WAN"
+
+msgid "Clear Traffic Data"
+msgstr "Hapus Data Lalu Lintas"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "Apakah Anda yakin ingin menghapus semua data lalu lintas? Tindakan ini tidak dapat dibatalkan."
+
+msgid "Failed to clear traffic data: "
+msgstr "Gagal menghapus data lalu lintas: "
+
+msgid "Restart Service"
+msgstr "Mulai Ulang Layanan"
+
+msgid "Restart Bandix Service"
+msgstr "Mulai Ulang Layanan Bandix"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "Apakah Anda yakin ingin memulai ulang layanan Bandix?"
+
+msgid "Failed to restart service: "
+msgstr "Gagal memulai ulang layanan: "
diff --git a/luci-app-bandix/po/ja/bandix.po b/luci-app-bandix/po/ja/bandix.po
index 7a1c54b..8b5abc4 100644
--- a/luci-app-bandix/po/ja/bandix.po
+++ b/luci-app-bandix/po/ja/bandix.po
@@ -841,3 +841,66 @@ msgstr "アクティブなルールなし"
msgid "Schedule Rules"
msgstr "スケジュール制限ルール"
+
+msgid "Upload Statistics"
+msgstr "アップロード統計"
+
+msgid "Download Statistics"
+msgstr "ダウンロード統計"
+
+msgid "Cumulative Traffic"
+msgstr "累積トラフィック"
+
+msgid "Daily"
+msgstr "日次"
+
+msgid "Weekly"
+msgstr "週次"
+
+msgid "Monthly"
+msgstr "月次"
+
+msgid "Statistics"
+msgstr "統計"
+
+msgid "Average"
+msgstr "平均"
+
+msgid "Maximum"
+msgstr "最大"
+
+msgid "Minimum"
+msgstr "最小"
+
+msgid "WAN Upload"
+msgstr "WAN アップロード"
+
+msgid "WAN Download"
+msgstr "WAN ダウンロード"
+
+msgid "WAN Uploaded"
+msgstr "WAN アップロード量"
+
+msgid "WAN Downloaded"
+msgstr "WAN ダウンロード量"
+
+msgid "Clear Traffic Data"
+msgstr "トラフィックデータを削除"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "すべてのトラフィックデータを削除してもよろしいですか?この操作は元に戻せません。"
+
+msgid "Failed to clear traffic data: "
+msgstr "トラフィックデータの削除に失敗しました:"
+
+msgid "Restart Service"
+msgstr "サービス再起動"
+
+msgid "Restart Bandix Service"
+msgstr "Bandix サービスを再起動"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "Bandix サービスを再起動してもよろしいですか?"
+
+msgid "Failed to restart service: "
+msgstr "サービスの再起動に失敗しました:"
diff --git a/luci-app-bandix/po/pl/bandix.po b/luci-app-bandix/po/pl/bandix.po
index 5abe740..491fd3c 100644
--- a/luci-app-bandix/po/pl/bandix.po
+++ b/luci-app-bandix/po/pl/bandix.po
@@ -842,3 +842,66 @@ msgstr "Brak aktywnej reguły"
msgid "Schedule Rules"
msgstr "Reguły limitu czasu"
+msgid "Upload Statistics"
+msgstr "Statystyki wysyłania"
+
+msgid "Download Statistics"
+msgstr "Statystyki pobierania"
+
+msgid "Cumulative Traffic"
+msgstr "Skumulowany ruch"
+
+msgid "Daily"
+msgstr "Dzienny"
+
+msgid "Weekly"
+msgstr "Tygodniowy"
+
+msgid "Monthly"
+msgstr "Miesięczny"
+
+msgid "Statistics"
+msgstr "Statystyki"
+
+msgid "Average"
+msgstr "Średnia"
+
+msgid "Maximum"
+msgstr "Maksimum"
+
+msgid "Minimum"
+msgstr "Minimum"
+
+msgid "WAN Upload"
+msgstr "Wysyłanie WAN"
+
+msgid "WAN Download"
+msgstr "Pobieranie WAN"
+
+msgid "WAN Uploaded"
+msgstr "Wysłano WAN"
+
+msgid "WAN Downloaded"
+msgstr "Pobrano WAN"
+
+msgid "Clear Traffic Data"
+msgstr "Wyczyść dane ruchu"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "Czy na pewno chcesz wyczyścić wszystkie dane ruchu? Tej operacji nie można cofnąć."
+
+msgid "Failed to clear traffic data: "
+msgstr "Nie udało się wyczyścić danych ruchu: "
+
+msgid "Restart Service"
+msgstr "Uruchom ponownie usługę"
+
+msgid "Restart Bandix Service"
+msgstr "Uruchom ponownie usługę Bandix"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "Czy na pewno chcesz uruchomić ponownie usługę Bandix?"
+
+msgid "Failed to restart service: "
+msgstr "Nie udało się uruchomić ponownie usługi: "
+
diff --git a/luci-app-bandix/po/ru/bandix.po b/luci-app-bandix/po/ru/bandix.po
index 29401e5..697a002 100644
--- a/luci-app-bandix/po/ru/bandix.po
+++ b/luci-app-bandix/po/ru/bandix.po
@@ -840,4 +840,67 @@ msgid "No active rule"
msgstr "Нет активных правил"
msgid "Schedule Rules"
-msgstr "Правила ограничения по расписанию"
\ No newline at end of file
+msgstr "Правила ограничения по расписанию"
+
+msgid "Upload Statistics"
+msgstr "Статистика отправки"
+
+msgid "Download Statistics"
+msgstr "Статистика загрузки"
+
+msgid "Cumulative Traffic"
+msgstr "Накопительный трафик"
+
+msgid "Daily"
+msgstr "Ежедневно"
+
+msgid "Weekly"
+msgstr "Еженедельно"
+
+msgid "Monthly"
+msgstr "Ежемесячно"
+
+msgid "Statistics"
+msgstr "Статистика"
+
+msgid "Average"
+msgstr "Среднее"
+
+msgid "Maximum"
+msgstr "Максимум"
+
+msgid "Minimum"
+msgstr "Минимум"
+
+msgid "WAN Upload"
+msgstr "Отправка WAN"
+
+msgid "WAN Download"
+msgstr "Загрузка WAN"
+
+msgid "WAN Uploaded"
+msgstr "Отправлено WAN"
+
+msgid "WAN Downloaded"
+msgstr "Загружено WAN"
+
+msgid "Clear Traffic Data"
+msgstr "Очистить данные трафика"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "Вы уверены, что хотите очистить все данные трафика? Это действие нельзя отменить."
+
+msgid "Failed to clear traffic data: "
+msgstr "Не удалось очистить данные трафика: "
+
+msgid "Restart Service"
+msgstr "Перезапустить службу"
+
+msgid "Restart Bandix Service"
+msgstr "Перезапустить службу Bandix"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "Вы уверены, что хотите перезапустить службу Bandix?"
+
+msgid "Failed to restart service: "
+msgstr "Не удалось перезапустить службу: "
\ No newline at end of file
diff --git a/luci-app-bandix/po/th/bandix.po b/luci-app-bandix/po/th/bandix.po
index aed52d4..68af5d0 100644
--- a/luci-app-bandix/po/th/bandix.po
+++ b/luci-app-bandix/po/th/bandix.po
@@ -841,3 +841,66 @@ msgstr "ไม่มีกฎที่ใช้งาน"
msgid "Schedule Rules"
msgstr "กฎการจำกัดอัตราแบบกำหนดเวลา"
+
+msgid "Upload Statistics"
+msgstr "สถิติการอัปโหลด"
+
+msgid "Download Statistics"
+msgstr "สถิติการดาวน์โหลด"
+
+msgid "Cumulative Traffic"
+msgstr "ปริมาณการใช้งานสะสม"
+
+msgid "Daily"
+msgstr "รายวัน"
+
+msgid "Weekly"
+msgstr "รายสัปดาห์"
+
+msgid "Monthly"
+msgstr "รายเดือน"
+
+msgid "Statistics"
+msgstr "สถิติ"
+
+msgid "Average"
+msgstr "ค่าเฉลี่ย"
+
+msgid "Maximum"
+msgstr "สูงสุด"
+
+msgid "Minimum"
+msgstr "ต่ำสุด"
+
+msgid "WAN Upload"
+msgstr "อัปโหลด WAN"
+
+msgid "WAN Download"
+msgstr "ดาวน์โหลด WAN"
+
+msgid "WAN Uploaded"
+msgstr "อัปโหลด WAN แล้ว"
+
+msgid "WAN Downloaded"
+msgstr "ดาวน์โหลด WAN แล้ว"
+
+msgid "Clear Traffic Data"
+msgstr "ลบข้อมูลทราฟฟิก"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "คุณแน่ใจหรือไม่ว่าต้องการลบข้อมูลทราฟฟิกทั้งหมด? การกระทำนี้ไม่สามารถยกเลิกได้"
+
+msgid "Failed to clear traffic data: "
+msgstr "ล้มเหลวในการลบข้อมูลทราฟฟิก: "
+
+msgid "Restart Service"
+msgstr "รีสตาร์ทบริการ"
+
+msgid "Restart Bandix Service"
+msgstr "รีสตาร์ทบริการ Bandix"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "คุณแน่ใจหรือไม่ว่าต้องการรีสตาร์ทบริการ Bandix?"
+
+msgid "Failed to restart service: "
+msgstr "ล้มเหลวในการรีสตาร์ทบริการ: "
diff --git a/luci-app-bandix/po/zh_Hans/bandix.po b/luci-app-bandix/po/zh_Hans/bandix.po
index 42859e0..369a9d9 100644
--- a/luci-app-bandix/po/zh_Hans/bandix.po
+++ b/luci-app-bandix/po/zh_Hans/bandix.po
@@ -840,4 +840,67 @@ msgid "No active rule"
msgstr "无生效规则"
msgid "Schedule Rules"
-msgstr "定时限速规则"
\ No newline at end of file
+msgstr "定时限速规则"
+
+msgid "Upload Statistics"
+msgstr "上传统计"
+
+msgid "Download Statistics"
+msgstr "下载统计"
+
+msgid "Cumulative Traffic"
+msgstr "累计流量"
+
+msgid "Daily"
+msgstr "每日"
+
+msgid "Weekly"
+msgstr "每周"
+
+msgid "Monthly"
+msgstr "每月"
+
+msgid "Statistics"
+msgstr "统计"
+
+msgid "Average"
+msgstr "平均值"
+
+msgid "Maximum"
+msgstr "最大值"
+
+msgid "Minimum"
+msgstr "最小值"
+
+msgid "WAN Upload"
+msgstr "WAN 上传"
+
+msgid "WAN Download"
+msgstr "WAN 下载"
+
+msgid "WAN Uploaded"
+msgstr "WAN 上传量"
+
+msgid "WAN Downloaded"
+msgstr "WAN 下载量"
+
+msgid "Clear Traffic Data"
+msgstr "删除流量数据"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "确定要清除所有流量数据吗?此操作无法撤销。"
+
+msgid "Failed to clear traffic data: "
+msgstr "清除流量数据失败:"
+
+msgid "Restart Service"
+msgstr "重启服务"
+
+msgid "Restart Bandix Service"
+msgstr "重启 Bandix 服务"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "确定要重启 Bandix 服务吗?"
+
+msgid "Failed to restart service: "
+msgstr "重启服务失败:"
\ No newline at end of file
diff --git a/luci-app-bandix/po/zh_Hant/bandix.po b/luci-app-bandix/po/zh_Hant/bandix.po
index ec598d2..f34822c 100644
--- a/luci-app-bandix/po/zh_Hant/bandix.po
+++ b/luci-app-bandix/po/zh_Hant/bandix.po
@@ -840,4 +840,67 @@ msgid "No active rule"
msgstr "無生效規則"
msgid "Schedule Rules"
-msgstr "定時限速規則"
\ No newline at end of file
+msgstr "定時限速規則"
+
+msgid "Upload Statistics"
+msgstr "上傳統計"
+
+msgid "Download Statistics"
+msgstr "下載統計"
+
+msgid "Cumulative Traffic"
+msgstr "累計流量"
+
+msgid "Daily"
+msgstr "每日"
+
+msgid "Weekly"
+msgstr "每週"
+
+msgid "Monthly"
+msgstr "每月"
+
+msgid "Statistics"
+msgstr "統計"
+
+msgid "Average"
+msgstr "平均值"
+
+msgid "Maximum"
+msgstr "最大值"
+
+msgid "Minimum"
+msgstr "最小值"
+
+msgid "WAN Upload"
+msgstr "WAN 上傳"
+
+msgid "WAN Download"
+msgstr "WAN 下載"
+
+msgid "WAN Uploaded"
+msgstr "WAN 上傳量"
+
+msgid "WAN Downloaded"
+msgstr "WAN 下載量"
+
+msgid "Clear Traffic Data"
+msgstr "刪除流量數據"
+
+msgid "Are you sure you want to clear all traffic data? This action cannot be undone."
+msgstr "確定要清除所有流量數據嗎?此操作無法撤銷。"
+
+msgid "Failed to clear traffic data: "
+msgstr "清除流量數據失敗:"
+
+msgid "Restart Service"
+msgstr "重啟服務"
+
+msgid "Restart Bandix Service"
+msgstr "重啟 Bandix 服務"
+
+msgid "Are you sure you want to restart the Bandix service?"
+msgstr "確定要重啟 Bandix 服務嗎?"
+
+msgid "Failed to restart service: "
+msgstr "重啟服務失敗:"
\ No newline at end of file
diff --git a/luci-app-bandix/root/usr/libexec/rpcd/luci.bandix b/luci-app-bandix/root/usr/libexec/rpcd/luci.bandix
index 4459919..144d13a 100755
--- a/luci-app-bandix/root/usr/libexec/rpcd/luci.bandix
+++ b/luci-app-bandix/root/usr/libexec/rpcd/luci.bandix
@@ -9,6 +9,9 @@ readonly BANDIX_API_BASE="http://127.0.0.1:$BANDIX_PORT"
readonly BANDIX_DEVICES_API="$BANDIX_API_BASE/api/traffic/devices"
readonly BANDIX_LIMITS_API="$BANDIX_API_BASE/api/traffic/limits"
readonly BANDIX_METRICS_API="$BANDIX_API_BASE/api/traffic/metrics"
+readonly BANDIX_METRICS_DAY_API="$BANDIX_API_BASE/api/traffic/metrics/day"
+readonly BANDIX_METRICS_WEEK_API="$BANDIX_API_BASE/api/traffic/metrics/week"
+readonly BANDIX_METRICS_MONTH_API="$BANDIX_API_BASE/api/traffic/metrics/month"
readonly BANDIX_CONNECTION_API="$BANDIX_API_BASE/api/connection/devices"
readonly BANDIX_DNS_QUERIES_API="$BANDIX_API_BASE/api/dns/queries"
readonly BANDIX_DNS_STATS_API="$BANDIX_API_BASE/api/dns/stats"
@@ -99,6 +102,90 @@ get_metrics() {
fi
}
+# 获取日指标(可选MAC)
+get_metrics_day() {
+ local mac="$1"
+ local url="$BANDIX_METRICS_DAY_API"
+ if [ -n "$mac" ]; then
+ # 转义MAC
+ local mac_escaped=$(echo "$mac" | sed 's/\//\\\//g')
+ url="$url?mac=$mac_escaped"
+ fi
+
+ local api_result=$(curl -s --connect-timeout 2 --max-time 10 "$url" 2>/dev/null)
+ local curl_exit_code=$?
+
+ if [ $curl_exit_code -ne 0 ] || [ -z "$api_result" ]; then
+ echo '{"retention_seconds":86400,"mac":"","metrics":[]}'
+ return
+ fi
+
+ # 使用 jsonfilter 提取 data 部分
+ local data_part=$(echo "$api_result" | jsonfilter -e '$.data' 2>/dev/null)
+ if [ -n "$data_part" ]; then
+ echo "$data_part"
+ return
+ else
+ echo '{"retention_seconds":86400,"mac":"","metrics":[]}'
+ fi
+}
+
+# 获取周指标(可选MAC)
+get_metrics_week() {
+ local mac="$1"
+ local url="$BANDIX_METRICS_WEEK_API"
+ if [ -n "$mac" ]; then
+ # 转义MAC
+ local mac_escaped=$(echo "$mac" | sed 's/\//\\\//g')
+ url="$url?mac=$mac_escaped"
+ fi
+
+ local api_result=$(curl -s --connect-timeout 2 --max-time 10 "$url" 2>/dev/null)
+ local curl_exit_code=$?
+
+ if [ $curl_exit_code -ne 0 ] || [ -z "$api_result" ]; then
+ echo '{"retention_seconds":604800,"mac":"","metrics":[]}'
+ return
+ fi
+
+ # 使用 jsonfilter 提取 data 部分
+ local data_part=$(echo "$api_result" | jsonfilter -e '$.data' 2>/dev/null)
+ if [ -n "$data_part" ]; then
+ echo "$data_part"
+ return
+ else
+ echo '{"retention_seconds":604800,"mac":"","metrics":[]}'
+ fi
+}
+
+# 获取月指标(可选MAC)
+get_metrics_month() {
+ local mac="$1"
+ local url="$BANDIX_METRICS_MONTH_API"
+ if [ -n "$mac" ]; then
+ # 转义MAC
+ local mac_escaped=$(echo "$mac" | sed 's/\//\\\//g')
+ url="$url?mac=$mac_escaped"
+ fi
+
+ local api_result=$(curl -s --connect-timeout 2 --max-time 10 "$url" 2>/dev/null)
+ local curl_exit_code=$?
+
+ if [ $curl_exit_code -ne 0 ] || [ -z "$api_result" ]; then
+ echo '{"retention_seconds":2592000,"mac":"","metrics":[]}'
+ return
+ fi
+
+ # 使用 jsonfilter 提取 data 部分
+ local data_part=$(echo "$api_result" | jsonfilter -e '$.data' 2>/dev/null)
+ if [ -n "$data_part" ]; then
+ echo "$data_part"
+ return
+ else
+ echo '{"retention_seconds":2592000,"mac":"","metrics":[]}'
+ fi
+}
+
# 设置设备主机名绑定
set_device_hostname() {
local mac="$1"
@@ -367,6 +454,39 @@ delete_schedule_limit() {
fi
}
+# 清空数据
+clear_data() {
+ local data_dir=$(uci get bandix.general.data_dir 2>/dev/null || echo "/usr/share/bandix")
+ local metrics_dir="$data_dir/metrics"
+
+ # 检查目录是否存在
+ if [ ! -d "$metrics_dir" ]; then
+ make_error "Metrics directory does not exist"
+ return
+ fi
+
+ # 删除 metrics 目录下的所有文件
+ rm -rf "$metrics_dir"/* 2>/dev/null
+
+ if [ $? -eq 0 ]; then
+ make_success "Data cleared successfully"
+ else
+ make_error "Failed to clear data"
+ fi
+}
+
+# 重启服务
+restart_service() {
+ # 执行服务重启
+ /etc/init.d/bandix restart >/dev/null 2>&1
+
+ if [ $? -eq 0 ]; then
+ make_success "Service restarted successfully"
+ else
+ make_error "Failed to restart service"
+ fi
+}
+
case "$1" in
list)
json_init
@@ -377,6 +497,18 @@ case "$1" in
json_add_string "mac"
json_close_object
+ json_add_object "getMetricsDay"
+ json_add_string "mac"
+ json_close_object
+
+ json_add_object "getMetricsWeek"
+ json_add_string "mac"
+ json_close_object
+
+ json_add_object "getMetricsMonth"
+ json_add_string "mac"
+ json_close_object
+
json_add_object "setHostname"
json_add_string "mac"
json_add_string "hostname"
@@ -410,16 +542,22 @@ case "$1" in
json_add_int "wide_tx_rate_limit"
json_close_object
- json_add_object "deleteScheduleLimit"
- json_add_string "mac"
- json_add_string "start_time"
- json_add_string "end_time"
- json_add_string "days"
- json_close_object
-
- json_dump
- json_cleanup
- ;;
+ json_add_object "deleteScheduleLimit"
+ json_add_string "mac"
+ json_add_string "start_time"
+ json_add_string "end_time"
+ json_add_string "days"
+ json_close_object
+
+ json_add_object "clearData"
+ json_close_object
+
+ json_add_object "restartService"
+ json_close_object
+
+ json_dump
+ json_cleanup
+ ;;
call)
case "$2" in
getStatus)
@@ -447,6 +585,48 @@ case "$1" in
fi
get_metrics "$mac"
;;
+ getMetricsDay)
+ mac=""
+ input=""
+ if read -t 1 -r input; then
+ :
+ fi
+ if [ -n "$input" ]; then
+ mac="$(echo "$input" | jsonfilter -e '$[0]' 2>/dev/null)"
+ [ -z "$mac" ] && mac="$(echo "$input" | jsonfilter -e '$.mac' 2>/dev/null)"
+ else
+ [ -n "$3" ] && mac="$3"
+ fi
+ get_metrics_day "$mac"
+ ;;
+ getMetricsWeek)
+ mac=""
+ input=""
+ if read -t 1 -r input; then
+ :
+ fi
+ if [ -n "$input" ]; then
+ mac="$(echo "$input" | jsonfilter -e '$[0]' 2>/dev/null)"
+ [ -z "$mac" ] && mac="$(echo "$input" | jsonfilter -e '$.mac' 2>/dev/null)"
+ else
+ [ -n "$3" ] && mac="$3"
+ fi
+ get_metrics_week "$mac"
+ ;;
+ getMetricsMonth)
+ mac=""
+ input=""
+ if read -t 1 -r input; then
+ :
+ fi
+ if [ -n "$input" ]; then
+ mac="$(echo "$input" | jsonfilter -e '$[0]' 2>/dev/null)"
+ [ -z "$mac" ] && mac="$(echo "$input" | jsonfilter -e '$.mac' 2>/dev/null)"
+ else
+ [ -n "$3" ] && mac="$3"
+ fi
+ get_metrics_month "$mac"
+ ;;
setHostname)
# logger "luci.bandix: setHostname called"
@@ -638,6 +818,14 @@ case "$1" in
make_error "No input received"
fi
;;
+ clearData)
+ # logger "luci.bandix: clearData called"
+ clear_data
+ ;;
+ restartService)
+ # logger "luci.bandix: restartService called"
+ restart_service
+ ;;
esac
;;
esac
diff --git a/luci-app-bandix/root/usr/share/rpcd/acl.d/luci-app-bandix.json b/luci-app-bandix/root/usr/share/rpcd/acl.d/luci-app-bandix.json
index 7cb6cd8..453abdc 100644
--- a/luci-app-bandix/root/usr/share/rpcd/acl.d/luci-app-bandix.json
+++ b/luci-app-bandix/root/usr/share/rpcd/acl.d/luci-app-bandix.json
@@ -6,13 +6,18 @@
"luci.bandix": [
"getStatus",
"getMetrics",
+ "getMetricsDay",
+ "getMetricsWeek",
+ "getMetricsMonth",
"getConnection",
"setHostname",
"getDnsQueries",
"getDnsStats",
"getScheduleLimits",
"setScheduleLimit",
- "deleteScheduleLimit"
+ "deleteScheduleLimit",
+ "clearData",
+ "restartService"
]
},
"uci": [
@@ -24,13 +29,18 @@
"luci.bandix": [
"getStatus",
"getMetrics",
+ "getMetricsDay",
+ "getMetricsWeek",
+ "getMetricsMonth",
"getConnection",
"setHostname",
"getDnsQueries",
"getDnsStats",
"getScheduleLimits",
"setScheduleLimit",
- "deleteScheduleLimit"
+ "deleteScheduleLimit",
+ "clearData",
+ "restartService"
]
},
"uci": [
diff --git a/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm
index c8a27c2..b0787f8 100644
--- a/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm
+++ b/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm
@@ -1,7 +1,7 @@
<%
local api = require "luci.passwall.api"
-%>
-
+