Gauge仪表盘面板
- 主要用于直观展示某个数值在定义的最小和最大范围内的位置。
Grafana8.2.7 + InfluxDB1.x + ECharts2.2.4 对运行时间进行全天的占比计算
OEE = 正常运行时间 / 24h
一、基础查询
sql
SELECT "valueInt" FROM "prod_process_values" WHERE ("topic" = 'CT/OESL/AS/CHN/QDA/HCS/Extrusion_Area/ERS104_Extrusion_Line/MachineState')
AND $timeFilter
二、ECharts 面板 JS 计算OEE
- 分母固定为24h
- 最后状态若为运行,则最后运行时间为:now - 状态起始时间

javascript
// console.log("=== 完整 Grafana 数据结构 ===", data);
// console.log("=== 顶层 series 数组 ===", data?.series ?? []);
// console.log("=== 查询状态 ===", data?.state);
// console.log("=== 系列总数 ===", Array.isArray(data?.series) ? data.series.length : 0);
/**
* 工具:安全判断有效非空数组
* @param {*} arr
* @returns {boolean}
*/
function isSafeArray(arr) {
return Array.isArray(arr) && arr.length > 0;
}
/**
* 按 refId 匹配,返回对应单条系列对象
* @param {Object|null|undefined} data Grafana 根数据
* @param {string} refId 查询标识 A/B/C
* @returns {Object|null} 单个series对象
*/
function getSeriesByRefId(data, refId) {
if (!data || !isSafeArray(data.series)) return null;
return data.series.find(item => item.refId === refId) || null;
}
/**
* 根据字段固定下标提取数值数组
* 约定:fields[0] = Time,fields[1] = valueInt
* @param {Object|null} singleSeries 单个series对象
* @param {number} fieldIndex 0=Time / 1=valueInt
* @returns {Array} 数据数组,无数据返回[]
*/
function getFieldByIndex(singleSeries, fieldIndex) {
// 校验series和fields数组
if (!singleSeries || !isSafeArray(singleSeries.fields)) return [];
// 下标越界直接返回空
if (fieldIndex < 0 || fieldIndex >= singleSeries.fields.length) return [];
const targetField = singleSeries.fields[fieldIndex];
if (!targetField?.values) return [];
// 兼容 Grafana 两种存储格式:buffer / 直接values数组
const valueList = targetField.values.buffer ?? targetField.values;
return isSafeArray(valueList) ? valueList : [];
}
// ====================== 业务提取逻辑 ======================
const targetSeriesItem = getSeriesByRefId(data, "A");
const timeArr = getFieldByIndex(targetSeriesItem, 0);
const valueArr = getFieldByIndex(targetSeriesItem, 1);
console.log("时间数组 Time(fields[0]):", timeArr);
console.log("状态数组 valueInt(fields[1]):", valueArr);
// ====================== 精准计算运行时长(修改:最后一段用实时now) ======================
let runTotalMs = 0;
const dataLen = timeArr.length;
const segmentLog = [];
// 【修改】最后一段统一使用浏览器实时当前时间戳,不再用面板timeRange.to
const realNowTs = Date.now();
console.log("浏览器实时当前时间戳 realNowTs:", realNowTs, new Date(realNowTs).toLocaleString());
if (dataLen >= 2) {
// 逐段计算两个点位之间时长
for (let i = 0; i < dataLen - 1; i++) {
const s = valueArr[i];
const tStart = timeArr[i];
const tEnd = timeArr[i + 1];
const dur = tEnd - tStart;
segmentLog.push({
idx: i,
state: s,
start: new Date(tStart).toLocaleString(),
end: new Date(tEnd).toLocaleString(),
durationMs: dur
});
// 仅状态1累加时长
if (s === 1) {
runTotalMs += dur;
}
}
// 处理最后一个点位:当前持续状态,结束时间取实时now
const lastState = valueArr[dataLen - 1];
const lastTs = timeArr[dataLen - 1];
const lastDur = realNowTs - lastTs;
segmentLog.push({
idx: "last",
state: lastState,
start: new Date(lastTs).toLocaleString(),
end: new Date(realNowTs).toLocaleString(),
durationMs: lastDur,
note: "最后一段到浏览器实时当前时间now"
});
if (lastState === 1) {
runTotalMs += lastDur;
}
}
// 打印每一段明细,方便核对时长
console.log("分段明细日志:", segmentLog);
console.log("累计运行总毫秒 runTotalMs =", runTotalMs);
// 辅助换算
const runHours = (runTotalMs / (1000 * 60 * 60)).toFixed(3);
const dayTotalMs = 24 * 60 * 60 * 1000;
const oeeRate = runTotalMs / dayTotalMs;
const oeePercent = (oeeRate * 100).toFixed(2);
console.log("累计运行小时:", runHours, "h");
console.log("24h运行占比OEE:", oeePercent, "%");
// ====================== ECharts2.2.4 仪表盘配置 ======================
return {
tooltip: {
formatter: "{b}: {c}%"
},
series: [
{
type: 'gauge',
min: 0,
max: 100,
splitNumber: 10,
axisLine: {
lineStyle: {
width: 10,
color: [
[0.3, '#ff4444'],
[0.7, '#ffbb33'],
[1, '#00C851']
]
}
},
axisTick: {
length: 15,
lineStyle: {
color: 'auto'
}
},
splitLine: {
length: 20,
lineStyle: {
color: 'auto'
}
},
pointer: {
width: 5
},
title: {
show: true,
offsetCenter: [0, '70%'],
textStyle: {
fontSize: 16
}
},
detail: {
formatter: '{value} %',
fontSize: 24,
offsetCenter: [0, '40%']
},
data: [
{
value: Number(oeePercent),
name: ''
}
]
}
]
};