// 判断内网还是公网 let apiURL = ''; fetch('/index.html') // 随便请求一个资源 .then(response => { // 获取X-Environment响应头 const environment = response.headers.get('X-Environment'); // 根据环境变量设置API URL if (environment === 'internal') { apiURL = 'http://10.1.16.174:15001'; } else { apiURL = 'http://gpus.lxblxb.top'; } console.log('访问地址: ' + apiURL); }) // 请求服务器获取数据 function fetchData() { fetch(apiURL + '/api/get_data') // 获取服务器和显卡数据 .then(response => response.json()) // 解析 JSON 响应 .then(data => { // 处理 JSON 数据 // console.log(data); displayServerData(data); // 调用显示数据的函数 }) .catch(error => { // console.error('Error fetching data:', error); displayError(error + " (多半是没有正确连接服务器端,可能是没开、网络错误)"); }); } // 显示错误 function displayError(err_info){ let serverDataContainer = document.getElementById('server-data'); serverDataContainer.innerHTML = ''; // 清空容器 let errDiv = document.createElement('div'); errDiv.classList.add('error-info'); errDiv.innerText = err_info; serverDataContainer.appendChild(errDiv); } // 将KB转为合适的格式 function parse_data_unit(num, fixedLen=2){ if (num < 1024){ return num.toFixed(fixedLen) + " KB"; } num /= 1024; if (num < 1024){ return num.toFixed(fixedLen) + " MB"; } num /= 1024; if (num < 1024){ return num.toFixed(fixedLen) + " GB"; } num /= 1024; if (num < 1024){ return num.toFixed(fixedLen) + " TB"; } } function add_bar(serverCard){ let bar = document.createElement('hr'); serverCard.appendChild(bar); } // 添加服务器信息的元素 function displayServerData(data){ let serverDataContainer = document.getElementById('server-data'); serverDataContainer.innerHTML = ''; // 清空容器 let serverDataDict = data['server_dict']; // 创建每一个服务器的信息 for (let serverTitle in serverDataDict){ let serverCard = document.createElement('div'); serverCard.className = 'card'; // 标题 let serverName = document.createElement('div'); serverName.className = 'server-name'; serverName.textContent = serverTitle; serverCard.appendChild(serverName); serverData = serverDataDict[serverTitle]; // 如果没有数据则跳过 if (serverData == null){ let errText = document.createElement('div'); errText.className = 'error-text'; errText.textContent = "No data."; serverCard.appendChild(errText); serverDataContainer.appendChild(serverCard); continue; } // 添加公告 if ('note' in serverData && serverData['note'] != ''){ let noteInfo = document.createElement('div'); noteInfo.className = 'note-info'; noteInfo.innerHTML = '
公告
' + serverData['note']; serverCard.appendChild(noteInfo); } // 判断时间 let lastTime = new Date(serverData['update_time_stamp'] * 1000); let timeFromUpdate = Date.now() - lastTime; if (timeFromUpdate > serverData['interval'] * 1000 * 4){ let errText = document.createElement('div'); errText.className = 'error-text'; errText.textContent = "长时间未更新,上次更新时间: " + lastTime.toLocaleString(); serverCard.appendChild(errText); serverDataContainer.appendChild(serverCard); continue; }else if (timeFromUpdate > serverData['interval'] * 1000 * 2.5){ serverName.textContent = serverTitle + " - Not update -"; } // 网速 if ('network_list' in serverData){ let networkInfo = document.createElement('div'); networkInfo.className = 'network-info'; // todo 暂时采用所有网卡总和的方法 let inSum = 0; let outSum = 0; let tmpTitle = ""; serverData.network_list.forEach(function(network){ inSum += network['in']; outSum += network['out']; tmpTitle += network['name'] + " in: " + parse_data_unit(network['in']) + "/s out: " + parse_data_unit(network['out']) + "/s\n"; }); let inStr = parse_data_unit(inSum); let outStr = parse_data_unit(outSum); networkInfo.innerHTML += " 网络 : in:" + inStr + "/s out:" + outStr + "/s
"; serverCard.appendChild(networkInfo); // 分割线 add_bar(serverCard); } // CPU if ('cpu' in serverData){ let cpuInfo = document.createElement('div'); cpuInfo.className = 'cpu-info'; temperature_list_str = ""; serverData.cpu['temperature_list'].forEach(function(v){ temperature_list_str += v + " ℃ "; }); cpuInfo.innerHTML = "" + serverData.cpu['name'] + "
" + "温度 : " + temperature_list_str + "
" + "占用率 : " + serverData.cpu['core_avg_occupy'] + "%"; serverCard.appendChild(cpuInfo); // 分割线 add_bar(serverCard); } // 内存 if ('memory' in serverData){ let memoryInfo = document.createElement('div'); memoryInfo.className = 'memory-info'; let totalNum = serverData.memory.total let usedNum = serverData.memory.used let totalMem = parse_data_unit(totalNum); let usedMem = parse_data_unit(usedNum); let tmpClass = "state-free"; if (usedNum / totalNum > 0.95) tmpClass = "state-super-occupy"; else if (usedNum / totalNum > 0.8) tmpClass = "state-occupy"; else if (usedNum / totalNum > 0.6) tmpClass = "state-light-occupy"; memoryInfo.innerHTML += " 内存 : " + usedMem + " / " + totalMem + "
"; serverCard.appendChild(memoryInfo); // 分割线 add_bar(serverCard); } // 存储空间 if ('storage_list' in serverData){ let storageInfo = document.createElement('div'); storageInfo.className = 'storage-info'; for (let i = 0; i < serverData.storage_list.length; i++) { let targetPath = serverData.storage_list[i].path; let totalNum = serverData.storage_list[i].total let availableNum = serverData.storage_list[i].available let totalStorage = parse_data_unit(totalNum); let availableStorage = parse_data_unit(totalNum - availableNum); let tmpClass = "state-free"; if (availableNum / totalNum < 0.01) tmpClass = "state-super-occupy"; else if (availableNum / totalNum < 0.1) tmpClass = "state-occupy"; else if (availableNum / totalNum < 0.3) tmpClass = "state-light-occupy"; storageInfo.innerHTML += '' + targetPath + " : " + availableStorage + " / " + totalStorage + "
"; } serverCard.appendChild(storageInfo); // 分割线 add_bar(serverCard); } // gpu if ('gpu_list' in serverData){ serverData.gpu_list.forEach(function(gpu){ let gpuInfo = document.createElement('div'); gpuInfo.className = 'gpu-info'; let markFree = ' 空闲'; let markLightOccupy = ' 占用'; let markOccupy = ' 占用'; let tmpMark = markFree; let memory_used_ratio = gpu.used_memory / gpu.total_memory; if (memory_used_ratio > 0.25 && gpu.utilization > 50){ tmpMark = markOccupy; } else if (memory_used_ratio > 0.25 || gpu.utilization > 50){ tmpMark = markLightOccupy; }else{ tmpMark = markFree; } gpuInfo.innerHTML = '' + gpu.idx + ' - ' + gpu.name + tmpMark + '
' + '温度: ' + gpu.temperature + '°C
' + '显存: ' + gpu.used_memory + ' / ' + gpu.total_memory + " MB" + '
' + '利用率: ' + gpu.utilization + '%'; // 添加进程信息 let processInfo = document.createElement('div'); processInfo.classList.add('process-info'); processInfo.innerHTML = "使用情况: "; gpu.process_list.sort((a, b) => b.memory - a.memory); gpu.process_list.forEach(function(item, index){ if (item.memory > 40) processInfo.innerHTML += `${item.user} (${item.memory}) `; }); gpuInfo.appendChild(processInfo); // 将用户信息添加到GPU信息中 serverCard.appendChild(gpuInfo); }); // 分割线 add_bar(serverCard); } // 错误信息 if ('error_dict' in serverData){ let errorInfo = document.createElement('div'); errorInfo.className = 'storage-info'; if (Object.keys(serverData.error_dict).length > 0){ for (let k in serverData.error_dict){ errorInfo.innerHTML += '' + k + " :" + serverData.error_dict[k] + "
"; } serverCard.appendChild(errorInfo); // 分割线 add_bar(serverCard); } } // 删除最后的分割线 if (serverCard.lastElementChild && serverCard.lastElementChild.tagName === 'HR') { serverCard.removeChild(serverCard.lastElementChild); } // 单个服务器信息作为child加入 serverDataContainer.appendChild(serverCard); } } // TODO test // fetchData() // 页面加载时获取数据并定时刷新 document.addEventListener('DOMContentLoaded', function() { fetchData(); setInterval(fetchData, 4000); // 每4秒刷新一次数据 });