V0.32.2.250620_alpha:模型开发页面添加了结构体的对应功能
This commit is contained in:
parent
129e1459ca
commit
ba9b024cd9
Binary file not shown.
@ -310,7 +310,7 @@ class InterfaceConfig extends HTMLElement {
|
||||
throw new Error('请先选择构型');
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/interface/list?systemName=XNSim&confID=${selection.configurationId}`);
|
||||
const response = await fetch(`/api/interface/list?confID=${selection.configurationId}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('获取数据失败');
|
||||
}
|
||||
|
@ -962,25 +962,56 @@ class ModelDevelopment extends HTMLElement {
|
||||
// 创建结构体参数标题
|
||||
const structHeader = document.createElement('div');
|
||||
structHeader.style.cssText = 'margin-bottom: 15px;';
|
||||
structHeader.innerHTML = '<label style="font-weight: 500; color: #333;">结构体参数</label>';
|
||||
structHeader.innerHTML = '<label style="font-weight: 500; color: #333;">结构体对应关系</label>';
|
||||
|
||||
// 创建结构体参数网格布局
|
||||
const structGrid = document.createElement('div');
|
||||
structGrid.style.cssText = 'display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;';
|
||||
structGrid.style.cssText = 'display: grid; grid-template-columns: auto repeat(3, 1fr); gap: 20px;';
|
||||
|
||||
// 添加三个结构体输入框
|
||||
// 添加六个下拉框,按类型分组
|
||||
structGrid.innerHTML = `
|
||||
<div class="form-group">
|
||||
<label for="inputStruct">输入结构体 (InputStruct)</label>
|
||||
<textarea id="inputStruct" name="InputStruct" placeholder="输入结构体JSON格式" title="模型的输入参数结构体,JSON格式" style="min-height: 80px; resize: vertical;">${this.currentVersion.InputStruct || ''}</textarea>
|
||||
<div class="label-column" style="display: flex; flex-direction: column; justify-content: flex-start; gap: 30px; padding-top: 30px;">
|
||||
<div style="font-size: 16px; color: #333; white-space: nowrap;">数据库中:</div>
|
||||
<div style="font-size: 16px; color: #333; white-space: nowrap;">头文件中:</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="outputStruct">输出结构体 (OutputStruct)</label>
|
||||
<textarea id="outputStruct" name="OutputStruct" placeholder="输出结构体JSON格式" title="模型的输出参数结构体,JSON格式" style="min-height: 80px; resize: vertical;">${this.currentVersion.OutputStruct || ''}</textarea>
|
||||
<div class="struct-column">
|
||||
<div class="struct-type-header" style="font-weight: 600; color: #333; margin-bottom: 10px; text-align: center;">输入</div>
|
||||
<div class="form-group">
|
||||
<select id="inputStructMapping1" name="InputStructMapping1" title="选择输入结构体对应关系1" style="width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<option value="">请选择...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select id="inputStructMapping2" name="InputStructMapping2" title="选择输入结构体对应关系2" style="width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<option value="">请选择...</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="heartStruct">心跳结构体 (HeartStruct)</label>
|
||||
<textarea id="heartStruct" name="HeartStruct" placeholder="心跳结构体JSON格式" title="模型的心跳参数结构体,JSON格式" style="min-height: 80px; resize: vertical;">${this.currentVersion.HeartStruct || ''}</textarea>
|
||||
<div class="struct-column">
|
||||
<div class="struct-type-header" style="font-weight: 600; color: #333; margin-bottom: 10px; text-align: center;">输出</div>
|
||||
<div class="form-group">
|
||||
<select id="outputStructMapping1" name="OutputStructMapping1" title="选择输出结构体对应关系1" style="width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<option value="">请选择...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select id="outputStructMapping2" name="OutputStructMapping2" title="选择输出结构体对应关系2" style="width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<option value="">请选择...</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="struct-column">
|
||||
<div class="struct-type-header" style="font-weight: 600; color: #333; margin-bottom: 10px; text-align: center;">心跳</div>
|
||||
<div class="form-group">
|
||||
<select id="heartStructMapping1" name="HeartStructMapping1" title="选择心跳结构体对应关系1" style="width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<option value="">请选择...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select id="heartStructMapping2" name="HeartStructMapping2" title="选择心跳结构体对应关系2" style="width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<option value="">请选择...</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -1025,8 +1056,8 @@ class ModelDevelopment extends HTMLElement {
|
||||
// 组装表单
|
||||
form.appendChild(basicInfoSection);
|
||||
form.appendChild(advancedSection);
|
||||
form.appendChild(cmdListSection);
|
||||
form.appendChild(structSection);
|
||||
form.appendChild(cmdListSection);
|
||||
form.appendChild(formActions);
|
||||
formContainer.appendChild(form);
|
||||
container.appendChild(formContainer);
|
||||
@ -1071,6 +1102,9 @@ class ModelDevelopment extends HTMLElement {
|
||||
this.updateRunNodeOptions();
|
||||
});
|
||||
}
|
||||
|
||||
// 填充数据库中结构体下拉框
|
||||
this.populateDatabaseStructDropdowns();
|
||||
}, 0);
|
||||
|
||||
// 添加表单提交事件
|
||||
@ -1151,6 +1185,17 @@ class ModelDevelopment extends HTMLElement {
|
||||
}
|
||||
});
|
||||
|
||||
// 构建结构体映射JSON字符串
|
||||
const buildStructMapping = (select1, select2) => {
|
||||
const selectedOption1 = select1.selectedOptions[0];
|
||||
const value2 = select2.value;
|
||||
|
||||
if (selectedOption1 && selectedOption1.dataset.fullname && value2) {
|
||||
return JSON.stringify({ [selectedOption1.dataset.fullname]: value2 });
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
// 构建版本数据
|
||||
const versionData = {
|
||||
PlaneName: selection.plane,
|
||||
@ -1169,9 +1214,18 @@ class ModelDevelopment extends HTMLElement {
|
||||
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,
|
||||
InputStruct: buildStructMapping(
|
||||
form.querySelector('#inputStructMapping1'),
|
||||
form.querySelector('#inputStructMapping2')
|
||||
),
|
||||
OutputStruct: buildStructMapping(
|
||||
form.querySelector('#outputStructMapping1'),
|
||||
form.querySelector('#outputStructMapping2')
|
||||
),
|
||||
HeartStruct: buildStructMapping(
|
||||
form.querySelector('#heartStructMapping1'),
|
||||
form.querySelector('#heartStructMapping2')
|
||||
),
|
||||
CmdList: JSON.stringify(cmdList),
|
||||
isUpdate: this.isEditMode,
|
||||
originalVersion: this.isEditMode ? this.currentVersion.Version : null
|
||||
@ -2223,6 +2277,197 @@ class ModelDevelopment extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充数据库中结构体下拉框
|
||||
*/
|
||||
async populateDatabaseStructDropdowns() {
|
||||
try {
|
||||
const savedSelection = localStorage.getItem('xnsim-selection');
|
||||
const selection = savedSelection ? JSON.parse(savedSelection) : {};
|
||||
|
||||
if (!selection.configurationId) {
|
||||
console.warn('未找到构型ID,无法获取结构体列表');
|
||||
return;
|
||||
}
|
||||
|
||||
const structResponse = await fetch(`/api/interface/list?confID=${selection.configurationId}`);
|
||||
if (structResponse.ok) {
|
||||
const structData = await structResponse.json();
|
||||
|
||||
// 以ModelStructName为key去重,只保留第一个全称
|
||||
const uniqueMap = {};
|
||||
structData.forEach(item => {
|
||||
if (!uniqueMap[item.ModelStructName]) {
|
||||
uniqueMap[item.ModelStructName] = `${item.SystemName}::${item.PlaneName}::${item.ATAName}::${item.ModelStructName}`;
|
||||
}
|
||||
});
|
||||
const structNames = Object.keys(uniqueMap);
|
||||
|
||||
// 获取下拉框元素
|
||||
const inputStructMapping1 = this.shadowRoot.querySelector('#inputStructMapping1');
|
||||
const outputStructMapping1 = this.shadowRoot.querySelector('#outputStructMapping1');
|
||||
const heartStructMapping1 = this.shadowRoot.querySelector('#heartStructMapping1');
|
||||
|
||||
// 填充数据库中结构体下拉框
|
||||
if (inputStructMapping1) {
|
||||
inputStructMapping1.innerHTML = '<option value="">请选择...</option>' +
|
||||
structNames.map(name => `<option value="${name}" data-fullname="${uniqueMap[name]}">${name}</option>`).join('');
|
||||
}
|
||||
if (outputStructMapping1) {
|
||||
outputStructMapping1.innerHTML = '<option value="">请选择...</option>' +
|
||||
structNames.map(name => `<option value="${name}" data-fullname="${uniqueMap[name]}">${name}</option>`).join('');
|
||||
}
|
||||
if (heartStructMapping1) {
|
||||
heartStructMapping1.innerHTML = '<option value="">请选择...</option>' +
|
||||
structNames.map(name => `<option value="${name}" data-fullname="${uniqueMap[name]}">${name}</option>`).join('');
|
||||
}
|
||||
|
||||
// 解析数据库中存储的JSON字符串并自动选择正确的选项
|
||||
this.selectStructMappingOptions();
|
||||
|
||||
// 检查数据包相关字段是否有值,如果有则获取结构体成员信息
|
||||
const dataPackagePathInput = this.shadowRoot.querySelector('#dataPackagePath');
|
||||
const dataPackageHeaderNameInput = this.shadowRoot.querySelector('#dataPackageHeaderName');
|
||||
const dataPackageInterfaceNameInput = this.shadowRoot.querySelector('#dataPackageInterfaceName');
|
||||
if (dataPackagePathInput && dataPackageHeaderNameInput && dataPackageInterfaceNameInput) {
|
||||
|
||||
const packagePath = dataPackagePathInput.value.trim();
|
||||
const hearderName = dataPackageHeaderNameInput.value.trim();
|
||||
const interfaceName = dataPackageInterfaceNameInput.value.trim();
|
||||
|
||||
if (packagePath && hearderName && interfaceName) {
|
||||
const headerFilePath = packagePath + '/' + hearderName;
|
||||
try {
|
||||
const memberResponse = await fetch('/api/filesystem/get-struct-members', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
confName: selection.configurationName,
|
||||
headerFilePath: headerFilePath,
|
||||
structName: interfaceName
|
||||
})
|
||||
});
|
||||
|
||||
if (memberResponse.ok) {
|
||||
const memberData = await memberResponse.json();
|
||||
|
||||
if (memberData.success && memberData.memberNames) {
|
||||
// 获取头文件结构体下拉框
|
||||
const inputStructMapping2 = this.shadowRoot.querySelector('#inputStructMapping2');
|
||||
const outputStructMapping2 = this.shadowRoot.querySelector('#outputStructMapping2');
|
||||
const heartStructMapping2 = this.shadowRoot.querySelector('#heartStructMapping2');
|
||||
|
||||
// 填充头文件中结构体下拉框
|
||||
if (inputStructMapping2 && outputStructMapping2 && heartStructMapping2) {
|
||||
const memberOptions = '<option value="">请选择...</option>' +
|
||||
memberData.memberNames.map(member => `<option value="${member}">${member}</option>`).join('');
|
||||
|
||||
inputStructMapping2.innerHTML = memberOptions;
|
||||
outputStructMapping2.innerHTML = memberOptions;
|
||||
heartStructMapping2.innerHTML = memberOptions;
|
||||
|
||||
// 在填充头文件结构体下拉框后,再次解析JSON并选择选项
|
||||
this.selectStructMappingOptions();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn('获取结构体成员信息失败:', memberResponse.status);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('获取结构体成员信息失败:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn('获取接口结构体列表失败:', structResponse.status);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('填充数据库结构体下拉框失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析数据库中存储的JSON字符串并自动选择正确的选项
|
||||
*/
|
||||
selectStructMappingOptions() {
|
||||
if (!this.currentVersion) return;
|
||||
|
||||
// 解析InputStruct
|
||||
if (this.currentVersion.InputStruct) {
|
||||
try {
|
||||
const inputStructData = JSON.parse(this.currentVersion.InputStruct);
|
||||
const inputStructKey = Object.keys(inputStructData)[0]; // 获取JSON对象的key
|
||||
const inputStructValue = inputStructData[inputStructKey]; // 获取JSON对象的value
|
||||
|
||||
// 选择数据库结构体下拉框
|
||||
const inputStructMapping1 = this.shadowRoot.querySelector('#inputStructMapping1');
|
||||
if (inputStructMapping1) {
|
||||
// 从全称中提取结构体名
|
||||
const structName = inputStructKey.split('::').pop();
|
||||
inputStructMapping1.value = structName;
|
||||
}
|
||||
|
||||
// 选择头文件结构体下拉框
|
||||
const inputStructMapping2 = this.shadowRoot.querySelector('#inputStructMapping2');
|
||||
if (inputStructMapping2) {
|
||||
inputStructMapping2.value = inputStructValue;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('解析InputStruct失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 解析OutputStruct
|
||||
if (this.currentVersion.OutputStruct) {
|
||||
try {
|
||||
const outputStructData = JSON.parse(this.currentVersion.OutputStruct);
|
||||
const outputStructKey = Object.keys(outputStructData)[0];
|
||||
const outputStructValue = outputStructData[outputStructKey];
|
||||
|
||||
// 选择数据库结构体下拉框
|
||||
const outputStructMapping1 = this.shadowRoot.querySelector('#outputStructMapping1');
|
||||
if (outputStructMapping1) {
|
||||
const structName = outputStructKey.split('::').pop();
|
||||
outputStructMapping1.value = structName;
|
||||
}
|
||||
|
||||
// 选择头文件结构体下拉框
|
||||
const outputStructMapping2 = this.shadowRoot.querySelector('#outputStructMapping2');
|
||||
if (outputStructMapping2) {
|
||||
outputStructMapping2.value = outputStructValue;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('解析OutputStruct失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 解析HeartStruct
|
||||
if (this.currentVersion.HeartStruct) {
|
||||
try {
|
||||
const heartStructData = JSON.parse(this.currentVersion.HeartStruct);
|
||||
const heartStructKey = Object.keys(heartStructData)[0];
|
||||
const heartStructValue = heartStructData[heartStructKey];
|
||||
|
||||
// 选择数据库结构体下拉框
|
||||
const heartStructMapping1 = this.shadowRoot.querySelector('#heartStructMapping1');
|
||||
if (heartStructMapping1) {
|
||||
const structName = heartStructKey.split('::').pop();
|
||||
heartStructMapping1.value = structName;
|
||||
}
|
||||
|
||||
// 选择头文件结构体下拉框
|
||||
const heartStructMapping2 = this.shadowRoot.querySelector('#heartStructMapping2');
|
||||
if (heartStructMapping2) {
|
||||
heartStructMapping2.value = heartStructValue;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('解析HeartStruct失败:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传数据包模型
|
||||
*/
|
||||
@ -2350,6 +2595,18 @@ class ModelDevelopment extends HTMLElement {
|
||||
dataPackageInterfaceNameInput.value = result.paramType;
|
||||
}
|
||||
|
||||
//将结构体名称填入对应下拉框的候选列表
|
||||
const inputStructMapping2 = this.shadowRoot.querySelector('#inputStructMapping2');
|
||||
const outputStructMapping2 = this.shadowRoot.querySelector('#outputStructMapping2');
|
||||
const heartStructMapping2 = this.shadowRoot.querySelector('#heartStructMapping2');
|
||||
|
||||
// 填充头文件中结构体下拉框
|
||||
if (inputStructMapping2 && outputStructMapping2 && heartStructMapping2) {
|
||||
inputStructMapping2.innerHTML = '<option value="">请选择...</option>' + result.memberNames.map(name => `<option value="${name}">${name}</option>`).join('');
|
||||
outputStructMapping2.innerHTML = '<option value="">请选择...</option>' + result.memberNames.map(name => `<option value="${name}">${name}</option>`).join('');
|
||||
heartStructMapping2.innerHTML = '<option value="">请选择...</option>' + result.memberNames.map(name => `<option value="${name}">${name}</option>`).join('');
|
||||
}
|
||||
|
||||
alert(`数据包上传成功!\n数据包路径: ${result.packagePath}\n头文件: ${result.headerFile}\n动态库文件: ${result.libraryFile}\n入口点: ${result.entryPoint}\n参数类型: ${result.paramType}`);
|
||||
} else {
|
||||
throw new Error(result.message || '上传失败');
|
||||
|
@ -488,14 +488,6 @@ 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; // 从前端获取文件夹名称
|
||||
|
||||
@ -697,6 +689,23 @@ router.post('/upload-package', packageUpload.array('files'), async (req, res) =>
|
||||
// 不阻止上传流程,只记录警告
|
||||
}
|
||||
|
||||
let memberNames = [];
|
||||
// 如果获取到了入口点函数信息,尝试从头文件中查找对应的结构体定义
|
||||
if (entryPointInfo && entryPointInfo.paramType) {
|
||||
try {
|
||||
const headerFile = uploadedFiles.find(file => file.type === 'header');
|
||||
if (headerFile) {
|
||||
const headerFilePath = path.join(targetPackagePath, headerFile.path);
|
||||
const structMemberNames = await findStructDefinition(headerFilePath, entryPointInfo.paramType);
|
||||
if (structMemberNames) {
|
||||
memberNames = structMemberNames;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('查找结构体定义失败:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 返回上传结果
|
||||
res.json({
|
||||
success: true,
|
||||
@ -705,7 +714,8 @@ router.post('/upload-package', packageUpload.array('files'), async (req, res) =>
|
||||
headerFile: path.basename(fileTypes.headerFiles[0].originalname),
|
||||
libraryFile: path.basename(fileTypes.libraryFiles[0].originalname),
|
||||
entryPoint: entryPointInfo ? entryPointInfo.symbolName : null,
|
||||
paramType: entryPointInfo ? entryPointInfo.paramType : null
|
||||
paramType: entryPointInfo ? entryPointInfo.paramType : null,
|
||||
memberNames: memberNames
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
@ -765,7 +775,6 @@ async function getEntryPointInfo(libraryPath) {
|
||||
paramType: paramType
|
||||
};
|
||||
|
||||
console.log('动态库入口点信息:', entryPoint);
|
||||
return entryPoint;
|
||||
}
|
||||
}
|
||||
@ -778,4 +787,157 @@ async function getEntryPointInfo(libraryPath) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
/**
|
||||
* 查找指定结构体的定义并返回其成员信息
|
||||
* @param {string} headerFilePath - 头文件路径
|
||||
* @param {string} structName - 要查找的结构体名称
|
||||
* @returns {Promise<Array<string>>} 结构体成员信息数组,格式为"type memberName"
|
||||
*/
|
||||
async function findStructDefinition(headerFilePath, structName) {
|
||||
try {
|
||||
// 检查文件是否存在
|
||||
await fsPromises.access(headerFilePath);
|
||||
|
||||
// 读取头文件内容
|
||||
const content = await fsPromises.readFile(headerFilePath, 'utf8');
|
||||
|
||||
// 移除注释,避免干扰解析
|
||||
const contentWithoutComments = content
|
||||
// 移除单行注释
|
||||
.replace(/\/\/.*$/gm, '')
|
||||
// 移除多行注释
|
||||
.replace(/\/\*[\s\S]*?\*\//g, '');
|
||||
|
||||
// 构建查找结构体定义的正则表达式
|
||||
// 匹配以下格式:
|
||||
// struct StructName {
|
||||
// struct StructName{
|
||||
// typedef struct StructName {
|
||||
// typedef struct StructName{
|
||||
const structPattern = new RegExp(
|
||||
`(?:typedef\\s+)?struct\\s+${structName}\\s*\\{([\\s\\S]*?)\\}\\s*;?`,
|
||||
'g'
|
||||
);
|
||||
|
||||
const memberNames = [];
|
||||
let match;
|
||||
|
||||
while ((match = structPattern.exec(contentWithoutComments)) !== null) {
|
||||
const structBody = match[1];
|
||||
// 按行分割结构体内容
|
||||
const lines = structBody.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmedLine = line.trim();
|
||||
|
||||
// 跳过空行和只包含分号的行
|
||||
if (!trimmedLine || trimmedLine === ';') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 匹配成员声明
|
||||
// 基础类型: int, double, float, char, short, long, unsigned, etc.
|
||||
// 结构体指针: struct xxx_S*
|
||||
// 结构体: struct xxx_S
|
||||
const memberRegex = /^(?:const\s+)?(?:struct\s+([A-Za-z_][A-Za-z0-9_]*)\s*)?(?:unsigned\s+)?(?:long\s+)?(?:int\s+)?(?:char\s+)?(?:short\s+)?(?:float\s+)?(?:double\s+)?(?:void\s*)?(?:[A-Za-z_][A-Za-z0-9_]*\s*)?(\*?)\s*([A-Za-z_][A-Za-z0-9_]*)\s*(?:\[[^\]]*\])?\s*;?\s*$/;
|
||||
|
||||
const memberMatch = trimmedLine.match(memberRegex);
|
||||
if (memberMatch) {
|
||||
const structType = memberMatch[1]; // 结构体类型名
|
||||
const isPointer = memberMatch[2]; // 是否为指针
|
||||
const memberName = memberMatch[3]; // 成员名
|
||||
|
||||
// 构建类型信息
|
||||
let type = '';
|
||||
if (structType) {
|
||||
// 结构体类型
|
||||
type = `struct ${structType}${isPointer ? '*' : ''}`;
|
||||
} else {
|
||||
// 基础类型,需要从原始行中提取
|
||||
const typeMatch = trimmedLine.match(/^(?:const\s+)?(?:unsigned\s+)?(?:long\s+)?(?:int\s+)?(?:char\s+)?(?:short\s+)?(?:float\s+)?(?:double\s+)?(?:void\s*)?(?:[A-Za-z_][A-Za-z0-9_]*\s*)?/);
|
||||
if (typeMatch) {
|
||||
type = typeMatch[0].trim() + (isPointer ? '*' : '');
|
||||
} else {
|
||||
type = 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
// 拼接类型和成员名
|
||||
const memberString = `${type} ${memberName}`;
|
||||
memberNames.push(memberString);
|
||||
}
|
||||
}
|
||||
}
|
||||
return memberNames;
|
||||
|
||||
} catch (error) {
|
||||
console.warn(`查找结构体 ${structName} 定义失败:`, error.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据构型名、头文件路径和结构体名获取结构体成员信息
|
||||
*/
|
||||
router.post('/get-struct-members', async (req, res) => {
|
||||
try {
|
||||
const { confName, headerFilePath, structName } = req.body;
|
||||
|
||||
if (!confName) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '未提供构型名称'
|
||||
});
|
||||
}
|
||||
|
||||
if (!headerFilePath) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '未提供头文件路径'
|
||||
});
|
||||
}
|
||||
|
||||
if (!structName) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '未提供结构体名称'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取数据包路径
|
||||
const { getPackagesPath } = require('../utils/file-utils');
|
||||
const packagesPath = getPackagesPath(confName);
|
||||
|
||||
if (!packagesPath) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '无法获取数据包路径'
|
||||
});
|
||||
}
|
||||
|
||||
// 组装完整的头文件路径
|
||||
const fullHeaderFilePath = path.join(packagesPath, headerFilePath);
|
||||
|
||||
// 调用findStructDefinition函数获取结构体成员信息
|
||||
const memberNames = await findStructDefinition(fullHeaderFilePath, structName);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
confName: confName,
|
||||
structName: structName,
|
||||
headerFilePath: headerFilePath,
|
||||
fullHeaderFilePath: fullHeaderFilePath,
|
||||
memberNames: memberNames,
|
||||
count: memberNames.length
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取结构体成员信息失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取结构体成员信息失败: ' + error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
@ -30,11 +30,11 @@ async function ensureDataDirectory() {
|
||||
// 获取接口列表
|
||||
router.get('/list', async (req, res) => {
|
||||
try {
|
||||
const { systemName, confID } = req.query;
|
||||
const { confID } = req.query;
|
||||
if (!confID) {
|
||||
return res.status(400).json({ error: 'ConfID 是必填字段' });
|
||||
}
|
||||
const interfaces = await getDataInterfaces(systemName, confID);
|
||||
const interfaces = await getDataInterfaces(confID);
|
||||
res.json(interfaces);
|
||||
} catch (error) {
|
||||
console.error('获取接口列表失败:', error);
|
||||
|
@ -1,7 +1,7 @@
|
||||
const { getDBConnection } = require('./file-utils');
|
||||
|
||||
// 获取接口列表
|
||||
function getDataInterfaces(systemName = 'XNSim', confID) {
|
||||
function getDataInterfaces(confID) {
|
||||
try {
|
||||
if (!confID) {
|
||||
throw new Error('ConfID 是必填字段');
|
||||
@ -10,6 +10,8 @@ function getDataInterfaces(systemName = 'XNSim', confID) {
|
||||
const db = getDBConnection(true);
|
||||
|
||||
const tableName = `DataInterface_${confID}`;
|
||||
|
||||
const systemName = 'XNSim'
|
||||
|
||||
// 查询所有接口
|
||||
const query = `
|
||||
|
Loading…
x
Reference in New Issue
Block a user