558 lines
20 KiB
JavaScript
558 lines
20 KiB
JavaScript
/**
|
||
* 对话框处理模块
|
||
* @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">×</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">×</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">×</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">×</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">×</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">×</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);
|
||
}
|
||
});
|
||
} |