🤞 Sync 2025-12-01 00:10:48
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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('<div class="ht-row"><span class="ht-key">' + label + '</span><span class="ht-val">' + val + '</span></div>');
|
||||
@@ -2815,64 +3040,99 @@ return view.extend({
|
||||
return { up: 'total_tx_bytes', down: 'total_rx_bytes' };
|
||||
}
|
||||
|
||||
lines.push('<div class="ht-title">' + msToTimeLabel(point.ts_ms) + '</div>');
|
||||
|
||||
// 若选择了设备,显示设备信息
|
||||
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('<div class="ht-device">' + _('Device') + ': ' + devLabel + '</div>');
|
||||
}
|
||||
// 标题:聚合数据显示完整日期时间,实时数据只显示时间
|
||||
if (isAggregated) {
|
||||
lines.push('<div class="ht-title">' + msToFullDateTimeLabel(point.ts_ms) + '</div>');
|
||||
var rangeLabel = currentTimeRange === 'day' ? _('Daily') :
|
||||
currentTimeRange === 'week' ? _('Weekly') :
|
||||
currentTimeRange === 'month' ? _('Monthly') : '';
|
||||
if (rangeLabel) {
|
||||
lines.push('<div style="font-size: 0.75rem; opacity: 0.6; margin-bottom: 4px;">' + rangeLabel + ' ' + _('Statistics') + '</div>');
|
||||
}
|
||||
} catch (e) {}
|
||||
} else {
|
||||
lines.push('<div class="ht-title">' + msToTimeLabel(point.ts_ms) + '</div>');
|
||||
}
|
||||
|
||||
// 关键信息:选中类型的上下行速率(大号显示)
|
||||
var kpiLabels = labelsFor(selType);
|
||||
var kpiRateKeys = rateKeysFor(selType);
|
||||
lines.push(
|
||||
'<div class="ht-kpis">' +
|
||||
'<div class="ht-kpi up">' +
|
||||
'<div class="ht-k-label">' + kpiLabels.up + '</div>' +
|
||||
'<div class="ht-k-value">' + rateValue(kpiRateKeys.up) + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="ht-kpi down">' +
|
||||
'<div class="ht-k-label">' + kpiLabels.down + '</div>' +
|
||||
'<div class="ht-k-value">' + rateValue(kpiRateKeys.down) + '</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
if (isAggregated) {
|
||||
// 聚合数据:显示 P95 值(主要指标)
|
||||
lines.push(
|
||||
'<div class="ht-kpis">' +
|
||||
'<div class="ht-kpi up">' +
|
||||
'<div class="ht-k-label">' + _('WAN Upload') + ' (P95)</div>' +
|
||||
'<div class="ht-k-value">' + formatByterate(point.wide_tx_rate_p95 || 0, speedUnit) + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="ht-kpi down">' +
|
||||
'<div class="ht-k-label">' + _('WAN Download') + ' (P95)</div>' +
|
||||
'<div class="ht-k-value">' + formatByterate(point.wide_rx_rate_p95 || 0, speedUnit) + '</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// 详细统计信息
|
||||
lines.push('<div class="ht-divider"></div>');
|
||||
lines.push('<div class="ht-section-title">' + _('Upload Statistics') + '</div>');
|
||||
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('<div class="ht-section-title" style="margin-top: 8px;">' + _('Download Statistics') + '</div>');
|
||||
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('<div class="ht-divider"></div>');
|
||||
lines.push('<div class="ht-section-title">' + _('Cumulative Traffic') + '</div>');
|
||||
row(_('WAN Uploaded'), bytesValue('wide_tx_bytes'));
|
||||
row(_('WAN Downloaded'), bytesValue('wide_rx_bytes'));
|
||||
} else {
|
||||
// 实时数据:显示实时速率
|
||||
lines.push(
|
||||
'<div class="ht-kpis">' +
|
||||
'<div class="ht-kpi up">' +
|
||||
'<div class="ht-k-label">' + kpiLabels.up + '</div>' +
|
||||
'<div class="ht-k-value">' + rateValue(kpiRateKeys.up) + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="ht-kpi down">' +
|
||||
'<div class="ht-k-label">' + kpiLabels.down + '</div>' +
|
||||
'<div class="ht-k-value">' + rateValue(kpiRateKeys.down) + '</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// 次要信息:其余类型的速率(精简展示)
|
||||
var otherTypes = ['total', 'lan', 'wan'].filter(function (t) { return t !== selType; });
|
||||
if (otherTypes.length) {
|
||||
lines.push('<div class="ht-section-title">' + _('Other Rates') + '</div>');
|
||||
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('<div class="ht-section-title">' + _('Other Rates') + '</div>');
|
||||
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('<div class="ht-divider"></div>');
|
||||
lines.push('<div class="ht-section-title">' + _('Cumulative') + '</div>');
|
||||
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('<div class="ht-divider"></div>');
|
||||
lines.push('<div class="ht-section-title">' + _('Cumulative') + '</div>');
|
||||
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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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: "
|
||||
|
||||
@@ -840,4 +840,67 @@ msgid "No active rule"
|
||||
msgstr "Aucune règle active"
|
||||
|
||||
msgid "Schedule Rules"
|
||||
msgstr "Règles de limitation programmée"
|
||||
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 : "
|
||||
@@ -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: "
|
||||
|
||||
@@ -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 "サービスの再起動に失敗しました:"
|
||||
|
||||
@@ -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: "
|
||||
|
||||
|
||||
@@ -840,4 +840,67 @@ msgid "No active rule"
|
||||
msgstr "Нет активных правил"
|
||||
|
||||
msgid "Schedule Rules"
|
||||
msgstr "Правила ограничения по расписанию"
|
||||
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 "Не удалось перезапустить службу: "
|
||||
@@ -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 "ล้มเหลวในการรีสตาร์ทบริการ: "
|
||||
|
||||
@@ -840,4 +840,67 @@ msgid "No active rule"
|
||||
msgstr "无生效规则"
|
||||
|
||||
msgid "Schedule Rules"
|
||||
msgstr "定时限速规则"
|
||||
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 "重启服务失败:"
|
||||
@@ -840,4 +840,67 @@ msgid "No active rule"
|
||||
msgstr "無生效規則"
|
||||
|
||||
msgid "Schedule Rules"
|
||||
msgstr "定時限速規則"
|
||||
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 "重啟服務失敗:"
|
||||
@@ -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
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<%
|
||||
local api = require "luci.passwall.api"
|
||||
-%>
|
||||
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js"></script>
|
||||
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js?v=25.11.27"></script>
|
||||
|
||||
<style>
|
||||
table th, .table .th {
|
||||
@@ -54,12 +54,6 @@ table td, .table .td {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.node-wrapper .cbi-input-checkbox {
|
||||
flex-grow: 0 !important;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.cbi-tabmenu > li {
|
||||
margin-right: 2px !important;
|
||||
}
|
||||
@@ -82,6 +76,76 @@ table td, .table .td {
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
#cbi-passwall-nodes .pw-checkbox, #cbi-passwall-nodes th:nth-child(1) {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
#select_all_btn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* enable flex for small screens*/
|
||||
@media screen and (max-width: 1152px) {
|
||||
.cbi-section-table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#cbi-passwall-nodes-default-fieldset {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cbi-section-table-titles {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* meticulously control how each component occupies the limited space we have */
|
||||
#cbi-passwall-nodes .pw-checkbox, #cbi-passwall-nodes th:nth-child(1) {
|
||||
flex: 0 0 40px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
#cbi-passwall-nodes .pw-remark {
|
||||
flex: 1 1 30%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
#cbi-passwall-nodes .pw-ping, #cbi-passwall-nodes .pw-tcping, #cbi-passwall-nodes .pw-urltest {
|
||||
flex: 0 0 50px;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.pw-actions {
|
||||
padding-top: 0 !important;
|
||||
border-top-width: 0 !important;
|
||||
flex: 1 1 350px;
|
||||
}
|
||||
|
||||
#select_all_btn {
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* shrink actionbar even further for mobile devices */
|
||||
@media screen and (max-width: 500px) {
|
||||
.node-wrapper {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.cbi-button {
|
||||
margin-left: 0 !important;
|
||||
margin-right: 1px !important;
|
||||
}
|
||||
|
||||
.pw-actions {
|
||||
padding-left: 5px!important;
|
||||
padding-right: 5px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sortable-chosen {
|
||||
background-color: rgba(220, 235, 245, 0.4) !important;
|
||||
opacity: 0.7;
|
||||
@@ -114,11 +178,7 @@ table td, .table .td {
|
||||
function cbi_t_switch(section, tab) {
|
||||
if( cbi_t[section] && cbi_t[section][tab] ) {
|
||||
//在切换选项卡之前,先取消当前激活选项卡的全选状态
|
||||
var btn = document.getElementById("select_all_btn");
|
||||
if (btn) {
|
||||
dechecked_all_node(btn);
|
||||
}
|
||||
|
||||
dechecked_all_node();
|
||||
var o = cbi_t[section][tab];
|
||||
var h = document.getElementById('tab.' + section);
|
||||
for( var tid in cbi_t[section] ) {
|
||||
@@ -143,10 +203,7 @@ table td, .table .td {
|
||||
if (typeof(cbi_t_switch) === "function") {
|
||||
var old_switch = cbi_t_switch;
|
||||
cbi_t_switch = function(section, tab) {
|
||||
var btn = document.getElementById("select_all_btn");
|
||||
if (btn) {
|
||||
dechecked_all_node(btn);
|
||||
}
|
||||
dechecked_all_node();
|
||||
return old_switch(section, tab);
|
||||
};
|
||||
}
|
||||
@@ -249,30 +306,59 @@ table td, .table .td {
|
||||
}
|
||||
}
|
||||
|
||||
function checked_all_node(btn) {
|
||||
function set_select_all_state(sectionChecked) {
|
||||
var visibleContainer = document.querySelector('#cbi-passwall-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
doms[i].checked = true;
|
||||
}
|
||||
btn.value = "<%:DeSelect all%>";
|
||||
btn.setAttribute("onclick", "dechecked_all_node(this)");
|
||||
var nodes = visibleContainer.getElementsByClassName("nodes_select");
|
||||
var selectAllChk = visibleContainer.querySelector(".nodes_select_all");
|
||||
var selectAllBtn = document.getElementById("select_all_btn");
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
nodes[i].checked = sectionChecked;
|
||||
}
|
||||
if (selectAllChk) {
|
||||
selectAllChk.checked = sectionChecked;
|
||||
selectAllChk.title = sectionChecked ? "<%:DeSelect all%>" : "<%:Select all%>";
|
||||
selectAllChk.setAttribute("onclick", sectionChecked ? "dechecked_all_node(this)" : "checked_all_node(this)");
|
||||
}
|
||||
if (selectAllBtn) {
|
||||
selectAllBtn.value = sectionChecked ? "<%:DeSelect all%>" : "<%:Select all%>";
|
||||
selectAllBtn.setAttribute("onclick", sectionChecked ? "dechecked_all_node(this)" : "checked_all_node(this)");
|
||||
}
|
||||
}
|
||||
|
||||
function checked_all_node(btn) {
|
||||
set_select_all_state(true);
|
||||
}
|
||||
|
||||
function dechecked_all_node(btn) {
|
||||
set_select_all_state(false);
|
||||
}
|
||||
|
||||
function update_select_state() {
|
||||
var visibleContainer = document.querySelector('#cbi-passwall-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
doms[i].checked = false;
|
||||
}
|
||||
btn.value = "<%:Select all%>";
|
||||
btn.setAttribute("onclick", "checked_all_node(this)");
|
||||
var nodes = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (!nodes.length) return;
|
||||
var selectAllChk = visibleContainer.querySelector(".nodes_select_all");
|
||||
var selectAllBtn = document.getElementById("select_all_btn");
|
||||
var checkedCount = 0;
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
if (nodes[i].checked) checkedCount++;
|
||||
}
|
||||
var allChecked = checkedCount === nodes.length;
|
||||
var title = allChecked ? "<%:DeSelect all%>" : "<%:Select all%>";
|
||||
var onclickFunc = allChecked ? "dechecked_all_node(this)" : "checked_all_node(this)";
|
||||
|
||||
function updateElement(el) {
|
||||
if (!el) return;
|
||||
if ("checked" in el) el.checked = allChecked;
|
||||
if ("title" in el) el.title = title;
|
||||
if ("value" in el) el.value = title;
|
||||
el.setAttribute("onclick", onclickFunc);
|
||||
}
|
||||
|
||||
updateElement(selectAllChk);
|
||||
updateElement(selectAllBtn);
|
||||
}
|
||||
|
||||
function delete_select_nodes() {
|
||||
@@ -622,6 +708,9 @@ table td, .table .td {
|
||||
<fieldset class="cbi-section cbi-tblsection" id="cbi-passwall-nodes-{{group}}-fieldset">
|
||||
<table class="table cbi-section-table" id="cbi-passwall-nodes-{{group}}-table" style="">
|
||||
<tr class="tr cbi-section-table-titles anonymous">
|
||||
<th class="th cbi-section-table-cell" style="width:20px">
|
||||
<input class="cbi-input-checkbox nodes_select_all" type="checkbox" onclick="checked_all_node(this)" title="<%:Select all%>"/>
|
||||
</th>
|
||||
<th class="th cbi-section-table-cell" style="width:40%"><%:Remarks%></th>
|
||||
<th class="th cbi-section-table-cell" style="width:8%">Ping</th>
|
||||
<th class="th cbi-section-table-cell" style="width:8%">TCPing</th>
|
||||
@@ -642,13 +731,15 @@ table td, .table .td {
|
||||
<input class="hidden" id="cbid.passwall.{{id}}.remarks" value="{{remarks_val}}"/>
|
||||
<input class="hidden" id="cbid.passwall.{{id}}.address" value="{{address_val}}"/>
|
||||
<input class="hidden" id="cbid.passwall.{{id}}.port" value="{{port_val}}"/>
|
||||
<td class="td cbi-value-field">{{remarks}}</td>
|
||||
<td class="td cbi-value-field">{{ping}}</td>
|
||||
<td class="td cbi-value-field">{{tcping}}</td>
|
||||
<td class="td cbi-value-field">{{url_test}}</td>
|
||||
<td class="td cbi-section-table-cell nowrap cbi-section-actions">
|
||||
<td class="td cbi-value-field pw-checkbox">
|
||||
<input class="cbi-input-checkbox nodes_select" type="checkbox" cbid="{{id}}" onclick="update_select_state()"/>
|
||||
</td>
|
||||
<td class="td cbi-value-field pw-remark">{{remarks}}</td>
|
||||
<td class="td cbi-value-field pw-ping">{{ping}}</td>
|
||||
<td class="td cbi-value-field pw-tcping">{{tcping}}</td>
|
||||
<td class="td cbi-value-field pw-urltest">{{url_test}}</td>
|
||||
<td class="td cbi-section-table-cell nowrap cbi-section-actions pw-actions">
|
||||
<div class="node-wrapper">
|
||||
<input class="cbi-input-checkbox nodes_select" type="checkbox" cbid="{{id}}" />
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:To Top%>" onclick="row_top(this)" title="<%:To Top%>"/>
|
||||
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Use%>" id="apply_{{id}}" onclick="open_set_node_div('{{id}}')"/>
|
||||
<input class="btn cbi-button cbi-button-add" type="button" value="<%:Copy%>" onclick="copy_node('{{id}}')"/>
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
--background-start: oklch(0.984 0.003 247.858);
|
||||
--background-mid: oklch(0.984 0.003 247.858);
|
||||
--background-end: oklch(0.984 0.003 247.858);
|
||||
|
||||
--progress-start: oklch(0.68 0.11 233);
|
||||
--progress-end: oklch(0.7535 0.1034 198.37);
|
||||
--primary: oklch(0.68 0.11 233);
|
||||
--primary-text: oklch(0.6656 0.1055 234.61);
|
||||
--primary-hover: oklch(0.64 0.1055 234.61);
|
||||
@@ -100,6 +101,8 @@
|
||||
--background-start: oklch(0.2077 0.0398 265.75);
|
||||
--background-mid: oklch(0.3861 0.059 188.42);
|
||||
--background-end: oklch(0.4318 0.0865 166.91);
|
||||
--progress-start: oklch(0.4318 0.0865 166.91);
|
||||
--progress-end: oklch(62.1% 0.145 189.632);
|
||||
--primary: oklch(0.534 0.118 190.485);
|
||||
--primary-text: oklch(0.779 0.168 188.745);
|
||||
--primary-hover: oklch(0.58 0.13 189.632);
|
||||
@@ -177,85 +180,6 @@
|
||||
--spacing: 0.25rem;
|
||||
}
|
||||
|
||||
@theme {
|
||||
--color-aurora-green: #6ee7b7;
|
||||
--color-aurora-green-50: oklch(97.2% 0.019 158.743);
|
||||
--color-aurora-green-100: oklch(94.8% 0.045 159.652);
|
||||
--color-aurora-green-200: oklch(90.5% 0.089 160.125);
|
||||
--color-aurora-green-300: oklch(84.7% 0.148 160.742);
|
||||
--color-aurora-green-400: oklch(89.6% 0.143 162.4);
|
||||
--color-aurora-green-500: oklch(77.1% 0.198 161.205);
|
||||
--color-aurora-green-600: oklch(64.3% 0.175 161.428);
|
||||
--color-aurora-green-700: oklch(55.2% 0.142 162.113);
|
||||
--color-aurora-green-800: oklch(47.1% 0.112 162.895);
|
||||
--color-aurora-green-900: oklch(40.8% 0.089 163.742);
|
||||
--color-aurora-green-950: oklch(27.9% 0.061 165.128);
|
||||
|
||||
--color-aurora-teal: #4fc3c7;
|
||||
--color-aurora-teal-50: oklch(97.8% 0.016 185.234);
|
||||
--color-aurora-teal-100: oklch(95.1% 0.041 186.152);
|
||||
--color-aurora-teal-200: oklch(90.8% 0.079 187.063);
|
||||
--color-aurora-teal-300: oklch(85.2% 0.128 187.894);
|
||||
--color-aurora-teal-500: oklch(75.8% 0.145 188.2);
|
||||
--color-aurora-teal-600: oklch(62.1% 0.145 189.632);
|
||||
--color-aurora-teal-700: oklch(53.4% 0.118 190.485);
|
||||
--color-aurora-teal-800: oklch(45.8% 0.094 191.328);
|
||||
--color-aurora-teal-900: oklch(39.7% 0.074 192.156);
|
||||
--color-aurora-teal-950: oklch(28.2% 0.052 193.864);
|
||||
|
||||
--color-aurora-sky: #499ecb;
|
||||
--color-aurora-sky-50: oklch(97.8% 0.012 214.3);
|
||||
--color-aurora-sky-100: oklch(95.2% 0.025 214.3);
|
||||
--color-aurora-sky-200: oklch(90.1% 0.051 214.3);
|
||||
--color-aurora-sky-300: oklch(82.8% 0.085 214.3);
|
||||
--color-aurora-sky-400: oklch(73.5% 0.128 214.3);
|
||||
--color-aurora-sky-500: oklch(68.5% 0.142 214.3);
|
||||
--color-aurora-sky-600: oklch(58.2% 0.135 214.3);
|
||||
--color-aurora-sky-700: oklch(49.8% 0.118 214.3);
|
||||
--color-aurora-sky-800: oklch(42.6% 0.095 214.3);
|
||||
--color-aurora-sky-900: oklch(36.1% 0.072 214.3);
|
||||
--color-aurora-sky-950: oklch(25.8% 0.048 214.3);
|
||||
|
||||
--color-aurora-night-slate: #0f172a;
|
||||
--color-aurora-night-slate-50: oklch(96.8% 0.008 245.123);
|
||||
--color-aurora-night-slate-100: oklch(93.2% 0.018 246.084);
|
||||
--color-aurora-night-slate-200: oklch(86.4% 0.035 247.159);
|
||||
--color-aurora-night-slate-300: oklch(76.8% 0.062 248.347);
|
||||
--color-aurora-night-slate-400: oklch(64.2% 0.098 249.638);
|
||||
--color-aurora-night-slate-500: oklch(52.1% 0.128 250.942);
|
||||
--color-aurora-night-slate-600: oklch(41.8% 0.145 252.258);
|
||||
--color-aurora-night-slate-700: oklch(33.6% 0.142 253.586);
|
||||
--color-aurora-night-slate-800: oklch(26.8% 0.128 254.926);
|
||||
--color-aurora-night-slate-900: oklch(11.8% 0.042 264.7);
|
||||
--color-aurora-night-slate-950: oklch(11.2% 0.089 257.847);
|
||||
|
||||
--color-aurora-night-teal: #134e4a;
|
||||
--color-aurora-night-teal-50: oklch(96.9% 0.012 168.245);
|
||||
--color-aurora-night-teal-100: oklch(92.8% 0.028 169.137);
|
||||
--color-aurora-night-teal-200: oklch(85.6% 0.055 170.029);
|
||||
--color-aurora-night-teal-300: oklch(75.4% 0.089 170.921);
|
||||
--color-aurora-night-teal-400: oklch(62.8% 0.128 171.813);
|
||||
--color-aurora-night-teal-500: oklch(51.2% 0.156 172.705);
|
||||
--color-aurora-night-teal-600: oklch(41.5% 0.172 173.597);
|
||||
--color-aurora-night-teal-700: oklch(33.8% 0.168 174.489);
|
||||
--color-aurora-night-teal-800: oklch(27.6% 0.148 175.381);
|
||||
--color-aurora-night-teal-900: oklch(29.5% 0.074 175.4);
|
||||
--color-aurora-night-teal-950: oklch(18.9% 0.089 177.165);
|
||||
|
||||
--color-aurora-night-emerald: #065f46;
|
||||
--color-aurora-night-emerald-50: oklch(97.1% 0.015 155.743);
|
||||
--color-aurora-night-emerald-100: oklch(94.2% 0.035 156.652);
|
||||
--color-aurora-night-emerald-200: oklch(88.9% 0.068 157.561);
|
||||
--color-aurora-night-emerald-300: oklch(81.3% 0.112 158.47);
|
||||
--color-aurora-night-emerald-400: oklch(71.8% 0.158 159.379);
|
||||
--color-aurora-night-emerald-500: oklch(61.2% 0.189 160.288);
|
||||
--color-aurora-night-emerald-600: oklch(51.8% 0.198 161.197);
|
||||
--color-aurora-night-emerald-700: oklch(43.6% 0.185 162.106);
|
||||
--color-aurora-night-emerald-800: oklch(36.8% 0.156 163.015);
|
||||
--color-aurora-night-emerald-900: oklch(34.2% 0.118 163.2);
|
||||
--color-aurora-night-emerald-950: oklch(22.1% 0.089 164.833);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-text: var(--text);
|
||||
@@ -263,6 +187,9 @@
|
||||
--color-aurora-mid: var(--background-mid);
|
||||
--color-aurora-end: var(--background-end);
|
||||
|
||||
--color-progress-start: var(--progress-start);
|
||||
--color-progress-end: var(--progress-end);
|
||||
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-text: var(--primary-text);
|
||||
--color-primary-hover: var(--primary-hover);
|
||||
@@ -355,9 +282,8 @@
|
||||
|
||||
html {
|
||||
@apply scrollbar-thumb-rounded-full scrollbar-thin scrollbar-track-slate-100 scrollbar-thumb-slate-500/70 dark:scrollbar-track-slate-900 dark:scrollbar-thumb-slate-300/65;
|
||||
@apply max-md:dark:bg-aurora-night-teal relative h-full font-sans max-md:bg-slate-100;
|
||||
@apply md:before:pointer-events-none md:before:fixed md:before:inset-0 md:before:-z-10;
|
||||
@apply md:before:from-aurora-start md:before:via-aurora-mid md:before:to-aurora-end md:before:bg-gradient-to-br;
|
||||
@apply relative h-full font-sans md:before:pointer-events-none md:before:fixed md:before:inset-0 md:before:-z-10;
|
||||
@apply md:before:from-aurora-start md:before:via-aurora-mid md:before:to-aurora-end max-md:bg-aurora-mid md:before:bg-gradient-to-br;
|
||||
|
||||
body {
|
||||
@apply flex flex-col bg-transparent text-sm leading-relaxed font-normal text-slate-900 transition-all duration-300 dark:text-slate-100;
|
||||
@@ -624,7 +550,7 @@
|
||||
}
|
||||
|
||||
#syslog {
|
||||
@apply bg-aurora-night-slate rounded-3xl border border-slate-400/25 p-6 text-slate-200 shadow-lg max-md:p-3 dark:border-gray-600/40 dark:bg-gray-900 dark:text-gray-100 dark:shadow-black/50;
|
||||
@apply rounded-3xl border border-slate-400/25 bg-slate-900 p-6 text-slate-100 shadow-lg max-md:p-3 dark:border-slate-600/40;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,7 +655,7 @@
|
||||
@layer button {
|
||||
button,
|
||||
.btn {
|
||||
@apply inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-2xl border px-3 py-1.5 text-sm font-medium antialiased transition-all duration-200 max-md:text-base max-md:font-medium;
|
||||
@apply inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-2xl border px-3 py-1.5 text-sm font-medium antialiased shadow-sm transition-all duration-200 max-md:text-base max-md:font-medium;
|
||||
&[disabled] {
|
||||
@apply cursor-not-allowed opacity-40 dark:opacity-30;
|
||||
}
|
||||
@@ -783,7 +709,7 @@
|
||||
input[type="password"],
|
||||
.cbi-input-text,
|
||||
.cbi-input {
|
||||
@apply focus:border-aurora-sky focus:ring-aurora-sky/20 dark:focus:border-primary dark:focus:ring-primary/30 relative rounded-2xl border border-slate-300/70 bg-white px-3 py-1.5 text-sm font-normal text-slate-900 placeholder-slate-400 shadow-sm transition-all duration-200 focus:ring-2 focus:outline-none dark:border-slate-600/60 dark:bg-slate-900 dark:text-slate-100 dark:placeholder-slate-400;
|
||||
@apply focus:border-primary focus:ring-primary/20 relative rounded-2xl border border-slate-300/70 bg-white px-3 py-1.5 text-sm font-normal text-slate-900 placeholder-slate-400 shadow-sm transition-all duration-200 focus:ring-2 focus:outline-none dark:border-slate-600/60 dark:bg-slate-900 dark:text-slate-100 dark:placeholder-slate-400;
|
||||
|
||||
.table.cbi-section-table & {
|
||||
@apply w-full;
|
||||
@@ -800,7 +726,7 @@
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
@apply focus:before:border-aurora-sky focus:before:ring-aurora-sky/20 checked:before:border-aurora-sky checked:before:bg-aurora-sky dark:focus:before:border-primary dark:focus:before:ring-primary/30 dark:checked:before:border-aurora-teal-600 dark:checked:before:bg-aurora-teal-600 relative mr-3 inline-block h-4 w-4 cursor-pointer appearance-none before:absolute before:top-0 before:left-0 before:h-4 before:w-4 before:border before:border-slate-300/70 before:bg-white before:transition-all before:duration-200 after:absolute after:top-0.5 after:left-0.5 after:h-3 after:w-3 after:bg-white after:opacity-0 after:transition-opacity after:duration-200 checked:after:opacity-100 hover:before:border-slate-400/60 focus:before:ring-2 focus:before:outline-none disabled:cursor-not-allowed dark:before:border-slate-600/60 dark:before:bg-slate-900 dark:hover:before:border-slate-500/60;
|
||||
@apply focus:before:border-primary focus:before:ring-primary/20 checked:before:border-primary checked:before:bg-primary relative mr-3 inline-block h-4 w-4 cursor-pointer appearance-none before:absolute before:top-0 before:left-0 before:h-4 before:w-4 before:border before:border-slate-300/70 before:bg-white before:transition-all before:duration-200 after:absolute after:top-0.5 after:left-0.5 after:h-3 after:w-3 after:bg-white after:opacity-0 after:transition-opacity after:duration-200 checked:after:opacity-100 hover:before:border-slate-400/60 focus:before:ring-2 focus:before:outline-none disabled:cursor-not-allowed dark:before:border-slate-600/60 dark:before:bg-slate-900 dark:hover:before:border-slate-500/60;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
@@ -818,7 +744,7 @@
|
||||
|
||||
@layer textarea {
|
||||
textarea {
|
||||
@apply focus:border-aurora-sky focus:ring-aurora-sky/20 dark:focus:border-primary dark:focus:ring-primary/30 min-h-24 w-full resize-y rounded-2xl border border-slate-300/70 bg-white px-3 py-2 text-sm font-normal text-slate-900 placeholder-slate-400 shadow-sm transition-all duration-200 focus:ring-2 focus:outline-none dark:border-slate-600/60 dark:bg-slate-900 dark:text-slate-100 dark:placeholder-slate-400;
|
||||
@apply focus:border-primary focus:ring-primary/20 min-h-24 w-full resize-y rounded-2xl border border-slate-300/70 bg-white px-3 py-2 text-sm font-normal text-slate-900 placeholder-slate-400 shadow-sm transition-all duration-200 focus:ring-2 focus:outline-none dark:border-slate-600/60 dark:bg-slate-900 dark:text-slate-100 dark:placeholder-slate-400;
|
||||
&[disabled] {
|
||||
@apply cursor-not-allowed opacity-40 dark:opacity-30;
|
||||
}
|
||||
@@ -827,7 +753,7 @@
|
||||
|
||||
@layer select {
|
||||
select {
|
||||
@apply focus:border-aurora-sky focus:ring-aurora-sky/20 dark:focus:border-primary dark:focus:ring-primary/30 appearance-none rounded-2xl border border-slate-300/70 bg-white px-3 py-1.5 pr-10 text-sm font-normal text-slate-900 shadow-sm transition-all duration-200 focus:ring-2 focus:outline-none dark:border-slate-600/60 dark:bg-slate-900 dark:text-slate-100;
|
||||
@apply focus:border-primary focus:ring-primary/20 appearance-none rounded-2xl border border-slate-300/70 bg-white px-3 py-1.5 pr-10 text-sm font-normal text-slate-900 shadow-sm transition-all duration-200 focus:ring-2 focus:outline-none dark:border-slate-600/60 dark:bg-slate-900 dark:text-slate-100;
|
||||
@apply bg-[url('@assets/icons/arrow-down.svg')] bg-[length:16px] bg-[right_0.75rem_center] bg-no-repeat dark:bg-[url('@assets/icons/arrow-down-dark.svg')];
|
||||
&[disabled] {
|
||||
@apply cursor-not-allowed opacity-40 dark:opacity-30;
|
||||
@@ -891,7 +817,7 @@
|
||||
@apply absolute left-0 z-60 w-fit min-w-full overflow-y-auto rounded-lg border border-slate-200/60 bg-white/95 shadow-xl backdrop-blur-sm dark:border-slate-600/40 dark:bg-slate-800/95;
|
||||
|
||||
& > li {
|
||||
@apply hover:bg-aurora-sky/8 dark:hover:bg-aurora-teal-600/15 min-h-9 w-full cursor-pointer px-3 py-1.5 font-medium text-slate-600 dark:text-slate-300;
|
||||
@apply hover:bg-primary/15 min-h-9 w-full cursor-pointer px-3 py-1.5 font-medium text-slate-600 dark:text-slate-300;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,7 +841,7 @@
|
||||
}
|
||||
|
||||
&[open] {
|
||||
@apply border-aurora-sky ring-aurora-sky/20 dark:border-primary dark:ring-primary/30 relative ring-2;
|
||||
@apply border-primary ring-primary/20 relative ring-2;
|
||||
|
||||
& > ul.dropdown {
|
||||
@apply block w-auto max-w-none;
|
||||
@@ -924,7 +850,7 @@
|
||||
@apply flex;
|
||||
|
||||
&[selected] {
|
||||
@apply bg-aurora-sky/20 text-aurora-sky-800 dark:bg-aurora-teal-600/25 dark:text-aurora-teal-200;
|
||||
@apply bg-primary/20 text-primary-text;
|
||||
}
|
||||
|
||||
&[unselectable] {
|
||||
@@ -1064,10 +990,10 @@
|
||||
|
||||
@layer progress {
|
||||
.cbi-progressbar {
|
||||
@apply relative h-3.5 w-full cursor-help overflow-hidden rounded-full bg-slate-300 before:absolute before:top-1/2 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:rounded-2xl before:text-xs/normal before:whitespace-nowrap before:text-slate-900 before:shadow-lg before:content-[attr(title)] max-md:h-4 max-md:rounded-2xl max-md:before:text-xs max-md:before:leading-normal dark:bg-slate-700 before:dark:border-slate-600 before:dark:text-slate-100 dark:before:text-slate-100 before:dark:shadow-black/40;
|
||||
@apply relative h-3.5 w-full cursor-help overflow-hidden rounded-full bg-slate-300 before:absolute before:top-1/2 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:rounded-2xl before:text-xs/normal before:whitespace-nowrap before:text-slate-900 before:content-[attr(title)] max-md:h-4 max-md:rounded-2xl max-md:before:text-xs max-md:before:leading-normal dark:bg-slate-700 before:dark:border-slate-600 before:dark:text-slate-100 dark:before:text-slate-100;
|
||||
|
||||
& > div {
|
||||
@apply from-aurora-sky to-aurora-teal dark:from-aurora-night-emerald dark:to-aurora-teal-600 dark:text-shadow-aurora-night-slate-800 h-full bg-gradient-to-r transition-all duration-300;
|
||||
@apply from-progress-start to-progress-end h-full bg-gradient-to-r transition-all duration-300;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1132,7 +1058,7 @@
|
||||
}
|
||||
|
||||
&.ifacebadge-active {
|
||||
@apply border-aurora-sky dark:border-primary font-semibold;
|
||||
@apply border-primary font-semibold;
|
||||
}
|
||||
|
||||
&.large {
|
||||
@@ -1229,7 +1155,7 @@
|
||||
}
|
||||
|
||||
&.active {
|
||||
@apply border-aurora-sky bg-aurora-sky dark:border-aurora-teal-600 dark:bg-aurora-teal-600 text-white;
|
||||
@apply border-primary bg-primary text-white;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1828,7 +1754,7 @@
|
||||
}
|
||||
|
||||
&.drag-over {
|
||||
@apply border-aurora-sky/60 bg-aurora-sky/5 ring-aurora-sky/30 dark:border-primary/60 dark:bg-aurora-teal-600/10 dark:ring-primary/30 scale-105 shadow-lg ring-2;
|
||||
@apply border-primary/60 bg-primary/5 ring-primary/30 scale-105 shadow-lg ring-2;
|
||||
}
|
||||
|
||||
& > span,
|
||||
|
||||
@@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=Aurora Theme (A modern browser theme built with Vite and Tailwind CSS)
|
||||
LUCI_DEPENDS:=+luci-base
|
||||
|
||||
PKG_VERSION:=0.8.6_beta
|
||||
PKG_RELEASE:=20251128
|
||||
PKG_VERSION:=0.8.7s_beta
|
||||
PKG_RELEASE:=20251130
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
LUCI_MINIFY_CSS:=
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,8 +10,8 @@ THEME_TITLE:=Kucat Theme
|
||||
PKG_NAME:=luci-theme-$(THEME_NAME)
|
||||
LUCI_TITLE:=Kucat Theme by sirpdboy
|
||||
LUCI_DEPENDS:=+wget +curl +jsonfilter
|
||||
PKG_VERSION:=3.1.4
|
||||
PKG_RELEASE:=20251126
|
||||
PKG_VERSION:=3.1.5
|
||||
PKG_RELEASE:=20251130
|
||||
|
||||
define Package/luci-theme-$(THEME_NAME)/conffiles
|
||||
/www/luci-static/resources/background/
|
||||
|
||||
@@ -294,20 +294,43 @@ body {
|
||||
|
||||
.td,
|
||||
.th {
|
||||
line-height: normal;
|
||||
display: table-cell;
|
||||
font-size: var(--font-x);
|
||||
color: var(--body-color);
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
padding: .78rem
|
||||
padding: .7rem
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: .6rem
|
||||
}
|
||||
|
||||
.tr.placeholder {
|
||||
height: 2rem
|
||||
height: 1.9rem
|
||||
}
|
||||
#cbi-firewall .tr[data-title]::before, #cbi-firewall .tr.cbi-section-table-titles.named::before {
|
||||
font-weight: bold;
|
||||
display: table-cell;
|
||||
align-self: center;
|
||||
flex: 1 1 5%;
|
||||
padding: .5rem;
|
||||
content: attr(data-title) "\20";
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
font-size: var(--font-z);
|
||||
}
|
||||
|
||||
#cbi-firewall .tr.cbi-section-table-titles.named::before {
|
||||
background-color: var(--menu-item-titlebg-color) !important;
|
||||
}
|
||||
|
||||
.cbi-section-table-row {
|
||||
text-align: center !important;
|
||||
}
|
||||
.tr.placeholder>.td {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
@@ -486,11 +509,6 @@ a:hover {
|
||||
text-decoration: underline
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: normal !important;
|
||||
line-height: 1.5;
|
||||
padding-left: 10px
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: var(--font-x);
|
||||
@@ -509,7 +527,7 @@ abbr {
|
||||
|
||||
hr {
|
||||
opacity: .1;
|
||||
border-color: #eee;
|
||||
border-color: var(--input-boxcolor);
|
||||
margin: 1rem 0
|
||||
}
|
||||
|
||||
@@ -544,7 +562,7 @@ footer a {
|
||||
#view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
/* gap: 1rem; */
|
||||
min-width: inherit;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden
|
||||
@@ -566,6 +584,13 @@ footer a {
|
||||
padding: 1rem 3rem !important
|
||||
}
|
||||
|
||||
.container .cbi-map>div:not(.cbi-button),
|
||||
.container .cbi-map>fieldset.cbi-section:not(.cbi-button),
|
||||
#view>#content_syslog,
|
||||
#view>div>div:not(.cbi-button) {
|
||||
padding: 0 1%;
|
||||
}
|
||||
|
||||
.main {
|
||||
position: relative;
|
||||
top: 0;
|
||||
@@ -610,7 +635,7 @@ footer a {
|
||||
flex-direction: column
|
||||
}
|
||||
|
||||
.main-right>#maincontent>.container {
|
||||
#maincontent>.container {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column
|
||||
@@ -1115,7 +1140,7 @@ li {
|
||||
min-width: inherit;
|
||||
overflow: unset;
|
||||
border-radius: var(--radius1);
|
||||
background-color: rgba(var(--primary-rgbbody), var(--primary-rgbm-ts));
|
||||
background-color: rgba(var(--primary-rgbbody), 0.9);
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 var(--input-boxcolor);
|
||||
padding: 1rem
|
||||
}
|
||||
@@ -1260,7 +1285,7 @@ select,
|
||||
}
|
||||
|
||||
select option {
|
||||
background-color: rgba(var(--primary-rgbbody), 1);
|
||||
background-color: rgba(var(--primary-rgbbody), 0.95);
|
||||
width: 100% !important;
|
||||
overflow: hidden
|
||||
}
|
||||
@@ -1302,7 +1327,7 @@ input[type='radio'] {
|
||||
appearance: none !important;
|
||||
-webkit-appearance: none !important;
|
||||
background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'-4 -4 8 8\'%3e%3ccircle r=\'3\' fill=\'%23ccc\'/%3e%3c/svg%3e');
|
||||
background-color: rgba(var(--primary-rgbm), 0.2);
|
||||
background-color: rgba(var(--primary-rgbm), 0.3);
|
||||
box-shadow: inset 0 2px 1px rgba(255, 255, 255, .6);
|
||||
border-radius: 70%;
|
||||
cursor: pointer;
|
||||
@@ -1419,11 +1444,11 @@ textarea,
|
||||
width: auto;
|
||||
min-width: 100%;
|
||||
max-width: none;
|
||||
max-height: 200px !important;
|
||||
max-height: 170px !important;
|
||||
box-shadow: 0 0 4px var(--inputborder-color);
|
||||
border-radius: var(--radius2);
|
||||
border: 0px solid var(--inputborder-color);
|
||||
background-color: rgba(var(--primary-rgbbody), 1);
|
||||
background-color: rgba(var(--primary-rgbbody), 0.95);
|
||||
color: var(--inputtext-color);
|
||||
margin-left: 0 !important;
|
||||
margin-top: 0rem;
|
||||
@@ -1551,12 +1576,23 @@ textarea,
|
||||
color: var(--menu-hover-color);
|
||||
border-right: 0.18751rem solid rgba(255, 255, 255, 0);
|
||||
letter-spacing: 1px;
|
||||
white-space: nowrap;
|
||||
/*white-space: nowrap; */
|
||||
margin-bottom: 0.5rem;
|
||||
overflow-x: auto;
|
||||
padding: 0.3rem 1rem
|
||||
}
|
||||
|
||||
.container .cbi-tabmenu, .container #tabmenu {
|
||||
margin-left: -2%!important;
|
||||
}
|
||||
|
||||
ul.tabs, .tabmenu .tabs, #tabmenu .tabs, ul.cbi-tabmenu {
|
||||
padding-left: 2.5%!important;
|
||||
box-shadow: 0 1px 0px 0px var(--input-boxcolor), 0 0px 1px -1px var(--input-boxcolor);
|
||||
transition: box-shadow .25s, -webkit-box-shadow .25s;
|
||||
margin-bottom: 10px;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 0.3rem;
|
||||
}
|
||||
.tabs>li,
|
||||
.cbi-tabmenu li {
|
||||
display: inline-block;
|
||||
@@ -1584,6 +1620,7 @@ textarea,
|
||||
margin-bottom: 0
|
||||
}
|
||||
|
||||
|
||||
[data-tab-title] {
|
||||
overflow: hidden;
|
||||
height: 0;
|
||||
@@ -2060,7 +2097,7 @@ body.modal-overlay-active #modal_overlay {
|
||||
|
||||
.notice {
|
||||
color: var(--primary-title-color);
|
||||
background-color: rgba(var(--primary-rgbbody), 1);
|
||||
background-color: rgba(var(--primary-rgbbody), 0.95);
|
||||
padding: 2rem 1rem
|
||||
}
|
||||
|
||||
@@ -2085,9 +2122,8 @@ body.modal-overlay-active #modal_overlay {
|
||||
.cbi-map {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
overflow-x: auto;
|
||||
gap: 1rem
|
||||
overflow-x: auto;
|
||||
/* gap: 1rem */
|
||||
}
|
||||
|
||||
.cbi-section,
|
||||
@@ -2111,7 +2147,7 @@ body.modal-overlay-active #modal_overlay {
|
||||
|
||||
.cbi-section {
|
||||
border: 0px solid rgba(0, 0, 0, 0);
|
||||
box-shadow: 0px 1px 0px var(--input-boxcolor);
|
||||
box-shadow: 0 1px 0px 0px var(--input-boxcolor), 0 0px 1px -1px var(--input-boxcolor);
|
||||
padding: 0
|
||||
}
|
||||
|
||||
@@ -2210,7 +2246,7 @@ table>thead>tr>th,
|
||||
letter-spacing: 1px;
|
||||
color: var(--body-color);
|
||||
white-space: nowrap;
|
||||
padding: 1.2rem 1.5rem
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
table .tr>.td.cbi-value-field,
|
||||
@@ -2220,9 +2256,12 @@ table .tr>.th.cbi-section-table-cell {
|
||||
display: table-cell !important;
|
||||
color: var(--body-color);
|
||||
white-space: nowrap;
|
||||
padding: 0.2rem
|
||||
width: auto;
|
||||
padding: 0.5rem
|
||||
}
|
||||
tr>td, tr>th, .tr>.td, .tr>.th, .cbi-section-table-row::before, #cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) {
|
||||
padding: 0.7rem 1rem;
|
||||
}
|
||||
|
||||
table .tr>.td.cbi-value-field>[id*="ifc-description"] {
|
||||
text-align: center;
|
||||
font-weight: 400 !important
|
||||
@@ -2251,28 +2290,29 @@ td.cbi-value-field var,
|
||||
.tr.table-titles>.th,
|
||||
.tr.cbi-section-table-titles>.th {
|
||||
font-size: var(--font-z);
|
||||
background-color: var(--menu-item-titlebg-color) !important;
|
||||
color: var(--title-color) !important;
|
||||
border-top: 0 !important;
|
||||
padding: 0.7rem 0.2rem !important
|
||||
}
|
||||
|
||||
.tr.table-titles>.th,
|
||||
.tr.cbi-section-table-titles>.th {
|
||||
background-color: var(--menu-item-titlebg-color) !important;
|
||||
}
|
||||
.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell {
|
||||
width: auto !important
|
||||
}
|
||||
|
||||
.cbi-tabcontainer>.cbi-value:nth-of-type(4n+2),
|
||||
.cbi-map>.cbi-section .cbi-value:nth-of-type(4n+2),
|
||||
fieldset>table>tbody>tr:nth-of-type(4n+2),
|
||||
.cbi-map>div>.cbi-section>.cbi-section-node>.cbi-value:nth-of-type(4n+1),
|
||||
table>tbody>tr:nth-of-type(4n+2),
|
||||
div>.table>.tr:nth-of-type(4n+2) {
|
||||
background-color: rgba(var(--primary-rgbs), var(--primary-rgbs-ts));
|
||||
background-image: var(--bgqs-image)
|
||||
}
|
||||
|
||||
.cbi-map>div>.cbi-section>.cbi-section-node>.cbi-value:nth-of-type(4n+2),
|
||||
.cbi-tabcontainer>.cbi-value:nth-of-type(4n),
|
||||
.cbi-map>.cbi-section .cbi-value:nth-of-type(4n),
|
||||
fieldset>table>tbody>tr:nth-of-type(4n),
|
||||
table>tbody>tr:nth-of-type(4n),
|
||||
div>.table>.tr:nth-of-type(4n) {
|
||||
background-color: rgba(var(--primary-rgbm), var(--primary-rgbs-ts));
|
||||
@@ -2281,17 +2321,16 @@ div>.table>.tr:nth-of-type(4n) {
|
||||
|
||||
.cbi-tabcontainer>.cbi-value:nth-of-type(4n+2):hover,
|
||||
.cbi-map>.cbi-section .cbi-value:nth-of-type(4n+2):hover,
|
||||
fieldset>table>tbody>tr:nth-of-type(4n+2):hover,
|
||||
.cbi-map>div>.cbi-section>.cbi-section-node>.cbi-value:nth-of-type(2n+1):hover,
|
||||
table>tbody>tr:nth-of-type(4n+2):hover,
|
||||
div>.table>.tr:nth-of-type(4n+2):hover,
|
||||
.cbi-tabcontainer>.cbi-value:nth-of-type(4n):hover,
|
||||
.cbi-map>.cbi-section .cbi-value:nth-of-type(4n):hover,
|
||||
fieldset>table>tbody>tr:nth-of-type(4n):hover,
|
||||
.cbi-map>div>.cbi-section>.cbi-section-node>.cbi-value:nth-of-type(2n):hover,
|
||||
table>tbody>tr:nth-of-type(4n):hover,
|
||||
div>.table>.tr:nth-of-type(4n):hover,
|
||||
.cbi-tabcontainer>.cbi-value:nth-of-type(2n+1):hover,
|
||||
.cbi-map>.cbi-section .cbi-value:nth-of-type(2n+1):hover,
|
||||
fieldset>table>tbody>tr:nth-of-type(2n+1):hover,
|
||||
table>tbody>tr:nth-of-type(2n+1):hover,
|
||||
div>.table>.tr:nth-of-type(2n+1):hover {
|
||||
background-color: var(--body-hover-bgcolor)
|
||||
@@ -2366,7 +2405,6 @@ div>.table>.tr:nth-of-type(2n+1):hover {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
line-height: 2.3rem;
|
||||
padding: 0 0.8rem
|
||||
}
|
||||
|
||||
.cbi-value:first-child {
|
||||
@@ -2508,7 +2546,10 @@ td>.ifacebadge,
|
||||
.nft-rules tr>td,
|
||||
.nft-rules tr>th {
|
||||
text-align: left !important;
|
||||
padding: 0 0.8rem !important
|
||||
}
|
||||
|
||||
.nft-rules tr>td{
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.network-status-table {
|
||||
@@ -2867,7 +2908,8 @@ body.lang_pl.node-main-login .cbi-value-title {
|
||||
}
|
||||
|
||||
.node-main-login>.main .cbi-map {
|
||||
padding: 1rem !important
|
||||
padding: 1rem !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.node-main-login>.main .container h2 {
|
||||
@@ -3065,6 +3107,7 @@ body.lang_pl.node-main-login .cbi-value-title {
|
||||
#view>div,
|
||||
#view>table {
|
||||
backdrop-filter: var(--ufilter);
|
||||
/* width: 100%; */
|
||||
-webkit-backdrop-filter: var(--ufilter)
|
||||
}
|
||||
|
||||
@@ -3117,7 +3160,6 @@ body.lang_pl.node-main-login .cbi-value-title {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
margin-bottom: 20px;
|
||||
margin-top: 5px;
|
||||
padding: 10px
|
||||
}
|
||||
|
||||
[data-page^="admin-status-channel"] #view>div:first-child,
|
||||
@@ -3184,6 +3226,7 @@ body.lang_pl.node-main-login .cbi-value-title {
|
||||
|
||||
[data-page^="admin-system-ttyd-ttyd"] #view>iframe {
|
||||
border-radius: var(--radius2) !important;
|
||||
padding: 0 1%;
|
||||
min-height: 600px !important
|
||||
}
|
||||
|
||||
@@ -3561,6 +3604,12 @@ pre {
|
||||
padding: 0 0.8rem
|
||||
}
|
||||
|
||||
.controls>*>.btn:not([aria-label$="page"]) {
|
||||
flex-grow: initial !important;
|
||||
margin-top: .25rem;
|
||||
padding: 0.5rem 1.2rem;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .pdboy-light:before,
|
||||
[data-theme="light"] .pdboy-dark:before {
|
||||
color: #aaa !important
|
||||
@@ -3660,8 +3709,7 @@ input,
|
||||
display: initial
|
||||
}
|
||||
|
||||
.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child,
|
||||
#cbi-firewall .cbi-value-field {
|
||||
.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
@@ -3852,9 +3900,6 @@ input,
|
||||
text-align: left
|
||||
}
|
||||
|
||||
.cbi-section {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
.cbi-tab-descr {
|
||||
padding: 0 0.3rem
|
||||
}
|
||||
@@ -3873,8 +3918,7 @@ input,
|
||||
table>tbody>tr>td,
|
||||
table>tfoot>tr>td,
|
||||
table>thead>tr>td {
|
||||
font-size: var(--font-x);
|
||||
color: var(--body-color);
|
||||
|
||||
padding: 1rem 0.5rem
|
||||
}
|
||||
|
||||
@@ -3912,6 +3956,12 @@ input,
|
||||
input[name="nslookup"] {
|
||||
width: 100%
|
||||
}
|
||||
[data-page="admin-network-diagnostics"] .tr .td {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
@@ -3950,7 +4000,7 @@ input,
|
||||
.th {
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
padding: 10px
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -4008,11 +4058,6 @@ input,
|
||||
padding: 0
|
||||
}
|
||||
|
||||
.cbi-input-textarea,
|
||||
textarea {
|
||||
width: 18rem !important;
|
||||
min-width: 8rem
|
||||
}
|
||||
|
||||
.modal.cbi-modal {
|
||||
max-width: 100%;
|
||||
@@ -4086,6 +4131,11 @@ input,
|
||||
[data-page^="admin-network-dhcp"] [data-tab-active="true"]{
|
||||
padding: 0 !important
|
||||
}
|
||||
|
||||
/* bandix */
|
||||
.device-card {
|
||||
background-color: rgba(var(--primary-rgbbody), 0.3)!important
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
|
||||
@@ -202,7 +202,7 @@ if (dayword == "1") {
|
||||
--menu-item-titlebg-color: rgba(var(--primary-rgbm),0.32);--body-hover-bgcolor: rgba(255,255,255,0.05);--menu-hover-color: #f5f5f5f5;--menu-fontcolor: #bbb;--primarytextcolor: #bbb;--primary-title-color: #ccc;--menu-color: #ddd;--title-color: #ddd;--body-color: #bbb;
|
||||
--primary-rgbbody:33,45,60;--inputtext-color: #ccc; --inputborder-color: rgba(255,255,255,0.2); --input-bgcolor: rgba(0,0,0,0.2); --input-boxcolor: rgba(255,255,255,0.22); --input-boxhovercolor: rgba(255,255,255,0.32); --input-checkcolor: rgba(255,255,255,0.7);--filter-color:invert(90%);
|
||||
{% else %}
|
||||
--menu-item-titlebg-color: rgba(var(--primary-rgbm),0.12);--body-hover-bgcolor: rgba(50,50,50,0.05);--menu-hover-color: #fff;--menu-fontcolor: #f5f5f5f5;--primarytextcolor: #505063;--primary-title-color: #4d4d5d;--menu-color: #eee;--title-color: #3c3c3c;--body-color: #424242;
|
||||
--menu-item-titlebg-color: rgba(var(--primary-rgbm),0.22);--body-hover-bgcolor: rgba(50,50,50,0.05);--menu-hover-color: #fff;--menu-fontcolor: #f5f5f5f5;--primarytextcolor: #505063;--primary-title-color: #4d4d5d;--menu-color: #eee;--title-color: #3c3c3c;--body-color: #424242;
|
||||
--primary-rgbbody:244,245,247;--inputtext-color: #383838; --inputborder-color: rgba(0,0,0,0.2); --input-bgcolor: rgba(255,255,255,0.2); --input-boxcolor: rgba(0,0,0,0.22); --input-boxhovercolor: rgba(0,0,0,0.32); --input-checkcolor: rgba(var(--primary-rgbm),1);--filter-color:invert(10%);
|
||||
{% endif %}
|
||||
{% if (bgqs == '0'): %}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=bandix
|
||||
PKG_VERSION:=0.9.0
|
||||
PKG_RELEASE:=2
|
||||
PKG_VERSION:=0.10.1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_MAINTAINER:=timsaya
|
||||
@@ -13,7 +13,7 @@ include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/rust/rust-values.mk
|
||||
|
||||
# 二进制文件的文件名和URL
|
||||
RUST_BANDIX_VERSION:=0.9.0
|
||||
RUST_BANDIX_VERSION:=0.10.1
|
||||
RUST_BINARY_FILENAME:=bandix-$(RUST_BANDIX_VERSION)-$(RUSTC_TARGET_ARCH).tar.gz
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user