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

380 lines
14 KiB
JavaScript
Raw Normal View History

'use strict';
'require view';
'require fs';
'require ui';
'require poll';
2024-07-05 14:45:17 +08:00
'require uci';
return view.extend({
load: function () {
2024-07-05 00:04:43 +08:00
var self = this;
// 清除 localStorage 中的排序设置
localStorage.removeItem('sortColumn');
localStorage.removeItem('sortDirection');
2024-07-05 14:45:17 +08:00
uci.load('wechatpush')
2024-07-05 00:04:43 +08:00
return this.fetchAndRenderDevices().then(function () {
self.setupAutoRefresh();
});
},
2024-07-05 00:04:43 +08:00
fetchAndRenderDevices: function () {
var self = this;
return this.fetchDevices().then(function (data) {
var container = self.render(data);
self.switchContent(container);
}).catch(function (error) {
console.error('Error fetching or rendering devices:', error);
});
},
fetchDevices: function () {
return fs.read('/tmp/wechatpush/devices.json').then(function (content) {
try {
var data = JSON.parse(content);
return { devices: data.devices };
} catch (e) {
console.error('Error parsing JSON:', e);
return { devices: [] };
}
2024-07-05 00:04:43 +08:00
});
},
render: function (data) {
2024-07-05 00:04:43 +08:00
if (!data || !data.devices || !Array.isArray(data.devices)) {
return document.createElement('div');
}
var devices = data.devices.filter(device => device.status === 'online' || device.status === 'unknown');
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;
2024-07-05 14:45:17 +08:00
// 获取配置中的默认排序列
var defaultSortColumn = uci.get('wechatpush', 'config', 'defaultSortColumn') || 'ip';
var defaultSortDirection = (defaultSortColumn === 'uptime') ? 'desc' : 'asc';
2024-07-05 00:04:43 +08:00
// 获取存储的排序设置,如果没有则使用默认设置
var storedSortColumn = localStorage.getItem('sortColumn');
var storedSortDirection = localStorage.getItem('sortDirection');
var currentSortColumn = storedSortColumn || defaultSortColumn;
var currentSortDirection = storedSortDirection || defaultSortDirection;
devices.sort(function (a, b) {
2024-07-05 20:40:39 +08:00
return compareDevices(a, b, currentSortColumn, currentSortDirection);
});
// 根据数据源决定可见列
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; /* 合并边框 */
margin-top: 10px; /* 顶部外边距 */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* 阴影效果 */
border-radius: 8px; /* 圆角边框 */
overflow: hidden; /* 内容溢出隐藏 */
}
.device-table th,
.device-table td {
padding: 10px; /* 单元格内边距 */
text-align: center; /* 文本居中 */
border: 1px solid #ddd; /* 边框样式 */
}
.device-table th {
background-color: rgba(0, 0, 0, 0.05); /* 表头背景色,透明 */
font-weight: bold; /* 粗体字体 */
cursor: pointer; /* 鼠标指针样式为指针 */
position: relative; /* 相对定位 */
}
.device-table th.sortable::after {
right: 10px; /* 右侧距离 */
top: 50%; /* 顶部偏移50% */
transform: translateY(-50%); /* 垂直居中 */
border-width: 5px 5px 0; /* 边框宽度 */
border-style: solid; /* 边框样式为实线 */
opacity: 0.6; /* 透明度 */
}
.device-table th.asc::after {
content: '';
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
border-width: 6px;
border-style: solid;
border-color: #666 transparent transparent transparent; /* 向上箭头颜色 */
}
.device-table th.desc::after {
content: '';
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
border-width: 6px;
border-style: solid;
border-color: transparent transparent #666 transparent; /* 向下箭头颜色 */
}
.device-table tbody tr:nth-child(even) {
background-color: rgba(0, 0, 0, 0.05); /* 偶数行背景色,透明 */
}
.device-table td:first-child {
text-align: left; /* 第一列文本左对齐 */
padding-left: 20px; /* 第一列左侧内边距 */
}
.device-table td a {
color: #007bff; /* 链接颜色 */
text-decoration: none; /* 去掉下划线 */
}
.device-table td a:hover {
text-decoration: underline; /* 鼠标悬停下划线 */
}
.device-table .hide {
display: none; /* 隐藏元素 */
}
@media (max-width: 767px) {
.device-table {
width: 100%; /* 表格宽度占满父容器 */
overflow: hidden; /* 内容溢出隐藏 */
}
.device-table th,
.device-table td {
padding: 3px; /* 单元格内边距 */
text-align: center; /* 文本居中 */
border: 0.35px solid #ddd; /* 边框样式 */
}
.device-table td:first-child {
max-width: 80px;
}
.device-table td:nth-of-type(5) { /* 控制第五列Online time的样式 */
font-size: 14px; /* 调整字体大小 */
}
.device-table td:first-child {
text-align: left; /* 第一列文本左对齐 */
padding-left: 2px; /* 第一列左侧内边距 */
}
.device-table th:nth-of-type(4),
.device-table td:nth-of-type(4) {
display: none; /* 在小屏幕下隐藏第四列 */
}
}
`;
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];
2024-07-05 00:04:43 +08:00
if (columns[i] === currentSortColumn) {
th.classList.add(currentSortDirection === 'asc' ? 'asc' : 'desc');
}
} 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');
if (columns[i] === 'uptime') {
cell.textContent = calculateUptime(device['uptime'], window.innerWidth <= 767);
} else if (columns[i] === 'ip' && device['http_access']) {
var link = document.createElement('a');
link.href = `${device['http_access']}://${device['ip']}`;
link.textContent = device['ip'];
link.target = '_blank';
cell.appendChild(link);
} else {
cell.textContent = device[columns[i]];
}
row.appendChild(cell);
}
}
tbody.appendChild(row);
});
table.appendChild(tbody);
return table;
}
function calculateUptime(uptime, simpleFormat = false) {
var startTimeStamp = parseInt(uptime);
var currentTimeStamp = Math.floor(Date.now() / 1000);
var uptimeInSeconds = currentTimeStamp - startTimeStamp;
var days = Math.floor(uptimeInSeconds / (3600 * 24));
var hours = Math.floor((uptimeInSeconds % (3600 * 24)) / 3600);
var minutes = Math.floor((uptimeInSeconds % 3600) / 60);
var seconds = uptimeInSeconds % 60;
if (simpleFormat) {
if (days > 0) {
return days + 'd ' + hours + 'h';
} else if (hours > 0) {
return hours + 'h ' + minutes + 'm';
} else if (minutes > 0) {
return minutes + 'm ' + seconds + 's';
} else {
return seconds + 's';
}
} else {
if (days > 0) {
return days + ' 天 ' + hours + ' 小时';
} else if (hours > 0) {
return hours + ' 小时 ' + minutes + ' 分';
} else if (minutes > 0) {
return minutes + ' 分 ' + seconds + ' 秒';
} else {
return seconds + ' 秒';
}
}
}
2024-07-05 20:40:39 +08:00
function compareDevices(a, b, column, direction) {
var value1 = getValueForSorting(a, column);
var value2 = getValueForSorting(b, column);
if (value1 < value2) {
return direction === 'asc' ? -1 : 1;
} else if (value1 > value2) {
return direction === 'asc' ? 1 : -1;
}
return 0;
}
2024-07-05 00:04:43 +08:00
function getValueForSorting(device, column) {
var value = device[column];
if (column === 'uptime') {
// 使用时间戳排序
return parseInt(device['uptime']);
} else if (column === 'ip') {
return ipToNumber(value);
}
2024-07-05 00:04:43 +08:00
return value;
}
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;
}
var container = document.createElement('div');
container.appendChild(document.createElement('h2')).textContent = _('当前共 ') + totalDevices + _(' 台设备在线');
container.appendChild(createTable());
container.appendChild(document.createElement('style')).textContent = style;
container.addEventListener('click', function (event) {
2024-07-05 00:04:43 +08:00
if (event.target.tagName === 'TH' && event.target.parentNode.rowIndex === 0) {
var columnIndex = event.target.cellIndex;
2024-07-05 00:04:43 +08:00
var column = columns[columnIndex];
var direction = 'asc';
2024-07-05 20:40:39 +08:00
// 使在线时间第一次点击方向为倒序
if (column === 'uptime') {
direction = currentSortDirection === 'desc' ? 'asc' : 'desc';
} else if (column === currentSortColumn) {
2024-07-05 00:04:43 +08:00
direction = currentSortDirection === 'asc' ? 'desc' : 'asc';
}
2024-07-05 20:40:39 +08:00
2024-07-05 00:04:43 +08:00
sortTable(column, direction, container);
}
});
2024-07-05 00:04:43 +08:00
function sortTable(column, direction, container) {
devices.sort(function (a, b) {
2024-07-05 20:40:39 +08:00
return compareDevices(a, b, column, direction);
});
2024-07-05 00:04:43 +08:00
currentSortColumn = column;
currentSortDirection = direction;
2024-07-05 00:04:43 +08:00
// 存储排序设置
localStorage.setItem('sortColumn', currentSortColumn);
localStorage.setItem('sortDirection', currentSortDirection);
2024-07-05 00:04:43 +08:00
container.innerHTML = '';
container.appendChild(document.createElement('h2')).textContent = _('当前共 ') + totalDevices + _(' 台设备在线');
container.appendChild(createTable());
container.appendChild(document.createElement('style')).textContent = style;
}
return container;
},
2024-07-05 00:04:43 +08:00
setupAutoRefresh: function () {
var self = this;
poll.add(L.bind(function () {
self.fetchAndRenderDevices();
}));
},
switchContent: function (newContent) {
var existingContainer = document.querySelector('#view');
if (!existingContainer) {
console.error('Table container not found.');
return;
}
existingContainer.innerHTML = '';
existingContainer.appendChild(newContent);
},
handleSave: null,
handleSaveApply: null,
handleReset: null
});