small-package/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/client.js

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
});