基于Apache环境:如何通过HTML脚本展示PHP存储的设备活跃下载状态
解决方案:实时展示设备活跃下载状态
第一步:修复后端PHP逻辑(确保正确保存所有设备的活跃状态)
当前你的PHP代码每次上传都会覆盖activeDownloads.json,导致只能保留最后一个设备的数据。我们需要修改代码,让它维护一个所有设备的活跃下载状态集合,并且定期清理已完成的下载(可选)。
修改后的PHP代码:
<?php // 读取请求体的JSON数据 $body = file_get_contents('php://input'); $data = json_decode($body, true); // 验证必填字段 $requiredFields = ['userid', 'username', 'gkdevice', 'status', 'TimeRemaining']; foreach ($requiredFields as $field) { if (!isset($data[$field])) { http_response_code(400); echo json_encode(['error' => "Missing required field: $field"]); exit; } } $userid = $data['userid']; $username = $data['username']; $gkdevice = $data['gkdevice']; $status = $data['status']; $timeRem = $data['TimeRemaining']; // 处理设备列表(添加新设备) $devicesFile = "Gkdevices.json"; $devices = file_exists($devicesFile) ? json_decode(file_get_contents($devicesFile), true) : ['JsonDevices' => []]; // 检查设备是否已存在(用gkdevice作为唯一标识) $deviceExists = false; foreach ($devices['JsonDevices'] as $existingDevice) { if ($existingDevice['gkdevice'] === $gkdevice) { $deviceExists = true; break; } } if (!$deviceExists) { $devices['JsonDevices'][] = ['gkdevice' => $gkdevice]; file_put_contents($devicesFile, json_encode($devices, JSON_PRETTY_PRINT)); } // 维护活跃下载状态(关键:不要覆盖,而是更新或添加设备条目) $activeFile = 'activeDownloads.json'; $activeDownloads = file_exists($activeFile) ? json_decode(file_get_contents($activeFile), true) : []; // 更新当前设备的下载状态 $activeDownloads[$gkdevice] = [ 'username' => $username, 'userid' => $userid, 'status' => $status, 'TimeRemaining' => $timeRem, 'lastUpdated' => time() // 添加时间戳,用于清理过期状态 ]; // 可选:清理已完成(状态不是"下载中")或超过10分钟未更新的条目 $expiryTime = time() - 600; // 10分钟 foreach ($activeDownloads as $deviceId => $deviceData) { if ($deviceData['status'] !== '下载中' || $deviceData['lastUpdated'] < $expiryTime) { unset($activeDownloads[$deviceId]); } } // 保存更新后的活跃状态 file_put_contents($activeFile, json_encode($activeDownloads, JSON_PRETTY_PRINT)); // 返回成功响应 http_response_code(200); echo json_encode(['success' => true]); ?>
第二步:修复前端JavaScript代码(正确渲染设备状态)
原JS代码存在变量未定义、DOM元素创建错误、逻辑判断错误等问题,下面是修复后的版本,它会从activeDownloads.json拉取数据,然后动态渲染到deviceGrid容器中:
<section> <div class="container-fluid pt-5 pb-5 bg-main"> <div class="container rounded pt-3 pb-3 content-box"> <div class="container"> <div class="row fw-bold border-bottom pb-2 mb-2"> <div class="col-2">Gerät</div> <div class="col-4">Status</div> <div class="col-6">Info</div> </div> <div id="deviceGrid"></div> <script> const activeDownloadsUrl = "api/activeDownloads.json"; // 确保路径正确 const refreshInterval = 1000; // 1秒刷新一次,可根据需求调整 let firstLoad = true; // 格式化剩余时间(毫秒转时分) function formatTimeRemaining(ms) { const hours = Math.floor(ms / 3600000); const minutes = Math.floor((ms % 3600000) / 60000); const parts = []; if (hours > 0) parts.push(`${hours} Std.`); if (minutes > 0) parts.push(`${minutes} Min.`); return parts.length > 0 ? parts.join(' ') : "Kurz"; } async function loadAndRenderDevices() { try { // 添加时间戳避免缓存 const response = await fetch(`${activeDownloadsUrl}?_=${Date.now()}`); if (!response.ok) throw new Error(`HTTP-Fehler: ${response.status}`); const activeDownloads = await response.json(); const deviceGrid = document.getElementById("deviceGrid"); deviceGrid.innerHTML = ""; // 清空之前的内容 // 遍历每个活跃设备 Object.entries(activeDownloads).forEach(([deviceId, deviceData]) => { // 创建行容器 const row = document.createElement("div"); row.className = "row align-items-center border-bottom py-2"; // 1. 设备编号列 const colDevice = document.createElement("div"); colDevice.className = "col-2"; colDevice.textContent = deviceId; row.appendChild(colDevice); // 2. 状态列(带图标) const colStatus = document.createElement("div"); colStatus.className = "col-4 d-flex align-items-center gap-2"; if (deviceData.status === "下载中") { colStatus.innerHTML = ` <img src="pictures/reject.png" alt="Download aktiv"> <span class="text-danger">Download aktiv</span> `; } else { colStatus.innerHTML = ` <img src="pictures/approved.png" alt="Kein Download"> <span class="text-success">Keine Downloads</span> `; } row.appendChild(colStatus); // 3. 信息列(用户名、剩余时间) const colInfo = document.createElement("div"); colInfo.className = "col-6"; colInfo.innerHTML = ` <div>Benutzer: ${deviceData.username} (ID: ${deviceData.userid})</div> <div>Verbleibende Zeit: ${formatTimeRemaining(deviceData.TimeRemaining)}</div> `; row.appendChild(colInfo); // 将行添加到网格 deviceGrid.appendChild(row); }); // 如果没有活跃设备,显示提示 if (Object.keys(activeDownloads).length === 0) { deviceGrid.innerHTML = '<div class="text-center py-4">Keine aktiven Downloads</div>'; } firstLoad = false; } catch (error) { console.error("Laden der Daten fehlgeschlagen:", error); if (firstLoad) { document.getElementById("deviceGrid").innerHTML = `<div class="text-center py-4 text-danger">Fehler beim Laden der Daten: ${error.message}</div>`; } } } // 初始化加载+定时刷新 loadAndRenderDevices(); setInterval(loadAndRenderDevices, refreshInterval); </script> </div> </div> </div> </section>
关键修复点说明
后端PHP
- 不再覆盖
activeDownloads.json,而是以gkdevice为键维护所有设备的状态 - 添加了必填字段验证,返回合适的HTTP状态码
- 新增了过期状态清理逻辑,避免无效数据堆积
- 优化了设备列表的存在性检查(原代码用
in_array对比整个数组,现在只检查gkdevice)
前端JavaScript
- 修正了变量未定义问题(比如原代码的
devicesFile) - 修复了DOM元素创建错误(原代码重复给同一个
colDevice设置不同的className,现在为每个列创建独立元素) - 修正了逻辑判断错误(原代码
if (downloadActive = true)是赋值,现在正确判断状态字段) - 添加了时间格式化函数,把毫秒转换为易读的时分格式
- 处理了无活跃设备的空状态提示
- 避免了缓存问题,每次请求添加时间戳参数
部署注意事项
- 确保存放PHP和JSON文件的目录有写权限,让PHP能创建和修改JSON文件
- 验证浏览器插件上传的JSON格式是否和PHP预期一致(所有必填字段都存在)
- 根据实际需求调整刷新间隔(
refreshInterval),不要设置太频繁避免服务器压力
内容的提问来源于stack exchange,提问作者user32421586
相关产品推荐
相关产品推荐

