-
Notifications
You must be signed in to change notification settings - Fork 19.8k
Open
Labels
bugpendingWe are not sure about whether this is a bug/new feature.We are not sure about whether this is a bug/new feature.
Description
Version
6.0.0
Link to Minimal Reproduction
下面贴源码
Steps to Reproduce
数据类型:
槽号:
时间选择:
确定
重置
<!-- 主容器:树在左、图在中、右侧数据列 -->
<div class="main-container">
<div id="treebox" class="tree-container">
<a-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys"
v-model:checkedKeys="checkedKeys" :tree-data="treeData" @select="onTreeSelect">
<template #title="{ title, key }">
<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
<template v-else>{{ title }}</template>
</template>
</a-tree>
</div>
<div ref="chartRef" class="chart-container"></div>
<div class="data-columns">
<div class="column">
<h3>A</h3>
<div v-for="(item, index) in dataColumnA" :key="index" class="data-item">
<span class="data-name">{{ item.name }}</span>
<span class="data-value">{{ item.value }}</span>
</div>
</div>
<div class="column">
<h3>B</h3>
<div v-for="(item, index) in dataColumnB" :key="index" class="data-item">
<span class="data-name">{{ item.name }}</span>
<span class="data-value">{{ item.value }}</span>
</div>
</div>
</div>
</div>
${time}
`;
params.forEach(p => {
content += `${p.seriesName}: ${p.data[1]}
`;
});
return content;
}
},
legend: {
data: seriesData.map(s => s.name),
top: -5,
textStyle: { fontSize: 10 },
itemWidth: 12,
itemHeight: 8,
type: 'scroll',
},
grid: { left: 40, right: 20, top: 20, bottom: 10 },
xAxis: { type: 'time', axisLabel: { formatter: v => dayjs(v).format('HH:mm:ss') } },
yAxis: { scale: true },
dataZoom: [{ type: 'inside', xAxisIndex: 0 }],
series: seriesData,
});
charts.value.push(chart);
}
}
echarts.connect(charts.value);
setTimeout(() => charts.value.forEach(c => c.resize()), 50);
}
// ---------- WebSocket ----------
let ws = null;
function startWebSocket() {
if (ws) { ws.close(); ws = null; }
const wsUrl = `${Config.wsUrl}data?mt_id=${areaValue.value}`;
ws = new WebSocket(wsUrl);
let lastUpdateTime = 0; // 节流控制
ws.onmessage = (evt) => {
try {
const now = Date.now();
if (now - lastUpdateTime < 200) return; // 节流
lastUpdateTime = now;
const arr = JSON.parse(evt.data);
if (!arr.length) return;
const newest = Array.isArray(arr) ? arr[arr.length - 1] : arr;
latestPoint.value = newest;
const currentTime = parseTimeToMs(newest.time);
if (currentTime === null) return;
let idx = 0;
for (let yidx = 0; yidx < _matrixDimensionData.y.length; yidx++) {
for (let xidx = 0; xidx < _matrixDimensionData.x.length; xidx++) {
const chart = charts.value[idx++];
if (!chart) continue;
const seriesCount = (yidx === 0 ? 1 : 3);
const curOpt = chart.getOption();
for (let si = 0; si < seriesCount; si++) {
const key = mapSeriesToKey(xidx, yidx, si);
const val = newest[key] ?? 0;
const seriesKey = `${idx}-${si}`;
// 跳过时间戳不递增的数据
if (lastTimestamps.value[seriesKey] && lastTimestamps.value[seriesKey] >= currentTime)
continue;
lastTimestamps.value[seriesKey] = currentTime;
// ✅ 直接修改原 series.data 引用
const s = curOpt.series[si];
s.data.push([currentTime, val]);
if (s.data.length > MAX_POINTS_KEEP) s.data.shift();
}
// 更新 xAxis 范围
const allData = curOpt.series.flatMap(s => s.data);
const minTime = allData.length > 0 ? allData[0][0] : currentTime - 60 * 1000;
const maxTime = currentTime + 1000;
// 只更新 xAxis 和 series,保留 tooltip/legend/grid 的引用
chart.setOption({
xAxis: { min: minTime, max: maxTime },
series: curOpt.series
}, { notMerge: false, lazyUpdate: false });
}
}
updateRightColumnsFromLatest();
} catch (e) {
console.error('WebSocket 数据处理错误:', e);
}
};
ws.onerror = (error) => {
console.error('WebSocket 错误:', error);
ws.close();
ws = null;
setTimeout(startWebSocket, 5000);
};
ws.onclose = () => {
console.log('WebSocket 连接关闭');
ws = null;
};
}
// ---------- 右侧数据列 ----------
const dataColumnA = ref([]);
const dataColumnB = ref([]);
function updateRightColumnsFromLatest() {
const src = latestPoint.value ?? (apiData.value.length ? apiData.value[apiData.value.length - 1] : null);
if (!src) {
dataColumnA.value = [];
dataColumnB.value = [];
return;
}
dataColumnA.value = [];
dataColumnB.value = [];
_matrixDimensionData.y.forEach((yItem, yidx) => {
if (yidx === 0) {
// ✅ 电压行
dataColumnA.value.push({ name: '电压', value: src.a01 ?? 0 });
dataColumnB.value.push({ name: '电压', value: src.b01 ?? 0 });
} else {
const names = txtName[yidx];
names.forEach((name, li) => {
let keyA, keyB;
// ✅ A01 / B01 复用电压
if (yidx === 1 && li === 0) {
keyA = 'a01';
keyB = 'b01';
} else {
const baseIndex = (yidx - 1) * 3 + li + 1; // 改为 +1,保持与上方一致
keyA = 'a' + String(baseIndex).padStart(2, '0');
keyB = 'b' + String(baseIndex).padStart(2, '0');
}
dataColumnA.value.push({ name: `A${name}`, value: src[keyA] ?? 0 });
dataColumnB.value.push({ name: `B${name}`, value: src[keyB] ?? 0 });
});
}
});
}
// ---------- 生命周期 ----------
onMounted(async () => {
nextTick(() => renderMatrixCharts());
});
onBeforeUnmount(() => {
if (ws) { ws.close(); ws = null; }
charts.value.forEach(c => c.dispose());
charts.value = [];
});
</script>
<style scoped>
#QueryCard {
border-radius: 8px;
background: linear-gradient(135deg, #ffffff, #f6f8fa);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
padding: 1vh;
font-size: 1.6vh;
cursor: default;
}
.Card_Item {
width: 90%;
margin: 1vh auto;
}
.QueryCard_Item {
display: flex;
align-items: center;
justify-content: center;
gap: 1.5vw;
}
.query-item {
display: flex;
align-items: center;
gap: 0.5vw;
}
.query-item span {
font-weight: 500;
color: #333;
}
#search {
background: linear-gradient(45deg, #399bff, #5abaff);
transition: transform 0.2s, box-shadow 0.2s;
}
#cancel {
background: linear-gradient(45deg, #efca04, #ffdb4d);
transition: transform 0.2s, box-shadow 0.2s;
}
.Button_Item {
color: #fff;
border-radius: 6px;
border: none;
width: 4vw;
height: 3.5vh;
letter-spacing: 0.2vw;
font-size: 0.8vw;
font-weight: 500;
cursor: pointer;
}
.Button_Item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.main-container {
display: flex;
width: 100%;
height: 79vh;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
overflow: visible;
}
.tree-container {
width: 12vw;
min-width: 150px;
max-width: 200px;
padding: 1vh;
background: #fafafa;
border-right: 1px solid #e8e8e8;
overflow: auto;
}
.chart-container {
flex: 1;
position: relative;
height: 100%;
background: #fff;
}
.data-columns {
width: 14vw;
min-width: 180px;
max-width: 220px;
padding: 1.5vh;
background: linear-gradient(#fff, #f9f9f9);
border-left: 1px solid #e8e8e8;
display: flex;
gap: 1rem;
box-sizing: border-box;
}
.column {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.data-item {
width: 100%;
display: flex;
justify-content: space-between;
padding: 0.5rem;
background: #fff;
border-radius: 6px;
margin-bottom: 6px;
}
</style>
Current Behavior
动态添加数据后无法显示tooltip
Expected Behavior
动态添加数据后正常显示tooltip,并且是联动显示
Environment
- OS:win11
- Browser:Chrome 96.0.4664.55
- Framework:Vue@3
Any additional comments?
主要是在setoption方法上的问题
Metadata
Metadata
Assignees
Labels
bugpendingWe are not sure about whether this is a bug/new feature.We are not sure about whether this is a bug/new feature.