使用easyswoole 框架开发的 新一代电话机器人开源PHP源码
项目地址:https://gitee.com/ddrjcode/robotphp
- 代理商页面演示地址
http://119.23.229.15:8080
用户名:c0508
密码:123456
包含 AI外呼管理,话术管理,CRM管理,坐席管理等功能。
- 管理员后台演示地址
http://119.23.229.15
用户名:admin
密码:123456
包含 线路管理,代理商管理等功能
AI外呼管理截图
话术管理截图
坐席页面
管理员页面
线路管理
机器人话术代码:
<?php/** * Created by PhpStorm. * User: WIN10 * Date: 2021/12/18 * Time: 16:04 */namespace App/Traits;use App/Model/Speech/SpeechLabelSynonym;use App/Model/Speech/SpeechNodeModel;use App/Model/Speech/SpeechProcessModel;use App/Model/Speech/SpeechProcessNodeSettingModel;use App/Model/SpeechMul/SpeechMulLabelSynonym;use App/Model/SpeechMul/SpeechMulProcessSettingModel;trait SpeechExamineTrait{ //主流程匹配关键词结果数组 public function getResultSynonym($speechId) { $resultSynonym = []; $synonymList = SpeechLabelSynonym::create()->getAll(["speech_id"=>$speechId]); foreach ($synonymList as $val){ if(isset($val["sls_name"])) { $resultSynonym[$val["node_id"]][$val["sls_keyword"]][] = $val["sls_name"]; } } return $resultSynonym; } //获取主流程的$nodesInfo信息 节点信息 //$processQueuesReal = []; //真实存在的主流程节点(只有节点才存在到这个主流程) public function getNodesInfoList($where) { $nodesInfo = [];//所有节点信息map=>(k,v) $processNodes = []; $processQueuesReal = []; //真实存在的主流程节点(只有节点才存在到这个主流程) //所有节点的信息 $nodesInfoList = SpeechNodeModel::create()->getAll($where); foreach ($nodesInfoList as $kk=>$vv) { $nodesInfo[$vv["node_id"]] = $vv; if(!isset($processNodes[$vv["process_id"]])){//真实存在 array_push($processQueuesReal,$vv["process_id"]); }else{ $processNodes[$vv["process_id"]] = []; } } return [$nodesInfo,$processQueuesReal]; } //$processNodesArr 所有节点的数组 //$processQueues 所有的流程按照顺序 public function getProcessQueues($where) { $processNodesArr = []; $processQueues = [];//所有的流程按照顺序 $processArray = SpeechProcessModel::create()->getAll($where,'process_id',["sort,process_id","ASC"]); foreach ($processArray as $a=>$item){ array_push($processQueues,$item["process_id"]); $processNodesArr[$item["process_id"]] = []; } return [$processNodesArr,$processQueues]; } //所有的参数节点流程 public function getArgArray($where) { $argList = SpeechProcessNodeSettingModel::create()->getAll($where,"set_key,set_value,node_id");//所有的参数节点流程 $argArray = []; foreach ($argList as $argK=>$argValue){ $argArray[$argValue["node_id"]][$argValue["set_key"]] = $argValue["set_value"]; } return $argArray; } //获取所有树的第一个节点集 // $nodes = SpeechNodeTreeModel::create()->getAll($where,'process_id,node_id,parent_id,nodes_id',["node_id","ASC"]); public function getTreeFirstNode($nodes) { $treeFirstNode = []; foreach ($nodes as $key=>$value) { if($value["parent_id"]==0){ $treeFirstNode[$value["process_id"]] = $value; } } return $treeFirstNode; } public function getMulTreeFirstNode($nodes) { $treeFirstNode = []; foreach ($nodes as $key=>$value) { if($value["parent_id"]==0){ $treeFirstNode[$value["process_mul_id"]] = $value; } } return $treeFirstNode; } //获取流程的节点的集 //$processNodesNode 子集 // $nodes = SpeechNodeTreeModel::create()->getAll($where,'process_id,node_id,parent_id,nodes_id',["node_id","ASC"]); //$resultSynonym 主流程匹配关键词结果数组集 //$childParent 父子节点数组 $childParent = SpeechSmallNodeRelationModel::create()->getColumn($where,"node_id","small_node_id"); //$processReal 真实按照顺序的主流程 //$processRealFlip 主流程反转主流程 //$treeFirstNode 获取所有树的第一个节点集 //$nodeSynonymList 匹配的关键词 //$targetLabel //$nodesInfo public function getProcessNodesNode($nodes,$processNodesArr,$nodesInfo,$resultSynonym,$childParent,$processReal,$targetLabel,$processRealFlip,$treeFirstNode,$nodeSynonymList) { //判断是否有相同的节点 $sameNodeList = []; $processNodesNode = []; //用一个权重数组去获取最终值吧(始终取最大的) $priorityArray = []; foreach ($nodes as $key=>$value) { $valueProcessId = $value["process_id"]; $processNodesArr[$valueProcessId][] = $value; $subFlowModel = []; $valueNodesId = $value["nodes_id"]; $valueParentId = $value["parent_id"]; $valueNodeId = $value["node_id"]; $priority = "0"; //分支权重 if($valueNodesId) { $word = $targetLabel[$valueNodesId]??""; if ($word) { $synonymCode = "W." . $word; $yesSynonym = []; $isMore = 0; $arrSubFlow = []; $synonymArray = []; switch ($word){ case "肯定": if(isset($resultSynonym[$childParent[$valueNodesId]]["yes"])) { $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["yes"]); } $priority = "5"; break; case "否定": if(isset($resultSynonym[$childParent[$valueNodesId]]["no"])) { $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["no"]); } $priority = "10"; break; case "拒绝": if(isset($resultSynonym[$childParent[$valueNodesId]]["reject"])) { $yesSynonym = array_values($resultSynonym[$childParent[$valueNodesId]]["reject"]); } $priority = "12"; break; case "默认": $priority = "2"; $isMore = 1; break; } if($isMore==0) {//不是默认 $synonymSystem = $yesSynonym ?: [$synonymCode]; foreach ($synonymSystem as $item){ $synonymArray[$item] = $word; } $arrSubFlow = [ "condition" => [ "text" => $synonymSystem ], "priority" => $priority, "description" => $word ]; }elseif($isMore==1){//是默认 $arrSubFlow = [ "condition" => [ "text" => ["any"] ], "priority" => $priority, "description" => $word ]; } if(!isset($priorityArray[$valueNodeId])) { $priorityArray[$valueNodeId] = $priority; }else{ if($priorityArray[$valueNodeId]<$priority){ $priorityArray[$valueNodeId] = $priority; } } if($nodesInfo[$valueNodeId]["info_talk_info"]) { //有信息的 if(!isset($sameNodeList[$valueProcessId][$valueParentId][$valueNodeId])) {//是否存在当前流程,当前父id的,节点id //判断是否当前节点参数是否为空 $subFlowModel["F" . $valueNodeId] = $arrSubFlow; if($isMore==0) {//不是默认 $nodeSynonymList[$valueNodeId] = $synonymArray; } $sameNodeList[$valueProcessId][$valueParentId][$valueNodeId] = $key+1; }else{ if(!isset($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"])) { $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"] = []; } if($isMore==0) {//非默认 //有text关键词的操作 if ($yesSynonym) { $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"] = array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"] ,$yesSynonym); } //没有关键词的操作 if (!$yesSynonym) { array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"], "W." . $word); } $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray); } if($isMore==1) {//默认// $processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"]= ["any"]; array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $valueNodeId]["condition"]["text"], "any"); } if(!isset($processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"])) { $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"] = $word; }else{ $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["description"] .= "," . $word; } $processNodesNode[$valueProcessId][$valueParentId]["F" . $valueNodeId]["priority"] = $priorityArray[$valueNodeId]; } } elseif(!$nodesInfo[$valueNodeId]["info_talk_info"] && $nodesInfo[$valueNodeId]["type_id"]==2){ $next = $nodesInfo[$value["node_id"]]["next"]; //跳转的条件 $nextId = $nodesInfo[$value["node_id"]]["next_id"];//流程id $process_id = $nodesInfo[$value["node_id"]]["process_id"]; //该流程id [$resReturnData,$returnKey,$resReturn] = $this->checkNextFlow($next,$nextId,$process_id,$processReal,$processRealFlip,$treeFirstNode,$arrSubFlow);//没有信息的就是跳转信息 if(!isset($sameNodeList[$valueProcessId][$valueParentId][$returnKey])) { //判断是否当前节点参数是否为空// $subFlowModel["F".$returnKey] = $resReturn; if($resReturn){ if(!isset($subFlowModel["F" . $returnKey]["condition"]["text"])) { $subFlowModel["F" . $returnKey]["condition"]["text"] = []; } if($isMore==0) {//非默认 if ($yesSynonym) { $subFlowModel["F" . $returnKey]["condition"]["text"] = array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym); } if (!$yesSynonym ) { array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "W." . $word); } } if($isMore==1) {//默认// $subFlowModel ["F" . $returnKey]["condition"]["text"]= ["any"]; array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "any"); } $subFlowModel["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId]; } $nodeSynonymList[$returnKey] = $synonymArray; $sameNodeList[$valueProcessId][$valueParentId][$returnKey] = $key+1; }else{ if(!isset($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"])) { $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = []; } if($isMore==0) {//非默认 if ($yesSynonym) { $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = array_merge($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym); $nodeSynonymList[$returnKey] = array_merge($nodeSynonymList[$returnKey],$synonymArray); } if (!$yesSynonym ) { array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "W." . $word); $nodeSynonymList[$returnKey] = array_merge($nodeSynonymList[$returnKey],$synonymArray); } } if($isMore==1) {//默认// $processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"]= ["any"]; array_push($processNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "any"); } if(isset($processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"])) { $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"] = $word; }else{ $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["description"] .= "," . $word; } $processNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId]; } } } } //是否存在当前的流程的process的id的,父id //不存在就是直接把subFlow赋值给他 if (!isset($processNodesNode[$valueProcessId][$valueParentId])) { $processNodesNode[$valueProcessId][$valueParentId] = $subFlowModel; } else { //存在就是数组连接一起 $processNodesNode[$valueProcessId][$valueParentId] = array_merge($processNodesNode[$valueProcessId][$valueParentId],$subFlowModel); } } return [$processNodesArr,$processNodesNode,$nodeSynonymList]; } //获取flow流程 //获取 $nodeSynonymList 匹配的关键词 //$firstNode //第一个主流程节点 //$version 版本 //$processReal 真实按照顺序的主流程 //$processRealFlip 主流程反转主流程 //$treeFirstNode 获取所有树的第一个节点集 //$nodeSynonymList 匹配的关键词 //$targetLabel //$nodesInfo //$processNodesNode 子集 public function getFlowList($flow,$processNodesArr,$nodeSynonymList,$version,$nodesInfo,$processNodesNode,$processReal,$processRealFlip,$treeFirstNode,$argArray,$allNodeWavKey,$allSettingsKey,$priority){ $count = 0; $firstNode = "";//第一个节点 foreach ($processNodesArr as $ke=>$ve){ foreach ($ve as $kkk=>$vvv){ $vvvNodeId = $vvv["node_id"]; if($count==0){ $flow["Start"] = [ 'action'=>'start', 'position'=>[ "x"=>2489, "y"=>72 ], "subflow"=>['F'.$vvvNodeId."_".$version=>new /stdClass()] ]; } $count++; $arg = []; $arg["action"] = "cti_play_and_detect_speech"; if($count==1){ $firstNode = $vvvNodeId."_".$version; } //模式 $argM = $argArray[$vvvNodeId]["moshi"]??"1"; if(isset($allSettingsKey[$vvvNodeId]['interrupt']) && $allSettingsKey[$vvvNodeId]['interrupt']) { $argM = "2"; } $argLuZao = $argArray[$vvvNodeId]["luzao"]??""; $argKaiShi = $argArray[$vvvNodeId]["kaishi"]??""; $argTingZhi = $argArray[$vvvNodeId]["tingzhi"]??""; $argDengDai = $argArray[$vvvNodeId]["dengdai"]??""; $argZuiDa = $argArray[$vvvNodeId]["zuida"]??""; $argCanShu = $argArray[$vvvNodeId]["canshu"]??""; $argLuYin = $argArray[$vvvNodeId]["luyin"]??""; //挂机不需要这些参数 if($nodesInfo[$vvvNodeId]['next']!=1) { $arg["filter"] = [ "text" => "S", "dtmf" => "none" ]; if ($priority == 1) { $arg["kb_priority"] = 0; } elseif ($priority == 2) { $arg["kb_priority"] = 1; } $arg["timeoutplaybacks"] = []; $arg["timeoutrepetition"] = ""; $arg["mismatchplaybacks"] = []; $arg["mismatchrepetition"] = "1"; $arg["globalflow"] = [ "all" ]; }else{//挂机节点不起用asr $argM = 0; } $arg["argument"] = "'$argM' '16' '' '$argLuZao' '' '$argKaiShi' '$argTingZhi' '$argDengDai' '$argZuiDa' '' '$argCanShu' '$argLuYin' '' ''"; $arg["position"] = [ "x"=>$nodesInfo[$vvvNodeId]["node_x"], "y"=>$nodesInfo[$vvvNodeId]["node_y"] ]; $arg["description"] = $nodesInfo[$vvvNodeId]["info_title"]; if(isset($allNodeWavKey[$vvvNodeId]) && $allNodeWavKey[$vvvNodeId]) { $arg["playbacks"] = [$allNodeWavKey[$vvvNodeId]]; }else{ $arg["playbacks"] = [$nodesInfo[$vvvNodeId]["info_talk_info"]]; } $arg["kb"] = 'C1'; if(isset($processNodesNode[$vvv["process_id"]][$vvvNodeId])) { $arg["subflow"] = $processNodesNode[$vvv["process_id"]][$vvvNodeId]; }else{ $next = $nodesInfo[$vvvNodeId]["next"]; //跳转的条件 $nextId = $nodesInfo[$vvvNodeId]["next_id"];//流程id $processId = $nodesInfo[$vvvNodeId]["process_id"]; //该流程id [$arg["subflow"],$returnKey,$resReturn] = $this->checkNextFlow($next,$nextId,$processId,$processReal,$processRealFlip,$treeFirstNode); } if($nodesInfo[$vvvNodeId]["info_talk_info"]) {//如果是跳转节点,没有输入声音就是不输入 if($count==1){ $vvvNodeId .= "_".$version; } $flow["F" . $vvvNodeId] = $arg; } } } return [$flow,$nodeSynonymList,$firstNode]; } //生成一个挂机节点 public function addEndPoints($flow) { /** * 生成一个挂机节点 */ $endPointsArray = [ 'action'=>'hangup', 'position'=>[ "x"=>67, "y"=>33 ] ]; $flow["F9999999999999999999"]=$endPointsArray; return $flow; } //生成一个等待用户回答节点 public function addWaitPoints($flow) { /** * 生成一个挂机节点 */ $endWaitArray = [ 'action'=>"cti_play_and_detect_speech", "argument"=>"'1' '16' '' '' '' '' '' '' '' '' '' '' '' ''", "position"=>[ "x"=>391833, "y"=>2372 ], "playbacks"=>[], "description"=>"", "sourceflowdepth"=>"1", "globalflow"=>[ "all" ], "kb" => 'C1', "kb_priority"=>2, "condition"=> [ "complete"=> [], "text"=> [] ], "timeoutrepetition"=>"", "mismatchplaybacks"=> [], "subflow"=>[] ]; $flow["F88888888888888888888"]=$endWaitArray;// $flow["F66666666666666666666"]=[// "action"=> "return",// "position"=> [// "x"=> 2263,// "y"=> 492// ]// ]; return $flow; } //生成一个挂机播放节点 public function addHangUpPlayContent($flow,$nodeId,$playbacks) { $hangUpArray = [ 'action'=>"cti_play_and_detect_speech", "argument"=>"'0' '16' '' '' '' '' '' '' '' '' '' '' '' ''", "position"=>[ "x"=>391833, "y"=>2372 ], "playbacks"=>$playbacks, "description"=>"", "sourceflowdepth"=>"1", "condition"=> [ "text"=> [] ], "mismatchplaybacks"=> [], "subflow"=>[ "F9999999999999999999"=> [ "condition"=>[ "complete"=> [ "any" ], ], ] ] ]; $flow["F".$nodeId] = $hangUpArray; return $flow; } //生成一个挂机播放节点 public function addHangUpPlay($flow) { $hangUpArray = [ 'action'=>"cti_play_and_detect_speech", "argument"=>"'0' '16' '' '' '' '' '' '' '' '' '' '' '' ''", "position"=>[ "x"=>391833, "y"=>2372 ], "playbacks"=>[], "description"=>"", "sourceflowdepth"=>"1", "condition"=> [ "text"=> [] ], "mismatchplaybacks"=> [], "subflow"=>[ "F9999999999999999999"=> [ "condition"=>[ "text"=> [ "any" ], ], ] ] ]; $flow["F5555555555555555555555"] = $hangUpArray; return $flow; } public function addWaitSubPoints(){ return [ "F9999999999999999999"=> [ "condition"=>[ "complete"=> [ "timeout()" ] ], "description"=> "静音挂断" ], "F66666666666666666666"=>[ "condition"=> [ "complete"=> [], "text"=> [ "F.+" ] ], "description"=> "有声音返回" ] ]; } //生成一个挂机节点 public function addHangUpPoints() { $endPointsArray["F9999999999999999999"] = [ 'condition'=>[ 'complete'=> [ "any" ] ], ]; return $endPointsArray; } //跳转到指定主流程 public function toMainFlow($flowId) { $arg["F".$flowId]= [ "condition"=>[ "complete"=> [], "text"=>[ "any" ], "description"=>"" ] ]; return $arg; } //跳转到指定多伦会话 public function toMulFlow($flowId) { $arg["F".$flowId."_".$flowId]= [ "condition"=>[ "complete"=> [], "text"=>[ "any" ], "description"=>"" ] ]; return $arg; } //判断主流程下个流程的节点 public function checkNextFlow($next,$nextId,$process_id,$processReal,$processRealFlip,$treeFirstNode,$arrSubFlow=[]) { $array = []; $keyNext = $processRealFlip[$process_id]+1;//下一个next $hangUp = $arrSubFlow?:["description"=>"无效回答", "condition"=>["text"=>["any"]]]; $nextProcess = $arrSubFlow?: ["condition" => ["text" => ["any"]], "description" => "跳转下一个流程"]; $keyReturn = ""; $resReturn = ""; switch ($next) { case 0: case 2: if(isset($processReal[$keyNext])){ $array["F" . $treeFirstNode[$processReal[$keyNext]]["node_id"]] = $nextProcess; $keyReturn = $treeFirstNode[$processReal[$keyNext]]["node_id"]; $resReturn = $nextProcess; }else{ $array["F9999999999999999999"] = $hangUp; $keyReturn = "9999999999999999999"; $resReturn = $hangUp; } break; case 1: $array["F9999999999999999999"] = $hangUp; $keyReturn = "9999999999999999999"; $resReturn = $hangUp; break; case 3: if(isset($treeFirstNode[$nextId])) { $fistNode = $treeFirstNode[$nextId]; $array["F" . $fistNode["node_id"]] = $nextProcess; $keyReturn = $fistNode["node_id"]; $resReturn = $nextProcess; }else{ $array["F9999999999999999999"] = $hangUp; $keyReturn = "9999999999999999999"; $resReturn = $hangUp; } break; case 4://返回接口 $keyReturn = substr(microtime(true),2,8).rand(0,99); $resReturn= [ 'action' =>'return', 'position'=>[ 'x'=>4085, 'y'=>377 ], ]; $array["F".$keyReturn] = $resReturn; break; } return [$array,$keyReturn,$resReturn]; } //多伦会话匹配关键词结果数组 public function getMulResultSynonym($speechId) { $resultSynonym = []; $synonymList = SpeechMulLabelSynonym::create()->getAll(["speech_id"=>$speechId]); foreach ($synonymList as $val){ if(isset($val["sls_name"])) { $resultSynonym[$val["node_mul_id"]][$val["sls_keyword"]][] = $val["sls_name"]; } } return $resultSynonym; } //获取所有子节点 public function getMulProcessNodesNode($flow,$nodesMul,$resultMulSynonym,$childMulParent,$nodesMulInfo,$targetMulLabel,$nodeSynonymList,$treeFirstNode) { //判断是否有相同的节点 $sameNodeList = []; $processMulNodesNode = []; $processMulNodesArr = [];//所有全局话术的根节点 //用一个权重数组去获取最终值吧(始终取最大的) $priorityArray = []; foreach ($nodesMul as $key=>$value) { $valueProcessId = $value["process_mul_id"]; $processMulNodesArr[$valueProcessId][] = $value; $subFlowModel = []; $valueNodesId = $value["nodes_id"]; $valueParentId = $value["parent_id"]; $valueNodeId = "F".$value["node_mul_id"]."_".$value["node_mul_id"]; $priority = "0"; if($valueNodesId) { $word = $targetMulLabel[$valueNodesId]??""; if ($word) { $synonymCode = "W." . $word; $yesSynonym = []; $isMore = 0; $arrSubFlow = []; $synonymArray = []; switch ($word){ case "肯定": if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["yes"])) { $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["yes"]); } $priority = "5"; break; case "否定": if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["no"])) { $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["no"]); } $priority = "10"; break; case "拒绝": if(isset($resultMulSynonym[$childMulParent[$valueNodesId]]["reject"])) { $yesSynonym = array_values($resultMulSynonym[$childMulParent[$valueNodesId]]["reject"]); } $priority = "12"; break; case "默认": $priority = "2"; $isMore = 1; break; } if($isMore==0) {//不是默认 $synonymSystem = $yesSynonym ?: [$synonymCode]; foreach ($synonymSystem as $item){ $synonymArray[$item] = $word; } $arrSubFlow = [ "condition" => [ "text" => $synonymSystem ], "priority" => $priority, "description" => $word ]; }elseif($isMore==1){//是默认 $arrSubFlow = [ "condition" => [ "text" => ["any"] ], "priority" => $priority, "description" => $word ]; } if(!isset($priorityArray[$valueNodeId])) { $priorityArray[$valueNodeId] = $priority; }else{ if($priorityArray[$valueNodeId]<$priority){ $priorityArray[$valueNodeId] = $priority; } } if($nodesMulInfo[$value["node_mul_id"]]["info_talk_info"]) { //有信息的(多伦会话只要有信息判断) if(!isset($sameNodeList[$valueProcessId][$valueParentId][$valueNodeId])) {//是否存在当前流程,当前父id的,节点id //判断是否当前节点参数是否为空 $subFlowModel[$valueNodeId] = $arrSubFlow; if($isMore==0) {//不是默认 $nodeSynonymList[$valueNodeId] = $synonymArray; } $sameNodeList[$valueProcessId][$valueParentId][$valueNodeId] = $key+1; }else{ if(!isset($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"])) { $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"] = []; } if($isMore==0) {//非默认 if ($yesSynonym) { $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"] ,$yesSynonym); } if (!$yesSynonym) { array_push($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"], "W." . $word); } $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray); } if($isMore==1) {//默认// $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"]= ["any"]; array_push($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["condition"]["text"], "any"); } if(!isset($processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"])) { $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"] = $word; }else{ $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["description"] .= "," . $word; } $processMulNodesNode[$valueProcessId][$valueParentId][$valueNodeId]["priority"] = $priorityArray[$valueNodeId]; } } elseif(!$nodesMulInfo[$value["node_mul_id"]]["info_talk_info"] && $nodesMulInfo[$value["node_mul_id"]]["type_id"]==2){ $next = $nodesMulInfo[$value["node_mul_id"]]["next"]; //跳转的条件 $nextId = $nodesMulInfo[$value["node_mul_id"]]["next_id"];//流程id [$arrSubFlows,$returnKey,$resReturn,$flow] = $this->checkNextMulFlow($next,$nextId,$treeFirstNode,$flow); if(!isset($sameNodeList[$valueProcessId][$valueParentId][$returnKey])) { //判断是否当前节点参数是否为空 if($resReturn){ if(!isset($subFlowModel["F" . $returnKey]["condition"]["text"])) { $subFlowModel["F" . $returnKey]["condition"]["text"] = []; } if($isMore==0) {//非默认 if ($yesSynonym) { $subFlowModel["F" . $returnKey]["condition"]["text"] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym); } if (!$yesSynonym ) { array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "W." . $word); } } if($isMore==1) {//默认// $subFlowModel ["F" . $returnKey]["condition"]["text"]= ["any"]; array_push($subFlowModel ["F" . $returnKey]["condition"]["text"], "any"); } $subFlowModel["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId]; } if($isMore==0) {//不是默认 $nodeSynonymList[$valueNodeId] = $synonymArray; }// $subFlowModel["F".$returnKey] = $resReturn; $sameNodeList[$valueProcessId][$valueParentId][$returnKey] = $key+1; }else{ if(!isset($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"])) { $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = []; } if($isMore==0) {//非默认 if ($yesSynonym) { $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"],$yesSynonym); } if (!$yesSynonym ) { array_push($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "W." . $word); } $nodeSynonymList[$valueNodeId] = array_merge($nodeSynonymList[$valueNodeId],$synonymArray); } if($isMore==1) {//默认// $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"]= ["any"]; array_push($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["condition"]["text"], "any"); } if(!isset($processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"])){ $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"] = ",".$word; }else{ $processMulNodesNode[$valueProcessId][$valueParentId] ["F" . $returnKey]["description"] .= ",".$word; } $processMulNodesNode[$valueProcessId][$valueParentId]["F" . $returnKey]["priority"] = $priorityArray[$valueNodeId]; } } } } if (!isset($processMulNodesNode[$valueProcessId][$valueParentId])) { $processMulNodesNode[$valueProcessId][$valueParentId] = $subFlowModel; } else { $processMulNodesNode[$valueProcessId][$valueParentId] = array_merge($processMulNodesNode[$valueProcessId][$valueParentId],$subFlowModel); } } return [$processMulNodesNode,$nodeSynonymList,$processMulNodesArr,$flow]; } //获取所有的 public function getMulFlowList($flow,$processMulNodesArr,$argMulArray,$nodesMulInfo,$treeFirstNode,$processMulNodesNode,$allNodeMulWavKey,$priority) { $count = 0; foreach ($processMulNodesArr as $ke=>$ve){ foreach ($ve as $kkk=>$vvv){ $vvvNodeId = $vvv["node_mul_id"]; $count++; $arg = []; $arg["action"] = "cti_play_and_detect_speech"; //模式 $argM = $argMulArray[$vvvNodeId]["moshi"]??"1"; $argLuZao = $argMulArray[$vvvNodeId]["luzao"]??""; $argKaiShi = $argMulArray[$vvvNodeId]["kaishi"]??""; $argTingZhi = $argMulArray[$vvvNodeId]["tingzhi"]??""; $argDengDai = $argMulArray[$vvvNodeId]["dengdai"]??""; $argZuiDa = $argMulArray[$vvvNodeId]["zuida"]??""; $argCanShu = $argMulArray[$vvvNodeId]["canshu"]??""; $argLuYin = $argMulArray[$vvvNodeId]["luyin"]??""; //挂机不需要这些参数 if($nodesMulInfo[$vvvNodeId]['next']!=1) { $arg["filter"] = [ "text" => "S", "dtmf" => "none" ]; if ($priority == 1) { $arg["kb_priority"] = 0; } elseif ($priority == 2) { $arg["kb_priority"] = 1; } $arg["timeoutplaybacks"] = []; $arg["timeoutrepetition"] = ""; $arg["mismatchplaybacks"] = []; $arg["mismatchrepetition"] = "1"; $arg["kb"] = 'C1'; $arg["globalflow"] = [ "all" ]; }else{//挂机节点不起用asr $argM = 0; } $arg["argument"] = "'$argM' '16' '' '$argLuZao' '' '$argKaiShi' '$argTingZhi' '$argDengDai' '$argZuiDa' '' '$argCanShu' '$argLuYin' '' ''"; $arg["position"] = [ "x"=>$nodesMulInfo[$vvvNodeId]["node_x"], "y"=>$nodesMulInfo[$vvvNodeId]["node_y"]]; $arg["description"] = $nodesMulInfo[$vvvNodeId]["info_title"]; if(isset($allNodeMulWavKey[$vvvNodeId]) && $allNodeMulWavKey[$vvvNodeId]) { $arg["playbacks"] = [$allNodeMulWavKey[$vvvNodeId]]; }else{ $arg["playbacks"] = [$nodesMulInfo[$vvvNodeId]["info_talk_info"]]; } if(isset($processMulNodesNode[$vvv["process_mul_id"]][$vvvNodeId])) { $arg["subflow"] = $processMulNodesNode[$vvv["process_mul_id"]][$vvvNodeId]; }else{ $next = $nodesMulInfo[$vvvNodeId]["next"]; //跳转的条件 $nextId = $nodesMulInfo[$vvvNodeId]["next_id"];//流程id [$arg["subflow"],$returnKey,$resReturn,$flow] = $this->checkNextMulFlow($next,$nextId,$treeFirstNode,$flow); } if($nodesMulInfo[$vvvNodeId]["info_talk_info"]) {//如果是跳转节点,没有输入声音就是不输入 $keyNode = "F".$vvvNodeId."_".$vvvNodeId; $flow[$keyNode] = $arg; } } } return $flow; } //多伦会话下一步 public function checkNextMulFlow($next,$nextId,$treeFirstNode,$flow) { $array = []; $info = ["description"=>"默认回答", "condition"=>["text"=>["any"]]]; $keyReturn = ""; $resReturn = ""; switch ($next) { case 0://普通节点默认挂机 case 1://挂机 $hangK = substr(microtime(true),2,8).rand(0,99); $hangKey = "F".$hangK; $array[$hangKey] = $info; $keyReturn = $hangK; $resReturn = $info; //挂机节点需要添加挂机节点 /** * 生成一个挂机节点 */ $endPointsArray = [ 'action'=>'hangup', 'position'=>[ "x"=>67, "y"=>33 ] ]; $flow[$hangKey]=$endPointsArray; break; case 2://跳转指定多伦会话 $hangKey = "F".$nextId."_".$nextId; $array[$hangKey] = $info; $keyReturn = $nextId."_".$nextId; $resReturn = $info; break; case 3://指定主流程 $hangKey = "F".$treeFirstNode[$nextId]['node_id']; $array[$hangKey] = $info; $keyReturn = $treeFirstNode[$nextId]['node_id']; $resReturn = $info; break; } return [$array,$keyReturn,$resReturn,$flow]; } //所有的多伦会话节点流程 public function getMulArgArray($where) { $argList = SpeechMulProcessSettingModel::create()->getAll($where,"set_key,set_value,node_mul_id");//所有的参数节点流程 $argArray = []; foreach ($argList as $argK=>$argValue){ $argArray[$argValue["node_mul_id"]][$argValue["set_key"]] = $argValue["set_value"]; } return $argArray; }}