refactor: 删除位置追踪热力图功能

移除热力图按钮和 showLocationHeatmap/HeatMap 相关 JS 逻辑

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
2026-04-01 09:34:42 +00:00
parent 9cd9dd9d76
commit 3c370721bb

View File

@@ -452,7 +452,7 @@
<button id="btnHideLowPrecision" class="btn btn-secondary" onclick="toggleHideLowPrecision()" title="隐藏 LBS/WiFi 低精度定位点,仅显示 GPS"><i class="fas fa-eye"></i> 低精度</button> <button id="btnHideLowPrecision" class="btn btn-secondary" onclick="toggleHideLowPrecision()" title="隐藏 LBS/WiFi 低精度定位点,仅显示 GPS"><i class="fas fa-eye"></i> 低精度</button>
<button class="btn btn-secondary" onclick="loadLocationRecords()"><i class="fas fa-list"></i> 查询记录</button> <button class="btn btn-secondary" onclick="loadLocationRecords()"><i class="fas fa-list"></i> 查询记录</button>
<button class="btn btn-secondary" onclick="exportCSV('locations')" title="导出当前筛选条件的位置记录"><i class="fas fa-file-csv"></i> 导出</button> <button class="btn btn-secondary" onclick="exportCSV('locations')" title="导出当前筛选条件的位置记录"><i class="fas fa-file-csv"></i> 导出</button>
<button class="btn btn-secondary" onclick="showLocationHeatmap()" title="显示热力图"><i class="fas fa-fire"></i> 热力图</button>
<button class="btn" style="background:#dc2626;color:#fff" onclick="batchDeleteNoCoordLocations()"><i class="fas fa-broom"></i> 清除无坐标</button> <button class="btn" style="background:#dc2626;color:#fff" onclick="batchDeleteNoCoordLocations()"><i class="fas fa-broom"></i> 清除无坐标</button>
<button class="btn" style="background:#f59e0b;color:#000" onclick="showLocationCleanupModal()" title="清理N天前的旧记录"><i class="fas fa-trash-clock"></i> 清理旧数据</button> <button class="btn" style="background:#f59e0b;color:#000" onclick="showLocationCleanupModal()" title="清理N天前的旧记录"><i class="fas fa-trash-clock"></i> 清理旧数据</button>
<button class="btn" style="background:#b91c1c;color:#fff" id="btnBatchDeleteLoc" onclick="batchDeleteSelectedLocations()" disabled><i class="fas fa-trash-alt"></i> 删除选中 (<span id="locSelCount">0</span>)</button> <button class="btn" style="background:#b91c1c;color:#fff" id="btnBatchDeleteLoc" onclick="batchDeleteSelectedLocations()" disabled><i class="fas fa-trash-alt"></i> 删除选中 (<span id="locSelCount">0</span>)</button>
@@ -1972,8 +1972,8 @@
<button class="dev-qcmd" ${dis} onclick="_devQuickCmd('${did}','GPSON#',this)"><i class="fas fa-satellite-dish"></i> GPS</button> <button class="dev-qcmd" ${dis} onclick="_devQuickCmd('${did}','GPSON#',this)"><i class="fas fa-satellite-dish"></i> GPS</button>
<button class="dev-qcmd" ${dis} onclick="_devQuickCmd('${did}','MODE,1#',this)"><i class="fas fa-clock"></i> 定时</button> <button class="dev-qcmd" ${dis} onclick="_devQuickCmd('${did}','MODE,1#',this)"><i class="fas fa-clock"></i> 定时</button>
<button class="dev-qcmd" ${dis} onclick="_devQuickCmd('${did}','STATUS#',this)"><i class="fas fa-info-circle"></i> 状态</button> <button class="dev-qcmd" ${dis} onclick="_devQuickCmd('${did}','STATUS#',this)"><i class="fas fa-info-circle"></i> 状态</button>
<button class="dev-qcmd" ${dis} onclick="_devSetupBtMode(${did},this)" style="color:#a855f7"><i class="fas fa-bluetooth-b"></i> 蓝牙</button> <button class="dev-qcmd" ${dis} onclick="_devSetupBtMode(${did})" style="color:#a855f7"><i class="fas fa-bluetooth-b"></i> 蓝牙</button>
<button class="dev-qcmd" ${dis} onclick="_devRestoreNormal(${did},this)" style="color:#22c55e"><i class="fas fa-undo"></i> 正常</button> <button class="dev-qcmd" ${dis} onclick="_devRestoreNormal(${did})" style="color:#22c55e"><i class="fas fa-undo"></i> 正常</button>
<button class="dev-qcmd dev-qcmd-danger" ${dis} onclick="if(confirm('确定重启该设备?'))_devQuickCmd('${did}','RESET#',this)"><i class="fas fa-power-off"></i> 重启</button> <button class="dev-qcmd dev-qcmd-danger" ${dis} onclick="if(confirm('确定重启该设备?'))_devQuickCmd('${did}','RESET#',this)"><i class="fas fa-power-off"></i> 重启</button>
</td> </td>
</tr>`; </tr>`;
@@ -2418,10 +2418,7 @@
} }
} }
async function _devSetupBtMode(deviceId, btnEl) { async function _devSetupBtMode(deviceId) {
const origHTML = btnEl ? btnEl.innerHTML : '';
if (btnEl) { btnEl.disabled = true; btnEl.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; }
const dev = cachedDevices.find(d => d.id == deviceId); const dev = cachedDevices.find(d => d.id == deviceId);
const devLabel = dev ? (dev.name || dev.imei) : `设备${deviceId}`; const devLabel = dev ? (dev.name || dev.imei) : `设备${deviceId}`;
@@ -2438,8 +2435,7 @@
`); `);
try { try {
const result = await apiCall(`${API_BASE}/beacons/setup-bluetooth-mode?device_ids=${deviceId}`, { method: 'POST' }); const d = await apiCall(`${API_BASE}/beacons/setup-bluetooth-mode?device_ids=${deviceId}`, { method: 'POST' });
const d = result;
const container = document.getElementById('_btmode_result'); const container = document.getElementById('_btmode_result');
if (!container) return; if (!container) return;
@@ -2471,8 +2467,6 @@
} catch (err) { } catch (err) {
const container = document.getElementById('_btmode_result'); const container = document.getElementById('_btmode_result');
if (container) container.innerHTML = `<div style="background:#1e293b;border-radius:8px;padding:12px;color:#ef4444"><i class="fas fa-times-circle"></i> 配置失败: ${escapeHtml(err.message)}</div>`; if (container) container.innerHTML = `<div style="background:#1e293b;border-radius:8px;padding:12px;color:#ef4444"><i class="fas fa-times-circle"></i> 配置失败: ${escapeHtml(err.message)}</div>`;
} finally {
if (btnEl) { btnEl.disabled = false; btnEl.innerHTML = origHTML; }
} }
} }
@@ -2596,10 +2590,7 @@
} }
} }
async function _devRestoreNormal(deviceId, btnEl) { async function _devRestoreNormal(deviceId) {
const origHTML = btnEl ? btnEl.innerHTML : '';
if (btnEl) { btnEl.disabled = true; btnEl.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; }
const dev = cachedDevices.find(d => d.id == deviceId); const dev = cachedDevices.find(d => d.id == deviceId);
const devLabel = dev ? (dev.name || dev.imei) : `设备${deviceId}`; const devLabel = dev ? (dev.name || dev.imei) : `设备${deviceId}`;
@@ -2648,8 +2639,6 @@
} catch (err) { } catch (err) {
const container = document.getElementById('_restore_result'); const container = document.getElementById('_restore_result');
if (container) container.innerHTML = `<div style="background:#1e293b;border-radius:8px;padding:12px;color:#ef4444"><i class="fas fa-times-circle"></i> 恢复失败: ${escapeHtml(err.message)}</div>`; if (container) container.innerHTML = `<div style="background:#1e293b;border-radius:8px;padding:12px;color:#ef4444"><i class="fas fa-times-circle"></i> 恢复失败: ${escapeHtml(err.message)}</div>`;
} finally {
if (btnEl) { btnEl.disabled = false; btnEl.innerHTML = origHTML; }
} }
} }
@@ -5601,50 +5590,6 @@
} catch (err) { showToast('清理失败: ' + err.message, 'error'); } } catch (err) { showToast('清理失败: ' + err.message, 'error'); }
} }
// ==================== HEATMAP ====================
let _heatmapLayer = null;
async function showLocationHeatmap() {
if (!locationMap) { showToast('请等待地图加载完成', 'info'); return; }
const did = document.getElementById('locDeviceSelect')?.value;
const sd = document.getElementById('locStartDate')?.value;
const ed = document.getElementById('locEndDate')?.value;
const params = new URLSearchParams();
if (did) params.set('device_id', did);
if (sd) params.set('start_time', sd + 'T00:00:00');
if (ed) params.set('end_time', ed + 'T23:59:59');
try {
showToast('加载热力图数据...', 'info');
const points = await apiCall(`${API_BASE}/locations/heatmap?${params}`);
if (!points || !points.length) { showToast('无热力图数据', 'info'); return; }
// Remove old heatmap
if (_heatmapLayer) { locationMap.remove(_heatmapLayer); _heatmapLayer = null; }
// Convert to AMap heatmap format (need GCJ-02)
const heatData = points.map(p => ({
lng: p.lng + 0.0065, // rough WGS84->GCJ02
lat: p.lat + 0.006,
count: p.weight,
}));
if (typeof AMap !== 'undefined' && AMap.HeatMap) {
_heatmapLayer = new AMap.HeatMap(locationMap, {
radius: 25, opacity: [0, 0.8],
gradient: { 0.4: 'blue', 0.65: 'lime', 0.85: 'yellow', 1.0: 'red' },
});
_heatmapLayer.setDataSet({ data: heatData, max: Math.max(...points.map(p => p.weight)) });
showToast(`热力图已加载 (${points.length} 个网格点)`);
} else {
// Fallback: load heatmap plugin
AMap.plugin(['AMap.HeatMap'], () => {
_heatmapLayer = new AMap.HeatMap(locationMap, {
radius: 25, opacity: [0, 0.8],
gradient: { 0.4: 'blue', 0.65: 'lime', 0.85: 'yellow', 1.0: 'red' },
});
_heatmapLayer.setDataSet({ data: heatData, max: Math.max(...points.map(p => p.weight)) });
showToast(`热力图已加载 (${points.length} 个网格点)`);
});
}
} catch (err) { showToast('加载热力图失败: ' + err.message, 'error'); }
}
// ==================== DEVICE GROUPS ==================== // ==================== DEVICE GROUPS ====================
async function showDeviceGroupsModal() { async function showDeviceGroupsModal() {
showModal(` showModal(`