🖥️ 客户端设备管理 (郭经理 9-29 拍板)

在线客户端
-
注册总数
-
今日活跃
-
异常离线 (>3 天)
-
总任务数
-
今日成功发布
-
设备 ID 用户 套餐 操作系统 CPU/内存 登录 IP 状态 注册时间 最后心跳 今日任务 操作
加载中...

设备详情

async function loadDevices() { const userFilter = document.getElementById('filterUser').value.trim(); const statusFilter = document.getElementById('filterStatus').value; let url = `${API_BASE}/api/client/v3/admin/list?`; if (userFilter) url += `username=${encodeURIComponent(userFilter)}&`; if (statusFilter) url += `status=${statusFilter}`; try { const r = await fetch(url, { headers: ADMIN_HEADERS }); const d = await r.json(); if (!d.ok) throw new Error(d.detail || '加载失败'); renderStats(d.stats || {}); renderDevices(d.items || []); } catch (e) { document.getElementById('devicesBody').innerHTML = `❌ ${e.message}`; } } function renderStats(s) { document.getElementById('statOnline').textContent = s.online || 0; document.getElementById('statTotal').textContent = s.total || 0; document.getElementById('statToday').textContent = s.today_active || 0; document.getElementById('statStale').textContent = s.stale || 0; document.getElementById('statTasks').textContent = s.total_tasks || 0; document.getElementById('statSuccess').textContent = s.today_success || 0; } function renderDevices(devices) { if (devices.length === 0) { document.getElementById('devicesBody').innerHTML = '📭 暂无设备'; return; } document.getElementById('devicesBody').innerHTML = devices.map(d => ` ${d.device_id} ${d.username || '-'}
${d.tenant_id || ''} ${d.plan_name ? `${d.plan_name}` : '-'} ${d.os || '-'}
${d.app_version || ''} ${d.cpu_cores || '?'} 核 / ${d.memory_gb || '?'} GB ${d.login_ip || '-'}
${d.login_location || ''} ${renderStatus(d)} ${formatTime(d.registered_at)} ${formatTime(d.last_heartbeat_at)}
${d.minutes_since_heartbeat || '?'} 分钟前 ${d.today_tasks || 0} / ${d.today_success || 0} 成功 `).join(''); } function renderStatus(d) { if (d.minutes_since_heartbeat !== undefined && d.minutes_since_heartbeat < 5) { return '🟢 在线'; } else if (d.minutes_since_heartbeat !== undefined && d.minutes_since_heartbeat < 60) { return '⚠️ 刚离线'; } else { return '⚫ 离线'; } } function formatTime(t) { if (!t) return '-'; try { return t.replace('T', ' ').slice(0, 16); } catch (e) { return t; } } function showDetail(d) { document.getElementById('detailTitle').textContent = `🖥️ ${d.device_id}`; document.getElementById('detailBody').innerHTML = `

📋 设备信息

设备 ID
${d.device_id}
客户端版本
${d.app_version || '-'}
操作系统
${d.os || '-'}
CPU 核数
${d.cpu_cores || '?'} 核
内存
${d.memory_gb || '?'} GB
屏幕分辨率
${d.screen || '-'}
User-Agent
${d.user_agent || '-'}

👤 账号信息

用户名
${d.username || '-'}
租户 ID
${d.tenant_id || '-'}
套餐
${d.plan_name || '-'}

🌐 网络信息

登录 IP
${d.login_ip || '-'}
地理位置
${d.login_location || '-'}
时区
${d.tz || '-'}

⏱️ 活动时间

注册时间
${formatTime(d.registered_at)}
最后心跳
${formatTime(d.last_heartbeat_at)} (${d.minutes_since_heartbeat || '?'} 分钟前)
最后登录
${formatTime(d.last_login_at)}

📊 任务统计

今日任务
${d.today_tasks || 0}
今日成功
${d.today_success || 0}
累计任务
${d.total_tasks || 0}
累计成功
${d.total_success || 0}
`; document.getElementById('deviceDetail').classList.add('show'); } function closeDetail() { document.getElementById('deviceDetail').classList.remove('show'); } async function kickDevice(deviceId) { if (!confirm(`确认踢下线 ${deviceId}?\n该设备需要重新登录才能继续使用`)) return; try { const r = await fetch(`${API_BASE}/api/devices/${deviceId}/kick`, { method: 'POST', headers: ADMIN_HEADERS }); const d = await r.json(); if (d.ok) { alert('✅ 已踢下线'); loadDevices(); } else alert('❌ ' + (d.detail || '失败')); } catch (e) { alert('失败: ' + e.message); } } document.getElementById('filterUser').addEventListener('input', () => { clearTimeout(window._filterT); window._filterT = setTimeout(loadDevices, 500); }); document.getElementById('filterStatus').addEventListener('change', loadDevices); loadDevices(); setInterval(loadDevices, 30000);