diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db
index 2090c35..44c1dd5 100644
Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ
diff --git a/XNSimHtml/bak/interface-config.js b/XNSimHtml/bak/interface-config.js
new file mode 100644
index 0000000..cd5710a
--- /dev/null
+++ b/XNSimHtml/bak/interface-config.js
@@ -0,0 +1,2120 @@
+class InterfaceConfig extends HTMLElement {
+ constructor() {
+ super();
+ this.attachShadow({ mode: 'open' });
+ this.idlContent = '';
+ this.filePath = '';
+ this.isEdited = false;
+ }
+
+ connectedCallback() {
+ this.render();
+ this.addEventListeners();
+
+ // 加载IDL文件列表到下拉框
+ this.loadIdlFileList();
+ }
+
+ addEventListeners() {
+ // 新建文件按钮
+ this.shadowRoot.getElementById('new-file').addEventListener('click', () => this.handleNewFile());
+
+ // 文件选择下拉框
+ this.shadowRoot.getElementById('file-select-dropdown').addEventListener('change', (e) => {
+ if (e.target.value) {
+ this.handleFileChange(e.target.value);
+ }
+ });
+
+ // 保存按钮
+ this.shadowRoot.getElementById('save-button').addEventListener('click', () => this.saveFile());
+
+ // 另存为按钮
+ this.shadowRoot.getElementById('save-as-button').addEventListener('click', () => this.saveFileAs());
+
+ // 文本编辑器内容变化时更新可视化编辑器和编辑状态
+ this.shadowRoot.getElementById('idl-editor').addEventListener('input', () => {
+ this.idlContent = this.shadowRoot.getElementById('idl-editor').value;
+ this.updateVisualEditor();
+ this.setEditedState(true);
+ });
+ }
+
+ async selectFile() {
+ try {
+ // 获取IDL文件列表
+ const response = await fetch('/api/idl/list');
+
+ if (!response.ok) {
+ const error = await response.json();
+ throw new Error(error.error || '获取文件列表失败');
+ }
+
+ const data = await response.json();
+
+ // 显示文件选择对话框
+ if (!data.files || data.files.length === 0) {
+ this.showConfirmDialog('文件列表', '没有可用的IDL文件', null);
+ return;
+ }
+
+ // 创建文件选择对话框
+ const fileSelector = document.createElement('div');
+ fileSelector.className = 'method-dialog';
+
+ const fileListHtml = data.files.map(file => `
+
+
${fieldItem ? '编辑字段' : '添加新字段'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+
+ this.shadowRoot.appendChild(dialog);
+
+ // 数组维度选择事件
+ this.shadowRoot.getElementById('array-dimension').addEventListener('change', (e) => {
+ const dimension = parseInt(e.target.value);
+
+ // 显示/隐藏数组大小输入框
+ for (let i = 1; i <= 2; i++) {
+ const row = this.shadowRoot.getElementById(`array-size-row-${i}`);
+ if (row) {
+ if (i <= dimension) {
+ row.classList.remove('hidden');
+ } else {
+ row.classList.add('hidden');
+ }
+ }
+ }
+ });
+
+ // 对话框取消事件
+ this.shadowRoot.getElementById('dialog-cancel').addEventListener('click', () => {
+ dialog.remove();
+ });
+
+ // 对话框保存事件
+ this.shadowRoot.getElementById('dialog-save').addEventListener('click', () => {
+ // 获取字段信息
+ const isOptional = this.shadowRoot.getElementById('field-optional').checked;
+ const fieldAnnotation = isOptional ? '@optional' : '';
+ const fieldType = this.shadowRoot.getElementById('field-type').value;
+ const fieldName = this.shadowRoot.getElementById('field-name').value.trim();
+ const arrayDimension = parseInt(this.shadowRoot.getElementById('array-dimension').value);
+
+ // 构建数组表示
+ let fieldArray = '';
+ if (arrayDimension > 0) {
+ for (let i = 1; i <= arrayDimension; i++) {
+ const size = this.shadowRoot.getElementById(`array-size-${i}`).value.trim();
+ fieldArray += `[${size}]`;
+ }
+ }
+
+ if (fieldName) {
+ const fieldContent = `
+
- 无法编辑:XML文档的根元素不是Model。
- 请确保XML文档的根元素是Model。
-
`;
- }
-
- container.appendChild(style);
- container.appendChild(visualEditor);
-
- // 自动保存配置到XML
- this.autoSaveToXml();
- }
-
- // 自动保存表单内容到XML
- autoSaveToXml() {
- // 为所有输入框添加change事件
- const inputs = this.shadowRoot.querySelectorAll('.property-input');
- inputs.forEach(input => {
- input.addEventListener('change', () => {
- this.updateXmlFromVisualEditor(); // 更新XML
- this.markEdited(); // 标记已编辑
- });
- });
- }
-
- renderBasicInfoSection(container, rootElement) {
- const section = document.createElement('div');
- section.className = 'section';
-
- const sectionHeader = document.createElement('div');
- sectionHeader.className = 'section-header';
-
- const sectionTitle = document.createElement('div');
- sectionTitle.className = 'section-title-text';
- sectionTitle.textContent = '基本信息';
-
- sectionHeader.appendChild(sectionTitle);
- section.appendChild(sectionHeader);
-
- // 基本信息字段及描述
- const basicInfoFields = [
- { name: 'Name', label: '模型名称', placeholder: '请输入模型名称', tooltip: '模型的名称,用于在系统中标识此模型' },
- { name: 'Description', label: '模型描述', placeholder: '请输入模型描述', tooltip: '对模型功能和用途的简要描述' },
- { name: 'Author', label: '作者', placeholder: '请输入作者', tooltip: '模型创建者或维护者的姓名' },
- { name: 'Version', label: '版本', placeholder: '请输入版本号,如: 1.0.0', tooltip: '模型的版本号,建议使用语义化版本号格式' },
- { name: 'CreateTime', label: '创建时间', placeholder: '创建时间,如: 2023-12-31 12:00:00', tooltip: '模型首次创建的日期和时间', type: 'datetime' },
- { name: 'ChangeTime', label: '修改时间', placeholder: '修改时间,如: 2023-12-31 12:00:00', tooltip: '模型最后一次修改的日期和时间', type: 'datetime' }
- ];
-
- // 创建两列布局容器
- const twoColumnForm = document.createElement('div');
- twoColumnForm.className = 'form-container two-column-form';
- twoColumnForm.style.display = 'grid';
- twoColumnForm.style.gridTemplateColumns = 'repeat(2, 1fr)';
- twoColumnForm.style.gap = '16px';
-
- // 处理基本信息字段
- basicInfoFields.forEach(field => {
- // 获取元素值
- const element = rootElement.querySelector(field.name);
- const value = element ? element.textContent : '';
-
- // 创建属性行
- const row = document.createElement('div');
- row.className = 'property-row';
-
- // 创建标签
- const label = document.createElement('div');
- label.className = 'property-label';
- label.textContent = field.label;
- label.style.width = '90px'; // 设置固定宽度使标签对齐
-
- // 创建输入容器
- const inputContainer = document.createElement('div');
- inputContainer.className = 'input-container';
- inputContainer.style.flex = '1';
- inputContainer.style.display = 'flex';
-
- // 创建输入框
- const input = document.createElement('input');
- input.type = 'text';
- input.className = 'property-input';
- input.dataset.field = field.name;
- input.value = value;
- input.placeholder = field.placeholder;
- input.title = field.tooltip;
-
- // 添加输入事件处理
- input.addEventListener('change', () => {
- this.updateElementValue(field.name, input.value);
- });
-
- inputContainer.appendChild(input);
-
- // 对于日期时间类型,添加日期选择按钮
- if (field.type === 'datetime') {
- input.style.flex = '1';
-
- const datetimeButton = document.createElement('button');
- datetimeButton.type = 'button';
- datetimeButton.className = 'icon-button calendar-button';
- datetimeButton.title = '选择日期和时间';
- datetimeButton.addEventListener('click', () => {
- this.showDateTimeDialog(input);
- });
-
- // 添加一个刷新按钮,快速设置为当前时间
- const refreshButton = document.createElement('button');
- refreshButton.type = 'button';
- refreshButton.className = 'icon-button refresh-button-sm';
- refreshButton.title = '设置为当前时间';
- refreshButton.addEventListener('click', () => {
- const now = new Date();
- const dateStr = now.toISOString().split('T')[0];
- const timeStr = now.toTimeString().split(' ')[0];
- const datetimeStr = `${dateStr} ${timeStr}`;
-
- input.value = datetimeStr;
- this.updateElementValue(field.name, datetimeStr);
- this.markEdited(); // 确保触发修改标志
- });
-
- inputContainer.appendChild(datetimeButton);
- inputContainer.appendChild(refreshButton);
- }
-
- // 组装行
- row.appendChild(label);
- row.appendChild(inputContainer);
- twoColumnForm.appendChild(row);
- });
-
- section.appendChild(twoColumnForm);
- container.appendChild(section);
- }
-
- // 显示日期时间选择对话框
- showDateTimeDialog(inputElement) {
- // 解析当前日期和时间
- let currentDate = new Date();
- let currentTime = '00:00:00';
-
- if (inputElement.value) {
- try {
- const parts = inputElement.value.split(' ');
- if (parts.length >= 1) {
- const dateParts = parts[0].split('-');
- if (dateParts.length === 3) {
- const year = parseInt(dateParts[0]);
- const month = parseInt(dateParts[1]) - 1; // 月份从0开始
- const day = parseInt(dateParts[2]);
- currentDate = new Date(year, month, day);
- }
- }
-
- if (parts.length >= 2) {
- currentTime = parts[1];
- }
- } catch (error) {
- console.error('解析日期时间失败:', error);
- currentDate = new Date();
- }
- }
-
- // 创建模态框
- const modal = document.createElement('div');
- modal.className = 'modal';
- modal.id = 'dateTimeModal';
-
- // 获取年、月、日
- const year = currentDate.getFullYear();
- const month = currentDate.getMonth(); // 0-11
- const day = currentDate.getDate();
-
- // 生成日历
- const daysInMonth = new Date(year, month + 1, 0).getDate();
- const firstDay = new Date(year, month, 1).getDay(); // 0-6,0表示周日
-
- // 生成月份选项
- let monthOptions = '';
- const monthNames = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
- monthNames.forEach((name, idx) => {
- monthOptions += `
- 无法编辑:XML文档的根元素不是Scenario。
- 请确保XML文档的根元素是Scenario。
-
`;
- }
-
- container.appendChild(style);
- container.appendChild(visualEditor);
-
- // 自动保存配置到XML
- this.autoSaveToXml();
- }
-
- // 自动保存表单内容到XML
- autoSaveToXml() {
- // 为所有输入框添加change事件
- const inputs = this.shadowRoot.querySelectorAll('.property-input');
- inputs.forEach(input => {
- input.addEventListener('change', () => {
- this.updateXmlFromVisualEditor();
- });
- });
- }
-
- // 创建模态对话框
- createModal(title, content, confirmCallback) {
- // 创建模态框容器
- const modalOverlay = document.createElement('div');
- modalOverlay.className = 'modal-overlay active';
- modalOverlay.style.position = 'fixed';
- modalOverlay.style.top = '0';
- modalOverlay.style.left = '0';
- modalOverlay.style.right = '0';
- modalOverlay.style.bottom = '0';
- modalOverlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
- modalOverlay.style.display = 'flex';
- modalOverlay.style.alignItems = 'center';
- modalOverlay.style.justifyContent = 'center';
- modalOverlay.style.zIndex = '1000';
-
- // 创建模态框
- const modal = document.createElement('div');
- modal.className = 'modal-content';
- modal.style.backgroundColor = 'white';
- modal.style.borderRadius = '12px';
- modal.style.padding = '24px';
- modal.style.width = '500px';
- modal.style.maxWidth = '90%';
- modal.style.maxHeight = '90vh';
- modal.style.overflowY = 'auto';
- modal.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)';
-
- // 创建模态框头部
- const modalHeader = document.createElement('div');
- modalHeader.className = 'modal-header';
- modalHeader.style.display = 'flex';
- modalHeader.style.justifyContent = 'space-between';
- modalHeader.style.alignItems = 'center';
- modalHeader.style.marginBottom = '16px';
-
- // 创建标题
- const modalTitle = document.createElement('h2');
- modalTitle.className = 'modal-title';
- modalTitle.textContent = title;
- modalTitle.style.fontSize = '20px';
- modalTitle.style.fontWeight = 'bold';
- modalTitle.style.color = '#2c3e50';
- modalTitle.style.margin = '0';
-
- // 关闭按钮
- const closeBtn = document.createElement('button');
- closeBtn.className = 'close-btn';
- closeBtn.innerHTML = '×';
- closeBtn.style.background = 'none';
- closeBtn.style.border = 'none';
- closeBtn.style.fontSize = '24px';
- closeBtn.style.cursor = 'pointer';
- closeBtn.style.color = '#718096';
- closeBtn.style.lineHeight = '1';
- closeBtn.style.padding = '0';
-
- // 添加关闭按钮事件
- closeBtn.onclick = () => {
- modalOverlay.remove();
- };
-
- // 组装头部
- modalHeader.appendChild(modalTitle);
- modalHeader.appendChild(closeBtn);
-
- // 创建表单容器
- const formContainer = document.createElement('form');
- formContainer.style.marginBottom = '0';
-
- // 添加内容
- if (content) {
- // 如果内容已经是DOM元素,直接使用
- if (content instanceof HTMLElement) {
- // 为内容添加样式
- content.style.margin = '0 0 20px 0';
- formContainer.appendChild(content);
- } else {
- // 否则创建新的内容容器
- const contentDiv = document.createElement('div');
- contentDiv.innerHTML = content;
- contentDiv.style.margin = '0 0 20px 0';
- formContainer.appendChild(contentDiv);
- }
- }
-
- // 创建按钮容器
- const modalFooter = document.createElement('div');
- modalFooter.className = 'modal-footer';
- modalFooter.style.display = 'flex';
- modalFooter.style.justifyContent = 'flex-end';
- modalFooter.style.gap = '12px';
- modalFooter.style.marginTop = '24px';
-
- // 取消按钮
- const cancelButton = document.createElement('button');
- cancelButton.className = 'btn btn-secondary';
- cancelButton.type = 'button';
- cancelButton.textContent = '取消';
- cancelButton.style.padding = '10px 16px';
- cancelButton.style.borderRadius = '6px';
- cancelButton.style.fontSize = '15px';
- cancelButton.style.cursor = 'pointer';
- cancelButton.style.transition = 'all 0.3s';
- cancelButton.style.backgroundColor = '#f8f9fa';
- cancelButton.style.border = '1px solid #ddd';
- cancelButton.style.color = '#718096';
-
- // 添加取消按钮事件
- cancelButton.onclick = () => {
- modalOverlay.remove();
- };
-
- // 确定按钮
- const confirmButton = document.createElement('button');
- confirmButton.className = 'btn btn-primary';
- confirmButton.type = 'button';
- confirmButton.textContent = '确定';
- confirmButton.style.padding = '10px 16px';
- confirmButton.style.borderRadius = '6px';
- confirmButton.style.fontSize = '15px';
- confirmButton.style.cursor = 'pointer';
- confirmButton.style.transition = 'all 0.3s';
- confirmButton.style.background = 'linear-gradient(135deg, #667eea, #764ba2)';
- confirmButton.style.border = 'none';
- confirmButton.style.color = 'white';
-
- // 添加确定按钮事件
- confirmButton.onclick = () => {
- if (confirmCallback) {
- confirmCallback();
- modalOverlay.remove(); // 确保回调执行后关闭对话框
- }
- };
-
- // 点击背景关闭
- modalOverlay.onclick = (e) => {
- if (e.target === modalOverlay) {
- modalOverlay.remove();
- }
- };
-
- // 组装底部按钮
- modalFooter.appendChild(cancelButton);
- modalFooter.appendChild(confirmButton);
-
- // 组装表单
- formContainer.appendChild(modalFooter);
-
- // 阻止表单提交默认行为
- formContainer.onsubmit = (e) => {
- e.preventDefault();
- if (confirmCallback) {
- confirmCallback();
- modalOverlay.remove(); // 确保回调执行后关闭对话框
- }
- return false;
- };
-
- // 组装整个模态框
- modal.appendChild(modalHeader);
- modal.appendChild(formContainer);
- modalOverlay.appendChild(modal);
-
- // 添加到DOM
- this.shadowRoot.appendChild(modalOverlay);
-
- // 返回引用
- return {
- modal: modalOverlay,
- confirmButton: confirmButton
- };
- }
-
- // 渲染Environment部分
- renderEnvironmentSection(container, rootElement) {
- const envElement = rootElement.querySelector('Environment');
-
- if (!envElement) {
- return; // 如果找不到Environment元素,直接返回
- }
-
- const section = document.createElement('div');
- section.className = 'editor-section';
-
- const title = document.createElement('div');
- title.className = 'section-title';
- title.textContent = '环境配置';
- section.appendChild(title);
-
- const propertyGroup = document.createElement('div');
- propertyGroup.className = 'property-group';
-
- // 获取并显示所有Environment属性
- Array.from(envElement.attributes).forEach(attr => {
- const propertyItem = document.createElement('div');
- propertyItem.className = 'property-item';
-
- const label = document.createElement('label');
- label.className = 'property-label';
- label.textContent = attr.name;
-
- // 对CPUAffinity属性使用特殊处理
- if (attr.name === 'CPUAffinity') {
- const inputContainer = document.createElement('div');
- inputContainer.style.display = 'flex';
- inputContainer.style.position = 'relative';
-
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.style.flexGrow = '1';
- input.title = 'CPU亲和性';
- input.addEventListener('change', () => this.markEdited());
-
- const dropdownButton = document.createElement('button');
- dropdownButton.className = 'dropdown-button';
- dropdownButton.type = 'button'; // 确保按钮类型为button
- dropdownButton.innerHTML = '▼';
- dropdownButton.style.width = '30px';
- dropdownButton.style.border = '1px solid #ddd';
- dropdownButton.style.borderLeft = 'none';
- dropdownButton.style.borderRadius = '0 4px 4px 0';
- dropdownButton.style.backgroundColor = '#f5f5f5';
- dropdownButton.style.cursor = 'pointer';
-
- // 创建下拉框容器
- const dropdown = document.createElement('div');
- dropdown.className = 'cpu-dropdown';
- dropdown.style.position = 'absolute';
- dropdown.style.top = '100%';
- dropdown.style.left = '0';
- dropdown.style.right = '0';
- dropdown.style.backgroundColor = 'white';
- dropdown.style.border = '1px solid #ddd';
- dropdown.style.borderRadius = '4px';
- dropdown.style.boxShadow = '0 2px 10px rgba(0,0,0,0.1)';
- dropdown.style.zIndex = '50'; // 提高z-index确保在最上层
- dropdown.style.padding = '10px';
- dropdown.style.display = 'none';
-
- // 生成CPU核心选项
- const cpuCount = 16; // 假设最多16个核心
-
- const selectedCores = attr.value.split(',').map(core => parseInt(core.trim())).filter(core => !isNaN(core));
-
- for (let i = 0; i < cpuCount; i++) {
- const checkboxContainer = document.createElement('div');
- checkboxContainer.style.marginBottom = '6px';
-
- const checkbox = document.createElement('input');
- checkbox.type = 'checkbox';
- checkbox.id = `cpu-${i}`;
- checkbox.value = i;
- checkbox.checked = selectedCores.includes(i);
- checkbox.style.marginRight = '6px';
-
- const checkboxLabel = document.createElement('label');
- checkboxLabel.htmlFor = `cpu-${i}`;
- checkboxLabel.textContent = `CPU ${i}`;
-
- checkbox.addEventListener('change', () => {
- // 获取所有选中的核心
- const checkedCores = Array.from(dropdown.querySelectorAll('input[type="checkbox"]:checked'))
- .map(cb => cb.value)
- .sort((a, b) => a - b);
-
- // 更新输入框的值
- input.value = checkedCores.join(',');
- input.dispatchEvent(new Event('change'));
- });
-
- checkboxContainer.appendChild(checkbox);
- checkboxContainer.appendChild(checkboxLabel);
- dropdown.appendChild(checkboxContainer);
- }
-
- // 添加应用和取消按钮
- const buttonContainer = document.createElement('div');
- buttonContainer.style.display = 'flex';
- buttonContainer.style.justifyContent = 'flex-end';
- buttonContainer.style.marginTop = '10px';
- buttonContainer.style.gap = '8px';
-
- const closeButton = document.createElement('button');
- closeButton.textContent = '关闭';
- closeButton.style.padding = '6px 12px';
- closeButton.style.backgroundColor = '#f0f0f0';
- closeButton.style.border = '1px solid #ddd';
- closeButton.style.borderRadius = '4px';
- closeButton.style.cursor = 'pointer';
-
- closeButton.addEventListener('click', (e) => {
- e.preventDefault();
- e.stopPropagation();
- dropdown.style.display = 'none';
- });
-
- buttonContainer.appendChild(closeButton);
- dropdown.appendChild(buttonContainer);
-
- // 使用更可靠的方法显示下拉菜单
- const toggleDropdown = (e) => {
- e.preventDefault();
- e.stopPropagation();
- if (dropdown.style.display === 'none' || !dropdown.style.display) {
- dropdown.style.display = 'block';
- // 添加全局一次性点击事件,用于关闭下拉框
- setTimeout(() => {
- const closeDropdown = (event) => {
- if (!dropdown.contains(event.target) && event.target !== dropdownButton) {
- dropdown.style.display = 'none';
- document.removeEventListener('click', closeDropdown);
- }
- };
- document.addEventListener('click', closeDropdown);
- }, 0);
- } else {
- dropdown.style.display = 'none';
- }
- };
-
- // 点击下拉按钮时显示或隐藏下拉框
- dropdownButton.addEventListener('click', toggleDropdown);
-
- inputContainer.appendChild(input);
- inputContainer.appendChild(dropdownButton);
- inputContainer.appendChild(dropdown);
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(inputContainer);
- } else if (attr.name === 'BaseFrequency') {
- // 对数字类型的属性使用number类型输入框
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'number';
- input.min = '0';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.title = '仿真运行基础频率,单位Hz';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'OSName') {
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.title = '操作系统名称';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'Version') {
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.title = '操作系统版本';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'RTXVersion') {
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.title = '实时内核版本';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'WorkPath') {
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.title = '仿真工作路径,XNCore环境变量所在路径';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'ModelsPath') {
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.title = '模型相对路径,相对于仿真工作路径';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'ServicesPath') {
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.title = '服务相对路径,相对于仿真工作路径';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'DomainID') {
- // 对数字类型的属性使用number类型输入框
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'number';
- input.min = '0';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.title = 'DDS通信域ID';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else {
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `Environment@${attr.name}`;
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- }
-
- propertyGroup.appendChild(propertyItem);
- });
-
- section.appendChild(propertyGroup);
-
- // 添加"添加新属性"按钮
- const addButton = document.createElement('button');
- addButton.className = 'add-button';
- addButton.textContent = '添加新属性';
- addButton.title = '添加新的运行环境属性';
- addButton.addEventListener('click', () => this.showAddPropertyDialog('Environment'));
- section.appendChild(addButton);
-
- container.appendChild(section);
- }
-
- // 添加新属性对话框
- showAddPropertyDialog(elementName) {
- // 创建表单内容
- const formContent = document.createElement('div');
- formContent.className = 'modal-form';
-
- // 属性名输入
- const nameRow = document.createElement('div');
- nameRow.className = 'form-row';
-
- const nameLabel = document.createElement('label');
- nameLabel.className = 'form-label';
- nameLabel.textContent = '属性名称';
-
- const nameInput = document.createElement('input');
- nameInput.className = 'form-input';
- nameInput.type = 'text';
- nameInput.placeholder = '请输入属性名称';
-
- nameRow.appendChild(nameLabel);
- nameRow.appendChild(nameInput);
- formContent.appendChild(nameRow);
-
- // 属性值输入
- const valueRow = document.createElement('div');
- valueRow.className = 'form-row';
-
- const valueLabel = document.createElement('label');
- valueLabel.className = 'form-label';
- valueLabel.textContent = '属性值';
-
- const valueInput = document.createElement('input');
- valueInput.className = 'form-input';
- valueInput.type = 'text';
- valueInput.placeholder = '请输入属性值';
-
- valueRow.appendChild(valueLabel);
- valueRow.appendChild(valueInput);
- formContent.appendChild(valueRow);
-
- // 显示对话框
- this.createModal('添加新属性', formContent, () => {
- const propertyName = nameInput.value.trim();
- const propertyValue = valueInput.value;
-
- if (propertyName) {
- this.addNewProperty(elementName, propertyName, propertyValue);
- }
- });
- }
-
- // 添加新属性
- addNewProperty(elementName, propertyName, propertyValue) {
- // 更新UI
- const section = Array.from(this.shadowRoot.querySelectorAll('.section-title')).find(el => {
- if (elementName === 'Environment' && el.textContent === '环境配置') return true;
- return false;
- })?.parentElement;
-
- if (section) {
- const propertyGroup = section.querySelector('.property-group');
- if (propertyGroup) {
- const propertyItem = document.createElement('div');
- propertyItem.className = 'property-item';
-
- const label = document.createElement('label');
- label.className = 'property-label';
- label.textContent = propertyName;
-
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = propertyValue;
- input.dataset.path = `${elementName}@${propertyName}`;
- input.dataset.isNew = 'true';
- input.addEventListener('change', () => this.markEdited());
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- propertyGroup.appendChild(propertyItem);
-
- this.markEdited();
- this.updateXmlFromVisualEditor(true); // 静默更新XML
- }
- }
- }
-
- // 全局变量,用于存储CPU亲和性设置
- updateCPUAffinityOptions() {
- // 从环境配置中获取CPUAffinity的值
- const envElement = this.xmlDoc.querySelector('Environment');
- if (!envElement) return [];
-
- const cpuAffinity = envElement.getAttribute('CPUAffinity') || '0';
- const availableCores = cpuAffinity.split(',').map(core => parseInt(core.trim())).filter(core => !isNaN(core));
- return availableCores;
- }
-
- // 渲染模型组部分
- renderModelGroupsSection(container, rootElement) {
- const section = document.createElement('div');
- section.className = 'editor-section';
-
- const title = document.createElement('div');
- title.className = 'section-title';
- title.textContent = '模型组配置';
- section.appendChild(title);
-
- // 获取所有ModelGroup元素
- const modelGroups = rootElement.querySelectorAll('ModelGroup');
-
- if (modelGroups.length === 0) {
- const emptyMsg = document.createElement('div');
- emptyMsg.textContent = '没有找到模型组配置';
- emptyMsg.style.color = '#888';
- emptyMsg.style.fontStyle = 'italic';
- emptyMsg.style.marginBottom = '16px';
- section.appendChild(emptyMsg);
- } else {
- // 为每个ModelGroup创建一个列表项
- modelGroups.forEach((modelGroup, index) => {
- const groupItem = document.createElement('div');
- groupItem.className = 'list-item';
- groupItem.dataset.index = index;
-
- // 创建组标题和操作按钮
- const header = document.createElement('div');
- header.className = 'list-item-header';
-
- const groupTitle = document.createElement('div');
- groupTitle.className = 'list-item-title';
- groupTitle.textContent = modelGroup.getAttribute('Name') || `模型组 ${index + 1}`;
-
- const actions = document.createElement('div');
- actions.className = 'list-item-actions';
-
- const deleteButton = document.createElement('button');
- deleteButton.className = 'action-icon';
- deleteButton.title = '删除模型组';
- deleteButton.style.border = 'none';
- deleteButton.style.background = 'none';
- deleteButton.style.cursor = 'pointer';
- deleteButton.style.padding = '4px';
- deleteButton.style.display = 'flex';
- deleteButton.style.alignItems = 'center';
- deleteButton.style.justifyContent = 'center';
-
- const deleteImg = document.createElement('img');
- deleteImg.src = 'assets/icons/png/delete_b.png';
- deleteImg.alt = '删除';
- deleteImg.style.width = '16px';
- deleteImg.style.height = '16px';
-
- deleteButton.appendChild(deleteImg);
- deleteButton.addEventListener('click', () => this.deleteModelGroup(index));
-
- actions.appendChild(deleteButton);
-
- header.appendChild(groupTitle);
- header.appendChild(actions);
- groupItem.appendChild(header);
-
- // 显示模型组属性
- const propertiesContainer = document.createElement('div');
- propertiesContainer.className = 'property-group';
- propertiesContainer.style.marginTop = '12px';
-
- // 获取可用的CPU核心选项
- const availableCores = this.updateCPUAffinityOptions();
-
- Array.from(modelGroup.attributes).forEach(attr => {
- const propertyItem = document.createElement('div');
- propertyItem.className = 'property-item';
-
- const label = document.createElement('label');
- label.className = 'property-label';
- label.textContent = attr.name;
-
- // 根据属性名使用不同的输入控件
- if (attr.name === 'FreqGroup') {
- // FreqGroup使用限制范围的数字输入框
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'number';
- input.min = '0';
- input.max = '6';
- input.value = attr.value;
- input.dataset.path = `ModelGroup[${index}]@${attr.name}`;
- input.title = '频率组,取值范围0-6';
- input.addEventListener('change', () => {
- // 确保值在有效范围内
- if (parseInt(input.value) > 6) {
- input.value = '6';
- }
- this.markEdited();
- });
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'Priority') {
- // Priority使用限制范围的数字输入框
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'number';
- input.min = '0';
- input.max = '99';
- input.value = attr.value;
- input.dataset.path = `ModelGroup[${index}]@${attr.name}`;
- input.title = '线程优先级,取值范围0-99';
- input.addEventListener('change', () => {
- // 确保值在有效范围内
- if (parseInt(input.value) > 99) {
- input.value = '99';
- }
- this.markEdited();
- });
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else if (attr.name === 'CPUAff') {
- // CPUAff使用下拉框
- const select = document.createElement('select');
- select.className = 'property-input';
- select.dataset.path = `ModelGroup[${index}]@${attr.name}`;
- select.title = '选择一个可用的亲和CPU核心';
-
- // 添加可用的CPU核心选项
- availableCores.forEach(core => {
- const option = document.createElement('option');
- option.value = core;
- option.textContent = `CPU ${core}`;
-
- // 如果当前值匹配,设为选中
- if (parseInt(attr.value) === core) {
- option.selected = true;
- }
-
- select.appendChild(option);
- });
-
- // 如果没有可用选项,添加一个默认选项
- if (availableCores.length === 0) {
- const option = document.createElement('option');
- option.value = attr.value;
- option.textContent = `CPU ${attr.value}`;
- option.selected = true;
- select.appendChild(option);
- }
-
- select.addEventListener('change', () => {
- this.markEdited();
- });
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(select);
- } else if (attr.name === 'Name') {
- // 模型组名称
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `ModelGroup[${index}]@${attr.name}`;
- input.title = '模型组名称';
- input.addEventListener('change', () => {
- this.markEdited();
- groupTitle.textContent = input.value || `模型组 ${index + 1}`;
- });
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- } else {
- // 其他属性使用文本输入框
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `ModelGroup[${index}]@${attr.name}`;
- input.addEventListener('change', () => {
- this.markEdited();
- });
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- }
-
- propertiesContainer.appendChild(propertyItem);
- });
-
- groupItem.appendChild(propertiesContainer);
-
- // 显示模型列表
- const modelsTitle = document.createElement('div');
- modelsTitle.textContent = '模型列表';
- modelsTitle.style.fontWeight = 'bold';
- modelsTitle.style.margin = '16px 0 12px';
- groupItem.appendChild(modelsTitle);
-
- const models = modelGroup.querySelectorAll('Model');
- const modelsContainer = document.createElement('div');
- modelsContainer.style.marginLeft = '16px';
-
- if (models.length === 0) {
- const emptyModelMsg = document.createElement('div');
- emptyModelMsg.textContent = '没有找到模型';
- emptyModelMsg.style.color = '#888';
- emptyModelMsg.style.fontStyle = 'italic';
- emptyModelMsg.style.marginBottom = '12px';
- modelsContainer.appendChild(emptyModelMsg);
- } else {
- models.forEach((model, modelIndex) => {
- const modelItem = document.createElement('div');
- modelItem.className = 'list-item';
- modelItem.style.marginBottom = '12px';
-
- const modelHeader = document.createElement('div');
- modelHeader.className = 'list-item-header';
-
- const modelTitle = document.createElement('div');
- modelTitle.className = 'list-item-title';
- modelTitle.textContent = model.getAttribute('Name') || `模型 ${modelIndex + 1}`;
-
- const modelActions = document.createElement('div');
- modelActions.className = 'list-item-actions';
-
- const deleteModelButton = document.createElement('button');
- deleteModelButton.className = 'action-icon';
- deleteModelButton.title = '删除模型';
- deleteModelButton.style.border = 'none';
- deleteModelButton.style.background = 'none';
- deleteModelButton.style.cursor = 'pointer';
- deleteModelButton.style.padding = '4px';
- deleteModelButton.style.display = 'flex';
- deleteModelButton.style.alignItems = 'center';
- deleteModelButton.style.justifyContent = 'center';
-
- const deleteModelImg = document.createElement('img');
- deleteModelImg.src = 'assets/icons/png/delete_b.png';
- deleteModelImg.alt = '删除';
- deleteModelImg.style.width = '16px';
- deleteModelImg.style.height = '16px';
-
- deleteModelButton.appendChild(deleteModelImg);
- deleteModelButton.addEventListener('click', () => this.deleteModel(index, modelIndex));
-
- modelActions.appendChild(deleteModelButton);
-
- modelHeader.appendChild(modelTitle);
- modelHeader.appendChild(modelActions);
- modelItem.appendChild(modelHeader);
-
- // 显示模型属性
- const modelProperties = document.createElement('div');
- modelProperties.className = 'property-group';
- modelProperties.style.marginTop = '12px';
-
- Array.from(model.attributes).forEach(attr => {
- if (attr.name === 'Name') {
- // 如果是Name属性,我们需要查看是否有ClassName属性
- const classNameAttr = model.getAttribute('ClassName');
-
- // 创建一个行容器,直接放在标题下方
- const rowContainer = document.createElement('div');
- rowContainer.style.display = 'flex';
- rowContainer.style.width = '100%';
- rowContainer.style.gap = '10px';
- rowContainer.style.marginTop = '8px';
- rowContainer.style.marginBottom = '8px';
-
- // 名称标签和输入框组
- const nameGroup = document.createElement('div');
- nameGroup.style.display = 'flex';
- nameGroup.style.alignItems = 'center';
- nameGroup.style.flex = '1';
-
- const nameLabel = document.createElement('label');
- nameLabel.className = 'property-label';
- nameLabel.textContent = 'Name';
- nameLabel.style.marginRight = '5px';
- nameLabel.style.minWidth = '60px';
-
- const nameInput = document.createElement('input');
- nameInput.className = 'property-input';
- nameInput.type = 'text';
- nameInput.value = attr.value;
- nameInput.dataset.path = `ModelGroup[${index}]/Model[${modelIndex}]@${attr.name}`;
- nameInput.title = '模型名称';
- nameInput.addEventListener('change', () => {
- this.markEdited();
- modelTitle.textContent = nameInput.value || `模型 ${modelIndex + 1}`;
- });
-
- nameGroup.appendChild(nameLabel);
- nameGroup.appendChild(nameInput);
-
- // 类名标签和输入框组
- const classGroup = document.createElement('div');
- classGroup.style.display = 'flex';
- classGroup.style.alignItems = 'center';
- classGroup.style.flex = '1';
-
- const classLabel = document.createElement('label');
- classLabel.className = 'property-label';
- classLabel.textContent = 'ClassName';
- classLabel.style.marginRight = '5px';
- classLabel.style.minWidth = '80px';
-
- const classInput = document.createElement('input');
- classInput.className = 'property-input';
- classInput.type = 'text';
- classInput.value = classNameAttr || '';
- classInput.dataset.path = `ModelGroup[${index}]/Model[${modelIndex}]@ClassName`;
- classInput.title = '模型C++类名';
- classInput.addEventListener('change', () => {
- this.markEdited();
- });
-
- classGroup.appendChild(classLabel);
- classGroup.appendChild(classInput);
-
- // 将名称组和类名组添加到行容器
- rowContainer.appendChild(nameGroup);
- rowContainer.appendChild(classGroup);
-
- // 直接添加到modelItem,而不是添加到modelProperties
- modelItem.appendChild(rowContainer);
-
- // 将ClassName标记为已处理,后面不需要再处理
- model.setAttribute('ClassName_processed', 'true');
- } else if (attr.name === 'ClassName') {
- // 如果是ClassName且已处理,则跳过
- if (model.getAttribute('ClassName_processed') === 'true') {
- return;
- }
-
- // 如果Name还没被处理,我们需要创建完整的行
- const nameAttr = model.getAttribute('Name');
-
- // 创建一个行容器
- const rowContainer = document.createElement('div');
- rowContainer.style.display = 'flex';
- rowContainer.style.width = '100%';
- rowContainer.style.gap = '10px';
- rowContainer.style.marginTop = '8px';
- rowContainer.style.marginBottom = '8px';
-
- // 名称标签和输入框组
- const nameGroup = document.createElement('div');
- nameGroup.style.display = 'flex';
- nameGroup.style.alignItems = 'center';
- nameGroup.style.flex = '1';
-
- const nameLabel = document.createElement('label');
- nameLabel.className = 'property-label';
- nameLabel.textContent = 'Name';
- nameLabel.style.marginRight = '5px';
- nameLabel.style.minWidth = '60px';
-
- const nameInput = document.createElement('input');
- nameInput.className = 'property-input';
- nameInput.type = 'text';
- nameInput.value = nameAttr || '';
- nameInput.dataset.path = `ModelGroup[${index}]/Model[${modelIndex}]@Name`;
- nameInput.title = '模型名称';
- nameInput.addEventListener('change', () => {
- this.markEdited();
- modelTitle.textContent = nameInput.value || `模型 ${modelIndex + 1}`;
- });
-
- nameGroup.appendChild(nameLabel);
- nameGroup.appendChild(nameInput);
-
- // 类名标签和输入框组
- const classGroup = document.createElement('div');
- classGroup.style.display = 'flex';
- classGroup.style.alignItems = 'center';
- classGroup.style.flex = '1';
-
- const classLabel = document.createElement('label');
- classLabel.className = 'property-label';
- classLabel.textContent = 'ClassName';
- classLabel.style.marginRight = '5px';
- classLabel.style.minWidth = '80px';
-
- const classInput = document.createElement('input');
- classInput.className = 'property-input';
- classInput.type = 'text';
- classInput.value = attr.value;
- classInput.dataset.path = `ModelGroup[${index}]/Model[${modelIndex}]@ClassName`;
- classInput.title = '模型C++类名';
- classInput.addEventListener('change', () => {
- this.markEdited();
- });
-
- classGroup.appendChild(classLabel);
- classGroup.appendChild(classInput);
-
- // 将名称组和类名组添加到行容器
- rowContainer.appendChild(nameGroup);
- rowContainer.appendChild(classGroup);
-
- // 直接添加到modelItem,而不是添加到modelProperties
- modelItem.appendChild(rowContainer);
-
- // 将Name标记为已处理
- model.setAttribute('Name_processed', 'true');
- } else {
- // 其他属性加入属性组
- const propertyItem = document.createElement('div');
- propertyItem.className = 'property-item';
-
- const label = document.createElement('label');
- label.className = 'property-label';
- label.textContent = attr.name;
-
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `ModelGroup[${index}]/Model[${modelIndex}]@${attr.name}`;
- input.addEventListener('change', () => {
- this.markEdited();
- });
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- modelProperties.appendChild(propertyItem);
- }
- });
-
- // 只有当有其他属性时才添加属性组
- if (modelProperties.children.length > 0) {
- // 添加一个标题来分隔基本属性和其他属性
- const otherPropsTitle = document.createElement('div');
- otherPropsTitle.textContent = '其他属性';
- otherPropsTitle.style.fontWeight = 'bold';
- otherPropsTitle.style.fontSize = '0.9em';
- otherPropsTitle.style.margin = '8px 0';
- modelItem.appendChild(otherPropsTitle);
-
- modelItem.appendChild(modelProperties);
- }
-
- // 清除处理标记
- Array.from(model.attributes).forEach(attr => {
- if (attr.name === 'Name_processed' || attr.name === 'ClassName_processed') {
- model.removeAttribute(attr.name);
- }
- });
-
- modelItem.appendChild(modelProperties);
- modelsContainer.appendChild(modelItem);
- });
- }
-
- groupItem.appendChild(modelsContainer);
-
- // 添加模型按钮
- const addModelButton = document.createElement('button');
- addModelButton.className = 'add-button';
- addModelButton.style.marginTop = '12px';
- addModelButton.textContent = '添加模型';
- addModelButton.title = '添加新模型到当前模型组';
- addModelButton.addEventListener('click', () => this.showAddModelDialog(index));
- groupItem.appendChild(addModelButton);
-
- section.appendChild(groupItem);
- });
- }
-
- // 添加新模型组按钮
- const addButton = document.createElement('button');
- addButton.className = 'add-button';
- addButton.style.marginTop = '16px';
- addButton.textContent = '添加模型组';
- addButton.title = '添加新的模型组';
- addButton.addEventListener('click', () => this.showAddModelGroupDialog());
- section.appendChild(addButton);
-
- container.appendChild(section);
- }
-
- // 渲染服务部分
- renderServicesSection(container, rootElement) {
- const section = document.createElement('div');
- section.className = 'editor-section';
-
- const title = document.createElement('div');
- title.className = 'section-title';
- title.textContent = '服务配置';
- section.appendChild(title);
-
- // 获取ServicesList元素
- const servicesList = rootElement.querySelector('ServicesList');
-
- if (!servicesList) {
- const emptyMsg = document.createElement('div');
- emptyMsg.textContent = '没有找到服务列表配置';
- emptyMsg.style.color = '#888';
- emptyMsg.style.fontStyle = 'italic';
- emptyMsg.style.marginBottom = '16px';
- section.appendChild(emptyMsg);
- } else {
- // 获取所有Service元素
- const services = servicesList.querySelectorAll('Service');
-
- if (services.length === 0) {
- const emptyMsg = document.createElement('div');
- emptyMsg.textContent = '没有找到服务配置';
- emptyMsg.style.color = '#888';
- emptyMsg.style.fontStyle = 'italic';
- emptyMsg.style.marginBottom = '16px';
- section.appendChild(emptyMsg);
- } else {
- // 为每个Service创建一个列表项
- services.forEach((service, index) => {
- const serviceItem = document.createElement('div');
- serviceItem.className = 'list-item';
-
- // 创建服务标题和操作按钮
- const header = document.createElement('div');
- header.className = 'list-item-header';
-
- const serviceTitle = document.createElement('div');
- serviceTitle.className = 'list-item-title';
- serviceTitle.textContent = service.getAttribute('Name') || `服务 ${index + 1}`;
-
- const actions = document.createElement('div');
- actions.className = 'list-item-actions';
-
- const deleteButton = document.createElement('button');
- deleteButton.className = 'action-icon';
- deleteButton.title = '删除服务';
- deleteButton.style.border = 'none';
- deleteButton.style.background = 'none';
- deleteButton.style.cursor = 'pointer';
- deleteButton.style.padding = '4px';
- deleteButton.style.display = 'flex';
- deleteButton.style.alignItems = 'center';
- deleteButton.style.justifyContent = 'center';
-
- const deleteImg = document.createElement('img');
- deleteImg.src = 'assets/icons/png/delete_b.png';
- deleteImg.alt = '删除';
- deleteImg.style.width = '16px';
- deleteImg.style.height = '16px';
-
- deleteButton.appendChild(deleteImg);
- deleteButton.addEventListener('click', () => this.deleteService(index));
-
- actions.appendChild(deleteButton);
-
- header.appendChild(serviceTitle);
- header.appendChild(actions);
- serviceItem.appendChild(header);
-
- // 显示服务属性
- const propertiesContainer = document.createElement('div');
- propertiesContainer.className = 'property-group';
- propertiesContainer.style.marginTop = '12px';
-
- Array.from(service.attributes).forEach(attr => {
- const propertyItem = document.createElement('div');
- propertyItem.className = 'property-item';
-
- const label = document.createElement('label');
- label.className = 'property-label';
- label.textContent = attr.name;
-
- if (attr.name === 'Name') {
- // 如果是Name属性,我们需要查看是否有ClassName属性
- const classNameAttr = service.getAttribute('ClassName');
-
- // 创建一个行容器,直接放在标题下方
- const rowContainer = document.createElement('div');
- rowContainer.style.display = 'flex';
- rowContainer.style.width = '100%';
- rowContainer.style.gap = '10px';
- rowContainer.style.marginTop = '8px';
- rowContainer.style.marginBottom = '8px';
-
- // 名称标签和输入框组
- const nameGroup = document.createElement('div');
- nameGroup.style.display = 'flex';
- nameGroup.style.alignItems = 'center';
- nameGroup.style.flex = '1';
-
- const nameLabel = document.createElement('label');
- nameLabel.className = 'property-label';
- nameLabel.textContent = 'Name';
- nameLabel.style.marginRight = '5px';
- nameLabel.style.minWidth = '60px';
-
- const nameInput = document.createElement('input');
- nameInput.className = 'property-input';
- nameInput.type = 'text';
- nameInput.value = attr.value;
- nameInput.dataset.path = `ServicesList/Service[${index}]@${attr.name}`;
- nameInput.title = '服务名称';
- nameInput.addEventListener('change', () => {
- this.markEdited();
- serviceTitle.textContent = nameInput.value || `服务 ${index + 1}`;
- });
-
- nameGroup.appendChild(nameLabel);
- nameGroup.appendChild(nameInput);
-
- // 类名标签和输入框组
- const classGroup = document.createElement('div');
- classGroup.style.display = 'flex';
- classGroup.style.alignItems = 'center';
- classGroup.style.flex = '1';
-
- const classLabel = document.createElement('label');
- classLabel.className = 'property-label';
- classLabel.textContent = 'ClassName';
- classLabel.style.marginRight = '5px';
- classLabel.style.minWidth = '80px';
-
- const classInput = document.createElement('input');
- classInput.className = 'property-input';
- classInput.type = 'text';
- classInput.value = classNameAttr || '';
- classInput.dataset.path = `ServicesList/Service[${index}]@ClassName`;
- classInput.title = '服务C++类名';
- classInput.addEventListener('change', () => {
- this.markEdited();
- });
-
- classGroup.appendChild(classLabel);
- classGroup.appendChild(classInput);
-
- // 将名称组和类名组添加到行容器
- rowContainer.appendChild(nameGroup);
- rowContainer.appendChild(classGroup);
-
- // 直接添加到serviceItem,而不是添加到propertiesContainer
- serviceItem.appendChild(rowContainer);
-
- // 将ClassName标记为已处理,后面不需要再处理
- service.setAttribute('ClassName_processed', 'true');
- } else if (attr.name === 'ClassName') {
- // 如果是ClassName且已处理,则跳过
- if (service.getAttribute('ClassName_processed') === 'true') {
- return;
- }
-
- // 如果Name还没被处理,我们需要创建完整的行
- const nameAttr = service.getAttribute('Name');
-
- // 创建一个行容器
- const rowContainer = document.createElement('div');
- rowContainer.style.display = 'flex';
- rowContainer.style.width = '100%';
- rowContainer.style.gap = '10px';
- rowContainer.style.marginTop = '8px';
- rowContainer.style.marginBottom = '8px';
-
- // 名称标签和输入框组
- const nameGroup = document.createElement('div');
- nameGroup.style.display = 'flex';
- nameGroup.style.alignItems = 'center';
- nameGroup.style.flex = '1';
-
- const nameLabel = document.createElement('label');
- nameLabel.className = 'property-label';
- nameLabel.textContent = 'Name';
- nameLabel.style.marginRight = '5px';
- nameLabel.style.minWidth = '60px';
-
- const nameInput = document.createElement('input');
- nameInput.className = 'property-input';
- nameInput.type = 'text';
- nameInput.value = nameAttr || '';
- nameInput.dataset.path = `ServicesList/Service[${index}]@Name`;
- nameInput.title = '服务名称';
- nameInput.addEventListener('change', () => {
- this.markEdited();
- serviceTitle.textContent = nameInput.value || `服务 ${index + 1}`;
- });
-
- nameGroup.appendChild(nameLabel);
- nameGroup.appendChild(nameInput);
-
- // 类名标签和输入框组
- const classGroup = document.createElement('div');
- classGroup.style.display = 'flex';
- classGroup.style.alignItems = 'center';
- classGroup.style.flex = '1';
-
- const classLabel = document.createElement('label');
- classLabel.className = 'property-label';
- classLabel.textContent = 'ClassName';
- classLabel.style.marginRight = '5px';
- classLabel.style.minWidth = '80px';
-
- const classInput = document.createElement('input');
- classInput.className = 'property-input';
- classInput.type = 'text';
- classInput.value = attr.value;
- classInput.dataset.path = `ServicesList/Service[${index}]@ClassName`;
- classInput.title = '服务C++类名';
- classInput.addEventListener('change', () => {
- this.markEdited();
- });
-
- classGroup.appendChild(classLabel);
- classGroup.appendChild(classInput);
-
- // 将名称组和类名组添加到行容器
- rowContainer.appendChild(nameGroup);
- rowContainer.appendChild(classGroup);
-
- propertyItem.appendChild(rowContainer);
- propertiesContainer.appendChild(propertyItem);
-
- // 将Name标记为已处理
- service.setAttribute('Name_processed', 'true');
- } else {
- // 其他属性
- const input = document.createElement('input');
- input.className = 'property-input';
- input.type = 'text';
- input.value = attr.value;
- input.dataset.path = `ServicesList/Service[${index}]@${attr.name}`;
- input.addEventListener('change', () => {
- this.markEdited();
- });
-
- propertyItem.appendChild(label);
- propertyItem.appendChild(input);
- propertiesContainer.appendChild(propertyItem);
- }
- });
-
- // 只有当有其他属性时才添加属性组
- if (propertiesContainer.children.length > 0) {
- // 添加一个标题来分隔基本属性和其他属性
- const otherPropsTitle = document.createElement('div');
- otherPropsTitle.textContent = '其他属性';
- otherPropsTitle.style.fontWeight = 'bold';
- otherPropsTitle.style.fontSize = '0.9em';
- otherPropsTitle.style.margin = '8px 0';
- serviceItem.appendChild(otherPropsTitle);
-
- serviceItem.appendChild(propertiesContainer);
- }
-
- // 清除处理标记
- Array.from(service.attributes).forEach(attr => {
- if (attr.name === 'Name_processed' || attr.name === 'ClassName_processed') {
- service.removeAttribute(attr.name);
- }
- });
-
- serviceItem.appendChild(propertiesContainer);
- section.appendChild(serviceItem);
- });
- }
-
- // 添加新服务按钮
- const addButton = document.createElement('button');
- addButton.className = 'add-button';
- addButton.style.marginTop = '16px';
- addButton.textContent = '添加服务';
- addButton.title = '添加新的服务';
- addButton.addEventListener('click', () => this.showAddServiceDialog());
- section.appendChild(addButton);
- }
-
- container.appendChild(section);
- }
-
- // 标记编辑状态
- markEdited() {
- if (!this.isEdited) {
- this.isEdited = true;
-
- // 更新保存按钮样式
- const saveButton = this.shadowRoot.getElementById('saveConfig');
- if (saveButton) {
- saveButton.classList.add('modified');
- saveButton.title = '文件已修改,请保存';
- }
- }
- }
-
- // 重置编辑状态
- resetEditState() {
- this.isEdited = false;
-
- // 更新保存按钮样式
- const saveButton = this.shadowRoot.getElementById('saveConfig');
- if (saveButton) {
- saveButton.classList.remove('modified');
- saveButton.title = '';
- }
- }
-
- // 渲染Console输出和日志部分
- renderConsoleAndLogSection(container, rootElement) {
- const section = document.createElement('div');
- section.className = 'editor-section';
-
- const title = document.createElement('div');
- title.className = 'section-title';
- title.textContent = '控制台和日志设置';
- section.appendChild(title);
-
- const propertyGroup = document.createElement('div');
- propertyGroup.className = 'property-group';
-
- // 处理ConsoleOutput元素
- const consoleElement = rootElement.querySelector('ConsoleOutput');
- if (consoleElement) {
- const consoleTitle = document.createElement('div');
- consoleTitle.style.gridColumn = '1 / -1';
- consoleTitle.style.fontWeight = 'bold';
- consoleTitle.textContent = '控制台输出';
- propertyGroup.appendChild(consoleTitle);
-
- Array.from(consoleElement.attributes).forEach(attr => {
- const propertyItem = document.createElement('div');
- propertyItem.className = 'property-item';
- propertyItem.style.display = 'flex';
- propertyItem.style.alignItems = 'center';
-
- const checkboxContainer = document.createElement('div');
- checkboxContainer.style.display = 'flex';
- checkboxContainer.style.alignItems = 'center';
-
- const checkbox = document.createElement('input');
- checkbox.className = 'property-checkbox';
- checkbox.type = 'checkbox';
- checkbox.checked = attr.value === '1';
- checkbox.dataset.path = `ConsoleOutput@${attr.name}`;
- checkbox.id = `console-${attr.name}`;
- checkbox.style.marginRight = '8px';
-
- // 添加提示
- if (attr.name === 'Debug') {
- checkbox.title = '是否输出调试信息';
- } else if (attr.name === 'Info') {
- checkbox.title = '是否输出提示信息';
- } else if (attr.name === 'Error') {
- checkbox.title = '是否输出错误信息';
- } else if (attr.name === 'Warning') {
- checkbox.title = '是否输出警告信息';
- } else {
- checkbox.title = `是否启用${attr.name}`;
- }
-
- checkbox.addEventListener('change', () => {
- // 更新XML数据
- this.updateConsoleOrLogCheckbox(checkbox, 'ConsoleOutput', attr.name);
- this.markEdited();
- });
-
- const label = document.createElement('label');
- label.className = 'property-label';
- label.textContent = attr.name;
- label.htmlFor = `console-${attr.name}`;
- label.style.cursor = 'pointer';
-
- checkboxContainer.appendChild(checkbox);
- checkboxContainer.appendChild(label);
- propertyItem.appendChild(checkboxContainer);
- propertyGroup.appendChild(propertyItem);
- });
- }
-
- // 处理Log元素
- const logElement = rootElement.querySelector('Log');
- if (logElement) {
- const logTitle = document.createElement('div');
- logTitle.style.gridColumn = '1 / -1';
- logTitle.style.fontWeight = 'bold';
- logTitle.style.marginTop = '12px';
- logTitle.textContent = '日志设置';
- propertyGroup.appendChild(logTitle);
-
- Array.from(logElement.attributes).forEach(attr => {
- const propertyItem = document.createElement('div');
- propertyItem.className = 'property-item';
- propertyItem.style.display = 'flex';
- propertyItem.style.alignItems = 'center';
-
- const checkboxContainer = document.createElement('div');
- checkboxContainer.style.display = 'flex';
- checkboxContainer.style.alignItems = 'center';
-
- const checkbox = document.createElement('input');
- checkbox.className = 'property-checkbox';
- checkbox.type = 'checkbox';
- checkbox.checked = attr.value === '1';
- checkbox.dataset.path = `Log@${attr.name}`;
- checkbox.id = `log-${attr.name}`;
- checkbox.style.marginRight = '8px';
-
- // 添加提示
- if (attr.name === 'Debug') {
- checkbox.title = '是否记录调试信息';
- } else if (attr.name === 'Info') {
- checkbox.title = '是否记录提示信息';
- } else if (attr.name === 'Error') {
- checkbox.title = '是否记录错误信息';
- } else if (attr.name === 'Warning') {
- checkbox.title = '是否记录警告信息';
- } else {
- checkbox.title = `是否启用${attr.name}日志`;
- }
-
- checkbox.addEventListener('change', () => {
- // 更新XML数据
- this.updateConsoleOrLogCheckbox(checkbox, 'Log', attr.name);
- this.markEdited();
- });
-
- const label = document.createElement('label');
- label.className = 'property-label';
- label.textContent = attr.name;
- label.htmlFor = `log-${attr.name}`;
- label.style.cursor = 'pointer';
-
- checkboxContainer.appendChild(checkbox);
- checkboxContainer.appendChild(label);
- propertyItem.appendChild(checkboxContainer);
- propertyGroup.appendChild(propertyItem);
- });
- }
-
- section.appendChild(propertyGroup);
- container.appendChild(section);
- }
-
- // 更新控制台或日志复选框值到XML
- updateConsoleOrLogCheckbox(checkbox, elementName, attrName) {
- const parser = new DOMParser();
- const xmlDoc = parser.parseFromString(this.xmlContent, 'text/xml');
- const element = xmlDoc.querySelector(elementName);
-
- if (element) {
- // 设置属性值为0或1
- element.setAttribute(attrName, checkbox.checked ? '1' : '0');
-
- // 更新XML内容
- const serializer = new XMLSerializer();
- this.xmlContent = serializer.serializeToString(xmlDoc);
-
- this.markEdited();
- }
- }
-
- // 显示添加模型组对话框
- showAddModelGroupDialog() {
- // 创建表单内容
- const formContent = document.createElement('div');
- formContent.className = 'modal-form';
-
- // 获取可用的CPU核心选项
- const availableCores = this.updateCPUAffinityOptions();
-
- // 常用属性输入字段
- const nameRow = document.createElement('div');
- nameRow.className = 'form-row';
-
- const nameLabel = document.createElement('label');
- nameLabel.className = 'form-label';
- nameLabel.textContent = '名称';
-
- const nameInput = document.createElement('input');
- nameInput.className = 'form-input';
- nameInput.name = 'Name';
- nameInput.type = 'text';
- nameInput.value = '新模型组';
-
- nameRow.appendChild(nameLabel);
- nameRow.appendChild(nameInput);
- formContent.appendChild(nameRow);
-
- // FreqGroup输入字段
- const freqGroupRow = document.createElement('div');
- freqGroupRow.className = 'form-row';
-
- const freqGroupLabel = document.createElement('label');
- freqGroupLabel.className = 'form-label';
- freqGroupLabel.textContent = '频率组';
-
- const freqGroupInput = document.createElement('input');
- freqGroupInput.className = 'form-input';
- freqGroupInput.name = 'FreqGroup';
- freqGroupInput.type = 'number';
- freqGroupInput.min = '0';
- freqGroupInput.max = '6';
- freqGroupInput.value = '0';
- freqGroupInput.title = '频率组,取值范围0-6';
-
- freqGroupRow.appendChild(freqGroupLabel);
- freqGroupRow.appendChild(freqGroupInput);
- formContent.appendChild(freqGroupRow);
-
- // Priority输入字段
- const priorityRow = document.createElement('div');
- priorityRow.className = 'form-row';
-
- const priorityLabel = document.createElement('label');
- priorityLabel.className = 'form-label';
- priorityLabel.textContent = '优先级';
-
- const priorityInput = document.createElement('input');
- priorityInput.className = 'form-input';
- priorityInput.name = 'Priority';
- priorityInput.type = 'number';
- priorityInput.min = '0';
- priorityInput.max = '99';
- priorityInput.value = '99';
- priorityInput.title = '线程优先级,取值范围0-99';
-
- priorityRow.appendChild(priorityLabel);
- priorityRow.appendChild(priorityInput);
- formContent.appendChild(priorityRow);
-
- // CPUAff下拉字段
- const cpuAffRow = document.createElement('div');
- cpuAffRow.className = 'form-row';
-
- const cpuAffLabel = document.createElement('label');
- cpuAffLabel.className = 'form-label';
- cpuAffLabel.textContent = 'CPU亲和性';
-
- const cpuAffSelect = document.createElement('select');
- cpuAffSelect.className = 'form-input';
- cpuAffSelect.name = 'CPUAff';
- cpuAffSelect.title = '选择一个可用的CPU核心';
-
- // 添加可用的CPU核心选项
- if (availableCores.length > 0) {
- availableCores.forEach(core => {
- const option = document.createElement('option');
- option.value = core;
- option.textContent = `CPU ${core}`;
- cpuAffSelect.appendChild(option);
- });
- } else {
- // 如果没有可用选项,添加一个默认选项
- const option = document.createElement('option');
- option.value = '0';
- option.textContent = `CPU 0`;
- cpuAffSelect.appendChild(option);
- }
-
- cpuAffRow.appendChild(cpuAffLabel);
- cpuAffRow.appendChild(cpuAffSelect);
- formContent.appendChild(cpuAffRow);
-
- // 显示对话框
- this.createModal('添加新模型组', formContent, () => {
- const props = {
- Name: nameInput.value,
- FreqGroup: freqGroupInput.value,
- Priority: priorityInput.value,
- CPUAff: cpuAffSelect.value
- };
-
- this.addModelGroup(props);
- });
- }
-
- // 显示添加模型对话框
- showAddModelDialog(groupIndex) {
- // 创建表单内容
- const formContent = document.createElement('div');
- formContent.className = 'modal-form';
-
- // 创建一个行容器来放置Name和ClassName
- const rowContainer = document.createElement('div');
- rowContainer.style.display = 'flex';
- rowContainer.style.width = '100%';
- rowContainer.style.gap = '10px';
- rowContainer.style.marginBottom = '10px';
-
- // 名称部分
- const nameGroup = document.createElement('div');
- nameGroup.style.display = 'flex';
- nameGroup.style.flexDirection = 'column';
- nameGroup.style.flex = '1';
-
- const nameLabel = document.createElement('label');
- nameLabel.className = 'form-label';
- nameLabel.textContent = '名称';
- nameLabel.style.marginBottom = '5px';
-
- const nameInput = document.createElement('input');
- nameInput.className = 'form-input';
- nameInput.name = 'Name';
- nameInput.type = 'text';
- nameInput.value = '新模型';
-
- nameGroup.appendChild(nameLabel);
- nameGroup.appendChild(nameInput);
-
- // 类名部分
- const classGroup = document.createElement('div');
- classGroup.style.display = 'flex';
- classGroup.style.flexDirection = 'column';
- classGroup.style.flex = '1';
-
- const classLabel = document.createElement('label');
- classLabel.className = 'form-label';
- classLabel.textContent = '类名';
- classLabel.style.marginBottom = '5px';
-
- const classInput = document.createElement('input');
- classInput.className = 'form-input';
- classInput.name = 'ClassName';
- classInput.type = 'text';
- classInput.value = 'XNModel';
-
- classGroup.appendChild(classLabel);
- classGroup.appendChild(classInput);
-
- // 将两个组添加到容器中
- rowContainer.appendChild(nameGroup);
- rowContainer.appendChild(classGroup);
-
- // 将容器添加到表单中
- formContent.appendChild(rowContainer);
-
- // 显示对话框
- this.createModal('添加新模型', formContent, () => {
- const props = {};
- formContent.querySelectorAll('.form-input').forEach(input => {
- props[input.name] = input.value;
- });
-
- this.addModel(groupIndex, props);
- });
- }
-
- // 显示添加服务对话框
- showAddServiceDialog() {
- // 创建表单内容
- const formContent = document.createElement('div');
- formContent.className = 'modal-form';
-
- // 创建一个行容器来放置Name和ClassName
- const rowContainer = document.createElement('div');
- rowContainer.style.display = 'flex';
- rowContainer.style.width = '100%';
- rowContainer.style.gap = '10px';
- rowContainer.style.marginBottom = '10px';
-
- // 名称部分
- const nameGroup = document.createElement('div');
- nameGroup.style.display = 'flex';
- nameGroup.style.flexDirection = 'column';
- nameGroup.style.flex = '1';
-
- const nameLabel = document.createElement('label');
- nameLabel.className = 'form-label';
- nameLabel.textContent = '名称';
- nameLabel.style.marginBottom = '5px';
-
- const nameInput = document.createElement('input');
- nameInput.className = 'form-input';
- nameInput.name = 'Name';
- nameInput.type = 'text';
- nameInput.value = '新服务';
-
- nameGroup.appendChild(nameLabel);
- nameGroup.appendChild(nameInput);
-
- // 类名部分
- const classGroup = document.createElement('div');
- classGroup.style.display = 'flex';
- classGroup.style.flexDirection = 'column';
- classGroup.style.flex = '1';
-
- const classLabel = document.createElement('label');
- classLabel.className = 'form-label';
- classLabel.textContent = '类名';
- classLabel.style.marginBottom = '5px';
-
- const classInput = document.createElement('input');
- classInput.className = 'form-input';
- classInput.name = 'ClassName';
- classInput.type = 'text';
- classInput.value = 'XNService';
-
- classGroup.appendChild(classLabel);
- classGroup.appendChild(classInput);
-
- // 将两个组添加到容器中
- rowContainer.appendChild(nameGroup);
- rowContainer.appendChild(classGroup);
-
- // 将容器添加到表单中
- formContent.appendChild(rowContainer);
-
- // 显示对话框
- this.createModal('添加新服务', formContent, () => {
- const props = {};
- formContent.querySelectorAll('.form-input').forEach(input => {
- props[input.name] = input.value;
- });
-
- this.addService(props);
- });
- }
-
- // 格式化XML字符串
- formatXml(xml) {
- if (!xml || !xml.trim()) return '';
-
- try {
- let formatted = '';
- const parser = new DOMParser();
- const doc = parser.parseFromString(xml, 'text/xml');
-
- // 检查是否解析错误
- const parseError = doc.querySelector('parsererror');
- if (parseError) {
- console.warn('XML解析错误,返回原始文本');
- return xml; // 如果解析错误,返回原始文本
- }
-
- // 使用XMLSerializer序列化为字符串
- const serializer = new XMLSerializer();
- formatted = serializer.serializeToString(doc);
-
- // 简单格式化:替换'><'为'>\n<'添加换行
- formatted = formatted.replace(/><(?!\/)/g, '>\n<');
-
- // 添加缩进
- const lines = formatted.split('\n');
- let indent = 0;
- formatted = lines.map(line => {
- if (line.match(/<\/[^>]+>/)) {
- // 关闭标签,减少缩进
- indent--;
- }
-
- const result = ' '.repeat(Math.max(0, indent * 2)) + line;
-
- if (line.match(/<[^\/][^>]*[^\/]>/) && !line.match(/<.*\/>/) && !line.match(/<[^>]+><\/[^>]+>/)) {
- // 开放标签,增加缩进
- indent++;
- }
-
- return result;
- }).join('\n');
-
- return formatted;
- } catch (e) {
- console.error('XML格式化失败:', e);
- return xml;
- }
- }
-
- // 转义HTML字符
- escapeHtml(unsafe) {
- return unsafe
- .replace(/&/g, "&")
- .replace(//g, ">")
- .replace(/"/g, """)
- .replace(/'/g, "'");
- }
-
- render() {
- this.shadowRoot.innerHTML = `
-
-
- 无法编辑:XML文档的根元素不是Service。
- 请确保XML文档的根元素是Service。
-
`;
- }
-
- container.appendChild(style);
- container.appendChild(visualEditor);
- }
-
- // 显示日期时间选择对话框
- showDateTimeDialog(inputElement) {
- // 解析当前日期和时间
- let currentDate = new Date();
- let currentTime = '00:00:00';
-
- if (inputElement.value) {
- try {
- const parts = inputElement.value.split(' ');
- if (parts.length >= 1) {
- const dateParts = parts[0].split('-');
- if (dateParts.length === 3) {
- const year = parseInt(dateParts[0]);
- const month = parseInt(dateParts[1]) - 1; // 月份从0开始
- const day = parseInt(dateParts[2]);
- currentDate = new Date(year, month, day);
- }
- }
-
- if (parts.length >= 2) {
- currentTime = parts[1];
- }
- } catch (error) {
- console.error('解析日期时间失败:', error);
- currentDate = new Date();
- }
- }
-
- // 创建模态框
- const modal = document.createElement('div');
- modal.className = 'modal';
- modal.id = 'dateTimeModal';
-
- // 获取年、月、日
- const year = currentDate.getFullYear();
- const month = currentDate.getMonth(); // 0-11
- const day = currentDate.getDate();
-
- // 生成日历
- const daysInMonth = new Date(year, month + 1, 0).getDate();
- const firstDay = new Date(year, month, 1).getDay(); // 0-6,0表示周日
-
- // 生成月份选项
- let monthOptions = '';
- const monthNames = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
- monthNames.forEach((name, idx) => {
- monthOptions += `
-
${fieldItem ? '编辑字段' : '添加新字段'}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `;
-
- this.shadowRoot.appendChild(dialog);
-
- // 数组维度选择事件
- this.shadowRoot.getElementById('array-dimension').addEventListener('change', (e) => {
- const dimension = parseInt(e.target.value);
-
- // 显示/隐藏数组大小输入框
- for (let i = 1; i <= 2; i++) {
- const row = this.shadowRoot.getElementById(`array-size-row-${i}`);
- if (row) {
- if (i <= dimension) {
- row.classList.remove('hidden');
+ });
+
+ // 下载模板事件
+ toolbar.addEventListener('download-template', async () => {
+ try {
+ const response = await fetch('/api/interface/template');
+ if (!response.ok) {
+ throw new Error('下载模板失败');
+ }
+
+ const blob = await response.blob();
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = '接口变量模板.xlsx';
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ window.URL.revokeObjectURL(url);
+ } catch (error) {
+ console.error('下载模板时出错:', error);
+ alert('下载模板失败');
+ }
+ });
+
+ // 导入数据事件
+ toolbar.addEventListener('import-data', () => {
+ const input = document.createElement('input');
+ input.type = 'file';
+ input.accept = '.xlsx,.xls';
+ input.onchange = async (e) => {
+ const file = e.target.files[0];
+ if (!file) return;
+
+ const formData = new FormData();
+ formData.append('file', file);
+
+ try {
+ const response = await fetch('/api/interface/import', {
+ method: 'POST',
+ body: formData
+ });
+
+ if (!response.ok) {
+ throw new Error('导入失败');
+ }
+
+ const result = await response.json();
+ if (result.success) {
+ await this.loadData();
+ alert(`导入完成,成功: ${result.results.filter(r => r.success).length}, 失败: ${result.results.filter(r => !r.success).length}`);
} else {
- row.classList.add('hidden');
+ throw new Error(result.error || '导入失败');
}
+ } catch (error) {
+ console.error('导入数据时出错:', error);
+ alert('导入数据失败');
}
+ };
+ input.click();
+ });
+
+ // 表格编辑按钮事件
+ dataTable.addEventListener('edit', (e) => {
+ const { SystemName, ProductName, ATAName, ModelStructName, InterfaceName } = e.detail;
+ const interfaceData = this.data.find(item =>
+ item.SystemName === SystemName &&
+ item.ProductName === ProductName &&
+ item.ATAName === ATAName &&
+ item.ModelStructName === ModelStructName &&
+ item.InterfaceName === InterfaceName
+ );
+ if (interfaceData) {
+ variableForm.setMode('edit', interfaceData);
+ variableForm.show();
}
});
-
- // 对话框取消事件
- this.shadowRoot.getElementById('dialog-cancel').addEventListener('click', () => {
- dialog.remove();
+
+ // 表格删除按钮事件
+ dataTable.addEventListener('delete', async (e) => {
+ const { SystemName, ProductName, ATAName, ModelStructName, InterfaceName } = e.detail;
+ if (!confirm('确定要删除这个接口吗?')) {
+ return;
+ }
+
+ try {
+ const response = await fetch(`/api/interface/delete?systemName=${SystemName}&productName=${ProductName}&ataName=${ATAName}&modelStructName=${ModelStructName}&interfaceName=${InterfaceName}`, {
+ method: 'DELETE'
+ });
+
+ if (!response.ok) {
+ throw new Error('删除失败');
+ }
+
+ await this.loadData();
+ alert('删除成功');
+ } catch (error) {
+ console.error('删除接口时出错:', error);
+ alert('删除接口失败');
+ }
});
-
- // 对话框保存事件
- this.shadowRoot.getElementById('dialog-save').addEventListener('click', () => {
- // 获取字段信息
- const isOptional = this.shadowRoot.getElementById('field-optional').checked;
- const fieldAnnotation = isOptional ? '@optional' : '';
- const fieldType = this.shadowRoot.getElementById('field-type').value;
- const fieldName = this.shadowRoot.getElementById('field-name').value.trim();
- const arrayDimension = parseInt(this.shadowRoot.getElementById('array-dimension').value);
-
- // 构建数组表示
- let fieldArray = '';
- if (arrayDimension > 0) {
- for (let i = 1; i <= arrayDimension; i++) {
- const size = this.shadowRoot.getElementById(`array-size-${i}`).value.trim();
- fieldArray += `[${size}]`;
+
+ // 表单保存成功事件
+ variableForm.addEventListener('save-success', async (e) => {
+ const interfaceData = e.detail;
+ try {
+ const url = interfaceData.mode === 'add' ? '/api/interface/add' : '/api/interface/update';
+ const method = interfaceData.mode === 'add' ? 'POST' : 'PUT';
+
+ const response = await fetch(url, {
+ method,
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(interfaceData)
+ });
+
+ if (!response.ok) {
+ throw new Error('保存失败');
}
+
+ await this.loadData();
+ alert('保存成功');
+ } catch (error) {
+ console.error('保存接口时出错:', error);
+ alert('保存接口失败');
}
-
- if (fieldName) {
- const fieldContent = `
-