diff --git a/Release/Configuration/C909_V1/Packages/ATA04_WeightBalance_2.0.14.6H_20241106/std_04_dll.h b/Release/Configuration/C909_V1/Packages/ATA04_WeightBalance_2.0.14.6H_20241106/std_04_dll.h old mode 100755 new mode 100644 diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db index 4d9be2d..d91ed91 100644 Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ diff --git a/XNInterfaceGenServer/GenIDL.cpp b/XNInterfaceGenServer/GenIDL.cpp index eb287d4..5ada630 100644 --- a/XNInterfaceGenServer/GenIDL.cpp +++ b/XNInterfaceGenServer/GenIDL.cpp @@ -11,7 +11,7 @@ std::string GenIDL::idlFilePath = ""; bool GenIDL::createConfigDirectory(const std::string &configName) { - std::string dirPath = GetXNCoreEnv() + "/IDL/" + configName; + std::string dirPath = GetXNCoreEnv() + "/Configuration/" + configName + "/IDL"; try { fs::create_directories(dirPath); GenIDL::idlFilePath = dirPath + "/" + configName + ".idl"; diff --git a/XNSimPortal/components/header-tools.js b/XNSimPortal/components/header-tools.js index e7c4796..b4de32f 100644 --- a/XNSimPortal/components/header-tools.js +++ b/XNSimPortal/components/header-tools.js @@ -21,11 +21,18 @@ class HeaderTools extends HTMLElement { return selectedOption ? selectedOption.dataset.domainId : ''; } + get selectedConfigurationName() { + const select = this.shadowRoot.getElementById('configurationSelect'); + const selectedOption = select.options[select.selectedIndex]; + return selectedOption ? selectedOption.textContent : ''; + } + // 保存选择到localStorage saveSelection() { const selection = { plane: this.selectedPlane, configurationId: this.selectedConfiguration, + configurationName: this.selectedConfigurationName, domainId: this.selectedDomain }; localStorage.setItem('xnsim-selection', JSON.stringify(selection)); diff --git a/XNSimPortal/components/model-development.js b/XNSimPortal/components/model-development.js index 9260149..ab09fb6 100644 --- a/XNSimPortal/components/model-development.js +++ b/XNSimPortal/components/model-development.js @@ -782,10 +782,12 @@ class ModelDevelopment extends HTMLElement { } } }, - { text: '生成代码', color: '#805ad5', action: () => alert('生成代码功能即将上线') }, - { text: '编辑代码', color: '#d69e2e', action: () => alert('编辑代码功能即将上线') }, - { text: '模型编译', color: '#dd6b20', action: () => alert('模型编译功能即将上线') }, - { text: '模型提交', color: '#e53e3e', action: () => alert('模型提交功能即将上线') } + { + text: '数据包模型上传', + color: '#dd6b20', + action: () => this.uploadDataPackage() + }, + { text: '自动封装', color: '#e53e3e', action: () => alert('自动封装功能即将上线') } ]; buttonConfigs.forEach(config => { @@ -878,17 +880,17 @@ class ModelDevelopment extends HTMLElement { // 添加左列输入框 const leftAdvancedColumn = document.createElement('div'); leftAdvancedColumn.innerHTML = ` -
- - -
- - + + +
+
+ +
`; @@ -952,6 +954,39 @@ class ModelDevelopment extends HTMLElement { cmdListSection.className = 'form-section cmd-list'; cmdListSection.style.cssText = 'border-top: 1px solid #e2e8f0; padding-top: 20px; margin-top: 20px;'; + // 添加结构体参数部分 + const structSection = document.createElement('div'); + structSection.className = 'form-section struct-params'; + structSection.style.cssText = 'border-top: 1px solid #e2e8f0; padding-top: 20px; margin-top: 20px;'; + + // 创建结构体参数标题 + const structHeader = document.createElement('div'); + structHeader.style.cssText = 'margin-bottom: 15px;'; + structHeader.innerHTML = ''; + + // 创建结构体参数网格布局 + const structGrid = document.createElement('div'); + structGrid.style.cssText = 'display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;'; + + // 添加三个结构体输入框 + structGrid.innerHTML = ` +
+ + +
+
+ + +
+
+ + +
+ `; + + structSection.appendChild(structHeader); + structSection.appendChild(structGrid); + // 创建表格标题和工具栏 const cmdListHeader = document.createElement('div'); cmdListHeader.style.cssText = 'display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;'; @@ -991,6 +1026,7 @@ class ModelDevelopment extends HTMLElement { form.appendChild(basicInfoSection); form.appendChild(advancedSection); form.appendChild(cmdListSection); + form.appendChild(structSection); form.appendChild(formActions); formContainer.appendChild(form); container.appendChild(formContainer); @@ -1068,6 +1104,34 @@ class ModelDevelopment extends HTMLElement { } } + // 验证结构体字段的JSON格式 + const inputStructInput = form.querySelector('#inputStruct'); + if (inputStructInput && inputStructInput.value.trim() !== '') { + try { + JSON.parse(inputStructInput.value); + } catch (e) { + throw new Error('InputStruct 必须是有效的 JSON 格式'); + } + } + + const outputStructInput = form.querySelector('#outputStruct'); + if (outputStructInput && outputStructInput.value.trim() !== '') { + try { + JSON.parse(outputStructInput.value); + } catch (e) { + throw new Error('OutputStruct 必须是有效的 JSON 格式'); + } + } + + const heartStructInput = form.querySelector('#heartStruct'); + if (heartStructInput && heartStructInput.value.trim() !== '') { + try { + JSON.parse(heartStructInput.value); + } catch (e) { + throw new Error('HeartStruct 必须是有效的 JSON 格式'); + } + } + // 收集指令列表数据 const cmdList = []; const cmdRows = this.shadowRoot.querySelectorAll('#cmdListBody tr'); @@ -1097,14 +1161,17 @@ class ModelDevelopment extends HTMLElement { Author: form.querySelector('#author').value, Description: form.querySelector('#description').value, ChangeTime: form.querySelector('#changeTime').value, - CodePath: form.querySelector('#codePath').value, RunFreqGroup: form.querySelector('#runFreqGroup').value, RunNode: form.querySelector('#runNode').value, Priority: form.querySelector('#priority').value, DataPackagePath: form.querySelector('#dataPackagePath').value, - DataPackageHeaderPath: form.querySelector('#dataPackageHeaderPath').value, + DataPackageName: form.querySelector('#dataPackageName').value, + DataPackageHeaderName: form.querySelector('#dataPackageHeaderName').value, DataPackageEntryPoint: form.querySelector('#dataPackageEntryPoint').value, DataPackageInterfaceName: form.querySelector('#dataPackageInterfaceName').value, + InputStruct: form.querySelector('#inputStruct').value, + OutputStruct: form.querySelector('#outputStruct').value, + HeartStruct: form.querySelector('#heartStruct').value, CmdList: JSON.stringify(cmdList), isUpdate: this.isEditMode, originalVersion: this.isEditMode ? this.currentVersion.Version : null @@ -1940,14 +2007,17 @@ class ModelDevelopment extends HTMLElement { Description: '', CreatTime: this.getCurrentDateTime(), ChangeTime: this.getCurrentDateTime(), - CodePath: '', RunFreqGroup: '0', RunNode: '0', Priority: '0', DataPackagePath: '', - DataPackageHeaderPath: '', + DataPackageName: '', + DataPackageHeaderName: '', DataPackageEntryPoint: '', DataPackageInterfaceName: '', + InputStruct: '', + OutputStruct: '', + HeartStruct: '', CmdList: [] // 初始化为空数组 }; @@ -2152,6 +2222,163 @@ class ModelDevelopment extends HTMLElement { } } } + + /** + * 上传数据包模型 + */ + async uploadDataPackage() { + try { + // 获取当前选择的构型信息 + const savedSelection = localStorage.getItem('xnsim-selection'); + const selection = savedSelection ? JSON.parse(savedSelection) : {}; + + if (!selection.configurationName) { + alert('请先选择构型!'); + return; + } + + // 创建文件输入元素 + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.webkitdirectory = true; + fileInput.directory = true; + fileInput.multiple = true; + fileInput.style.display = 'none'; + + // 添加到DOM + document.body.appendChild(fileInput); + + // 监听文件选择 + fileInput.addEventListener('change', async (event) => { + try { + const files = Array.from(event.target.files); + + if (files.length === 0) { + alert('请选择文件夹!'); + return; + } + + // 从第一个文件的webkitRelativePath中获取文件夹名称 + let folderName = null; + if (files.length > 0 && files[0].webkitRelativePath) { + const pathParts = files[0].webkitRelativePath.split('/'); + if (pathParts.length > 1) { + folderName = pathParts[0]; + } + } + + if (!folderName) { + alert('无法获取文件夹名称,请重新选择文件夹!'); + return; + } + + // 验证文件夹内容 + const headerFiles = files.filter(file => file.name.toLowerCase().endsWith('.h')); + const libraryFiles = files.filter(file => file.name.toLowerCase().includes('.so')); + + if (headerFiles.length !== 1) { + alert(`文件夹必须包含且仅包含一个.h文件,当前包含 ${headerFiles.length} 个.h文件`); + return; + } + + if (libraryFiles.length !== 1) { + alert(`文件夹必须包含且仅包含一个动态库文件,当前包含 ${libraryFiles.length} 个动态库文件`); + return; + } + + if (files.length !== 2) { + alert(`文件夹只能包含一个.h文件和一个动态库文件,当前包含 ${files.length} 个文件`); + return; + } + + // 创建FormData + const formData = new FormData(); + formData.append('confName', selection.configurationName); + formData.append('folderName', folderName); + + // 添加所有文件 + files.forEach(file => { + formData.append('files', file); + }); + + // 显示上传进度 + const uploadButton = this.shadowRoot.querySelector('.toolbar-button:nth-child(3)'); + if (uploadButton) { + const originalText = uploadButton.textContent; + uploadButton.textContent = '上传中...'; + uploadButton.disabled = true; + } + + // 发送上传请求 + const response = await fetch('/api/filesystem/upload-package', { + method: 'POST', + body: formData + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.message || `上传失败: ${response.status}`); + } + + const result = await response.json(); + + if (result.success) { + // 将返回的值填入对应的输入框 + const dataPackagePathInput = this.shadowRoot.querySelector('#dataPackagePath'); + const dataPackageNameInput = this.shadowRoot.querySelector('#dataPackageName'); + const dataPackageHeaderNameInput = this.shadowRoot.querySelector('#dataPackageHeaderName'); + const dataPackageEntryPointInput = this.shadowRoot.querySelector('#dataPackageEntryPoint'); + const dataPackageInterfaceNameInput = this.shadowRoot.querySelector('#dataPackageInterfaceName'); + + if (dataPackagePathInput) { + dataPackagePathInput.value = result.packagePath; + } + + if (dataPackageNameInput) { + dataPackageNameInput.value = result.libraryFile; + } + + if (dataPackageHeaderNameInput) { + dataPackageHeaderNameInput.value = result.headerFile; + } + + if (dataPackageEntryPointInput) { + dataPackageEntryPointInput.value = result.entryPoint; + } + + if (dataPackageInterfaceNameInput) { + dataPackageInterfaceNameInput.value = result.paramType; + } + + alert(`数据包上传成功!\n数据包路径: ${result.packagePath}\n头文件: ${result.headerFile}\n动态库文件: ${result.libraryFile}\n入口点: ${result.entryPoint}\n参数类型: ${result.paramType}`); + } else { + throw new Error(result.message || '上传失败'); + } + + } catch (error) { + console.error('数据包上传失败:', error); + alert(`数据包上传失败: ${error.message}`); + } finally { + // 恢复按钮状态 + const uploadButton = this.shadowRoot.querySelector('.toolbar-button:nth-child(3)'); + if (uploadButton) { + uploadButton.textContent = '数据包模型上传'; + uploadButton.disabled = false; + } + + // 清理文件输入元素 + document.body.removeChild(fileInput); + } + }); + + // 触发文件选择对话框 + fileInput.click(); + + } catch (error) { + console.error('数据包上传初始化失败:', error); + alert(`数据包上传失败: ${error.message}`); + } + } } customElements.define('model-development', ModelDevelopment); \ No newline at end of file diff --git a/XNSimPortal/routes/filesystem.js b/XNSimPortal/routes/filesystem.js index 051f992..c41b864 100644 --- a/XNSimPortal/routes/filesystem.js +++ b/XNSimPortal/routes/filesystem.js @@ -4,8 +4,12 @@ const fsPromises = require('fs').promises; const fs = require('fs'); const path = require('path'); const multer = require('multer'); +const { exec } = require('child_process'); +const { promisify } = require('util'); const { getActualLogPath, getUploadPath, saveUploadedFile, isAllowedFileType } = require('../utils/file-utils'); +const execAsync = promisify(exec); + // 获取上传目录路径 const uploadPath = getUploadPath(); @@ -35,6 +39,17 @@ const fileFilter = (req, file, cb) => { } }; +// 数据包上传文件过滤器 +const packageFileFilter = (req, file, cb) => { + // 允许的文件类型:.h文件和包含.so的文件 + const fileName = file.originalname.toLowerCase(); + if (fileName.endsWith('.h') || fileName.includes('.so')) { + cb(null, true); + } else { + cb(new Error('数据包只能包含.h文件和动态库文件')); + } +}; + const upload = multer({ storage: storage, fileFilter: fileFilter, @@ -43,6 +58,15 @@ const upload = multer({ } }); +// 数据包上传专用multer配置 +const packageUpload = multer({ + storage: storage, + fileFilter: packageFileFilter, + limits: { + fileSize: 50 * 1024 * 1024 // 限制文件大小为50MB + } +}); + // 读取目录内容 router.get('/readdir', async (req, res) => { try { @@ -461,4 +485,297 @@ router.get('/download', async (req, res) => { } }); +// 上传数据包文件夹 +router.post('/upload-package', packageUpload.array('files'), async (req, res) => { + try { + console.log('接收到的请求体:', req.body); + console.log('接收到的文件:', req.files ? req.files.map(f => f.originalname) : '无文件'); + console.log('文件详细信息:', req.files ? req.files.map(f => ({ + originalname: f.originalname, + webkitRelativePath: f.webkitRelativePath, + fieldname: f.fieldname + })) : '无文件'); + + const { confName } = req.body; + const { folderName } = req.body; // 从前端获取文件夹名称 + + if (!confName) { + return res.status(400).json({ + success: false, + message: '未提供构型名称' + }); + } + + if (!req.files || req.files.length === 0) { + return res.status(400).json({ + success: false, + message: '未提供文件' + }); + } + + // 验证是否为文件夹上传 + const hasFolderStructure = req.files.some(file => + file.originalname.includes('/') || file.originalname.includes('\\') + ); + + // 优先使用前端传递的文件夹名称,如果没有则从文件路径中提取 + let packageName = null; + + if (folderName) { + // 使用前端传递的文件夹名称 + packageName = folderName; + } else if (hasFolderStructure) { + // 如果文件路径包含分隔符,从路径中提取 + for (const file of req.files) { + const pathParts = file.originalname.replace(/\\/g, '/').split('/'); + if (pathParts.length > 1) { + packageName = pathParts[0]; // 取第一级目录名作为数据包名称 + break; + } + } + } else { + // 如果文件路径不包含分隔符,尝试从webkitRelativePath获取 + if (req.files.length > 0 && req.files[0].webkitRelativePath) { + const pathParts = req.files[0].webkitRelativePath.split('/'); + if (pathParts.length > 1) { + packageName = pathParts[0]; + } + } + + // 如果还是无法获取,使用默认名称 + if (!packageName) { + packageName = 'uploaded_package_' + Date.now(); + } + } + + if (!packageName) { + return res.status(400).json({ + success: false, + message: '无法从上传的文件中提取文件夹名称' + }); + } + + // 验证文件夹内容 + const fileTypes = { + headerFiles: [], // .h文件 + libraryFiles: [] // 动态库文件 + }; + + req.files.forEach(file => { + const fileName = path.basename(file.originalname); + const ext = path.extname(fileName).toLowerCase(); + + if (ext === '.h') { + fileTypes.headerFiles.push(file); + } else if (fileName.toLowerCase().includes('.so')) { + fileTypes.libraryFiles.push(file); + } + }); + + // 验证文件数量 + if (fileTypes.headerFiles.length !== 1) { + return res.status(400).json({ + success: false, + message: `文件夹必须包含且仅包含一个.h文件,当前包含 ${fileTypes.headerFiles.length} 个.h文件` + }); + } + + if (fileTypes.libraryFiles.length !== 1) { + return res.status(400).json({ + success: false, + message: `文件夹必须包含且仅包含一个动态库文件,当前包含 ${fileTypes.libraryFiles.length} 个动态库文件` + }); + } + + // 验证总文件数量 + const totalFiles = fileTypes.headerFiles.length + fileTypes.libraryFiles.length; + if (totalFiles !== req.files.length) { + return res.status(400).json({ + success: false, + message: `文件夹只能包含一个.h文件和一个动态库文件,当前包含 ${req.files.length} 个文件` + }); + } + + // 获取数据包路径 + const { getPackagesPath } = require('../utils/file-utils'); + const packagesPath = getPackagesPath(confName); + + if (!packagesPath) { + return res.status(400).json({ + success: false, + message: '无法获取数据包路径' + }); + } + + // 创建目标数据包目录 + const targetPackagePath = path.join(packagesPath, packageName); + + try { + await fsPromises.mkdir(targetPackagePath, { recursive: true }); + } catch (error) { + if (error.code !== 'EEXIST') { + console.error('创建数据包目录失败:', error); + return res.status(500).json({ + success: false, + message: '创建数据包目录失败: ' + error.message + }); + } + } + + const uploadedFiles = []; + const errors = []; + + // 处理每个上传的文件 + for (const file of req.files) { + try { + // 从文件的相对路径中提取目标路径 + let targetPath; + if (file.originalname.includes('/') || file.originalname.includes('\\')) { + // 如果文件名包含路径分隔符,说明是文件夹上传 + const relativePath = file.originalname.replace(/\\/g, '/'); + targetPath = path.join(targetPackagePath, relativePath); + } else { + // 单个文件,直接放在数据包根目录 + targetPath = path.join(targetPackagePath, file.originalname); + } + + // 确保目标目录存在 + const targetDir = path.dirname(targetPath); + try { + await fsPromises.mkdir(targetDir, { recursive: true }); + } catch (mkdirError) { + if (mkdirError.code !== 'EEXIST') { + throw mkdirError; + } + } + + // 移动文件到目标位置 + await fsPromises.copyFile(file.path, targetPath); + + // 删除临时文件 + try { + await fsPromises.unlink(file.path); + } catch (unlinkError) { + console.warn('删除临时文件失败:', unlinkError); + } + + // 获取文件信息 + const stats = await fsPromises.stat(targetPath); + const fileName = path.basename(targetPath); + const ext = path.extname(fileName).toLowerCase(); + + uploadedFiles.push({ + name: fileName, + path: path.relative(targetPackagePath, targetPath), + size: stats.size, + created: stats.birthtime, + modified: stats.mtime, + type: ext === '.h' ? 'header' : 'library' + }); + + } catch (fileError) { + console.error(`处理文件 ${file.originalname} 失败:`, fileError); + errors.push({ + file: file.originalname, + error: fileError.message + }); + } + } + + // 对动态库执行nm -D命令获取入口点函数信息 + let entryPointInfo = null; + + try { + // 找到动态库文件路径 + const libraryFile = uploadedFiles.find(file => file.type === 'library'); + if (libraryFile) { + const libraryPath = path.join(targetPackagePath, libraryFile.path); + entryPointInfo = await getEntryPointInfo(libraryPath); + } + } catch (error) { + console.warn('获取动态库入口点信息失败:', error.message); + // 不阻止上传流程,只记录警告 + } + + // 返回上传结果 + res.json({ + success: true, + message: `成功上传数据包 ${packageName},包含 ${fileTypes.headerFiles.length} 个头文件和 ${fileTypes.libraryFiles.length} 个动态库文件`, + packagePath: packageName, // 相对于Packages目录的路径 + headerFile: path.basename(fileTypes.headerFiles[0].originalname), + libraryFile: path.basename(fileTypes.libraryFiles[0].originalname), + entryPoint: entryPointInfo ? entryPointInfo.symbolName : null, + paramType: entryPointInfo ? entryPointInfo.paramType : null + }); + + } catch (error) { + console.error('数据包上传失败:', error); + res.status(500).json({ + success: false, + message: '数据包上传失败: ' + error.message + }); + } +}); + +/** + * 获取动态库入口点函数信息 + * @param {string} libraryPath - 动态库文件路径 + * @returns {Promise} 入口点信息对象或null + */ +async function getEntryPointInfo(libraryPath) { + try { + // 执行nm -D命令获取动态符号表 + const { stdout } = await execAsync(`nm -D "${libraryPath}" | grep EntryPoint`); + + if (!stdout.trim()) { + console.log('未找到EntryPoint相关的符号'); + return null; + } + + // 解析nm输出,只取第一个匹配的入口点 + const lines = stdout.trim().split('\n'); + + if (lines.length > 0) { + const line = lines[0]; // 只处理第一行 + // nm输出格式: 地址 类型 符号名 + const parts = line.trim().split(/\s+/); + if (parts.length >= 3) { + const symbolName = parts[2]; + + // 尝试从函数名中提取参数类型信息 + // 函数名格式示例: _Z28SACSCWeightBalanceEntryPointP20ComacDataStructure_S + let paramType = null; + + if (symbolName.startsWith('_Z')) { + // 解析C++符号名格式 + const match = symbolName.match(/_Z\d+([A-Za-z0-9_]+)P(\d+)([A-Za-z0-9_]+)/); + if (match) { + paramType = match[3]; + } else { + // 如果无法解析,使用原始符号名 + paramType = symbolName; + } + } else { + // C函数名,使用原始符号名 + paramType = symbolName; + } + + const entryPoint = { + symbolName: symbolName, + paramType: paramType + }; + + console.log('动态库入口点信息:', entryPoint); + return entryPoint; + } + } + + return null; + + } catch (error) { + console.warn('获取动态库入口点信息失败:', error.message); + return null; + } +} + module.exports = router; \ No newline at end of file diff --git a/XNSimPortal/utils/file-utils.js b/XNSimPortal/utils/file-utils.js index 877b4b8..752557f 100644 --- a/XNSimPortal/utils/file-utils.js +++ b/XNSimPortal/utils/file-utils.js @@ -49,32 +49,64 @@ function getXNCorePath() { return xnCorePath; } -// 模型项目文件目录路径 -function getProjectModelPath() { +// 获取当前构型路径 +function getCurrentConfPath(confName) { + if (!confName) { + return ''; + } const xnCorePath = getXNCorePath(); if (!xnCorePath) return ''; - return path.join(xnCorePath, 'Project', 'Model'); + return path.join(xnCorePath, 'Configuration', confName); +} + +// 模型项目文件目录路径 +function getProjectModelPath(confName) { + if (!confName) { + return ''; + } + const xnCorePath = getXNCorePath(); + if (!xnCorePath) return ''; + return path.join(xnCorePath, 'Configuration', confName, 'ModelProjects'); } // 模型文件目录路径 -function getModelPath() { +function getModelPath(confName) { + if (!confName) { + return ''; + } const xnCorePath = getXNCorePath(); if (!xnCorePath) return ''; - return path.join(xnCorePath, 'Models'); + return path.join(xnCorePath, 'Configuration', confName, 'Models'); } //服务项目文件目录路径 -function getProjectServicePath() { +function getProjectServicePath(confName) { + if (!confName) { + return ''; + } const xnCorePath = getXNCorePath(); if (!xnCorePath) return ''; - return path.join(xnCorePath, 'Project', 'Service'); + return path.join(xnCorePath, 'Configuration', confName, 'ServiceProjects'); } // 服务文件目录路径 -function getServicePath() { +function getServicePath(confName) { + if (!confName) { + return ''; + } const xnCorePath = getXNCorePath(); if (!xnCorePath) return ''; - return path.join(xnCorePath, 'Services'); + return path.join(xnCorePath, 'Configuration', confName, 'Services'); +} + +//数据包路径 +function getPackagesPath(confName) { + if (!confName) { + return ''; + } + const xnCorePath = getXNCorePath(); + if (!xnCorePath) return ''; + return path.join(xnCorePath, 'Configuration', confName, 'Packages'); } // 日志目录路径处理 @@ -152,9 +184,12 @@ function isAllowedFileType(fileName, allowedTypes = []) { module.exports = { getXNCorePath, + getCurrentConfPath, getModelPath, getProjectModelPath, + getProjectServicePath, getServicePath, + getPackagesPath, getActualLogPath, isPathSafe, ensureDirectoryExists, diff --git a/XNSimPortal/utils/model-utils.js b/XNSimPortal/utils/model-utils.js index be86f80..0fb31e0 100644 --- a/XNSimPortal/utils/model-utils.js +++ b/XNSimPortal/utils/model-utils.js @@ -59,10 +59,10 @@ function getModelVersionsByClassName(className, planeName) { const query = ` SELECT - PlaneName, ClassName, Name, Version, CodePath, Author, Description, + PlaneName, ClassName, Name, ConfID, Version, Author, Description, CreatTime, ChangeTime, RunFreqGroup, RunNode, Priority, - DataPackagePath, DataPackageHeaderPath, DataPackageEntryPoint, DataPackageInterfaceName, - ConfID, CmdList + DataPackagePath, DataPackageName, DataPackageHeaderName, DataPackageEntryPoint, DataPackageInterfaceName, + InputStruct, OutputStruct, HeartStruct, CmdList FROM 'XNModelsVersion' WHERE ClassName = ? AND PlaneName = ? ORDER BY Version DESC @@ -124,8 +124,8 @@ function saveModelVersion(versionData) { PlaneName = ?, ClassName = ?, Name = ?, + ConfID = ?, Version = ?, - CodePath = ?, Author = ?, Description = ?, CreatTime = ?, @@ -134,18 +134,21 @@ function saveModelVersion(versionData) { RunNode = ?, Priority = ?, DataPackagePath = ?, - DataPackageHeaderPath = ?, + DataPackageName = ?, + DataPackageHeaderName = ?, DataPackageEntryPoint = ?, DataPackageInterfaceName = ?, - ConfID = ?, + InputStruct = ?, + OutputStruct = ?, + HeartStruct = ?, CmdList = ? WHERE ClassName = ? AND Version = ? AND PlaneName = ? `).run( versionData.PlaneName, versionData.ClassName, versionData.Name, + versionData.ConfID, versionData.Version, - versionData.CodePath || '', versionData.Author, versionData.Description || '', versionData.CreatTime || changeTime, @@ -154,10 +157,13 @@ function saveModelVersion(versionData) { versionData.RunNode || '', versionData.Priority || '0', versionData.DataPackagePath || '', - versionData.DataPackageHeaderPath || '', + versionData.DataPackageName || '', + versionData.DataPackageHeaderName || '', versionData.DataPackageEntryPoint || '', versionData.DataPackageInterfaceName || '', - versionData.ConfID, + versionData.InputStruct || '', + versionData.OutputStruct || '', + versionData.HeartStruct || '', versionData.CmdList || '[]', versionData.ClassName, versionData.originalVersion || versionData.Version, @@ -210,17 +216,17 @@ function saveNewVersion(db, versionData) { // 插入新版本 const insertResult = db.prepare(` INSERT INTO 'XNModelsVersion' ( - PlaneName, ClassName, Name, Version, CodePath, Author, Description, + PlaneName, ClassName, Name, ConfID, Version, Author, Description, CreatTime, ChangeTime, RunFreqGroup, RunNode, Priority, - DataPackagePath, DataPackageHeaderPath, DataPackageEntryPoint, DataPackageInterfaceName, - ConfID, CmdList - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + DataPackagePath, DataPackageName, DataPackageHeaderName, DataPackageEntryPoint, DataPackageInterfaceName, + InputStruct, OutputStruct, HeartStruct, CmdList + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( versionData.PlaneName, versionData.ClassName, versionData.Name, + versionData.ConfID, versionData.Version, - versionData.CodePath || '', versionData.Author, versionData.Description || '', createTime, @@ -229,10 +235,13 @@ function saveNewVersion(db, versionData) { versionData.RunNode || '', versionData.Priority || '0', versionData.DataPackagePath || '', - versionData.DataPackageHeaderPath || '', + versionData.DataPackageName || '', + versionData.DataPackageHeaderName || '', versionData.DataPackageEntryPoint || '', versionData.DataPackageInterfaceName || '', - versionData.ConfID, + versionData.InputStruct || '', + versionData.OutputStruct || '', + versionData.HeartStruct || '', versionData.CmdList || '[]' );