846 lines
34 KiB
JavaScript
846 lines
34 KiB
JavaScript
|
/**
|
|||
|
* 模型组模块
|
|||
|
*/
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|