265 lines
8.7 KiB
JavaScript
265 lines
8.7 KiB
JavaScript
'use strict';
|
|
'require view';
|
|
'require fs';
|
|
'require ui';
|
|
|
|
return view.extend({
|
|
load: function () {
|
|
return L.resolveDefault(fs.exec_direct('/usr/libexec/wechatpush-call', ['get_client'], 'json'), { devices: [] });
|
|
},
|
|
render: function (data) {
|
|
|
|
var devices = data.devices;
|
|
var totalDevices = devices.length;
|
|
var headers = [_('Hostname'), _('IPv4 address'), _('MAC address'), _('Interfaces'), _('Online time'), _('Details')];
|
|
var columns = ['name', 'ip', 'mac', 'interface', 'uptime', 'usage'];
|
|
var visibleColumns = [];
|
|
var hasData = false;
|
|
|
|
for (var i = 0; i < columns.length; i++) {
|
|
var column = columns[i];
|
|
var hasColumnData = false;
|
|
|
|
for (var j = 0; j < devices.length; j++) {
|
|
if (devices[j][column] !== '') {
|
|
hasColumnData = true;
|
|
hasData = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hasColumnData) {
|
|
visibleColumns.push(i);
|
|
}
|
|
}
|
|
|
|
var style = `
|
|
.device-table {
|
|
width: 80%;
|
|
border-collapse: collapse;
|
|
}
|
|
.device-table th,
|
|
.device-table td {
|
|
padding: 0.5rem;
|
|
text-align: center;
|
|
border: 1px solid #ccc;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
.device-table td:first-child {
|
|
word-wrap: break-word;
|
|
}
|
|
.device-table th {
|
|
background-color: #f2f2f2;
|
|
font-weight: bold;
|
|
color: #666;
|
|
cursor: pointer;
|
|
}
|
|
.device-table tbody tr:nth-of-type(even) {
|
|
background-color: #f9f9f9;
|
|
}
|
|
.sortable {
|
|
cursor: pointer;
|
|
position: relative;
|
|
}
|
|
.sortable::after {
|
|
content: '';
|
|
position: absolute;
|
|
right: -10px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 0;
|
|
height: 0;
|
|
border-style: solid;
|
|
border-width: 5px 5px 0 5px;
|
|
border-color: #aaa transparent transparent transparent;
|
|
opacity: 0.6;
|
|
}
|
|
.sortable.asc::after {
|
|
border-color: #666 transparent transparent transparent;
|
|
}
|
|
.sortable.desc::after {
|
|
border-color: transparent transparent #666 transparent;
|
|
}
|
|
.device-table .hide {
|
|
display: none;
|
|
}
|
|
@media (max-width: 767px) {
|
|
.device-table th:nth-of-type(4),
|
|
.device-table td:nth-of-type(4) {
|
|
display: none;
|
|
}
|
|
.device-table th,
|
|
.device-table td {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
.device-table td:first-child {
|
|
max-width: 150px;
|
|
}
|
|
}
|
|
`;
|
|
|
|
function createTable() {
|
|
var table = document.createElement('table');
|
|
table.classList.add('device-table');
|
|
|
|
var thead = document.createElement('thead');
|
|
var tr = document.createElement('tr');
|
|
|
|
for (var i = 0; i < headers.length; i++) {
|
|
var th = document.createElement('th');
|
|
th.textContent = headers[i];
|
|
|
|
if (visibleColumns.includes(i)) {
|
|
th.classList.add('sortable');
|
|
th.dataset.column = columns[i];
|
|
} else {
|
|
th.classList.add('hide');
|
|
}
|
|
|
|
tr.appendChild(th);
|
|
}
|
|
|
|
thead.appendChild(tr);
|
|
table.appendChild(thead);
|
|
|
|
var tbody = document.createElement('tbody');
|
|
devices.forEach(function (device) {
|
|
var row = document.createElement('tr');
|
|
for (var i = 0; i < columns.length; i++) {
|
|
if (visibleColumns.includes(i)) {
|
|
var cell = document.createElement('td');
|
|
cell.textContent = device[columns[i]];
|
|
row.appendChild(cell);
|
|
}
|
|
}
|
|
tbody.appendChild(row);
|
|
});
|
|
|
|
table.appendChild(tbody);
|
|
|
|
return table;
|
|
}
|
|
|
|
var container = document.createElement('div');
|
|
container.appendChild(document.createElement('h2')).textContent = _('当前共 ') + totalDevices + _(' 台设备在线');
|
|
container.appendChild(createTable());
|
|
container.appendChild(document.createElement('style')).textContent = style;
|
|
|
|
function sortTable(column) {
|
|
var table = container.querySelector('.device-table');
|
|
var tbody = table.querySelector('tbody');
|
|
var rows = Array.from(tbody.querySelectorAll('tr'));
|
|
|
|
var isAscending = true;
|
|
|
|
if (table.classList.contains('sorted') && table.dataset.sortColumn === column) {
|
|
isAscending = !table.classList.contains('asc');
|
|
}
|
|
|
|
rows.sort(function (row1, row2) {
|
|
var value1 = row1.querySelector('td:nth-of-type(' + (visibleColumns.indexOf(column) + 1) + ')').textContent.toLowerCase();
|
|
var value2 = row2.querySelector('td:nth-of-type(' + (visibleColumns.indexOf(column) + 1) + ')').textContent.toLowerCase();
|
|
|
|
if (value1 < value2) {
|
|
return isAscending ? -1 : 1;
|
|
} else if (value1 > value2) {
|
|
return isAscending ? 1 : -1;
|
|
}
|
|
|
|
return 0;
|
|
});
|
|
|
|
tbody.innerHTML = '';
|
|
|
|
rows.forEach(function (row) {
|
|
tbody.appendChild(row);
|
|
});
|
|
|
|
table.classList.remove('sorted', 'asc', 'desc');
|
|
if (isAscending) {
|
|
table.classList.add('sorted', 'asc');
|
|
} else {
|
|
table.classList.add('sorted', 'desc');
|
|
}
|
|
table.dataset.sortColumn = column;
|
|
}
|
|
|
|
container.addEventListener('click', function (event) {
|
|
if (
|
|
event.target.tagName === 'TH' &&
|
|
event.target.parentNode.rowIndex === 0
|
|
) {
|
|
var columnIndex = event.target.cellIndex;
|
|
var table = container.querySelector('.device-table');
|
|
var tbody = table.querySelector('tbody');
|
|
var rows = Array.from(tbody.querySelectorAll('tr'));
|
|
|
|
rows.sort(function (row1, row2) {
|
|
var value1 = row1.cells[columnIndex].textContent.trim();
|
|
var value2 = row2.cells[columnIndex].textContent.trim();
|
|
|
|
if (columnIndex === 0) {
|
|
return value1.length - value2.length;
|
|
} else if (columnIndex === 1) {
|
|
value1 = ipToNumber(value1);
|
|
value2 = ipToNumber(value2);
|
|
} else if (columnIndex === 4) {
|
|
value1 = parseOnlineTime(value1);
|
|
value2 = parseOnlineTime(value2);
|
|
}
|
|
|
|
if (value1 < value2) {
|
|
return -1;
|
|
} else if (value1 > value2) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
});
|
|
|
|
rows.forEach(function (row) {
|
|
tbody.appendChild(row);
|
|
});
|
|
}
|
|
});
|
|
|
|
function ipToNumber(ipAddress) {
|
|
var parts = ipAddress.split('.');
|
|
var number = 0;
|
|
|
|
for (var i = 0; i < parts.length; i++) {
|
|
number = number * 256 + parseInt(parts[i]);
|
|
}
|
|
|
|
return number;
|
|
}
|
|
|
|
function parseOnlineTime(time) {
|
|
var regex = /(\d+)\s+(小时|分钟|秒)/g;
|
|
var matches = time.matchAll(regex);
|
|
var minutes = 0;
|
|
|
|
for (var match of matches) {
|
|
var value = parseInt(match[1]);
|
|
var unit = match[2];
|
|
|
|
if (unit === '小时') {
|
|
minutes += value * 60;
|
|
} else if (unit === '分钟') {
|
|
minutes += value;
|
|
}
|
|
}
|
|
|
|
return minutes;
|
|
}
|
|
return container;
|
|
},
|
|
handleSave: null,
|
|
handleSaveApply: null,
|
|
handleReset: null
|
|
});
|