🐶 Sync 2025-11-02 14:26:26

This commit is contained in:
actions-user
2025-11-02 14:26:26 +08:00
parent 64bcc56c2a
commit ac011db799
1557 changed files with 746465 additions and 0 deletions

View File

@@ -0,0 +1,862 @@
'use strict';
'require view';
'require ui';
'require uci';
'require rpc';
'require poll';
const translations = {
'zh-cn': {
'Bandix 连接监控': 'Bandix 连接监控',
'正在加载数据...': '正在加载数据...',
'无法获取数据': '无法获取数据',
'连接监控': '连接监控',
'设备连接统计': '设备连接统计',
'全局连接统计': '全局连接统计',
'设备': '设备',
'IP地址': 'IP地址',
'MAC地址': 'MAC地址',
'活跃TCP': '活跃TCP',
'活跃UDP': '活跃UDP',
'已关闭TCP': '已关闭TCP',
'总连接数': '总连接数',
'最后更新': '最后更新',
'总连接数统计': '总连接数统计',
'TCP连接数': 'TCP连接数',
'UDP连接数': 'UDP连接数',
'已建立TCP': '已建立TCP',
'TIME_WAIT TCP': 'TIME_WAIT TCP',
'CLOSE_WAIT TCP': 'CLOSE_WAIT TCP',
'设备总数': '设备总数',
'连接监控未启用': '连接监控未启用',
'请在设置中启用连接监控功能': '请在设置中启用连接监控功能',
'前往设置': '前往设置',
'无数据': '无数据',
'未知设备': '未知设备',
'在线设备': '在线设备',
'从未上线': '从未上线',
'刚刚': '刚刚',
'分钟前': '分钟前',
'小时前': '小时前',
'天前': '天前',
'个月前': '个月前',
'年前': '年前',
'最后上线': '最后上线',
'列表只显示局域网设备连接,数据可能和总连接数不一致。': '列表只显示局域网设备连接,数据可能和总连接数不一致。',
'TCP 状态详情': 'TCP 状态详情'
},
'zh-tw': {
'Bandix 连接监控': 'Bandix 連接監控',
'正在加载数据...': '正在載入資料...',
'无法获取数据': '無法獲取資料',
'连接监控': '連接監控',
'设备连接统计': '設備連接統計',
'全局连接统计': '全局連接統計',
'设备': '設備',
'IP地址': 'IP地址',
'MAC地址': 'MAC地址',
'活跃TCP': '活躍TCP',
'活跃UDP': '活躍UDP',
'已关闭TCP': '已關閉TCP',
'总连接数': '總連接數',
'最后更新': '最後更新',
'总连接数统计': '總連接數統計',
'TCP连接数': 'TCP連接數',
'UDP连接数': 'UDP連接數',
'已建立TCP': '已建立TCP',
'TIME_WAIT TCP': 'TIME_WAIT TCP',
'CLOSE_WAIT TCP': 'CLOSE_WAIT TCP',
'设备总数': '設備總數',
'连接监控未启用': '連接監控未啟用',
'请在设置中启用连接监控功能': '請在設置中啟用連接監控功能',
'前往设置': '前往設置',
'无数据': '無數據',
'未知设备': '未知設備',
'在线设备': '在線設備',
'从未上线': '從未上線',
'刚刚': '剛剛',
'分钟前': '分鐘前',
'小时前': '小時前',
'天前': '天前',
'个月前': '個月前',
'年前': '年前',
'最后上线': '最後上線',
'列表只显示局域网设备连接,数据可能和总连接数不一致。': '列表只顯示局域網設備連接,數據可能和總連接數不一致。',
'TCP 状态详情': 'TCP 狀態詳情'
},
'en': {
'Bandix 连接监控': 'Bandix Connection Monitor',
'正在加载数据...': 'Loading data...',
'无法获取数据': 'Unable to fetch data',
'连接监控': 'Connection Monitor',
'设备连接统计': 'Device Connection Statistics',
'全局连接统计': 'Global Connection Statistics',
'设备': 'Device',
'IP地址': 'IP Address',
'MAC地址': 'MAC Address',
'活跃TCP': 'Active TCP',
'活跃UDP': 'Active UDP',
'已关闭TCP': 'Closed TCP',
'总连接数': 'Total Connections',
'最后更新': 'Last Updated',
'总连接数统计': 'Total Connections',
'TCP连接数': 'TCP Connections',
'UDP连接数': 'UDP Connections',
'已建立TCP': 'Established TCP',
'TIME_WAIT TCP': 'TIME_WAIT TCP',
'CLOSE_WAIT TCP': 'CLOSE_WAIT TCP',
'设备总数': 'Total Devices',
'连接监控未启用': 'Connection Monitor Disabled',
'请在设置中启用连接监控功能': 'Please enable connection monitoring in settings',
'前往设置': 'Go to Settings',
'无数据': 'No Data',
'未知设备': 'Unknown Device',
'在线设备': 'Online Devices',
'从未上线': 'Never Online',
'刚刚': 'Just now',
'分钟前': 'minutes ago',
'小时前': 'hours ago',
'天前': 'days ago',
'个月前': 'months ago',
'年前': 'years ago',
'最后上线': 'Last seen',
'列表只显示局域网设备连接,数据可能和总连接数不一致。': 'List only shows LAN device connections, data may differ from total connections.',
'TCP 状态详情': 'TCP Status Details'
},
'fr': {
'Bandix 连接监控': 'Surveillance de Connexion Bandix',
'正在加载数据...': 'Chargement des données...',
'无法获取数据': 'Impossible de récupérer les données',
'连接监控': 'Surveillance des Connexions',
'设备连接统计': 'Statistiques de Connexion des Appareils',
'全局连接统计': 'Statistiques de Connexion Globales',
'设备': 'Appareil',
'IP地址': 'Adresse IP',
'MAC地址': 'Adresse MAC',
'活跃TCP': 'TCP Actif',
'活跃UDP': 'UDP Actif',
'已关闭TCP': 'TCP Fermé',
'总连接数': 'Total des Connexions',
'最后更新': 'Dernière Mise à Jour',
'总连接数统计': 'Total des Connexions',
'TCP连接数': 'Connexions TCP',
'UDP连接数': 'Connexions UDP',
'已建立TCP': 'TCP Établi',
'TIME_WAIT TCP': 'TCP TIME_WAIT',
'CLOSE_WAIT TCP': 'TCP CLOSE_WAIT',
'设备总数': 'Total des Appareils',
'连接监控未启用': 'Surveillance des Connexions Désactivée',
'请在设置中启用连接监控功能': 'Veuillez activer la surveillance des connexions dans les paramètres',
'前往设置': 'Aller aux Paramètres',
'无数据': 'Aucune Donnée',
'未知设备': 'Appareil Inconnu',
'在线设备': 'Appareils En Ligne',
'从未上线': 'Jamais En Ligne',
'刚刚': 'À l\'instant',
'分钟前': 'il y a minutes',
'小时前': 'il y a heures',
'天前': 'il y a jours',
'个月前': 'il y a mois',
'年前': 'il y a années',
'最后上线': 'Dernier Vue',
'列表只显示局域网设备连接,数据可能和总连接数不一致。': 'La liste ne montre que les connexions des appareils LAN, les données peuvent différer du total des connexions.',
'TCP 状态详情': 'Détails du Statut TCP'
},
'ja': {
'Bandix 连接监控': 'Bandix 接続監視',
'正在加载数据...': 'データを読み込み中...',
'无法获取数据': 'データを取得できません',
'连接监控': '接続監視',
'设备连接统计': 'デバイス接続統計',
'全局连接统计': 'グローバル接続統計',
'设备': 'デバイス',
'IP地址': 'IPアドレス',
'MAC地址': 'MACアドレス',
'活跃TCP': 'アクティブTCP',
'活跃UDP': 'アクティブUDP',
'已关闭TCP': 'クローズドTCP',
'总连接数': '総接続数',
'最后更新': '最終更新',
'总连接数统计': '総接続数',
'TCP连接数': 'TCP接続数',
'UDP连接数': 'UDP接続数',
'已建立TCP': 'TCP確立済',
'TIME_WAIT TCP': 'TCP TIME_WAIT',
'CLOSE_WAIT TCP': 'TCP CLOSE_WAIT',
'设备总数': '総デバイス数',
'连接监控未启用': '接続監視が無効',
'请在设置中启用连接监控功能': '設定で接続監視機能を有効にしてください',
'前往设置': '設定に移動',
'无数据': 'データなし',
'未知设备': '不明なデバイス',
'在线设备': 'オンラインデバイス',
'从未上线': '未接続',
'刚刚': 'たった今',
'分钟前': '分前',
'小时前': '時間前',
'天前': '日前',
'个月前': 'ヶ月前',
'年前': '年前',
'最后上线': '最後の接続',
'列表只显示局域网设备连接,数据可能和总连接数不一致。': 'リストはLANデバイスの接続のみを表示し、データは総接続数と異なる場合があります。',
'TCP 状态详情': 'TCP状態詳細'
},
'ru': {
'Bandix 连接监控': 'Мониторинг Соединений Bandix',
'正在加载数据...': 'Загрузка данных...',
'无法获取数据': 'Не удалось получить данные',
'连接监控': 'Мониторинг Соединений',
'设备连接统计': 'Статистика Соединений Устройств',
'全局连接统计': 'Глобальная Статистика Соединений',
'设备': 'Устройство',
'IP地址': 'IP-адрес',
'MAC地址': 'MAC-адрес',
'活跃TCP': 'Активные TCP',
'活跃UDP': 'Активные UDP',
'已关闭TCP': 'Закрытые TCP',
'总连接数': 'Всего Соединений',
'最后更新': 'Последнее Обновление',
'总连接数统计': 'Всего Соединений',
'TCP连接数': 'TCP Соединения',
'UDP连接数': 'UDP Соединения',
'已建立TCP': 'Установленные TCP',
'TIME_WAIT TCP': 'TCP TIME_WAIT',
'CLOSE_WAIT TCP': 'TCP CLOSE_WAIT',
'设备总数': 'Всего Устройств',
'连接监控未启用': 'Мониторинг Соединений Отключен',
'请在设置中启用连接监控功能': 'Пожалуйста, включите мониторинг соединений в настройках',
'前往设置': 'Перейти к Настройкам',
'无数据': 'Нет Данных',
'未知设备': 'Неизвестное Устройство',
'在线设备': 'Устройства Онлайн',
'从未上线': 'Никогда Не Было Онлайн',
'刚刚': 'Только что',
'分钟前': 'минут назад',
'小时前': 'часов назад',
'天前': 'дней назад',
'个月前': 'месяцев назад',
'年前': 'лет назад',
'最后上线': 'Последний раз видели',
'列表只显示局域网设备连接,数据可能和总连接数不一致。': 'Список показывает только соединения LAN-устройств, данные могут отличаться от общего количества соединений.',
'TCP 状态详情': 'Детали Статуса TCP'
}
};
function getTranslation(key, language) {
return translations[language]?.[key] || key;
}
// 获取系统语言
function getSystemLanguage() {
var luciLang = uci.get('luci', 'main', 'lang');
if (luciLang && translations[luciLang]) {
return luciLang;
}
var systemLang = document.documentElement.lang || 'en';
if (translations[systemLang]) {
return systemLang;
}
return 'en';
}
// 检查是否为暗黑模式
function isDarkMode() {
// 首先检查用户设置的主题
var userTheme = uci.get('bandix', 'general', 'theme');
if (userTheme) {
if (userTheme === 'dark') {
return true;
} else if (userTheme === 'light') {
return false;
}
// 如果是 'auto',继续检查系统主题
}
// 获取 LuCI 主题设置
var mediaUrlBase = uci.get('luci', 'main', 'mediaurlbase');
if (mediaUrlBase && mediaUrlBase.toLowerCase().includes('dark')) {
return true;
}
// 如果是 argon 主题,检查 argon 配置
if (mediaUrlBase && mediaUrlBase.toLowerCase().includes('argon')) {
var argonMode = uci.get('argon', '@global[0]', 'mode');
if (argonMode) {
if (argonMode.toLowerCase() === 'dark') {
return true;
} else if (argonMode.toLowerCase() === 'light') {
return false;
}
// 如果是 'normal' 或 'auto',使用浏览器检测系统颜色偏好
if (argonMode.toLowerCase() === 'normal' || argonMode.toLowerCase() === 'auto') {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return true;
}
return false;
}
}
}
// 默认情况下也使用浏览器检测系统颜色偏好
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return true;
}
return false;
}
// 格式化时间戳
function formatTimestamp(timestamp) {
if (!timestamp) return getTranslation('从未上线', getSystemLanguage());
var now = Math.floor(Date.now() / 1000);
var diff = now - timestamp;
var language = getSystemLanguage();
if (diff < 60) {
return getTranslation('刚刚', language);
} else if (diff < 3600) {
var minutes = Math.floor(diff / 60);
return minutes + ' ' + getTranslation('分钟前', language);
} else if (diff < 86400) {
var hours = Math.floor(diff / 3600);
return hours + ' ' + getTranslation('小时前', language);
} else if (diff < 2592000) {
var days = Math.floor(diff / 86400);
return days + ' ' + getTranslation('天前', language);
} else if (diff < 31536000) {
var months = Math.floor(diff / 2592000);
return months + ' ' + getTranslation('个月前', language);
} else {
var years = Math.floor(diff / 31536000);
return years + ' ' + getTranslation('年前', language);
}
}
// 格式化设备名称
function formatDeviceName(device) {
if (device.hostname && device.hostname !== '') {
return device.hostname;
}
return device.ip_address || device.mac_address || getTranslation('未知设备', getSystemLanguage());
}
// RPC调用
var callGetConnection = rpc.declare({
object: 'luci.bandix',
method: 'getConnection',
expect: {}
});
return view.extend({
load: function () {
return Promise.all([
uci.load('bandix'),
uci.load('luci'),
uci.load('argon').catch(function () {
return null;
})
]);
},
render: function (data) {
var language = uci.get('bandix', 'general', 'language');
if (!language || language === 'auto') {
language = getSystemLanguage();
}
var darkMode = isDarkMode();
var connectionEnabled = uci.get('bandix', 'connections', 'enabled') === '1';
// 创建样式
var style = E('style', {}, `
.bandix-connection-container {
margin: 0;
padding: 24px;
background-color: ${darkMode ? '#1E1E1E' : '#f8fafc'};
min-height: calc(100vh - 100px);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: ${darkMode ? '#e2e8f0' : '#1f2937'};
border-radius: 8px;
}
.bandix-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.bandix-title {
font-size: 1.5rem;
font-weight: 700;
color: ${darkMode ? '#f1f5f9' : '#1f2937'};
margin: 0;
}
.bandix-badge {
background-color: ${darkMode ? '#333333' : '#f3f4f6'};
border: 1px solid ${darkMode ? '#252526' : '#d1d5db'};
border-radius: 6px;
padding: 4px 12px;
font-size: 0.875rem;
color: ${darkMode ? '#e2e8f0' : '#374151'};
}
.bandix-alert {
background-color: ${darkMode ? '#451a03' : '#fef3c7'};
border: 1px solid ${darkMode ? '#92400e' : '#f59e0b'};
border-radius: 8px;
padding: 8px;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
color: ${darkMode ? '#fbbf24' : '#92400e'};
}
.bandix-alert-icon {
color: ${darkMode ? '#fbbf24' : '#f59e0b'};
font-size: 1rem;
}
.bandix-card {
background-color: ${darkMode ? '#252526' : 'white'};
border-radius: 12px;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, ${darkMode ? '0.3' : '0.1'});
margin-bottom: 24px;
overflow: hidden;
}
.bandix-card-header {
padding: 20px 24px 16px;
border-bottom: 1px solid ${darkMode ? '#252526' : '#e5e7eb'};
background-color: ${darkMode ? '#333333' : '#fafafa'};
}
.bandix-card-title {
font-size: 1.125rem;
font-weight: 600;
color: ${darkMode ? '#f1f5f9' : '#1f2937'};
margin: 0;
display: flex;
align-items: center;
gap: 8px;
}
.bandix-card-body {
padding: 24px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
margin-bottom: 32px;
}
.stats-card {
background-color: ${darkMode ? '#252526' : 'white'};
border-radius: 12px;
padding: 20px;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, ${darkMode ? '0.3' : '0.1'});
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.stats-card-title {
font-size: 0.875rem;
font-weight: 500;
color: ${darkMode ? '#9ca3af' : '#6b7280'};
margin: 0 0 12px 0;
}
.stats-card-main-value {
font-size: 2.25rem;
font-weight: 700;
color: ${darkMode ? '#f1f5f9' : '#1f2937'};
margin: 0 0 8px 0;
line-height: 1;
}
.stats-card-details {
margin-top: 12px;
display: flex;
flex-direction: column;
gap: 6px;
width: 100%;
}
.stats-detail-row {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.875rem;
}
.stats-detail-label {
color: ${darkMode ? '#9ca3af' : '#6b7280'};
font-weight: 500;
}
.stats-detail-value {
font-weight: 600;
color: ${darkMode ? '#e2e8f0' : '#374151'};
}
.bandix-table {
width: 100%;
border-collapse: collapse;
background-color: transparent;
table-layout: fixed;
}
.bandix-table th {
background-color: ${darkMode ? '#333333' : '#f9fafb'};
padding: 16px 20px;
text-align: left;
font-weight: 600;
color: ${darkMode ? '#e2e8f0' : '#374151'};
border: none;
font-size: 0.875rem;
white-space: nowrap;
}
.bandix-table th:nth-child(1) { width: 30%; }
.bandix-table th:nth-child(2) { width: 12%; }
.bandix-table th:nth-child(3) { width: 12%; }
.bandix-table th:nth-child(4) { width: 31%; }
.bandix-table th:nth-child(5) { width: 15%; }
.bandix-table td {
padding: 16px 20px;
border-bottom: 1px solid ${darkMode ? '#252526' : '#f1f5f9'};
vertical-align: middle;
word-break: break-word;
overflow-wrap: break-word;
color: ${darkMode ? '#cbd5e1' : 'inherit'};
}
.device-info {
display: flex;
align-items: center;
gap: 12px;
}
.device-status {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.device-status.online {
background-color: #10b981;
}
.device-status.offline {
background-color: #9ca3af;
}
.device-details {
min-width: 0;
flex: 1;
}
.device-name {
font-weight: 600;
color: ${darkMode ? '#f1f5f9' : '#1f2937'};
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 4px;
}
.device-ip {
color: ${darkMode ? '#94a3b8' : '#6b7280'};
font-size: 0.875rem;
}
.device-mac {
color: ${darkMode ? '#64748b' : '#9ca3af'};
font-size: 0.75rem;
}
.tcp-status-details {
display: flex;
flex-direction: column;
gap: 6px;
font-size: 0.875rem;
}
.tcp-status-item {
display: flex;
align-items: center;
gap: 8px;
}
.tcp-status-label {
display: inline-block;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 600;
color: white;
min-width: 50px;
text-align: center;
}
.tcp-status-label.established {
background-color: #10b981;
}
.tcp-status-label.time-wait {
background-color: #f59e0b;
}
.tcp-status-label.closed {
background-color: #6b7280;
}
.tcp-status-value {
font-weight: 600;
color: ${darkMode ? '#e2e8f0' : '#374151'};
}
.loading-state {
text-align: center;
padding: 40px;
color: ${darkMode ? '#94a3b8' : '#6b7280'};
font-style: italic;
}
.error-state {
text-align: center;
padding: 40px;
color: ${darkMode ? '#f87171' : '#ef4444'};
}
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
border-radius: 6px;
font-size: 0.875rem;
font-weight: 500;
text-decoration: none;
border: none;
cursor: pointer;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.btn-primary {
background-color: #3b82f6;
color: white;
}
.btn-primary:hover {
background-color: #2563eb;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
`);
document.head.appendChild(style);
var container = E('div', { 'class': 'bandix-connection-container' });
// 页面标题
var header = E('div', { 'class': 'bandix-header' }, [
E('h1', { 'class': 'bandix-title' }, getTranslation('Bandix 连接监控', language))
]);
container.appendChild(header);
// 检查连接监控是否启用
if (!connectionEnabled) {
var alertDiv = E('div', { 'class': 'bandix-alert' }, [
E('span', { 'class': 'bandix-alert-icon' }, '⚠'),
E('div', {}, [
E('strong', {}, getTranslation('连接监控未启用', language)),
E('p', { 'style': 'margin: 4px 0 0 0;' },
getTranslation('请在设置中启用连接监控功能', language))
])
]);
container.appendChild(alertDiv);
var settingsCard = E('div', { 'class': 'bandix-card' }, [
E('div', { 'class': 'bandix-card-body', 'style': 'text-align: center;' }, [
E('a', {
'href': '/cgi-bin/luci/admin/network/bandix/settings',
'class': 'btn btn-primary'
}, getTranslation('前往设置', language))
])
]);
container.appendChild(settingsCard);
return container;
}
// 添加提示信息
var infoAlert = E('div', { 'class': 'bandix-alert' }, [
E('span', { 'class': 'bandix-alert-icon' }, '⚠️'),
E('span', {}, getTranslation('列表只显示局域网设备连接,数据可能和总连接数不一致。', language))
]);
container.appendChild(infoAlert);
// 全局统计卡片
var statsGrid = E('div', { 'class': 'stats-grid' }, [
E('div', { 'class': 'stats-card' }, [
E('div', { 'class': 'stats-card-title' }, getTranslation('总连接数统计', language)),
E('div', { 'class': 'stats-card-main-value', 'id': 'total-connections' }, '-')
]),
E('div', { 'class': 'stats-card' }, [
E('div', { 'class': 'stats-card-title' }, getTranslation('TCP连接数', language)),
E('div', { 'class': 'stats-card-main-value', 'id': 'tcp-connections' }, '-'),
E('div', { 'class': 'stats-card-details' }, [
E('div', { 'class': 'stats-detail-row' }, [
E('span', { 'class': 'stats-detail-label' }, 'ESTABLISHED'),
E('span', { 'class': 'stats-detail-value', 'id': 'established-tcp' }, '-')
]),
E('div', { 'class': 'stats-detail-row' }, [
E('span', { 'class': 'stats-detail-label' }, 'TIME_WAIT'),
E('span', { 'class': 'stats-detail-value', 'id': 'time-wait-tcp' }, '-')
]),
E('div', { 'class': 'stats-detail-row' }, [
E('span', { 'class': 'stats-detail-label' }, 'CLOSE_WAIT'),
E('span', { 'class': 'stats-detail-value', 'id': 'close-wait-tcp' }, '-')
])
])
]),
E('div', { 'class': 'stats-card' }, [
E('div', { 'class': 'stats-card-title' }, getTranslation('UDP连接数', language)),
E('div', { 'class': 'stats-card-main-value', 'id': 'udp-connections' }, '-')
])
]);
container.appendChild(statsGrid);
// 设备连接统计表格
var deviceCard = E('div', { 'class': 'bandix-card' }, [
E('div', { 'class': 'bandix-card-body' }, [
E('div', { 'id': 'device-table-container' }, [
E('table', { 'class': 'bandix-table' }, [
E('thead', {}, [
E('tr', {}, [
E('th', {}, getTranslation('设备', language)),
E('th', {}, 'TCP'),
E('th', {}, 'UDP'),
E('th', {}, getTranslation('TCP 状态详情', language)),
E('th', {}, getTranslation('总连接数', language))
])
]),
E('tbody', {})
])
])
])
]);
container.appendChild(deviceCard);
// 更新全局统计
function updateGlobalStats(stats) {
if (!stats) return;
document.getElementById('total-connections').textContent = stats.total_connections || 0;
document.getElementById('tcp-connections').textContent = stats.tcp_connections || 0;
document.getElementById('udp-connections').textContent = stats.udp_connections || 0;
document.getElementById('established-tcp').textContent = stats.established_tcp || 0;
document.getElementById('time-wait-tcp').textContent = stats.time_wait_tcp || 0;
document.getElementById('close-wait-tcp').textContent = stats.close_wait_tcp || 0;
}
// 更新设备表格
function updateDeviceTable(devices) {
var container = document.getElementById('device-table-container');
if (!devices || devices.length === 0) {
container.innerHTML = '';
container.appendChild(E('div', { 'class': 'loading-state' },
getTranslation('无数据', language)));
return;
}
var table = E('table', { 'class': 'bandix-table' }, [
E('thead', {}, [
E('tr', {}, [
E('th', {}, getTranslation('设备', language)),
E('th', {}, 'TCP'),
E('th', {}, 'UDP'),
E('th', {}, getTranslation('TCP 状态详情', language)),
E('th', {}, getTranslation('总连接数', language))
])
]),
E('tbody', {}, devices.map(function (device) {
return E('tr', {}, [
E('td', {}, [
E('div', { 'class': 'device-info' }, [
E('div', { 'class': 'device-status online' }),
E('div', { 'class': 'device-details' }, [
E('div', { 'class': 'device-name' }, formatDeviceName(device)),
E('div', { 'class': 'device-ip' }, device.ip_address || '-'),
E('div', { 'class': 'device-mac' }, device.mac_address || '-')
])
])
]),
E('td', { 'style': 'font-weight: 600;' }, device.tcp_connections || 0),
E('td', { 'style': 'font-weight: 600;' }, device.udp_connections || 0),
E('td', {}, [
E('div', { 'class': 'tcp-status-details' }, [
E('div', { 'class': 'tcp-status-item' }, [
E('span', { 'class': 'tcp-status-label established' }, 'EST'),
E('span', { 'class': 'tcp-status-value' }, device.established_tcp || 0)
]),
E('div', { 'class': 'tcp-status-item' }, [
E('span', { 'class': 'tcp-status-label time-wait' }, 'WAIT'),
E('span', { 'class': 'tcp-status-value' }, device.time_wait_tcp || 0)
]),
E('div', { 'class': 'tcp-status-item' }, [
E('span', { 'class': 'tcp-status-label closed' }, 'CLOSE'),
E('span', { 'class': 'tcp-status-value' }, device.close_wait_tcp || 0)
])
])
]),
E('td', {}, E('strong', {}, device.total_connections || 0))
]);
}))
]);
container.innerHTML = '';
container.appendChild(table);
}
// 显示错误信息
function showError(message) {
var container = document.getElementById('device-table-container');
container.innerHTML = '';
container.appendChild(E('div', { 'class': 'error-state' }, message));
}
// 定义更新连接数据的函数
function updateConnectionData() {
return callGetConnection().then(function (result) {
if (result && result.status === 'success' && result.data) {
updateGlobalStats(result.data.global_stats);
updateDeviceTable(result.data.devices);
} else {
showError(getTranslation('无法获取数据', language));
}
}).catch(function (error) {
console.error('Failed to load connection data:', error);
showError(getTranslation('无法获取数据', language));
});
}
// 轮询获取数据
poll.add(updateConnectionData, 1);
// 立即执行一次,不等待轮询
updateConnectionData();
return container;
}
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,681 @@
'use strict';
'require view';
'require form';
'require ui';
'require uci';
'require fs';
const translations = {
'zh-cn': {
'基本设置': '基本设置',
'流量监控设置': '流量监控设置',
'连接监控设置': '连接监控设置',
'Bandix 基本配置': 'Bandix 基本配置',
'配置 Bandix 服务的基本参数': '配置 Bandix 服务的基本参数',
'Bandix 流量监控配置': 'Bandix 流量监控配置',
'配置流量监控相关参数': '配置流量监控相关参数',
'Bandix 连接监控配置': 'Bandix 连接监控配置',
'配置连接监控相关参数': '配置连接监控相关参数',
'启用': '启用',
'启用 Bandix 流量监控服务': '启用 Bandix 流量监控服务',
'启用流量监控': '启用流量监控',
'启用连接监控': '启用连接监控',
'界面语言': '界面语言',
'选择 Bandix 流量监控的显示语言': '选择 Bandix 流量监控的显示语言',
'简体中文': '简体中文',
'繁体中文': '繁体中文',
'端口': '端口',
'Bandix 服务监听的端口': 'Bandix 服务监听的端口',
'监控网卡': '监控网卡',
'选择要监控的网络接口': '选择要监控的LAN网络接口',
'网速单位': '网速单位',
'选择网速显示的单位格式': '选择网速显示的单位格式',
'字节单位 (B/s, KB/s, MB/s)': '字节单位 (B/s, KB/s, MB/s)',
'比特单位 (bps, Kbps, Mbps)': '比特单位 (bps, Kbps, Mbps)',
'界面主题': '界面主题',
'选择 Bandix 流量监控的显示主题': '选择 Bandix 流量监控的显示主题',
'跟随系统': '跟随系统',
'明亮模式': '明亮模式',
'暗黑模式': '暗黑模式',
'意见反馈': '意见反馈',
'离线超时时间': '离线超时时间',
'设置设备离线判断的超时时间(秒)': '设置设备离线判断的超时时间(秒)。超过此时间未活动的设备将被标记为离线',
'历史流量周期': '历史流量周期',
'设置历史流量数据周期': '10分钟下1个设备固定占用约60KB修改会清空已有数据。\n由于ubus单次通信限制无法设置更大的值。',
'数据 flush 间隔': '数据 flush 间隔',
'设置数据 flush 间隔': '设置数据写入磁盘的时间间隔',
'1 分钟': '1 分钟',
'5 分钟': '5 分钟',
'10 分钟': '10 分钟',
'15 分钟': '15 分钟',
'20 分钟': '20 分钟',
'25 分钟': '25 分钟',
'30 分钟': '30 分钟',
'1 小时': '1 小时',
'2 小时': '2 小时',
'数据目录': '数据目录',
'Bandix 数据存储目录': 'Bandix 数据存储目录',
'启用 Bandix 连接监控功能': '启用 Bandix 连接监控功能',
'持久化历史数据': '持久化历史数据',
'启用数据持久化功能': '启用数据持久化功能,只有启用此选项后才会持久化到磁盘'
},
'zh-tw': {
'基本设置': '基本設置',
'流量监控设置': '流量監控設置',
'连接监控设置': '連接監控設置',
'Bandix 基本配置': 'Bandix 基本配置',
'配置 Bandix 服务的基本参数': '配置 Bandix 服務的基本參數',
'Bandix 流量监控配置': 'Bandix 流量監控配置',
'配置流量监控相关参数': '配置流量監控相關參數',
'Bandix 连接监控配置': 'Bandix 連接監控配置',
'配置连接监控相关参数': '配置連接監控相關參數',
'启用': '啟用',
'启用 Bandix 流量监控服务': '啟用 Bandix 流量監控服務',
'启用流量监控': '啟用流量監控',
'启用连接监控': '啟用連接監控',
'界面语言': '界面語言',
'选择 Bandix 流量监控的显示语言': '選擇 Bandix 流量監控的顯示語言',
'简体中文': '簡體中文',
'繁体中文': '繁體中文',
'端口': '端口',
'Bandix 服务监听的端口': 'Bandix 服務監聽的端口',
'监控网卡': '監控網卡',
'选择要监控的网络接口': '選擇要監控的LAN網絡接口',
'网速单位': '網速單位',
'选择网速显示的单位格式': '選擇網速顯示的單位格式',
'字节单位 (B/s, KB/s, MB/s)': '字節單位 (B/s, KB/s, MB/s)',
'比特单位 (bps, Kbps, Mbps)': '比特單位 (bps, Kbps, Mbps)',
'界面主题': '介面主題',
'选择 Bandix 流量监控的显示主题': '選擇 Bandix 流量監控的顯示主題',
'跟随系统': '跟隨系統',
'明亮模式': '明亮模式',
'暗黑模式': '暗黑模式',
'意见反馈': '意見反饋',
'离线超时时间': '離線超時時間',
'设置设备离线判断的超时时间(秒)': '設定設備離線判斷的超時時間(秒)。超過此時間未活動的設備將被標記為離線',
'历史流量周期': '歷史流量週期',
'设置历史流量数据周期': '10分鐘下1個設備固定占用約60KB修改會清空已有資料。\n由於ubus單次通信限制無法設置更大的值。',
'数据 flush 间隔': '資料flush間隔',
'设置数据 flush 间隔': '設定資料寫入磁碟的時間間隔',
'1 分钟': '1 分鐘',
'5 分钟': '5 分鐘',
'10 分钟': '10 分鐘',
'15 分钟': '15 分鐘',
'20 分钟': '20 分鐘',
'25 分钟': '25 分鐘',
'30 分钟': '30 分鐘',
'1 小时': '1 小時',
'2 小时': '2 小時',
'数据目录': '數據目錄',
'Bandix 数据存储目录': 'Bandix 數據存儲目錄',
'启用 Bandix 连接监控功能': '啟用 Bandix 連接監控功能',
'持久化历史数据': '持久化歷史數據',
'启用数据持久化功能': '啟用數據持久化功能,只有啟用此選項後才會持久化到磁碟'
},
'en': {
'基本设置': 'Basic Settings',
'流量监控设置': 'Traffic Monitor Settings',
'连接监控设置': 'Connection Monitor Settings',
'Bandix 基本配置': 'Bandix Basic Configuration',
'配置 Bandix 服务的基本参数': 'Configure basic parameters for Bandix service',
'Bandix 流量监控配置': 'Bandix Traffic Monitor Configuration',
'配置流量监控相关参数': 'Configure traffic monitoring related parameters',
'Bandix 连接监控配置': 'Bandix Connection Monitor Configuration',
'配置连接监控相关参数': 'Configure connection monitoring related parameters',
'启用': 'Enable',
'启用 Bandix 流量监控服务': 'Enable Bandix Traffic Monitor Service',
'启用流量监控': 'Enable Traffic Monitoring',
'启用连接监控': 'Enable Connection Monitoring',
'界面语言': 'Interface Language',
'选择 Bandix 流量监控的显示语言': 'Select the display language for Bandix Traffic Monitor',
'简体中文': 'Simplified Chinese',
'繁体中文': 'Traditional Chinese',
'端口': 'Port',
'Bandix 服务监听的端口': 'Port for Bandix service to listen on',
'监控网卡': 'Monitor Interface',
'选择要监控的网络接口': 'Select the LAN network interface to monitor',
'网速单位': 'Speed Units',
'选择网速显示的单位格式': 'Select the speed display unit format',
'字节单位 (B/s, KB/s, MB/s)': 'Bytes Units (B/s, KB/s, MB/s)',
'比特单位 (bps, Kbps, Mbps)': 'Bits Units (bps, Kbps, Mbps)',
'界面主题': 'Interface Theme',
'选择 Bandix 流量监控的显示主题': 'Select the display theme for Bandix Traffic Monitor',
'跟随系统': 'Follow System',
'明亮模式': 'Light Mode',
'暗黑模式': 'Dark Mode',
'意见反馈': 'Feedback',
'离线超时时间': 'Offline Timeout',
'设置设备离线判断的超时时间(秒)': 'Set the timeout for device offline detection (seconds). Devices inactive for longer than this time will be marked as offline',
'历史流量周期': 'Traffic History Period',
'设置历史流量数据周期': 'With 10-minute interval, 1 device uses a fixed size of about 60 KB, changing will clear existing data.\nDue to ubus single communication limit, larger values cannot be set.',
'数据 flush 间隔': 'Data Flush Interval',
'设置数据 flush 间隔': 'Set the interval for flushing data to disk',
'1 分钟': '1 minute',
'5 分钟': '5 minutes',
'10 分钟': '10 minutes',
'15 分钟': '15 minutes',
'20 分钟': '20 minutes',
'25 分钟': '25 minutes',
'30 分钟': '30 minutes',
'1 小时': '1 hour',
'2 小时': '2 hours',
'数据目录': 'Data Directory',
'Bandix 数据存储目录': 'Bandix data storage directory',
'启用 Bandix 连接监控功能': 'Enable Bandix connection monitoring',
'持久化历史数据': 'Persist History Data',
'启用数据持久化功能': 'Enable data persistence functionality, data will only be persisted to disk when this option is enabled'
},
'fr': {
'基本设置': 'Paramètres de Base',
'流量监控设置': 'Paramètres de Surveillance du Trafic',
'连接监控设置': 'Paramètres de Surveillance des Connexions',
'Bandix 基本配置': 'Configuration de Base Bandix',
'配置 Bandix 服务的基本参数': 'Configurer les paramètres de base du service Bandix',
'Bandix 流量监控配置': 'Configuration de Surveillance du Trafic Bandix',
'配置流量监控相关参数': 'Configurer les paramètres liés à la surveillance du trafic',
'Bandix 连接监控配置': 'Configuration de Surveillance des Connexions Bandix',
'配置连接监控相关参数': 'Configurer les paramètres liés à la surveillance des connexions',
'启用': 'Activer',
'启用 Bandix 流量监控服务': 'Activer le Service de Surveillance du Trafic Bandix',
'启用流量监控': 'Activer la Surveillance du Trafic',
'启用连接监控': 'Activer la Surveillance des Connexions',
'界面语言': 'Langue de l\'Interface',
'选择 Bandix 流量监控的显示语言': 'Sélectionner la langue d\'affichage pour le Moniteur de Trafic Bandix',
'简体中文': 'Chinois Simplifié',
'繁体中文': 'Chinois Traditionnel',
'端口': 'Port',
'Bandix 服务监听的端口': 'Port d\'écoute du service Bandix',
'监控网卡': 'Interface de Surveillance',
'选择要监控的网络接口': 'Sélectionner l\'interface réseau LAN à surveiller',
'网速单位': 'Unités de Vitesse',
'选择网速显示的单位格式': 'Sélectionner le format d\'unité d\'affichage de la vitesse',
'字节单位 (B/s, KB/s, MB/s)': 'Unités d\'Octets (B/s, KB/s, MB/s)',
'比特单位 (bps, Kbps, Mbps)': 'Unités de Bits (bps, Kbps, Mbps)',
'界面主题': 'Thème de l\'Interface',
'选择 Bandix 流量监控的显示主题': 'Sélectionner le thème d\'affichage pour le Moniteur de Trafic Bandix',
'跟随系统': 'Suivre le Système',
'明亮模式': 'Mode Clair',
'暗黑模式': 'Mode Sombre',
'意见反馈': 'Commentaires',
'离线超时时间': 'Délai d\'expiration hors ligne',
'设置设备离线判断的超时时间(秒)': 'Définir le délai d\'expiration pour la détection hors ligne des appareils (secondes). Les appareils inactifs plus longtemps que cette durée seront marqués comme hors ligne',
'历史流量周期': 'Période d\'Historique du Trafic',
'设置历史流量数据周期': "Avec un intervalle de 10 minutes, 1 appareil occupe environ 60 Ko (taille fixe), la modification effacera les données existantes.\nEn raison de la limite de communication unique d'ubus, des valeurs plus importantes ne peuvent pas être définies.",
'数据 flush 间隔': 'Intervalle de flush',
'设置数据 flush 间隔': 'Définir l\'intervalle pour effectuer le flush des données sur le disque',
'1 分钟': '1 minute',
'5 分钟': '5 minutes',
'10 分钟': '10 minutes',
'15 分钟': '15 minutes',
'20 分钟': '20 minutes',
'25 分钟': '25 minutes',
'30 分钟': '30 minutes',
'1 小时': '1 heure',
'2 小时': '2 heures',
'数据目录': 'Répertoire de Données',
'Bandix 数据存储目录': 'Répertoire de stockage de données Bandix',
'启用 Bandix 连接监控功能': 'Activer la surveillance des connexions Bandix',
'持久化历史数据': 'Persister les Données Historiques',
'启用数据持久化功能': 'Activer la fonctionnalité de persistance des données, les données ne seront persistées sur le disque que lorsque cette option est activée'
},
'ja': {
'基本设置': '基本設定',
'流量监控设置': 'トラフィック監視設定',
'连接监控设置': '接続監視設定',
'Bandix 基本配置': 'Bandix 基本設定',
'配置 Bandix 服务的基本参数': 'Bandix サービスの基本パラメータを設定',
'Bandix 流量监控配置': 'Bandix トラフィック監視設定',
'配置流量监控相关参数': 'トラフィック監視関連パラメータを設定',
'Bandix 连接监控配置': 'Bandix 接続監視設定',
'配置连接监控相关参数': '接続監視関連パラメータを設定',
'启用': '有効',
'启用 Bandix 流量监控服务': 'Bandix トラフィックモニターサービスを有効にする',
'启用流量监控': 'トラフィック監視を有効にする',
'启用连接监控': '接続監視を有効にする',
'界面语言': 'インターフェース言語',
'选择 Bandix 流量监控的显示语言': 'Bandix トラフィックモニターの表示言語を選択',
'简体中文': '簡体字中国語',
'繁体中文': '繁体字中国語',
'端口': 'ポート',
'Bandix 服务监听的端口': 'Bandix サービスのリッスンポート',
'监控网卡': '監視インターフェース',
'选择要监控的网络接口': '監視するLANネットワークインターフェースを選択',
'网速单位': '速度単位',
'选择网速显示的单位格式': '速度表示の単位形式を選択',
'字节单位 (B/s, KB/s, MB/s)': 'バイト単位 (B/s, KB/s, MB/s)',
'比特单位 (bps, Kbps, Mbps)': 'ビット単位 (bps, Kbps, Mbps)',
'界面主题': 'インターフェーステーマ',
'选择 Bandix 流量监控的显示主题': 'Bandix トラフィックモニターの表示テーマを選択',
'跟随系统': 'システムに従う',
'明亮模式': 'ライトモード',
'暗黑模式': 'ダークモード',
'意见反馈': 'フィードバック',
'离线超时时间': 'オフラインタイムアウト',
'设置设备离线判断的超时时间(秒)': 'デバイスのオフライン検出のタイムアウト時間(秒)を設定。この時間を超えて非アクティブなデバイスはオフラインとしてマークされます',
'历史流量周期': 'トラフィック履歴期間',
'设置历史流量数据周期': '10分間隔では、1台のデバイスで固定サイズとして約60KBを使用し、変更すると既存データがクリアされます。\nubusの単一通信制限により、より大きな値を設定することはできません。',
'数据 flush 间隔': 'データflush間隔',
'设置数据 flush 间隔': 'データをディスクにflushする間隔を設定',
'1 分钟': '1 分',
'5 分钟': '5 分',
'10 分钟': '10 分',
'15 分钟': '15 分',
'20 分钟': '20 分',
'25 分钟': '25 分',
'30 分钟': '30 分',
'1 小时': '1 時間',
'2 小时': '2 時間',
'数据目录': 'データディレクトリ',
'Bandix 数据存储目录': 'Bandix データ保存ディレクトリ',
'启用 Bandix 连接监控功能': 'Bandix 接続監視機能を有効にする',
'持久化历史数据': '履歴データの永続化',
'启用数据持久化功能': 'データ永続化機能を有効にする。このオプションが有効な場合のみ、データがディスクに永続化されます'
},
'ru': {
'基本设置': 'Основные Настройки',
'流量监控设置': 'Настройки Мониторинга Трафика',
'连接监控设置': 'Настройки Мониторинга Соединений',
'Bandix 基本配置': 'Базовая Конфигурация Bandix',
'配置 Bandix 服务的基本参数': 'Настроить основные параметры службы Bandix',
'Bandix 流量监控配置': 'Конфигурация Мониторинга Трафика Bandix',
'配置流量监控相关参数': 'Настроить параметры, связанные с мониторингом трафика',
'Bandix 连接监控配置': 'Конфигурация Мониторинга Соединений Bandix',
'配置连接监控相关参数': 'Настроить параметры, связанные с мониторингом соединений',
'启用': 'Включить',
'启用 Bandix 流量监控服务': 'Включить Службу Мониторинга Трафика Bandix',
'启用流量监控': 'Включить Мониторинг Трафика',
'启用连接监控': 'Включить Мониторинг Соединений',
'界面语言': 'Язык Интерфейса',
'选择 Bandix 流量监控的显示语言': 'Выберите язык отображения для Монитора Трафика Bandix',
'简体中文': 'Упрощенный Китайский',
'繁体中文': 'Традиционный Китайский',
'端口': 'Порт',
'Bandix 服务监听的端口': 'Порт прослушивания службы Bandix',
'监控网卡': 'Интерфейс Мониторинга',
'选择要监控的网络接口': 'Выберите сетевой интерфейс LAN для мониторинга',
'网速单位': 'Единицы Скорости',
'选择网速显示的单位格式': 'Выберите формат единиц отображения скорости',
'字节单位 (B/s, KB/s, MB/s)': 'Единицы Байтов (B/s, KB/s, MB/s)',
'比特单位 (bps, Kbps, Mbps)': 'Единицы Битов (bps, Kbps, Mbps)',
'界面主题': 'Тема Интерфейса',
'选择 Bandix 流量监控的显示主题': 'Выберите тему отображения для Монитора Трафика Bandix',
'跟随系统': 'Следовать Системе',
'明亮模式': 'Светлый Режим',
'暗黑模式': 'Темный Режим',
'意见反馈': 'Обратная связь',
'离线超时时间': 'Таймаут отключения',
'设置设备离线判断的超时时间(秒)': 'Установить таймаут для обнаружения отключения устройств (секунды). Устройства, неактивные дольше этого времени, будут помечены как отключенные',
'历史流量周期': 'Период Истории Трафика',
'设置历史流量数据周期': 'При интервале 10 минут одно устройство занимает около 60 КБ (фиксированный размер), изменение очистит существующие данные.\nИз-за ограничения единичной связи ubus нельзя установить большие значения.',
'数据 flush 间隔': 'Интервал flush данных',
'设置数据 flush 间隔': 'Установить интервал flush данных на диск',
'1 分钟': '1 минута',
'5 分钟': '5 минут',
'10 分钟': '10 минут',
'15 分钟': '15 минут',
'20 分钟': '20 минут',
'25 分钟': '25 минут',
'30 分钟': '30 минут',
'1 小时': '1 час',
'2 小时': '2 часа',
'数据目录': 'Каталог Данных',
'Bandix 数据存储目录': 'Каталог хранения данных Bandix',
'启用 Bandix 连接监控功能': 'Включить мониторинг соединений Bandix',
'持久化历史数据': 'Персистентность Исторических Данных',
'启用数据持久化功能': 'Включить функциональность персистентности данных, данные будут сохраняться на диск только при включении этой опции'
}
};
function getTranslation(key, language) {
return translations[language]?.[key] || key;
}
// 获取系统语言并返回支持的语言代码
function getSystemLanguage() {
// 尝试获取 LuCI 的语言设置
var luciLang = uci.get('luci', 'main', 'lang');
if (luciLang && translations[luciLang]) {
return luciLang;
}
// 如果没有 LuCI 语言设置,尝试获取浏览器语言作为回退
var systemLang = document.documentElement.lang || 'en';
// 检查是否支持该语言
if (translations[systemLang]) {
return systemLang;
}
// 如果不支持,返回英语
return 'en';
}
function isDarkMode() {
// 首先检查用户设置的主题
var userTheme = uci.get('bandix', 'general', 'theme');
if (userTheme) {
if (userTheme === 'dark') {
return true;
} else if (userTheme === 'light') {
return false;
}
// 如果是 'auto',继续检查系统主题
}
// 获取 LuCI 主题设置
var mediaUrlBase = uci.get('luci', 'main', 'mediaurlbase');
if (mediaUrlBase && mediaUrlBase.toLowerCase().includes('dark')) {
return true;
}
// 如果是 argon 主题,检查 argon 配置
if (mediaUrlBase && mediaUrlBase.toLowerCase().includes('argon')) {
var argonMode = uci.get('argon', '@global[0]', 'mode');
if (argonMode && argonMode.toLowerCase().includes('dark')) {
return true;
}
}
return false;
}
return view.extend({
load: function () {
return Promise.all([
uci.load('bandix'),
uci.load('network'),
uci.load('luci'),
uci.load('argon').catch(function() {
// argon 配置可能不存在,忽略错误
return null;
})
]);
},
render: function (data) {
var m, s, o;
var networkConfig = uci.sections('network', 'device');
var physicalInterfaces = [];
// 确保UCI section存在否则表单不会显示
if (!uci.get('bandix', 'general')) {
uci.add('bandix', 'general', 'general');
}
if (!uci.get('bandix', 'traffic')) {
uci.add('bandix', 'traffic', 'traffic');
}
if (!uci.get('bandix', 'connections')) {
uci.add('bandix', 'connections', 'connections');
}
var language = uci.get('bandix', 'general', 'language');
if (!language || language === 'auto') {
language = getSystemLanguage();
}
var darkMode = isDarkMode();
// 添加暗黑模式样式支持
if (darkMode) {
var style = E('style', {}, `
body, .main {
background-color: #0f172a !important;
color: #e2e8f0 !important;
}
.cbi-section {
background-color: #1E1E1E !important;
border-radius: 8px !important;
}
.cbi-section h3 {
color: #f1f5f9 !important;
background-color: #333333 !important;
border-bottom: 1px solid #1E1E1E !important;
}
.cbi-section-descr {
color: #94a3b8 !important;
}
.cbi-value {
border-bottom: 1px solid #1E1E1E !important;
}
.cbi-value-title {
color: #e2e8f0 !important;
}
.cbi-value-description {
color: #94a3b8 !important;
}
input[type="text"], input[type="number"], select, textarea {
background-color: #333333 !important;
color: #e2e8f0 !important;
}
input[type="text"]:focus, input[type="number"]:focus, select:focus, textarea:focus {
border-color: #3b82f6 !important;
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2) !important;
}
input[type="checkbox"] {
accent-color: #3b82f6 !important;
}
.cbi-button, .btn {
background-color: #333333 !important;
color: #e2e8f0 !important;
}
.cbi-button:hover, .btn:hover {
background-color: #1E1E1E !important;
}
.cbi-button-save {
background-color: #3b82f6 !important;
border-color: #3b82f6 !important;
color: white !important;
}
.cbi-button-save:hover {
background-color: #2563eb !important;
}
.cbi-section-error {
background-color: #7f1d1d !important;
border-color: #dc2626 !important;
color: #fca5a5 !important;
}
/* 表格样式 */
.table {
background-color: #1E1E1E !important;
}
.table th {
background-color: #333333 !important;
color: #e2e8f0 !important;
border-bottom: 1px solid #1E1E1E !important;
}
.table td {
color: #cbd5e1 !important;
border-bottom: 1px solid #1E1E1E !important;
}
.table tr:hover {
background-color: #1E1E1E !important;
}
`);
document.head.appendChild(style);
}
// 从network配置中提取物理接口名称
if (networkConfig && networkConfig.length > 0) {
networkConfig.forEach(function (device) {
if (device.name) {
physicalInterfaces.push(device.name);
}
});
}
// 添加网络接口配置中的物理接口
var interfaces = uci.sections('network', 'interface');
if (interfaces && interfaces.length > 0) {
interfaces.forEach(function (iface) {
if (iface.device && physicalInterfaces.indexOf(iface.device) === -1) {
physicalInterfaces.push(iface.device);
}
});
}
// 确保至少有一些默认值
if (physicalInterfaces.length === 0) {
physicalInterfaces = [];
}
// 创建表单
m = new form.Map('bandix');
// 1. 基本设置部分 (general)
s = m.section(form.NamedSection, 'general', 'general', getTranslation('基本设置', language));
s.description = getTranslation('配置 Bandix 服务的基本参数', language);
s.addremove = false;
// 添加端口设置选项
o = s.option(form.Value, 'port', getTranslation('端口', language),
getTranslation('Bandix 服务监听的端口', language));
o.default = '8686';
o.datatype = 'port';
o.placeholder = '8686';
o.rmempty = false;
// 添加网卡选择下拉菜单
o = s.option(form.ListValue, 'iface', getTranslation('监控网卡', language),
getTranslation('选择要监控的网络接口', language));
o.rmempty = false;
// 添加从配置获取的物理接口
physicalInterfaces.forEach(function (iface) {
o.value(iface, iface);
});
// 添加语言选择选项
o = s.option(form.ListValue, 'language', getTranslation('界面语言', language),
getTranslation('选择 Bandix 流量监控的显示语言', language));
o.value('auto', getTranslation('跟随系统', language));
o.value('zh-cn', getTranslation('简体中文', language));
o.value('zh-tw', getTranslation('繁体中文', language));
o.value('en', 'English');
o.value('fr', 'Français');
o.value('ja', '日本語');
o.value('ru', 'Русский');
o.default = 'auto';
o.rmempty = false;
// 添加主题选择选项
o = s.option(form.ListValue, 'theme', getTranslation('界面主题', language),
getTranslation('选择 Bandix 流量监控的显示主题', language));
o.value('auto', getTranslation('跟随系统', language));
o.value('light', getTranslation('明亮模式', language));
o.value('dark', getTranslation('暗黑模式', language));
o.default = 'auto';
o.rmempty = false;
// 添加数据目录设置(只读)
o = s.option(form.DummyValue, 'data_dir', getTranslation('数据目录', language));
o.default = '/usr/share/bandix';
o.cfgvalue = function(section_id) {
return uci.get('bandix', section_id, 'data_dir') || '/usr/share/bandix';
};
// 添加意见反馈信息
o = s.option(form.DummyValue, 'feedback_info', getTranslation('意见反馈', language));
o.href = 'https://github.com/timsaya';
o.cfgvalue = function() {
return 'https://github.com/timsaya';
};
// 2. 流量监控设置部分 (traffic)
s = m.section(form.NamedSection, 'traffic', 'traffic', getTranslation('流量监控设置', language));
s.description = getTranslation('配置流量监控相关参数', language);
s.addremove = false;
o = s.option(form.Flag, 'enabled', getTranslation('启用流量监控', language),
getTranslation('启用 Bandix 流量监控服务', language));
o.default = '0';
o.rmempty = false;
// 添加网速单位选择选项
o = s.option(form.ListValue, 'speed_unit', getTranslation('网速单位', language),
getTranslation('选择网速显示的单位格式', language));
o.value('bytes', getTranslation('字节单位 (B/s, KB/s, MB/s)', language));
o.value('bits', getTranslation('比特单位 (bps, Kbps, Mbps)', language));
o.default = 'bytes';
o.rmempty = false;
// 添加离线超时时间(秒)
o = s.option(form.Value, 'offline_timeout', getTranslation('离线超时时间', language),
getTranslation('设置设备离线判断的超时时间(秒)', language));
o.datatype = 'uinteger';
o.placeholder = '600';
o.default = '600';
o.rmempty = true;
// 添加持久化历史数据选项
o = s.option(form.Flag, 'traffic_persist_history', getTranslation('持久化历史数据', language),
getTranslation('启用数据持久化功能', language));
o.default = '0';
o.rmempty = false;
// 添加数据 flush 间隔(秒)
o = s.option(form.ListValue, 'traffic_flush_interval_seconds', getTranslation('数据 flush 间隔', language),
getTranslation('设置数据 flush 间隔', language));
o.value('60', getTranslation('1 分钟', language));
o.value('300', getTranslation('5 分钟', language));
o.value('600', getTranslation('10 分钟', language));
o.value('900', getTranslation('15 分钟', language));
o.value('1200', getTranslation('20 分钟', language));
o.value('1500', getTranslation('25 分钟', language));
o.value('1800', getTranslation('30 分钟', language));
o.value('3600', getTranslation('1 小时', language));
o.value('7200', getTranslation('2 小时', language));
o.default = '600';
o.rmempty = false;
o.depends('traffic_persist_history', '1');
// 添加历史流量周期(秒)
o = s.option(form.ListValue, 'traffic_retention_seconds', getTranslation('历史流量周期', language),
getTranslation('设置历史流量数据周期', language));
o.value('60', getTranslation('1 分钟', language));
o.value('300', getTranslation('5 分钟', language));
o.value('600', getTranslation('10 分钟', language));
o.value('900', getTranslation('15 分钟', language));
o.value('1200', getTranslation('20 分钟', language));
o.value('1500', getTranslation('25 分钟', language));
o.value('1800', getTranslation('30 分钟', language));
o.default = '600';
o.rmempty = false;
// 3. 连接监控设置部分 (connections)
s = m.section(form.NamedSection, 'connections', 'connections', getTranslation('连接监控设置', language));
s.description = getTranslation('配置连接监控相关参数', language);
s.addremove = false;
o = s.option(form.Flag, 'enabled', getTranslation('启用连接监控', language),
getTranslation('启用 Bandix 连接监控功能', language));
o.default = '0';
o.rmempty = false;
return m.render();
}
});