XNSim/XNSimHtml/components/data-collection.js

358 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class DataCollection extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.monitorStatus = 0; // 0-未监控1-监控中2-错误
this.statusTimer = null;
}
getCurrentSelection() {
const selection = localStorage.getItem('xnsim-selection');
if (!selection) {
return { plane: '', configurationId: '', domainId: '' };
}
try {
const parsedSelection = JSON.parse(selection);
return {
plane: parsedSelection.plane || '',
configurationId: parsedSelection.configurationId || '',
domainId: parsedSelection.domainId || ''
};
} catch (error) {
return { plane: '', configurationId: '', domainId: '' };
}
}
async loadInterfaces() {
try {
const { configurationId } = this.getCurrentSelection();
if (!configurationId) {
console.warn('未找到配置ID');
this.interfaces = [];
return;
}
const response = await fetch(`/api/interface/list?systemName=XNSim&confID=${configurationId}`);
const data = await response.json();
this.interfaces = data;
} catch (error) {
console.error('加载接口数据失败:', error);
this.interfaces = [];
}
}
async connectedCallback() {
await this.loadInterfaces();
this.render();
setTimeout(() => {
this.startStatusTimer();
}, 1000);
}
startStatusTimer() {
if (this.statusTimer) {
clearInterval(this.statusTimer);
}
this.statusTimer = setInterval(async () => {
try {
const res = await fetch('/api/dds-monitor/status');
if (!res.ok) throw new Error('网络错误');
const data = await res.json();
if (data.isInitialized) {
this.monitorStatus = 1;
} else {
this.monitorStatus = 0;
}
} catch (e) {
this.monitorStatus = 2;
}
this.updateMonitorStatus();
}, 1000);
}
disconnectedCallback() {
if (this.statusTimer) {
clearInterval(this.statusTimer);
this.statusTimer = null;
}
}
updateMonitorStatus() {
const statusIndicator = this.shadowRoot.getElementById('statusIndicator');
const statusText = this.shadowRoot.getElementById('statusText');
if (statusIndicator) {
statusIndicator.classList.remove('active', 'inactive', 'error');
switch (this.monitorStatus) {
case 1:
statusIndicator.classList.add('active');
break;
case 2:
statusIndicator.classList.add('error');
break;
default:
statusIndicator.classList.add('inactive');
}
}
if (statusText) {
switch (this.monitorStatus) {
case 1:
statusText.textContent = '监控中';
break;
case 2:
statusText.textContent = '监控错误';
break;
default:
statusText.textContent = '未监控';
}
}
}
render() {
// 树型控件分组
const groupedInterfaces = (this.interfaces || []).reduce((groups, item) => {
const group = groups[item.ModelStructName] || [];
group.push(item);
groups[item.ModelStructName] = group;
return groups;
}, {});
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
height: 100%;
overflow: auto;
padding: 16px;
box-sizing: border-box;
}
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 16px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
margin-bottom: 16px;
}
.toolbar-left {
display: flex;
align-items: center;
gap: 12px;
}
.monitor-status {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
color: #666;
}
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background: #ccc;
}
.status-indicator.active {
background: #52c41a;
}
.status-indicator.error {
background: #ff4d4f;
}
.status-indicator.inactive {
background: #d9d9d9;
}
.main-container {
display: flex;
height: calc(100% - 56px);
gap: 16px;
}
.left-panel {
width: 320px;
min-width: 280px;
display: flex;
flex-direction: column;
gap: 16px;
height: 100%;
}
.panel-section {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
}
.button-row {
display: flex;
gap: 12px;
}
.action-btn {
flex: 1;
padding: 8px 0;
border: none;
border-radius: 4px;
background: #1890ff;
color: #fff;
font-size: 14px;
cursor: pointer;
transition: background 0.2s;
}
.action-btn:hover {
background: #40a9ff;
}
.input-row {
display: flex;
flex-direction: column;
gap: 8px;
}
.input-group {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
width: 100%;
}
.input-label {
font-size: 13px;
color: #666;
min-width: 90px;
max-width: 90px;
flex-shrink: 0;
text-align: right;
line-height: 32px;
height: 32px;
display: flex;
align-items: center;
}
.input-box {
flex: 1;
width: 100%;
padding: 0 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
height: 32px;
line-height: 32px;
display: flex;
align-items: center;
}
.input-box[readonly] {
background: #f5f5f5;
color: #aaa;
cursor: not-allowed;
}
.tree-section {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
padding: 16px;
flex: 1 1 0;
min-height: 120px;
overflow-y: auto;
display: flex;
flex-direction: column;
}
.tree-view {
width: 100%;
flex: 1 1 0;
}
.tree-group {
margin-bottom: 8px;
width: 100%;
}
.group-header {
font-weight: bold;
padding: 8px;
background-color: #f5f5f5;
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
width: 100%;
box-sizing: border-box;
}
.group-content {
margin-left: 20px;
display: block;
width: calc(100% - 20px);
}
.group-content.collapsed {
display: none;
}
.interface-item {
padding: 6px 8px;
border-radius: 4px;
margin: 2px 0;
user-select: none;
width: 100%;
box-sizing: border-box;
color: #333;
}
.interface-item:hover {
background-color: #f0f0f0;
}
.collection-container {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
padding: 16px;
height: 100%;
box-sizing: border-box;
}
.collection-title {
font-size: 18px;
font-weight: bold;
color: #333;
}
</style>
<div class="toolbar">
<div class="toolbar-left">
<div class="monitor-status">
<div class="status-indicator" id="statusIndicator"></div>
<span id="statusText">未监控</span>
</div>
</div>
</div>
<div class="main-container">
<div class="left-panel">
<div class="panel-section">
<div class="button-row">
<button class="action-btn" id="loadScriptBtn">载入脚本</button>
<button class="action-btn" id="startCollectBtn">开始采集</button>
</div>
<div class="input-row">
<div class="input-group">
<div class="input-label">脚本文件</div>
<input class="input-box" id="scriptFileInput" type="text" value="" readonly />
</div>
<div class="input-group">
<div class="input-label">采集频率 (Hz)</div>
<input class="input-box" id="collectFreqInput" type="number" min="1" max="10000" value="100" />
</div>
<div class="input-group">
<div class="input-label">采集时长 (秒)</div>
<input class="input-box" id="collectDurationInput" type="number" min="1" max="86400" value="60" />
</div>
<div class="input-group">
<div class="input-label">输出文件</div>
<input class="input-box" id="outputFileInput" type="text" value="" />
</div>
</div>
</div>
<div class="tree-section">
<div style="font-size:14px;color:#333;font-weight:bold;margin-bottom:8px;">采集列表:</div>
<div class="tree-view">
<!-- 采集列表树型控件内容暂不显示 -->
</div>
</div>
</div>
</div>
`;
this.updateMonitorStatus();
}
}
customElements.define('data-collection', DataCollection);