diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db
index 6ba44ec..8d22ca3 100644
Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ
diff --git a/XNSimHtml/components/FloatingChartWindow.js b/XNSimHtml/components/FloatingChartWindow.js
index 554e2da..630b869 100644
--- a/XNSimHtml/components/FloatingChartWindow.js
+++ b/XNSimHtml/components/FloatingChartWindow.js
@@ -198,10 +198,6 @@ class FloatingChartWindow extends HTMLElement {
flex-direction: column;
}
- .window-content.minimized {
- display: none;
- }
-
.chart-container {
flex: 1;
position: relative;
@@ -240,7 +236,6 @@ class FloatingChartWindow extends HTMLElement {
@@ -364,6 +359,16 @@ class FloatingChartWindow extends HTMLElement {
}
};
+ // 确保数据集配置正确
+ if (chartData.datasets && chartData.datasets.length > 0) {
+ chartData.datasets = chartData.datasets.map(dataset => ({
+ ...dataset,
+ borderWidth: 2,
+ pointRadius: 0,
+ tension: 0
+ }));
+ }
+
this.chartInstance = new Chart(ctx, {
type: 'line',
data: chartData,
@@ -373,12 +378,10 @@ class FloatingChartWindow extends HTMLElement {
addEventListeners() {
const header = this.shadowRoot.querySelector('.window-header');
- const minimizeButton = this.shadowRoot.querySelector('.minimize-button');
const closeButton = this.shadowRoot.querySelector('.close-button');
const resizeHandle = this.shadowRoot.querySelector('.resize-handle');
header.addEventListener('mousedown', this.handleMouseDown);
- minimizeButton.addEventListener('click', this.handleMinimize);
closeButton.addEventListener('click', this.handleClose);
resizeHandle.addEventListener('mousedown', this.handleResizeStart);
@@ -394,7 +397,7 @@ class FloatingChartWindow extends HTMLElement {
handleMouseDown(e) {
// 检查点击是否在标题栏或其子元素上
const header = this.shadowRoot.querySelector('.window-header');
- if (header && (e.target === header || header.contains(e.target)) && !this.isMinimized) {
+ if (header && (e.target === header || header.contains(e.target))) {
this.isDragging = true;
this.dragOffset = {
x: e.clientX - this.position.x,
@@ -420,7 +423,7 @@ class FloatingChartWindow extends HTMLElement {
y: Math.max(minY, e.clientY - this.dragOffset.y)
};
this.updatePosition();
- } else if (this.isResizing && !this.isMinimized) {
+ } else if (this.isResizing) {
const deltaX = e.clientX - this.resizeStart.x;
const deltaY = e.clientY - this.resizeStart.y;
@@ -452,7 +455,7 @@ class FloatingChartWindow extends HTMLElement {
}
handleResize(e) {
- if (this.isResizing && !this.isMinimized) {
+ if (this.isResizing) {
const deltaX = e.clientX - this.resizeStart.x;
const deltaY = e.clientY - this.resizeStart.y;
@@ -546,6 +549,38 @@ class FloatingChartWindow extends HTMLElement {
// 始终使用普通数字格式,保留一位小数
return `${context.dataset.label}: ${value.toFixed(1)}`;
};
+
+ // 计算所有数据点的范围
+ let min = Infinity;
+ let max = -Infinity;
+
+ data.datasets.forEach(dataset => {
+ if (dataset.data && dataset.data.length > 0) {
+ const datasetMin = Math.min(...dataset.data);
+ const datasetMax = Math.max(...dataset.data);
+ min = Math.min(min, datasetMin);
+ max = Math.max(max, datasetMax);
+ }
+ });
+
+ if (min !== Infinity && max !== -Infinity) {
+ const range = max - min;
+ // 如果所有数据都是0,使用固定范围
+ if (min === 0 && max === 0) {
+ options.scales.y.min = -1;
+ options.scales.y.max = 1;
+ }
+ // 如果范围很小,使用固定比例
+ else if (range < 1) {
+ options.scales.y.min = min - 0.5;
+ options.scales.y.max = max + 0.5;
+ } else {
+ // 如果范围较大,使用百分比
+ const margin = range * 0.2; // 使用20%的边距
+ options.scales.y.min = min - margin;
+ options.scales.y.max = max + margin;
+ }
+ }
// 更新图表
this.chartInstance.update('none');
@@ -565,6 +600,70 @@ class FloatingChartWindow extends HTMLElement {
window.style.zIndex = zIndex;
}
}
+
+ // 添加新方法:处理数据更新
+ handleDataUpdate(values, interfaceName) {
+ if (!this.chartInstance) return;
+
+ const chartData = this.chartInstance.data;
+
+ // 如果是第一次收到数据,创建数据集
+ if (chartData.datasets.length === 0) {
+ if (values.length > 1) {
+ // 创建多个数据集
+ chartData.datasets = values.map((_, index) => ({
+ label: `${interfaceName} (${index + 1})`,
+ data: [],
+ borderColor: this.getRandomColor(),
+ fill: false,
+ borderWidth: 2,
+ pointRadius: 0,
+ tension: 0
+ }));
+ } else {
+ // 创建单个数据集
+ chartData.datasets = [{
+ label: interfaceName,
+ data: [],
+ borderColor: this.getRandomColor(),
+ fill: false,
+ borderWidth: 2,
+ pointRadius: 0,
+ tension: 0
+ }];
+ }
+ }
+
+ // 添加新的数据点
+ chartData.labels.push(this.dataPointIndex.toString());
+ values.forEach((value, index) => {
+ if (index < chartData.datasets.length) {
+ chartData.datasets[index].data.push(value);
+ }
+ });
+ this.dataPointIndex++;
+
+ // 保持最近100个数据点
+ if (chartData.labels.length > 100) {
+ chartData.labels.shift();
+ chartData.datasets.forEach(dataset => {
+ dataset.data.shift();
+ });
+ }
+
+ // 更新图表
+ this.updateChartData(chartData);
+ }
+
+ // 添加新方法:获取随机颜色
+ getRandomColor() {
+ const letters = '0123456789ABCDEF';
+ let color = '#';
+ for (let i = 0; i < 6; i++) {
+ color += letters[Math.floor(Math.random() * 16)];
+ }
+ return color;
+ }
}
customElements.define('floating-chart-window', FloatingChartWindow);
\ No newline at end of file
diff --git a/XNSimHtml/components/data-monitor.js b/XNSimHtml/components/data-monitor.js
index 73b4b4c..5a955c7 100644
--- a/XNSimHtml/components/data-monitor.js
+++ b/XNSimHtml/components/data-monitor.js
@@ -366,6 +366,7 @@ class DataMonitor extends HTMLElement {
}
const groupedInterfaces = this.getGroupedInterfaces();
+ const allData = {}; // 存储所有结构体的数据
// 对每个结构体启动监控并获取数据
for (const [structName, interfaceNames] of Object.entries(groupedInterfaces)) {
@@ -403,13 +404,18 @@ class DataMonitor extends HTMLElement {
throw new Error(`获取监控数据失败: 返回数据为空`);
}
- // 更新表格数据
- this.updateTableData(responseData.data);
+ // 合并数据
+ Object.assign(allData, responseData.data);
} catch (structError) {
console.error(`处理结构体 ${structName} 时出错:`, structError);
continue;
}
}
+
+ // 一次性更新所有数据
+ if (Object.keys(allData).length > 0) {
+ this.updateTableData(allData);
+ }
} catch (error) {
console.error('数据更新失败:', error);
this.stopDataUpdateTimer();
@@ -488,7 +494,12 @@ class DataMonitor extends HTMLElement {
* @param {string} modelStructName - 结构体名称
*/
async handlePlot(interfaceName, modelStructName) {
-
+ // 检查监控状态
+ const statusIndicator = this.shadowRoot.getElementById('statusIndicator');
+ if (!statusIndicator || !statusIndicator.classList.contains('active')) {
+ return; // 如果不在监控状态,直接返回
+ }
+
// 检查是否已经存在该接口的图表窗口
const windowId = `${interfaceName}_${modelStructName}`;
if (this.chartWindows.has(windowId)) {
@@ -506,12 +517,7 @@ class DataMonitor extends HTMLElement {
// 创建图表数据
const chartData = {
labels: [],
- datasets: [{
- label: interfaceName,
- data: [],
- borderColor: this.getRandomColor(),
- fill: false
- }]
+ datasets: []
};
// 创建图表配置
@@ -530,6 +536,7 @@ class DataMonitor extends HTMLElement {
scales: {
y: {
beginAtZero: false,
+ display: true,
ticks: {
callback: function(value) {
// 如果数值的绝对值大于1000或小于0.1,使用科学计数法
@@ -567,11 +574,7 @@ class DataMonitor extends HTMLElement {
callbacks: {
label: function(context) {
const value = context.raw;
- // 如果数值的绝对值大于1000或小于0.1,使用科学计数法
- if (Math.abs(value) > 1000 || (Math.abs(value) < 0.1 && value !== 0)) {
- return `${context.dataset.label}: ${value.toExponential(1)}`;
- }
- // 否则使用普通数字,保留一位小数
+ // 始终使用普通数字格式,保留一位小数
return `${context.dataset.label}: ${value.toFixed(1)}`;
}
}
@@ -594,7 +597,7 @@ class DataMonitor extends HTMLElement {
// 再设置属性
floatingWindow.setAttribute('title', interfaceName);
- floatingWindow.setAttribute('initial-position', JSON.stringify({ x: 400, y: 200 })); // 调整初始位置
+ floatingWindow.setAttribute('initial-position', JSON.stringify({ x: 400, y: 200 }));
floatingWindow.setAttribute('initial-size', JSON.stringify({ width: 400, height: 300 }));
floatingWindow.setAttribute('chart-data', JSON.stringify(chartData));
floatingWindow.setAttribute('chart-options', JSON.stringify(chartOptions));
@@ -608,42 +611,26 @@ class DataMonitor extends HTMLElement {
if (row && row.monitorData) {
try {
- const data = JSON.parse(row.monitorData);
- let value;
- // 处理数值类型
- if (typeof data === 'number') {
- value = data;
- } else if (typeof data === 'object') {
- value = JSON.stringify(data);
+ const data = row.monitorData;
+ let values = [];
+
+ // 尝试解析数据
+ if (typeof data === 'string' && data.includes(',')) {
+ // 如果是逗号分隔的字符串,分割并转换为数字
+ values = data.split(',').map(v => parseFloat(v.trim()));
+ } else if (typeof data === 'number') {
+ // 如果是单个数字
+ values = [data];
} else {
// 尝试将字符串转换为数字
const numValue = parseFloat(data);
- value = isNaN(numValue) ? data : numValue;
- }
-
- // 使用独立的数据点计数器
- chartData.labels.push(floatingWindow.dataPointIndex.toString());
- chartData.datasets[0].data.push(value);
- floatingWindow.dataPointIndex++; // 增加计数器
-
- // 保持最近100个数据点
- if (chartData.labels.length > 100) {
- chartData.labels.shift();
- chartData.datasets[0].data.shift();
+ values = isNaN(numValue) ? [] : [numValue];
}
- // 如果是第一个数据点,设置y轴范围
- if (chartData.datasets[0].data.length === 1 && typeof value === 'number') {
- // 计算合适的y轴范围
- const range = Math.abs(value) * 0.2; // 使用20%的范围
- chartOptions.scales.y.min = value - range;
- chartOptions.scales.y.max = value + range;
- // 更新图表配置
- floatingWindow.setAttribute('chart-options', JSON.stringify(chartOptions));
+ // 如果数据有效,更新图表
+ if (values.length > 0) {
+ floatingWindow.handleDataUpdate(values, interfaceName);
}
-
- // 更新图表数据
- floatingWindow.setAttribute('chart-data', JSON.stringify(chartData));
} catch (e) {
console.error('解析数据失败:', e);
}
@@ -671,6 +658,10 @@ class DataMonitor extends HTMLElement {
}
render() {
+ // 获取当前监控状态
+ const statusIndicator = this.shadowRoot.getElementById('statusIndicator');
+ const isMonitoring = statusIndicator && statusIndicator.classList.contains('active');
+
// 按ModelStructName分组
const groupedInterfaces = this.filteredInterfaces.reduce((groups, item) => {
const group = groups[item.ModelStructName] || [];
@@ -1043,7 +1034,8 @@ class DataMonitor extends HTMLElement {
- ${this.tableData.map(row => `
+ ${this.tableData.map(row => `
+
${row.InterfaceName} |
${row.ModelStructName} |
${this.formatMonitorData(row.monitorData)} |