angle_dtu/static/js/main.js
2025-05-14 17:31:15 +08:00

432 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

let sensorChart = null;
let refreshInterval = null;
let allSensors = [];
let currentSensorData = [];
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 初始化日期选择器为今天
initializeDatePickers();
// 加载所有传感器ID
loadSensors();
// 添加事件监听器
setupEventListeners();
// 设置自动刷新
setupAutoRefresh();
});
// 初始化日期选择器
function initializeDatePickers() {
const now = new Date();
const today = now.toISOString().split('T')[0];
const time = now.toTimeString().split(' ')[0].substring(0, 5);
// 设置默认的开始时间为当天00:00
document.getElementById('startDate').value = `${today}T00:00`;
// 设置默认的结束时间为当前时间
document.getElementById('endDate').value = `${today}T${time}`;
}
// 设置事件监听器
function setupEventListeners() {
// 查询按钮
document.getElementById('queryBtn').addEventListener('click', function() {
loadData();
});
// 重置按钮
document.getElementById('resetBtn').addEventListener('click', function() {
resetFilters();
});
// 传感器选择变化
document.getElementById('sensorSelect').addEventListener('change', function() {
loadData();
});
// 记录数限制变化
document.getElementById('limitSelect').addEventListener('change', function() {
loadData();
});
// 导出CSV按钮
document.getElementById('exportBtn').addEventListener('click', function() {
exportToCSV();
});
}
// 设置自动刷新
function setupAutoRefresh() {
const autoRefreshCheckbox = document.getElementById('autoRefresh');
// 初始化自动刷新
if (autoRefreshCheckbox.checked) {
startAutoRefresh();
}
// 监听复选框变化
autoRefreshCheckbox.addEventListener('change', function() {
if (this.checked) {
startAutoRefresh();
} else {
stopAutoRefresh();
}
});
}
// 开始自动刷新
function startAutoRefresh() {
if (refreshInterval) {
clearInterval(refreshInterval);
}
refreshInterval = setInterval(loadData, 10000); // 10秒刷新一次
}
// 停止自动刷新
function stopAutoRefresh() {
if (refreshInterval) {
clearInterval(refreshInterval);
refreshInterval = null;
}
}
// 重置筛选条件
function resetFilters() {
initializeDatePickers();
document.getElementById('sensorSelect').value = 'all';
document.getElementById('limitSelect').value = '100';
loadData();
}
// 加载所有传感器ID
function loadSensors() {
fetch('/api/sensors')
.then(response => {
if (!response.ok) {
throw new Error('获取传感器列表失败');
}
return response.json();
})
.then(data => {
allSensors = data;
updateSensorSelect(data);
// 加载数据
loadData();
})
.catch(error => {
console.error('加载传感器列表出错:', error);
alert('加载传感器列表出错: ' + error.message);
});
}
// 更新传感器选择下拉框
function updateSensorSelect(sensors) {
const select = document.getElementById('sensorSelect');
// 保留"所有传感器"选项
const allOption = select.querySelector('option[value="all"]');
select.innerHTML = '';
select.appendChild(allOption);
if (sensors.length === 0) {
const option = document.createElement('option');
option.value = '';
option.textContent = '没有可用的传感器';
select.appendChild(option);
return;
}
sensors.forEach(id => {
const option = document.createElement('option');
option.value = id;
option.textContent = `传感器 ${id}`;
select.appendChild(option);
});
}
// 加载传感器数据
function loadData() {
const sensorID = document.getElementById('sensorSelect').value;
const limit = document.getElementById('limitSelect').value;
const startDate = document.getElementById('startDate').value;
const endDate = document.getElementById('endDate').value;
let url = '/api/data?';
let params = [];
// 添加查询参数
if (sensorID !== 'all') {
params.push(`sensor_id=${sensorID}`);
}
if (limit) {
params.push(`limit=${limit}`);
}
if (startDate) {
params.push(`start_date=${encodeURIComponent(startDate)}`);
}
if (endDate) {
params.push(`end_date=${encodeURIComponent(endDate)}`);
}
url += params.join('&');
// 显示加载状态
document.getElementById('queryBtn').textContent = '加载中...';
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('获取传感器数据失败');
}
return response.json();
})
.then(data => {
currentSensorData = data;
updateTable(data);
updateChart(data);
document.getElementById('queryBtn').textContent = '查询数据';
})
.catch(error => {
console.error('加载数据出错:', error);
alert('加载数据出错: ' + error.message);
document.getElementById('queryBtn').textContent = '查询数据';
});
}
// 更新数据表格
function updateTable(data) {
const tableBody = document.getElementById('tableBody');
tableBody.innerHTML = '';
if (data.length === 0) {
const row = document.createElement('tr');
row.innerHTML = '<td colspan="6" style="text-align: center;">没有数据</td>';
tableBody.appendChild(row);
return;
}
data.forEach(item => {
const row = document.createElement('tr');
// 解析时间并调整为中国时间UTC+8
const date = new Date(item.timestamp);
// 减去8小时因为数据库时间似乎比实际时间早了8小时
date.setHours(date.getHours() - 8);
// 格式化为中文日期时间格式
const formattedDate =
date.getFullYear() + '/' +
(date.getMonth() + 1).toString().padStart(2, '0') + '/' +
date.getDate().toString().padStart(2, '0') + ' ' +
date.getHours().toString().padStart(2, '0') + ':' +
date.getMinutes().toString().padStart(2, '0') + ':' +
date.getSeconds().toString().padStart(2, '0');
row.innerHTML =
'<td>' + item.id + '</td>' +
'<td>' + item.sensor_id + '</td>' +
'<td>' + item.x.toFixed(3) + '</td>' +
'<td>' + item.y.toFixed(3) + '</td>' +
'<td>' + item.z.toFixed(3) + '</td>' +
'<td>' + formattedDate + '</td>';
tableBody.appendChild(row);
});
}
// 更新图表
function updateChart(data) {
// 准备图表数据
const chartData = prepareChartData(data);
// 如果图表已经存在,销毁它
if (sensorChart) {
sensorChart.destroy();
}
// 获取图表Canvas
const ctx = document.getElementById('sensorChart').getContext('2d');
// 创建新图表
sensorChart = new Chart(ctx, {
type: 'line',
data: chartData,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: '传感器数据趋势'
},
tooltip: {
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
label += context.parsed.y.toFixed(3);
}
return label;
}
}
}
},
scales: {
x: {
title: {
display: true,
text: '时间'
}
},
y: {
title: {
display: true,
text: '值'
}
}
}
}
});
}
// 准备图表数据
function prepareChartData(data) {
// 如果没有数据,返回空数据集
if (data.length === 0) {
return {
labels: [],
datasets: []
};
}
// 反转数据以便按时间先后顺序显示
const sortedData = [...data].sort((a, b) => {
return new Date(a.timestamp) - new Date(b.timestamp);
});
// 获取所有传感器ID
let sensorIDs = [...new Set(sortedData.map(item => item.sensor_id))];
// 按传感器ID分组数据
let datasets = [];
let labels = [];
// 准备时间标签(使用第一个传感器的数据)
if (sensorIDs.length > 0) {
const firstSensorData = sortedData.filter(item => item.sensor_id === sensorIDs[0]);
labels = firstSensorData.map(item => {
const date = new Date(item.timestamp);
date.setHours(date.getHours() - 8); // 调整时区
return date.toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
});
}
// 定义颜色
const colors = [
'rgb(75, 192, 192)',
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)',
'rgb(153, 102, 255)',
'rgb(255, 159, 64)'
];
// 为X, Y, Z创建不同的数据集
const dataTypes = [
{ key: 'x', label: 'X值' },
{ key: 'y', label: 'Y值' },
{ key: 'z', label: 'Z值' }
];
sensorIDs.forEach((sensorID, sensorIndex) => {
const sensorData = sortedData.filter(item => item.sensor_id === sensorID);
dataTypes.forEach((type, typeIndex) => {
const colorIndex = (sensorIndex * dataTypes.length + typeIndex) % colors.length;
datasets.push({
label: `传感器${sensorID} - ${type.label}`,
data: sensorData.map(item => item[type.key]),
fill: false,
borderColor: colors[colorIndex],
tension: 0.1
});
});
});
return {
labels: labels,
datasets: datasets
};
}
// 导出到CSV文件
function exportToCSV() {
if (currentSensorData.length === 0) {
alert('没有数据可导出');
return;
}
// 准备CSV内容
let csvContent = "ID,传感器ID,X值,Y值,Z值,时间戳\n";
currentSensorData.forEach(item => {
// 解析时间并调整为中国时间
const date = new Date(item.timestamp);
date.setHours(date.getHours() - 8);
// 格式化日期
const formattedDate =
date.getFullYear() + '/' +
(date.getMonth() + 1).toString().padStart(2, '0') + '/' +
date.getDate().toString().padStart(2, '0') + ' ' +
date.getHours().toString().padStart(2, '0') + ':' +
date.getMinutes().toString().padStart(2, '0') + ':' +
date.getSeconds().toString().padStart(2, '0');
// 添加一行数据
csvContent +=
item.id + "," +
item.sensor_id + "," +
item.x.toFixed(3) + "," +
item.y.toFixed(3) + "," +
item.z.toFixed(3) + "," +
formattedDate + "\n";
});
// 创建Blob对象
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
// 创建下载链接
const link = document.createElement("a");
const url = URL.createObjectURL(blob);
// 设置下载属性
link.setAttribute("href", url);
link.setAttribute("download", "sensor_data.csv");
// 添加到文档并点击
document.body.appendChild(link);
link.click();
// 清理
document.body.removeChild(link);
}