voiceTemplatesConfig = $config; Logger::debug("VoiceGenerationStrategy 初始化完成"); } /** * 执行语音生成 */ protected function doExecute(ProcessContext $context, ProcessNodeInterface $node): ProcessContext { // 如果存在流程中自定义语音,就直接输出 if (!empty($context->getVoice()->message)) { Logger::warn( "流程中存在自定义语音或存在多次设置语音,语音应该在 VoiceGenerationStrategy 策略中配置,否则不能拦截与自定义配置", new IllegalUsageException("In the existing process, there is custom voice, which should be configured in the VoiceGenerationStrategy strategy; otherwise, it cannot be intercepted and customized") ); return $context->builder()->voiceMessage($context->getVoice()->message)->build(); } // 如果已经有错误,生成错误语音 // 否则生成正常流程语音 $voice = !$context->isSuccess() ? $this->generateErrorVoice($context) : $this->generateNormalVoice($context, $node); // 应用语音模板 foreach ($context->getVoice()->templateParams as $key => $val) { $replaceVal = match (true) { is_array($val) => implode(',', $val), is_bool($val) => $val ? 'true' : 'false', is_null($val) => '', default => (string) $val }; $voice = str_replace('{' . $key . '}', $replaceVal, $voice); } Logger::debug("应用语音模板后的内容: {$voice}"); return $context->builder()->voiceMessage($voice)->build(); } /** * 生成正常流程语音 */ protected function generateNormalVoice(ProcessContext $context, ProcessNodeInterface $node): string { $stepCode = $node->getCode(); $stepName = $node->getName(); $processType = $context->getProcessType(); // 根据流程类型选择模板 $templateKey = $this->getTemplateKey($processType, $stepCode, $context); $templates = $this->voiceTemplatesConfig->getTemplates($templateKey); if (empty($templates)) { $templates = $this->voiceTemplatesConfig->normalWash; } // 优先使用自定义步骤语音(直接存储在对应模板key中) $voice = $templates[$stepCode] ?? $stepCode . '完成'; // 添加提醒信息 $remind = $this->getRemindMessage($context); if ($remind) { $voice .= $remind; } return $voice; } /** * 生成错误语音 */ protected function generateErrorVoice(ProcessContext $context): string { $errorMessage = $context->getVoice()->errorMessage; $errorTemplates = $this->voiceTemplatesConfig->voiceMessage; $errorMsg = $errorTemplates[$errorMessage->name] ?? $errorMessage->value; if (empty($errorMsg)) { $errorMsg = $context->getVoice()->message; Logger::debug("错误信息配置未命中,使用自定义语音: {$errorMsg}"); } else { Logger::debug("错误信息配置命中: {$errorMsg}"); } if (empty($errorMsg)) { Logger::error("配置文件与枚举信息中未找匹配到错误信息"); } return $errorMsg ?: '刷卡错误'; } /** * 流程类型到模板键的映射 */ protected const array PROCESS_TYPE_MAP = [ '机洗' => 'machine_wash', '机洗(晨洗)' => 'machine_wash', '机洗(加强)' => 'machine_wash', '测漏' => 'leak_test', '存储' => 'storage', ]; /** * 获取模板键 */ protected function getTemplateKey(string $processType, string $stepCode, ProcessContext $context): string { // 晨洗流程中的清洗/机洗步骤 if ($context->getMorningWash()->needMorningWash) { return 'morning_wash'; } // 从映射表中获取,默认返回 normal_wash return self::PROCESS_TYPE_MAP[$processType] ?? 'normal_wash'; } /** * 获取提醒信息 */ protected function getRemindMessage(ProcessContext $context): string { $reminds = []; if ($context->isLeakTestRemindNeeded()) { $reminds[] = ',清洗开始前,请测漏'; } if ($context->isStorageRemindNeeded()) { $reminds[] = ',未登记取出'; } return implode('', $reminds); } /** * 判断策略是否适用 */ public function isApplicable(ProcessContext $context, ProcessNodeInterface $node): bool { return true; } /** * 获取策略名称 */ public function getName(): string { return '语音生成策略'; } }