class SimulationMonitor extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.monitorStatus = { isMonitoring: false, lastError: null }; this.systemInfo = null; this.threadInfo = null; this.statusCheckInterval = null; this.chart = null; this.chartInitialized = false; } connectedCallback() { this.render(); // 等待组件完全加载 setTimeout(() => { this.initializeComponent(); }, 100); } initializeComponent() { if (this.chartInitialized) return; try { this.initChart(); this.startStatusCheck(); this.chartInitialized = true; } catch (error) { console.error('初始化组件失败:', error); } } disconnectedCallback() { this.stopStatusCheck(); } startStatusCheck() { this.checkMonitorStatus(); this.statusCheckInterval = setInterval(() => { this.checkMonitorStatus(); }, 1000); } stopStatusCheck() { if (this.statusCheckInterval) { clearInterval(this.statusCheckInterval); this.statusCheckInterval = null; } } async checkMonitorStatus() { try { // 获取监控状态 const statusResponse = await fetch('/api/system-monitor/status'); const statusData = await statusResponse.json(); this.monitorStatus = statusData; if (this.monitorStatus.isMonitoring) { // 获取系统信息 const systemResponse = await fetch('/api/system-monitor/system-info'); const systemData = await systemResponse.json(); this.systemInfo = systemData.data; console.log('系统信息:', this.systemInfo); // 获取线程信息 const threadResponse = await fetch('/api/system-monitor/thread-info'); const threadData = await threadResponse.json(); this.threadInfo = threadData.data; } this.updateUI(); } catch (error) { console.error('获取监控状态失败:', error); this.monitorStatus.lastError = error.message; this.updateUI(); } } updateUI() { const input = this.shadowRoot.querySelector('.domain-input'); const startButton = this.shadowRoot.querySelector('.start-button'); const stopButton = this.shadowRoot.querySelector('.stop-button'); const statusDisplay = this.shadowRoot.querySelector('.status-display'); const engineInfo = this.shadowRoot.querySelector('#engine-info'); const coreStatus = this.shadowRoot.querySelector('#core-status'); const threadTableBody = this.shadowRoot.querySelector('#thread-table-body'); if (this.monitorStatus.isMonitoring) { input.disabled = true; startButton.disabled = true; stopButton.disabled = false; } else { input.disabled = false; startButton.disabled = false; stopButton.disabled = true; } // 更新状态显示 statusDisplay.textContent = `监控状态: ${this.monitorStatus.isMonitoring ? '运行中' : '已停止'}`; if (this.monitorStatus.lastError) { statusDisplay.textContent += ` (错误: ${this.monitorStatus.lastError})`; } // 更新引擎信息 const engineInfoFields = [ { label: '引擎名称', key: 'name' }, { label: '引擎ID', key: 'id' }, { label: '引擎状态', key: 'status' }, { label: '引擎亲和性', key: 'affinity' }, { label: '线程数', key: 'threadCount' } ]; engineInfo.innerHTML = `
${engineInfoFields.map(field => `
${field.label}
${this.monitorStatus.isMonitoring && this.systemInfo?.engineInfo ? (this.systemInfo.engineInfo[field.key] || '未知') : (field.key === 'status' ? '未运行' : '未知')}
`).join('')}
`; // 更新核心状态 const coreStatusFields = [ { label: '主框架状态', key: 'fwStatus' }, { label: '时间管理器状态', key: 'tmStatus' }, { label: '事件管理器状态', key: 'emStatus' }, { label: '环境管理器状态', key: 'sdStatus' }, { label: '线程管理器状态', key: 'thmStatus' }, { label: '模型管理器状态', key: 'mmStatus' }, { label: '服务管理器状态', key: 'smStatus' }, { label: 'DDS管理器状态', key: 'dmStatus' } ]; // 确保coreStatus元素存在 if (!coreStatus) { console.error('找不到核心状态元素'); return; } // 无论是否有数据,都显示状态项 coreStatus.innerHTML = `
${coreStatusFields.map(field => `
${field.label}
${this.monitorStatus.isMonitoring && this.systemInfo?.coreStatus ? (this.systemInfo.coreStatus[field.key] || '未知') : '未知'}
`).join('')}
`; // 更新线程表格 if (this.monitorStatus.isMonitoring && this.threadInfo && Array.isArray(this.threadInfo)) { threadTableBody.innerHTML = this.threadInfo.map(thread => ` ${thread.name || '未知'} ${thread.id || '未知'} ${thread.status || '未知'} ${thread.priority || '未知'} ${thread.runCount || '0'} ${(thread.currentFrequency || 0).toFixed(2)} ${(thread.setFrequency || 0).toFixed(2)} ${(thread.currentPeriod || 0).toFixed(2)} `).join(''); // 更新图表数据 this.updateChartData(); } else { threadTableBody.innerHTML = '暂无线程信息'; // 清空图表数据 if (this.chart) { this.chart.data.labels = []; this.chart.data.datasets = []; this.chart.update(); } } } async startMonitoring() { const domainId = this.shadowRoot.querySelector('.domain-input').value.trim(); // 验证域ID是否为有效的数字字符串 if (!/^\d+$/.test(domainId)) { console.error('域ID必须是有效的数字'); return; } try { // 首先检查DDS监控状态 const ddsStatusResponse = await fetch('/api/dds-monitor/status'); const ddsStatusData = await ddsStatusResponse.json(); // 如果DDS监控未初始化,先初始化DDS监控 if (!ddsStatusData.isInitialized) { const ddsInitResponse = await fetch('/api/dds-monitor/initialize', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domainId }) }); if (!ddsInitResponse.ok) { const errorData = await ddsInitResponse.json(); console.error('DDS监控初始化失败:', errorData.error); return; } } // 启动系统监控 const response = await fetch('/api/system-monitor/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domainId }) }); const data = await response.json(); if (response.ok) { this.monitorStatus = data.status; this.updateUI(); } else { console.error('启动监控失败:', data.error); } } catch (error) { console.error('启动监控失败:', error); } } async stopMonitoring() { try { const response = await fetch('/api/system-monitor/stop', { method: 'POST' }); const data = await response.json(); if (response.ok) { this.monitorStatus = data.status; this.updateUI(); } else { console.error('停止监控失败:', data.error); } } catch (error) { console.error('停止监控失败:', error); } } render() { this.shadowRoot.innerHTML = `
监控状态: 未启动

引擎信息

核心状态

线程信息

线程名称 线程ID 状态 优先级 运行次数 当前频率(Hz) 设置频率(Hz) 当前周期(ms)

线程监控

显示类型: 频率
`; } initChart() { const chartElement = this.shadowRoot.querySelector('#thread-chart'); if (!chartElement) { console.error('找不到图表元素'); return; } // 确保 Chart.js 已加载 if (typeof Chart === 'undefined') { console.error('Chart.js 未加载'); return; } try { // 创建图表实例 const ctx = chartElement.getContext('2d'); if (!ctx) { console.error('无法获取 canvas 上下文'); return; } // 销毁已存在的图表实例 if (this.chart) { this.chart.destroy(); } // 创建新的图表实例 this.chart = new Chart(ctx, { type: 'line', data: { labels: [], datasets: [] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true } }, animation: false, plugins: { legend: { display: true }, tooltip: { enabled: false } } } }); // 监听显示类型切换 const switchInput = this.shadowRoot.querySelector('#display-type-switch'); const displayTypeLabel = this.shadowRoot.querySelector('#display-type-label'); if (switchInput && displayTypeLabel) { switchInput.addEventListener('change', (e) => { const isFrequency = e.target.checked; displayTypeLabel.textContent = isFrequency ? '频率' : '周期'; this.updateChartDisplayType(isFrequency); }); } } catch (error) { console.error('初始化图表失败:', error); this.chart = null; } } updateChartData() { if (!this.chart || !this.threadInfo || !Array.isArray(this.threadInfo)) return; const isFrequency = this.shadowRoot.querySelector('#display-type-switch').checked; const currentTime = new Date().toLocaleTimeString(); // 确保图表数据集存在 if (!this.chart.data.datasets || this.chart.data.datasets.length === 0) { this.updateChartDisplayType(isFrequency); } // 更新数据 const newData = { labels: [...this.chart.data.labels, currentTime].slice(-30), datasets: this.threadInfo.map((thread, index) => { const dataset = this.chart.data.datasets[index] || { label: thread.name, data: [], borderColor: this.getRandomColor(), fill: false }; const value = isFrequency ? (thread.currentFrequency || 0) : (thread.currentPeriod || 0); dataset.data = [...dataset.data, value].slice(-30); return dataset; }) }; // 使用新数据更新图表 this.chart.data = newData; this.chart.update('none'); // 使用 'none' 模式更新,避免触发动画和事件 } updateChartDisplayType(isFrequency) { if (!this.threadInfo) return; const datasets = this.threadInfo.map(thread => ({ label: thread.name, data: [], borderColor: this.getRandomColor(), fill: false })); this.chart.data.datasets = datasets; this.chart.update('none'); // 使用 'none' 模式更新 } getRandomColor() { const letters = '0123456789ABCDEF'; let color = '#'; for (let i = 0; i < 6; i++) { color += letters[Math.floor(Math.random() * 16)]; } return color; } } customElements.define('simulation-monitor', SimulationMonitor);