846 lines
34 KiB
JavaScript
Raw Normal View History

2025-04-28 12:25:20 +08:00
/**
* 模型组模块
*/
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);
}
}
}
}