Files
openwrt_packages/luci-app-bandix/htdocs/luci-static/resources/view/bandix/connection.js
2025-11-05 00:13:10 +08:00

862 lines
34 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'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: 8px;
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;
}
});