⚠️ 您的账号将于 -- 到期,请联系管理员续期

🌱 智慧农业系统

SMART AGRICULTURE MONITORING SYSTEM

⚙️ 系统管理后台

👥 用户管理
🔧 设备管理
📋 操作日志
📊 系统状态
ID账号姓名园区状态到期时间操作
ID名称IP地址位置状态绑定用户操作
时间用户园区操作详情
--
总用户数
--
活跃用户
--
总设备数
--
在线设备
--
今日操作次数
.then(data => { document.getElementById('userTable').innerHTML = data.map(u => { let statusClass = 'status-active'; let statusText = '正常'; if (u.status === 'disabled') { statusClass = 'status-disabled'; statusText = '禁用'; } else if (u.expire_time && new Date(u.expire_time) < new Date()) { statusClass = 'status-expired'; statusText = '已到期'; } return '' + u.id + '' + u.username + '' + (u.name || '--') + '' + (u.garden_name || '--') + '' + statusText + '' + (u.expire_time ? new Date(u.expire_time).toLocaleDateString('zh-CN') : '永久') + '' + (u.id !== currentUser.id ? '' : '当前用户') + ''; }).join(''); }); } function addUser() { const username = document.getElementById('newUsername').value.trim(); const name = document.getElementById('newName').value.trim(); const password = document.getElementById('newPassword').value; const phone = document.getElementById('newPhone').value.trim(); const garden_id = document.getElementById('newGarden').value; const expire_time = document.getElementById('newExpire').value; if (!username || !password) { alert('账号和密码必填'); return; } fetch(API_BASE + '/api/admin/users', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify({ username, password, name, phone, garden_id, expire_time }) }) .then(r => r.json()) .then(data => { if (data.error) { alert(data.error); return; } alert('用户创建成功'); loadUsers(); document.getElementById('newUsername').value = ''; document.getElementById('newName').value = ''; document.getElementById('newPassword').value = ''; document.getElementById('newPhone').value = ''; }); } function deleteUser(id) { if (!confirm('确定删除该用户?')) return; fetch(API_BASE + '/api/admin/users/' + id, { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + token } }) .then(r => r.json()) .then(() => loadUsers()); } function loadAdminDevices() { fetch(API_BASE + '/api/admin/devices', { headers: { 'Authorization': 'Bearer ' + token } }) .then(r => r.json()) .then(data => { const container = document.getElementById('adminDeviceList'); if (!data.grouped || Object.keys(data.grouped).length === 0) { container.innerHTML = '
暂无设备
'; return; } let html = ''; for (const [gardenName, devices] of Object.entries(data.grouped)) { html += '
'; html += '
🏘️ ' + gardenName + ' (' + devices.length + '个设备)
'; html += ''; devices.forEach(d => { const statusClass = d.status === 'online' ? 'status-active' : 'status-offline'; const statusText = d.status === 'online' ? '在线' : '离线'; html += ''; }); html += '
ID名称类型传感器IP状态用户操作
' + d.id + '' + d.device_name + '' + (d.device_type === 'sensor' ? '传感器' : '控制器') + '' + (d.sensor_type || '--') + '' + (d.device_ip || '--') + '' + statusText + '' + (d.user_name || '--') + '
'; } container.innerHTML = html; }); } function remoteControlDevice(deviceId) { const ch = prompt('请输入控制通道 (0-3):\n0: 水泵\n1: 电磁阀\n2: 风机\n3: 补光灯'); if (ch === null || ch === '' || ch < 0 || ch > 3) return; const state = confirm('开启还是关闭?\n确定=开启,取消=关闭') ? 1 : 0; fetch(API_BASE + '/api/device/control', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify({ device_id: deviceId, ch: parseInt(ch), state }) }) .then(r => r.json()) .then(data => { if (data.success) alert('远程控制指令已发送'); else alert('控制失败: ' + data.error); }); } function deleteAdminDevice(id) { if (!confirm('确定删除该设备?')) return; fetch(API_BASE + '/api/admin/devices/' + id, { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + token } }) .then(r => r.json()) .then(() => loadAdminDevices()); } function loadGardens() { fetch(API_BASE + '/api/admin/gardens', { headers: { 'Authorization': 'Bearer ' + token } }) .then(r => r.json()) .then(data => { document.getElementById('gardenTable').innerHTML = data.map(g => { return '' + g.id + '' + g.name + '' + (g.device_ip || '--') + '' + (g.location || '--') + '' + (g.device_count || 0) + '' + (g.user_count || 0) + ''; }).join(''); }); } function addGarden() { const name = document.getElementById('gardenName').value.trim(); const device_ip = document.getElementById('gardenIP').value.trim(); const location = document.getElementById('gardenLocation').value.trim(); if (!name) { alert('园区名称必填'); return; } fetch(API_BASE + '/api/admin/gardens', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify({ name, device_ip, location }) }) .then(r => r.json()) .then(data => { if (data.error) { alert(data.error); return; } alert('园区创建成功'); loadGardens(); loadGardensForSelect(); document.getElementById('gardenName').value = ''; document.getElementById('gardenIP').value = ''; document.getElementById('gardenLocation').value = ''; }); } function deleteGarden(id) { if (!confirm('确定删除该园区?')) return; fetch(API_BASE + '/api/admin/gardens/' + id, { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + token } }) .then(r => r.json()) .then(() => { loadGardens(); loadGardensForSelect(); }); } function loadLogs() { fetch(API_BASE + '/api/logs', { headers: { 'Authorization': 'Bearer ' + token } }) .then(r => r.json()) .then(data => { document.getElementById('logTable').innerHTML = data.map(l => '' + new Date(l.created_at).toLocaleString('zh-CN') + '' + (l.user_name || '--') + '' + (l.garden_name || '--') + '' + l.action + '' + l.detail + '' ).join(''); }); } function loadSystemStatus() { fetch(API_BASE + '/api/system/status', { headers: { 'Authorization': 'Bearer ' + token } }) .then(r => r.json()) .then(data => { document.getElementById('sysTotalUsers').textContent = data.users.total; document.getElementById('sysActiveUsers').textContent = data.users.active; document.getElementById('sysTotalDevices').textContent = data.devices.total; document.getElementById('sysOnlineDevices').textContent = data.gardens.online; document.getElementById('sysTodayLogs').textContent = data.logs_today; }); }