给哪吒V1探针面板添加周期流量显示
预览
、
前提:在后台警报规则中为每台服务器添加了流量告警规则,仅支持v1默认主题
因为不想进探针后,还要点那个服务才能看到月流量,就想直接看到,所以有了这个代码
在面板后台自定义代码中加入如下代码
<script>
window.FixedTopServerName = true; /* 固定顶部显示服务器名称 */
setInterval(function() {
function formatFileSize(bytes) {
if (bytes === 0) return { value: '0', unit: 'B' };
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
let unitIndex = 0;
let size = bytes;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
let decimalPlaces = 1;
if (unitIndex === 0) decimalPlaces = 0;
return {
value: size.toFixed(decimalPlaces),
unit: units[unitIndex]
};
}
function calculatePercentage(used, total) {
if (typeof used === 'string') used = Number(used);
if (typeof total === 'string') total = Number(total);
if (used > 1e15 || total > 1e15) {
used = used / 1e10;
total = total / 1e10;
}
return (used / total * 100).toFixed(1);
}
fetch('/api/v1/service')
.then(response => response.json())
.then(data => {
if (data.success) {
const trafficData = data.data.cycle_transfer_stats;
const serverMap = new Map();
for (const cycleId in trafficData) {
const cycle = trafficData[cycleId];
if (cycle.server_name && cycle.transfer) {
for (const serverId in cycle.server_name) {
const serverName = cycle.server_name[serverId];
const transfer = cycle.transfer[serverId];
const max = cycle.max;
if (serverName && transfer !== undefined && max) {
serverMap.set(serverName, {
id: serverId, // 服务器ID
transfer: transfer, // 已使用流量(字节)
max: max, // 最大流量(字节)
name: cycle.name // 流量包名称
});
}
}
}
}
serverMap.forEach((serverData, serverName) => {
const targetElement = Array.from(document.querySelectorAll('section.grid.items-center.gap-2')).find(el =>
el.textContent.trim().includes(serverName));
if (targetElement) {
const usedFormatted = formatFileSize(serverData.transfer);
const totalFormatted = formatFileSize(serverData.max);
const percentage = calculatePercentage(serverData.transfer, serverData.max);
const uniqueClassName = 'traffic-stats-for-server-' + serverData.id;
const insertedElement = targetElement.parentNode.querySelector('.' + uniqueClassName);
if (insertedElement) {
const usedSpan = insertedElement.querySelector('.used-traffic');
const usedUnitSpan = insertedElement.querySelector('.used-unit');
const totalSpan = insertedElement.querySelector('.total-traffic');
const totalUnitSpan = insertedElement.querySelector('.total-unit');
const percentageSpan = insertedElement.querySelector('.percentage-value');
const progressBar = insertedElement.querySelector('.progress-bar');
if (usedSpan) usedSpan.textContent = usedFormatted.value;
if (usedUnitSpan) usedUnitSpan.textContent = usedFormatted.unit;
if (totalSpan) totalSpan.textContent = totalFormatted.value;
if (totalUnitSpan) totalUnitSpan.textContent = totalFormatted.unit;
if (percentageSpan) percentageSpan.textContent = percentage + '%';
if (progressBar) progressBar.style.width = percentage + '%';
return;
}
let currentElement = targetElement;
for (let i = 0; i < 2; i++) {
currentElement = currentElement.nextElementSibling;
if (!currentElement) {
currentElement = targetElement;
currentElement = currentElement.nextElementSibling;
}
}
const newElement = document.createElement('div');
newElement.classList.add('space-y-1.5', 'new-inserted-element', uniqueClassName);
newElement.style.width = '100%';
newElement.innerHTML = `
<div class="flex items-center justify-between">
<div class="flex items-baseline gap-1">
<span class="text-sm font-medium text-neutral-800 dark:text-neutral-200 used-traffic">${usedFormatted.value}</span>
<span class="text-sm font-medium text-neutral-800 dark:text-neutral-200 used-unit">${usedFormatted.unit}</span>
<span class="text-xs text-neutral-500 dark:text-neutral-400">/ </span>
<span class="text-xs text-neutral-500 dark:text-neutral-400 total-traffic">${totalFormatted.value}</span>
<span class="text-xs text-neutral-500 dark:text-neutral-400 total-unit">${totalFormatted.unit}</span>
</div>
<span class="text-xs font-medium text-neutral-600 dark:text-neutral-300 percentage-value">${percentage}%</span>
</div>
<div class="relative h-1.5">
<div class="absolute inset-0 bg-neutral-100 dark:bg-neutral-800 rounded-full"></div>
<div class="absolute inset-0 bg-emerald-500 rounded-full transition-all duration-300 progress-bar" style="width: ${percentage}%;"></div>
</div>
`;
currentElement.insertAdjacentElement('afterend', newElement);
} else {
console.log(`没有找到服务器 ${serverName}(ID: ${serverData.id}) 的元素`);
}
});
} else {
console.log('API请求成功但返回数据不正确');
}
})
.catch(error => {
console.error('获取流量数据失败:', error);
});
}, 3000);
</script>
本文链接:
/archives/eu2K61NT
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
薪萤-博客!
喜欢就支持一下吧
打赏
微信
支付宝