import { apiFetch } from "./api.js"; import { dom } from "./dom.js"; import { state } from "./state.js"; export async function openChart(pointId, pointName) { state.chartPointId = pointId; state.chartPointName = pointName || "点位"; dom.chartTitle.textContent = `${state.chartPointName} 曲线`; const items = await apiFetch(`/api/point/${pointId}/history?limit=120`); state.chartData = (items || []) .map((item) => ({ timestamp: item.timestamp || "", valueNumber: typeof item.value_number === "number" ? item.value_number : null, valueText: item.value_text || "", })) .filter((item) => item.valueNumber !== null); renderChart(); } export function renderChart() { const ctx = dom.chartCanvas.getContext("2d"); const width = dom.chartCanvas.width; const height = dom.chartCanvas.height; ctx.clearRect(0, 0, width, height); if (!state.chartData.length) { ctx.fillStyle = "#94a3b8"; ctx.font = "14px Segoe UI"; ctx.fillText("Click a point row to view its chart", 24, 40); dom.chartSummary.textContent = "点击上方点位表中的一行查看曲线"; return; } const values = state.chartData.map((item) => item.valueNumber); let min = Math.min(...values); let max = Math.max(...values); if (min === max) { min -= 1; max += 1; } const padding = { top: 20, right: 20, bottom: 36, left: 52 }; const plotWidth = width - padding.left - padding.right; const plotHeight = height - padding.top - padding.bottom; ctx.strokeStyle = "#2563eb"; ctx.lineWidth = 2; ctx.beginPath(); state.chartData.forEach((item, index) => { const x = padding.left + (plotWidth * index) / Math.max(1, state.chartData.length - 1); const y = padding.top + ((max - item.valueNumber) / (max - min)) * plotHeight; if (index === 0) { ctx.moveTo(x, y); } else { ctx.lineTo(x, y); } }); ctx.stroke(); const latest = state.chartData[state.chartData.length - 1]; dom.chartSummary.textContent = `最近 ${state.chartData.length} 个点,当前值 ${latest.valueText || latest.valueNumber}`; }