2025-04-28 12:25:20 +08:00

846 lines
34 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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

/**
* 模型组模块
*/
import { createModal, markEdited } from './utils.js';
import { getCPUAffinityOptions } from './environment-section.js';
/**
* 渲染模型组部分
* @param {HTMLElement} component - 组件实例
* @param {HTMLElement} container - 容器元素
* @param {Element} rootElement - XML根元素
*/
export function renderModelGroupsSection(component, 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', () => deleteModelGroup(component, 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 = getCPUAffinityOptions(component.xmlDoc);
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';
}
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
});
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';
}
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
});
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', () => {
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
});
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', () => {
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
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', () => {
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
});
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) => {
renderModelItem(component, modelsContainer, model, modelIndex, index);
});
}
groupItem.appendChild(modelsContainer);
// 添加模型按钮
const addModelButton = document.createElement('button');
addModelButton.className = 'add-button';
addModelButton.style.marginTop = '12px';
addModelButton.textContent = '添加模型';
addModelButton.title = '添加新模型到当前模型组';
addModelButton.addEventListener('click', () => showAddModelDialog(component, 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', () => showAddModelGroupDialog(component));
section.appendChild(addButton);
container.appendChild(section);
}
/**
* 渲染模型项
* @param {HTMLElement} component - 组件实例
* @param {HTMLElement} container - 容器元素
* @param {Element} model - 模型XML元素
* @param {number} modelIndex - 模型索引
* @param {number} groupIndex - 模型组索引
*/
function renderModelItem(component, container, model, modelIndex, groupIndex) {
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', () => deleteModel(component, groupIndex, 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[${groupIndex}]/Model[${modelIndex}]@${attr.name}`;
nameInput.title = '模型名称';
nameInput.addEventListener('change', () => {
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
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[${groupIndex}]/Model[${modelIndex}]@ClassName`;
classInput.title = '模型C++类名';
classInput.addEventListener('change', () => {
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
});
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[${groupIndex}]/Model[${modelIndex}]@Name`;
nameInput.title = '模型名称';
nameInput.addEventListener('change', () => {
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
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[${groupIndex}]/Model[${modelIndex}]@ClassName`;
classInput.title = '模型C++类名';
classInput.addEventListener('change', () => {
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
});
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[${groupIndex}]/Model[${modelIndex}]@${attr.name}`;
input.addEventListener('change', () => {
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
});
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);
}
});
container.appendChild(modelItem);
}
/**
* 显示添加模型组对话框
* @param {HTMLElement} component - 组件实例
*/
export function showAddModelGroupDialog(component) {
// 创建表单内容
const formContent = document.createElement('div');
formContent.className = 'modal-form';
// 获取可用的CPU核心选项
const availableCores = getCPUAffinityOptions(component.xmlDoc);
// 常用属性输入字段
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);
// 显示对话框
createModal(component.shadowRoot, '添加新模型组', formContent, () => {
const props = {
Name: nameInput.value,
FreqGroup: freqGroupInput.value,
Priority: priorityInput.value,
CPUAff: cpuAffSelect.value
};
addModelGroup(component, props);
});
}
/**
* 显示添加模型对话框
* @param {HTMLElement} component - 组件实例
* @param {number} groupIndex - 模型组索引
*/
export function showAddModelDialog(component, 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);
// 显示对话框
createModal(component.shadowRoot, '添加新模型', formContent, () => {
const props = {};
formContent.querySelectorAll('.form-input').forEach(input => {
props[input.name] = input.value;
});
addModel(component, groupIndex, props);
});
}
/**
* 添加模型组
* @param {HTMLElement} component - 组件实例
* @param {Object} properties - 属性对象
*/
export function addModelGroup(component, properties = {}) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(component.xmlContent, 'text/xml');
// 创建新的模型组
const newGroup = xmlDoc.createElement('ModelGroup');
// 设置默认属性
const defaultProps = {
Name: '新模型组',
FreqGroup: '0',
Priority: '99',
CPUAff: '0'
};
// 合并默认属性和传入的属性
const finalProps = { ...defaultProps, ...properties };
// 设置属性
for (const [name, value] of Object.entries(finalProps)) {
newGroup.setAttribute(name, value);
}
// 查找或创建ModelGroupList容器
let modelGroupList = xmlDoc.querySelector('ModelGroupList');
if (!modelGroupList) {
modelGroupList = xmlDoc.createElement('ModelGroupList');
xmlDoc.documentElement.appendChild(modelGroupList);
}
// 添加到ModelGroupList
modelGroupList.appendChild(newGroup);
// 重新生成XML内容
const serializer = new XMLSerializer();
component.xmlContent = serializer.serializeToString(xmlDoc);
// 更新编辑器
component.updateFileContent();
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
}
/**
* 删除模型组
* @param {HTMLElement} component - 组件实例
* @param {number} groupIndex - 模型组索引
*/
export function deleteModelGroup(component, groupIndex) {
if (confirm('确定要删除此模型组吗?此操作不可撤销。')) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(component.xmlContent, 'text/xml');
const modelGroups = xmlDoc.querySelectorAll('ModelGroup');
if (groupIndex >= 0 && groupIndex < modelGroups.length) {
const group = modelGroups[groupIndex];
group.parentNode.removeChild(group);
// 重新生成XML内容
const serializer = new XMLSerializer();
component.xmlContent = serializer.serializeToString(xmlDoc);
// 更新编辑器
component.updateFileContent();
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
}
}
}
/**
* 添加模型
* @param {HTMLElement} component - 组件实例
* @param {number} groupIndex - 模型组索引
* @param {Object} properties - 属性对象
*/
export function addModel(component, groupIndex, properties = {}) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(component.xmlContent, 'text/xml');
const modelGroups = xmlDoc.querySelectorAll('ModelGroup');
if (groupIndex >= 0 && groupIndex < modelGroups.length) {
const group = modelGroups[groupIndex];
// 创建新的模型元素
const newModel = xmlDoc.createElement('Model');
// 设置默认属性
const defaultProps = {
Name: '新模型',
ClassName: 'XNModel'
};
// 合并默认属性和传入的属性
const finalProps = { ...defaultProps, ...properties };
// 设置属性
for (const [name, value] of Object.entries(finalProps)) {
newModel.setAttribute(name, value);
}
// 添加到模型组
group.appendChild(newModel);
// 重新生成XML内容
const serializer = new XMLSerializer();
component.xmlContent = serializer.serializeToString(xmlDoc);
// 更新编辑器
component.updateFileContent();
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
}
}
/**
* 删除模型
* @param {HTMLElement} component - 组件实例
* @param {number} groupIndex - 模型组索引
* @param {number} modelIndex - 模型索引
*/
export function deleteModel(component, groupIndex, modelIndex) {
if (confirm('确定要删除此模型吗?此操作不可撤销。')) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(component.xmlContent, 'text/xml');
const modelGroups = xmlDoc.querySelectorAll('ModelGroup');
if (groupIndex >= 0 && groupIndex < modelGroups.length) {
const group = modelGroups[groupIndex];
const models = group.querySelectorAll('Model');
if (modelIndex >= 0 && modelIndex < models.length) {
const model = models[modelIndex];
model.parentNode.removeChild(model);
// 重新生成XML内容
const serializer = new XMLSerializer();
component.xmlContent = serializer.serializeToString(xmlDoc);
// 更新编辑器
component.updateFileContent();
component.isEdited = markEdited(component.shadowRoot, component.isEdited);
}
}
}
}