diff --git a/src/scripts/plugin/CommandHandler.js b/src/scripts/plugin/CommandHandler.js new file mode 100644 index 000000000..0e3a4d28d --- /dev/null +++ b/src/scripts/plugin/CommandHandler.js @@ -0,0 +1,44 @@ +import { sendCommand } from '@/api/jmap/training'; +import router from '@/router'; + +class CommandHandle { + constructor() { + this.data = []; + this.instructionMap = {}; + } + + getInstruction(type) { + return this.instructionMap[type] || {}; + } + + getCommand(operates) { + const operate = operates[operates.length - 1]; + const instruction = this.getInstruction(operate.type); + if (operate && operate.send && instruction) { + return { + type: instruction.type, + params: operates + }; + } + + return null; + } + + execute(command) { + return new Promise((resolve, reject) => { + const group = router.currentRoute.query.group; + if (command) { + sendCommand(group, command).then((response) => { + resolve(response); + }).catch(error => { + reject(error); + }); + } else { + reject(); + } + + }); + } +} + +export default new CommandHandle(); diff --git a/src/scripts/plugin/OperateHandler.js b/src/scripts/plugin/OperateHandler.js new file mode 100644 index 000000000..cd2d62408 --- /dev/null +++ b/src/scripts/plugin/OperateHandler.js @@ -0,0 +1,203 @@ +import store from '@/store'; +import router from '@/router'; +import OperateConverter from '@/scripts/plugin/OperateConvert2Command'; +import CommandHandler from './CommandHandler.js'; +import { TrainingMode } from '@/scripts/ConstDic'; +import { getConverter } from '@/scripts/plugin/Converter/manager'; +import { sendTrainingNextStep } from '@/api/jmap/training'; +import { Message } from 'element-ui'; +import { OperationEvent } from '@/scripts/ConstDic'; +import LangStorage from '@/utils/lang'; + +const isNewCmd = true; +class OperateHandler { + constructor() { + this.operates = []; // 操作数据 + this.command = {}; // 命令对象 + } + + /** 操作组 */ + backStep(num) { + this.operates = this.operates.slice(0, num); + } + + /** 清空操作组 */ + cleanOperates() { + this.operates.splice(0, this.operates.length); + } + + /** 判断操作步骤是否正确 */ + judge (operate) { + const steps = this.getSteps(); + const order = this.getOrder(); + + let valid = false; + if (order < steps.length) { + const standard = steps[order]; + if (operate && standard && operate.code == standard.code && operate.type == standard.type && + operate.operation == standard.operation && + operate.val == standard.val) { + valid = true; + } + } + + return valid; + } + + getCommand(operate) { + let command = null; + if (operate.send) { + command = CommandHandler.getCommand(this.operates); + if (command && command.error) { + this.operates.pop(); + store.dispatch('training/setTempStep', null); + command = null; + } else if (command && command.over) { + OperateHandler.cleanOperates(); + store.dispatch('menuOperation/setButtonOperation', null); + } + + this.command = command; + } else { + if (operate.operation === OperationEvent.Command.cancel.menu.operation || operate.over) { + OperateHandler.cleanOperates(); + } + } + + return command; + } + + commandConvert(operate) { + const converter = getConverter(this.operates); + if (converter && converter.preHandle instanceof Function) { + Object.assign(operate, converter.preHandle(this.operates) || {}); + } + } + + /** 步骤前处理*/ + preProcessor(operate) { + // 按钮操作之后,第二步错误操作菜单的情况,需要直接返回 + if ((this.operates.length && operate.start === true) && (this.operates[0].type === 'mbm')) { + return false; + } + + // 如果是正常的第一步操作,需要清空operates数组 + if (operate.type === 'mbm' || operate.type === 'bar' || operate.start === true) { + this.cleanOperates(); + } + + // 记录步骤数据 + this.operates.push(operate); + + // 构造命令 + if (isNewCmd) { + this.command = this.getCommand(operate); + } else { + this.commandConvert(operate); + } + } + + /** 步骤后处理*/ + postProcessor(operate, valid) { + const basicInfo = store.getters['training/basicInfo']; + if (basicInfo.id && valid) { + // 发送记录步骤数据 + const group = router.currentRoute.query.group; + sendTrainingNextStep({ trainingId: basicInfo.id, operate: operate }, group); + } + + if (!valid) { + this.operates.pop(); + } else { + if (operate.cancel === true) { + this.cleanOperates(); + } + } + } + + /** 根据模式验证操作步骤 */ + validate(operate) { + this.preProcessor(operate); + + let valid = true; + if (TrainingMode.EDIT === this.getTrainingMode()) { + // 编辑制作模式 + if (this.getOperateBreakStatus()) { + valid = false; + const tip = LangStorage.getLang() == 'en' ? 'Please enter a hint and click next' : '请输入提示并点击下一步'; + Message.error(tip); + this.operates.pop(); + return valid; + } + + if (this.getTrainingStart()) { + store.dispatch('training/setTempStep', operate); + } + + } else if (TrainingMode.TEACH === this.getTrainingMode() || TrainingMode.PRACTICE === this.getTrainingMode()) { + // 教学模式/练习模式 + if (this.getTrainingStart()) { + valid = this.judge(operate); + } else { + this.cleanOperates(); + valid = false; + } + } + + this.postProcessor(operate, valid); + + return valid; + } + + handle(operate) { + return new Promise((resolve, reject) => { + const rtn = { valid: false, response: null }; + const valid = this.validate(operate); + + rtn.valid = valid; + + if (valid) { + if (isNewCmd) { + CommandHandler.execute(this.command).then(response => { + rtn.response = response; + resolve(rtn); + }).catch(error => { + reject(error); + }); + } else { + OperateConverter.convertAndSend(operate).then(response => { + rtn.response = response; + resolve(rtn); + }).catch(error => { + reject(error); + }); + } + + } else { + resolve(rtn); + } + }); + } + + getTrainingMode () { + return store.state.training.mode; + } + + getSteps() { + return store.state.training.steps; + } + + getOrder() { + return store.state.training.order; + } + + getTrainingStart() { + return store.state.training.started; + } + + getOperateBreakStatus () { + return store.state.menuOperation.break; + } +} + +export default new OperateHandler();