// 主脚本文件 - Scene Step 编辑器 function SceneStepEditor() { this.fileManager = new FileManager(); this.codeGenerator = new CodeGenerator(); this.currentSteps = []; this.stepFoldouts = []; this.actionFoldouts = []; this.initializeElements(); this.bindEvents(); this.loadInitialData(); } // 初始化DOM元素引用 SceneStepEditor.prototype.initializeElements = function() { this.fileSelect = document.getElementById('fileSelect'); this.newProcessBtn = document.getElementById('newProcessBtn'); this.stepsContainer = document.getElementById('stepsContainer'); this.saveBtn = document.getElementById('saveBtn'); this.generateCodeBtn = document.getElementById('generateCodeBtn'); // 模态框元素 this.newProcessModal = document.getElementById('newProcessModal'); this.newProcessName = document.getElementById('newProcessName'); this.confirmNewProcess = document.getElementById('confirmNewProcess'); this.cancelNewProcess = document.getElementById('cancelNewProcess'); this.confirmModal = document.getElementById('confirmModal'); this.confirmTitle = document.getElementById('confirmTitle'); this.confirmMessage = document.getElementById('confirmMessage'); this.confirmOk = document.getElementById('confirmOk'); this.confirmCancel = document.getElementById('confirmCancel'); this.codeModal = document.getElementById('codeModal'); this.generatedCode = document.getElementById('generatedCode'); this.copyCodeBtn = document.getElementById('copyCodeBtn'); this.closeCodeModal = document.getElementById('closeCodeModal'); } // 绑定事件 bindEvents() { // 文件选择 this.fileSelect.addEventListener('change', (e) => { this.loadProcessFile(e.target.value); }); // 新增流程 this.newProcessBtn.addEventListener('click', () => { this.showNewProcessModal(); }); // 保存 this.saveBtn.addEventListener('click', () => { this.saveConfiguration(); }); // 生成代码 this.generateCodeBtn.addEventListener('click', () => { this.generateProcessEventsCode(); }); // 新增流程模态框 this.confirmNewProcess.addEventListener('click', () => { this.createNewProcess(); }); this.cancelNewProcess.addEventListener('click', () => { this.hideNewProcessModal(); }); // 确认模态框 this.confirmOk.addEventListener('click', () => { this.hideConfirmModal(); if (this.confirmCallback) { this.confirmCallback(); } }); this.confirmCancel.addEventListener('click', () => { this.hideConfirmModal(); }); // 代码模态框 this.copyCodeBtn.addEventListener('click', () => { this.copyGeneratedCode(); }); this.closeCodeModal.addEventListener('click', () => { this.hideCodeModal(); }); // 点击模态框背景关闭 window.addEventListener('click', (e) => { if (e.target === this.newProcessModal) { this.hideNewProcessModal(); } if (e.target === this.confirmModal) { this.hideConfirmModal(); } if (e.target === this.codeModal) { this.hideCodeModal(); } }); // 键盘事件 document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { this.hideNewProcessModal(); this.hideConfirmModal(); this.hideCodeModal(); } }); } // 加载初始数据 loadInitialData() { // 尝试从localStorage加载 this.fileManager.loadFromLocalStorage(); // 更新文件下拉列表 this.updateFileDropdown(); // 加载默认文件 this.loadProcessFile(this.fileManager.getCurrentFileName()); } // 更新文件下拉列表 updateFileDropdown() { const fileNames = this.fileManager.getFileNames(); const currentFile = this.fileManager.getCurrentFileName(); this.fileSelect.innerHTML = ''; fileNames.forEach(fileName => { const option = document.createElement('option'); option.value = fileName; option.textContent = fileName; if (fileName === currentFile) { option.selected = true; } this.fileSelect.appendChild(option); }); // 更新保存按钮文本 this.saveBtn.textContent = `保存到 ${currentFile}`; } // 加载流程文件 loadProcessFile(fileName) { if (!fileName) return; if (this.fileManager.setCurrentFile(fileName)) { this.currentSteps = this.fileManager.loadProcessFile(fileName); this.stepFoldouts = new Array(this.currentSteps.length).fill(true); this.actionFoldouts = this.currentSteps.map(step => new Array(step.Actions.length).fill(true) ); this.updateFileDropdown(); this.renderSteps(); } } // 渲染步骤列表 renderSteps() { this.stepsContainer.innerHTML = ''; if (this.currentSteps.length === 0) { this.renderEmptyState(); return; } this.currentSteps.forEach((step, stepIndex) => { this.renderStep(step, stepIndex); }); } // 渲染空状态 renderEmptyState() { const emptyDiv = document.createElement('div'); emptyDiv.className = 'empty-state'; emptyDiv.innerHTML = `

暂无步骤

`; this.stepsContainer.appendChild(emptyDiv); } // HTML转义函数 escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // 渲染单个步骤 renderStep(step, stepIndex) { const stepDiv = document.createElement('div'); stepDiv.className = 'step-item'; // 确保折叠状态数组长度正确 this.ensureFoldoutLists(stepIndex); const isExpanded = this.stepFoldouts[stepIndex]; stepDiv.innerHTML = `
${stepIndex === this.currentSteps.length - 1 ? `` : '' }
`; this.stepsContainer.appendChild(stepDiv); // 渲染动作列表 if (isExpanded) { this.renderActions(stepIndex); } } // 确保折叠状态数组长度正确 ensureFoldoutLists(stepIndex) { while (this.stepFoldouts.length <= stepIndex) { this.stepFoldouts.push(true); } while (this.actionFoldouts.length <= stepIndex) { this.actionFoldouts.push([]); } } // 确保动作折叠状态数组长度正确 ensureActionFoldoutList(stepIndex, actionIndex) { this.ensureFoldoutLists(stepIndex); while (this.actionFoldouts[stepIndex].length <= actionIndex) { this.actionFoldouts[stepIndex].push(true); } } // 切换步骤折叠状态 toggleStepFoldout(stepIndex) { this.stepFoldouts[stepIndex] = !this.stepFoldouts[stepIndex]; this.renderSteps(); } // 切换动作折叠状态 toggleActionFoldout(stepIndex, actionIndex) { this.actionFoldouts[stepIndex][actionIndex] = !this.actionFoldouts[stepIndex][actionIndex]; this.renderActions(stepIndex); } // 更新步骤描述 updateStepDescription(stepIndex, value) { if (this.currentSteps[stepIndex]) { this.currentSteps[stepIndex].StepDescription = value; } } // 添加新步骤 addNewStep() { const newStep = DataUtils.createNewStep(); this.currentSteps.push(newStep); this.stepFoldouts.push(true); this.actionFoldouts.push([]); this.renderSteps(); } // 删除步骤 removeStep(stepIndex) { this.showConfirmModal( "确认删除", `确定要删除步骤 "${this.currentSteps[stepIndex].StepDescription}" 吗?`, () => { this.currentSteps.splice(stepIndex, 1); this.stepFoldouts.splice(stepIndex, 1); this.actionFoldouts.splice(stepIndex, 1); this.renderSteps(); } ); } // 渲染动作列表 renderActions(stepIndex) { const actionsContainer = document.getElementById(`actionsContainer_${stepIndex}`); if (!actionsContainer) return; const step = this.currentSteps[stepIndex]; actionsContainer.innerHTML = ''; if (step.Actions.length === 0) { const emptyDiv = document.createElement('div'); emptyDiv.className = 'empty-state'; emptyDiv.innerHTML = `

暂无动作

`; actionsContainer.appendChild(emptyDiv); return; } step.Actions.forEach((action, actionIndex) => { this.renderAction(stepIndex, action, actionIndex, actionsContainer); }); } // 渲染单个动作 renderAction(stepIndex, action, actionIndex, container) { this.ensureActionFoldoutList(stepIndex, actionIndex); const isExpanded = this.actionFoldouts[stepIndex][actionIndex]; const actionDiv = document.createElement('div'); actionDiv.className = 'action-item'; actionDiv.innerHTML = `
${actionIndex === this.currentSteps[stepIndex].Actions.length - 1 ? `` : '' } ${actionIndex > 0 ? `` : '' } ${actionIndex < this.currentSteps[stepIndex].Actions.length - 1 ? `` : '' }
`; container.appendChild(actionDiv); // 渲染动作详情 if (isExpanded) { this.renderActionDetails(stepIndex, actionIndex); } } // 渲染动作详情 renderActionDetails(stepIndex, actionIndex) { const actionContent = document.getElementById(`actionContent_${stepIndex}_${actionIndex}`); if (!actionContent) return; const action = this.currentSteps[stepIndex].Actions[actionIndex]; actionContent.innerHTML = `
`; this.renderActionTypeContent(stepIndex, actionIndex); } // 根据动作类型渲染不同内容 renderActionTypeContent(stepIndex, actionIndex) { const actionTypeContent = document.getElementById(`actionTypeContent_${stepIndex}_${actionIndex}`); if (!actionTypeContent) return; const action = this.currentSteps[stepIndex].Actions[actionIndex]; let content = ''; // 通用属性 content += `
`; if (action.ActionType === ProcessActionType.DEFAULT) { content += `
`; } else if (action.ActionType === ProcessActionType.JUDGMENT) { content += `
`; } else if (action.ActionType === ProcessActionType.MULTIPLE_CHOICE) { content += `
`; } actionTypeContent.innerHTML = content; // 渲染具体内容 if (action.ActionType === ProcessActionType.DEFAULT) { this.renderTargetObjects(stepIndex, actionIndex); } else if (action.ActionType === ProcessActionType.JUDGMENT) { this.renderJudgmentQuestions(stepIndex, actionIndex); } else if (action.ActionType === ProcessActionType.MULTIPLE_CHOICE) { this.renderMultipleChoiceQuestions(stepIndex, actionIndex); } } // 更新动作属性 updateActionProperty(stepIndex, actionIndex, property, value) { if (this.currentSteps[stepIndex] && this.currentSteps[stepIndex].Actions[actionIndex]) { this.currentSteps[stepIndex].Actions[actionIndex][property] = value; } } // 更新动作类型 updateActionType(stepIndex, actionIndex, newType) { const action = this.currentSteps[stepIndex].Actions[actionIndex]; if (action.ActionType !== newType) { action.ActionType = newType; // 清理不相关的数据 if (newType === ProcessActionType.DEFAULT) { action.JudgmentQuestions = []; action.MultipleChoiceQuestions = []; if (!action.TargetObjects) { action.TargetObjects = []; } } else if (newType === ProcessActionType.JUDGMENT) { action.TargetObjects = []; action.MultipleChoiceQuestions = []; action.IsSequential = false; if (!action.JudgmentQuestions) { action.JudgmentQuestions = []; } } else if (newType === ProcessActionType.MULTIPLE_CHOICE) { action.TargetObjects = []; action.JudgmentQuestions = []; action.IsSequential = false; if (!action.MultipleChoiceQuestions) { action.MultipleChoiceQuestions = []; } } this.renderActionTypeContent(stepIndex, actionIndex); } } // 添加新动作 addNewAction(stepIndex) { const newAction = DataUtils.createNewAction(); this.currentSteps[stepIndex].Actions.push(newAction); this.actionFoldouts[stepIndex].push(true); this.renderActions(stepIndex); } // 删除动作 removeAction(stepIndex, actionIndex) { const action = this.currentSteps[stepIndex].Actions[actionIndex]; this.showConfirmModal( "确认删除", `确定要删除动作 "${action.Title}" 吗?`, () => { this.currentSteps[stepIndex].Actions.splice(actionIndex, 1); this.actionFoldouts[stepIndex].splice(actionIndex, 1); this.renderActions(stepIndex); } ); } // 上移动作 moveActionUp(stepIndex, actionIndex) { if (actionIndex > 0) { const actions = this.currentSteps[stepIndex].Actions; const foldouts = this.actionFoldouts[stepIndex]; // 交换动作 [actions[actionIndex], actions[actionIndex - 1]] = [actions[actionIndex - 1], actions[actionIndex]]; // 交换折叠状态 [foldouts[actionIndex], foldouts[actionIndex - 1]] = [foldouts[actionIndex - 1], foldouts[actionIndex]]; this.renderActions(stepIndex); } } // 下移动作 moveActionDown(stepIndex, actionIndex) { const actions = this.currentSteps[stepIndex].Actions; if (actionIndex < actions.length - 1) { const foldouts = this.actionFoldouts[stepIndex]; // 交换动作 [actions[actionIndex], actions[actionIndex + 1]] = [actions[actionIndex + 1], actions[actionIndex]]; // 交换折叠状态 [foldouts[actionIndex], foldouts[actionIndex + 1]] = [foldouts[actionIndex + 1], foldouts[actionIndex]]; this.renderActions(stepIndex); } } // 渲染目标对象列表 renderTargetObjects(stepIndex, actionIndex) { const container = document.getElementById(`targetObjectsContainer_${stepIndex}_${actionIndex}`); if (!container) return; const action = this.currentSteps[stepIndex].Actions[actionIndex]; let content = '

目标对象列表

'; if (action.TargetObjects.length === 0) { content += `

暂无目标对象

`; } else { action.TargetObjects.forEach((target, targetIndex) => { content += `
目标对象 ${targetIndex + 1} ${targetIndex > 0 ? `` : '' } ${targetIndex < action.TargetObjects.length - 1 ? `` : '' }
`; }); content += `
`; } container.innerHTML = content; } // 添加目标对象 addTargetObject(stepIndex, actionIndex) { const newTarget = DataUtils.createNewTargetObject(); this.currentSteps[stepIndex].Actions[actionIndex].TargetObjects.push(newTarget); this.renderTargetObjects(stepIndex, actionIndex); } // 删除目标对象 removeTargetObject(stepIndex, actionIndex, targetIndex) { const target = this.currentSteps[stepIndex].Actions[actionIndex].TargetObjects[targetIndex]; this.showConfirmModal( "确认删除", `确定要删除目标对象 "${target.ObjectName}" 吗?`, () => { this.currentSteps[stepIndex].Actions[actionIndex].TargetObjects.splice(targetIndex, 1); this.renderTargetObjects(stepIndex, actionIndex); } ); } // 上移目标对象 moveTargetObjectUp(stepIndex, actionIndex, targetIndex) { if (targetIndex > 0) { const targets = this.currentSteps[stepIndex].Actions[actionIndex].TargetObjects; [targets[targetIndex], targets[targetIndex - 1]] = [targets[targetIndex - 1], targets[targetIndex]]; this.renderTargetObjects(stepIndex, actionIndex); } } // 下移目标对象 moveTargetObjectDown(stepIndex, actionIndex, targetIndex) { const targets = this.currentSteps[stepIndex].Actions[actionIndex].TargetObjects; if (targetIndex < targets.length - 1) { [targets[targetIndex], targets[targetIndex + 1]] = [targets[targetIndex + 1], targets[targetIndex]]; this.renderTargetObjects(stepIndex, actionIndex); } } // 更新目标对象属性 updateTargetObjectProperty(stepIndex, actionIndex, targetIndex, property, value) { const target = this.currentSteps[stepIndex].Actions[actionIndex].TargetObjects[targetIndex]; if (target) { target[property] = value; } } // 渲染判断题列表 renderJudgmentQuestions(stepIndex, actionIndex) { const container = document.getElementById(`judgmentQuestionsContainer_${stepIndex}_${actionIndex}`); if (!container) return; const action = this.currentSteps[stepIndex].Actions[actionIndex]; let content = '

判断题配置

'; if (action.JudgmentQuestions.length === 0) { content += `

暂无判断题

`; } else { action.JudgmentQuestions.forEach((question, questionIndex) => { content += `
题目 ${questionIndex + 1}
`; }); content += `
`; } container.innerHTML = content; } // 添加判断题 addJudgmentQuestion(stepIndex, actionIndex) { const newQuestion = DataUtils.createNewJudgmentQuestion(); this.currentSteps[stepIndex].Actions[actionIndex].JudgmentQuestions.push(newQuestion); this.renderJudgmentQuestions(stepIndex, actionIndex); } // 删除判断题 removeJudgmentQuestion(stepIndex, actionIndex, questionIndex) { this.showConfirmModal( "确认删除", "确定要删除这个判断题吗?", () => { this.currentSteps[stepIndex].Actions[actionIndex].JudgmentQuestions.splice(questionIndex, 1); this.renderJudgmentQuestions(stepIndex, actionIndex); } ); } // 更新判断题属性 updateJudgmentQuestionProperty(stepIndex, actionIndex, questionIndex, property, value) { const question = this.currentSteps[stepIndex].Actions[actionIndex].JudgmentQuestions[questionIndex]; if (question) { question[property] = value; } } // 渲染多选题列表 renderMultipleChoiceQuestions(stepIndex, actionIndex) { const container = document.getElementById(`multipleChoiceContainer_${stepIndex}_${actionIndex}`); if (!container) return; const action = this.currentSteps[stepIndex].Actions[actionIndex]; let content = '

多选题配置

'; if (action.MultipleChoiceQuestions.length === 0) { content += `

暂无多选题

`; } else { action.MultipleChoiceQuestions.forEach((question, questionIndex) => { content += `
题目 ${questionIndex + 1}
`; }); content += `
`; } container.innerHTML = content; // 渲染每个题目的选项 action.MultipleChoiceQuestions.forEach((question, questionIndex) => { this.renderMultipleChoiceOptions(stepIndex, actionIndex, questionIndex); }); } // 渲染多选题选项 renderMultipleChoiceOptions(stepIndex, actionIndex, questionIndex) { const container = document.getElementById(`optionsContainer_${stepIndex}_${actionIndex}_${questionIndex}`); if (!container) return; const question = this.currentSteps[stepIndex].Actions[actionIndex].MultipleChoiceQuestions[questionIndex]; let content = ''; question.Options.forEach((option, optionIndex) => { const isCorrect = question.CorrectAnswers.includes(option); content += `
`; }); content += `
`; container.innerHTML = content; } // 添加多选题 addMultipleChoiceQuestion(stepIndex, actionIndex) { const newQuestion = DataUtils.createNewMultipleChoice(); this.currentSteps[stepIndex].Actions[actionIndex].MultipleChoiceQuestions.push(newQuestion); this.renderMultipleChoiceQuestions(stepIndex, actionIndex); } // 删除多选题 removeMultipleChoiceQuestion(stepIndex, actionIndex, questionIndex) { this.showConfirmModal( "确认删除", "确定要删除这个多选题吗?", () => { this.currentSteps[stepIndex].Actions[actionIndex].MultipleChoiceQuestions.splice(questionIndex, 1); this.renderMultipleChoiceQuestions(stepIndex, actionIndex); } ); } // 更新多选题属性 updateMultipleChoiceQuestionProperty(stepIndex, actionIndex, questionIndex, property, value) { const question = this.currentSteps[stepIndex].Actions[actionIndex].MultipleChoiceQuestions[questionIndex]; if (question) { question[property] = value; } } // 添加多选题选项 addMultipleChoiceOption(stepIndex, actionIndex, questionIndex) { const question = this.currentSteps[stepIndex].Actions[actionIndex].MultipleChoiceQuestions[questionIndex]; question.Options.push(""); this.renderMultipleChoiceOptions(stepIndex, actionIndex, questionIndex); } // 删除多选题选项 removeMultipleChoiceOption(stepIndex, actionIndex, questionIndex, optionIndex) { const question = this.currentSteps[stepIndex].Actions[actionIndex].MultipleChoiceQuestions[questionIndex]; const option = question.Options[optionIndex]; // 从选项列表中删除 question.Options.splice(optionIndex, 1); // 从正确答案列表中删除(如果存在) const correctIndex = question.CorrectAnswers.indexOf(option); if (correctIndex > -1) { question.CorrectAnswers.splice(correctIndex, 1); } this.renderMultipleChoiceOptions(stepIndex, actionIndex, questionIndex); } // 更新多选题选项 updateMultipleChoiceOption(stepIndex, actionIndex, questionIndex, optionIndex, newValue) { const question = this.currentSteps[stepIndex].Actions[actionIndex].MultipleChoiceQuestions[questionIndex]; const oldValue = question.Options[optionIndex]; // 更新选项值 question.Options[optionIndex] = newValue; // 如果旧值在正确答案中,替换为新值 const correctIndex = question.CorrectAnswers.indexOf(oldValue); if (correctIndex > -1) { question.CorrectAnswers[correctIndex] = newValue; } } // 切换正确答案状态 toggleCorrectAnswer(stepIndex, actionIndex, questionIndex, optionIndex, isCorrect) { const question = this.currentSteps[stepIndex].Actions[actionIndex].MultipleChoiceQuestions[questionIndex]; const option = question.Options[optionIndex]; if (isCorrect) { // 添加到正确答案列表 if (!question.CorrectAnswers.includes(option)) { question.CorrectAnswers.push(option); } } else { // 从正确答案列表中删除 const index = question.CorrectAnswers.indexOf(option); if (index > -1) { question.CorrectAnswers.splice(index, 1); } } } // 显示新增流程模态框 showNewProcessModal() { this.newProcessName.value = "新流程"; this.newProcessModal.style.display = 'block'; this.newProcessName.focus(); this.newProcessName.select(); } // 隐藏新增流程模态框 hideNewProcessModal() { this.newProcessModal.style.display = 'none'; } // 创建新流程 createNewProcess() { const fileName = this.newProcessName.value.trim(); if (!fileName) { alert("请输入流程名称"); return; } const result = this.fileManager.createNewProcessFile(fileName); if (result.success) { this.hideNewProcessModal(); this.updateFileDropdown(); this.loadProcessFile(result.fileName); this.showAlert("新流程创建成功", `已创建新流程:${result.fileName}`); } else { alert(`创建失败:${result.error}`); } } // 显示确认模态框 showConfirmModal(title, message, callback) { this.confirmTitle.textContent = title; this.confirmMessage.textContent = message; this.confirmCallback = callback; this.confirmModal.style.display = 'block'; } // 隐藏确认模态框 hideConfirmModal() { this.confirmModal.style.display = 'none'; this.confirmCallback = null; } // 显示代码模态框 showCodeModal(code) { this.generatedCode.value = code; this.codeModal.style.display = 'block'; } // 隐藏代码模态框 hideCodeModal() { this.codeModal.style.display = 'none'; } // 复制生成的代码 copyGeneratedCode() { this.generatedCode.select(); document.execCommand('copy'); this.showAlert("复制成功", "代码已复制到剪贴板"); } // 显示提示信息 showAlert(title, message) { // 简单的alert实现,可以后续改为更美观的提示框 alert(`${title}\n${message}`); } // 保存配置 saveConfiguration() { const currentFileName = this.fileManager.getCurrentFileName(); this.showConfirmModal( "确认保存", `是否要保存当前配置到 ${currentFileName}?`, () => { const result = this.fileManager.saveProcessFile(currentFileName, this.currentSteps); if (result.success) { this.showAlert("保存成功", `配置已保存到 ${currentFileName}`); } else { alert(`保存失败:${result.error}`); } } ); } // 生成ProcessEvents代码 generateProcessEventsCode() { try { const currentFileName = this.fileManager.getCurrentFileName(); if (!this.currentSteps || this.currentSteps.length === 0) { alert("当前流程文件为空,无法生成代码"); return; } const code = this.codeGenerator.generateProcessEventsCode(currentFileName, this.currentSteps); this.showCodeModal(code); } catch (error) { alert(`生成代码失败:${error.message}`); } } } // 全局编辑器实例 let editor; // 页面加载完成后初始化编辑器 document.addEventListener('DOMContentLoaded', function() { editor = new SceneStepEditor(); });