From 6b2158c26e323fb0f74e4059ec3a999e46a571a6 Mon Sep 17 00:00:00 2001 From: jinchao <383321154@qq.com> Date: Wed, 28 May 2025 10:01:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=BC=80=E5=8F=91=E5=92=8C?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=BC=80=E5=8F=91=E9=A1=B5=E9=9D=A2=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Release/database/XNSim.db | Bin 1224704 -> 1224704 bytes XNSimHtml/components/model-development.js | 321 +++++++++++++++++--- XNSimHtml/components/service-development.js | 305 +++++++++++++++++-- XNSimHtml/routes/model-dev.js | 22 +- XNSimHtml/routes/service-dev.js | 17 ++ XNSimHtml/utils/model-utils.js | 105 +++---- XNSimHtml/utils/service-utils.js | 16 +- 7 files changed, 644 insertions(+), 142 deletions(-) diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db index f160d209e3cebf8d3c9c03e62e923e0d4e79570a..8604d96119e57ffcf7009661482cbd456e34e06a 100644 GIT binary patch delta 1114 zcmZuvZA@EL7`|V<{kZM9El?^}V=qdUrBLo|so5G0EMsm#!-rTy#Hj>`nURqpE;2&k zc4brsbn_N&95C9A6@D<*?MlihY*}LT?~L(>aVW-~+t$UP|BQ>#QySe5{qekc&v~Es zc|Xn>*=ZQrX}Dmw3}6`U#4xNLp%g*6Sn1IWV6M~WZ+6Yq0u8#t*+V9F3 z$Oq3DkmW#J(l*ypAOYeE=Xev8=t&zcxZEy*`^V!Q%EntSa~hV#SQe4K0Mh-b^2z{% z8!I^bq2ghWNAz3T8vXUnt=)a6Pjq(s>&26ggBH;)?Mz*I?)YH&E4`f^?>G1M^_M$* z4#DlI@m4y@U+d_5x4ZvX?+55s+78=shw^(^U#H-8f3ZvWeZ6_cLDCBS>mN|!PDX5eU4|y$;;lX>9+gIb3K6>y2qM=p3`rl%h(zE>n zUivy-Vs+Z}&cnq*L4p|?^kT}L?_aVcsdw-{7xrn|FhDW{dk?IDLC^rom=Z%)+o|10 zKO`B`x0I5`-QFtR zTjf3=@IIdR3B0--gO|_4%@G*B2tS!n=O*EJtZ>Z5)^hV#)Y;F}nS|g{BRA9uQJok| zrxsyI&c>E=qm!AfRfF4ANGcH0TX!>&<%ZU#MtEHw&aA}K>$eKT+?9E_I0M50bvp6W zNT8#u=fp{|$C2+(2n_D^$3O0mKj`y5?{j{g!VaivpJg^|f zCY~xB)v0SRe06toLXF%`uWw{h3+eTdOyuUjikZlQ8oH1dsd2&NEme-H$}}9^gsZnz yc`5U8D4)9$%f?0It8*(boPIPRz-H3xGMbvDHdG`N@en0r^EGN>&PnM#d(lK$Rhh zMd_&}9{I&3N|W#OOK<+s&*{JmbQd%C7Y4o+yy4tmHY*A|;}&a5U=|kDmFCoR6*e|D z=HOs#l&r5cozCXNn8jjhWneZv(T7oZdbn7QBFW8gW)!AONhOw;#I#-{S zosI2LlS?Dp_T{WhE{sAz|8N5_2-r8Wvxx`mPJhVBs5rfol}T#*Yc{5>EbO+83~b_o z+S42Pm=vb*F-dUqx0uzli)(8$b|_C5V`frjaIZumrP;0hyxhDF!S+%nHP8K+F!r u96-#uJ;i`)!T#+m23-I7Tba3AnR!~7d0UzJTA6`dfmUY0t;|Ay*8>2)HKEf0 diff --git a/XNSimHtml/components/model-development.js b/XNSimHtml/components/model-development.js index de2c705..cb35238 100644 --- a/XNSimHtml/components/model-development.js +++ b/XNSimHtml/components/model-development.js @@ -393,9 +393,15 @@ class ModelDevelopment extends HTMLElement { async fetchModels(chapterId) { try { - const headerTools = document.querySelector('header-tools'); - const productName = headerTools.selectedProduct; - const response = await fetch(`/api/chapter-models/${chapterId}?productName=${encodeURIComponent(productName)}`); + const savedSelection = localStorage.getItem('xnsim-selection'); + const selection = savedSelection ? JSON.parse(savedSelection) : {}; + const plane = selection.plane; + + if (!plane) { + throw new Error('请先选择机型!'); + } + + const response = await fetch(`/api/chapter-models/${chapterId}?planeName=${encodeURIComponent(plane)}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); @@ -412,10 +418,19 @@ class ModelDevelopment extends HTMLElement { async fetchModelVersions(className, modelName) { try { - const headerTools = document.querySelector('header-tools'); - const productName = headerTools.selectedProduct; + const savedSelection = localStorage.getItem('xnsim-selection'); + const selection = savedSelection ? JSON.parse(savedSelection) : {}; + const plane = selection.plane; + const confID = selection.configurationId; - const response = await fetch(`/api/model-versions/${encodeURIComponent(className)}?productName=${encodeURIComponent(productName)}`); + if (!plane) { + throw new Error('请先选择机型!'); + } + if (!confID) { + throw new Error('请先选择构型!'); + } + + const response = await fetch(`/api/model-versions/${encodeURIComponent(className)}?planeName=${encodeURIComponent(plane)}&confID=${encodeURIComponent(confID)}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -430,10 +445,6 @@ class ModelDevelopment extends HTMLElement { async saveModelVersion(versionData) { try { - const headerTools = document.querySelector('header-tools'); - const productName = headerTools.selectedProduct; - versionData.ProductName = productName; - const response = await fetch('/api/model-versions', { method: 'POST', headers: { @@ -443,7 +454,8 @@ class ModelDevelopment extends HTMLElement { }); if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + const errorData = await response.json(); + throw new Error(errorData.error || `HTTP error! status: ${response.status}`); } return await response.json(); @@ -664,6 +676,24 @@ class ModelDevelopment extends HTMLElement { showVersionEditor(versionData) { this.currentView = 'versionEditor'; + // 确保 CmdList 是数组 + if (versionData.CmdList) { + try { + // 如果 CmdList 是字符串,尝试解析它 + if (typeof versionData.CmdList === 'string') { + versionData.CmdList = JSON.parse(versionData.CmdList); + } + // 确保 CmdList 是数组 + if (!Array.isArray(versionData.CmdList)) { + versionData.CmdList = []; + } + } catch (e) { + console.error('解析 CmdList 失败:', e); + versionData.CmdList = []; + } + } else { + versionData.CmdList = []; + } this.currentVersion = versionData; this.isEditMode = versionData && versionData.Version ? true : false; @@ -803,6 +833,16 @@ class ModelDevelopment extends HTMLElement { + `; + + // 右列 - 描述和其他信息 + const rightColumn = document.createElement('div'); + rightColumn.className = 'form-column'; + rightColumn.innerHTML = ` +
+ + +
@@ -823,16 +863,6 @@ class ModelDevelopment extends HTMLElement {
`; - // 右列 - 描述和其他信息 - const rightColumn = document.createElement('div'); - rightColumn.className = 'form-column'; - rightColumn.innerHTML = ` -
- - -
- `; - basicInfoSection.appendChild(leftColumn); basicInfoSection.appendChild(rightColumn); @@ -917,21 +947,73 @@ class ModelDevelopment extends HTMLElement { advancedSection.appendChild(gridLayout); advancedSection.appendChild(bottomRow); + // 添加指令列表参数表格 + const cmdListSection = document.createElement('div'); + cmdListSection.className = 'form-section cmd-list'; + cmdListSection.style.cssText = 'border-top: 1px solid #e2e8f0; padding-top: 20px; margin-top: 20px;'; + + // 创建表格标题和工具栏 + const cmdListHeader = document.createElement('div'); + cmdListHeader.style.cssText = 'display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;'; + cmdListHeader.innerHTML = ` + + + `; + + // 创建表格 + const cmdListTable = document.createElement('table'); + cmdListTable.style.cssText = 'width: 100%; border-collapse: collapse; margin-top: 10px;'; + cmdListTable.innerHTML = ` + + + 名称 + 描述 + 调用函数 + 操作 + + + + ${this.renderCmdListRows()} + + `; + + cmdListSection.appendChild(cmdListHeader); + cmdListSection.appendChild(cmdListTable); + // 表单操作按钮 const formActions = document.createElement('div'); formActions.className = 'form-actions'; formActions.style.cssText = 'margin-top: 30px; text-align: right; border-top: 1px solid #e2e8f0; padding-top: 20px;'; - formActions.innerHTML = ` - - `; // 组装表单 form.appendChild(basicInfoSection); form.appendChild(advancedSection); + form.appendChild(cmdListSection); form.appendChild(formActions); formContainer.appendChild(form); container.appendChild(formContainer); + // 为添加指令按钮添加事件监听器 + setTimeout(() => { + const addCmdBtn = this.shadowRoot.querySelector('#addCmdBtn'); + if (addCmdBtn) { + addCmdBtn.addEventListener('click', () => { + this.addCmdListRow(); + }); + } + + // 为删除按钮添加事件监听器 + const deleteButtons = this.shadowRoot.querySelectorAll('.delete-cmd-btn'); + deleteButtons.forEach(button => { + button.addEventListener('click', (e) => { + const index = parseInt(e.target.dataset.index); + this.deleteCmdListRow(index); + }); + }); + }, 0); + // 为日期时间按钮添加事件监听器 setTimeout(() => { const dateTimePickerButton = this.shadowRoot.querySelector('#dateTimePickerButton'); @@ -960,11 +1042,16 @@ class ModelDevelopment extends HTMLElement { e.preventDefault(); try { - // 显示加载提示 - const saveButton = form.querySelector('.save-button'); - const originalButtonText = saveButton.textContent; - saveButton.textContent = '保存中...'; - saveButton.disabled = true; + const savedSelection = localStorage.getItem('xnsim-selection'); + const selection = savedSelection ? JSON.parse(savedSelection) : {}; + + // 获取工具栏中的保存按钮 + const saveButton = this.shadowRoot.querySelector('.toolbar-button:nth-child(2)'); + if (saveButton) { + const originalButtonText = saveButton.textContent; + saveButton.textContent = '保存中...'; + saveButton.disabled = true; + } // 验证版本号格式 const versionInput = form.querySelector('#version'); @@ -981,8 +1068,29 @@ class ModelDevelopment extends HTMLElement { } } + // 收集指令列表数据 + const cmdList = []; + const cmdRows = this.shadowRoot.querySelectorAll('#cmdListBody tr'); + cmdRows.forEach(row => { + const nameInput = row.querySelector('input[name^="cmdList"][name$=".Name"]'); + const descriptionInput = row.querySelector('input[name^="cmdList"][name$=".Description"]'); + const callInput = row.querySelector('input[name^="cmdList"][name$=".Call"]'); + + if (nameInput && descriptionInput && callInput) { + // 确保每个字段都有值,如果没有则使用空字符串 + const cmd = { + "Name" : nameInput.value.trim() || "", + "Description" : descriptionInput.value.trim() || "", + "Call" : callInput.value.trim() || "" + }; + cmdList.push(cmd); + } + }); + // 构建版本数据 const versionData = { + PlaneName: selection.plane, + ConfID: selection.configurationId, ClassName: form.querySelector('#className').value, Name: form.querySelector('#name').value, Version: form.querySelector('#version').value, @@ -997,12 +1105,13 @@ class ModelDevelopment extends HTMLElement { DataPackageHeaderPath: form.querySelector('#dataPackageHeaderPath').value, DataPackageEntryPoint: form.querySelector('#dataPackageEntryPoint').value, DataPackageInterfaceName: form.querySelector('#dataPackageInterfaceName').value, + CmdList: JSON.stringify(cmdList), isUpdate: this.isEditMode, originalVersion: this.isEditMode ? this.currentVersion.Version : null }; // 验证必填字段 - const requiredFields = ['ClassName', 'Name', 'Version', 'Author', 'ChangeTime']; + const requiredFields = ['PlaneName', 'ConfID', 'ClassName', 'Name', 'Version', 'Author', 'ChangeTime']; for (const field of requiredFields) { if (!versionData[field]) { throw new Error(`${field}是必填字段`); @@ -1021,7 +1130,7 @@ class ModelDevelopment extends HTMLElement { alert(`保存失败: ${error.message}`); } finally { // 恢复按钮状态 - const saveButton = form.querySelector('.save-button'); + const saveButton = this.shadowRoot.querySelector('.toolbar-button:nth-child(2)'); if (saveButton) { saveButton.textContent = this.isEditMode ? '保存修改' : '创建版本'; saveButton.disabled = false; @@ -1794,7 +1903,8 @@ class ModelDevelopment extends HTMLElement { DataPackagePath: '', DataPackageHeaderPath: '', DataPackageEntryPoint: '', - DataPackageInterfaceName: '' + DataPackageInterfaceName: '', + CmdList: [] // 初始化为空数组 }; // 打开编辑界面 @@ -1861,25 +1971,142 @@ class ModelDevelopment extends HTMLElement { return `${date} ${time}`; } - saveVersionChanges(form) { - // 收集表单数据 - const formData = new FormData(form); - const updatedVersion = {}; - - for (const [key, value] of formData.entries()) { - updatedVersion[key] = value; + /** + * 渲染指令列表行 + * @returns {string} 表格行的HTML字符串 + */ + renderCmdListRows() { + if (!this.currentVersion.CmdList || !Array.isArray(this.currentVersion.CmdList) || this.currentVersion.CmdList.length === 0) { + return '暂无指令参数'; } - // 确保重要字段值不变 - updatedVersion.ClassName = this.currentVersion.ClassName; + return this.currentVersion.CmdList.map((cmd, index) => ` + + + + + + + + + + + + + + + `).join(''); + } + + /** + * 添加新的指令行 + */ + addCmdListRow() { + if (!this.currentVersion.CmdList) { + this.currentVersion.CmdList = []; + } - // 在这里可以添加保存逻辑,例如调用API - console.log('要保存的版本数据:', updatedVersion); + this.currentVersion.CmdList.push({ + Name: '', + Description: '', + Call: '' + }); - // 提示用户 - alert('版本数据保存功能正在开发中...'); - - // 保存成功后不再自动返回版本列表,留在当前编辑页面 + // 更新表格内容 + const tbody = this.shadowRoot.querySelector('#cmdListBody'); + if (tbody) { + // 如果当前显示的是"暂无指令参数"的提示,则清空表格 + if (tbody.children.length === 1 && tbody.children[0].children.length === 1) { + tbody.innerHTML = ''; + } + + // 创建新的表格行 + const newRow = document.createElement('tr'); + + // 创建指令名称输入框 + const nameCell = document.createElement('td'); + nameCell.style.cssText = 'padding: 8px; border: 1px solid #e2e8f0;'; + const nameInput = document.createElement('input'); + nameInput.type = 'text'; + nameInput.className = 'cmd-name'; + nameInput.style.cssText = 'width: 100%; border: none; padding: 4px;'; + nameCell.appendChild(nameInput); + + // 创建描述输入框 + const descCell = document.createElement('td'); + descCell.style.cssText = 'padding: 8px; border: 1px solid #e2e8f0;'; + const descInput = document.createElement('input'); + descInput.type = 'text'; + descInput.className = 'cmd-description'; + descInput.style.cssText = 'width: 100%; border: none; padding: 4px;'; + descCell.appendChild(descInput); + + // 创建调用函数输入框 + const callCell = document.createElement('td'); + callCell.style.cssText = 'padding: 8px; border: 1px solid #e2e8f0;'; + const callInput = document.createElement('input'); + callInput.type = 'text'; + callInput.className = 'cmd-call'; + callInput.style.cssText = 'width: 100%; border: none; padding: 4px;'; + callCell.appendChild(callInput); + + // 创建删除按钮 + const actionCell = document.createElement('td'); + actionCell.style.cssText = 'padding: 8px; border: 1px solid #e2e8f0; text-align: center;'; + const deleteButton = document.createElement('button'); + deleteButton.type = 'button'; + deleteButton.className = 'delete-cmd'; + deleteButton.dataset.index = (this.currentVersion.CmdList.length - 1).toString(); + deleteButton.style.cssText = 'background-color: #e53e3e; color: white; border: none; border-radius: 4px; padding: 4px 8px; cursor: pointer;'; + deleteButton.textContent = '删除'; + deleteButton.addEventListener('click', (e) => { + const index = parseInt(e.target.dataset.index); + this.deleteCmdListRow(index); + }); + actionCell.appendChild(deleteButton); + + // 组装行 + newRow.appendChild(nameCell); + newRow.appendChild(descCell); + newRow.appendChild(callCell); + newRow.appendChild(actionCell); + + // 添加到表格 + tbody.appendChild(newRow); + } + } + + /** + * 删除指令行 + * @param {number} index - 要删除的行索引 + */ + deleteCmdListRow(index) { + if (this.currentVersion.CmdList && Array.isArray(this.currentVersion.CmdList)) { + this.currentVersion.CmdList.splice(index, 1); + + // 更新表格内容 + const tbody = this.shadowRoot.querySelector('#cmdListBody'); + if (tbody) { + if (this.currentVersion.CmdList.length === 0) { + // 如果没有指令了,显示提示信息 + tbody.innerHTML = '暂无指令参数'; + } else { + // 重新渲染所有行 + tbody.innerHTML = this.renderCmdListRows(); + + // 重新绑定删除按钮事件 + const deleteButtons = this.shadowRoot.querySelectorAll('.delete-cmd-btn'); + deleteButtons.forEach(button => { + button.addEventListener('click', (e) => { + const index = parseInt(e.target.dataset.index); + this.deleteCmdListRow(index); + }); + }); + } + } + } } } diff --git a/XNSimHtml/components/service-development.js b/XNSimHtml/components/service-development.js index 9c1a528..b66a7cf 100644 --- a/XNSimHtml/components/service-development.js +++ b/XNSimHtml/components/service-development.js @@ -436,6 +436,36 @@ class ServiceDevelopment extends HTMLElement { async saveServiceVersion(versionData) { try { + // 确保 CmdList 和 OtherParam 是有效的 JSON 字符串 + if (versionData.CmdList) { + try { + const cmdList = JSON.parse(versionData.CmdList); + if (!Array.isArray(cmdList)) { + throw new Error('CmdList 必须是数组'); + } + // 验证每个命令对象的格式 + cmdList.forEach(cmd => { + if (!cmd.Name || !cmd.Description || !cmd.Call) { + throw new Error('每个命令必须包含 Name、Description 和 Call 字段'); + } + }); + } catch (e) { + throw new Error(`CmdList 格式错误: ${e.message}`); + } + } else { + versionData.CmdList = '[]'; + } + + if (versionData.OtherParam) { + try { + JSON.parse(versionData.OtherParam); + } catch (e) { + throw new Error(`OtherParam 格式错误: ${e.message}`); + } + } else { + versionData.OtherParam = '{}'; + } + const response = await fetch('/api/service-versions', { method: 'POST', headers: { @@ -725,6 +755,26 @@ class ServiceDevelopment extends HTMLElement { showVersionEditor(versionData) { this.currentView = 'versionEditor'; + + // 确保 CmdList 是有效的数组 + if (versionData.CmdList) { + try { + if (typeof versionData.CmdList === 'string') { + // 如果已经是字符串,尝试解析它 + const parsed = JSON.parse(versionData.CmdList); + versionData.CmdList = Array.isArray(parsed) ? parsed : []; + } else if (!Array.isArray(versionData.CmdList)) { + // 如果不是数组,初始化为空数组 + versionData.CmdList = []; + } + } catch (e) { + console.error('解析 CmdList 失败:', e); + versionData.CmdList = []; + } + } else { + versionData.CmdList = []; + } + this.currentVersion = versionData; this.isEditMode = versionData && versionData.Version ? true : false; @@ -864,6 +914,16 @@ class ServiceDevelopment extends HTMLElement { + `; + + // 右列 - 描述和其他信息 + const rightColumn = document.createElement('div'); + rightColumn.className = 'form-column'; + rightColumn.innerHTML = ` +
+ + +
@@ -884,16 +944,6 @@ class ServiceDevelopment extends HTMLElement {
`; - // 右列 - 描述和其他信息 - const rightColumn = document.createElement('div'); - rightColumn.className = 'form-column'; - rightColumn.innerHTML = ` -
- - -
- `; - basicInfoSection.appendChild(leftColumn); basicInfoSection.appendChild(rightColumn); @@ -910,19 +960,76 @@ class ServiceDevelopment extends HTMLElement { `; codePathSection.appendChild(codePathGroup); + + // 添加 CmdList 和 OtherParam 字段 + const jsonFieldsSection = document.createElement('div'); + jsonFieldsSection.className = 'form-section json-fields'; + jsonFieldsSection.style.cssText = 'margin-top: 20px; border-top: 1px solid #e2e8f0; padding-top: 20px;'; + + // CmdList 字段 + const cmdListGroup = document.createElement('div'); + cmdListGroup.className = 'form-group'; - // 表单操作按钮 - const formActions = document.createElement('div'); - formActions.className = 'form-actions'; - formActions.style.cssText = 'margin-top: 30px; text-align: right; border-top: 1px solid #e2e8f0; padding-top: 20px;'; - formActions.innerHTML = ` - + // 确保 CmdList 是有效的 JSON 字符串 + let cmdListValue = '[]'; + if (this.currentVersion.CmdList) { + try { + if (typeof this.currentVersion.CmdList === 'string') { + // 如果已经是字符串,验证它是否是有效的 JSON + JSON.parse(this.currentVersion.CmdList); + cmdListValue = this.currentVersion.CmdList; + } else if (Array.isArray(this.currentVersion.CmdList)) { + // 如果是数组,转换为 JSON 字符串 + cmdListValue = JSON.stringify(this.currentVersion.CmdList); + } + } catch (e) { + console.error('CmdList 格式错误:', e); + cmdListValue = '[]'; + } + } + + cmdListGroup.innerHTML = ` +
+ + +
+
+ + + + + + + + + + + + + + +
名称描述调用函数操作
暂无指令参数
+
+ `; + jsonFieldsSection.appendChild(cmdListGroup); + + // OtherParam 字段 + const otherParamGroup = document.createElement('div'); + otherParamGroup.className = 'form-group'; + otherParamGroup.innerHTML = ` + + + 请输入有效的JSON字符串,例如: {"key": "value"} + `; + jsonFieldsSection.appendChild(otherParamGroup); // 组装表单 form.appendChild(basicInfoSection); form.appendChild(codePathSection); - form.appendChild(formActions); + form.appendChild(jsonFieldsSection); formContainer.appendChild(form); container.appendChild(formContainer); @@ -943,17 +1050,27 @@ class ServiceDevelopment extends HTMLElement { e.preventDefault(); try { - // 显示加载提示 - const saveButton = form.querySelector('.save-button'); - const originalButtonText = saveButton.textContent; - saveButton.textContent = '保存中...'; - saveButton.disabled = true; - // 验证版本号格式 const versionInput = form.querySelector('#version'); if (versionInput && !/^[0-9.]+$/.test(versionInput.value)) { throw new Error('版本号只能包含数字和小数点'); } + + // 验证 CmdList 和 OtherParam 是否为有效的 JSON + const cmdListInput = form.querySelector('#cmdList'); + const otherParamInput = form.querySelector('#otherParam'); + + try { + JSON.parse(cmdListInput.value); + } catch (e) { + throw new Error('CmdList 必须是有效的 JSON 数组字符串'); + } + + try { + JSON.parse(otherParamInput.value); + } catch (e) { + throw new Error('OtherParam 必须是有效的 JSON 字符串'); + } // 构建版本数据 const versionData = { @@ -964,6 +1081,8 @@ class ServiceDevelopment extends HTMLElement { Description: form.querySelector('#description').value, ChangeTime: form.querySelector('#changeTime').value, CodePath: form.querySelector('#codePath').value, + CmdList: cmdListInput.value, + OtherParam: otherParamInput.value, isUpdate: this.isEditMode, originalVersion: this.isEditMode ? this.currentVersion.Version : null }; @@ -986,15 +1105,137 @@ class ServiceDevelopment extends HTMLElement { this.fetchServiceVersions(this.currentService.className, this.currentService.name); } catch (error) { alert(`保存失败: ${error.message}`); - } finally { - // 恢复按钮状态 - const saveButton = form.querySelector('.save-button'); - if (saveButton) { - saveButton.textContent = this.isEditMode ? '保存修改' : '创建版本'; - saveButton.disabled = false; - } } }); + + // 初始化 CmdList 表格 + const cmdListBody = cmdListGroup.querySelector('#cmdListBody'); + const cmdListInput = cmdListGroup.querySelector('#cmdList'); + const addCmdBtn = cmdListGroup.querySelector('#addCmdBtn'); + + // 渲染 CmdList 表格行 + const renderCmdListRows = () => { + try { + const cmdListInput = cmdListGroup.querySelector('#cmdList'); + if (!cmdListInput) { + console.error('找不到 CmdList 输入元素'); + return; + } + + let cmdList; + try { + // 如果 currentVersion.CmdList 是数组,直接使用它 + if (Array.isArray(this.currentVersion.CmdList)) { + cmdList = this.currentVersion.CmdList; + cmdListInput.value = JSON.stringify(cmdList); + } else { + // 否则尝试解析输入值 + cmdList = JSON.parse(cmdListInput.value); + } + } catch (e) { + console.error('解析 CmdList 失败:', e); + cmdList = []; + cmdListInput.value = '[]'; + } + + if (!Array.isArray(cmdList)) { + console.error('CmdList 不是数组:', cmdList); + cmdList = []; + cmdListInput.value = '[]'; + } + + if (cmdList.length === 0) { + cmdListBody.innerHTML = '暂无指令参数'; + return; + } + + cmdListBody.innerHTML = cmdList.map((cmd, index) => ` + + + + + + + + + + + + + + + `).join(''); + + // 添加删除按钮事件 + cmdListBody.querySelectorAll('.delete-cmd').forEach(btn => { + btn.addEventListener('click', (e) => { + const index = parseInt(e.target.dataset.index); + try { + const cmdList = Array.isArray(this.currentVersion.CmdList) ? + this.currentVersion.CmdList : + JSON.parse(cmdListInput.value); + cmdList.splice(index, 1); + this.currentVersion.CmdList = cmdList; + cmdListInput.value = JSON.stringify(cmdList); + renderCmdListRows(); + } catch (e) { + console.error('删除指令失败:', e); + alert('删除指令失败,请重试'); + } + }); + }); + + // 添加输入框事件 + cmdListBody.querySelectorAll('input').forEach(input => { + input.addEventListener('change', () => { + try { + const cmdList = Array.isArray(this.currentVersion.CmdList) ? + this.currentVersion.CmdList : + JSON.parse(cmdListInput.value); + const row = input.closest('tr'); + const index = Array.from(row.parentNode.children).indexOf(row); + const field = input.classList[0].split('-')[1]; + cmdList[index][field.charAt(0).toUpperCase() + field.slice(1)] = input.value; + this.currentVersion.CmdList = cmdList; + cmdListInput.value = JSON.stringify(cmdList); + } catch (e) { + console.error('更新指令失败:', e); + alert('更新指令失败,请重试'); + } + }); + }); + } catch (e) { + console.error('渲染指令列表失败:', e); + cmdListBody.innerHTML = '指令列表格式错误'; + } + }; + + // 添加指令按钮事件 + addCmdBtn.addEventListener('click', () => { + try { + let cmdList = Array.isArray(this.currentVersion.CmdList) ? + this.currentVersion.CmdList : + JSON.parse(cmdListInput.value); + + // 添加新的指令 + cmdList.push({ Name: '', Description: '', Call: '' }); + + // 更新 currentVersion 和输入框的值 + this.currentVersion.CmdList = cmdList; + cmdListInput.value = JSON.stringify(cmdList); + + // 重新渲染表格 + renderCmdListRows(); + } catch (e) { + console.error('添加指令失败:', e); + alert('添加指令失败,请检查指令列表格式'); + } + }); + + // 初始渲染表格 + renderCmdListRows(); } /** @@ -1289,7 +1530,9 @@ class ServiceDevelopment extends HTMLElement { Description: '', CreatTime: this.getCurrentDateTime(), ChangeTime: this.getCurrentDateTime(), - CodePath: '' + CodePath: '', + CmdList: [], // 初始化为空数组 + OtherParam: '{}' // 初始化为空对象的 JSON 字符串 }; // 打开编辑界面 diff --git a/XNSimHtml/routes/model-dev.js b/XNSimHtml/routes/model-dev.js index f9a810f..d3d051e 100644 --- a/XNSimHtml/routes/model-dev.js +++ b/XNSimHtml/routes/model-dev.js @@ -27,6 +27,9 @@ router.get('/chapter-models/:chapterId', (req, res) => { if (!chapterId) { return res.status(400).json({ error: '缺少章节ID参数' }); } + if (!planeName) { + return res.status(400).json({ error: '缺少飞机名称参数' }); + } const models = getModelsByChapterId(chapterId, planeName); res.json(models); @@ -40,13 +43,19 @@ router.get('/chapter-models/:chapterId', (req, res) => { router.get('/model-versions/:className', (req, res) => { try { const className = req.params.className; - const { planeName } = req.query; + const { planeName, confID } = req.query; if (!className) { return res.status(400).json({ error: '模型类名不能为空' }); } + if (!planeName) { + return res.status(400).json({ error: '飞机名称不能为空' }); + } + if (!confID) { + return res.status(400).json({ error: '配置ID不能为空' }); + } - const versions = getModelVersionsByClassName(className, planeName); + const versions = getModelVersionsByClassName(className, planeName, confID); res.json(versions); } catch (error) { console.error(`获取模型版本失败: ${error.message}`); @@ -71,6 +80,15 @@ router.post('/model-versions', (req, res) => { } } + // 验证 CmdList 是否为有效的 JSON 字符串 + if (versionData.CmdList !== undefined) { + try { + JSON.parse(versionData.CmdList); + } catch (e) { + return res.status(400).json({ error: 'CmdList 必须是有效的 JSON 字符串' }); + } + } + const result = saveModelVersion(versionData); res.json(result); } catch (error) { diff --git a/XNSimHtml/routes/service-dev.js b/XNSimHtml/routes/service-dev.js index 2a8b187..1c5a731 100644 --- a/XNSimHtml/routes/service-dev.js +++ b/XNSimHtml/routes/service-dev.js @@ -58,6 +58,23 @@ router.post('/service-versions', (req, res) => { versionData.ServiceName = versionData.Name; } + // 验证 CmdList 和 OtherParam 是否为有效的 JSON 字符串 + if (versionData.CmdList !== undefined) { + try { + JSON.parse(versionData.CmdList); + } catch (e) { + return res.status(400).json({ error: 'CmdList 必须是有效的 JSON 字符串' }); + } + } + + if (versionData.OtherParam !== undefined) { + try { + JSON.parse(versionData.OtherParam); + } catch (e) { + return res.status(400).json({ error: 'OtherParam 必须是有效的 JSON 字符串' }); + } + } + const result = saveServiceVersion(versionData); res.json(result); } catch (error) { diff --git a/XNSimHtml/utils/model-utils.js b/XNSimHtml/utils/model-utils.js index 266bbbc..ca1f066 100644 --- a/XNSimHtml/utils/model-utils.js +++ b/XNSimHtml/utils/model-utils.js @@ -18,31 +18,24 @@ function getATAChapters() { // 根据章节ID查询XNModels表中的模型 function getModelsByChapterId(chapterId, planeName) { try { + // 验证必填参数 + if (!chapterId) { + throw new Error('ChapterId 是必填参数'); + } + if (!planeName) { + throw new Error('PlaneName 是必填参数'); + } + const db = getDBConnection(true); - // 根据planeName是否为空构建不同的查询 - let query; - let params; + const query = ` + SELECT PlaneName, Chapters_ID, ModelName, ModelName_CN, Description, ClassName + FROM 'XNModels' + WHERE Chapters_ID = ? AND PlaneName = ? + ORDER BY ModelName + `; - if (!planeName || planeName === '' || planeName === 'undefined') { - query = ` - SELECT PlaneName, Chapters_ID, ModelName, ModelName_CN, Description, ClassName - FROM 'XNModels' - WHERE Chapters_ID = ? - ORDER BY ModelName - `; - params = [chapterId]; - } else { - query = ` - SELECT PlaneName, Chapters_ID, ModelName, ModelName_CN, Description, ClassName - FROM 'XNModels' - WHERE Chapters_ID = ? AND PlaneName = ? - ORDER BY ModelName - `; - params = [chapterId, planeName]; - } - - const models = db.prepare(query).all(...params); + const models = db.prepare(query).all(chapterId, planeName); return models; } catch (error) { @@ -52,41 +45,33 @@ function getModelsByChapterId(chapterId, planeName) { } // 根据ClassName查询XNModelsVersion表中的模型版本 -function getModelVersionsByClassName(className, planeName) { +function getModelVersionsByClassName(className, planeName, confID) { try { + // 验证必填参数 + if (!className) { + throw new Error('ClassName 是必填参数'); + } + if (!planeName) { + throw new Error('PlaneName 是必填参数'); + } + if (!confID) { + throw new Error('ConfID 是必填参数'); + } + const db = getDBConnection(true); - // 根据planeName是否为空构建不同的查询 - let query; - let params; + const query = ` + SELECT + PlaneName, ClassName, Name, Version, CodePath, Author, Description, + CreatTime, ChangeTime, RunFreqGroup, RunNode, Priority, + DataPackagePath, DataPackageHeaderPath, DataPackageEntryPoint, DataPackageInterfaceName, + ConfID, CmdList + FROM 'XNModelsVersion' + WHERE ClassName = ? AND PlaneName = ? AND ConfID = ? + ORDER BY Version DESC + `; - if (!planeName || planeName === '') { - query = ` - SELECT - PlaneName, ClassName, Name, Version, CodePath, Author, Description, - CreatTime, ChangeTime, RunFreqGroup, RunNode, Priority, - DataPackagePath, DataPackageHeaderPath, DataPackageEntryPoint, DataPackageInterfaceName, - ConfID - FROM 'XNModelsVersion' - WHERE ClassName = ? - ORDER BY Version DESC - `; - params = [className]; - } else { - query = ` - SELECT - PlaneName, ClassName, Name, Version, CodePath, Author, Description, - CreatTime, ChangeTime, RunFreqGroup, RunNode, Priority, - DataPackagePath, DataPackageHeaderPath, DataPackageEntryPoint, DataPackageInterfaceName, - ConfID - FROM 'XNModelsVersion' - WHERE ClassName = ? AND PlaneName = ? - ORDER BY Version DESC - `; - params = [className, planeName]; - } - - const versions = db.prepare(query).all(...params); + const versions = db.prepare(query).all(className, planeName, confID); return versions; } catch (error) { @@ -155,7 +140,8 @@ function saveModelVersion(versionData) { DataPackageHeaderPath = ?, DataPackageEntryPoint = ?, DataPackageInterfaceName = ?, - ConfID = ? + ConfID = ?, + CmdList = ? WHERE ClassName = ? AND Version = ? AND PlaneName = ? `).run( versionData.PlaneName, @@ -175,6 +161,7 @@ function saveModelVersion(versionData) { versionData.DataPackageEntryPoint || '', versionData.DataPackageInterfaceName || '', versionData.ConfID, + versionData.CmdList || '[]', versionData.ClassName, versionData.originalVersion || versionData.Version, versionData.PlaneName @@ -229,8 +216,8 @@ function saveNewVersion(db, versionData) { PlaneName, ClassName, Name, Version, CodePath, Author, Description, CreatTime, ChangeTime, RunFreqGroup, RunNode, Priority, DataPackagePath, DataPackageHeaderPath, DataPackageEntryPoint, DataPackageInterfaceName, - ConfID - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ConfID, CmdList + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( versionData.PlaneName, versionData.ClassName, @@ -248,7 +235,11 @@ function saveNewVersion(db, versionData) { versionData.DataPackageHeaderPath || '', versionData.DataPackageEntryPoint || '', versionData.DataPackageInterfaceName || '', - versionData.ConfID + versionData.ConfID, + versionData.CmdList || '[]', + versionData.ClassName, + versionData.originalVersion || versionData.Version, + versionData.PlaneName ); return { diff --git a/XNSimHtml/utils/service-utils.js b/XNSimHtml/utils/service-utils.js index 111f310..2dc2952 100644 --- a/XNSimHtml/utils/service-utils.js +++ b/XNSimHtml/utils/service-utils.js @@ -27,7 +27,7 @@ function getServiceVersionsByClassName(className) { // 查询该类名下的所有版本 const versions = db.prepare(` SELECT ClassName, Name, Version, CodePath, Author, Description, - CreatTime, ChangeTime + CreatTime, ChangeTime, CmdList, OtherParam FROM 'XNServiceVersion' WHERE ClassName = ? ORDER BY Version DESC @@ -89,7 +89,9 @@ function saveServiceVersion(versionData) { Author = ?, Description = ?, CodePath = ?, - ChangeTime = ? + ChangeTime = ?, + CmdList = ?, + OtherParam = ? WHERE ClassName = ? AND Version = ? `).run( versionData.Name, @@ -98,6 +100,8 @@ function saveServiceVersion(versionData) { versionData.Description || '', versionData.CodePath || '', changeTime, // 使用前端传来的时间或生成的当前时间 + versionData.CmdList || '[]', + versionData.OtherParam || '{}', versionData.ClassName, versionData.originalVersion || versionData.Version ); @@ -149,8 +153,8 @@ function saveNewServiceVersion(db, versionData) { const insertResult = db.prepare(` INSERT INTO 'XNServiceVersion' ( ClassName, Name, Version, CodePath, Author, Description, - CreatTime, ChangeTime - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + CreatTime, ChangeTime, CmdList, OtherParam + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( versionData.ClassName, versionData.Name, @@ -159,7 +163,9 @@ function saveNewServiceVersion(db, versionData) { versionData.Author, versionData.Description || '', createTime, // 使用前端传来的创建时间或生成的当前时间 - changeTime // 使用前端传来的修改时间或生成的当前时间 + changeTime, // 使用前端传来的修改时间或生成的当前时间 + versionData.CmdList || '[]', + versionData.OtherParam || '{}' ); return {