|
|
@@ -55,6 +55,19 @@
|
|
|
</div>
|
|
|
|
|
|
<div class="section">
|
|
|
+ <div class="section-title">炉温曲线(最近 60 个采集点)</div>
|
|
|
+ <div style="position:relative; height:340px; border:1px solid rgba(0,160,255,0.25); border-radius:10px; padding:14px 16px 8px; background:rgba(8,26,56,0.4);">
|
|
|
+ <div style="margin-bottom:6px; font-size:12px; color:#9cc4f0;">
|
|
|
+ <span style="margin-right:18px;"><i style="display:inline-block;width:14px;height:3px;background:#ffb454;vertical-align:middle;margin-right:4px;"></i>一区温控PV</span>
|
|
|
+ <span style="margin-right:18px;"><i style="display:inline-block;width:14px;height:3px;background:#5ab8ff;vertical-align:middle;margin-right:4px;"></i>二区温控PV</span>
|
|
|
+ <span style="margin-right:18px;"><i style="display:inline-block;width:14px;height:3px;background:#41e6c3;vertical-align:middle;margin-right:4px;"></i>一区监控PV</span>
|
|
|
+ <span><i style="display:inline-block;width:14px;height:3px;background:#ff7a9c;vertical-align:middle;margin-right:4px;"></i>二区监控PV</span>
|
|
|
+ </div>
|
|
|
+ <canvas id="trendChart" style="width:100%; height:300px; display:block;"></canvas>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="section">
|
|
|
<div class="section-title">一区温度</div>
|
|
|
<div class="cards">
|
|
|
<div class="card tc-pv"><div class="card-label">一区温控 PV</div><div><span class="card-value" id="z1TcPv">--</span><span class="card-unit">℃</span></div></div>
|
|
|
@@ -124,11 +137,121 @@
|
|
|
error: function(){ setConn(false); }
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
+ // ===== 炉温曲线 =====
|
|
|
+ var trendCache = null;
|
|
|
+ function loadTrend(){
|
|
|
+ $.ajax({
|
|
|
+ url: CTX + '/mes/mesHeatProcess/trendData',
|
|
|
+ type: 'POST',
|
|
|
+ dataType: 'json',
|
|
|
+ data: { size: 60 },
|
|
|
+ success: function(data){
|
|
|
+ if(!data) return;
|
|
|
+ trendCache = data;
|
|
|
+ drawTrend();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function drawTrend(){
|
|
|
+ var c = document.getElementById('trendChart');
|
|
|
+ if(!c || !trendCache) return;
|
|
|
+ // 适配 DPR + 自适应宽度
|
|
|
+ var dpr = window.devicePixelRatio || 1;
|
|
|
+ var w = c.clientWidth, h = c.clientHeight;
|
|
|
+ c.width = w * dpr; c.height = h * dpr;
|
|
|
+ var ctx = c.getContext('2d');
|
|
|
+ ctx.setTransform(dpr,0,0,dpr,0,0);
|
|
|
+ ctx.clearRect(0,0,w,h);
|
|
|
+
|
|
|
+ var labels = trendCache.labels || [];
|
|
|
+ var series = [
|
|
|
+ { name:'一区温控PV', color:'#ffb454', data: trendCache.zone1TcPv || [] },
|
|
|
+ { name:'二区温控PV', color:'#5ab8ff', data: trendCache.zone2TcPv || [] },
|
|
|
+ { name:'一区监控PV', color:'#41e6c3', data: trendCache.zone1MonPv || [] },
|
|
|
+ { name:'二区监控PV', color:'#ff7a9c', data: trendCache.zone2MonPv || [] }
|
|
|
+ ];
|
|
|
+ var n = labels.length;
|
|
|
+ if(n < 2){
|
|
|
+ ctx.fillStyle = '#6f93c4'; ctx.font='14px Microsoft YaHei';
|
|
|
+ ctx.textAlign = 'center';
|
|
|
+ ctx.fillText('数据不足,等待采集...', w/2, h/2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算 Y 轴范围
|
|
|
+ var minV = Number.POSITIVE_INFINITY, maxV = Number.NEGATIVE_INFINITY;
|
|
|
+ for(var i=0;i<series.length;i++){
|
|
|
+ for(var j=0;j<series[i].data.length;j++){
|
|
|
+ var v = series[i].data[j];
|
|
|
+ if(v == null) continue;
|
|
|
+ if(v < minV) minV = v;
|
|
|
+ if(v > maxV) maxV = v;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!isFinite(minV) || !isFinite(maxV)){ minV = 0; maxV = 100; }
|
|
|
+ if(maxV === minV){ maxV = minV + 10; }
|
|
|
+ // 上下留一点空间
|
|
|
+ var range = maxV - minV;
|
|
|
+ minV = Math.floor(minV - range * 0.1);
|
|
|
+ maxV = Math.ceil(maxV + range * 0.1);
|
|
|
+
|
|
|
+ var padL = 50, padR = 14, padT = 10, padB = 28;
|
|
|
+ var cw = w - padL - padR, ch = h - padT - padB;
|
|
|
+
|
|
|
+ // 网格 + Y 轴
|
|
|
+ ctx.strokeStyle = 'rgba(0,143,253,0.18)';
|
|
|
+ ctx.fillStyle = 'rgba(120,180,230,0.85)';
|
|
|
+ ctx.font = '11px Microsoft YaHei';
|
|
|
+ ctx.textAlign = 'right';
|
|
|
+ ctx.lineWidth = 1;
|
|
|
+ for(var g=0; g<=4; g++){
|
|
|
+ var y = padT + ch * g / 4;
|
|
|
+ var val = Math.round(maxV - (maxV - minV) * g / 4);
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.moveTo(padL, y); ctx.lineTo(padL + cw, y);
|
|
|
+ ctx.stroke();
|
|
|
+ ctx.fillText(val, padL - 5, y + 4);
|
|
|
+ }
|
|
|
+
|
|
|
+ // X 轴标签:等距挑 6 个
|
|
|
+ ctx.textAlign = 'center';
|
|
|
+ var xCount = Math.min(6, n);
|
|
|
+ for(var t=0; t<xCount; t++){
|
|
|
+ var idx = Math.round((n - 1) * t / (xCount - 1));
|
|
|
+ var x = padL + (cw * idx) / (n - 1);
|
|
|
+ ctx.fillText(labels[idx] || '', x, padT + ch + 18);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 折线
|
|
|
+ for(var s=0; s<series.length; s++){
|
|
|
+ var sr = series[s];
|
|
|
+ ctx.strokeStyle = sr.color;
|
|
|
+ ctx.lineWidth = 2;
|
|
|
+ ctx.beginPath();
|
|
|
+ var started = false;
|
|
|
+ for(var k=0; k<n; k++){
|
|
|
+ var v = sr.data[k];
|
|
|
+ if(v == null){ started = false; continue; }
|
|
|
+ var x = padL + (cw * k) / (n - 1);
|
|
|
+ var y = padT + ch - ((v - minV) / (maxV - minV)) * ch;
|
|
|
+ if(!started){ ctx.moveTo(x,y); started = true; }
|
|
|
+ else { ctx.lineTo(x,y); }
|
|
|
+ }
|
|
|
+ ctx.stroke();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 窗口尺寸变化重绘
|
|
|
+ window.addEventListener('resize', drawTrend);
|
|
|
$(function(){
|
|
|
updateClock();
|
|
|
setInterval(updateClock, 1000);
|
|
|
loadData();
|
|
|
+ loadTrend();
|
|
|
setInterval(loadData, 5000);
|
|
|
+ setInterval(loadTrend, 5000);
|
|
|
});
|
|
|
</script>
|
|
|
</body>
|