558 lines
20 KiB
JavaScript
Raw Normal View History

2025-04-28 12:25:20 +08:00
/**
* 对话框处理模块
* @type {module}
*/
import { isValidElementName } from './utils.js';
import { addElement, deleteElement, updateElementByPath } from './xml-handler.js';
import { createNewConfig, saveFileAs } from './api.js';
/**
* 显示添加元素对话框
* @param {Element} parentElement - 父元素
* @param {string} parentPath - 父元素路径
* @param {Document} xmlDoc - XML文档对象
* @param {Function} onSuccess - 成功回调函数
* @param {Element} context - 组件上下文用于访问shadowRoot
*/
export function showAddElementDialog(parentElement, parentPath, xmlDoc, onSuccess, context) {
// 创建模态框
const modal = document.createElement('div');
modal.className = 'modal';
modal.id = 'addElementModal';
modal.innerHTML = `
<div class="modal-content">
<div class="modal-header">
<div class="modal-title">添加元素</div>
<span class="close">&times;</span>
</div>
<div class="modal-body">
<div class="form-group">
<label for="elementName">元素名称</label>
<input type="text" id="elementName" class="form-control" placeholder="输入元素名称" />
<div id="elementNameError" class="error-message" style="display: none; font-size: 12px; margin-top: 5px;"></div>
</div>
<div class="form-group">
<label for="elementValue">元素值 <small>(如果需要)</small></label>
<input type="text" id="elementValue" class="form-control" placeholder="输入元素值" />
</div>
</div>
<div class="modal-footer">
<button id="cancelAddElement" class="action-button secondary">取消</button>
<button id="confirmAddElement" class="action-button">添加</button>
</div>
</div>
`;
// 获取shadowRoot
const shadowRoot = context.shadowRoot;
shadowRoot.appendChild(modal);
modal.style.display = 'block';
// 事件处理
const closeBtn = modal.querySelector('.close');
const cancelBtn = modal.querySelector('#cancelAddElement');
const confirmBtn = modal.querySelector('#confirmAddElement');
const nameInput = modal.querySelector('#elementName');
const valueInput = modal.querySelector('#elementValue');
const errorDiv = modal.querySelector('#elementNameError');
// 实时验证元素名称
nameInput.addEventListener('input', () => {
const name = nameInput.value.trim();
const isValid = isValidElementName(name);
if (!name) {
errorDiv.textContent = '元素名称不能为空';
errorDiv.style.display = 'block';
confirmBtn.disabled = true;
} else if (!isValid) {
errorDiv.textContent = '无效的元素名称。元素名称必须以字母或下划线开头,不能包含空格或特殊字符。';
errorDiv.style.display = 'block';
confirmBtn.disabled = true;
} else {
errorDiv.style.display = 'none';
confirmBtn.disabled = false;
}
});
const closeModal = () => {
modal.style.display = 'none';
shadowRoot.removeChild(modal);
};
closeBtn.addEventListener('click', closeModal);
cancelBtn.addEventListener('click', closeModal);
confirmBtn.addEventListener('click', () => {
const name = nameInput.value.trim();
const value = valueInput.value;
if (!name) {
alert('元素名称不能为空');
return;
}
if (!isValidElementName(name)) {
alert('无效的元素名称。元素名称必须以字母或下划线开头,不能包含空格或特殊字符。');
return;
}
// 添加元素
addElement(xmlDoc, parentElement, name, value);
// 调用成功回调
if (onSuccess && typeof onSuccess === 'function') {
onSuccess();
}
closeModal();
});
}
/**
* 显示编辑元素对话框
* @param {Element} element - 要编辑的元素
* @param {string} elementPath - 元素路径
* @param {Document} xmlDoc - XML文档对象
* @param {Function} onSuccess - 成功回调函数
* @param {Element} context - 组件上下文用于访问shadowRoot
*/
export function showEditElementDialog(element, elementPath, xmlDoc, onSuccess, context) {
// 创建模态框
const modal = document.createElement('div');
modal.className = 'modal';
modal.id = 'editElementModal';
modal.innerHTML = `
<div class="modal-content">
<div class="modal-header">
<div class="modal-title">编辑元素</div>
<span class="close">&times;</span>
</div>
<div class="modal-body">
<div class="form-group">
<label for="elementPath">元素路径</label>
<input type="text" id="elementPath" class="form-control" value="${elementPath}" readonly />
</div>
<div class="form-group">
<label for="elementValue">元素值</label>
<input type="text" id="elementValue" class="form-control" value="${element.textContent}" placeholder="输入元素值" />
</div>
</div>
<div class="modal-footer">
<button id="cancelEditElement" class="action-button secondary">取消</button>
<button id="confirmEditElement" class="action-button">保存</button>
</div>
</div>
`;
// 获取shadowRoot
const shadowRoot = context.shadowRoot;
shadowRoot.appendChild(modal);
modal.style.display = 'block';
// 事件处理
const closeBtn = modal.querySelector('.close');
const cancelBtn = modal.querySelector('#cancelEditElement');
const confirmBtn = modal.querySelector('#confirmEditElement');
const valueInput = modal.querySelector('#elementValue');
const closeModal = () => {
modal.style.display = 'none';
shadowRoot.removeChild(modal);
};
closeBtn.addEventListener('click', closeModal);
cancelBtn.addEventListener('click', closeModal);
confirmBtn.addEventListener('click', () => {
const value = valueInput.value;
// 更新元素值
updateElementByPath(xmlDoc, elementPath, value);
// 调用成功回调
if (onSuccess && typeof onSuccess === 'function') {
onSuccess();
}
closeModal();
});
}
/**
* 显示新建配置对话框
* @param {Function} onSuccess - 成功回调函数
* @param {Element} context - 上下文元素用于获取shadowRoot
*/
export function showNewConfigDialog(onSuccess, context) {
// 创建模态框
const modal = document.createElement('div');
modal.className = 'modal';
modal.id = 'newConfigModal';
modal.innerHTML = `
<div class="modal-content">
<div class="modal-header">
<div class="modal-title">创建新模型配置</div>
<span class="close">&times;</span>
</div>
<div class="modal-body">
<div class="form-group">
<label for="newFileName">文件名</label>
<input type="text" id="newFileName" class="form-control" placeholder="输入文件名 (例如: mymodel.mcfg)" />
</div>
</div>
<div class="modal-footer">
<button id="cancelNewConfig" class="action-button secondary">取消</button>
<button id="confirmNewConfig" class="action-button">创建</button>
</div>
</div>
`;
// 获取shadowRoot
const shadowRoot = context.shadowRoot;
shadowRoot.appendChild(modal);
modal.style.display = 'block';
// 事件处理
const closeBtn = modal.querySelector('.close');
const cancelBtn = modal.querySelector('#cancelNewConfig');
const confirmBtn = modal.querySelector('#confirmNewConfig');
const closeModal = () => {
modal.style.display = 'none';
shadowRoot.removeChild(modal);
};
closeBtn.addEventListener('click', closeModal);
cancelBtn.addEventListener('click', closeModal);
confirmBtn.addEventListener('click', async () => {
let fileName = modal.querySelector('#newFileName').value.trim();
if (!fileName) {
alert('文件名不能为空');
return;
}
// 如果文件名不以.mcfg结尾自动添加
if (!fileName.endsWith('.mcfg')) {
fileName += '.mcfg';
}
try {
const result = await createNewConfig(fileName);
if (onSuccess && typeof onSuccess === 'function') {
onSuccess(result);
}
closeModal();
} catch (error) {
if (error.message.includes('文件已存在')) {
if (confirm('文件已存在,是否覆盖?')) {
try {
const result = await createNewConfig(fileName, true);
if (onSuccess && typeof onSuccess === 'function') {
onSuccess(result);
}
closeModal();
} catch (retryError) {
alert('创建文件失败: ' + retryError.message);
}
}
} else {
alert('创建文件失败: ' + error.message);
}
}
});
}
/**
* 显示另存为对话框
* @param {string} xmlContent - XML内容
* @param {string} selectedFile - 当前选中的文件
* @param {Function} onSuccess - 成功回调函数
* @param {Element} context - 上下文元素用于获取shadowRoot
*/
export function showSaveAsDialog(xmlContent, selectedFile, onSuccess, context) {
// 创建模态框
const modal = document.createElement('div');
modal.className = 'modal';
modal.id = 'saveAsModal';
modal.innerHTML = `
<div class="modal-content">
<div class="modal-header">
<div class="modal-title">另存为</div>
<span class="close">&times;</span>
</div>
<div class="modal-body">
<div class="form-group">
<label for="saveAsFileName">文件名</label>
<input type="text" id="saveAsFileName" class="form-control" placeholder="输入文件名 (例如: mymodel.mcfg)" />
</div>
</div>
<div class="modal-footer">
<button id="cancelSaveAs" class="action-button secondary">取消</button>
<button id="confirmSaveAs" class="action-button">保存</button>
</div>
</div>
`;
// 获取shadowRoot
const shadowRoot = context.shadowRoot;
shadowRoot.appendChild(modal);
modal.style.display = 'block';
// 事件处理
const closeBtn = modal.querySelector('.close');
const cancelBtn = modal.querySelector('#cancelSaveAs');
const confirmBtn = modal.querySelector('#confirmSaveAs');
const closeModal = () => {
modal.style.display = 'none';
shadowRoot.removeChild(modal);
};
closeBtn.addEventListener('click', closeModal);
cancelBtn.addEventListener('click', closeModal);
confirmBtn.addEventListener('click', async () => {
let fileName = modal.querySelector('#saveAsFileName').value.trim();
if (!fileName) {
alert('文件名不能为空');
return;
}
// 如果文件名不以.mcfg结尾自动添加
if (!fileName.endsWith('.mcfg')) {
fileName += '.mcfg';
}
try {
const result = await saveFileAs(fileName, xmlContent, selectedFile);
if (onSuccess && typeof onSuccess === 'function') {
onSuccess(result);
}
closeModal();
} catch (error) {
if (error.message.includes('文件已存在')) {
if (confirm('文件已存在,是否覆盖?')) {
try {
const result = await saveFileAs(fileName, xmlContent, selectedFile, true);
if (onSuccess && typeof onSuccess === 'function') {
onSuccess(result);
}
closeModal();
} catch (retryError) {
alert('保存失败: ' + retryError.message);
}
}
} else {
alert('保存失败: ' + error.message);
}
}
});
}
/**
* 显示添加命令对话框
* @param {Element} rootElement - XML根元素
* @param {Document} xmlDoc - XML文档对象
* @param {Function} onSuccess - 成功回调函数
* @param {Element} context - 上下文元素用于获取shadowRoot
*/
export function showAddCommandDialog(rootElement, xmlDoc, onSuccess, context) {
// 创建模态框
const modal = document.createElement('div');
modal.className = 'modal';
modal.id = 'addCommandModal';
modal.innerHTML = `
<div class="modal-content">
<div class="modal-header">
<div class="modal-title">添加命令</div>
<span class="close">&times;</span>
</div>
<div class="modal-body">
<div class="form-group">
<label for="commandName">命令名称</label>
<input type="text" id="commandName" class="form-control" placeholder="输入命令名称" />
</div>
<div class="form-group">
<label for="commandCall">命令调用</label>
<input type="text" id="commandCall" class="form-control" placeholder="输入命令调用" />
</div>
<div class="form-group">
<label for="commandDescription">命令描述</label>
<input type="text" id="commandDescription" class="form-control" placeholder="输入命令描述" />
</div>
</div>
<div class="modal-footer">
<button id="cancelAddCommand" class="action-button secondary">取消</button>
<button id="confirmAddCommand" class="action-button">添加</button>
</div>
</div>
`;
// 获取shadowRoot
const shadowRoot = context.shadowRoot;
shadowRoot.appendChild(modal);
modal.style.display = 'block';
// 事件处理
const closeBtn = modal.querySelector('.close');
const cancelBtn = modal.querySelector('#cancelAddCommand');
const confirmBtn = modal.querySelector('#confirmAddCommand');
const closeModal = () => {
modal.style.display = 'none';
shadowRoot.removeChild(modal);
};
closeBtn.addEventListener('click', closeModal);
cancelBtn.addEventListener('click', closeModal);
confirmBtn.addEventListener('click', () => {
const name = modal.querySelector('#commandName').value.trim();
const call = modal.querySelector('#commandCall').value.trim();
const description = modal.querySelector('#commandDescription').value.trim();
if (!name) {
alert('命令名称不能为空');
return;
}
if (!call) {
alert('命令调用不能为空');
return;
}
try {
// 查找或创建CommandList元素
let commandListElement = rootElement.querySelector('CommandList');
if (!commandListElement) {
commandListElement = xmlDoc.createElement('CommandList');
rootElement.appendChild(commandListElement);
}
// 创建新Command元素
const commandElement = xmlDoc.createElement('Command');
commandElement.setAttribute('Name', name);
commandElement.setAttribute('Call', call);
commandElement.setAttribute('Description', description || `${name}描述`);
// 添加到CommandList
commandListElement.appendChild(commandElement);
// 调用成功回调
if (onSuccess && typeof onSuccess === 'function') {
onSuccess();
}
closeModal();
} catch (error) {
console.error('添加命令失败:', error);
alert('添加命令失败: ' + error.message);
}
});
}
/**
* 显示编辑命令对话框
* @param {Element} commandElement - 命令元素
* @param {number} index - 命令索引
* @param {Function} onSuccess - 成功回调函数
* @param {Element} context - 上下文元素用于获取shadowRoot
*/
export function showEditCommandDialog(commandElement, index, onSuccess, context) {
// 获取当前命令属性
const name = commandElement.getAttribute('Name') || '';
const call = commandElement.getAttribute('Call') || '';
const description = commandElement.getAttribute('Description') || '';
// 创建模态框
const modal = document.createElement('div');
modal.className = 'modal';
modal.id = 'editCommandModal';
modal.innerHTML = `
<div class="modal-content">
<div class="modal-header">
<div class="modal-title">编辑命令</div>
<span class="close">&times;</span>
</div>
<div class="modal-body">
<div class="form-group">
<label for="commandName">命令名称</label>
<input type="text" id="commandName" class="form-control" value="${name}" placeholder="输入命令名称" />
</div>
<div class="form-group">
<label for="commandCall">命令调用</label>
<input type="text" id="commandCall" class="form-control" value="${call}" placeholder="输入命令调用" />
</div>
<div class="form-group">
<label for="commandDescription">命令描述</label>
<input type="text" id="commandDescription" class="form-control" value="${description}" placeholder="输入命令描述" />
</div>
</div>
<div class="modal-footer">
<button id="cancelEditCommand" class="action-button secondary">取消</button>
<button id="confirmEditCommand" class="action-button">保存</button>
</div>
</div>
`;
// 获取shadowRoot
const shadowRoot = context.shadowRoot;
shadowRoot.appendChild(modal);
modal.style.display = 'block';
// 事件处理
const closeBtn = modal.querySelector('.close');
const cancelBtn = modal.querySelector('#cancelEditCommand');
const confirmBtn = modal.querySelector('#confirmEditCommand');
const closeModal = () => {
modal.style.display = 'none';
shadowRoot.removeChild(modal);
};
closeBtn.addEventListener('click', closeModal);
cancelBtn.addEventListener('click', closeModal);
confirmBtn.addEventListener('click', () => {
const newName = modal.querySelector('#commandName').value.trim();
const newCall = modal.querySelector('#commandCall').value.trim();
const newDescription = modal.querySelector('#commandDescription').value.trim();
if (!newName) {
alert('命令名称不能为空');
return;
}
if (!newCall) {
alert('命令调用不能为空');
return;
}
try {
// 更新命令属性
commandElement.setAttribute('Name', newName);
commandElement.setAttribute('Call', newCall);
commandElement.setAttribute('Description', newDescription || `${newName}描述`);
// 调用成功回调
if (onSuccess && typeof onSuccess === 'function') {
onSuccess();
}
closeModal();
} catch (error) {
console.error('编辑命令失败:', error);
alert('编辑命令失败: ' + error.message);
}
});
}