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

558 lines
20 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.

/**
* 对话框处理模块
* @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);
}
});
}