ysyt-agent-sdk 1.1.42 → 1.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -911,4 +911,4 @@ Bs=Ts,function(){var t="input is invalid type",s="object"==typeof window,i=s?win
911
911
  `:""}
912
912
  </div>
913
913
  </my-popover>
914
- `;mt(s,this.rttHTML)}}class Ps{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const A=await navigator.mediaDevices.enumerateDevices();if(A.some(A=>"audioinput"===A.kind&&""!==A.label))return null;return await navigator.mediaDevices.getUserMedia({audio:!0})}catch(A){return console.warn("获取音频权限失败:",A),null}}static show(A,e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(A,{body:e,tag:`xy-global-notification${(new Date).getTime()}`,renotify:!0});i.onclick=()=>{window.focus(),i.close(),t?.()},setTimeout(()=>i.close(),1e3*(s||3))}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}const zs=console.log,Xs=(...A)=>{Ve.logBuiltinEnabled&&zs(...A)};let _s=null;class $s{constructor(A,e){this.url=A,this.onOpenCallback=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Ks,this.sipClient=null,this.pendingMessages=new Map,this.initWebSocket()}static getInstance({url:A,sipClient:e,onOpen:t}){if(!_s){if(!A)throw new Error("WebSocket 尚未初始化");_s=new $s(A,t),_s.sipClient=e}return _s}setSipClient(A){this.sipClient=A}stateIdleChange(){const{state:A}=Ve.stateObject;A!==exports.AgentStatus.IDLE&&this.apiClient._changeState({data:{...Ve.stateBeforeChange,state_name:Ve.stateBeforeChange.state===exports.AgentStatus.IDLE?"空闲":"忙碌"}})}inCallAutoAnswer(){const{soft_device_auto_answer:A,auto_answer_time:e}=Ve.agentInfo,t=1===A,s=le.get("direction");if(t&&s===exports.DirectionEnum.INCOMING){const A=Number(e)||0;A>0&&(Ve.autoAnswerTimer=setTimeout(()=>{this.sipClient?.answerCall(),Ve.autoAnswerTimer=null},1e3*A))}}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{le.updateCustomerInfo(A.data||{phone:A.data.phone,is_vip:0,customer_name:"未知客户",city:"未知",province:"未知",contact_count:0,in_contact_count:0,trace_id:A.data.trace_id,contact_count_month:0,in_contact_count_month:0})}})}catch(A){}}putAgentState(A,e){if(!A)return;if(5===e)return void this.stateIdleChange();Ve.sessionId="";const{post_call_process_time:t}=Ve.agentInfo,s=t||0;if(Ve.autoStateTimer&&(clearTimeout(Ve.autoStateTimer),Ve.autoStateTimer=null),le.updateCustomerInfo(void 0),s>0){const{state:A}=Ve.stateObject;if(A===exports.AgentStatus.IDLE)return;this.apiClient._changeState({data:{state:exports.AgentStatus.BUSY,state_name:"整理"}}),Ve.autoStateTimer=setTimeout(()=>{Ve.autoStateTimer=null,this.stateIdleChange()},1e3*s)}else this.stateIdleChange()}stateBusyChange(){Ve.sessionId="",clearTimeout(Ve.autoStateTimer),le.updateCustomerInfo(void 0),this.apiClient._changeState({data:{state:exports.AgentStatus.BUSY,state_name:"忙碌"}})}initWebSocket(){if(1===this.ws?.readyState)return;const A=Ds(Fs,Ys);this.ws=new WebSocket(this.url+A),this.ws.onopen=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now()),this.startHeartbeat(),this.manualClose=!1,this.onOpenCallback&&this.onOpenCallback()},this.ws.onmessage=async A=>{const e=JSON.parse(A.data),{type:t,data:s,code:i,msg:n,msg_id:o}=e;if(0===t&&o){const A=this.pendingMessages.get(o),e=performance.now()-A;Ve.latency=parseFloat(e.toFixed(2)),this.pendingMessages.delete(o)}if(0!==t&&Xs("%cWebSocket 收到消息:","color: blue; font-weight: bold;",e),t!==exports.WebsocketTypeEnum.OUT_CALL&&t!==exports.WebsocketTypeEnum.PREVIEW_OUT_CALL||(0!==i?(le.reset(),ae.emit(exports.CallSipCallEventEnum.OUT_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n),le.updateActionConfigs(ft),setTimeout(()=>{le.updateCustomerInfo(void 0)},500),this.stateIdleChange()):0===i&&(ae.emit(exports.CallSipCallEventEnum.OUT_SUCCESS),clearTimeout(Ve.autoStateTimer))),t===exports.WebsocketTypeEnum.AGENT_STATE){const{state:A,state_name:e}=s;Ve.stateObject={state:A,state_name:e},Ve.stateBeforeChange?.state||Ve.stateObject.state!==exports.AgentStatus.IDLE&&(Ve.stateObject.state!==exports.AgentStatus.BUSY||"整理"===e)||(Ve.stateBeforeChange=Ve.stateObject),"振铃中"===e&&le.updateDisplayText(exports.DisplayTextEnum.AGENT_RINGING),A===exports.AgentStatus.UNREGISTERED&&le.updateActionConfigs(Mt),A===exports.AgentStatus.IDLE&&Ve.stateObject.state===exports.AgentStatus.UNREGISTERED&&le.updateActionConfigs(ft),ae.emit(exports.CallSipCallEventEnum.AGENT_STATE,{state:A,state_name:e})}if(t===exports.WebsocketTypeEnum.OUT_CALL_INCOMING_CALL){try{await this.getCustomerInfo(s.trace_id||s.customer_phone)}catch(A){console.error(A)}s.preview_task_id?ae.emit(exports.CallSipCallEventEnum.PREVIEW_OUT_INCOMING_CALL,{customer_phone:s.customer_phone,session_id:s.session_id,preview_task_id:s.preview_task_id,trace_id:s.trace_id}):ae.emit(exports.CallSipCallEventEnum.OUT_INCOMING_CALL,{customer_phone:s.customer_phone,session_id:s.session_id,trace_id:s.trace_id}),Ve.sessionId=s.session_id,le.updateActionConfigs(St)}if(t===exports.WebsocketTypeEnum.OUT_CALL_END)if(le.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.OUT_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0);else if(2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.OUR_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0);else if(2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){le.get("isCalling")&&(le.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(Qt))}else if(3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.THREE_WAY_OUR_SIDE_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0);else if(4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.TRANSFER_END,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0);else if(4===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){ae.emit(exports.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),ae.emit(exports.EventName.FAIL_NOTIFICATION,"转接失败");const A=le.get("direction");A===exports.DirectionEnum.OUTGOING?le.updateActionConfigs(Qt):A===exports.DirectionEnum.INCOMING&&le.updateActionConfigs(Ut)}else 5===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(Ve.monitoredAgentNo="",Ve.earSpeakAgent="",le.reset(),ae.emit(exports.CallSipCallEventEnum.LISTEN_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0,5));if(t===exports.WebsocketTypeEnum.OUT_CALL_RINGING&&1===s.type&&(ae.emit(exports.CallSipCallEventEnum.OUT_RINGING,{session_id:Ve.sessionId,type:s.type}),le.updateDisplayText(exports.DisplayTextEnum.RINGING)),t===exports.WebsocketTypeEnum.OUT_CALL_ANSWER&&(clearTimeout(Ve.autoStateTimer),le.updateIsCalling(!0),ae.emit(exports.CallSipCallEventEnum.OUT_OFF_ANSWER,{session_id:Ve.sessionId}),le.updateOutCallIsAnswer(!0),le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateActionConfigs(Qt)),t===exports.WebsocketTypeEnum.CONSULT_RINGING&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_RINGING,{session_id:s.session_id}),le.updateDisplayText(exports.DisplayTextEnum.AGENT_RINGING),le.updateActionConfigs([]),clearTimeout(Ve.autoStateTimer)),t===exports.WebsocketTypeEnum.CONSULT_ANSWER&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_OFF_HOOK,{session_id:s.session_id}),le.updateConsultIsAnswer(!0),le.updateDisplayText(exports.DisplayTextEnum.CONSULTING),le.updateActionConfigs(Tt)),t===exports.WebsocketTypeEnum.CONSULT_FAIL&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_FAILED,{custom_reason:s.custom_reason}),le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateActionConfigs(Qt)),t===exports.WebsocketTypeEnum.CONSULT_CALL_IN&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_INCOMING,{agent_no:s.agent_no,agent_mane:s.agent_name,session_id:s.session_id}),Ve.sessionId=s.session_id,le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.CONSULT),le.updateDisplayText(exports.DisplayTextEnum.CONSULT_CALL_IN),le.updateActionConfigs(Rt),Ve.enableBrowserAlert&&Ps.show("📞 咨询来电",`坐席 [${s.agent_name}] 正在咨询...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{agent_mane:s.agent_name,agent_no:s.agent_no})},Ve.browserAlertTime)),t===exports.WebsocketTypeEnum.CONSULT_CALL_IN_SUCCESS&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_CALL_IN_SUCCESS,{session_id:s.session_id}),le.updateConsultIsAnswer(!0),le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateActionConfigs(yt)),t===exports.WebsocketTypeEnum.CONSULT_RETURN_CALL_SUCCESS&&("success"===s.status?(le.updateConsultIsAnswer(!1),ae.emit(exports.CallSipCallEventEnum.CONSULT_RETURN_CALL_SUCCESS),le.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP),le.updateActionConfigs(Qt)):ae.emit(exports.EventName.FAIL_NOTIFICATION,"媒体失败")),t===exports.WebsocketTypeEnum.MUTE&&(0===i?(le.updateIsMuted(!0),ae.emit(exports.CallSipCallEventEnum.MUTE_SUCCESS),le.updateDisplayText(exports.DisplayTextEnum.MUTING)):(ae.emit(exports.CallSipCallEventEnum.MUTE_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.UNMUTE&&(0===i?(le.updateIsMuted(!1),ae.emit(exports.CallSipCallEventEnum.UNMUTE_SUCCESS),le.updateDisplayText(exports.DisplayTextEnum.CALLING)):(ae.emit(exports.CallSipCallEventEnum.UNMUTE_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CALL_HOLD&&(0===i?(le.updateIsHold(!0),le.updateDisplayText(exports.DisplayTextEnum.HOLDING),ae.emit(exports.CallSipCallEventEnum.HOLD_SUCCESS)):(ae.emit(exports.CallSipCallEventEnum.HOLD_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CALL_UNHOLD&&(0===i?(le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateIsHold(!1),ae.emit(exports.CallSipCallEventEnum.UNHOLD_SUCCESS)):(ae.emit(exports.CallSipCallEventEnum.UNHOLD_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER&&(0===i?ae.emit(exports.CallSipCallEventEnum.CONSULT_TRANSFER_SUCCESS):(ae.emit(exports.CallSipCallEventEnum.CONSULT_TRANSFER_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER_FAILED&&ae.emit(exports.CallSipCallEventEnum.CONSULT_TRANSFER_FAILED,s.status),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER_OFF_HOOK&&(le.updateDirection(exports.DirectionEnum.INCOMING),le.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEventEnum.CONSULT_TRANSFER_OFF_HOOK),le.updateActionConfigs(Ut),le.updateIncomingIsAnswer(!0),le.updateConsultIsAnswer(!1)),t===exports.WebsocketTypeEnum.INCOMING_CALL){clearTimeout(Ve.autoStateTimer),Ve.sessionId=s.session_id;try{await this.getCustomerInfo(s.trace_id||s.customer_phone)}catch(A){console.error(A)}le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.INCOMING),le.updateDisplayText(exports.DisplayTextEnum.INCOMING_CALL),this.inCallAutoAnswer(),1===s.direction&&ae.emit(exports.CallSipCallEventEnum.INCOMING_CALL,{customer_phone:s.customer_phone,trace_id:s.trace_id,session_id:s.session_id}),3===s.direction&&ae.emit(exports.CallSipCallEventEnum.PREDICT_INCOMING_CALL,{customer_phone:s.customer_phone,trace_id:s.trace_id,session_id:s.session_id}),le.updateActionConfigs(Rt),Ve.enableBrowserAlert&&Ps.show("📞 客户来电",`客户 [${s.customer_phone}] 正在呼入...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})},Ve.browserAlertTime)}if(t===exports.WebsocketTypeEnum.INCOMING_CALL_OFF_HOOK&&(le.updateIncomingIsAnswer(!0),ae.emit(exports.CallSipCallEventEnum.INCOMING_CALL_OFF_HOOK,{session_id:Ve.sessionId}),le.updateActionConfigs(Ut),le.updateDisplayText(exports.DisplayTextEnum.CALLING)),t===exports.WebsocketTypeEnum.INCOMING_CALL_END)if(le.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),le.reset(),ae.emit(exports.CallSipCallEventEnum.INCOMING_CALL_END,{session_id:s.session_id}),le.updateActionConfigs(ft);else if(2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.OUR_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),this.putAgentState(!0),le.updateActionConfigs(ft);else if(2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no)le.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(Qt);else if(3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),le.reset(),ae.emit(exports.CallSipCallEventEnum.THREE_WAY_OUR_SIDE_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft);else if(4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),le.reset(),ae.emit(exports.CallSipCallEventEnum.TRANSFER_END,{session_id:s.session_id}),le.updateActionConfigs(ft);else if(4===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){ae.emit(exports.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),ae.emit(exports.EventName.FAIL_NOTIFICATION,"转接失败");const A=le.get("direction");A===exports.DirectionEnum.OUTGOING?le.updateActionConfigs(Qt):A===exports.DirectionEnum.INCOMING&&le.updateActionConfigs(Ut)}else 5===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(!0,5),Ve.monitoredAgentNo="",Ve.earSpeakAgent="",le.reset(),ae.emit(exports.CallSipCallEventEnum.LISTEN_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft));if(t===exports.WebsocketTypeEnum.SATISFACTION_EVALUATION&&(0===i?ae.emit(exports.CallSipCallEventEnum.SATISFACTION_EVALUATION_SUCCESS):(ae.emit(exports.CallSipCallEventEnum.SATISFACTION_EVALUATION_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CONSULT_THREE_WAY&&(0!==i?(ae.emit(exports.CallSipCallEventEnum.CONSULT_THREE_WAY_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n)):0===i&&le.updateIsMeeting(!0)),t===exports.WebsocketTypeEnum.CONSULT_THREE_WAY_RESULT&&("success"===s.status?(le.updateDirection(exports.DirectionEnum.MEETING),le.updateDisplayText(exports.DisplayTextEnum.MEETING),le.updateActionConfigs(Dt),ae.emit(exports.CallSipCallEventEnum.CONSULT_THREE_WAY_SUCCESS)):(ae.emit(exports.CallSipCallEventEnum.CONSULT_THREE_WAY_FAILED,{conf_name:s.conf_name}),le.updateIsMeeting(!1))),t===exports.WebsocketTypeEnum.TRANSFER_INCOMING_CALL&&(clearTimeout(Ve.autoStateTimer),s.agent_no===Ve.agentInfo.agent_no?(le.updateDisplayText(exports.DisplayTextEnum.TRANSFERRING),ae.emit(exports.CallSipCallEventEnum.TRANSFER_PROGRESS),le.updateActionConfigs([]),le.updateTransferIsAnswer(!0)):(Ve.sessionId=s.session_id,ae.emit(exports.CallSipCallEventEnum.TRANSFER_INCOMING_CALL,{agent_no:s.agent_no,agent_name:s.agent_name,session_id:s.session_id}),le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.TRANSFER),le.updateDisplayText(exports.DisplayTextEnum.TRANSFER_INCOMING_CALL),le.updateActionConfigs(Rt),Ve.enableBrowserAlert&&Ps.show("📞 转接来电",`坐席 [${s.agent_no}] 正在转接...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{agent_no:s.agent_no})},Ve.browserAlertTime))),t===exports.WebsocketTypeEnum.TRANSFER_OFF_HOOK&&(ae.emit(exports.CallSipCallEventEnum.TRANSFER_OFF_HOOK,{session_id:Ve.sessionId}),le.updateTransferIsAnswer(!1),le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateActionConfigs(Ut)),t===exports.WebsocketTypeEnum.TRANSFER_FAILED&&"failed"===s.status){ae.emit(exports.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),ae.emit(exports.EventName.FAIL_NOTIFICATION,"转接失败");const A=le.get("direction");A===exports.DirectionEnum.OUTGOING?le.updateActionConfigs(Qt):A===exports.DirectionEnum.INCOMING&&le.updateActionConfigs(Ut)}t===exports.WebsocketTypeEnum.KICK_OFFLINE&&ae.emit(exports.EventName.KICK_OFF),t===exports.WebsocketTypeEnum.CONTINUOUS_NOT_ANSWER&&(ae.emit(exports.EventName.FAIL_NOTIFICATION,`已连续 ${s.miss_count} 次未接, 设置忙碌`),this.stateBusyChange()),t===exports.WebsocketTypeEnum.SIGN_OUT&&ae.emit(exports.EventName.SIGN_OUT),t===exports.WebsocketTypeEnum.SIGN_IN_SWITCH_DEVICE&&ae.emit(exports.EventName.SIGN_IN_SWITCH_DEVICE,s),t===exports.WebsocketTypeEnum.LISTEN_INCOMING_CALL&&(clearTimeout(Ve.autoStateTimer),Ve.sessionId=s.session_id,le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.INCOMING),this.inCallAutoAnswer(),le.updateDisplayText(exports.DisplayTextEnum.LISTENING),le.updateActionConfigs(Rt),ae.emit(exports.CallSipCallEventEnum.LISTEN_INCOMING_CALL,{session_id:s.session_id}),Ve.enableBrowserAlert&&Ps.show("📞 监听来电","正在来电...",()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})},Ve.browserAlertTime)),t===exports.WebsocketTypeEnum.LISTEN_INCOMING_CALL_OFF_HOOK&&(Ve.monitoredAgentNo=s.monitored_agent_no,Ve.earSpeakAgent="",le.updateIncomingIsAnswer(!0),ae.emit(exports.CallSipCallEventEnum.LISTEN_INCOMING_CALL_OFF_HOOK,{session_id:Ve.sessionId,monitored_agent_no:s.monitored_agent_no}),le.updateActionConfigs(kt),le.updateDisplayText(exports.DisplayTextEnum.CALLING)),t===exports.WebsocketTypeEnum.LISTEN_CALL_FAILED&&"failed"===s.status&&(ae.emit(exports.CallSipCallEventEnum.LISTEN_CALL_FAILED),Ve.monitoredAgentNo=""),t===exports.WebsocketTypeEnum.EAR_SPEECH&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&(le.updateActionConfigs(Gt),ae.emit(exports.CallSipCallEventEnum.EAR_SPEECH_BE_SUCCESS)),s.monitor_agent_no===Ve.agentInfo.agent_no&&(le.updateActionConfigs(Ft),ae.emit(exports.CallSipCallEventEnum.EAR_SPEECH_SUCCESS,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no}),Ve.earSpeakAgent=s.monitored_agent_no)):ae.emit(exports.CallSipCallEventEnum.EAR_SPEECH_FAILED)),t===exports.WebsocketTypeEnum.STOP_EAR_SPEECH&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&le.updateActionConfigs(Ut),s.monitor_agent_no===Ve.agentInfo.agent_no&&le.updateActionConfigs(kt),Ve.earSpeakAgent="",ae.emit(exports.CallSipCallEventEnum.STOP_EAR_SPEECH_SUCCESS)):ae.emit(exports.CallSipCallEventEnum.STOP_EAR_SPEECH_FAILED)),t===exports.WebsocketTypeEnum.CALL_FORCE_INSERT&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&(le.updateActionConfigs(xt),ae.emit(exports.CallSipCallEventEnum.CALL_FORCE_INSERT_SUCCESS,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no})),s.monitor_agent_no===Ve.agentInfo.agent_no&&(le.updateActionConfigs(Yt),ae.emit(exports.CallSipCallEventEnum.CALL_FORCE_INSERT_SUCCESS_LISTENER,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no}))):ae.emit(exports.CallSipCallEventEnum.CALL_FORCE_INSERT_FAILED))},this.ws.onclose=A=>{ae.emit(exports.EventName.FAIL_NOTIFICATION,"链接已断开,请检查网络"),this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=A=>{ae.emit(exports.EventName.FAIL_NOTIFICATION,"连接失败,请检查网络"),this.ws?.close()}}startHeartbeat(){const A=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 5000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),e=URL.createObjectURL(A);this.heartbeatWorker=new Worker(e),this.heartbeatWorker.onmessage=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now())},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify(A)),0!==A.type&&Xs("%cWebSocket 发送消息:","color: green; font-weight: bold;",A)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}reconnect(){this.initWebSocket()}static __internalClose(){_s&&(_s.close(),_s=null)}static __internalSend(A){if(!_s)throw new Error("WebSocket 尚未初始化");_s.sendMessage(A)}}class Ai{constructor(A){this.sipClient=null,this.sipClient=A}roleMute(){const A=le.get("isCalling"),e=Ve.sessionId;if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}))}holdCall(){this.roleMute();const A=le.get("isHold"),{sessionId:e}=Ve;if(!e)return;if(!le.get("actionConfigs").includes("hold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿保持"}));if(A)throw new Error(JSON.stringify({code:1,msg:"当前已处于保持状态"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CALL_HOLD,data:{session_id:e}})}unholdCall(){this.roleMute();const{isHold:A}=le.getState(),{sessionId:e}=Ve;if(!le.get("actionConfigs").includes("unhold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取消保持"}));if(e){if(!A)throw new Error(JSON.stringify({code:1,msg:"当前未处于保持状态"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CALL_UNHOLD,data:{session_id:e}})}}sendDTMF(A){if(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!le.get("actionConfigs").includes("dtmf"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿发送按键"}));const{isCalling:e}=le.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));this.sipClient.sendDTMF(A)}cancelCall(){if(!le.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;ae.emit(exports.CallSipCallEventEnum.REJECT,{session_id:A}),$s.__internalSend({type:exports.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:A}})}async consultCall(A){this.roleMute();const{isCalling:e,outCallIsAnswer:t,consultIsAnswer:s,incomingIsAnswer:i}=le.getState(),n=Ve.sessionId;if(!le.get("actionConfigs").includes("consult"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询"}));if(s)throw new Error(JSON.stringify({code:1,msg:"当前正在咨询"}));if(!(e||t||i))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!n)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:A}})}async answerCall(){if(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}makeCall(A){if("string"!=typeof A||""===A.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));const e={};if(Rs(A))e.trace_id=A;else{if(!/^(?:1[3-9]\d{9}|0\d{2,3}-?\d{7,8})$/.test(A.trim()))throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));e.customer_phone=A.replace(/[\s\r\n-]+/g,"")}const t=le.get("isCalling"),s=le.get("selectOutNumber")||"";if(t)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.OUTGOING),$s.__internalSend({type:exports.WebsocketTypeEnum.OUT_CALL,data:{...e,caller:s.replace(/[\s\r\n-]+/g,"")}})}previewCall(A,e){const t={};Rs(A)?t.trace_id=A:t.customer_phone=A.replace(/[\s\r\n-]+/g,"");const s=le.get("isCalling"),i=le.get("selectOutNumber")||"";if(s)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));if("string"!=typeof A||""===A.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.OUTGOING),$s.__internalSend({type:exports.WebsocketTypeEnum.PREVIEW_OUT_CALL,data:{...t,caller:i,preview_task_id:e}})}async hangup(){if(!le.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;$s.__internalSend({type:exports.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:A}})}mute(){this.roleMute();const A=le.get("actionConfigs"),e=le.get("isMuted"),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前未处于静音状态"}));if(!A.includes("mute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:exports.WebsocketTypeEnum.MUTE,data:{session_id:t}})}unmute(){this.roleMute();const A=le.get("actionConfigs"),e=le.get("isMuted"),t=Ve.sessionId;if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于未静音状态"}));if(!A.includes("unmute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:exports.WebsocketTypeEnum.UNMUTE,data:{session_id:t}})}consultTransfer(){this.roleMute();const A=le.get("consultIsAnswer"),e=Ve.sessionId;if(!le.get("actionConfigs").includes("consult_transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询转移"}));if(!A)throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_TRANSFER,data:{session_id:e}})}satisfactionEvaluation(){this.roleMute();const A=Ve.sessionId;if(!le.get("actionConfigs").includes("satisfaction"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用满意度评价"}));$s.__internalSend({type:exports.WebsocketTypeEnum.SATISFACTION_EVALUATION,data:{session_id:A}})}startConference(){this.roleMute();if(!le.get("actionConfigs").includes("conference"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用三方会议"}));const A=Ve.sessionId;if(!le.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_THREE_WAY,data:{session_id:A}})}consultRetrieve(){this.roleMute();if(!le.get("actionConfigs").includes("consult_retrieve"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取回通话"}));const A=Ve.sessionId;if(!le.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_RETURN_CALL,data:{session_id:A}})}async transferAgent(A){this.roleMute();if(!le.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));const{transferIsAnswer:e}=le.getState(),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:exports.WebsocketTypeEnum.TRANSFER,data:{session_id:t,transfer_type:0,transfer_dest:A}})}async transferOutline(A){this.roleMute();if(!le.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));if(!A)throw new Error(JSON.stringify({code:1,msg:"号码不能为空"}));if(!/^\d+$/.test(A))throw new Error(JSON.stringify({code:1,msg:"号码格式错误"}));const{transferIsAnswer:e}=le.getState(),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:exports.WebsocketTypeEnum.TRANSFER,data:{session_id:t,transfer_type:2,transfer_dest:A}})}}var ei;class ti{static{this._instance=null}#A;#e;#t;#s;#i;#n;#o;#r;static{this._timer=null}#a;constructor(){if(this.#A=null,this.#e=new Ks,this.#s=null,this.#i=!1,this.#r=!1,this.#a=null,this.#V=()=>{le.updateIsNextState(!0)},this.#c=()=>{le.updateIsNextState(!1)},this.initWebRtc=async()=>{if(this.#A)return;const A=Ve.agentInfo.sip_account_list.find(A=>1===A.device_type);if(!A)throw new Error(JSON.stringify({code:1,msg:"未找到 sip_account_list"}));{const e=A.sip_register_addr;this.#A=new ge({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#l),await this.#A.start()}},this.#l=A=>{const{type:e,data:t}=A;ae.emit(e,t)},!ei._creatingInstance)throw new Error("请使用 YSYTAgentSdk.getInstance() 获取实例");clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#h();he.updateRttObject(A)},2e3),Ps.requestMediaPermissions(),this.#o=le.subscribeKey("isNextState",async A=>{if(A){await this.#e._agentLogin(xs);1===le.get("answerDevice")&&await this.#A.reconnect();let A="";const e=new URL(Gs).host;A=Gs.includes("https")?`wss://${e}`:`ws://${e}`;const{agent_no:t}=Ve.agentInfo;$s.getInstance({url:`${A}/ccs-ws/api/v1/ws/call/${t}?Authorization=`,sipClient:this.#A}),Ve.stateObject.state===exports.AgentStatus.OFFLINE&&setTimeout(()=>{this.#e._changeState({data:{...this.#a,state_name:this.#a.state===exports.AgentStatus.BUSY&&"整理"===this.#a.state_name?"忙碌":this.#a.state_name},success:()=>{le.updateDisplayText(""),ae.emit(exports.CallSipCallEventEnum.AGENT_STATE,this.#a)}})},10)}else this.#a=Ve.stateObject,$s.__internalClose(),le.updateDisplayText("离线")}),this.on(exports.EventName.KICK_OFF,()=>{this.destroy()}),window.addEventListener("beforeunload",A=>{A.returnValue="",this.destroy()}),window.addEventListener("online",this.#V),window.addEventListener("offline",this.#c)}#V;#c;async#g(){const A=le.get("isNextState");try{await Ns(),A||le.updateIsNextState(!0)}catch(e){ae.emit(exports.EventName.FAIL_NOTIFICATION,"网络断开,请检查网络"),A&&le.updateIsNextState(!1)}}#q(){ei._timer||(ei._timer=setInterval(()=>this.#g(),3e3))}static get instance(){return this._instance}static async destroyInstance(){this._instance&&(await this._instance.destroy(),this._instance=null)}static getInstance(A){if(!this._instance){if(!A)throw new Error("首次调用必须传入配置参数");const{url:e,appKey:t,appSecret:s,agentNo:i}=A;Gs=e||"https://aicc-api.yescloudy.com",Fs=t,Ys=s,xs=i,ei._creatingInstance=!0,this._instance=new ei,delete ei._creatingInstance}return this._instance}getInit(){return this.#r}async init({actionNodeParams:A,enableBrowserAlert:e,logBuiltinEnabled:t,browserAlertTime:s,initialState:i,initDevice:n}){try{let o="";const r=new URL(Gs).host;o=Gs.includes("https")?`wss://${r}`:`ws://${r}`;const a=$s.getInstance({url:`${o}/ccs-ws/api/v1/ws/call/${xs}?Authorization=`,sipClient:null,onOpen:async()=>{const{viewHtmlElement:o,rttHTML:r}=A||{};Ve.logBuiltinEnabled=t||!1,Ve.browserAlertTime=s||5e3,await this.#e._agentLogin(xs);const{current_answer_device:V,current_state:c,out_display_number:l,out_display_select_switch:h}=Ve.agentInfo;(i||c)===exports.AgentStatus.IDLE?(le.updateActionConfigs(ft),Ve.stateObject={state:i||c,state_name:"空闲"},Ve.stateBeforeChange=Ve.stateObject):(i||c)===exports.AgentStatus.BUSY?(le.updateActionConfigs(Bt),Ve.stateObject={state:c,state_name:"忙碌"},Ve.stateBeforeChange=Ve.stateObject):(i||c)===exports.AgentStatus.UNREGISTERED&&(le.updateActionConfigs(Bt),Ve.stateObject={state:c,state_name:"未注册"}),1===h?le.updateSelectOutNumber(l):le.updateSelectOutNumber(""),le.updateAnswerDevice(n||V),1===(n||V)&&(await this.initWebRtc(),Ks.setInitRtcFn(this.initWebRtc),a.setSipClient(this.#A)),this.#t=new Ai(this.#A),A&&o&&(this.#i=!0,new Ws({container:o,rttHTML:r,statusParams:{state:Ve.stateObject.state,statusName:Ve.stateObject.state_name}},this,this.#t)),Ve.enableBrowserAlert=e,e&&Ps.requestPermission(),ae.emit(exports.EventName.AGENT_INIT_STATUS,!0),this.#r=!0,clearInterval(ei._timer),ei._timer=null,this.#q(),this.#n=le.subscribeKey("answerDevice",async A=>{1===A?Ve.stateObject.state===exports.AgentStatus.UNREGISTERED&&await this.#e._changeState({data:{...Ve.stateBeforeChange,state_name:Ve.stateBeforeChange.state===exports.AgentStatus.IDLE?"空闲":"忙碌"}}):await this.destroyRtc()})}})}catch(A){this.#i&&Hs("初始化失败"),ae.emit(exports.EventName.AGENT_INIT_STATUS,!1),this.#r=!1}}#l;on(A,e){return ae.on(A,e),this}off(A,e){ae.off(A,e)}offAll(){ae.clearAllListeners()}async destroyRtc(){await(this.#A?.destroy()),this.#A=null}async destroy(){ei._instance&&(await this.destroyRtc(),this.#n?.(),this.#o?.(),clearInterval(this.#s),$s.__internalClose(),ae.emit(exports.EventName.DESTROY),this.offAll(),this.#i=!1,ei._instance=null,le.reset(),le.updateSelectOutNumber(""),clearInterval(ei._timer),ei._timer=null)}async#h(){return this.#A?this.#A.getNetworkStats():{}}get call_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{answerCall:A(()=>this.#t.answerCall()),makeCall:A=>this.#t.makeCall(A),previewMakeCall:(A,e)=>this.#t.previewCall(A,e),cancelCall:A(()=>this.#t.cancelCall()),hangup:A(()=>this.#t.hangup()),sendDTMF:A(A=>this.#t.sendDTMF(A)),holdCall:A(()=>this.#t.holdCall()),unholdCall:A(()=>this.#t.unholdCall()),consultCall:A(async A=>{try{await this.#t.consultCall(A)}catch(A){throw console.warn(A),A}}),consultRetrieve:A(()=>this.#t.consultRetrieve()),consultTransfer:A(()=>this.#t.consultTransfer()),mute:A(()=>this.#t.mute()),unmute:A(()=>this.#t.unmute()),satisfactionEvaluation:A(()=>this.#t.satisfactionEvaluation()),startConference:A(()=>this.#t.startConference()),transferAgent:A(A=>this.#t.transferAgent(A)),transferOutline:A(A=>this.#t.transferOutline(A)),earSpeakStart:A(A=>this.#e.earCall(A)),earSpeakStop:A(A=>this.#e.stopEarCall(A)),forceInsert:A(A=>this.#e.forceInsert(A)),forceDisconnect:A(A=>this.#e.forceDisconnect(A))}}get agent_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{changeDevice:A(A=>this.#e.changeDevice(A)),changeState:A(A=>this.#e.changeState(A)),getIdleAgentList:A(A=>this.#e.getIdleAgentList(A)),getAgentState:A(A=>this.#e.getAgentState(A)),setAgentExplicit:A(A=>this.#e.setAgentExplicit(A)),checkAgentLogin:A=>this.#e.checkAgentLogin(A),getCallRecord:A=>this.#e.getCallRecord(A),agentLogout:async(A,e)=>{try{await this.#e.logout(A),await this.destroy(),e?.({code:0,msg:""})}catch(A){}},listenAgentCall:A=>this.#e.listenCall(A)}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,out_display_data:s,out_display_select_switch:i,current_state:n}=Ve.agentInfo,{stateObject:o}=Ve,r={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:n,default_device:le.get("answerDevice"),out_display_data:s,out_display_select_switch:i,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:r[Number(A)]})),stateObject:o}}async getRealTimeCustomerInfo(){return le.get("customerObject")}setBrowserAlert(A){if("boolean"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));Ve.logBuiltinEnabled=A||!1}setBrowserAlertTime(A){if("number"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));Ve.browserAlertTime=A||3e3}}ei=ti,exports.default=ti;
914
+ `;mt(s,this.rttHTML)}}class Ps{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const A=await navigator.mediaDevices.enumerateDevices();if(A.some(A=>"audioinput"===A.kind&&""!==A.label))return null;return await navigator.mediaDevices.getUserMedia({audio:!0})}catch(A){return console.warn("获取音频权限失败:",A),null}}static show(A,e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(A,{body:e,tag:`xy-global-notification${(new Date).getTime()}`,renotify:!0});i.onclick=()=>{window.focus(),i.close(),t?.()},setTimeout(()=>i.close(),1e3*(s||3))}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}const zs=console.log,Xs=(...A)=>{Ve.logBuiltinEnabled&&zs(...A)};let _s=null;class $s{constructor(A,e){this.url=A,this.onOpenCallback=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Ks,this.sipClient=null,this.pendingMessages=new Map,this.initWebSocket()}static getInstance({url:A,sipClient:e,onOpen:t}){if(!_s){if(!A)throw new Error("WebSocket 尚未初始化");_s=new $s(A,t),_s.sipClient=e}return _s}setSipClient(A){this.sipClient=A}stateIdleChange(){const{state:A}=Ve.stateObject;A!==exports.AgentStatus.IDLE&&this.apiClient._changeState({data:{...Ve.stateBeforeChange,state_name:Ve.stateBeforeChange.state===exports.AgentStatus.IDLE?"空闲":"忙碌"}})}inCallAutoAnswer(){const{soft_device_auto_answer:A,auto_answer_time:e}=Ve.agentInfo,t=1===A,s=le.get("direction");if(t&&s===exports.DirectionEnum.INCOMING){const A=Number(e)||0;A>0&&(Ve.autoAnswerTimer=setTimeout(()=>{this.sipClient?.answerCall(),Ve.autoAnswerTimer=null},1e3*A))}}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{le.updateCustomerInfo(A.data||{phone:A.data.phone,is_vip:0,customer_name:"未知客户",city:"未知",province:"未知",contact_count:0,in_contact_count:0,trace_id:A.data.trace_id,contact_count_month:0,in_contact_count_month:0})}})}catch(A){}}putAgentState(A,e){if(!A)return;if(5===e)return void this.stateIdleChange();Ve.sessionId="";const{post_call_process_time:t}=Ve.agentInfo,s=t||0;if(Ve.autoStateTimer&&(clearTimeout(Ve.autoStateTimer),Ve.autoStateTimer=null),le.updateCustomerInfo(void 0),s>0){const{state:A}=Ve.stateObject;if(A===exports.AgentStatus.IDLE)return;this.apiClient._changeState({data:{state:exports.AgentStatus.BUSY,state_name:"整理"}}),Ve.autoStateTimer=setTimeout(()=>{Ve.autoStateTimer=null,this.stateIdleChange()},1e3*s)}else this.stateIdleChange()}stateBusyChange(){Ve.sessionId="",clearTimeout(Ve.autoStateTimer),le.updateCustomerInfo(void 0),this.apiClient._changeState({data:{state:exports.AgentStatus.BUSY,state_name:"忙碌"}})}initWebSocket(){if(1===this.ws?.readyState)return;const A=Ds(Fs,Ys);this.ws=new WebSocket(this.url+A),this.ws.onopen=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now()),this.startHeartbeat(),this.manualClose=!1,this.onOpenCallback&&this.onOpenCallback()},this.ws.onmessage=async A=>{const e=JSON.parse(A.data),{type:t,data:s,code:i,msg:n,msg_id:o}=e;if(0===t&&o){const A=this.pendingMessages.get(o),e=performance.now()-A;Ve.latency=parseFloat(e.toFixed(2)),this.pendingMessages.delete(o)}if(0!==t&&Xs("%cWebSocket 收到消息:","color: blue; font-weight: bold;",e),t!==exports.WebsocketTypeEnum.OUT_CALL&&t!==exports.WebsocketTypeEnum.PREVIEW_OUT_CALL||(0!==i?(le.reset(),ae.emit(exports.CallSipCallEventEnum.OUT_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n),le.updateActionConfigs(ft),setTimeout(()=>{le.updateCustomerInfo(void 0)},500),this.stateIdleChange()):0===i&&(ae.emit(exports.CallSipCallEventEnum.OUT_SUCCESS),clearTimeout(Ve.autoStateTimer))),t===exports.WebsocketTypeEnum.AGENT_STATE){const{state:A,state_name:e}=s;Ve.stateObject={state:A,state_name:e},Ve.stateBeforeChange?.state||Ve.stateObject.state!==exports.AgentStatus.IDLE&&(Ve.stateObject.state!==exports.AgentStatus.BUSY||"整理"===e)||(Ve.stateBeforeChange=Ve.stateObject),"振铃中"===e&&le.updateDisplayText(exports.DisplayTextEnum.AGENT_RINGING),A===exports.AgentStatus.UNREGISTERED&&le.updateActionConfigs(Mt),A===exports.AgentStatus.IDLE&&Ve.stateObject.state===exports.AgentStatus.UNREGISTERED&&le.updateActionConfigs(ft),ae.emit(exports.CallSipCallEventEnum.AGENT_STATE,{state:A,state_name:e})}if(t===exports.WebsocketTypeEnum.OUT_CALL_INCOMING_CALL){try{await this.getCustomerInfo(s.trace_id||s.customer_phone)}catch(A){console.error(A)}s.preview_task_id?ae.emit(exports.CallSipCallEventEnum.PREVIEW_OUT_INCOMING_CALL,{customer_phone:s.customer_phone,session_id:s.session_id,preview_task_id:s.preview_task_id,trace_id:s.trace_id}):ae.emit(exports.CallSipCallEventEnum.OUT_INCOMING_CALL,{customer_phone:s.customer_phone,session_id:s.session_id,trace_id:s.trace_id}),Ve.sessionId=s.session_id,le.updateActionConfigs(St)}if(t===exports.WebsocketTypeEnum.OUT_CALL_END)if(le.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.OUT_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0);else if(2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.OUR_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0);else if(2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){le.get("isCalling")&&(le.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(Qt))}else if(3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.THREE_WAY_OUR_SIDE_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0);else if(4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.TRANSFER_END,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0);else if(4===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){ae.emit(exports.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),ae.emit(exports.EventName.FAIL_NOTIFICATION,"转接失败");const A=le.get("direction");A===exports.DirectionEnum.OUTGOING?le.updateActionConfigs(Qt):A===exports.DirectionEnum.INCOMING&&le.updateActionConfigs(Ut)}else 5===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(Ve.monitoredAgentNo="",Ve.earSpeakAgent="",le.reset(),ae.emit(exports.CallSipCallEventEnum.LISTEN_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft),this.putAgentState(!0,5));if(t===exports.WebsocketTypeEnum.OUT_CALL_RINGING&&1===s.type&&(ae.emit(exports.CallSipCallEventEnum.OUT_RINGING,{session_id:Ve.sessionId,type:s.type}),le.updateDisplayText(exports.DisplayTextEnum.RINGING)),t===exports.WebsocketTypeEnum.OUT_CALL_ANSWER&&(clearTimeout(Ve.autoStateTimer),le.updateIsCalling(!0),ae.emit(exports.CallSipCallEventEnum.OUT_OFF_ANSWER,{session_id:Ve.sessionId}),le.updateOutCallIsAnswer(!0),le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateActionConfigs(Qt)),t===exports.WebsocketTypeEnum.CONSULT_RINGING&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_RINGING,{session_id:s.session_id}),le.updateDisplayText(exports.DisplayTextEnum.AGENT_RINGING),le.updateActionConfigs([]),clearTimeout(Ve.autoStateTimer)),t===exports.WebsocketTypeEnum.CONSULT_ANSWER&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_OFF_HOOK,{session_id:s.session_id}),le.updateConsultIsAnswer(!0),le.updateDisplayText(exports.DisplayTextEnum.CONSULTING),le.updateActionConfigs(Tt)),t===exports.WebsocketTypeEnum.CONSULT_FAIL&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_FAILED,{custom_reason:s.custom_reason}),le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateActionConfigs(Qt)),t===exports.WebsocketTypeEnum.CONSULT_CALL_IN&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_INCOMING,{agent_no:s.agent_no,agent_mane:s.agent_name,session_id:s.session_id}),Ve.sessionId=s.session_id,le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.CONSULT),le.updateDisplayText(exports.DisplayTextEnum.CONSULT_CALL_IN),le.updateActionConfigs(Rt),Ve.enableBrowserAlert&&Ps.show("📞 咨询来电",`坐席 [${s.agent_name}] 正在咨询...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{agent_mane:s.agent_name,agent_no:s.agent_no})},Ve.browserAlertTime)),t===exports.WebsocketTypeEnum.CONSULT_CALL_IN_SUCCESS&&(ae.emit(exports.CallSipCallEventEnum.CONSULT_CALL_IN_SUCCESS,{session_id:s.session_id}),le.updateConsultIsAnswer(!0),le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateActionConfigs(yt)),t===exports.WebsocketTypeEnum.CONSULT_RETURN_CALL_SUCCESS&&("success"===s.status?(le.updateConsultIsAnswer(!1),ae.emit(exports.CallSipCallEventEnum.CONSULT_RETURN_CALL_SUCCESS),le.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP),le.updateActionConfigs(Qt)):ae.emit(exports.EventName.FAIL_NOTIFICATION,"媒体失败")),t===exports.WebsocketTypeEnum.MUTE&&(0===i?(le.updateIsMuted(!0),ae.emit(exports.CallSipCallEventEnum.MUTE_SUCCESS),le.updateDisplayText(exports.DisplayTextEnum.MUTING)):(ae.emit(exports.CallSipCallEventEnum.MUTE_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.UNMUTE&&(0===i?(le.updateIsMuted(!1),ae.emit(exports.CallSipCallEventEnum.UNMUTE_SUCCESS),le.updateDisplayText(exports.DisplayTextEnum.CALLING)):(ae.emit(exports.CallSipCallEventEnum.UNMUTE_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CALL_HOLD&&(0===i?(le.updateIsHold(!0),le.updateDisplayText(exports.DisplayTextEnum.HOLDING),ae.emit(exports.CallSipCallEventEnum.HOLD_SUCCESS)):(ae.emit(exports.CallSipCallEventEnum.HOLD_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CALL_UNHOLD&&(0===i?(le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateIsHold(!1),ae.emit(exports.CallSipCallEventEnum.UNHOLD_SUCCESS)):(ae.emit(exports.CallSipCallEventEnum.UNHOLD_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER&&(0===i?ae.emit(exports.CallSipCallEventEnum.CONSULT_TRANSFER_SUCCESS):(ae.emit(exports.CallSipCallEventEnum.CONSULT_TRANSFER_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER_FAILED&&ae.emit(exports.CallSipCallEventEnum.CONSULT_TRANSFER_FAILED,s.status),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER_OFF_HOOK&&(le.updateDirection(exports.DirectionEnum.INCOMING),le.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEventEnum.CONSULT_TRANSFER_OFF_HOOK),le.updateActionConfigs(Ut),le.updateIncomingIsAnswer(!0),le.updateConsultIsAnswer(!1)),t===exports.WebsocketTypeEnum.INCOMING_CALL){clearTimeout(Ve.autoStateTimer),Ve.sessionId=s.session_id;try{await this.getCustomerInfo(s.trace_id||s.customer_phone)}catch(A){console.error(A)}le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.INCOMING),le.updateDisplayText(exports.DisplayTextEnum.INCOMING_CALL),this.inCallAutoAnswer(),1===s.direction&&ae.emit(exports.CallSipCallEventEnum.INCOMING_CALL,{customer_phone:s.customer_phone,trace_id:s.trace_id,session_id:s.session_id}),3===s.direction&&ae.emit(exports.CallSipCallEventEnum.PREDICT_INCOMING_CALL,{customer_phone:s.customer_phone,trace_id:s.trace_id,session_id:s.session_id}),le.updateActionConfigs(Rt),Ve.enableBrowserAlert&&Ps.show("📞 客户来电",`客户 [${s.customer_phone}] 正在呼入...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})},Ve.browserAlertTime)}if(t===exports.WebsocketTypeEnum.INCOMING_CALL_OFF_HOOK&&(le.updateIncomingIsAnswer(!0),ae.emit(exports.CallSipCallEventEnum.INCOMING_CALL_OFF_HOOK,{session_id:Ve.sessionId}),le.updateActionConfigs(Ut),le.updateDisplayText(exports.DisplayTextEnum.CALLING)),t===exports.WebsocketTypeEnum.INCOMING_CALL_END)if(le.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),le.reset(),ae.emit(exports.CallSipCallEventEnum.INCOMING_CALL_END,{session_id:s.session_id}),le.updateActionConfigs(ft);else if(2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)le.reset(),ae.emit(exports.CallSipCallEventEnum.OUR_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),this.putAgentState(!0),le.updateActionConfigs(ft);else if(2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no)le.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(Qt);else if(3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),le.reset(),ae.emit(exports.CallSipCallEventEnum.THREE_WAY_OUR_SIDE_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft);else if(4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),le.reset(),ae.emit(exports.CallSipCallEventEnum.TRANSFER_END,{session_id:s.session_id}),le.updateActionConfigs(ft);else if(4===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){ae.emit(exports.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),ae.emit(exports.EventName.FAIL_NOTIFICATION,"转接失败");const A=le.get("direction");A===exports.DirectionEnum.OUTGOING?le.updateActionConfigs(Qt):A===exports.DirectionEnum.INCOMING&&le.updateActionConfigs(Ut)}else 5===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(!0,5),Ve.monitoredAgentNo="",Ve.earSpeakAgent="",le.reset(),ae.emit(exports.CallSipCallEventEnum.LISTEN_HANGUP,{session_id:s.session_id}),le.updateActionConfigs(ft));if(t===exports.WebsocketTypeEnum.SATISFACTION_EVALUATION&&(0===i?ae.emit(exports.CallSipCallEventEnum.SATISFACTION_EVALUATION_SUCCESS):(ae.emit(exports.CallSipCallEventEnum.SATISFACTION_EVALUATION_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n))),t===exports.WebsocketTypeEnum.CONSULT_THREE_WAY&&(0!==i?(ae.emit(exports.CallSipCallEventEnum.CONSULT_THREE_WAY_FAILED,n),ae.emit(exports.EventName.FAIL_NOTIFICATION,n)):0===i&&le.updateIsMeeting(!0)),t===exports.WebsocketTypeEnum.CONSULT_THREE_WAY_RESULT&&("success"===s.status?(le.updateDirection(exports.DirectionEnum.MEETING),le.updateDisplayText(exports.DisplayTextEnum.MEETING),le.updateActionConfigs(Dt),ae.emit(exports.CallSipCallEventEnum.CONSULT_THREE_WAY_SUCCESS)):(ae.emit(exports.CallSipCallEventEnum.CONSULT_THREE_WAY_FAILED,{conf_name:s.conf_name}),le.updateIsMeeting(!1))),t===exports.WebsocketTypeEnum.TRANSFER_INCOMING_CALL&&(clearTimeout(Ve.autoStateTimer),s.agent_no===Ve.agentInfo.agent_no?(le.updateDisplayText(exports.DisplayTextEnum.TRANSFERRING),ae.emit(exports.CallSipCallEventEnum.TRANSFER_PROGRESS),le.updateActionConfigs([]),le.updateTransferIsAnswer(!0)):(Ve.sessionId=s.session_id,ae.emit(exports.CallSipCallEventEnum.TRANSFER_INCOMING_CALL,{agent_no:s.agent_no,agent_name:s.agent_name,session_id:s.session_id}),le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.TRANSFER),le.updateDisplayText(exports.DisplayTextEnum.TRANSFER_INCOMING_CALL),le.updateActionConfigs(Rt),Ve.enableBrowserAlert&&Ps.show("📞 转接来电",`坐席 [${s.agent_no}] 正在转接...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{agent_no:s.agent_no})},Ve.browserAlertTime))),t===exports.WebsocketTypeEnum.TRANSFER_OFF_HOOK&&(ae.emit(exports.CallSipCallEventEnum.TRANSFER_OFF_HOOK,{session_id:Ve.sessionId}),le.updateTransferIsAnswer(!1),le.updateDisplayText(exports.DisplayTextEnum.CALLING),le.updateActionConfigs(Ut)),t===exports.WebsocketTypeEnum.TRANSFER_FAILED&&"failed"===s.status){ae.emit(exports.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),ae.emit(exports.EventName.FAIL_NOTIFICATION,"转接失败");const A=le.get("direction");A===exports.DirectionEnum.OUTGOING?le.updateActionConfigs(Qt):A===exports.DirectionEnum.INCOMING&&le.updateActionConfigs(Ut)}t===exports.WebsocketTypeEnum.KICK_OFFLINE&&ae.emit(exports.EventName.KICK_OFF),t===exports.WebsocketTypeEnum.CONTINUOUS_NOT_ANSWER&&(ae.emit(exports.EventName.FAIL_NOTIFICATION,`已连续 ${s.miss_count} 次未接, 设置忙碌`),this.stateBusyChange()),t===exports.WebsocketTypeEnum.SIGN_OUT&&ae.emit(exports.EventName.SIGN_OUT),t===exports.WebsocketTypeEnum.SIGN_IN_SWITCH_DEVICE&&ae.emit(exports.EventName.SIGN_IN_SWITCH_DEVICE,s),t===exports.WebsocketTypeEnum.LISTEN_INCOMING_CALL&&(clearTimeout(Ve.autoStateTimer),Ve.sessionId=s.session_id,le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.INCOMING),this.inCallAutoAnswer(),le.updateDisplayText(exports.DisplayTextEnum.LISTENING),le.updateActionConfigs(Rt),ae.emit(exports.CallSipCallEventEnum.LISTEN_INCOMING_CALL,{session_id:s.session_id}),Ve.enableBrowserAlert&&Ps.show("📞 监听来电","正在来电...",()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})},Ve.browserAlertTime)),t===exports.WebsocketTypeEnum.LISTEN_INCOMING_CALL_OFF_HOOK&&(Ve.monitoredAgentNo=s.monitored_agent_no,Ve.earSpeakAgent="",le.updateIncomingIsAnswer(!0),ae.emit(exports.CallSipCallEventEnum.LISTEN_INCOMING_CALL_OFF_HOOK,{session_id:Ve.sessionId,monitored_agent_no:s.monitored_agent_no}),le.updateActionConfigs(kt),le.updateDisplayText(exports.DisplayTextEnum.CALLING)),t===exports.WebsocketTypeEnum.LISTEN_CALL_FAILED&&"failed"===s.status&&(ae.emit(exports.CallSipCallEventEnum.LISTEN_CALL_FAILED),Ve.monitoredAgentNo=""),t===exports.WebsocketTypeEnum.EAR_SPEECH&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&(le.updateActionConfigs(Gt),ae.emit(exports.CallSipCallEventEnum.EAR_SPEECH_BE_SUCCESS)),s.monitor_agent_no===Ve.agentInfo.agent_no&&(le.updateActionConfigs(Ft),ae.emit(exports.CallSipCallEventEnum.EAR_SPEECH_SUCCESS,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no}),Ve.earSpeakAgent=s.monitored_agent_no)):ae.emit(exports.CallSipCallEventEnum.EAR_SPEECH_FAILED)),t===exports.WebsocketTypeEnum.STOP_EAR_SPEECH&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&le.updateActionConfigs(Ut),s.monitor_agent_no===Ve.agentInfo.agent_no&&le.updateActionConfigs(kt),Ve.earSpeakAgent="",ae.emit(exports.CallSipCallEventEnum.STOP_EAR_SPEECH_SUCCESS)):ae.emit(exports.CallSipCallEventEnum.STOP_EAR_SPEECH_FAILED)),t===exports.WebsocketTypeEnum.CALL_FORCE_INSERT&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&(le.updateActionConfigs(xt),ae.emit(exports.CallSipCallEventEnum.CALL_FORCE_INSERT_SUCCESS,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no})),s.monitor_agent_no===Ve.agentInfo.agent_no&&(le.updateActionConfigs(Yt),ae.emit(exports.CallSipCallEventEnum.CALL_FORCE_INSERT_SUCCESS_LISTENER,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no}))):ae.emit(exports.CallSipCallEventEnum.CALL_FORCE_INSERT_FAILED))},this.ws.onclose=A=>{ae.emit(exports.EventName.FAIL_NOTIFICATION,"链接已断开,请检查网络"),this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=A=>{ae.emit(exports.EventName.FAIL_NOTIFICATION,"连接失败,请检查网络"),this.ws?.close()}}startHeartbeat(){const A=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 5000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),e=URL.createObjectURL(A);this.heartbeatWorker=new Worker(e),this.heartbeatWorker.onmessage=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now())},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify(A)),0!==A.type&&Xs("%cWebSocket 发送消息:","color: green; font-weight: bold;",A)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}reconnect(){this.initWebSocket()}static __internalClose(){_s&&(_s.close(),_s=null)}static __internalSend(A){if(!_s)throw new Error("WebSocket 尚未初始化");_s.sendMessage(A)}}class Ai{constructor(A){this.sipClient=null,this.sipClient=A}roleMute(){const A=le.get("isCalling"),e=Ve.sessionId;if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}))}holdCall(){this.roleMute();const A=le.get("isHold"),{sessionId:e}=Ve;if(!e)return;if(!le.get("actionConfigs").includes("hold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿保持"}));if(A)throw new Error(JSON.stringify({code:1,msg:"当前已处于保持状态"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CALL_HOLD,data:{session_id:e}})}unholdCall(){this.roleMute();const{isHold:A}=le.getState(),{sessionId:e}=Ve;if(!le.get("actionConfigs").includes("unhold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取消保持"}));if(e){if(!A)throw new Error(JSON.stringify({code:1,msg:"当前未处于保持状态"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CALL_UNHOLD,data:{session_id:e}})}}sendDTMF(A){if(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!le.get("actionConfigs").includes("dtmf"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿发送按键"}));const{isCalling:e}=le.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));this.sipClient.sendDTMF(A)}cancelCall(){if(!le.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;ae.emit(exports.CallSipCallEventEnum.REJECT,{session_id:A}),$s.__internalSend({type:exports.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:A}})}async consultCall(A){this.roleMute();const{isCalling:e,outCallIsAnswer:t,consultIsAnswer:s,incomingIsAnswer:i}=le.getState(),n=Ve.sessionId;if(!le.get("actionConfigs").includes("consult"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询"}));if(s)throw new Error(JSON.stringify({code:1,msg:"当前正在咨询"}));if(!(e||t||i))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!n)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:A}})}async answerCall(){if(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}makeCall(A){if("string"!=typeof A||""===A.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));const e={};if(Rs(A))e.trace_id=A;else{if(!/^(?:1[3-9]\d{9}|0\d{2,3}-?\d{7,8})$/.test(A.trim()))throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));e.customer_phone=A.replace(/[\s\r\n-]+/g,"")}const t=le.get("isCalling"),s=le.get("selectOutNumber")||"";if(t)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.OUTGOING),$s.__internalSend({type:exports.WebsocketTypeEnum.OUT_CALL,data:{...e,caller:s.replace(/[\s\r\n-]+/g,"")}})}previewCall(A,e){const t={};Rs(A)?t.trace_id=A:t.customer_phone=A.replace(/[\s\r\n-]+/g,"");const s=le.get("isCalling"),i=le.get("selectOutNumber")||"";if(s)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));if("string"!=typeof A||""===A.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));le.updateIsCalling(!0),le.updateDirection(exports.DirectionEnum.OUTGOING),$s.__internalSend({type:exports.WebsocketTypeEnum.PREVIEW_OUT_CALL,data:{...t,caller:i,preview_task_id:e}})}async hangup(){if(!le.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;$s.__internalSend({type:exports.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:A}})}mute(){this.roleMute();const A=le.get("actionConfigs"),e=le.get("isMuted"),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前未处于静音状态"}));if(!A.includes("mute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:exports.WebsocketTypeEnum.MUTE,data:{session_id:t}})}unmute(){this.roleMute();const A=le.get("actionConfigs"),e=le.get("isMuted"),t=Ve.sessionId;if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于未静音状态"}));if(!A.includes("unmute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:exports.WebsocketTypeEnum.UNMUTE,data:{session_id:t}})}consultTransfer(){this.roleMute();const A=le.get("consultIsAnswer"),e=Ve.sessionId;if(!le.get("actionConfigs").includes("consult_transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询转移"}));if(!A)throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_TRANSFER,data:{session_id:e}})}satisfactionEvaluation(){this.roleMute();const A=Ve.sessionId;if(!le.get("actionConfigs").includes("satisfaction"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用满意度评价"}));$s.__internalSend({type:exports.WebsocketTypeEnum.SATISFACTION_EVALUATION,data:{session_id:A}})}startConference(){this.roleMute();if(!le.get("actionConfigs").includes("conference"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用三方会议"}));const A=Ve.sessionId;if(!le.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_THREE_WAY,data:{session_id:A}})}consultRetrieve(){this.roleMute();if(!le.get("actionConfigs").includes("consult_retrieve"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取回通话"}));const A=Ve.sessionId;if(!le.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_RETURN_CALL,data:{session_id:A}})}async transferAgent(A){this.roleMute();if(!le.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));const{transferIsAnswer:e}=le.getState(),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:exports.WebsocketTypeEnum.TRANSFER,data:{session_id:t,transfer_type:0,transfer_dest:A}})}async transferOutline(A){this.roleMute();if(!le.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));if(!A)throw new Error(JSON.stringify({code:1,msg:"号码不能为空"}));if(!/^\d+$/.test(A))throw new Error(JSON.stringify({code:1,msg:"号码格式错误"}));const{transferIsAnswer:e}=le.getState(),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:exports.WebsocketTypeEnum.TRANSFER,data:{session_id:t,transfer_type:2,transfer_dest:A}})}}var ei;class ti{static{this._instance=null}#A;#e;#t;#s;#i;#n;#o;#r;static{this._timer=null}#a;constructor(){if(this.#A=null,this.#e=new Ks,this.#s=null,this.#i=!1,this.#r=!1,this.#a=null,this.#V=()=>{le.updateIsNextState(!0)},this.#c=()=>{le.updateIsNextState(!1)},this.initWebRtc=async()=>{if(this.#A)return;const A=Ve.agentInfo.sip_account_list.find(A=>1===A.device_type);if(!A)throw new Error(JSON.stringify({code:1,msg:"未找到 sip_account_list"}));{const e=A.sip_register_addr;this.#A=new ge({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#l),await this.#A.start()}},this.#l=A=>{const{type:e,data:t}=A;ae.emit(e,t)},!ei._creatingInstance)throw new Error("请使用 YSYTAgentSdk.getInstance() 获取实例");clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#h();he.updateRttObject(A)},2e3),Ps.requestMediaPermissions(),this.#o=le.subscribeKey("isNextState",async A=>{if(A){await this.#e._agentLogin(xs);1===le.get("answerDevice")&&await this.#A.reconnect();let A="";const e=new URL(Gs).host;A=Gs.includes("https")?`wss://${e}`:`ws://${e}`;const{agent_no:t}=Ve.agentInfo;$s.getInstance({url:`${A}/ccs-ws/api/v1/ws/call/${t}?Authorization=`,sipClient:this.#A}),Ve.stateObject.state===exports.AgentStatus.OFFLINE&&setTimeout(()=>{this.#e._changeState({data:{...this.#a,state_name:this.#a.state===exports.AgentStatus.BUSY&&"整理"===this.#a.state_name?"忙碌":this.#a.state_name},success:()=>{le.updateDisplayText(""),ae.emit(exports.CallSipCallEventEnum.AGENT_STATE,this.#a)}})},10)}else this.#a=Ve.stateObject,$s.__internalClose(),le.updateDisplayText("离线")}),this.#n=le.subscribeKey("answerDevice",async A=>{1===A?Ve.stateObject.state===exports.AgentStatus.UNREGISTERED&&await this.#e._changeState({data:{...Ve.stateBeforeChange,state_name:Ve.stateBeforeChange.state===exports.AgentStatus.IDLE?"空闲":"忙碌"}}):await this.destroyRtc()}),this.on(exports.EventName.KICK_OFF,()=>{this.destroy()}),window.addEventListener("beforeunload",A=>{A.returnValue="",this.destroy()}),window.addEventListener("online",this.#V),window.addEventListener("offline",this.#c)}#V;#c;async#g(){const A=le.get("isNextState");try{await Ns(),A||le.updateIsNextState(!0)}catch(e){ae.emit(exports.EventName.FAIL_NOTIFICATION,"网络断开,请检查网络"),A&&le.updateIsNextState(!1)}}#q(){ei._timer||(ei._timer=setInterval(()=>this.#g(),3e3))}static get instance(){return this._instance}static async destroyInstance(){this._instance&&(await this._instance.destroy(),this._instance=null)}static getInstance(A){if(!this._instance){if(!A)throw new Error("首次调用必须传入配置参数");const{url:e,appKey:t,appSecret:s,agentNo:i}=A;Gs=e||"https://aicc-api.yescloudy.com",Fs=t,Ys=s,xs=i,ei._creatingInstance=!0,this._instance=new ei,delete ei._creatingInstance}return this._instance}getInit(){return this.#r}async init({actionNodeParams:A,enableBrowserAlert:e,logBuiltinEnabled:t,browserAlertTime:s,initialState:i,initDevice:n}){try{let o="";const r=new URL(Gs).host;o=Gs.includes("https")?`wss://${r}`:`ws://${r}`;const a=$s.getInstance({url:`${o}/ccs-ws/api/v1/ws/call/${xs}?Authorization=`,sipClient:null,onOpen:async()=>{const{viewHtmlElement:o,rttHTML:r}=A||{};Ve.logBuiltinEnabled=t||!1,Ve.browserAlertTime=s||5e3,await this.#e._agentLogin(xs);const{current_answer_device:V,current_state:c,out_display_number:l,out_display_select_switch:h}=Ve.agentInfo;(i||c)===exports.AgentStatus.IDLE?(le.updateActionConfigs(ft),Ve.stateObject={state:i||c,state_name:"空闲"},Ve.stateBeforeChange=Ve.stateObject):(i||c)===exports.AgentStatus.BUSY?(le.updateActionConfigs(Bt),Ve.stateObject={state:c,state_name:"忙碌"},Ve.stateBeforeChange=Ve.stateObject):(i||c)===exports.AgentStatus.UNREGISTERED&&(le.updateActionConfigs(Bt),Ve.stateObject={state:c,state_name:"未注册"}),1===h?le.updateSelectOutNumber(l):le.updateSelectOutNumber(""),le.updateAnswerDevice(n||V),Ks.setInitRtcFn(this.initWebRtc),1===(n||V)&&(await this.initWebRtc(),a.setSipClient(this.#A)),this.#t=new Ai(this.#A),A&&o&&(this.#i=!0,new Ws({container:o,rttHTML:r,statusParams:{state:Ve.stateObject.state,statusName:Ve.stateObject.state_name}},this,this.#t)),Ve.enableBrowserAlert=e,e&&Ps.requestPermission(),ae.emit(exports.EventName.AGENT_INIT_STATUS,!0),this.#r=!0,clearInterval(ei._timer),ei._timer=null,this.#q()}})}catch(A){this.#i&&Hs("初始化失败"),ae.emit(exports.EventName.AGENT_INIT_STATUS,!1),this.#r=!1}}#l;on(A,e){return ae.on(A,e),this}off(A,e){ae.off(A,e)}offAll(){ae.clearAllListeners()}async destroyRtc(){await(this.#A?.destroy()),this.#A=null}async destroy(){ei._instance&&(await this.destroyRtc(),this.#n?.(),this.#o?.(),clearInterval(this.#s),$s.__internalClose(),ae.emit(exports.EventName.DESTROY),this.offAll(),this.#i=!1,ei._instance=null,le.reset(),le.updateSelectOutNumber(""),clearInterval(ei._timer),ei._timer=null)}async#h(){return this.#A?this.#A.getNetworkStats():{}}get call_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{answerCall:A(()=>this.#t.answerCall()),makeCall:A=>this.#t.makeCall(A),previewMakeCall:(A,e)=>this.#t.previewCall(A,e),cancelCall:A(()=>this.#t.cancelCall()),hangup:A(()=>this.#t.hangup()),sendDTMF:A(A=>this.#t.sendDTMF(A)),holdCall:A(()=>this.#t.holdCall()),unholdCall:A(()=>this.#t.unholdCall()),consultCall:A(async A=>{try{await this.#t.consultCall(A)}catch(A){throw console.warn(A),A}}),consultRetrieve:A(()=>this.#t.consultRetrieve()),consultTransfer:A(()=>this.#t.consultTransfer()),mute:A(()=>this.#t.mute()),unmute:A(()=>this.#t.unmute()),satisfactionEvaluation:A(()=>this.#t.satisfactionEvaluation()),startConference:A(()=>this.#t.startConference()),transferAgent:A(A=>this.#t.transferAgent(A)),transferOutline:A(A=>this.#t.transferOutline(A)),earSpeakStart:A(A=>this.#e.earCall(A)),earSpeakStop:A(A=>this.#e.stopEarCall(A)),forceInsert:A(A=>this.#e.forceInsert(A)),forceDisconnect:A(A=>this.#e.forceDisconnect(A))}}get agent_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{changeDevice:A(A=>this.#e.changeDevice(A)),changeState:A(A=>this.#e.changeState(A)),getIdleAgentList:A(A=>this.#e.getIdleAgentList(A)),getAgentState:A(A=>this.#e.getAgentState(A)),setAgentExplicit:A(A=>this.#e.setAgentExplicit(A)),checkAgentLogin:A=>this.#e.checkAgentLogin(A),getCallRecord:A=>this.#e.getCallRecord(A),agentLogout:async(A,e)=>{try{await this.#e.logout(A),await this.destroy(),e?.({code:0,msg:""})}catch(A){}},listenAgentCall:A=>this.#e.listenCall(A)}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,out_display_data:s,out_display_select_switch:i,current_state:n}=Ve.agentInfo,{stateObject:o}=Ve,r={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:n,default_device:le.get("answerDevice"),out_display_data:s,out_display_select_switch:i,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:r[Number(A)]})),stateObject:o}}async getRealTimeCustomerInfo(){return le.get("customerObject")}setBrowserAlert(A){if("boolean"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));Ve.logBuiltinEnabled=A||!1}setBrowserAlertTime(A){if("number"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));Ve.browserAlertTime=A||3e3}}ei=ti,exports.default=ti;
@@ -911,4 +911,4 @@ Bs=Ts,function(){var t="input is invalid type",s="object"==typeof window,i=s?win
911
911
  `:""}
912
912
  </div>
913
913
  </my-popover>
914
- `;mt(s,this.rttHTML)}}class Ps{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const A=await navigator.mediaDevices.enumerateDevices();if(A.some(A=>"audioinput"===A.kind&&""!==A.label))return null;return await navigator.mediaDevices.getUserMedia({audio:!0})}catch(A){return console.warn("获取音频权限失败:",A),null}}static show(A,e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(A,{body:e,tag:`xy-global-notification${(new Date).getTime()}`,renotify:!0});i.onclick=()=>{window.focus(),i.close(),t?.()},setTimeout(()=>i.close(),1e3*(s||3))}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}const zs=console.log,Xs=(...A)=>{Ve.logBuiltinEnabled&&zs(...A)};let _s=null;class $s{constructor(A,e){this.url=A,this.onOpenCallback=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Ks,this.sipClient=null,this.pendingMessages=new Map,this.initWebSocket()}static getInstance({url:A,sipClient:e,onOpen:t}){if(!_s){if(!A)throw new Error("WebSocket 尚未初始化");_s=new $s(A,t),_s.sipClient=e}return _s}setSipClient(A){this.sipClient=A}stateIdleChange(){const{state:A}=Ve.stateObject;A!==Ae.IDLE&&this.apiClient._changeState({data:{...Ve.stateBeforeChange,state_name:Ve.stateBeforeChange.state===Ae.IDLE?"空闲":"忙碌"}})}inCallAutoAnswer(){const{soft_device_auto_answer:A,auto_answer_time:e}=Ve.agentInfo,t=1===A,s=he.get("direction");if(t&&s===ee.INCOMING){const A=Number(e)||0;A>0&&(Ve.autoAnswerTimer=setTimeout(()=>{this.sipClient?.answerCall(),Ve.autoAnswerTimer=null},1e3*A))}}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{he.updateCustomerInfo(A.data||{phone:A.data.phone,is_vip:0,customer_name:"未知客户",city:"未知",province:"未知",contact_count:0,in_contact_count:0,trace_id:A.data.trace_id,contact_count_month:0,in_contact_count_month:0})}})}catch(A){}}putAgentState(A,e){if(!A)return;if(5===e)return void this.stateIdleChange();Ve.sessionId="";const{post_call_process_time:t}=Ve.agentInfo,s=t||0;if(Ve.autoStateTimer&&(clearTimeout(Ve.autoStateTimer),Ve.autoStateTimer=null),he.updateCustomerInfo(void 0),s>0){const{state:A}=Ve.stateObject;if(A===Ae.IDLE)return;this.apiClient._changeState({data:{state:Ae.BUSY,state_name:"整理"}}),Ve.autoStateTimer=setTimeout(()=>{Ve.autoStateTimer=null,this.stateIdleChange()},1e3*s)}else this.stateIdleChange()}stateBusyChange(){Ve.sessionId="",clearTimeout(Ve.autoStateTimer),he.updateCustomerInfo(void 0),this.apiClient._changeState({data:{state:Ae.BUSY,state_name:"忙碌"}})}initWebSocket(){if(1===this.ws?.readyState)return;const A=Rs(Fs,Ys);this.ws=new WebSocket(this.url+A),this.ws.onopen=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now()),this.startHeartbeat(),this.manualClose=!1,this.onOpenCallback&&this.onOpenCallback()},this.ws.onmessage=async A=>{const e=JSON.parse(A.data),{type:t,data:s,code:i,msg:n,msg_id:o}=e;if(0===t&&o){const A=this.pendingMessages.get(o),e=performance.now()-A;Ve.latency=parseFloat(e.toFixed(2)),this.pendingMessages.delete(o)}if(0!==t&&Xs("%cWebSocket 收到消息:","color: blue; font-weight: bold;",e),t!==te.OUT_CALL&&t!==te.PREVIEW_OUT_CALL||(0!==i?(he.reset(),ae.emit(ie.OUT_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n),he.updateActionConfigs(ft),setTimeout(()=>{he.updateCustomerInfo(void 0)},500),this.stateIdleChange()):0===i&&(ae.emit(ie.OUT_SUCCESS),clearTimeout(Ve.autoStateTimer))),t===te.AGENT_STATE){const{state:A,state_name:e}=s;Ve.stateObject={state:A,state_name:e},Ve.stateBeforeChange?.state||Ve.stateObject.state!==Ae.IDLE&&(Ve.stateObject.state!==Ae.BUSY||"整理"===e)||(Ve.stateBeforeChange=Ve.stateObject),"振铃中"===e&&he.updateDisplayText(oe.AGENT_RINGING),A===Ae.UNREGISTERED&&he.updateActionConfigs(Mt),A===Ae.IDLE&&Ve.stateObject.state===Ae.UNREGISTERED&&he.updateActionConfigs(ft),ae.emit(ie.AGENT_STATE,{state:A,state_name:e})}if(t===te.OUT_CALL_INCOMING_CALL){try{await this.getCustomerInfo(s.trace_id||s.customer_phone)}catch(A){console.error(A)}s.preview_task_id?ae.emit(ie.PREVIEW_OUT_INCOMING_CALL,{customer_phone:s.customer_phone,session_id:s.session_id,preview_task_id:s.preview_task_id,trace_id:s.trace_id}):ae.emit(ie.OUT_INCOMING_CALL,{customer_phone:s.customer_phone,session_id:s.session_id,trace_id:s.trace_id}),Ve.sessionId=s.session_id,he.updateActionConfigs(Qt)}if(t===te.OUT_CALL_END)if(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.OUT_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0);else if(2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.OUR_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0);else if(2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){he.get("isCalling")&&(he.updateDisplayText(oe.CALLING),ae.emit(ie.OTHER_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(St))}else if(3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.THREE_WAY_OUR_SIDE_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0);else if(4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.TRANSFER_END,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0);else if(4===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){ae.emit(ie.TRANSFER_FAILED,"未知原因"),ae.emit(ne.FAIL_NOTIFICATION,"转接失败");const A=he.get("direction");A===ee.OUTGOING?he.updateActionConfigs(St):A===ee.INCOMING&&he.updateActionConfigs(Ut)}else 5===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(Ve.monitoredAgentNo="",Ve.earSpeakAgent="",he.reset(),ae.emit(ie.LISTEN_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0,5));if(t===te.OUT_CALL_RINGING&&1===s.type&&(ae.emit(ie.OUT_RINGING,{session_id:Ve.sessionId,type:s.type}),he.updateDisplayText(oe.RINGING)),t===te.OUT_CALL_ANSWER&&(clearTimeout(Ve.autoStateTimer),he.updateIsCalling(!0),ae.emit(ie.OUT_OFF_ANSWER,{session_id:Ve.sessionId}),he.updateOutCallIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(St)),t===te.CONSULT_RINGING&&(ae.emit(ie.CONSULT_RINGING,{session_id:s.session_id}),he.updateDisplayText(oe.AGENT_RINGING),he.updateActionConfigs([]),clearTimeout(Ve.autoStateTimer)),t===te.CONSULT_ANSWER&&(ae.emit(ie.CONSULT_OFF_HOOK,{session_id:s.session_id}),he.updateConsultIsAnswer(!0),he.updateDisplayText(oe.CONSULTING),he.updateActionConfigs(Tt)),t===te.CONSULT_FAIL&&(ae.emit(ie.CONSULT_FAILED,{custom_reason:s.custom_reason}),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(St)),t===te.CONSULT_CALL_IN&&(ae.emit(ie.CONSULT_INCOMING,{agent_no:s.agent_no,agent_mane:s.agent_name,session_id:s.session_id}),Ve.sessionId=s.session_id,he.updateIsCalling(!0),he.updateDirection(ee.CONSULT),he.updateDisplayText(oe.CONSULT_CALL_IN),he.updateActionConfigs(Dt),Ve.enableBrowserAlert&&Ps.show("📞 咨询来电",`坐席 [${s.agent_name}] 正在咨询...`,()=>{ae.emit(ne.NOTIFICATION_CLICK,{agent_mane:s.agent_name,agent_no:s.agent_no})},Ve.browserAlertTime)),t===te.CONSULT_CALL_IN_SUCCESS&&(ae.emit(ie.CONSULT_CALL_IN_SUCCESS,{session_id:s.session_id}),he.updateConsultIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(yt)),t===te.CONSULT_RETURN_CALL_SUCCESS&&("success"===s.status?(he.updateConsultIsAnswer(!1),ae.emit(ie.CONSULT_RETURN_CALL_SUCCESS),he.updateDisplayText(oe.CALLING),ae.emit(ie.OTHER_SIDE_CONSULT_HANGUP),he.updateActionConfigs(St)):ae.emit(ne.FAIL_NOTIFICATION,"媒体失败")),t===te.MUTE&&(0===i?(he.updateIsMuted(!0),ae.emit(ie.MUTE_SUCCESS),he.updateDisplayText(oe.MUTING)):(ae.emit(ie.MUTE_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.UNMUTE&&(0===i?(he.updateIsMuted(!1),ae.emit(ie.UNMUTE_SUCCESS),he.updateDisplayText(oe.CALLING)):(ae.emit(ie.UNMUTE_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CALL_HOLD&&(0===i?(he.updateIsHold(!0),he.updateDisplayText(oe.HOLDING),ae.emit(ie.HOLD_SUCCESS)):(ae.emit(ie.HOLD_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CALL_UNHOLD&&(0===i?(he.updateDisplayText(oe.CALLING),he.updateIsHold(!1),ae.emit(ie.UNHOLD_SUCCESS)):(ae.emit(ie.UNHOLD_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CONSULT_TRANSFER&&(0===i?ae.emit(ie.CONSULT_TRANSFER_SUCCESS):(ae.emit(ie.CONSULT_TRANSFER_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CONSULT_TRANSFER_FAILED&&ae.emit(ie.CONSULT_TRANSFER_FAILED,s.status),t===te.CONSULT_TRANSFER_OFF_HOOK&&(he.updateDirection(ee.INCOMING),he.updateDisplayText(oe.CALLING),ae.emit(ie.CONSULT_TRANSFER_OFF_HOOK),he.updateActionConfigs(Ut),he.updateIncomingIsAnswer(!0),he.updateConsultIsAnswer(!1)),t===te.INCOMING_CALL){clearTimeout(Ve.autoStateTimer),Ve.sessionId=s.session_id;try{await this.getCustomerInfo(s.trace_id||s.customer_phone)}catch(A){console.error(A)}he.updateIsCalling(!0),he.updateDirection(ee.INCOMING),he.updateDisplayText(oe.INCOMING_CALL),this.inCallAutoAnswer(),1===s.direction&&ae.emit(ie.INCOMING_CALL,{customer_phone:s.customer_phone,trace_id:s.trace_id,session_id:s.session_id}),3===s.direction&&ae.emit(ie.PREDICT_INCOMING_CALL,{customer_phone:s.customer_phone,trace_id:s.trace_id,session_id:s.session_id}),he.updateActionConfigs(Dt),Ve.enableBrowserAlert&&Ps.show("📞 客户来电",`客户 [${s.customer_phone}] 正在呼入...`,()=>{ae.emit(ne.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})},Ve.browserAlertTime)}if(t===te.INCOMING_CALL_OFF_HOOK&&(he.updateIncomingIsAnswer(!0),ae.emit(ie.INCOMING_CALL_OFF_HOOK,{session_id:Ve.sessionId}),he.updateActionConfigs(Ut),he.updateDisplayText(oe.CALLING)),t===te.INCOMING_CALL_END)if(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),he.reset(),ae.emit(ie.INCOMING_CALL_END,{session_id:s.session_id}),he.updateActionConfigs(ft);else if(2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.OUR_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),this.putAgentState(!0),he.updateActionConfigs(ft);else if(2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no)he.updateDisplayText(oe.CALLING),ae.emit(ie.OTHER_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(St);else if(3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),he.reset(),ae.emit(ie.THREE_WAY_OUR_SIDE_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft);else if(4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),he.reset(),ae.emit(ie.TRANSFER_END,{session_id:s.session_id}),he.updateActionConfigs(ft);else if(4===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){ae.emit(ie.TRANSFER_FAILED,"未知原因"),ae.emit(ne.FAIL_NOTIFICATION,"转接失败");const A=he.get("direction");A===ee.OUTGOING?he.updateActionConfigs(St):A===ee.INCOMING&&he.updateActionConfigs(Ut)}else 5===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(!0,5),Ve.monitoredAgentNo="",Ve.earSpeakAgent="",he.reset(),ae.emit(ie.LISTEN_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft));if(t===te.SATISFACTION_EVALUATION&&(0===i?ae.emit(ie.SATISFACTION_EVALUATION_SUCCESS):(ae.emit(ie.SATISFACTION_EVALUATION_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CONSULT_THREE_WAY&&(0!==i?(ae.emit(ie.CONSULT_THREE_WAY_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n)):0===i&&he.updateIsMeeting(!0)),t===te.CONSULT_THREE_WAY_RESULT&&("success"===s.status?(he.updateDirection(ee.MEETING),he.updateDisplayText(oe.MEETING),he.updateActionConfigs(Rt),ae.emit(ie.CONSULT_THREE_WAY_SUCCESS)):(ae.emit(ie.CONSULT_THREE_WAY_FAILED,{conf_name:s.conf_name}),he.updateIsMeeting(!1))),t===te.TRANSFER_INCOMING_CALL&&(clearTimeout(Ve.autoStateTimer),s.agent_no===Ve.agentInfo.agent_no?(he.updateDisplayText(oe.TRANSFERRING),ae.emit(ie.TRANSFER_PROGRESS),he.updateActionConfigs([]),he.updateTransferIsAnswer(!0)):(Ve.sessionId=s.session_id,ae.emit(ie.TRANSFER_INCOMING_CALL,{agent_no:s.agent_no,agent_name:s.agent_name,session_id:s.session_id}),he.updateIsCalling(!0),he.updateDirection(ee.TRANSFER),he.updateDisplayText(oe.TRANSFER_INCOMING_CALL),he.updateActionConfigs(Dt),Ve.enableBrowserAlert&&Ps.show("📞 转接来电",`坐席 [${s.agent_no}] 正在转接...`,()=>{ae.emit(ne.NOTIFICATION_CLICK,{agent_no:s.agent_no})},Ve.browserAlertTime))),t===te.TRANSFER_OFF_HOOK&&(ae.emit(ie.TRANSFER_OFF_HOOK,{session_id:Ve.sessionId}),he.updateTransferIsAnswer(!1),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(Ut)),t===te.TRANSFER_FAILED&&"failed"===s.status){ae.emit(ie.TRANSFER_FAILED,"未知原因"),ae.emit(ne.FAIL_NOTIFICATION,"转接失败");const A=he.get("direction");A===ee.OUTGOING?he.updateActionConfigs(St):A===ee.INCOMING&&he.updateActionConfigs(Ut)}t===te.KICK_OFFLINE&&ae.emit(ne.KICK_OFF),t===te.CONTINUOUS_NOT_ANSWER&&(ae.emit(ne.FAIL_NOTIFICATION,`已连续 ${s.miss_count} 次未接, 设置忙碌`),this.stateBusyChange()),t===te.SIGN_OUT&&ae.emit(ne.SIGN_OUT),t===te.SIGN_IN_SWITCH_DEVICE&&ae.emit(ne.SIGN_IN_SWITCH_DEVICE,s),t===te.LISTEN_INCOMING_CALL&&(clearTimeout(Ve.autoStateTimer),Ve.sessionId=s.session_id,he.updateIsCalling(!0),he.updateDirection(ee.INCOMING),this.inCallAutoAnswer(),he.updateDisplayText(oe.LISTENING),he.updateActionConfigs(Dt),ae.emit(ie.LISTEN_INCOMING_CALL,{session_id:s.session_id}),Ve.enableBrowserAlert&&Ps.show("📞 监听来电","正在来电...",()=>{ae.emit(ne.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})},Ve.browserAlertTime)),t===te.LISTEN_INCOMING_CALL_OFF_HOOK&&(Ve.monitoredAgentNo=s.monitored_agent_no,Ve.earSpeakAgent="",he.updateIncomingIsAnswer(!0),ae.emit(ie.LISTEN_INCOMING_CALL_OFF_HOOK,{session_id:Ve.sessionId,monitored_agent_no:s.monitored_agent_no}),he.updateActionConfigs(kt),he.updateDisplayText(oe.CALLING)),t===te.LISTEN_CALL_FAILED&&"failed"===s.status&&(ae.emit(ie.LISTEN_CALL_FAILED),Ve.monitoredAgentNo=""),t===te.EAR_SPEECH&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&(he.updateActionConfigs(Gt),ae.emit(ie.EAR_SPEECH_BE_SUCCESS)),s.monitor_agent_no===Ve.agentInfo.agent_no&&(he.updateActionConfigs(Ft),ae.emit(ie.EAR_SPEECH_SUCCESS,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no}),Ve.earSpeakAgent=s.monitored_agent_no)):ae.emit(ie.EAR_SPEECH_FAILED)),t===te.STOP_EAR_SPEECH&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&he.updateActionConfigs(Ut),s.monitor_agent_no===Ve.agentInfo.agent_no&&he.updateActionConfigs(kt),Ve.earSpeakAgent="",ae.emit(ie.STOP_EAR_SPEECH_SUCCESS)):ae.emit(ie.STOP_EAR_SPEECH_FAILED)),t===te.CALL_FORCE_INSERT&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&(he.updateActionConfigs(Zt),ae.emit(ie.CALL_FORCE_INSERT_SUCCESS,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no})),s.monitor_agent_no===Ve.agentInfo.agent_no&&(he.updateActionConfigs(Yt),ae.emit(ie.CALL_FORCE_INSERT_SUCCESS_LISTENER,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no}))):ae.emit(ie.CALL_FORCE_INSERT_FAILED))},this.ws.onclose=A=>{ae.emit(ne.FAIL_NOTIFICATION,"链接已断开,请检查网络"),this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=A=>{ae.emit(ne.FAIL_NOTIFICATION,"连接失败,请检查网络"),this.ws?.close()}}startHeartbeat(){const A=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 5000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),e=URL.createObjectURL(A);this.heartbeatWorker=new Worker(e),this.heartbeatWorker.onmessage=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now())},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify(A)),0!==A.type&&Xs("%cWebSocket 发送消息:","color: green; font-weight: bold;",A)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}reconnect(){this.initWebSocket()}static __internalClose(){_s&&(_s.close(),_s=null)}static __internalSend(A){if(!_s)throw new Error("WebSocket 尚未初始化");_s.sendMessage(A)}}class Ai{constructor(A){this.sipClient=null,this.sipClient=A}roleMute(){const A=he.get("isCalling"),e=Ve.sessionId;if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}))}holdCall(){this.roleMute();const A=he.get("isHold"),{sessionId:e}=Ve;if(!e)return;if(!he.get("actionConfigs").includes("hold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿保持"}));if(A)throw new Error(JSON.stringify({code:1,msg:"当前已处于保持状态"}));$s.__internalSend({type:te.CALL_HOLD,data:{session_id:e}})}unholdCall(){this.roleMute();const{isHold:A}=he.getState(),{sessionId:e}=Ve;if(!he.get("actionConfigs").includes("unhold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取消保持"}));if(e){if(!A)throw new Error(JSON.stringify({code:1,msg:"当前未处于保持状态"}));$s.__internalSend({type:te.CALL_UNHOLD,data:{session_id:e}})}}sendDTMF(A){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!he.get("actionConfigs").includes("dtmf"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿发送按键"}));const{isCalling:e}=he.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));this.sipClient.sendDTMF(A)}cancelCall(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;ae.emit(ie.REJECT,{session_id:A}),$s.__internalSend({type:te.AGENT_HANGUP,data:{session_id:A}})}async consultCall(A){this.roleMute();const{isCalling:e,outCallIsAnswer:t,consultIsAnswer:s,incomingIsAnswer:i}=he.getState(),n=Ve.sessionId;if(!he.get("actionConfigs").includes("consult"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询"}));if(s)throw new Error(JSON.stringify({code:1,msg:"当前正在咨询"}));if(!(e||t||i))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!n)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));$s.__internalSend({type:te.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:A}})}async answerCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}makeCall(A){if("string"!=typeof A||""===A.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));const e={};if(Ds(A))e.trace_id=A;else{if(!/^(?:1[3-9]\d{9}|0\d{2,3}-?\d{7,8})$/.test(A.trim()))throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));e.customer_phone=A.replace(/[\s\r\n-]+/g,"")}const t=he.get("isCalling"),s=he.get("selectOutNumber")||"";if(t)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));he.updateIsCalling(!0),he.updateDirection(ee.OUTGOING),$s.__internalSend({type:te.OUT_CALL,data:{...e,caller:s.replace(/[\s\r\n-]+/g,"")}})}previewCall(A,e){const t={};Ds(A)?t.trace_id=A:t.customer_phone=A.replace(/[\s\r\n-]+/g,"");const s=he.get("isCalling"),i=he.get("selectOutNumber")||"";if(s)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));if("string"!=typeof A||""===A.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));he.updateIsCalling(!0),he.updateDirection(ee.OUTGOING),$s.__internalSend({type:te.PREVIEW_OUT_CALL,data:{...t,caller:i,preview_task_id:e}})}async hangup(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;$s.__internalSend({type:te.AGENT_HANGUP,data:{session_id:A}})}mute(){this.roleMute();const A=he.get("actionConfigs"),e=he.get("isMuted"),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前未处于静音状态"}));if(!A.includes("mute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:te.MUTE,data:{session_id:t}})}unmute(){this.roleMute();const A=he.get("actionConfigs"),e=he.get("isMuted"),t=Ve.sessionId;if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于未静音状态"}));if(!A.includes("unmute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:te.UNMUTE,data:{session_id:t}})}consultTransfer(){this.roleMute();const A=he.get("consultIsAnswer"),e=Ve.sessionId;if(!he.get("actionConfigs").includes("consult_transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询转移"}));if(!A)throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:te.CONSULT_TRANSFER,data:{session_id:e}})}satisfactionEvaluation(){this.roleMute();const A=Ve.sessionId;if(!he.get("actionConfigs").includes("satisfaction"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用满意度评价"}));$s.__internalSend({type:te.SATISFACTION_EVALUATION,data:{session_id:A}})}startConference(){this.roleMute();if(!he.get("actionConfigs").includes("conference"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用三方会议"}));const A=Ve.sessionId;if(!he.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:te.CONSULT_THREE_WAY,data:{session_id:A}})}consultRetrieve(){this.roleMute();if(!he.get("actionConfigs").includes("consult_retrieve"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取回通话"}));const A=Ve.sessionId;if(!he.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:te.CONSULT_RETURN_CALL,data:{session_id:A}})}async transferAgent(A){this.roleMute();if(!he.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));const{transferIsAnswer:e}=he.getState(),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:te.TRANSFER,data:{session_id:t,transfer_type:0,transfer_dest:A}})}async transferOutline(A){this.roleMute();if(!he.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));if(!A)throw new Error(JSON.stringify({code:1,msg:"号码不能为空"}));if(!/^\d+$/.test(A))throw new Error(JSON.stringify({code:1,msg:"号码格式错误"}));const{transferIsAnswer:e}=he.getState(),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:te.TRANSFER,data:{session_id:t,transfer_type:2,transfer_dest:A}})}}var ei;class ti{static{this._instance=null}#A;#e;#t;#s;#i;#n;#o;#r;static{this._timer=null}#a;constructor(){if(this.#A=null,this.#e=new Ks,this.#s=null,this.#i=!1,this.#r=!1,this.#a=null,this.#V=()=>{he.updateIsNextState(!0)},this.#c=()=>{he.updateIsNextState(!1)},this.initWebRtc=async()=>{if(this.#A)return;const A=Ve.agentInfo.sip_account_list.find(A=>1===A.device_type);if(!A)throw new Error(JSON.stringify({code:1,msg:"未找到 sip_account_list"}));{const e=A.sip_register_addr;this.#A=new ge({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#h),await this.#A.start()}},this.#h=A=>{const{type:e,data:t}=A;ae.emit(e,t)},!ei._creatingInstance)throw new Error("请使用 YSYTAgentSdk.getInstance() 获取实例");clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#l();le.updateRttObject(A)},2e3),Ps.requestMediaPermissions(),this.#o=he.subscribeKey("isNextState",async A=>{if(A){await this.#e._agentLogin(Zs);1===he.get("answerDevice")&&await this.#A.reconnect();let A="";const e=new URL(Gs).host;A=Gs.includes("https")?`wss://${e}`:`ws://${e}`;const{agent_no:t}=Ve.agentInfo;$s.getInstance({url:`${A}/ccs-ws/api/v1/ws/call/${t}?Authorization=`,sipClient:this.#A}),Ve.stateObject.state===Ae.OFFLINE&&setTimeout(()=>{this.#e._changeState({data:{...this.#a,state_name:this.#a.state===Ae.BUSY&&"整理"===this.#a.state_name?"忙碌":this.#a.state_name},success:()=>{he.updateDisplayText(""),ae.emit(ie.AGENT_STATE,this.#a)}})},10)}else this.#a=Ve.stateObject,$s.__internalClose(),he.updateDisplayText("离线")}),this.on(ne.KICK_OFF,()=>{this.destroy()}),window.addEventListener("beforeunload",A=>{A.returnValue="",this.destroy()}),window.addEventListener("online",this.#V),window.addEventListener("offline",this.#c)}#V;#c;async#g(){const A=he.get("isNextState");try{await xs(),A||he.updateIsNextState(!0)}catch(e){ae.emit(ne.FAIL_NOTIFICATION,"网络断开,请检查网络"),A&&he.updateIsNextState(!1)}}#q(){ei._timer||(ei._timer=setInterval(()=>this.#g(),3e3))}static get instance(){return this._instance}static async destroyInstance(){this._instance&&(await this._instance.destroy(),this._instance=null)}static getInstance(A){if(!this._instance){if(!A)throw new Error("首次调用必须传入配置参数");const{url:e,appKey:t,appSecret:s,agentNo:i}=A;Gs=e||"https://aicc-api.yescloudy.com",Fs=t,Ys=s,Zs=i,ei._creatingInstance=!0,this._instance=new ei,delete ei._creatingInstance}return this._instance}getInit(){return this.#r}async init({actionNodeParams:A,enableBrowserAlert:e,logBuiltinEnabled:t,browserAlertTime:s,initialState:i,initDevice:n}){try{let o="";const r=new URL(Gs).host;o=Gs.includes("https")?`wss://${r}`:`ws://${r}`;const a=$s.getInstance({url:`${o}/ccs-ws/api/v1/ws/call/${Zs}?Authorization=`,sipClient:null,onOpen:async()=>{const{viewHtmlElement:o,rttHTML:r}=A||{};Ve.logBuiltinEnabled=t||!1,Ve.browserAlertTime=s||5e3,await this.#e._agentLogin(Zs);const{current_answer_device:V,current_state:c,out_display_number:h,out_display_select_switch:l}=Ve.agentInfo;(i||c)===Ae.IDLE?(he.updateActionConfigs(ft),Ve.stateObject={state:i||c,state_name:"空闲"},Ve.stateBeforeChange=Ve.stateObject):(i||c)===Ae.BUSY?(he.updateActionConfigs(Bt),Ve.stateObject={state:c,state_name:"忙碌"},Ve.stateBeforeChange=Ve.stateObject):(i||c)===Ae.UNREGISTERED&&(he.updateActionConfigs(Bt),Ve.stateObject={state:c,state_name:"未注册"}),1===l?he.updateSelectOutNumber(h):he.updateSelectOutNumber(""),he.updateAnswerDevice(n||V),1===(n||V)&&(await this.initWebRtc(),Ks.setInitRtcFn(this.initWebRtc),a.setSipClient(this.#A)),this.#t=new Ai(this.#A),A&&o&&(this.#i=!0,new Ws({container:o,rttHTML:r,statusParams:{state:Ve.stateObject.state,statusName:Ve.stateObject.state_name}},this,this.#t)),Ve.enableBrowserAlert=e,e&&Ps.requestPermission(),ae.emit(ne.AGENT_INIT_STATUS,!0),this.#r=!0,clearInterval(ei._timer),ei._timer=null,this.#q(),this.#n=he.subscribeKey("answerDevice",async A=>{1===A?Ve.stateObject.state===Ae.UNREGISTERED&&await this.#e._changeState({data:{...Ve.stateBeforeChange,state_name:Ve.stateBeforeChange.state===Ae.IDLE?"空闲":"忙碌"}}):await this.destroyRtc()})}})}catch(A){this.#i&&Hs("初始化失败"),ae.emit(ne.AGENT_INIT_STATUS,!1),this.#r=!1}}#h;on(A,e){return ae.on(A,e),this}off(A,e){ae.off(A,e)}offAll(){ae.clearAllListeners()}async destroyRtc(){await(this.#A?.destroy()),this.#A=null}async destroy(){ei._instance&&(await this.destroyRtc(),this.#n?.(),this.#o?.(),clearInterval(this.#s),$s.__internalClose(),ae.emit(ne.DESTROY),this.offAll(),this.#i=!1,ei._instance=null,he.reset(),he.updateSelectOutNumber(""),clearInterval(ei._timer),ei._timer=null)}async#l(){return this.#A?this.#A.getNetworkStats():{}}get call_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{answerCall:A(()=>this.#t.answerCall()),makeCall:A=>this.#t.makeCall(A),previewMakeCall:(A,e)=>this.#t.previewCall(A,e),cancelCall:A(()=>this.#t.cancelCall()),hangup:A(()=>this.#t.hangup()),sendDTMF:A(A=>this.#t.sendDTMF(A)),holdCall:A(()=>this.#t.holdCall()),unholdCall:A(()=>this.#t.unholdCall()),consultCall:A(async A=>{try{await this.#t.consultCall(A)}catch(A){throw console.warn(A),A}}),consultRetrieve:A(()=>this.#t.consultRetrieve()),consultTransfer:A(()=>this.#t.consultTransfer()),mute:A(()=>this.#t.mute()),unmute:A(()=>this.#t.unmute()),satisfactionEvaluation:A(()=>this.#t.satisfactionEvaluation()),startConference:A(()=>this.#t.startConference()),transferAgent:A(A=>this.#t.transferAgent(A)),transferOutline:A(A=>this.#t.transferOutline(A)),earSpeakStart:A(A=>this.#e.earCall(A)),earSpeakStop:A(A=>this.#e.stopEarCall(A)),forceInsert:A(A=>this.#e.forceInsert(A)),forceDisconnect:A(A=>this.#e.forceDisconnect(A))}}get agent_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{changeDevice:A(A=>this.#e.changeDevice(A)),changeState:A(A=>this.#e.changeState(A)),getIdleAgentList:A(A=>this.#e.getIdleAgentList(A)),getAgentState:A(A=>this.#e.getAgentState(A)),setAgentExplicit:A(A=>this.#e.setAgentExplicit(A)),checkAgentLogin:A=>this.#e.checkAgentLogin(A),getCallRecord:A=>this.#e.getCallRecord(A),agentLogout:async(A,e)=>{try{await this.#e.logout(A),await this.destroy(),e?.({code:0,msg:""})}catch(A){}},listenAgentCall:A=>this.#e.listenCall(A)}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,out_display_data:s,out_display_select_switch:i,current_state:n}=Ve.agentInfo,{stateObject:o}=Ve,r={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:n,default_device:he.get("answerDevice"),out_display_data:s,out_display_select_switch:i,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:r[Number(A)]})),stateObject:o}}async getRealTimeCustomerInfo(){return he.get("customerObject")}setBrowserAlert(A){if("boolean"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));Ve.logBuiltinEnabled=A||!1}setBrowserAlertTime(A){if("number"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));Ve.browserAlertTime=A||3e3}}ei=ti,import.meta.hot&&import.meta.hot.dispose(()=>{window.location.reload()});export{Ae as AgentStatus,ie as CallSipCallEventEnum,ee as DirectionEnum,oe as DisplayTextEnum,ne as EventName,se as WebRtcCallSipEventEnum,te as WebsocketTypeEnum,ti as default};
914
+ `;mt(s,this.rttHTML)}}class Ps{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const A=await navigator.mediaDevices.enumerateDevices();if(A.some(A=>"audioinput"===A.kind&&""!==A.label))return null;return await navigator.mediaDevices.getUserMedia({audio:!0})}catch(A){return console.warn("获取音频权限失败:",A),null}}static show(A,e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(A,{body:e,tag:`xy-global-notification${(new Date).getTime()}`,renotify:!0});i.onclick=()=>{window.focus(),i.close(),t?.()},setTimeout(()=>i.close(),1e3*(s||3))}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}const zs=console.log,Xs=(...A)=>{Ve.logBuiltinEnabled&&zs(...A)};let _s=null;class $s{constructor(A,e){this.url=A,this.onOpenCallback=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Ks,this.sipClient=null,this.pendingMessages=new Map,this.initWebSocket()}static getInstance({url:A,sipClient:e,onOpen:t}){if(!_s){if(!A)throw new Error("WebSocket 尚未初始化");_s=new $s(A,t),_s.sipClient=e}return _s}setSipClient(A){this.sipClient=A}stateIdleChange(){const{state:A}=Ve.stateObject;A!==Ae.IDLE&&this.apiClient._changeState({data:{...Ve.stateBeforeChange,state_name:Ve.stateBeforeChange.state===Ae.IDLE?"空闲":"忙碌"}})}inCallAutoAnswer(){const{soft_device_auto_answer:A,auto_answer_time:e}=Ve.agentInfo,t=1===A,s=he.get("direction");if(t&&s===ee.INCOMING){const A=Number(e)||0;A>0&&(Ve.autoAnswerTimer=setTimeout(()=>{this.sipClient?.answerCall(),Ve.autoAnswerTimer=null},1e3*A))}}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{he.updateCustomerInfo(A.data||{phone:A.data.phone,is_vip:0,customer_name:"未知客户",city:"未知",province:"未知",contact_count:0,in_contact_count:0,trace_id:A.data.trace_id,contact_count_month:0,in_contact_count_month:0})}})}catch(A){}}putAgentState(A,e){if(!A)return;if(5===e)return void this.stateIdleChange();Ve.sessionId="";const{post_call_process_time:t}=Ve.agentInfo,s=t||0;if(Ve.autoStateTimer&&(clearTimeout(Ve.autoStateTimer),Ve.autoStateTimer=null),he.updateCustomerInfo(void 0),s>0){const{state:A}=Ve.stateObject;if(A===Ae.IDLE)return;this.apiClient._changeState({data:{state:Ae.BUSY,state_name:"整理"}}),Ve.autoStateTimer=setTimeout(()=>{Ve.autoStateTimer=null,this.stateIdleChange()},1e3*s)}else this.stateIdleChange()}stateBusyChange(){Ve.sessionId="",clearTimeout(Ve.autoStateTimer),he.updateCustomerInfo(void 0),this.apiClient._changeState({data:{state:Ae.BUSY,state_name:"忙碌"}})}initWebSocket(){if(1===this.ws?.readyState)return;const A=Rs(Fs,Ys);this.ws=new WebSocket(this.url+A),this.ws.onopen=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now()),this.startHeartbeat(),this.manualClose=!1,this.onOpenCallback&&this.onOpenCallback()},this.ws.onmessage=async A=>{const e=JSON.parse(A.data),{type:t,data:s,code:i,msg:n,msg_id:o}=e;if(0===t&&o){const A=this.pendingMessages.get(o),e=performance.now()-A;Ve.latency=parseFloat(e.toFixed(2)),this.pendingMessages.delete(o)}if(0!==t&&Xs("%cWebSocket 收到消息:","color: blue; font-weight: bold;",e),t!==te.OUT_CALL&&t!==te.PREVIEW_OUT_CALL||(0!==i?(he.reset(),ae.emit(ie.OUT_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n),he.updateActionConfigs(ft),setTimeout(()=>{he.updateCustomerInfo(void 0)},500),this.stateIdleChange()):0===i&&(ae.emit(ie.OUT_SUCCESS),clearTimeout(Ve.autoStateTimer))),t===te.AGENT_STATE){const{state:A,state_name:e}=s;Ve.stateObject={state:A,state_name:e},Ve.stateBeforeChange?.state||Ve.stateObject.state!==Ae.IDLE&&(Ve.stateObject.state!==Ae.BUSY||"整理"===e)||(Ve.stateBeforeChange=Ve.stateObject),"振铃中"===e&&he.updateDisplayText(oe.AGENT_RINGING),A===Ae.UNREGISTERED&&he.updateActionConfigs(Mt),A===Ae.IDLE&&Ve.stateObject.state===Ae.UNREGISTERED&&he.updateActionConfigs(ft),ae.emit(ie.AGENT_STATE,{state:A,state_name:e})}if(t===te.OUT_CALL_INCOMING_CALL){try{await this.getCustomerInfo(s.trace_id||s.customer_phone)}catch(A){console.error(A)}s.preview_task_id?ae.emit(ie.PREVIEW_OUT_INCOMING_CALL,{customer_phone:s.customer_phone,session_id:s.session_id,preview_task_id:s.preview_task_id,trace_id:s.trace_id}):ae.emit(ie.OUT_INCOMING_CALL,{customer_phone:s.customer_phone,session_id:s.session_id,trace_id:s.trace_id}),Ve.sessionId=s.session_id,he.updateActionConfigs(Qt)}if(t===te.OUT_CALL_END)if(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.OUT_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0);else if(2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.OUR_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0);else if(2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){he.get("isCalling")&&(he.updateDisplayText(oe.CALLING),ae.emit(ie.OTHER_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(St))}else if(3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.THREE_WAY_OUR_SIDE_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0);else if(4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.TRANSFER_END,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0);else if(4===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){ae.emit(ie.TRANSFER_FAILED,"未知原因"),ae.emit(ne.FAIL_NOTIFICATION,"转接失败");const A=he.get("direction");A===ee.OUTGOING?he.updateActionConfigs(St):A===ee.INCOMING&&he.updateActionConfigs(Ut)}else 5===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(Ve.monitoredAgentNo="",Ve.earSpeakAgent="",he.reset(),ae.emit(ie.LISTEN_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft),this.putAgentState(!0,5));if(t===te.OUT_CALL_RINGING&&1===s.type&&(ae.emit(ie.OUT_RINGING,{session_id:Ve.sessionId,type:s.type}),he.updateDisplayText(oe.RINGING)),t===te.OUT_CALL_ANSWER&&(clearTimeout(Ve.autoStateTimer),he.updateIsCalling(!0),ae.emit(ie.OUT_OFF_ANSWER,{session_id:Ve.sessionId}),he.updateOutCallIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(St)),t===te.CONSULT_RINGING&&(ae.emit(ie.CONSULT_RINGING,{session_id:s.session_id}),he.updateDisplayText(oe.AGENT_RINGING),he.updateActionConfigs([]),clearTimeout(Ve.autoStateTimer)),t===te.CONSULT_ANSWER&&(ae.emit(ie.CONSULT_OFF_HOOK,{session_id:s.session_id}),he.updateConsultIsAnswer(!0),he.updateDisplayText(oe.CONSULTING),he.updateActionConfigs(Tt)),t===te.CONSULT_FAIL&&(ae.emit(ie.CONSULT_FAILED,{custom_reason:s.custom_reason}),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(St)),t===te.CONSULT_CALL_IN&&(ae.emit(ie.CONSULT_INCOMING,{agent_no:s.agent_no,agent_mane:s.agent_name,session_id:s.session_id}),Ve.sessionId=s.session_id,he.updateIsCalling(!0),he.updateDirection(ee.CONSULT),he.updateDisplayText(oe.CONSULT_CALL_IN),he.updateActionConfigs(Dt),Ve.enableBrowserAlert&&Ps.show("📞 咨询来电",`坐席 [${s.agent_name}] 正在咨询...`,()=>{ae.emit(ne.NOTIFICATION_CLICK,{agent_mane:s.agent_name,agent_no:s.agent_no})},Ve.browserAlertTime)),t===te.CONSULT_CALL_IN_SUCCESS&&(ae.emit(ie.CONSULT_CALL_IN_SUCCESS,{session_id:s.session_id}),he.updateConsultIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(yt)),t===te.CONSULT_RETURN_CALL_SUCCESS&&("success"===s.status?(he.updateConsultIsAnswer(!1),ae.emit(ie.CONSULT_RETURN_CALL_SUCCESS),he.updateDisplayText(oe.CALLING),ae.emit(ie.OTHER_SIDE_CONSULT_HANGUP),he.updateActionConfigs(St)):ae.emit(ne.FAIL_NOTIFICATION,"媒体失败")),t===te.MUTE&&(0===i?(he.updateIsMuted(!0),ae.emit(ie.MUTE_SUCCESS),he.updateDisplayText(oe.MUTING)):(ae.emit(ie.MUTE_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.UNMUTE&&(0===i?(he.updateIsMuted(!1),ae.emit(ie.UNMUTE_SUCCESS),he.updateDisplayText(oe.CALLING)):(ae.emit(ie.UNMUTE_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CALL_HOLD&&(0===i?(he.updateIsHold(!0),he.updateDisplayText(oe.HOLDING),ae.emit(ie.HOLD_SUCCESS)):(ae.emit(ie.HOLD_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CALL_UNHOLD&&(0===i?(he.updateDisplayText(oe.CALLING),he.updateIsHold(!1),ae.emit(ie.UNHOLD_SUCCESS)):(ae.emit(ie.UNHOLD_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CONSULT_TRANSFER&&(0===i?ae.emit(ie.CONSULT_TRANSFER_SUCCESS):(ae.emit(ie.CONSULT_TRANSFER_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CONSULT_TRANSFER_FAILED&&ae.emit(ie.CONSULT_TRANSFER_FAILED,s.status),t===te.CONSULT_TRANSFER_OFF_HOOK&&(he.updateDirection(ee.INCOMING),he.updateDisplayText(oe.CALLING),ae.emit(ie.CONSULT_TRANSFER_OFF_HOOK),he.updateActionConfigs(Ut),he.updateIncomingIsAnswer(!0),he.updateConsultIsAnswer(!1)),t===te.INCOMING_CALL){clearTimeout(Ve.autoStateTimer),Ve.sessionId=s.session_id;try{await this.getCustomerInfo(s.trace_id||s.customer_phone)}catch(A){console.error(A)}he.updateIsCalling(!0),he.updateDirection(ee.INCOMING),he.updateDisplayText(oe.INCOMING_CALL),this.inCallAutoAnswer(),1===s.direction&&ae.emit(ie.INCOMING_CALL,{customer_phone:s.customer_phone,trace_id:s.trace_id,session_id:s.session_id}),3===s.direction&&ae.emit(ie.PREDICT_INCOMING_CALL,{customer_phone:s.customer_phone,trace_id:s.trace_id,session_id:s.session_id}),he.updateActionConfigs(Dt),Ve.enableBrowserAlert&&Ps.show("📞 客户来电",`客户 [${s.customer_phone}] 正在呼入...`,()=>{ae.emit(ne.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})},Ve.browserAlertTime)}if(t===te.INCOMING_CALL_OFF_HOOK&&(he.updateIncomingIsAnswer(!0),ae.emit(ie.INCOMING_CALL_OFF_HOOK,{session_id:Ve.sessionId}),he.updateActionConfigs(Ut),he.updateDisplayText(oe.CALLING)),t===te.INCOMING_CALL_END)if(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),he.reset(),ae.emit(ie.INCOMING_CALL_END,{session_id:s.session_id}),he.updateActionConfigs(ft);else if(2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)he.reset(),ae.emit(ie.OUR_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),this.putAgentState(!0),he.updateActionConfigs(ft);else if(2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no)he.updateDisplayText(oe.CALLING),ae.emit(ie.OTHER_SIDE_CONSULT_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(St);else if(3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),he.reset(),ae.emit(ie.THREE_WAY_OUR_SIDE_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft);else if(4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no)this.putAgentState(!0),he.reset(),ae.emit(ie.TRANSFER_END,{session_id:s.session_id}),he.updateActionConfigs(ft);else if(4===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no){ae.emit(ie.TRANSFER_FAILED,"未知原因"),ae.emit(ne.FAIL_NOTIFICATION,"转接失败");const A=he.get("direction");A===ee.OUTGOING?he.updateActionConfigs(St):A===ee.INCOMING&&he.updateActionConfigs(Ut)}else 5===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(!0,5),Ve.monitoredAgentNo="",Ve.earSpeakAgent="",he.reset(),ae.emit(ie.LISTEN_HANGUP,{session_id:s.session_id}),he.updateActionConfigs(ft));if(t===te.SATISFACTION_EVALUATION&&(0===i?ae.emit(ie.SATISFACTION_EVALUATION_SUCCESS):(ae.emit(ie.SATISFACTION_EVALUATION_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n))),t===te.CONSULT_THREE_WAY&&(0!==i?(ae.emit(ie.CONSULT_THREE_WAY_FAILED,n),ae.emit(ne.FAIL_NOTIFICATION,n)):0===i&&he.updateIsMeeting(!0)),t===te.CONSULT_THREE_WAY_RESULT&&("success"===s.status?(he.updateDirection(ee.MEETING),he.updateDisplayText(oe.MEETING),he.updateActionConfigs(Rt),ae.emit(ie.CONSULT_THREE_WAY_SUCCESS)):(ae.emit(ie.CONSULT_THREE_WAY_FAILED,{conf_name:s.conf_name}),he.updateIsMeeting(!1))),t===te.TRANSFER_INCOMING_CALL&&(clearTimeout(Ve.autoStateTimer),s.agent_no===Ve.agentInfo.agent_no?(he.updateDisplayText(oe.TRANSFERRING),ae.emit(ie.TRANSFER_PROGRESS),he.updateActionConfigs([]),he.updateTransferIsAnswer(!0)):(Ve.sessionId=s.session_id,ae.emit(ie.TRANSFER_INCOMING_CALL,{agent_no:s.agent_no,agent_name:s.agent_name,session_id:s.session_id}),he.updateIsCalling(!0),he.updateDirection(ee.TRANSFER),he.updateDisplayText(oe.TRANSFER_INCOMING_CALL),he.updateActionConfigs(Dt),Ve.enableBrowserAlert&&Ps.show("📞 转接来电",`坐席 [${s.agent_no}] 正在转接...`,()=>{ae.emit(ne.NOTIFICATION_CLICK,{agent_no:s.agent_no})},Ve.browserAlertTime))),t===te.TRANSFER_OFF_HOOK&&(ae.emit(ie.TRANSFER_OFF_HOOK,{session_id:Ve.sessionId}),he.updateTransferIsAnswer(!1),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(Ut)),t===te.TRANSFER_FAILED&&"failed"===s.status){ae.emit(ie.TRANSFER_FAILED,"未知原因"),ae.emit(ne.FAIL_NOTIFICATION,"转接失败");const A=he.get("direction");A===ee.OUTGOING?he.updateActionConfigs(St):A===ee.INCOMING&&he.updateActionConfigs(Ut)}t===te.KICK_OFFLINE&&ae.emit(ne.KICK_OFF),t===te.CONTINUOUS_NOT_ANSWER&&(ae.emit(ne.FAIL_NOTIFICATION,`已连续 ${s.miss_count} 次未接, 设置忙碌`),this.stateBusyChange()),t===te.SIGN_OUT&&ae.emit(ne.SIGN_OUT),t===te.SIGN_IN_SWITCH_DEVICE&&ae.emit(ne.SIGN_IN_SWITCH_DEVICE,s),t===te.LISTEN_INCOMING_CALL&&(clearTimeout(Ve.autoStateTimer),Ve.sessionId=s.session_id,he.updateIsCalling(!0),he.updateDirection(ee.INCOMING),this.inCallAutoAnswer(),he.updateDisplayText(oe.LISTENING),he.updateActionConfigs(Dt),ae.emit(ie.LISTEN_INCOMING_CALL,{session_id:s.session_id}),Ve.enableBrowserAlert&&Ps.show("📞 监听来电","正在来电...",()=>{ae.emit(ne.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})},Ve.browserAlertTime)),t===te.LISTEN_INCOMING_CALL_OFF_HOOK&&(Ve.monitoredAgentNo=s.monitored_agent_no,Ve.earSpeakAgent="",he.updateIncomingIsAnswer(!0),ae.emit(ie.LISTEN_INCOMING_CALL_OFF_HOOK,{session_id:Ve.sessionId,monitored_agent_no:s.monitored_agent_no}),he.updateActionConfigs(kt),he.updateDisplayText(oe.CALLING)),t===te.LISTEN_CALL_FAILED&&"failed"===s.status&&(ae.emit(ie.LISTEN_CALL_FAILED),Ve.monitoredAgentNo=""),t===te.EAR_SPEECH&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&(he.updateActionConfigs(Gt),ae.emit(ie.EAR_SPEECH_BE_SUCCESS)),s.monitor_agent_no===Ve.agentInfo.agent_no&&(he.updateActionConfigs(Ft),ae.emit(ie.EAR_SPEECH_SUCCESS,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no}),Ve.earSpeakAgent=s.monitored_agent_no)):ae.emit(ie.EAR_SPEECH_FAILED)),t===te.STOP_EAR_SPEECH&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&he.updateActionConfigs(Ut),s.monitor_agent_no===Ve.agentInfo.agent_no&&he.updateActionConfigs(kt),Ve.earSpeakAgent="",ae.emit(ie.STOP_EAR_SPEECH_SUCCESS)):ae.emit(ie.STOP_EAR_SPEECH_FAILED)),t===te.CALL_FORCE_INSERT&&("success"===s.status?(s.monitored_agent_no===Ve.agentInfo.agent_no&&(he.updateActionConfigs(Zt),ae.emit(ie.CALL_FORCE_INSERT_SUCCESS,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no})),s.monitor_agent_no===Ve.agentInfo.agent_no&&(he.updateActionConfigs(Yt),ae.emit(ie.CALL_FORCE_INSERT_SUCCESS_LISTENER,{monitored_agent_no:s.monitored_agent_no,monitor_agent_no:s.monitor_agent_no}))):ae.emit(ie.CALL_FORCE_INSERT_FAILED))},this.ws.onclose=A=>{ae.emit(ne.FAIL_NOTIFICATION,"链接已断开,请检查网络"),this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=A=>{ae.emit(ne.FAIL_NOTIFICATION,"连接失败,请检查网络"),this.ws?.close()}}startHeartbeat(){const A=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 5000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),e=URL.createObjectURL(A);this.heartbeatWorker=new Worker(e),this.heartbeatWorker.onmessage=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now())},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify(A)),0!==A.type&&Xs("%cWebSocket 发送消息:","color: green; font-weight: bold;",A)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}reconnect(){this.initWebSocket()}static __internalClose(){_s&&(_s.close(),_s=null)}static __internalSend(A){if(!_s)throw new Error("WebSocket 尚未初始化");_s.sendMessage(A)}}class Ai{constructor(A){this.sipClient=null,this.sipClient=A}roleMute(){const A=he.get("isCalling"),e=Ve.sessionId;if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}))}holdCall(){this.roleMute();const A=he.get("isHold"),{sessionId:e}=Ve;if(!e)return;if(!he.get("actionConfigs").includes("hold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿保持"}));if(A)throw new Error(JSON.stringify({code:1,msg:"当前已处于保持状态"}));$s.__internalSend({type:te.CALL_HOLD,data:{session_id:e}})}unholdCall(){this.roleMute();const{isHold:A}=he.getState(),{sessionId:e}=Ve;if(!he.get("actionConfigs").includes("unhold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取消保持"}));if(e){if(!A)throw new Error(JSON.stringify({code:1,msg:"当前未处于保持状态"}));$s.__internalSend({type:te.CALL_UNHOLD,data:{session_id:e}})}}sendDTMF(A){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!he.get("actionConfigs").includes("dtmf"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿发送按键"}));const{isCalling:e}=he.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));this.sipClient.sendDTMF(A)}cancelCall(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;ae.emit(ie.REJECT,{session_id:A}),$s.__internalSend({type:te.AGENT_HANGUP,data:{session_id:A}})}async consultCall(A){this.roleMute();const{isCalling:e,outCallIsAnswer:t,consultIsAnswer:s,incomingIsAnswer:i}=he.getState(),n=Ve.sessionId;if(!he.get("actionConfigs").includes("consult"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询"}));if(s)throw new Error(JSON.stringify({code:1,msg:"当前正在咨询"}));if(!(e||t||i))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!n)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));$s.__internalSend({type:te.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:A}})}async answerCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}makeCall(A){if("string"!=typeof A||""===A.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));const e={};if(Ds(A))e.trace_id=A;else{if(!/^(?:1[3-9]\d{9}|0\d{2,3}-?\d{7,8})$/.test(A.trim()))throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));e.customer_phone=A.replace(/[\s\r\n-]+/g,"")}const t=he.get("isCalling"),s=he.get("selectOutNumber")||"";if(t)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));he.updateIsCalling(!0),he.updateDirection(ee.OUTGOING),$s.__internalSend({type:te.OUT_CALL,data:{...e,caller:s.replace(/[\s\r\n-]+/g,"")}})}previewCall(A,e){const t={};Ds(A)?t.trace_id=A:t.customer_phone=A.replace(/[\s\r\n-]+/g,"");const s=he.get("isCalling"),i=he.get("selectOutNumber")||"";if(s)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));if("string"!=typeof A||""===A.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));he.updateIsCalling(!0),he.updateDirection(ee.OUTGOING),$s.__internalSend({type:te.PREVIEW_OUT_CALL,data:{...t,caller:i,preview_task_id:e}})}async hangup(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;$s.__internalSend({type:te.AGENT_HANGUP,data:{session_id:A}})}mute(){this.roleMute();const A=he.get("actionConfigs"),e=he.get("isMuted"),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前未处于静音状态"}));if(!A.includes("mute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:te.MUTE,data:{session_id:t}})}unmute(){this.roleMute();const A=he.get("actionConfigs"),e=he.get("isMuted"),t=Ve.sessionId;if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于未静音状态"}));if(!A.includes("unmute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:te.UNMUTE,data:{session_id:t}})}consultTransfer(){this.roleMute();const A=he.get("consultIsAnswer"),e=Ve.sessionId;if(!he.get("actionConfigs").includes("consult_transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询转移"}));if(!A)throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:te.CONSULT_TRANSFER,data:{session_id:e}})}satisfactionEvaluation(){this.roleMute();const A=Ve.sessionId;if(!he.get("actionConfigs").includes("satisfaction"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用满意度评价"}));$s.__internalSend({type:te.SATISFACTION_EVALUATION,data:{session_id:A}})}startConference(){this.roleMute();if(!he.get("actionConfigs").includes("conference"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用三方会议"}));const A=Ve.sessionId;if(!he.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:te.CONSULT_THREE_WAY,data:{session_id:A}})}consultRetrieve(){this.roleMute();if(!he.get("actionConfigs").includes("consult_retrieve"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取回通话"}));const A=Ve.sessionId;if(!he.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:te.CONSULT_RETURN_CALL,data:{session_id:A}})}async transferAgent(A){this.roleMute();if(!he.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));const{transferIsAnswer:e}=he.getState(),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:te.TRANSFER,data:{session_id:t,transfer_type:0,transfer_dest:A}})}async transferOutline(A){this.roleMute();if(!he.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));if(!A)throw new Error(JSON.stringify({code:1,msg:"号码不能为空"}));if(!/^\d+$/.test(A))throw new Error(JSON.stringify({code:1,msg:"号码格式错误"}));const{transferIsAnswer:e}=he.getState(),t=Ve.sessionId;if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));if(e)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:te.TRANSFER,data:{session_id:t,transfer_type:2,transfer_dest:A}})}}var ei;class ti{static{this._instance=null}#A;#e;#t;#s;#i;#n;#o;#r;static{this._timer=null}#a;constructor(){if(this.#A=null,this.#e=new Ks,this.#s=null,this.#i=!1,this.#r=!1,this.#a=null,this.#V=()=>{he.updateIsNextState(!0)},this.#c=()=>{he.updateIsNextState(!1)},this.initWebRtc=async()=>{if(this.#A)return;const A=Ve.agentInfo.sip_account_list.find(A=>1===A.device_type);if(!A)throw new Error(JSON.stringify({code:1,msg:"未找到 sip_account_list"}));{const e=A.sip_register_addr;this.#A=new ge({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#h),await this.#A.start()}},this.#h=A=>{const{type:e,data:t}=A;ae.emit(e,t)},!ei._creatingInstance)throw new Error("请使用 YSYTAgentSdk.getInstance() 获取实例");clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#l();le.updateRttObject(A)},2e3),Ps.requestMediaPermissions(),this.#o=he.subscribeKey("isNextState",async A=>{if(A){await this.#e._agentLogin(Zs);1===he.get("answerDevice")&&await this.#A.reconnect();let A="";const e=new URL(Gs).host;A=Gs.includes("https")?`wss://${e}`:`ws://${e}`;const{agent_no:t}=Ve.agentInfo;$s.getInstance({url:`${A}/ccs-ws/api/v1/ws/call/${t}?Authorization=`,sipClient:this.#A}),Ve.stateObject.state===Ae.OFFLINE&&setTimeout(()=>{this.#e._changeState({data:{...this.#a,state_name:this.#a.state===Ae.BUSY&&"整理"===this.#a.state_name?"忙碌":this.#a.state_name},success:()=>{he.updateDisplayText(""),ae.emit(ie.AGENT_STATE,this.#a)}})},10)}else this.#a=Ve.stateObject,$s.__internalClose(),he.updateDisplayText("离线")}),this.#n=he.subscribeKey("answerDevice",async A=>{1===A?Ve.stateObject.state===Ae.UNREGISTERED&&await this.#e._changeState({data:{...Ve.stateBeforeChange,state_name:Ve.stateBeforeChange.state===Ae.IDLE?"空闲":"忙碌"}}):await this.destroyRtc()}),this.on(ne.KICK_OFF,()=>{this.destroy()}),window.addEventListener("beforeunload",A=>{A.returnValue="",this.destroy()}),window.addEventListener("online",this.#V),window.addEventListener("offline",this.#c)}#V;#c;async#g(){const A=he.get("isNextState");try{await xs(),A||he.updateIsNextState(!0)}catch(e){ae.emit(ne.FAIL_NOTIFICATION,"网络断开,请检查网络"),A&&he.updateIsNextState(!1)}}#q(){ei._timer||(ei._timer=setInterval(()=>this.#g(),3e3))}static get instance(){return this._instance}static async destroyInstance(){this._instance&&(await this._instance.destroy(),this._instance=null)}static getInstance(A){if(!this._instance){if(!A)throw new Error("首次调用必须传入配置参数");const{url:e,appKey:t,appSecret:s,agentNo:i}=A;Gs=e||"https://aicc-api.yescloudy.com",Fs=t,Ys=s,Zs=i,ei._creatingInstance=!0,this._instance=new ei,delete ei._creatingInstance}return this._instance}getInit(){return this.#r}async init({actionNodeParams:A,enableBrowserAlert:e,logBuiltinEnabled:t,browserAlertTime:s,initialState:i,initDevice:n}){try{let o="";const r=new URL(Gs).host;o=Gs.includes("https")?`wss://${r}`:`ws://${r}`;const a=$s.getInstance({url:`${o}/ccs-ws/api/v1/ws/call/${Zs}?Authorization=`,sipClient:null,onOpen:async()=>{const{viewHtmlElement:o,rttHTML:r}=A||{};Ve.logBuiltinEnabled=t||!1,Ve.browserAlertTime=s||5e3,await this.#e._agentLogin(Zs);const{current_answer_device:V,current_state:c,out_display_number:h,out_display_select_switch:l}=Ve.agentInfo;(i||c)===Ae.IDLE?(he.updateActionConfigs(ft),Ve.stateObject={state:i||c,state_name:"空闲"},Ve.stateBeforeChange=Ve.stateObject):(i||c)===Ae.BUSY?(he.updateActionConfigs(Bt),Ve.stateObject={state:c,state_name:"忙碌"},Ve.stateBeforeChange=Ve.stateObject):(i||c)===Ae.UNREGISTERED&&(he.updateActionConfigs(Bt),Ve.stateObject={state:c,state_name:"未注册"}),1===l?he.updateSelectOutNumber(h):he.updateSelectOutNumber(""),he.updateAnswerDevice(n||V),Ks.setInitRtcFn(this.initWebRtc),1===(n||V)&&(await this.initWebRtc(),a.setSipClient(this.#A)),this.#t=new Ai(this.#A),A&&o&&(this.#i=!0,new Ws({container:o,rttHTML:r,statusParams:{state:Ve.stateObject.state,statusName:Ve.stateObject.state_name}},this,this.#t)),Ve.enableBrowserAlert=e,e&&Ps.requestPermission(),ae.emit(ne.AGENT_INIT_STATUS,!0),this.#r=!0,clearInterval(ei._timer),ei._timer=null,this.#q()}})}catch(A){this.#i&&Hs("初始化失败"),ae.emit(ne.AGENT_INIT_STATUS,!1),this.#r=!1}}#h;on(A,e){return ae.on(A,e),this}off(A,e){ae.off(A,e)}offAll(){ae.clearAllListeners()}async destroyRtc(){await(this.#A?.destroy()),this.#A=null}async destroy(){ei._instance&&(await this.destroyRtc(),this.#n?.(),this.#o?.(),clearInterval(this.#s),$s.__internalClose(),ae.emit(ne.DESTROY),this.offAll(),this.#i=!1,ei._instance=null,he.reset(),he.updateSelectOutNumber(""),clearInterval(ei._timer),ei._timer=null)}async#l(){return this.#A?this.#A.getNetworkStats():{}}get call_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{answerCall:A(()=>this.#t.answerCall()),makeCall:A=>this.#t.makeCall(A),previewMakeCall:(A,e)=>this.#t.previewCall(A,e),cancelCall:A(()=>this.#t.cancelCall()),hangup:A(()=>this.#t.hangup()),sendDTMF:A(A=>this.#t.sendDTMF(A)),holdCall:A(()=>this.#t.holdCall()),unholdCall:A(()=>this.#t.unholdCall()),consultCall:A(async A=>{try{await this.#t.consultCall(A)}catch(A){throw console.warn(A),A}}),consultRetrieve:A(()=>this.#t.consultRetrieve()),consultTransfer:A(()=>this.#t.consultTransfer()),mute:A(()=>this.#t.mute()),unmute:A(()=>this.#t.unmute()),satisfactionEvaluation:A(()=>this.#t.satisfactionEvaluation()),startConference:A(()=>this.#t.startConference()),transferAgent:A(A=>this.#t.transferAgent(A)),transferOutline:A(A=>this.#t.transferOutline(A)),earSpeakStart:A(A=>this.#e.earCall(A)),earSpeakStop:A(A=>this.#e.stopEarCall(A)),forceInsert:A(A=>this.#e.forceInsert(A)),forceDisconnect:A(A=>this.#e.forceDisconnect(A))}}get agent_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{changeDevice:A(A=>this.#e.changeDevice(A)),changeState:A(A=>this.#e.changeState(A)),getIdleAgentList:A(A=>this.#e.getIdleAgentList(A)),getAgentState:A(A=>this.#e.getAgentState(A)),setAgentExplicit:A(A=>this.#e.setAgentExplicit(A)),checkAgentLogin:A=>this.#e.checkAgentLogin(A),getCallRecord:A=>this.#e.getCallRecord(A),agentLogout:async(A,e)=>{try{await this.#e.logout(A),await this.destroy(),e?.({code:0,msg:""})}catch(A){}},listenAgentCall:A=>this.#e.listenCall(A)}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,out_display_data:s,out_display_select_switch:i,current_state:n}=Ve.agentInfo,{stateObject:o}=Ve,r={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:n,default_device:he.get("answerDevice"),out_display_data:s,out_display_select_switch:i,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:r[Number(A)]})),stateObject:o}}async getRealTimeCustomerInfo(){return he.get("customerObject")}setBrowserAlert(A){if("boolean"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));Ve.logBuiltinEnabled=A||!1}setBrowserAlertTime(A){if("number"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));Ve.browserAlertTime=A||3e3}}ei=ti,import.meta.hot&&import.meta.hot.dispose(()=>{window.location.reload()});export{Ae as AgentStatus,ie as CallSipCallEventEnum,ee as DirectionEnum,oe as DisplayTextEnum,ne as EventName,se as WebRtcCallSipEventEnum,te as WebsocketTypeEnum,ti as default};
@@ -911,4 +911,4 @@ const Nt=A=>(e,t)=>{void 0!==t?t.addInitializer(()=>{customElements.define(A,e)}
911
911
  `:""}
912
912
  </div>
913
913
  </my-popover>
914
- `;Ct(s,this.rttHTML)}}class Ps{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const A=await navigator.mediaDevices.enumerateDevices();if(A.some(A=>"audioinput"===A.kind&&""!==A.label))return null;return await navigator.mediaDevices.getUserMedia({audio:!0})}catch(A){return console.warn("获取音频权限失败:",A),null}}static show(A,e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(A,{body:e,tag:`xy-global-notification${(new Date).getTime()}`,renotify:!0});i.onclick=()=>{window.focus(),i.close(),t?.()},setTimeout(()=>i.close(),1e3*(s||3))}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}const zs=console.log,Xs=(...A)=>{ce.logBuiltinEnabled&&zs(...A)};let _s=null;class $s{constructor(A,e){this.url=A,this.onOpenCallback=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Ks,this.sipClient=null,this.pendingMessages=new Map,this.initWebSocket()}static getInstance({url:A,sipClient:e,onOpen:t}){if(!_s){if(!A)throw new Error("WebSocket 尚未初始化");_s=new $s(A,t),_s.sipClient=e}return _s}setSipClient(A){this.sipClient=A}stateIdleChange(){const{state:e}=ce.stateObject;e!==A.AgentStatus.IDLE&&this.apiClient._changeState({data:{...ce.stateBeforeChange,state_name:ce.stateBeforeChange.state===A.AgentStatus.IDLE?"空闲":"忙碌"}})}inCallAutoAnswer(){const{soft_device_auto_answer:e,auto_answer_time:t}=ce.agentInfo,s=1===e,i=he.get("direction");if(s&&i===A.DirectionEnum.INCOMING){const A=Number(t)||0;A>0&&(ce.autoAnswerTimer=setTimeout(()=>{this.sipClient?.answerCall(),ce.autoAnswerTimer=null},1e3*A))}}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{he.updateCustomerInfo(A.data||{phone:A.data.phone,is_vip:0,customer_name:"未知客户",city:"未知",province:"未知",contact_count:0,in_contact_count:0,trace_id:A.data.trace_id,contact_count_month:0,in_contact_count_month:0})}})}catch(A){}}putAgentState(e,t){if(!e)return;if(5===t)return void this.stateIdleChange();ce.sessionId="";const{post_call_process_time:s}=ce.agentInfo,i=s||0;if(ce.autoStateTimer&&(clearTimeout(ce.autoStateTimer),ce.autoStateTimer=null),he.updateCustomerInfo(void 0),i>0){const{state:e}=ce.stateObject;if(e===A.AgentStatus.IDLE)return;this.apiClient._changeState({data:{state:A.AgentStatus.BUSY,state_name:"整理"}}),ce.autoStateTimer=setTimeout(()=>{ce.autoStateTimer=null,this.stateIdleChange()},1e3*i)}else this.stateIdleChange()}stateBusyChange(){ce.sessionId="",clearTimeout(ce.autoStateTimer),he.updateCustomerInfo(void 0),this.apiClient._changeState({data:{state:A.AgentStatus.BUSY,state_name:"忙碌"}})}initWebSocket(){if(1===this.ws?.readyState)return;const e=Ds(Fs,Ys);this.ws=new WebSocket(this.url+e),this.ws.onopen=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now()),this.startHeartbeat(),this.manualClose=!1,this.onOpenCallback&&this.onOpenCallback()},this.ws.onmessage=async e=>{const t=JSON.parse(e.data),{type:s,data:i,code:n,msg:o,msg_id:r}=t;if(0===s&&r){const A=this.pendingMessages.get(r),e=performance.now()-A;ce.latency=parseFloat(e.toFixed(2)),this.pendingMessages.delete(r)}if(0!==s&&Xs("%cWebSocket 收到消息:","color: blue; font-weight: bold;",t),s!==A.WebsocketTypeEnum.OUT_CALL&&s!==A.WebsocketTypeEnum.PREVIEW_OUT_CALL||(0!==n?(he.reset(),Ve.emit(A.CallSipCallEventEnum.OUT_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o),he.updateActionConfigs(Bt),setTimeout(()=>{he.updateCustomerInfo(void 0)},500),this.stateIdleChange()):0===n&&(Ve.emit(A.CallSipCallEventEnum.OUT_SUCCESS),clearTimeout(ce.autoStateTimer))),s===A.WebsocketTypeEnum.AGENT_STATE){const{state:e,state_name:t}=i;ce.stateObject={state:e,state_name:t},ce.stateBeforeChange?.state||ce.stateObject.state!==A.AgentStatus.IDLE&&(ce.stateObject.state!==A.AgentStatus.BUSY||"整理"===t)||(ce.stateBeforeChange=ce.stateObject),"振铃中"===t&&he.updateDisplayText(A.DisplayTextEnum.AGENT_RINGING),e===A.AgentStatus.UNREGISTERED&&he.updateActionConfigs(ft),e===A.AgentStatus.IDLE&&ce.stateObject.state===A.AgentStatus.UNREGISTERED&&he.updateActionConfigs(Bt),Ve.emit(A.CallSipCallEventEnum.AGENT_STATE,{state:e,state_name:t})}if(s===A.WebsocketTypeEnum.OUT_CALL_INCOMING_CALL){try{await this.getCustomerInfo(i.trace_id||i.customer_phone)}catch(A){console.error(A)}i.preview_task_id?Ve.emit(A.CallSipCallEventEnum.PREVIEW_OUT_INCOMING_CALL,{customer_phone:i.customer_phone,session_id:i.session_id,preview_task_id:i.preview_task_id,trace_id:i.trace_id}):Ve.emit(A.CallSipCallEventEnum.OUT_INCOMING_CALL,{customer_phone:i.customer_phone,session_id:i.session_id,trace_id:i.trace_id}),ce.sessionId=i.session_id,he.updateActionConfigs(Qt)}if(s===A.WebsocketTypeEnum.OUT_CALL_END)if(he.updateDisplayText(""),1===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.OUT_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0);else if(2===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.OUR_SIDE_CONSULT_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0);else if(2===i.device_type&&i.agent_no!==ce.agentInfo.agent_no){he.get("isCalling")&&(he.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Tt))}else if(3===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.THREE_WAY_OUR_SIDE_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0);else if(4===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.TRANSFER_END,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0);else if(4===i.device_type&&i.agent_no!==ce.agentInfo.agent_no){Ve.emit(A.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),Ve.emit(A.EventName.FAIL_NOTIFICATION,"转接失败");const e=he.get("direction");e===A.DirectionEnum.OUTGOING?he.updateActionConfigs(Tt):e===A.DirectionEnum.INCOMING&&he.updateActionConfigs(kt)}else 5===i.device_type&&i.agent_no===ce.agentInfo.agent_no&&(ce.monitoredAgentNo="",ce.earSpeakAgent="",he.reset(),Ve.emit(A.CallSipCallEventEnum.LISTEN_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0,5));if(s===A.WebsocketTypeEnum.OUT_CALL_RINGING&&1===i.type&&(Ve.emit(A.CallSipCallEventEnum.OUT_RINGING,{session_id:ce.sessionId,type:i.type}),he.updateDisplayText(A.DisplayTextEnum.RINGING)),s===A.WebsocketTypeEnum.OUT_CALL_ANSWER&&(clearTimeout(ce.autoStateTimer),he.updateIsCalling(!0),Ve.emit(A.CallSipCallEventEnum.OUT_OFF_ANSWER,{session_id:ce.sessionId}),he.updateOutCallIsAnswer(!0),he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateActionConfigs(Tt)),s===A.WebsocketTypeEnum.CONSULT_RINGING&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_RINGING,{session_id:i.session_id}),he.updateDisplayText(A.DisplayTextEnum.AGENT_RINGING),he.updateActionConfigs([]),clearTimeout(ce.autoStateTimer)),s===A.WebsocketTypeEnum.CONSULT_ANSWER&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_OFF_HOOK,{session_id:i.session_id}),he.updateConsultIsAnswer(!0),he.updateDisplayText(A.DisplayTextEnum.CONSULTING),he.updateActionConfigs(yt)),s===A.WebsocketTypeEnum.CONSULT_FAIL&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_FAILED,{custom_reason:i.custom_reason}),he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateActionConfigs(Tt)),s===A.WebsocketTypeEnum.CONSULT_CALL_IN&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_INCOMING,{agent_no:i.agent_no,agent_mane:i.agent_name,session_id:i.session_id}),ce.sessionId=i.session_id,he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.CONSULT),he.updateDisplayText(A.DisplayTextEnum.CONSULT_CALL_IN),he.updateActionConfigs(Ut),ce.enableBrowserAlert&&Ps.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{agent_mane:i.agent_name,agent_no:i.agent_no})},ce.browserAlertTime)),s===A.WebsocketTypeEnum.CONSULT_CALL_IN_SUCCESS&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_CALL_IN_SUCCESS,{session_id:i.session_id}),he.updateConsultIsAnswer(!0),he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateActionConfigs(Dt)),s===A.WebsocketTypeEnum.CONSULT_RETURN_CALL_SUCCESS&&("success"===i.status?(he.updateConsultIsAnswer(!1),Ve.emit(A.CallSipCallEventEnum.CONSULT_RETURN_CALL_SUCCESS),he.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP),he.updateActionConfigs(Tt)):Ve.emit(A.EventName.FAIL_NOTIFICATION,"媒体失败")),s===A.WebsocketTypeEnum.MUTE&&(0===n?(he.updateIsMuted(!0),Ve.emit(A.CallSipCallEventEnum.MUTE_SUCCESS),he.updateDisplayText(A.DisplayTextEnum.MUTING)):(Ve.emit(A.CallSipCallEventEnum.MUTE_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.UNMUTE&&(0===n?(he.updateIsMuted(!1),Ve.emit(A.CallSipCallEventEnum.UNMUTE_SUCCESS),he.updateDisplayText(A.DisplayTextEnum.CALLING)):(Ve.emit(A.CallSipCallEventEnum.UNMUTE_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CALL_HOLD&&(0===n?(he.updateIsHold(!0),he.updateDisplayText(A.DisplayTextEnum.HOLDING),Ve.emit(A.CallSipCallEventEnum.HOLD_SUCCESS)):(Ve.emit(A.CallSipCallEventEnum.HOLD_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CALL_UNHOLD&&(0===n?(he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateIsHold(!1),Ve.emit(A.CallSipCallEventEnum.UNHOLD_SUCCESS)):(Ve.emit(A.CallSipCallEventEnum.UNHOLD_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CONSULT_TRANSFER&&(0===n?Ve.emit(A.CallSipCallEventEnum.CONSULT_TRANSFER_SUCCESS):(Ve.emit(A.CallSipCallEventEnum.CONSULT_TRANSFER_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CONSULT_TRANSFER_FAILED&&Ve.emit(A.CallSipCallEventEnum.CONSULT_TRANSFER_FAILED,i.status),s===A.WebsocketTypeEnum.CONSULT_TRANSFER_OFF_HOOK&&(he.updateDirection(A.DirectionEnum.INCOMING),he.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEventEnum.CONSULT_TRANSFER_OFF_HOOK),he.updateActionConfigs(kt),he.updateIncomingIsAnswer(!0),he.updateConsultIsAnswer(!1)),s===A.WebsocketTypeEnum.INCOMING_CALL){clearTimeout(ce.autoStateTimer),ce.sessionId=i.session_id;try{await this.getCustomerInfo(i.trace_id||i.customer_phone)}catch(A){console.error(A)}he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.INCOMING),he.updateDisplayText(A.DisplayTextEnum.INCOMING_CALL),this.inCallAutoAnswer(),1===i.direction&&Ve.emit(A.CallSipCallEventEnum.INCOMING_CALL,{customer_phone:i.customer_phone,trace_id:i.trace_id,session_id:i.session_id}),3===i.direction&&Ve.emit(A.CallSipCallEventEnum.PREDICT_INCOMING_CALL,{customer_phone:i.customer_phone,trace_id:i.trace_id,session_id:i.session_id}),he.updateActionConfigs(Ut),ce.enableBrowserAlert&&Ps.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})},ce.browserAlertTime)}if(s===A.WebsocketTypeEnum.INCOMING_CALL_OFF_HOOK&&(he.updateIncomingIsAnswer(!0),Ve.emit(A.CallSipCallEventEnum.INCOMING_CALL_OFF_HOOK,{session_id:ce.sessionId}),he.updateActionConfigs(kt),he.updateDisplayText(A.DisplayTextEnum.CALLING)),s===A.WebsocketTypeEnum.INCOMING_CALL_END)if(he.updateDisplayText(""),1===i.device_type&&i.agent_no===ce.agentInfo.agent_no)this.putAgentState(!0),he.reset(),Ve.emit(A.CallSipCallEventEnum.INCOMING_CALL_END,{session_id:i.session_id}),he.updateActionConfigs(Bt);else if(2===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.OUR_SIDE_CONSULT_HANGUP,{session_id:i.session_id}),this.putAgentState(!0),he.updateActionConfigs(Bt);else if(2===i.device_type&&i.agent_no!==ce.agentInfo.agent_no)he.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Tt);else if(3===i.device_type&&i.agent_no===ce.agentInfo.agent_no)this.putAgentState(!0),he.reset(),Ve.emit(A.CallSipCallEventEnum.THREE_WAY_OUR_SIDE_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt);else if(4===i.device_type&&i.agent_no===ce.agentInfo.agent_no)this.putAgentState(!0),he.reset(),Ve.emit(A.CallSipCallEventEnum.TRANSFER_END,{session_id:i.session_id}),he.updateActionConfigs(Bt);else if(4===i.device_type&&i.agent_no!==ce.agentInfo.agent_no){Ve.emit(A.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),Ve.emit(A.EventName.FAIL_NOTIFICATION,"转接失败");const e=he.get("direction");e===A.DirectionEnum.OUTGOING?he.updateActionConfigs(Tt):e===A.DirectionEnum.INCOMING&&he.updateActionConfigs(kt)}else 5===i.device_type&&i.agent_no===ce.agentInfo.agent_no&&(this.putAgentState(!0,5),ce.monitoredAgentNo="",ce.earSpeakAgent="",he.reset(),Ve.emit(A.CallSipCallEventEnum.LISTEN_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt));if(s===A.WebsocketTypeEnum.SATISFACTION_EVALUATION&&(0===n?Ve.emit(A.CallSipCallEventEnum.SATISFACTION_EVALUATION_SUCCESS):(Ve.emit(A.CallSipCallEventEnum.SATISFACTION_EVALUATION_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CONSULT_THREE_WAY&&(0!==n?(Ve.emit(A.CallSipCallEventEnum.CONSULT_THREE_WAY_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o)):0===n&&he.updateIsMeeting(!0)),s===A.WebsocketTypeEnum.CONSULT_THREE_WAY_RESULT&&("success"===i.status?(he.updateDirection(A.DirectionEnum.MEETING),he.updateDisplayText(A.DisplayTextEnum.MEETING),he.updateActionConfigs(Rt),Ve.emit(A.CallSipCallEventEnum.CONSULT_THREE_WAY_SUCCESS)):(Ve.emit(A.CallSipCallEventEnum.CONSULT_THREE_WAY_FAILED,{conf_name:i.conf_name}),he.updateIsMeeting(!1))),s===A.WebsocketTypeEnum.TRANSFER_INCOMING_CALL&&(clearTimeout(ce.autoStateTimer),i.agent_no===ce.agentInfo.agent_no?(he.updateDisplayText(A.DisplayTextEnum.TRANSFERRING),Ve.emit(A.CallSipCallEventEnum.TRANSFER_PROGRESS),he.updateActionConfigs([]),he.updateTransferIsAnswer(!0)):(ce.sessionId=i.session_id,Ve.emit(A.CallSipCallEventEnum.TRANSFER_INCOMING_CALL,{agent_no:i.agent_no,agent_name:i.agent_name,session_id:i.session_id}),he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.TRANSFER),he.updateDisplayText(A.DisplayTextEnum.TRANSFER_INCOMING_CALL),he.updateActionConfigs(Ut),ce.enableBrowserAlert&&Ps.show("📞 转接来电",`坐席 [${i.agent_no}] 正在转接...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{agent_no:i.agent_no})},ce.browserAlertTime))),s===A.WebsocketTypeEnum.TRANSFER_OFF_HOOK&&(Ve.emit(A.CallSipCallEventEnum.TRANSFER_OFF_HOOK,{session_id:ce.sessionId}),he.updateTransferIsAnswer(!1),he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateActionConfigs(kt)),s===A.WebsocketTypeEnum.TRANSFER_FAILED&&"failed"===i.status){Ve.emit(A.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),Ve.emit(A.EventName.FAIL_NOTIFICATION,"转接失败");const e=he.get("direction");e===A.DirectionEnum.OUTGOING?he.updateActionConfigs(Tt):e===A.DirectionEnum.INCOMING&&he.updateActionConfigs(kt)}s===A.WebsocketTypeEnum.KICK_OFFLINE&&Ve.emit(A.EventName.KICK_OFF),s===A.WebsocketTypeEnum.CONTINUOUS_NOT_ANSWER&&(Ve.emit(A.EventName.FAIL_NOTIFICATION,`已连续 ${i.miss_count} 次未接, 设置忙碌`),this.stateBusyChange()),s===A.WebsocketTypeEnum.SIGN_OUT&&Ve.emit(A.EventName.SIGN_OUT),s===A.WebsocketTypeEnum.SIGN_IN_SWITCH_DEVICE&&Ve.emit(A.EventName.SIGN_IN_SWITCH_DEVICE,i),s===A.WebsocketTypeEnum.LISTEN_INCOMING_CALL&&(clearTimeout(ce.autoStateTimer),ce.sessionId=i.session_id,he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.INCOMING),this.inCallAutoAnswer(),he.updateDisplayText(A.DisplayTextEnum.LISTENING),he.updateActionConfigs(Ut),Ve.emit(A.CallSipCallEventEnum.LISTEN_INCOMING_CALL,{session_id:i.session_id}),ce.enableBrowserAlert&&Ps.show("📞 监听来电","正在来电...",()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})},ce.browserAlertTime)),s===A.WebsocketTypeEnum.LISTEN_INCOMING_CALL_OFF_HOOK&&(ce.monitoredAgentNo=i.monitored_agent_no,ce.earSpeakAgent="",he.updateIncomingIsAnswer(!0),Ve.emit(A.CallSipCallEventEnum.LISTEN_INCOMING_CALL_OFF_HOOK,{session_id:ce.sessionId,monitored_agent_no:i.monitored_agent_no}),he.updateActionConfigs(Gt),he.updateDisplayText(A.DisplayTextEnum.CALLING)),s===A.WebsocketTypeEnum.LISTEN_CALL_FAILED&&"failed"===i.status&&(Ve.emit(A.CallSipCallEventEnum.LISTEN_CALL_FAILED),ce.monitoredAgentNo=""),s===A.WebsocketTypeEnum.EAR_SPEECH&&("success"===i.status?(i.monitored_agent_no===ce.agentInfo.agent_no&&(he.updateActionConfigs(Ft),Ve.emit(A.CallSipCallEventEnum.EAR_SPEECH_BE_SUCCESS)),i.monitor_agent_no===ce.agentInfo.agent_no&&(he.updateActionConfigs(Yt),Ve.emit(A.CallSipCallEventEnum.EAR_SPEECH_SUCCESS,{monitored_agent_no:i.monitored_agent_no,monitor_agent_no:i.monitor_agent_no}),ce.earSpeakAgent=i.monitored_agent_no)):Ve.emit(A.CallSipCallEventEnum.EAR_SPEECH_FAILED)),s===A.WebsocketTypeEnum.STOP_EAR_SPEECH&&("success"===i.status?(i.monitored_agent_no===ce.agentInfo.agent_no&&he.updateActionConfigs(kt),i.monitor_agent_no===ce.agentInfo.agent_no&&he.updateActionConfigs(Gt),ce.earSpeakAgent="",Ve.emit(A.CallSipCallEventEnum.STOP_EAR_SPEECH_SUCCESS)):Ve.emit(A.CallSipCallEventEnum.STOP_EAR_SPEECH_FAILED)),s===A.WebsocketTypeEnum.CALL_FORCE_INSERT&&("success"===i.status?(i.monitored_agent_no===ce.agentInfo.agent_no&&(he.updateActionConfigs(Zt),Ve.emit(A.CallSipCallEventEnum.CALL_FORCE_INSERT_SUCCESS,{monitored_agent_no:i.monitored_agent_no,monitor_agent_no:i.monitor_agent_no})),i.monitor_agent_no===ce.agentInfo.agent_no&&(he.updateActionConfigs(vt),Ve.emit(A.CallSipCallEventEnum.CALL_FORCE_INSERT_SUCCESS_LISTENER,{monitored_agent_no:i.monitored_agent_no,monitor_agent_no:i.monitor_agent_no}))):Ve.emit(A.CallSipCallEventEnum.CALL_FORCE_INSERT_FAILED))},this.ws.onclose=e=>{Ve.emit(A.EventName.FAIL_NOTIFICATION,"链接已断开,请检查网络"),this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=e=>{Ve.emit(A.EventName.FAIL_NOTIFICATION,"连接失败,请检查网络"),this.ws?.close()}}startHeartbeat(){const A=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 5000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),e=URL.createObjectURL(A);this.heartbeatWorker=new Worker(e),this.heartbeatWorker.onmessage=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now())},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify(A)),0!==A.type&&Xs("%cWebSocket 发送消息:","color: green; font-weight: bold;",A)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}reconnect(){this.initWebSocket()}static __internalClose(){_s&&(_s.close(),_s=null)}static __internalSend(A){if(!_s)throw new Error("WebSocket 尚未初始化");_s.sendMessage(A)}}class Ai{constructor(A){this.sipClient=null,this.sipClient=A}roleMute(){const A=he.get("isCalling"),e=ce.sessionId;if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}))}holdCall(){this.roleMute();const e=he.get("isHold"),{sessionId:t}=ce;if(!t)return;if(!he.get("actionConfigs").includes("hold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿保持"}));if(e)throw new Error(JSON.stringify({code:1,msg:"当前已处于保持状态"}));$s.__internalSend({type:A.WebsocketTypeEnum.CALL_HOLD,data:{session_id:t}})}unholdCall(){this.roleMute();const{isHold:e}=he.getState(),{sessionId:t}=ce;if(!he.get("actionConfigs").includes("unhold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取消保持"}));if(t){if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于保持状态"}));$s.__internalSend({type:A.WebsocketTypeEnum.CALL_UNHOLD,data:{session_id:t}})}}sendDTMF(A){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!he.get("actionConfigs").includes("dtmf"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿发送按键"}));const{isCalling:e}=he.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));this.sipClient.sendDTMF(A)}cancelCall(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=ce.sessionId;Ve.emit(A.CallSipCallEventEnum.REJECT,{session_id:e}),$s.__internalSend({type:A.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:e}})}async consultCall(e){this.roleMute();const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:n}=he.getState(),o=ce.sessionId;if(!he.get("actionConfigs").includes("consult"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询"}));if(i)throw new Error(JSON.stringify({code:1,msg:"当前正在咨询"}));if(!(t||s||n))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!o)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));$s.__internalSend({type:A.WebsocketTypeEnum.CONSULT_REQUEST,data:{session_id:o,consultation_agent_no:e}})}async answerCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}makeCall(e){if("string"!=typeof e||""===e.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));const t={};if(Rs(e))t.trace_id=e;else{if(!/^(?:1[3-9]\d{9}|0\d{2,3}-?\d{7,8})$/.test(e.trim()))throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));t.customer_phone=e.replace(/[\s\r\n-]+/g,"")}const s=he.get("isCalling"),i=he.get("selectOutNumber")||"";if(s)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.OUTGOING),$s.__internalSend({type:A.WebsocketTypeEnum.OUT_CALL,data:{...t,caller:i.replace(/[\s\r\n-]+/g,"")}})}previewCall(e,t){const s={};Rs(e)?s.trace_id=e:s.customer_phone=e.replace(/[\s\r\n-]+/g,"");const i=he.get("isCalling"),n=he.get("selectOutNumber")||"";if(i)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));if("string"!=typeof e||""===e.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.OUTGOING),$s.__internalSend({type:A.WebsocketTypeEnum.PREVIEW_OUT_CALL,data:{...s,caller:n,preview_task_id:t}})}async hangup(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=ce.sessionId;$s.__internalSend({type:A.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:e}})}mute(){this.roleMute();const e=he.get("actionConfigs"),t=he.get("isMuted"),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前未处于静音状态"}));if(!e.includes("mute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:A.WebsocketTypeEnum.MUTE,data:{session_id:s}})}unmute(){this.roleMute();const e=he.get("actionConfigs"),t=he.get("isMuted"),s=ce.sessionId;if(!t)throw new Error(JSON.stringify({code:1,msg:"当前未处于未静音状态"}));if(!e.includes("unmute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:A.WebsocketTypeEnum.UNMUTE,data:{session_id:s}})}consultTransfer(){this.roleMute();const e=he.get("consultIsAnswer"),t=ce.sessionId;if(!he.get("actionConfigs").includes("consult_transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询转移"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:A.WebsocketTypeEnum.CONSULT_TRANSFER,data:{session_id:t}})}satisfactionEvaluation(){this.roleMute();const e=ce.sessionId;if(!he.get("actionConfigs").includes("satisfaction"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用满意度评价"}));$s.__internalSend({type:A.WebsocketTypeEnum.SATISFACTION_EVALUATION,data:{session_id:e}})}startConference(){this.roleMute();if(!he.get("actionConfigs").includes("conference"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用三方会议"}));const e=ce.sessionId;if(!he.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:A.WebsocketTypeEnum.CONSULT_THREE_WAY,data:{session_id:e}})}consultRetrieve(){this.roleMute();if(!he.get("actionConfigs").includes("consult_retrieve"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取回通话"}));const e=ce.sessionId;if(!he.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:A.WebsocketTypeEnum.CONSULT_RETURN_CALL,data:{session_id:e}})}async transferAgent(e){this.roleMute();if(!he.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));const{transferIsAnswer:t}=he.getState(),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:A.WebsocketTypeEnum.TRANSFER,data:{session_id:s,transfer_type:0,transfer_dest:e}})}async transferOutline(e){this.roleMute();if(!he.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"号码不能为空"}));if(!/^\d+$/.test(e))throw new Error(JSON.stringify({code:1,msg:"号码格式错误"}));const{transferIsAnswer:t}=he.getState(),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:A.WebsocketTypeEnum.TRANSFER,data:{session_id:s,transfer_type:2,transfer_dest:e}})}}var ei;class ti{static{this._instance=null}#A;#e;#t;#s;#i;#n;#o;#r;static{this._timer=null}#a;constructor(){if(this.#A=null,this.#e=new Ks,this.#s=null,this.#i=!1,this.#r=!1,this.#a=null,this.#V=()=>{he.updateIsNextState(!0)},this.#c=()=>{he.updateIsNextState(!1)},this.initWebRtc=async()=>{if(this.#A)return;const A=ce.agentInfo.sip_account_list.find(A=>1===A.device_type);if(!A)throw new Error(JSON.stringify({code:1,msg:"未找到 sip_account_list"}));{const e=A.sip_register_addr;this.#A=new qe({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#l),await this.#A.start()}},this.#l=A=>{const{type:e,data:t}=A;Ve.emit(e,t)},!ei._creatingInstance)throw new Error("请使用 YSYTAgentSdk.getInstance() 获取实例");clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#h();ge.updateRttObject(A)},2e3),Ps.requestMediaPermissions(),this.#o=he.subscribeKey("isNextState",async e=>{if(e){await this.#e._agentLogin(vs);1===he.get("answerDevice")&&await this.#A.reconnect();let e="";const t=new URL(Gs).host;e=Gs.includes("https")?`wss://${t}`:`ws://${t}`;const{agent_no:s}=ce.agentInfo;$s.getInstance({url:`${e}/ccs-ws/api/v1/ws/call/${s}?Authorization=`,sipClient:this.#A}),ce.stateObject.state===A.AgentStatus.OFFLINE&&setTimeout(()=>{this.#e._changeState({data:{...this.#a,state_name:this.#a.state===A.AgentStatus.BUSY&&"整理"===this.#a.state_name?"忙碌":this.#a.state_name},success:()=>{he.updateDisplayText(""),Ve.emit(A.CallSipCallEventEnum.AGENT_STATE,this.#a)}})},10)}else this.#a=ce.stateObject,$s.__internalClose(),he.updateDisplayText("离线")}),this.on(A.EventName.KICK_OFF,()=>{this.destroy()}),window.addEventListener("beforeunload",A=>{A.returnValue="",this.destroy()}),window.addEventListener("online",this.#V),window.addEventListener("offline",this.#c)}#V;#c;async#g(){const e=he.get("isNextState");try{await xs(),e||he.updateIsNextState(!0)}catch(t){Ve.emit(A.EventName.FAIL_NOTIFICATION,"网络断开,请检查网络"),e&&he.updateIsNextState(!1)}}#q(){ei._timer||(ei._timer=setInterval(()=>this.#g(),3e3))}static get instance(){return this._instance}static async destroyInstance(){this._instance&&(await this._instance.destroy(),this._instance=null)}static getInstance(A){if(!this._instance){if(!A)throw new Error("首次调用必须传入配置参数");const{url:e,appKey:t,appSecret:s,agentNo:i}=A;Gs=e||"https://aicc-api.yescloudy.com",Fs=t,Ys=s,vs=i,ei._creatingInstance=!0,this._instance=new ei,delete ei._creatingInstance}return this._instance}getInit(){return this.#r}async init({actionNodeParams:e,enableBrowserAlert:t,logBuiltinEnabled:s,browserAlertTime:i,initialState:n,initDevice:o}){try{let r="";const a=new URL(Gs).host;r=Gs.includes("https")?`wss://${a}`:`ws://${a}`;const V=$s.getInstance({url:`${r}/ccs-ws/api/v1/ws/call/${vs}?Authorization=`,sipClient:null,onOpen:async()=>{const{viewHtmlElement:r,rttHTML:a}=e||{};ce.logBuiltinEnabled=s||!1,ce.browserAlertTime=i||5e3,await this.#e._agentLogin(vs);const{current_answer_device:c,current_state:l,out_display_number:h,out_display_select_switch:g}=ce.agentInfo;(n||l)===A.AgentStatus.IDLE?(he.updateActionConfigs(Bt),ce.stateObject={state:n||l,state_name:"空闲"},ce.stateBeforeChange=ce.stateObject):(n||l)===A.AgentStatus.BUSY?(he.updateActionConfigs(St),ce.stateObject={state:l,state_name:"忙碌"},ce.stateBeforeChange=ce.stateObject):(n||l)===A.AgentStatus.UNREGISTERED&&(he.updateActionConfigs(St),ce.stateObject={state:l,state_name:"未注册"}),1===g?he.updateSelectOutNumber(h):he.updateSelectOutNumber(""),he.updateAnswerDevice(o||c),1===(o||c)&&(await this.initWebRtc(),Ks.setInitRtcFn(this.initWebRtc),V.setSipClient(this.#A)),this.#t=new Ai(this.#A),e&&r&&(this.#i=!0,new Ws({container:r,rttHTML:a,statusParams:{state:ce.stateObject.state,statusName:ce.stateObject.state_name}},this,this.#t)),ce.enableBrowserAlert=t,t&&Ps.requestPermission(),Ve.emit(A.EventName.AGENT_INIT_STATUS,!0),this.#r=!0,clearInterval(ei._timer),ei._timer=null,this.#q(),this.#n=he.subscribeKey("answerDevice",async e=>{1===e?ce.stateObject.state===A.AgentStatus.UNREGISTERED&&await this.#e._changeState({data:{...ce.stateBeforeChange,state_name:ce.stateBeforeChange.state===A.AgentStatus.IDLE?"空闲":"忙碌"}}):await this.destroyRtc()})}})}catch(e){this.#i&&Hs("初始化失败"),Ve.emit(A.EventName.AGENT_INIT_STATUS,!1),this.#r=!1}}#l;on(A,e){return Ve.on(A,e),this}off(A,e){Ve.off(A,e)}offAll(){Ve.clearAllListeners()}async destroyRtc(){await(this.#A?.destroy()),this.#A=null}async destroy(){ei._instance&&(await this.destroyRtc(),this.#n?.(),this.#o?.(),clearInterval(this.#s),$s.__internalClose(),Ve.emit(A.EventName.DESTROY),this.offAll(),this.#i=!1,ei._instance=null,he.reset(),he.updateSelectOutNumber(""),clearInterval(ei._timer),ei._timer=null)}async#h(){return this.#A?this.#A.getNetworkStats():{}}get call_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{answerCall:A(()=>this.#t.answerCall()),makeCall:A=>this.#t.makeCall(A),previewMakeCall:(A,e)=>this.#t.previewCall(A,e),cancelCall:A(()=>this.#t.cancelCall()),hangup:A(()=>this.#t.hangup()),sendDTMF:A(A=>this.#t.sendDTMF(A)),holdCall:A(()=>this.#t.holdCall()),unholdCall:A(()=>this.#t.unholdCall()),consultCall:A(async A=>{try{await this.#t.consultCall(A)}catch(A){throw console.warn(A),A}}),consultRetrieve:A(()=>this.#t.consultRetrieve()),consultTransfer:A(()=>this.#t.consultTransfer()),mute:A(()=>this.#t.mute()),unmute:A(()=>this.#t.unmute()),satisfactionEvaluation:A(()=>this.#t.satisfactionEvaluation()),startConference:A(()=>this.#t.startConference()),transferAgent:A(A=>this.#t.transferAgent(A)),transferOutline:A(A=>this.#t.transferOutline(A)),earSpeakStart:A(A=>this.#e.earCall(A)),earSpeakStop:A(A=>this.#e.stopEarCall(A)),forceInsert:A(A=>this.#e.forceInsert(A)),forceDisconnect:A(A=>this.#e.forceDisconnect(A))}}get agent_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{changeDevice:A(A=>this.#e.changeDevice(A)),changeState:A(A=>this.#e.changeState(A)),getIdleAgentList:A(A=>this.#e.getIdleAgentList(A)),getAgentState:A(A=>this.#e.getAgentState(A)),setAgentExplicit:A(A=>this.#e.setAgentExplicit(A)),checkAgentLogin:A=>this.#e.checkAgentLogin(A),getCallRecord:A=>this.#e.getCallRecord(A),agentLogout:async(A,e)=>{try{await this.#e.logout(A),await this.destroy(),e?.({code:0,msg:""})}catch(A){}},listenAgentCall:A=>this.#e.listenCall(A)}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,out_display_data:s,out_display_select_switch:i,current_state:n}=ce.agentInfo,{stateObject:o}=ce,r={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:n,default_device:he.get("answerDevice"),out_display_data:s,out_display_select_switch:i,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:r[Number(A)]})),stateObject:o}}async getRealTimeCustomerInfo(){return he.get("customerObject")}setBrowserAlert(A){if("boolean"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));ce.logBuiltinEnabled=A||!1}setBrowserAlertTime(A){if("number"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));ce.browserAlertTime=A||3e3}}ei=ti,A.default=ti,Object.defineProperty(A,"__esModule",{value:!0})});
914
+ `;Ct(s,this.rttHTML)}}class Ps{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const A=await navigator.mediaDevices.enumerateDevices();if(A.some(A=>"audioinput"===A.kind&&""!==A.label))return null;return await navigator.mediaDevices.getUserMedia({audio:!0})}catch(A){return console.warn("获取音频权限失败:",A),null}}static show(A,e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(A,{body:e,tag:`xy-global-notification${(new Date).getTime()}`,renotify:!0});i.onclick=()=>{window.focus(),i.close(),t?.()},setTimeout(()=>i.close(),1e3*(s||3))}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}const zs=console.log,Xs=(...A)=>{ce.logBuiltinEnabled&&zs(...A)};let _s=null;class $s{constructor(A,e){this.url=A,this.onOpenCallback=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Ks,this.sipClient=null,this.pendingMessages=new Map,this.initWebSocket()}static getInstance({url:A,sipClient:e,onOpen:t}){if(!_s){if(!A)throw new Error("WebSocket 尚未初始化");_s=new $s(A,t),_s.sipClient=e}return _s}setSipClient(A){this.sipClient=A}stateIdleChange(){const{state:e}=ce.stateObject;e!==A.AgentStatus.IDLE&&this.apiClient._changeState({data:{...ce.stateBeforeChange,state_name:ce.stateBeforeChange.state===A.AgentStatus.IDLE?"空闲":"忙碌"}})}inCallAutoAnswer(){const{soft_device_auto_answer:e,auto_answer_time:t}=ce.agentInfo,s=1===e,i=he.get("direction");if(s&&i===A.DirectionEnum.INCOMING){const A=Number(t)||0;A>0&&(ce.autoAnswerTimer=setTimeout(()=>{this.sipClient?.answerCall(),ce.autoAnswerTimer=null},1e3*A))}}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{he.updateCustomerInfo(A.data||{phone:A.data.phone,is_vip:0,customer_name:"未知客户",city:"未知",province:"未知",contact_count:0,in_contact_count:0,trace_id:A.data.trace_id,contact_count_month:0,in_contact_count_month:0})}})}catch(A){}}putAgentState(e,t){if(!e)return;if(5===t)return void this.stateIdleChange();ce.sessionId="";const{post_call_process_time:s}=ce.agentInfo,i=s||0;if(ce.autoStateTimer&&(clearTimeout(ce.autoStateTimer),ce.autoStateTimer=null),he.updateCustomerInfo(void 0),i>0){const{state:e}=ce.stateObject;if(e===A.AgentStatus.IDLE)return;this.apiClient._changeState({data:{state:A.AgentStatus.BUSY,state_name:"整理"}}),ce.autoStateTimer=setTimeout(()=>{ce.autoStateTimer=null,this.stateIdleChange()},1e3*i)}else this.stateIdleChange()}stateBusyChange(){ce.sessionId="",clearTimeout(ce.autoStateTimer),he.updateCustomerInfo(void 0),this.apiClient._changeState({data:{state:A.AgentStatus.BUSY,state_name:"忙碌"}})}initWebSocket(){if(1===this.ws?.readyState)return;const e=Ds(Fs,Ys);this.ws=new WebSocket(this.url+e),this.ws.onopen=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now()),this.startHeartbeat(),this.manualClose=!1,this.onOpenCallback&&this.onOpenCallback()},this.ws.onmessage=async e=>{const t=JSON.parse(e.data),{type:s,data:i,code:n,msg:o,msg_id:r}=t;if(0===s&&r){const A=this.pendingMessages.get(r),e=performance.now()-A;ce.latency=parseFloat(e.toFixed(2)),this.pendingMessages.delete(r)}if(0!==s&&Xs("%cWebSocket 收到消息:","color: blue; font-weight: bold;",t),s!==A.WebsocketTypeEnum.OUT_CALL&&s!==A.WebsocketTypeEnum.PREVIEW_OUT_CALL||(0!==n?(he.reset(),Ve.emit(A.CallSipCallEventEnum.OUT_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o),he.updateActionConfigs(Bt),setTimeout(()=>{he.updateCustomerInfo(void 0)},500),this.stateIdleChange()):0===n&&(Ve.emit(A.CallSipCallEventEnum.OUT_SUCCESS),clearTimeout(ce.autoStateTimer))),s===A.WebsocketTypeEnum.AGENT_STATE){const{state:e,state_name:t}=i;ce.stateObject={state:e,state_name:t},ce.stateBeforeChange?.state||ce.stateObject.state!==A.AgentStatus.IDLE&&(ce.stateObject.state!==A.AgentStatus.BUSY||"整理"===t)||(ce.stateBeforeChange=ce.stateObject),"振铃中"===t&&he.updateDisplayText(A.DisplayTextEnum.AGENT_RINGING),e===A.AgentStatus.UNREGISTERED&&he.updateActionConfigs(ft),e===A.AgentStatus.IDLE&&ce.stateObject.state===A.AgentStatus.UNREGISTERED&&he.updateActionConfigs(Bt),Ve.emit(A.CallSipCallEventEnum.AGENT_STATE,{state:e,state_name:t})}if(s===A.WebsocketTypeEnum.OUT_CALL_INCOMING_CALL){try{await this.getCustomerInfo(i.trace_id||i.customer_phone)}catch(A){console.error(A)}i.preview_task_id?Ve.emit(A.CallSipCallEventEnum.PREVIEW_OUT_INCOMING_CALL,{customer_phone:i.customer_phone,session_id:i.session_id,preview_task_id:i.preview_task_id,trace_id:i.trace_id}):Ve.emit(A.CallSipCallEventEnum.OUT_INCOMING_CALL,{customer_phone:i.customer_phone,session_id:i.session_id,trace_id:i.trace_id}),ce.sessionId=i.session_id,he.updateActionConfigs(Qt)}if(s===A.WebsocketTypeEnum.OUT_CALL_END)if(he.updateDisplayText(""),1===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.OUT_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0);else if(2===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.OUR_SIDE_CONSULT_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0);else if(2===i.device_type&&i.agent_no!==ce.agentInfo.agent_no){he.get("isCalling")&&(he.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Tt))}else if(3===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.THREE_WAY_OUR_SIDE_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0);else if(4===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.TRANSFER_END,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0);else if(4===i.device_type&&i.agent_no!==ce.agentInfo.agent_no){Ve.emit(A.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),Ve.emit(A.EventName.FAIL_NOTIFICATION,"转接失败");const e=he.get("direction");e===A.DirectionEnum.OUTGOING?he.updateActionConfigs(Tt):e===A.DirectionEnum.INCOMING&&he.updateActionConfigs(kt)}else 5===i.device_type&&i.agent_no===ce.agentInfo.agent_no&&(ce.monitoredAgentNo="",ce.earSpeakAgent="",he.reset(),Ve.emit(A.CallSipCallEventEnum.LISTEN_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt),this.putAgentState(!0,5));if(s===A.WebsocketTypeEnum.OUT_CALL_RINGING&&1===i.type&&(Ve.emit(A.CallSipCallEventEnum.OUT_RINGING,{session_id:ce.sessionId,type:i.type}),he.updateDisplayText(A.DisplayTextEnum.RINGING)),s===A.WebsocketTypeEnum.OUT_CALL_ANSWER&&(clearTimeout(ce.autoStateTimer),he.updateIsCalling(!0),Ve.emit(A.CallSipCallEventEnum.OUT_OFF_ANSWER,{session_id:ce.sessionId}),he.updateOutCallIsAnswer(!0),he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateActionConfigs(Tt)),s===A.WebsocketTypeEnum.CONSULT_RINGING&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_RINGING,{session_id:i.session_id}),he.updateDisplayText(A.DisplayTextEnum.AGENT_RINGING),he.updateActionConfigs([]),clearTimeout(ce.autoStateTimer)),s===A.WebsocketTypeEnum.CONSULT_ANSWER&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_OFF_HOOK,{session_id:i.session_id}),he.updateConsultIsAnswer(!0),he.updateDisplayText(A.DisplayTextEnum.CONSULTING),he.updateActionConfigs(yt)),s===A.WebsocketTypeEnum.CONSULT_FAIL&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_FAILED,{custom_reason:i.custom_reason}),he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateActionConfigs(Tt)),s===A.WebsocketTypeEnum.CONSULT_CALL_IN&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_INCOMING,{agent_no:i.agent_no,agent_mane:i.agent_name,session_id:i.session_id}),ce.sessionId=i.session_id,he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.CONSULT),he.updateDisplayText(A.DisplayTextEnum.CONSULT_CALL_IN),he.updateActionConfigs(Ut),ce.enableBrowserAlert&&Ps.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{agent_mane:i.agent_name,agent_no:i.agent_no})},ce.browserAlertTime)),s===A.WebsocketTypeEnum.CONSULT_CALL_IN_SUCCESS&&(Ve.emit(A.CallSipCallEventEnum.CONSULT_CALL_IN_SUCCESS,{session_id:i.session_id}),he.updateConsultIsAnswer(!0),he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateActionConfigs(Dt)),s===A.WebsocketTypeEnum.CONSULT_RETURN_CALL_SUCCESS&&("success"===i.status?(he.updateConsultIsAnswer(!1),Ve.emit(A.CallSipCallEventEnum.CONSULT_RETURN_CALL_SUCCESS),he.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP),he.updateActionConfigs(Tt)):Ve.emit(A.EventName.FAIL_NOTIFICATION,"媒体失败")),s===A.WebsocketTypeEnum.MUTE&&(0===n?(he.updateIsMuted(!0),Ve.emit(A.CallSipCallEventEnum.MUTE_SUCCESS),he.updateDisplayText(A.DisplayTextEnum.MUTING)):(Ve.emit(A.CallSipCallEventEnum.MUTE_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.UNMUTE&&(0===n?(he.updateIsMuted(!1),Ve.emit(A.CallSipCallEventEnum.UNMUTE_SUCCESS),he.updateDisplayText(A.DisplayTextEnum.CALLING)):(Ve.emit(A.CallSipCallEventEnum.UNMUTE_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CALL_HOLD&&(0===n?(he.updateIsHold(!0),he.updateDisplayText(A.DisplayTextEnum.HOLDING),Ve.emit(A.CallSipCallEventEnum.HOLD_SUCCESS)):(Ve.emit(A.CallSipCallEventEnum.HOLD_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CALL_UNHOLD&&(0===n?(he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateIsHold(!1),Ve.emit(A.CallSipCallEventEnum.UNHOLD_SUCCESS)):(Ve.emit(A.CallSipCallEventEnum.UNHOLD_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CONSULT_TRANSFER&&(0===n?Ve.emit(A.CallSipCallEventEnum.CONSULT_TRANSFER_SUCCESS):(Ve.emit(A.CallSipCallEventEnum.CONSULT_TRANSFER_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CONSULT_TRANSFER_FAILED&&Ve.emit(A.CallSipCallEventEnum.CONSULT_TRANSFER_FAILED,i.status),s===A.WebsocketTypeEnum.CONSULT_TRANSFER_OFF_HOOK&&(he.updateDirection(A.DirectionEnum.INCOMING),he.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEventEnum.CONSULT_TRANSFER_OFF_HOOK),he.updateActionConfigs(kt),he.updateIncomingIsAnswer(!0),he.updateConsultIsAnswer(!1)),s===A.WebsocketTypeEnum.INCOMING_CALL){clearTimeout(ce.autoStateTimer),ce.sessionId=i.session_id;try{await this.getCustomerInfo(i.trace_id||i.customer_phone)}catch(A){console.error(A)}he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.INCOMING),he.updateDisplayText(A.DisplayTextEnum.INCOMING_CALL),this.inCallAutoAnswer(),1===i.direction&&Ve.emit(A.CallSipCallEventEnum.INCOMING_CALL,{customer_phone:i.customer_phone,trace_id:i.trace_id,session_id:i.session_id}),3===i.direction&&Ve.emit(A.CallSipCallEventEnum.PREDICT_INCOMING_CALL,{customer_phone:i.customer_phone,trace_id:i.trace_id,session_id:i.session_id}),he.updateActionConfigs(Ut),ce.enableBrowserAlert&&Ps.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})},ce.browserAlertTime)}if(s===A.WebsocketTypeEnum.INCOMING_CALL_OFF_HOOK&&(he.updateIncomingIsAnswer(!0),Ve.emit(A.CallSipCallEventEnum.INCOMING_CALL_OFF_HOOK,{session_id:ce.sessionId}),he.updateActionConfigs(kt),he.updateDisplayText(A.DisplayTextEnum.CALLING)),s===A.WebsocketTypeEnum.INCOMING_CALL_END)if(he.updateDisplayText(""),1===i.device_type&&i.agent_no===ce.agentInfo.agent_no)this.putAgentState(!0),he.reset(),Ve.emit(A.CallSipCallEventEnum.INCOMING_CALL_END,{session_id:i.session_id}),he.updateActionConfigs(Bt);else if(2===i.device_type&&i.agent_no===ce.agentInfo.agent_no)he.reset(),Ve.emit(A.CallSipCallEventEnum.OUR_SIDE_CONSULT_HANGUP,{session_id:i.session_id}),this.putAgentState(!0),he.updateActionConfigs(Bt);else if(2===i.device_type&&i.agent_no!==ce.agentInfo.agent_no)he.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEventEnum.OTHER_SIDE_CONSULT_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Tt);else if(3===i.device_type&&i.agent_no===ce.agentInfo.agent_no)this.putAgentState(!0),he.reset(),Ve.emit(A.CallSipCallEventEnum.THREE_WAY_OUR_SIDE_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt);else if(4===i.device_type&&i.agent_no===ce.agentInfo.agent_no)this.putAgentState(!0),he.reset(),Ve.emit(A.CallSipCallEventEnum.TRANSFER_END,{session_id:i.session_id}),he.updateActionConfigs(Bt);else if(4===i.device_type&&i.agent_no!==ce.agentInfo.agent_no){Ve.emit(A.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),Ve.emit(A.EventName.FAIL_NOTIFICATION,"转接失败");const e=he.get("direction");e===A.DirectionEnum.OUTGOING?he.updateActionConfigs(Tt):e===A.DirectionEnum.INCOMING&&he.updateActionConfigs(kt)}else 5===i.device_type&&i.agent_no===ce.agentInfo.agent_no&&(this.putAgentState(!0,5),ce.monitoredAgentNo="",ce.earSpeakAgent="",he.reset(),Ve.emit(A.CallSipCallEventEnum.LISTEN_HANGUP,{session_id:i.session_id}),he.updateActionConfigs(Bt));if(s===A.WebsocketTypeEnum.SATISFACTION_EVALUATION&&(0===n?Ve.emit(A.CallSipCallEventEnum.SATISFACTION_EVALUATION_SUCCESS):(Ve.emit(A.CallSipCallEventEnum.SATISFACTION_EVALUATION_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o))),s===A.WebsocketTypeEnum.CONSULT_THREE_WAY&&(0!==n?(Ve.emit(A.CallSipCallEventEnum.CONSULT_THREE_WAY_FAILED,o),Ve.emit(A.EventName.FAIL_NOTIFICATION,o)):0===n&&he.updateIsMeeting(!0)),s===A.WebsocketTypeEnum.CONSULT_THREE_WAY_RESULT&&("success"===i.status?(he.updateDirection(A.DirectionEnum.MEETING),he.updateDisplayText(A.DisplayTextEnum.MEETING),he.updateActionConfigs(Rt),Ve.emit(A.CallSipCallEventEnum.CONSULT_THREE_WAY_SUCCESS)):(Ve.emit(A.CallSipCallEventEnum.CONSULT_THREE_WAY_FAILED,{conf_name:i.conf_name}),he.updateIsMeeting(!1))),s===A.WebsocketTypeEnum.TRANSFER_INCOMING_CALL&&(clearTimeout(ce.autoStateTimer),i.agent_no===ce.agentInfo.agent_no?(he.updateDisplayText(A.DisplayTextEnum.TRANSFERRING),Ve.emit(A.CallSipCallEventEnum.TRANSFER_PROGRESS),he.updateActionConfigs([]),he.updateTransferIsAnswer(!0)):(ce.sessionId=i.session_id,Ve.emit(A.CallSipCallEventEnum.TRANSFER_INCOMING_CALL,{agent_no:i.agent_no,agent_name:i.agent_name,session_id:i.session_id}),he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.TRANSFER),he.updateDisplayText(A.DisplayTextEnum.TRANSFER_INCOMING_CALL),he.updateActionConfigs(Ut),ce.enableBrowserAlert&&Ps.show("📞 转接来电",`坐席 [${i.agent_no}] 正在转接...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{agent_no:i.agent_no})},ce.browserAlertTime))),s===A.WebsocketTypeEnum.TRANSFER_OFF_HOOK&&(Ve.emit(A.CallSipCallEventEnum.TRANSFER_OFF_HOOK,{session_id:ce.sessionId}),he.updateTransferIsAnswer(!1),he.updateDisplayText(A.DisplayTextEnum.CALLING),he.updateActionConfigs(kt)),s===A.WebsocketTypeEnum.TRANSFER_FAILED&&"failed"===i.status){Ve.emit(A.CallSipCallEventEnum.TRANSFER_FAILED,"未知原因"),Ve.emit(A.EventName.FAIL_NOTIFICATION,"转接失败");const e=he.get("direction");e===A.DirectionEnum.OUTGOING?he.updateActionConfigs(Tt):e===A.DirectionEnum.INCOMING&&he.updateActionConfigs(kt)}s===A.WebsocketTypeEnum.KICK_OFFLINE&&Ve.emit(A.EventName.KICK_OFF),s===A.WebsocketTypeEnum.CONTINUOUS_NOT_ANSWER&&(Ve.emit(A.EventName.FAIL_NOTIFICATION,`已连续 ${i.miss_count} 次未接, 设置忙碌`),this.stateBusyChange()),s===A.WebsocketTypeEnum.SIGN_OUT&&Ve.emit(A.EventName.SIGN_OUT),s===A.WebsocketTypeEnum.SIGN_IN_SWITCH_DEVICE&&Ve.emit(A.EventName.SIGN_IN_SWITCH_DEVICE,i),s===A.WebsocketTypeEnum.LISTEN_INCOMING_CALL&&(clearTimeout(ce.autoStateTimer),ce.sessionId=i.session_id,he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.INCOMING),this.inCallAutoAnswer(),he.updateDisplayText(A.DisplayTextEnum.LISTENING),he.updateActionConfigs(Ut),Ve.emit(A.CallSipCallEventEnum.LISTEN_INCOMING_CALL,{session_id:i.session_id}),ce.enableBrowserAlert&&Ps.show("📞 监听来电","正在来电...",()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})},ce.browserAlertTime)),s===A.WebsocketTypeEnum.LISTEN_INCOMING_CALL_OFF_HOOK&&(ce.monitoredAgentNo=i.monitored_agent_no,ce.earSpeakAgent="",he.updateIncomingIsAnswer(!0),Ve.emit(A.CallSipCallEventEnum.LISTEN_INCOMING_CALL_OFF_HOOK,{session_id:ce.sessionId,monitored_agent_no:i.monitored_agent_no}),he.updateActionConfigs(Gt),he.updateDisplayText(A.DisplayTextEnum.CALLING)),s===A.WebsocketTypeEnum.LISTEN_CALL_FAILED&&"failed"===i.status&&(Ve.emit(A.CallSipCallEventEnum.LISTEN_CALL_FAILED),ce.monitoredAgentNo=""),s===A.WebsocketTypeEnum.EAR_SPEECH&&("success"===i.status?(i.monitored_agent_no===ce.agentInfo.agent_no&&(he.updateActionConfigs(Ft),Ve.emit(A.CallSipCallEventEnum.EAR_SPEECH_BE_SUCCESS)),i.monitor_agent_no===ce.agentInfo.agent_no&&(he.updateActionConfigs(Yt),Ve.emit(A.CallSipCallEventEnum.EAR_SPEECH_SUCCESS,{monitored_agent_no:i.monitored_agent_no,monitor_agent_no:i.monitor_agent_no}),ce.earSpeakAgent=i.monitored_agent_no)):Ve.emit(A.CallSipCallEventEnum.EAR_SPEECH_FAILED)),s===A.WebsocketTypeEnum.STOP_EAR_SPEECH&&("success"===i.status?(i.monitored_agent_no===ce.agentInfo.agent_no&&he.updateActionConfigs(kt),i.monitor_agent_no===ce.agentInfo.agent_no&&he.updateActionConfigs(Gt),ce.earSpeakAgent="",Ve.emit(A.CallSipCallEventEnum.STOP_EAR_SPEECH_SUCCESS)):Ve.emit(A.CallSipCallEventEnum.STOP_EAR_SPEECH_FAILED)),s===A.WebsocketTypeEnum.CALL_FORCE_INSERT&&("success"===i.status?(i.monitored_agent_no===ce.agentInfo.agent_no&&(he.updateActionConfigs(Zt),Ve.emit(A.CallSipCallEventEnum.CALL_FORCE_INSERT_SUCCESS,{monitored_agent_no:i.monitored_agent_no,monitor_agent_no:i.monitor_agent_no})),i.monitor_agent_no===ce.agentInfo.agent_no&&(he.updateActionConfigs(vt),Ve.emit(A.CallSipCallEventEnum.CALL_FORCE_INSERT_SUCCESS_LISTENER,{monitored_agent_no:i.monitored_agent_no,monitor_agent_no:i.monitor_agent_no}))):Ve.emit(A.CallSipCallEventEnum.CALL_FORCE_INSERT_FAILED))},this.ws.onclose=e=>{Ve.emit(A.EventName.FAIL_NOTIFICATION,"链接已断开,请检查网络"),this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=e=>{Ve.emit(A.EventName.FAIL_NOTIFICATION,"连接失败,请检查网络"),this.ws?.close()}}startHeartbeat(){const A=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 5000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),e=URL.createObjectURL(A);this.heartbeatWorker=new Worker(e),this.heartbeatWorker.onmessage=()=>{const A=(new Date).getTime();this.sendMessage({type:0,msg_id:A}),this.pendingMessages.set(A,performance.now())},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify(A)),0!==A.type&&Xs("%cWebSocket 发送消息:","color: green; font-weight: bold;",A)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}reconnect(){this.initWebSocket()}static __internalClose(){_s&&(_s.close(),_s=null)}static __internalSend(A){if(!_s)throw new Error("WebSocket 尚未初始化");_s.sendMessage(A)}}class Ai{constructor(A){this.sipClient=null,this.sipClient=A}roleMute(){const A=he.get("isCalling"),e=ce.sessionId;if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}))}holdCall(){this.roleMute();const e=he.get("isHold"),{sessionId:t}=ce;if(!t)return;if(!he.get("actionConfigs").includes("hold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿保持"}));if(e)throw new Error(JSON.stringify({code:1,msg:"当前已处于保持状态"}));$s.__internalSend({type:A.WebsocketTypeEnum.CALL_HOLD,data:{session_id:t}})}unholdCall(){this.roleMute();const{isHold:e}=he.getState(),{sessionId:t}=ce;if(!he.get("actionConfigs").includes("unhold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取消保持"}));if(t){if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于保持状态"}));$s.__internalSend({type:A.WebsocketTypeEnum.CALL_UNHOLD,data:{session_id:t}})}}sendDTMF(A){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!he.get("actionConfigs").includes("dtmf"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿发送按键"}));const{isCalling:e}=he.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));this.sipClient.sendDTMF(A)}cancelCall(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=ce.sessionId;Ve.emit(A.CallSipCallEventEnum.REJECT,{session_id:e}),$s.__internalSend({type:A.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:e}})}async consultCall(e){this.roleMute();const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:n}=he.getState(),o=ce.sessionId;if(!he.get("actionConfigs").includes("consult"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询"}));if(i)throw new Error(JSON.stringify({code:1,msg:"当前正在咨询"}));if(!(t||s||n))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!o)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));$s.__internalSend({type:A.WebsocketTypeEnum.CONSULT_REQUEST,data:{session_id:o,consultation_agent_no:e}})}async answerCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}makeCall(e){if("string"!=typeof e||""===e.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));const t={};if(Rs(e))t.trace_id=e;else{if(!/^(?:1[3-9]\d{9}|0\d{2,3}-?\d{7,8})$/.test(e.trim()))throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));t.customer_phone=e.replace(/[\s\r\n-]+/g,"")}const s=he.get("isCalling"),i=he.get("selectOutNumber")||"";if(s)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.OUTGOING),$s.__internalSend({type:A.WebsocketTypeEnum.OUT_CALL,data:{...t,caller:i.replace(/[\s\r\n-]+/g,"")}})}previewCall(e,t){const s={};Rs(e)?s.trace_id=e:s.customer_phone=e.replace(/[\s\r\n-]+/g,"");const i=he.get("isCalling"),n=he.get("selectOutNumber")||"";if(i)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));if("string"!=typeof e||""===e.trim())throw new Error(JSON.stringify({code:1,msg:"外呼号码非法"}));he.updateIsCalling(!0),he.updateDirection(A.DirectionEnum.OUTGOING),$s.__internalSend({type:A.WebsocketTypeEnum.PREVIEW_OUT_CALL,data:{...s,caller:n,preview_task_id:t}})}async hangup(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=ce.sessionId;$s.__internalSend({type:A.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:e}})}mute(){this.roleMute();const e=he.get("actionConfigs"),t=he.get("isMuted"),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前未处于静音状态"}));if(!e.includes("mute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:A.WebsocketTypeEnum.MUTE,data:{session_id:s}})}unmute(){this.roleMute();const e=he.get("actionConfigs"),t=he.get("isMuted"),s=ce.sessionId;if(!t)throw new Error(JSON.stringify({code:1,msg:"当前未处于未静音状态"}));if(!e.includes("unmute"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用静音"}));$s.__internalSend({type:A.WebsocketTypeEnum.UNMUTE,data:{session_id:s}})}consultTransfer(){this.roleMute();const e=he.get("consultIsAnswer"),t=ce.sessionId;if(!he.get("actionConfigs").includes("consult_transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询转移"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:A.WebsocketTypeEnum.CONSULT_TRANSFER,data:{session_id:t}})}satisfactionEvaluation(){this.roleMute();const e=ce.sessionId;if(!he.get("actionConfigs").includes("satisfaction"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用满意度评价"}));$s.__internalSend({type:A.WebsocketTypeEnum.SATISFACTION_EVALUATION,data:{session_id:e}})}startConference(){this.roleMute();if(!he.get("actionConfigs").includes("conference"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用三方会议"}));const e=ce.sessionId;if(!he.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:A.WebsocketTypeEnum.CONSULT_THREE_WAY,data:{session_id:e}})}consultRetrieve(){this.roleMute();if(!he.get("actionConfigs").includes("consult_retrieve"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取回通话"}));const e=ce.sessionId;if(!he.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));$s.__internalSend({type:A.WebsocketTypeEnum.CONSULT_RETURN_CALL,data:{session_id:e}})}async transferAgent(e){this.roleMute();if(!he.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));const{transferIsAnswer:t}=he.getState(),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:A.WebsocketTypeEnum.TRANSFER,data:{session_id:s,transfer_type:0,transfer_dest:e}})}async transferOutline(e){this.roleMute();if(!he.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"号码不能为空"}));if(!/^\d+$/.test(e))throw new Error(JSON.stringify({code:1,msg:"号码格式错误"}));const{transferIsAnswer:t}=he.getState(),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));$s.__internalSend({type:A.WebsocketTypeEnum.TRANSFER,data:{session_id:s,transfer_type:2,transfer_dest:e}})}}var ei;class ti{static{this._instance=null}#A;#e;#t;#s;#i;#n;#o;#r;static{this._timer=null}#a;constructor(){if(this.#A=null,this.#e=new Ks,this.#s=null,this.#i=!1,this.#r=!1,this.#a=null,this.#V=()=>{he.updateIsNextState(!0)},this.#c=()=>{he.updateIsNextState(!1)},this.initWebRtc=async()=>{if(this.#A)return;const A=ce.agentInfo.sip_account_list.find(A=>1===A.device_type);if(!A)throw new Error(JSON.stringify({code:1,msg:"未找到 sip_account_list"}));{const e=A.sip_register_addr;this.#A=new qe({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#l),await this.#A.start()}},this.#l=A=>{const{type:e,data:t}=A;Ve.emit(e,t)},!ei._creatingInstance)throw new Error("请使用 YSYTAgentSdk.getInstance() 获取实例");clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#h();ge.updateRttObject(A)},2e3),Ps.requestMediaPermissions(),this.#o=he.subscribeKey("isNextState",async e=>{if(e){await this.#e._agentLogin(vs);1===he.get("answerDevice")&&await this.#A.reconnect();let e="";const t=new URL(Gs).host;e=Gs.includes("https")?`wss://${t}`:`ws://${t}`;const{agent_no:s}=ce.agentInfo;$s.getInstance({url:`${e}/ccs-ws/api/v1/ws/call/${s}?Authorization=`,sipClient:this.#A}),ce.stateObject.state===A.AgentStatus.OFFLINE&&setTimeout(()=>{this.#e._changeState({data:{...this.#a,state_name:this.#a.state===A.AgentStatus.BUSY&&"整理"===this.#a.state_name?"忙碌":this.#a.state_name},success:()=>{he.updateDisplayText(""),Ve.emit(A.CallSipCallEventEnum.AGENT_STATE,this.#a)}})},10)}else this.#a=ce.stateObject,$s.__internalClose(),he.updateDisplayText("离线")}),this.#n=he.subscribeKey("answerDevice",async e=>{1===e?ce.stateObject.state===A.AgentStatus.UNREGISTERED&&await this.#e._changeState({data:{...ce.stateBeforeChange,state_name:ce.stateBeforeChange.state===A.AgentStatus.IDLE?"空闲":"忙碌"}}):await this.destroyRtc()}),this.on(A.EventName.KICK_OFF,()=>{this.destroy()}),window.addEventListener("beforeunload",A=>{A.returnValue="",this.destroy()}),window.addEventListener("online",this.#V),window.addEventListener("offline",this.#c)}#V;#c;async#g(){const e=he.get("isNextState");try{await xs(),e||he.updateIsNextState(!0)}catch(t){Ve.emit(A.EventName.FAIL_NOTIFICATION,"网络断开,请检查网络"),e&&he.updateIsNextState(!1)}}#q(){ei._timer||(ei._timer=setInterval(()=>this.#g(),3e3))}static get instance(){return this._instance}static async destroyInstance(){this._instance&&(await this._instance.destroy(),this._instance=null)}static getInstance(A){if(!this._instance){if(!A)throw new Error("首次调用必须传入配置参数");const{url:e,appKey:t,appSecret:s,agentNo:i}=A;Gs=e||"https://aicc-api.yescloudy.com",Fs=t,Ys=s,vs=i,ei._creatingInstance=!0,this._instance=new ei,delete ei._creatingInstance}return this._instance}getInit(){return this.#r}async init({actionNodeParams:e,enableBrowserAlert:t,logBuiltinEnabled:s,browserAlertTime:i,initialState:n,initDevice:o}){try{let r="";const a=new URL(Gs).host;r=Gs.includes("https")?`wss://${a}`:`ws://${a}`;const V=$s.getInstance({url:`${r}/ccs-ws/api/v1/ws/call/${vs}?Authorization=`,sipClient:null,onOpen:async()=>{const{viewHtmlElement:r,rttHTML:a}=e||{};ce.logBuiltinEnabled=s||!1,ce.browserAlertTime=i||5e3,await this.#e._agentLogin(vs);const{current_answer_device:c,current_state:l,out_display_number:h,out_display_select_switch:g}=ce.agentInfo;(n||l)===A.AgentStatus.IDLE?(he.updateActionConfigs(Bt),ce.stateObject={state:n||l,state_name:"空闲"},ce.stateBeforeChange=ce.stateObject):(n||l)===A.AgentStatus.BUSY?(he.updateActionConfigs(St),ce.stateObject={state:l,state_name:"忙碌"},ce.stateBeforeChange=ce.stateObject):(n||l)===A.AgentStatus.UNREGISTERED&&(he.updateActionConfigs(St),ce.stateObject={state:l,state_name:"未注册"}),1===g?he.updateSelectOutNumber(h):he.updateSelectOutNumber(""),he.updateAnswerDevice(o||c),Ks.setInitRtcFn(this.initWebRtc),1===(o||c)&&(await this.initWebRtc(),V.setSipClient(this.#A)),this.#t=new Ai(this.#A),e&&r&&(this.#i=!0,new Ws({container:r,rttHTML:a,statusParams:{state:ce.stateObject.state,statusName:ce.stateObject.state_name}},this,this.#t)),ce.enableBrowserAlert=t,t&&Ps.requestPermission(),Ve.emit(A.EventName.AGENT_INIT_STATUS,!0),this.#r=!0,clearInterval(ei._timer),ei._timer=null,this.#q()}})}catch(e){this.#i&&Hs("初始化失败"),Ve.emit(A.EventName.AGENT_INIT_STATUS,!1),this.#r=!1}}#l;on(A,e){return Ve.on(A,e),this}off(A,e){Ve.off(A,e)}offAll(){Ve.clearAllListeners()}async destroyRtc(){await(this.#A?.destroy()),this.#A=null}async destroy(){ei._instance&&(await this.destroyRtc(),this.#n?.(),this.#o?.(),clearInterval(this.#s),$s.__internalClose(),Ve.emit(A.EventName.DESTROY),this.offAll(),this.#i=!1,ei._instance=null,he.reset(),he.updateSelectOutNumber(""),clearInterval(ei._timer),ei._timer=null)}async#h(){return this.#A?this.#A.getNetworkStats():{}}get call_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{answerCall:A(()=>this.#t.answerCall()),makeCall:A=>this.#t.makeCall(A),previewMakeCall:(A,e)=>this.#t.previewCall(A,e),cancelCall:A(()=>this.#t.cancelCall()),hangup:A(()=>this.#t.hangup()),sendDTMF:A(A=>this.#t.sendDTMF(A)),holdCall:A(()=>this.#t.holdCall()),unholdCall:A(()=>this.#t.unholdCall()),consultCall:A(async A=>{try{await this.#t.consultCall(A)}catch(A){throw console.warn(A),A}}),consultRetrieve:A(()=>this.#t.consultRetrieve()),consultTransfer:A(()=>this.#t.consultTransfer()),mute:A(()=>this.#t.mute()),unmute:A(()=>this.#t.unmute()),satisfactionEvaluation:A(()=>this.#t.satisfactionEvaluation()),startConference:A(()=>this.#t.startConference()),transferAgent:A(A=>this.#t.transferAgent(A)),transferOutline:A(A=>this.#t.transferOutline(A)),earSpeakStart:A(A=>this.#e.earCall(A)),earSpeakStop:A(A=>this.#e.stopEarCall(A)),forceInsert:A(A=>this.#e.forceInsert(A)),forceDisconnect:A(A=>this.#e.forceDisconnect(A))}}get agent_api(){const A=A=>(...e)=>{if(!this.#i)return A.apply(this,e);console.warn("当前未使用个人开发模式")};return{changeDevice:A(A=>this.#e.changeDevice(A)),changeState:A(A=>this.#e.changeState(A)),getIdleAgentList:A(A=>this.#e.getIdleAgentList(A)),getAgentState:A(A=>this.#e.getAgentState(A)),setAgentExplicit:A(A=>this.#e.setAgentExplicit(A)),checkAgentLogin:A=>this.#e.checkAgentLogin(A),getCallRecord:A=>this.#e.getCallRecord(A),agentLogout:async(A,e)=>{try{await this.#e.logout(A),await this.destroy(),e?.({code:0,msg:""})}catch(A){}},listenAgentCall:A=>this.#e.listenCall(A)}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,out_display_data:s,out_display_select_switch:i,current_state:n}=ce.agentInfo,{stateObject:o}=ce,r={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:n,default_device:he.get("answerDevice"),out_display_data:s,out_display_select_switch:i,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:r[Number(A)]})),stateObject:o}}async getRealTimeCustomerInfo(){return he.get("customerObject")}setBrowserAlert(A){if("boolean"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));ce.logBuiltinEnabled=A||!1}setBrowserAlertTime(A){if("number"!=typeof A)throw new Error(JSON.stringify({code:1,msg:"参数类型错误"}));ce.browserAlertTime=A||3e3}}ei=ti,A.default=ti,Object.defineProperty(A,"__esModule",{value:!0})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ysyt-agent-sdk",
3
- "version": "1.1.42",
3
+ "version": "1.1.43",
4
4
  "main": "dist/ysyt-agent-sdk.cjs.js",
5
5
  "module": "dist/ysyt-agent-sdk.esm.js",
6
6
  "types": "dist/src/index.d.ts",