ysyt-agent-sdk 1.0.23 → 1.0.24
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.
|
@@ -808,4 +808,4 @@ const ai=e=>(t,s)=>{void 0!==s?s.addInitializer(()=>{customElements.define(e,t)}
|
|
|
808
808
|
`:""}
|
|
809
809
|
</div>
|
|
810
810
|
</my-popover>
|
|
811
|
-
`;us(i,this.rttHTML)}}const Oi=new class{constructor(){this.events={}}on(e,t){this.events[e]=this.events[e]||[],this.events[e].push(t)}off(e,t){this.events[e]=(this.events[e]||[]).filter(e=>e!==t)}emit(e,...t){(this.events[e]||[]).forEach(e=>e(...t))}};class qi{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const e=await navigator.mediaDevices.enumerateDevices();if(e.some(e=>"audioinput"===e.kind&&""!==e.label))return console.log("已授权麦克风权限,无需再次获取"),null;const t=await navigator.mediaDevices.getUserMedia({audio:!0});return console.log("获取音频权限成功"),t}catch(e){return console.warn("获取音频权限失败:",e),null}}static show(e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(e,{body:t,tag:"xy-global-notification",renotify:!0});i.onclick=()=>{window.focus(),i.close(),s?.()},setTimeout(()=>i.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(e=>"audioinput"===e.kind&&""!==e.label)}catch(e){return console.warn("无法检查设备权限:",e),!1}}}let Li=null;class Ui{constructor(e){this.url=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Hi,this.initWebSocket()}static getInstance(e){if(!Li){if(!e)throw new Error("WebSocket 尚未初始化");Li=new Ui(e)}return Li}stateIdleChange(){const{state:e}=_s.stateObject;e!==et.IDLE&&this.apiClient.changeState({data:{state:et.IDLE,state_name:"空闲"}})}putAgentState(){_s.sessionId="";const{post_call_process_time:e}=_s.agentInfo,t=e||0;_s.autoStateTimer&&(clearTimeout(_s.autoStateTimer),_s.autoStateTimer=null),t>0?_s.autoStateTimer=setTimeout(()=>{_s.autoStateTimer=null,this.stateIdleChange()},t):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=e=>{const t=JSON.parse(e.data),{type:s,data:i,code:r,msg:n}=t;if(0!==s&&console.warn(s),s===rt.OUT_CALL&&0!==r&&(ct.emit(it.OUT_FAILED,n),this.stateIdleChange()),s===rt.AGENT_STATE){const{state:e,state_name:t}=i;_s.stateObject={state:e,state_name:t},"振铃中"===t&&Rs.updateDisplayText(ot.AGENT_RINGING),ct.emit(it.AGENT_STATE,{state:e,state_name:t})}s===rt.OUT_CALL_INCOMING_CALL&&(ct.emit(it.OUT_INCOMING_CALL,i),_s.sessionId=i.session_id,Rs.updateActionConfigs(bs)),s===rt.OUT_CALL_END&&(1===i.device_type?(this.putAgentState(),Rs.reset(),ct.emit(it.OUT_HANGUP,i)):2===i.device_type&&(Rs.get("direction")===tt.CONSULT?(Rs.reset(),ct.emit(it.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState()):Rs.get("isCalling")&&(Rs.updateDisplayText(ot.CALLING),ct.emit(it.OTHER_SIDE_CONSULT_HANGUP,i),Rs.updateActionConfigs(Ts)))),s===rt.OUT_CALL_RINGING&&(ct.emit(it.OUT_RINGING,i),Rs.updateDisplayText(ot.RINGING)),s===rt.OUT_CALL_ANSWER&&(ct.emit(it.OUT_OFF_ANSWER,i),Rs.updateOutCallIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_RINGING&&(ct.emit(it.CONSULT_RINGING,i),Rs.updateDisplayText(ot.AGENT_RINGING),Rs.updateActionConfigs([])),s===rt.CONSULT_ANSWER&&(ct.emit(it.CONSULT_OFF_HOOK,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CONSULTING),Rs.updateActionConfigs(Ss)),s===rt.CONSULT_FAIL&&(ct.emit(it.CONSULT_FAILED),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_CALL_IN&&(ct.emit(it.CONSULT_INCOMING,i),Rs.updateIsCalling(!0),Rs.updateDirection(tt.CONSULT),Rs.updateDisplayText(ot.CONSULT_CALL_IN),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&qi.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{agent_mane:i.agent_name})})),s===rt.CONSULT_CALL_IN_SUCCESS&&(_s.sessionId=i.session_id,ct.emit(it.CONSULT_CALL_IN_SUCCESS,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Cs)),s===rt.MUTE&&(0===r?(Rs.updateIsMuted(!0),ct.emit(it.MUTE_SUCCESS)):ct.emit(it.MUTE_FAILED,n)),s===rt.UNMUTE&&(0===r?(Rs.updateIsMuted(!1),ct.emit(it.UNMUTE_SUCCESS)):ct.emit(it.UNMUTE_FAILED,n)),s===rt.CONSULT_TRANSFER&&(0===r?ct.emit(it.CONSULT_TRANSFER_SUCCESS):ct.emit(it.CONSULT_TRANSFER_FAILED,n)),s===rt.CONSULT_TRANSFER_FAILED&&ct.emit(it.CONSULT_TRANSFER_FAILED,i.status),s===rt.CONSULT_TRANSFER_OFF_HOOK&&(Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.CALLING),ct.emit(it.CONSULT_TRANSFER_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateIncomingIsAnswer(!0),Rs.updateConsultIsAnswer(!1)),s===rt.INCOMING_CALL&&(_s.sessionId=i.session_id,Rs.updateIsCalling(!0),Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.INCOMING_CALL),ct.emit(it.INCOMING_CALL,{customer_phone:i.customer_phone}),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&qi.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})})),s===rt.INCOMING_CALL_OFF_HOOK&&(Rs.updateIncomingIsAnswer(!0),ct.emit(it.INCOMING_CALL_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateDisplayText(ot.CALLING)),s===rt.INCOMING_CALL_END&&1===i.device_type&&(ct.emit(it.INCOMING_CALL_END),Rs.reset(),Rs.updateActionConfigs(ws),this.putAgentState()),0!==s&&Oi.emit("ws-message",t)},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{this.ws?.close()}}startHeartbeat(){const e=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 14000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),t=URL.createObjectURL(e);this.heartbeatWorker=new Worker(t),this.heartbeatWorker.onmessage=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(e){this.ws?.readyState===WebSocket.OPEN?this.ws.send(JSON.stringify(e)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Li&&(Li.close(),Li=null)}static __internalSend(e){if(!Li)throw new Error("WebSocket 尚未初始化");Li.sendMessage(e)}}module.exports=class{#e=null;#t=new Hi;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const e=await this.#n();Ei.updateRttObject(e)},2e3),qi.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=Rs.subscribeKey("answerDevice",e=>{1===e&&this.initWebRtc()})}async initWebRtc(){const e=_s.agentInfo.sip_account_list.find(e=>1===e.device_type);if(e){const t=e.sip_register_addr;this.#e=new Ai({server:t.split(":")[0],user:e.sip_account,password:e.sip_password,webSocket:`wss://${t}`,callTimeout:3e4},this.#o),await this.#e.start()}}async init({actionNodeParams:e,url:t,appKey:s,appSecret:i,agentNo:r,enableBrowserAlert:n}){try{const{viewHtmlElement:o,rttHTML:a}=e;bi=t||"https://aicc-api.yescloudy.com",Ti=s,Si=i;const c=ni(s,i);await this.#t._agentLogin(r);const{agent_no:h,current_answer_device:d,init_state:l}=_s.agentInfo;l===et.IDLE?(Rs.updateActionConfigs(ws),_s.stateObject={state:l,state_name:"空闲"}):l===et.BUSY&&(Rs.updateActionConfigs(ys),_s.stateObject={state:l,state_name:"忙碌"}),Ui.getInstance(`ws://112.90.183.54:8719/api/v1/ws/call/${h}?Authorization=${c}`),Rs.updateAnswerDevice(d),1===d&&await this.initWebRtc(),e&&o&&(this.#i=!0,new Pi({container:o,rttHTML:a,statusParams:{state:et.IDLE,statusName:"空闲"}},this)),_s.enableBrowserAlert=n,n&&qi.requestPermission()}catch(e){this.#i&&mi("初始化失败"),console.log(e)}}#o=e=>{const{type:t,data:s}=e;ct.emit(t,s)};#a=e=>{};on(e,t){return ct.on(e,t),this}off(e,t){ct.off(e,t)}offAll(){ct.clearAllListeners()}#c(){if(!this.#e)throw new Error("请先初始化SDK");const e=Rs.get("isCalling"),t=_s.sessionId;if(!e)throw new Error("当前没有通话");if(!t)throw new Error("sessionId不存在")}#h(){const e=Rs.get("isHold"),{sessionId:t}=_s;if(t){if(e)throw new Error("当前已处于保持状态");Ui.__internalSend({type:rt.CALL_HOLD,data:{session_id:t}}),Rs.updateDisplayText(ot.HOLD),Rs.updateIsHold(!0)}}#d(){const{isHold:e}=Rs.getState(),{sessionId:t}=_s;if(t){if(!e)throw new Error("当前未处于保持状态");Ui.__internalSend({type:rt.CALL_UNHOLD,data:{session_id:t}}),Rs.updateDisplayText(""),Rs.updateIsHold(!1)}}#l(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t}=Rs.getState();if(!t)throw new Error("当前没有通话");this.#e.sendDTMF(e)}#g(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e,direction:t,outCallIsAnswer:s}=Rs.getState();if(!e)throw new Error("当前没有通话");s||(t===tt.INCOMING?this.#u():t===tt.OUTGOING&&this.#p())}async#f(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:r}=Rs.getState(),n=_s.sessionId;if(i)throw new Error("当前正在咨询");if(!(t||s||r))throw new Error("当前没有通话");if(!n)throw new Error("sessionId不存在");Ui.__internalSend({type:rt.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:e}})}async#m(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");await this.#e.answerCall()}async#u(){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e}=Rs.getState();if(!e)throw new Error("当前没有通话");await this.#e.rejectInCall()}async#v(e){if(!this.#e)throw new Error("请先初始化SDK");if(Rs.getState().isCalling)throw new Error("正在呼叫中,请勿重复点击");Rs.updateIsCalling(!0),Rs.updateDirection(tt.OUTGOING),Ui.__internalSend({type:rt.OUT_CALL,data:{customer_phone:e}})}async#p(){const{isCalling:e}=Rs.getState();if(!this.#e)throw new Error("请先初始化SDK");if(!e)throw new Error("当前没有通话");await this.#e.rejectOutCall()}async#w(){if(!this.#e)throw new Error("请先初始化SDK");if(!Rs.get("isCalling"))throw new Error("当前没有通话");await this.#e.hangup()}#y(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(t)throw new Error("当前未处于静音状态");if(!e.includes("mute"))throw new Error("当前状态请勿调用静音");Ui.__internalSend({type:rt.MUTE,data:{session_id:s}})}#b(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(!t)throw new Error("当前未处于未静音状态");if(!e.includes("unmute"))throw new Error("当前状态请勿调用静音");Ui.__internalSend({type:rt.UNMUTE,data:{session_id:s}})}#T(){this.#c();const e=Rs.get("consultIsAnswer"),t=_s.sessionId;if(!Rs.get("actionConfigs").includes("consult_transfer"))throw new Error("当前状态请勿调用咨询转移");if(!e)throw new Error("当前未处于咨询中");Ui.__internalSend({type:rt.CONSULT_TRANSFER,data:{session_id:t}})}async destroyRtc(){await(this.#e?.destroy())}destroy(){this.destroyRtc(),clearInterval(this.#s),Oi.off("ws-message",this.#a),Ui.__internalClose(),this.offAll(),this.#r?.()}async#n(){return this.#e?this.#e.getNetworkStats():{}}get call_api(){return this.#i?{answerCall:this.#m.bind(this),makeCall:this.#v.bind(this),cancelCall:this.#g.bind(this),hangup:this.#w.bind(this),sendDTMF:this.#l.bind(this),holdCall:this.#h.bind(this),unholdCall:this.#d.bind(this),consultCall:async e=>{try{await this.#f(e)}catch(e){throw console.warn(e),e}},consultTransfer:this.#T.bind(this),mute:this.#y.bind(this),unmute:this.#b.bind(this)}:{}}get agent_api(){return this.#i?{changeDevice:this.#t.changeDevice.bind(this.#t),changeState:this.#t.changeState.bind(this.#t),getIdleAgentList:e=>this.#t.getIdleAgentList(e),getAgentState:e=>this.#t.getAgentState(e)}:{}}};
|
|
811
|
+
`;us(i,this.rttHTML)}}const Oi=new class{constructor(){this.events={}}on(e,t){this.events[e]=this.events[e]||[],this.events[e].push(t)}off(e,t){this.events[e]=(this.events[e]||[]).filter(e=>e!==t)}emit(e,...t){(this.events[e]||[]).forEach(e=>e(...t))}};class qi{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const e=await navigator.mediaDevices.enumerateDevices();if(e.some(e=>"audioinput"===e.kind&&""!==e.label))return console.log("已授权麦克风权限,无需再次获取"),null;const t=await navigator.mediaDevices.getUserMedia({audio:!0});return console.log("获取音频权限成功"),t}catch(e){return console.warn("获取音频权限失败:",e),null}}static show(e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(e,{body:t,tag:"xy-global-notification",renotify:!0});i.onclick=()=>{window.focus(),i.close(),s?.()},setTimeout(()=>i.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(e=>"audioinput"===e.kind&&""!==e.label)}catch(e){return console.warn("无法检查设备权限:",e),!1}}}let Li=null;class Ui{constructor(e){this.url=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Hi,this.initWebSocket()}static getInstance(e){if(!Li){if(!e)throw new Error("WebSocket 尚未初始化");Li=new Ui(e)}return Li}stateIdleChange(){const{state:e}=_s.stateObject;e!==et.IDLE&&this.apiClient.changeState({data:{state:et.IDLE,state_name:"空闲"}})}putAgentState(){_s.sessionId="";const{post_call_process_time:e}=_s.agentInfo,t=e||0;_s.autoStateTimer&&(clearTimeout(_s.autoStateTimer),_s.autoStateTimer=null),t>0?_s.autoStateTimer=setTimeout(()=>{_s.autoStateTimer=null,this.stateIdleChange()},t):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=e=>{const t=JSON.parse(e.data),{type:s,data:i,code:r,msg:n}=t;if(0!==s&&console.warn(s),s===rt.OUT_CALL&&0!==r&&(ct.emit(it.OUT_FAILED,n),this.stateIdleChange()),s===rt.AGENT_STATE){const{state:e,state_name:t}=i;_s.stateObject={state:e,state_name:t},"振铃中"===t&&Rs.updateDisplayText(ot.AGENT_RINGING),ct.emit(it.AGENT_STATE,{state:e,state_name:t})}s===rt.OUT_CALL_INCOMING_CALL&&(ct.emit(it.OUT_INCOMING_CALL,i),_s.sessionId=i.session_id,Rs.updateActionConfigs(bs)),s===rt.OUT_CALL_END&&(1===i.device_type?(this.putAgentState(),Rs.reset(),ct.emit(it.OUT_HANGUP,i)):2===i.device_type&&(Rs.get("direction")===tt.CONSULT?(Rs.reset(),ct.emit(it.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState()):Rs.get("isCalling")&&(Rs.updateDisplayText(ot.CALLING),ct.emit(it.OTHER_SIDE_CONSULT_HANGUP,i),Rs.updateActionConfigs(Ts)))),s===rt.OUT_CALL_RINGING&&(ct.emit(it.OUT_RINGING,i),Rs.updateDisplayText(ot.RINGING)),s===rt.OUT_CALL_ANSWER&&(ct.emit(it.OUT_OFF_ANSWER,i),Rs.updateOutCallIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_RINGING&&(ct.emit(it.CONSULT_RINGING,i),Rs.updateDisplayText(ot.AGENT_RINGING),Rs.updateActionConfigs([])),s===rt.CONSULT_ANSWER&&(ct.emit(it.CONSULT_OFF_HOOK,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CONSULTING),Rs.updateActionConfigs(Ss)),s===rt.CONSULT_FAIL&&(ct.emit(it.CONSULT_FAILED),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_CALL_IN&&(ct.emit(it.CONSULT_INCOMING,i),Rs.updateIsCalling(!0),Rs.updateDirection(tt.CONSULT),Rs.updateDisplayText(ot.CONSULT_CALL_IN),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&qi.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{agent_mane:i.agent_name})})),s===rt.CONSULT_CALL_IN_SUCCESS&&(_s.sessionId=i.session_id,ct.emit(it.CONSULT_CALL_IN_SUCCESS,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Cs)),s===rt.MUTE&&(0===r?(Rs.updateIsMuted(!0),ct.emit(it.MUTE_SUCCESS)):ct.emit(it.MUTE_FAILED,n)),s===rt.UNMUTE&&(0===r?(Rs.updateIsMuted(!1),ct.emit(it.UNMUTE_SUCCESS)):ct.emit(it.UNMUTE_FAILED,n)),s===rt.CONSULT_TRANSFER&&(0===r?ct.emit(it.CONSULT_TRANSFER_SUCCESS):ct.emit(it.CONSULT_TRANSFER_FAILED,n)),s===rt.CONSULT_TRANSFER_FAILED&&ct.emit(it.CONSULT_TRANSFER_FAILED,i.status),s===rt.CONSULT_TRANSFER_OFF_HOOK&&(Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.CALLING),ct.emit(it.CONSULT_TRANSFER_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateIncomingIsAnswer(!0),Rs.updateConsultIsAnswer(!1)),s===rt.INCOMING_CALL&&(_s.sessionId=i.session_id,Rs.updateIsCalling(!0),Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.INCOMING_CALL),ct.emit(it.INCOMING_CALL,{customer_phone:i.customer_phone}),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&qi.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})})),s===rt.INCOMING_CALL_OFF_HOOK&&(Rs.updateIncomingIsAnswer(!0),ct.emit(it.INCOMING_CALL_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateDisplayText(ot.CALLING)),s===rt.INCOMING_CALL_END&&1===i.device_type&&(ct.emit(it.INCOMING_CALL_END),Rs.reset(),Rs.updateActionConfigs(ws),this.putAgentState()),0!==s&&Oi.emit("ws-message",t)},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{this.ws?.close()}}startHeartbeat(){const e=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 14000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),t=URL.createObjectURL(e);this.heartbeatWorker=new Worker(t),this.heartbeatWorker.onmessage=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(e){this.ws?.readyState===WebSocket.OPEN?this.ws.send(JSON.stringify(e)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Li&&(Li.close(),Li=null)}static __internalSend(e){if(!Li)throw new Error("WebSocket 尚未初始化");Li.sendMessage(e)}}module.exports=class{#e=null;#t=new Hi;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const e=await this.#n();Ei.updateRttObject(e)},2e3),qi.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=Rs.subscribeKey("answerDevice",e=>{1===e&&this.initWebRtc()})}async initWebRtc(){const e=_s.agentInfo.sip_account_list.find(e=>1===e.device_type);if(e){const t=e.sip_register_addr;this.#e=new Ai({server:t.split(":")[0],user:e.sip_account,password:e.sip_password,webSocket:`wss://${t}`,callTimeout:3e4},this.#o),await this.#e.start()}}async init({actionNodeParams:e,url:t,appKey:s,appSecret:i,agentNo:r,enableBrowserAlert:n}){try{const{viewHtmlElement:o,rttHTML:a}=e;bi=t||"https://aicc-api.yescloudy.com",Ti=s,Si=i;const c=ni(s,i);await this.#t._agentLogin(r);const{agent_no:h,current_answer_device:d,init_state:l}=_s.agentInfo;l===et.IDLE?(Rs.updateActionConfigs(ws),_s.stateObject={state:l,state_name:"空闲"}):l===et.BUSY&&(Rs.updateActionConfigs(ys),_s.stateObject={state:l,state_name:"忙碌"}),Ui.getInstance(`ws://112.90.183.54:8719/api/v1/ws/call/${h}?Authorization=${c}`),Rs.updateAnswerDevice(d),1===d&&await this.initWebRtc(),e&&o&&(this.#i=!0,new Pi({container:o,rttHTML:a,statusParams:{state:et.IDLE,statusName:"空闲"}},this)),_s.enableBrowserAlert=n,n&&qi.requestPermission()}catch(e){this.#i&&mi("初始化失败"),console.log(e)}}#o=e=>{const{type:t,data:s}=e;ct.emit(t,s)};#a=e=>{};on(e,t){return ct.on(e,t),this}off(e,t){ct.off(e,t)}offAll(){ct.clearAllListeners()}#c(){if(!this.#e)throw new Error("请先初始化SDK");const e=Rs.get("isCalling"),t=_s.sessionId;if(!e)throw new Error("当前没有通话");if(!t)throw new Error("sessionId不存在")}#h(){const e=Rs.get("isHold"),{sessionId:t}=_s;if(t){if(e)throw new Error("当前已处于保持状态");Ui.__internalSend({type:rt.CALL_HOLD,data:{session_id:t}}),Rs.updateDisplayText(ot.HOLD),Rs.updateIsHold(!0)}}#d(){const{isHold:e}=Rs.getState(),{sessionId:t}=_s;if(t){if(!e)throw new Error("当前未处于保持状态");Ui.__internalSend({type:rt.CALL_UNHOLD,data:{session_id:t}}),Rs.updateDisplayText(""),Rs.updateIsHold(!1)}}#l(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t}=Rs.getState();if(!t)throw new Error("当前没有通话");this.#e.sendDTMF(e)}#g(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e,direction:t,outCallIsAnswer:s}=Rs.getState();if(!e)throw new Error("当前没有通话");s||(t===tt.INCOMING?this.#u():t===tt.OUTGOING&&this.#p())}async#f(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:r}=Rs.getState(),n=_s.sessionId;if(i)throw new Error("当前正在咨询");if(!(t||s||r))throw new Error("当前没有通话");if(!n)throw new Error("sessionId不存在");Ui.__internalSend({type:rt.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:e}})}async#m(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");await this.#e.answerCall()}async#u(){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e}=Rs.getState();if(!e)throw new Error("当前没有通话");await this.#e.rejectInCall()}async#v(e){if(!this.#e)throw new Error("请先初始化SDK");if(Rs.getState().isCalling)throw new Error("正在呼叫中,请勿重复点击");Rs.updateIsCalling(!0),Rs.updateDirection(tt.OUTGOING),Ui.__internalSend({type:rt.OUT_CALL,data:{customer_phone:e}})}async#p(){const{isCalling:e}=Rs.getState();if(!this.#e)throw new Error("请先初始化SDK");if(!e)throw new Error("当前没有通话");await this.#e.rejectOutCall()}async#w(){if(!this.#e)throw new Error("请先初始化SDK");if(!Rs.get("isCalling"))throw new Error("当前没有通话");await this.#e.hangup()}#y(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(t)throw new Error("当前未处于静音状态");if(!e.includes("mute"))throw new Error("当前状态请勿调用静音");Ui.__internalSend({type:rt.MUTE,data:{session_id:s}})}#b(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(!t)throw new Error("当前未处于未静音状态");if(!e.includes("unmute"))throw new Error("当前状态请勿调用静音");Ui.__internalSend({type:rt.UNMUTE,data:{session_id:s}})}#T(){this.#c();const e=Rs.get("consultIsAnswer"),t=_s.sessionId;if(!Rs.get("actionConfigs").includes("consult_transfer"))throw new Error("当前状态请勿调用咨询转移");if(!e)throw new Error("当前未处于咨询中");Ui.__internalSend({type:rt.CONSULT_TRANSFER,data:{session_id:t}})}async destroyRtc(){await(this.#e?.destroy())}destroy(){this.destroyRtc(),clearInterval(this.#s),Oi.off("ws-message",this.#a),Ui.__internalClose(),this.offAll(),this.#r?.(),this.#e=null,this.#t=null,this.#i=!1,console.log(1111)}async#n(){return this.#e?this.#e.getNetworkStats():{}}get call_api(){return this.#i?{answerCall:this.#m.bind(this),makeCall:this.#v.bind(this),cancelCall:this.#g.bind(this),hangup:this.#w.bind(this),sendDTMF:this.#l.bind(this),holdCall:this.#h.bind(this),unholdCall:this.#d.bind(this),consultCall:async e=>{try{await this.#f(e)}catch(e){throw console.warn(e),e}},consultTransfer:this.#T.bind(this),mute:this.#y.bind(this),unmute:this.#b.bind(this)}:{}}get agent_api(){return this.#i?{changeDevice:this.#t.changeDevice.bind(this.#t),changeState:this.#t.changeState.bind(this.#t),getIdleAgentList:e=>this.#t.getIdleAgentList(e),getAgentState:e=>this.#t.getAgentState(e)}:{}}};
|
|
@@ -808,4 +808,4 @@ const ci=e=>(t,s)=>{void 0!==s?s.addInitializer(()=>{customElements.define(e,t)}
|
|
|
808
808
|
`:""}
|
|
809
809
|
</div>
|
|
810
810
|
</my-popover>
|
|
811
|
-
`;us(i,this.rttHTML)}}const qi=new class{constructor(){this.events={}}on(e,t){this.events[e]=this.events[e]||[],this.events[e].push(t)}off(e,t){this.events[e]=(this.events[e]||[]).filter(e=>e!==t)}emit(e,...t){(this.events[e]||[]).forEach(e=>e(...t))}};class Li{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const e=await navigator.mediaDevices.enumerateDevices();if(e.some(e=>"audioinput"===e.kind&&""!==e.label))return console.log("已授权麦克风权限,无需再次获取"),null;const t=await navigator.mediaDevices.getUserMedia({audio:!0});return console.log("获取音频权限成功"),t}catch(e){return console.warn("获取音频权限失败:",e),null}}static show(e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(e,{body:t,tag:"xy-global-notification",renotify:!0});i.onclick=()=>{window.focus(),i.close(),s?.()},setTimeout(()=>i.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(e=>"audioinput"===e.kind&&""!==e.label)}catch(e){return console.warn("无法检查设备权限:",e),!1}}}let Ui=null;class Mi{constructor(e){this.url=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Pi,this.initWebSocket()}static getInstance(e){if(!Ui){if(!e)throw new Error("WebSocket 尚未初始化");Ui=new Mi(e)}return Ui}stateIdleChange(){const{state:e}=_s.stateObject;e!==et.IDLE&&this.apiClient.changeState({data:{state:et.IDLE,state_name:"空闲"}})}putAgentState(){_s.sessionId="";const{post_call_process_time:e}=_s.agentInfo,t=e||0;_s.autoStateTimer&&(clearTimeout(_s.autoStateTimer),_s.autoStateTimer=null),t>0?_s.autoStateTimer=setTimeout(()=>{_s.autoStateTimer=null,this.stateIdleChange()},t):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=e=>{const t=JSON.parse(e.data),{type:s,data:i,code:r,msg:n}=t;if(0!==s&&console.warn(s),s===rt.OUT_CALL&&0!==r&&(ct.emit(it.OUT_FAILED,n),this.stateIdleChange()),s===rt.AGENT_STATE){const{state:e,state_name:t}=i;_s.stateObject={state:e,state_name:t},"振铃中"===t&&Rs.updateDisplayText(ot.AGENT_RINGING),ct.emit(it.AGENT_STATE,{state:e,state_name:t})}s===rt.OUT_CALL_INCOMING_CALL&&(ct.emit(it.OUT_INCOMING_CALL,i),_s.sessionId=i.session_id,Rs.updateActionConfigs(bs)),s===rt.OUT_CALL_END&&(1===i.device_type?(this.putAgentState(),Rs.reset(),ct.emit(it.OUT_HANGUP,i)):2===i.device_type&&(Rs.get("direction")===tt.CONSULT?(Rs.reset(),ct.emit(it.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState()):Rs.get("isCalling")&&(Rs.updateDisplayText(ot.CALLING),ct.emit(it.OTHER_SIDE_CONSULT_HANGUP,i),Rs.updateActionConfigs(Ts)))),s===rt.OUT_CALL_RINGING&&(ct.emit(it.OUT_RINGING,i),Rs.updateDisplayText(ot.RINGING)),s===rt.OUT_CALL_ANSWER&&(ct.emit(it.OUT_OFF_ANSWER,i),Rs.updateOutCallIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_RINGING&&(ct.emit(it.CONSULT_RINGING,i),Rs.updateDisplayText(ot.AGENT_RINGING),Rs.updateActionConfigs([])),s===rt.CONSULT_ANSWER&&(ct.emit(it.CONSULT_OFF_HOOK,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CONSULTING),Rs.updateActionConfigs(Ss)),s===rt.CONSULT_FAIL&&(ct.emit(it.CONSULT_FAILED),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_CALL_IN&&(ct.emit(it.CONSULT_INCOMING,i),Rs.updateIsCalling(!0),Rs.updateDirection(tt.CONSULT),Rs.updateDisplayText(ot.CONSULT_CALL_IN),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&Li.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{agent_mane:i.agent_name})})),s===rt.CONSULT_CALL_IN_SUCCESS&&(_s.sessionId=i.session_id,ct.emit(it.CONSULT_CALL_IN_SUCCESS,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Cs)),s===rt.MUTE&&(0===r?(Rs.updateIsMuted(!0),ct.emit(it.MUTE_SUCCESS)):ct.emit(it.MUTE_FAILED,n)),s===rt.UNMUTE&&(0===r?(Rs.updateIsMuted(!1),ct.emit(it.UNMUTE_SUCCESS)):ct.emit(it.UNMUTE_FAILED,n)),s===rt.CONSULT_TRANSFER&&(0===r?ct.emit(it.CONSULT_TRANSFER_SUCCESS):ct.emit(it.CONSULT_TRANSFER_FAILED,n)),s===rt.CONSULT_TRANSFER_FAILED&&ct.emit(it.CONSULT_TRANSFER_FAILED,i.status),s===rt.CONSULT_TRANSFER_OFF_HOOK&&(Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.CALLING),ct.emit(it.CONSULT_TRANSFER_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateIncomingIsAnswer(!0),Rs.updateConsultIsAnswer(!1)),s===rt.INCOMING_CALL&&(_s.sessionId=i.session_id,Rs.updateIsCalling(!0),Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.INCOMING_CALL),ct.emit(it.INCOMING_CALL,{customer_phone:i.customer_phone}),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&Li.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})})),s===rt.INCOMING_CALL_OFF_HOOK&&(Rs.updateIncomingIsAnswer(!0),ct.emit(it.INCOMING_CALL_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateDisplayText(ot.CALLING)),s===rt.INCOMING_CALL_END&&1===i.device_type&&(ct.emit(it.INCOMING_CALL_END),Rs.reset(),Rs.updateActionConfigs(ws),this.putAgentState()),0!==s&&qi.emit("ws-message",t)},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{this.ws?.close()}}startHeartbeat(){const e=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 14000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),t=URL.createObjectURL(e);this.heartbeatWorker=new Worker(t),this.heartbeatWorker.onmessage=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(e){this.ws?.readyState===WebSocket.OPEN?this.ws.send(JSON.stringify(e)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Ui&&(Ui.close(),Ui=null)}static __internalSend(e){if(!Ui)throw new Error("WebSocket 尚未初始化");Ui.sendMessage(e)}}class Fi{#e=null;#t=new Pi;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const e=await this.#n();Ai.updateRttObject(e)},2e3),Li.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=Rs.subscribeKey("answerDevice",e=>{1===e&&this.initWebRtc()})}async initWebRtc(){const e=_s.agentInfo.sip_account_list.find(e=>1===e.device_type);if(e){const t=e.sip_register_addr;this.#e=new _i({server:t.split(":")[0],user:e.sip_account,password:e.sip_password,webSocket:`wss://${t}`,callTimeout:3e4},this.#o),await this.#e.start()}}async init({actionNodeParams:e,url:t,appKey:s,appSecret:i,agentNo:r,enableBrowserAlert:n}){try{const{viewHtmlElement:o,rttHTML:a}=e;Ti=t||"https://aicc-api.yescloudy.com",Si=s,Ci=i;const c=oi(s,i);await this.#t._agentLogin(r);const{agent_no:h,current_answer_device:d,init_state:l}=_s.agentInfo;l===et.IDLE?(Rs.updateActionConfigs(ws),_s.stateObject={state:l,state_name:"空闲"}):l===et.BUSY&&(Rs.updateActionConfigs(ys),_s.stateObject={state:l,state_name:"忙碌"}),Mi.getInstance(`ws://112.90.183.54:8719/api/v1/ws/call/${h}?Authorization=${c}`),Rs.updateAnswerDevice(d),1===d&&await this.initWebRtc(),e&&o&&(this.#i=!0,new Oi({container:o,rttHTML:a,statusParams:{state:et.IDLE,statusName:"空闲"}},this)),_s.enableBrowserAlert=n,n&&Li.requestPermission()}catch(e){this.#i&&vi("初始化失败"),console.log(e)}}#o=e=>{const{type:t,data:s}=e;ct.emit(t,s)};#a=e=>{};on(e,t){return ct.on(e,t),this}off(e,t){ct.off(e,t)}offAll(){ct.clearAllListeners()}#c(){if(!this.#e)throw new Error("请先初始化SDK");const e=Rs.get("isCalling"),t=_s.sessionId;if(!e)throw new Error("当前没有通话");if(!t)throw new Error("sessionId不存在")}#h(){const e=Rs.get("isHold"),{sessionId:t}=_s;if(t){if(e)throw new Error("当前已处于保持状态");Mi.__internalSend({type:rt.CALL_HOLD,data:{session_id:t}}),Rs.updateDisplayText(ot.HOLD),Rs.updateIsHold(!0)}}#d(){const{isHold:e}=Rs.getState(),{sessionId:t}=_s;if(t){if(!e)throw new Error("当前未处于保持状态");Mi.__internalSend({type:rt.CALL_UNHOLD,data:{session_id:t}}),Rs.updateDisplayText(""),Rs.updateIsHold(!1)}}#l(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t}=Rs.getState();if(!t)throw new Error("当前没有通话");this.#e.sendDTMF(e)}#g(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e,direction:t,outCallIsAnswer:s}=Rs.getState();if(!e)throw new Error("当前没有通话");s||(t===tt.INCOMING?this.#u():t===tt.OUTGOING&&this.#p())}async#f(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:r}=Rs.getState(),n=_s.sessionId;if(i)throw new Error("当前正在咨询");if(!(t||s||r))throw new Error("当前没有通话");if(!n)throw new Error("sessionId不存在");Mi.__internalSend({type:rt.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:e}})}async#m(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");await this.#e.answerCall()}async#u(){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e}=Rs.getState();if(!e)throw new Error("当前没有通话");await this.#e.rejectInCall()}async#v(e){if(!this.#e)throw new Error("请先初始化SDK");if(Rs.getState().isCalling)throw new Error("正在呼叫中,请勿重复点击");Rs.updateIsCalling(!0),Rs.updateDirection(tt.OUTGOING),Mi.__internalSend({type:rt.OUT_CALL,data:{customer_phone:e}})}async#p(){const{isCalling:e}=Rs.getState();if(!this.#e)throw new Error("请先初始化SDK");if(!e)throw new Error("当前没有通话");await this.#e.rejectOutCall()}async#w(){if(!this.#e)throw new Error("请先初始化SDK");if(!Rs.get("isCalling"))throw new Error("当前没有通话");await this.#e.hangup()}#y(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(t)throw new Error("当前未处于静音状态");if(!e.includes("mute"))throw new Error("当前状态请勿调用静音");Mi.__internalSend({type:rt.MUTE,data:{session_id:s}})}#b(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(!t)throw new Error("当前未处于未静音状态");if(!e.includes("unmute"))throw new Error("当前状态请勿调用静音");Mi.__internalSend({type:rt.UNMUTE,data:{session_id:s}})}#T(){this.#c();const e=Rs.get("consultIsAnswer"),t=_s.sessionId;if(!Rs.get("actionConfigs").includes("consult_transfer"))throw new Error("当前状态请勿调用咨询转移");if(!e)throw new Error("当前未处于咨询中");Mi.__internalSend({type:rt.CONSULT_TRANSFER,data:{session_id:t}})}async destroyRtc(){await(this.#e?.destroy())}destroy(){this.destroyRtc(),clearInterval(this.#s),qi.off("ws-message",this.#a),Mi.__internalClose(),this.offAll(),this.#r?.()}async#n(){return this.#e?this.#e.getNetworkStats():{}}get call_api(){return this.#i?{answerCall:this.#m.bind(this),makeCall:this.#v.bind(this),cancelCall:this.#g.bind(this),hangup:this.#w.bind(this),sendDTMF:this.#l.bind(this),holdCall:this.#h.bind(this),unholdCall:this.#d.bind(this),consultCall:async e=>{try{await this.#f(e)}catch(e){throw console.warn(e),e}},consultTransfer:this.#T.bind(this),mute:this.#y.bind(this),unmute:this.#b.bind(this)}:{}}get agent_api(){return this.#i?{changeDevice:this.#t.changeDevice.bind(this.#t),changeState:this.#t.changeState.bind(this.#t),getIdleAgentList:e=>this.#t.getIdleAgentList(e),getAgentState:e=>this.#t.getAgentState(e)}:{}}}export{Fi as default};
|
|
811
|
+
`;us(i,this.rttHTML)}}const qi=new class{constructor(){this.events={}}on(e,t){this.events[e]=this.events[e]||[],this.events[e].push(t)}off(e,t){this.events[e]=(this.events[e]||[]).filter(e=>e!==t)}emit(e,...t){(this.events[e]||[]).forEach(e=>e(...t))}};class Li{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const e=await navigator.mediaDevices.enumerateDevices();if(e.some(e=>"audioinput"===e.kind&&""!==e.label))return console.log("已授权麦克风权限,无需再次获取"),null;const t=await navigator.mediaDevices.getUserMedia({audio:!0});return console.log("获取音频权限成功"),t}catch(e){return console.warn("获取音频权限失败:",e),null}}static show(e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(e,{body:t,tag:"xy-global-notification",renotify:!0});i.onclick=()=>{window.focus(),i.close(),s?.()},setTimeout(()=>i.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(e=>"audioinput"===e.kind&&""!==e.label)}catch(e){return console.warn("无法检查设备权限:",e),!1}}}let Ui=null;class Mi{constructor(e){this.url=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Pi,this.initWebSocket()}static getInstance(e){if(!Ui){if(!e)throw new Error("WebSocket 尚未初始化");Ui=new Mi(e)}return Ui}stateIdleChange(){const{state:e}=_s.stateObject;e!==et.IDLE&&this.apiClient.changeState({data:{state:et.IDLE,state_name:"空闲"}})}putAgentState(){_s.sessionId="";const{post_call_process_time:e}=_s.agentInfo,t=e||0;_s.autoStateTimer&&(clearTimeout(_s.autoStateTimer),_s.autoStateTimer=null),t>0?_s.autoStateTimer=setTimeout(()=>{_s.autoStateTimer=null,this.stateIdleChange()},t):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=e=>{const t=JSON.parse(e.data),{type:s,data:i,code:r,msg:n}=t;if(0!==s&&console.warn(s),s===rt.OUT_CALL&&0!==r&&(ct.emit(it.OUT_FAILED,n),this.stateIdleChange()),s===rt.AGENT_STATE){const{state:e,state_name:t}=i;_s.stateObject={state:e,state_name:t},"振铃中"===t&&Rs.updateDisplayText(ot.AGENT_RINGING),ct.emit(it.AGENT_STATE,{state:e,state_name:t})}s===rt.OUT_CALL_INCOMING_CALL&&(ct.emit(it.OUT_INCOMING_CALL,i),_s.sessionId=i.session_id,Rs.updateActionConfigs(bs)),s===rt.OUT_CALL_END&&(1===i.device_type?(this.putAgentState(),Rs.reset(),ct.emit(it.OUT_HANGUP,i)):2===i.device_type&&(Rs.get("direction")===tt.CONSULT?(Rs.reset(),ct.emit(it.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState()):Rs.get("isCalling")&&(Rs.updateDisplayText(ot.CALLING),ct.emit(it.OTHER_SIDE_CONSULT_HANGUP,i),Rs.updateActionConfigs(Ts)))),s===rt.OUT_CALL_RINGING&&(ct.emit(it.OUT_RINGING,i),Rs.updateDisplayText(ot.RINGING)),s===rt.OUT_CALL_ANSWER&&(ct.emit(it.OUT_OFF_ANSWER,i),Rs.updateOutCallIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_RINGING&&(ct.emit(it.CONSULT_RINGING,i),Rs.updateDisplayText(ot.AGENT_RINGING),Rs.updateActionConfigs([])),s===rt.CONSULT_ANSWER&&(ct.emit(it.CONSULT_OFF_HOOK,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CONSULTING),Rs.updateActionConfigs(Ss)),s===rt.CONSULT_FAIL&&(ct.emit(it.CONSULT_FAILED),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_CALL_IN&&(ct.emit(it.CONSULT_INCOMING,i),Rs.updateIsCalling(!0),Rs.updateDirection(tt.CONSULT),Rs.updateDisplayText(ot.CONSULT_CALL_IN),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&Li.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{agent_mane:i.agent_name})})),s===rt.CONSULT_CALL_IN_SUCCESS&&(_s.sessionId=i.session_id,ct.emit(it.CONSULT_CALL_IN_SUCCESS,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Cs)),s===rt.MUTE&&(0===r?(Rs.updateIsMuted(!0),ct.emit(it.MUTE_SUCCESS)):ct.emit(it.MUTE_FAILED,n)),s===rt.UNMUTE&&(0===r?(Rs.updateIsMuted(!1),ct.emit(it.UNMUTE_SUCCESS)):ct.emit(it.UNMUTE_FAILED,n)),s===rt.CONSULT_TRANSFER&&(0===r?ct.emit(it.CONSULT_TRANSFER_SUCCESS):ct.emit(it.CONSULT_TRANSFER_FAILED,n)),s===rt.CONSULT_TRANSFER_FAILED&&ct.emit(it.CONSULT_TRANSFER_FAILED,i.status),s===rt.CONSULT_TRANSFER_OFF_HOOK&&(Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.CALLING),ct.emit(it.CONSULT_TRANSFER_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateIncomingIsAnswer(!0),Rs.updateConsultIsAnswer(!1)),s===rt.INCOMING_CALL&&(_s.sessionId=i.session_id,Rs.updateIsCalling(!0),Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.INCOMING_CALL),ct.emit(it.INCOMING_CALL,{customer_phone:i.customer_phone}),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&Li.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})})),s===rt.INCOMING_CALL_OFF_HOOK&&(Rs.updateIncomingIsAnswer(!0),ct.emit(it.INCOMING_CALL_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateDisplayText(ot.CALLING)),s===rt.INCOMING_CALL_END&&1===i.device_type&&(ct.emit(it.INCOMING_CALL_END),Rs.reset(),Rs.updateActionConfigs(ws),this.putAgentState()),0!==s&&qi.emit("ws-message",t)},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{this.ws?.close()}}startHeartbeat(){const e=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 14000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),t=URL.createObjectURL(e);this.heartbeatWorker=new Worker(t),this.heartbeatWorker.onmessage=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(e){this.ws?.readyState===WebSocket.OPEN?this.ws.send(JSON.stringify(e)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Ui&&(Ui.close(),Ui=null)}static __internalSend(e){if(!Ui)throw new Error("WebSocket 尚未初始化");Ui.sendMessage(e)}}class Fi{#e=null;#t=new Pi;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const e=await this.#n();Ai.updateRttObject(e)},2e3),Li.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=Rs.subscribeKey("answerDevice",e=>{1===e&&this.initWebRtc()})}async initWebRtc(){const e=_s.agentInfo.sip_account_list.find(e=>1===e.device_type);if(e){const t=e.sip_register_addr;this.#e=new _i({server:t.split(":")[0],user:e.sip_account,password:e.sip_password,webSocket:`wss://${t}`,callTimeout:3e4},this.#o),await this.#e.start()}}async init({actionNodeParams:e,url:t,appKey:s,appSecret:i,agentNo:r,enableBrowserAlert:n}){try{const{viewHtmlElement:o,rttHTML:a}=e;Ti=t||"https://aicc-api.yescloudy.com",Si=s,Ci=i;const c=oi(s,i);await this.#t._agentLogin(r);const{agent_no:h,current_answer_device:d,init_state:l}=_s.agentInfo;l===et.IDLE?(Rs.updateActionConfigs(ws),_s.stateObject={state:l,state_name:"空闲"}):l===et.BUSY&&(Rs.updateActionConfigs(ys),_s.stateObject={state:l,state_name:"忙碌"}),Mi.getInstance(`ws://112.90.183.54:8719/api/v1/ws/call/${h}?Authorization=${c}`),Rs.updateAnswerDevice(d),1===d&&await this.initWebRtc(),e&&o&&(this.#i=!0,new Oi({container:o,rttHTML:a,statusParams:{state:et.IDLE,statusName:"空闲"}},this)),_s.enableBrowserAlert=n,n&&Li.requestPermission()}catch(e){this.#i&&vi("初始化失败"),console.log(e)}}#o=e=>{const{type:t,data:s}=e;ct.emit(t,s)};#a=e=>{};on(e,t){return ct.on(e,t),this}off(e,t){ct.off(e,t)}offAll(){ct.clearAllListeners()}#c(){if(!this.#e)throw new Error("请先初始化SDK");const e=Rs.get("isCalling"),t=_s.sessionId;if(!e)throw new Error("当前没有通话");if(!t)throw new Error("sessionId不存在")}#h(){const e=Rs.get("isHold"),{sessionId:t}=_s;if(t){if(e)throw new Error("当前已处于保持状态");Mi.__internalSend({type:rt.CALL_HOLD,data:{session_id:t}}),Rs.updateDisplayText(ot.HOLD),Rs.updateIsHold(!0)}}#d(){const{isHold:e}=Rs.getState(),{sessionId:t}=_s;if(t){if(!e)throw new Error("当前未处于保持状态");Mi.__internalSend({type:rt.CALL_UNHOLD,data:{session_id:t}}),Rs.updateDisplayText(""),Rs.updateIsHold(!1)}}#l(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t}=Rs.getState();if(!t)throw new Error("当前没有通话");this.#e.sendDTMF(e)}#g(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e,direction:t,outCallIsAnswer:s}=Rs.getState();if(!e)throw new Error("当前没有通话");s||(t===tt.INCOMING?this.#u():t===tt.OUTGOING&&this.#p())}async#f(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:r}=Rs.getState(),n=_s.sessionId;if(i)throw new Error("当前正在咨询");if(!(t||s||r))throw new Error("当前没有通话");if(!n)throw new Error("sessionId不存在");Mi.__internalSend({type:rt.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:e}})}async#m(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");await this.#e.answerCall()}async#u(){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e}=Rs.getState();if(!e)throw new Error("当前没有通话");await this.#e.rejectInCall()}async#v(e){if(!this.#e)throw new Error("请先初始化SDK");if(Rs.getState().isCalling)throw new Error("正在呼叫中,请勿重复点击");Rs.updateIsCalling(!0),Rs.updateDirection(tt.OUTGOING),Mi.__internalSend({type:rt.OUT_CALL,data:{customer_phone:e}})}async#p(){const{isCalling:e}=Rs.getState();if(!this.#e)throw new Error("请先初始化SDK");if(!e)throw new Error("当前没有通话");await this.#e.rejectOutCall()}async#w(){if(!this.#e)throw new Error("请先初始化SDK");if(!Rs.get("isCalling"))throw new Error("当前没有通话");await this.#e.hangup()}#y(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(t)throw new Error("当前未处于静音状态");if(!e.includes("mute"))throw new Error("当前状态请勿调用静音");Mi.__internalSend({type:rt.MUTE,data:{session_id:s}})}#b(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(!t)throw new Error("当前未处于未静音状态");if(!e.includes("unmute"))throw new Error("当前状态请勿调用静音");Mi.__internalSend({type:rt.UNMUTE,data:{session_id:s}})}#T(){this.#c();const e=Rs.get("consultIsAnswer"),t=_s.sessionId;if(!Rs.get("actionConfigs").includes("consult_transfer"))throw new Error("当前状态请勿调用咨询转移");if(!e)throw new Error("当前未处于咨询中");Mi.__internalSend({type:rt.CONSULT_TRANSFER,data:{session_id:t}})}async destroyRtc(){await(this.#e?.destroy())}destroy(){this.destroyRtc(),clearInterval(this.#s),qi.off("ws-message",this.#a),Mi.__internalClose(),this.offAll(),this.#r?.(),this.#e=null,this.#t=null,this.#i=!1,console.log(1111)}async#n(){return this.#e?this.#e.getNetworkStats():{}}get call_api(){return this.#i?{answerCall:this.#m.bind(this),makeCall:this.#v.bind(this),cancelCall:this.#g.bind(this),hangup:this.#w.bind(this),sendDTMF:this.#l.bind(this),holdCall:this.#h.bind(this),unholdCall:this.#d.bind(this),consultCall:async e=>{try{await this.#f(e)}catch(e){throw console.warn(e),e}},consultTransfer:this.#T.bind(this),mute:this.#y.bind(this),unmute:this.#b.bind(this)}:{}}get agent_api(){return this.#i?{changeDevice:this.#t.changeDevice.bind(this.#t),changeState:this.#t.changeState.bind(this.#t),getIdleAgentList:e=>this.#t.getIdleAgentList(e),getAgentState:e=>this.#t.getAgentState(e)}:{}}}export{Fi as default};
|
|
@@ -808,4 +808,4 @@ const ai=e=>(t,s)=>{void 0!==s?s.addInitializer(()=>{customElements.define(e,t)}
|
|
|
808
808
|
`:""}
|
|
809
809
|
</div>
|
|
810
810
|
</my-popover>
|
|
811
|
-
`;gs(i,this.rttHTML)}}const Oi=new class{constructor(){this.events={}}on(e,t){this.events[e]=this.events[e]||[],this.events[e].push(t)}off(e,t){this.events[e]=(this.events[e]||[]).filter(e=>e!==t)}emit(e,...t){(this.events[e]||[]).forEach(e=>e(...t))}};class qi{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const e=await navigator.mediaDevices.enumerateDevices();if(e.some(e=>"audioinput"===e.kind&&""!==e.label))return console.log("已授权麦克风权限,无需再次获取"),null;const t=await navigator.mediaDevices.getUserMedia({audio:!0});return console.log("获取音频权限成功"),t}catch(e){return console.warn("获取音频权限失败:",e),null}}static show(e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(e,{body:t,tag:"xy-global-notification",renotify:!0});i.onclick=()=>{window.focus(),i.close(),s?.()},setTimeout(()=>i.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(e=>"audioinput"===e.kind&&""!==e.label)}catch(e){return console.warn("无法检查设备权限:",e),!1}}}let Li=null;class Ui{constructor(e){this.url=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Hi,this.initWebSocket()}static getInstance(e){if(!Li){if(!e)throw new Error("WebSocket 尚未初始化");Li=new Ui(e)}return Li}stateIdleChange(){const{state:e}=_s.stateObject;e!==et.IDLE&&this.apiClient.changeState({data:{state:et.IDLE,state_name:"空闲"}})}putAgentState(){_s.sessionId="";const{post_call_process_time:e}=_s.agentInfo,t=e||0;_s.autoStateTimer&&(clearTimeout(_s.autoStateTimer),_s.autoStateTimer=null),t>0?_s.autoStateTimer=setTimeout(()=>{_s.autoStateTimer=null,this.stateIdleChange()},t):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=e=>{const t=JSON.parse(e.data),{type:s,data:i,code:r,msg:n}=t;if(0!==s&&console.warn(s),s===rt.OUT_CALL&&0!==r&&(ct.emit(it.OUT_FAILED,n),this.stateIdleChange()),s===rt.AGENT_STATE){const{state:e,state_name:t}=i;_s.stateObject={state:e,state_name:t},"振铃中"===t&&Rs.updateDisplayText(ot.AGENT_RINGING),ct.emit(it.AGENT_STATE,{state:e,state_name:t})}s===rt.OUT_CALL_INCOMING_CALL&&(ct.emit(it.OUT_INCOMING_CALL,i),_s.sessionId=i.session_id,Rs.updateActionConfigs(bs)),s===rt.OUT_CALL_END&&(1===i.device_type?(this.putAgentState(),Rs.reset(),ct.emit(it.OUT_HANGUP,i)):2===i.device_type&&(Rs.get("direction")===tt.CONSULT?(Rs.reset(),ct.emit(it.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState()):Rs.get("isCalling")&&(Rs.updateDisplayText(ot.CALLING),ct.emit(it.OTHER_SIDE_CONSULT_HANGUP,i),Rs.updateActionConfigs(Ts)))),s===rt.OUT_CALL_RINGING&&(ct.emit(it.OUT_RINGING,i),Rs.updateDisplayText(ot.RINGING)),s===rt.OUT_CALL_ANSWER&&(ct.emit(it.OUT_OFF_ANSWER,i),Rs.updateOutCallIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_RINGING&&(ct.emit(it.CONSULT_RINGING,i),Rs.updateDisplayText(ot.AGENT_RINGING),Rs.updateActionConfigs([])),s===rt.CONSULT_ANSWER&&(ct.emit(it.CONSULT_OFF_HOOK,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CONSULTING),Rs.updateActionConfigs(Ss)),s===rt.CONSULT_FAIL&&(ct.emit(it.CONSULT_FAILED),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_CALL_IN&&(ct.emit(it.CONSULT_INCOMING,i),Rs.updateIsCalling(!0),Rs.updateDirection(tt.CONSULT),Rs.updateDisplayText(ot.CONSULT_CALL_IN),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&qi.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{agent_mane:i.agent_name})})),s===rt.CONSULT_CALL_IN_SUCCESS&&(_s.sessionId=i.session_id,ct.emit(it.CONSULT_CALL_IN_SUCCESS,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Cs)),s===rt.MUTE&&(0===r?(Rs.updateIsMuted(!0),ct.emit(it.MUTE_SUCCESS)):ct.emit(it.MUTE_FAILED,n)),s===rt.UNMUTE&&(0===r?(Rs.updateIsMuted(!1),ct.emit(it.UNMUTE_SUCCESS)):ct.emit(it.UNMUTE_FAILED,n)),s===rt.CONSULT_TRANSFER&&(0===r?ct.emit(it.CONSULT_TRANSFER_SUCCESS):ct.emit(it.CONSULT_TRANSFER_FAILED,n)),s===rt.CONSULT_TRANSFER_FAILED&&ct.emit(it.CONSULT_TRANSFER_FAILED,i.status),s===rt.CONSULT_TRANSFER_OFF_HOOK&&(Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.CALLING),ct.emit(it.CONSULT_TRANSFER_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateIncomingIsAnswer(!0),Rs.updateConsultIsAnswer(!1)),s===rt.INCOMING_CALL&&(_s.sessionId=i.session_id,Rs.updateIsCalling(!0),Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.INCOMING_CALL),ct.emit(it.INCOMING_CALL,{customer_phone:i.customer_phone}),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&qi.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})})),s===rt.INCOMING_CALL_OFF_HOOK&&(Rs.updateIncomingIsAnswer(!0),ct.emit(it.INCOMING_CALL_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateDisplayText(ot.CALLING)),s===rt.INCOMING_CALL_END&&1===i.device_type&&(ct.emit(it.INCOMING_CALL_END),Rs.reset(),Rs.updateActionConfigs(ws),this.putAgentState()),0!==s&&Oi.emit("ws-message",t)},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{this.ws?.close()}}startHeartbeat(){const e=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 14000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),t=URL.createObjectURL(e);this.heartbeatWorker=new Worker(t),this.heartbeatWorker.onmessage=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(e){this.ws?.readyState===WebSocket.OPEN?this.ws.send(JSON.stringify(e)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Li&&(Li.close(),Li=null)}static __internalSend(e){if(!Li)throw new Error("WebSocket 尚未初始化");Li.sendMessage(e)}}return class{#e=null;#t=new Hi;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const e=await this.#n();Ei.updateRttObject(e)},2e3),qi.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=Rs.subscribeKey("answerDevice",e=>{1===e&&this.initWebRtc()})}async initWebRtc(){const e=_s.agentInfo.sip_account_list.find(e=>1===e.device_type);if(e){const t=e.sip_register_addr;this.#e=new Ai({server:t.split(":")[0],user:e.sip_account,password:e.sip_password,webSocket:`wss://${t}`,callTimeout:3e4},this.#o),await this.#e.start()}}async init({actionNodeParams:e,url:t,appKey:s,appSecret:i,agentNo:r,enableBrowserAlert:n}){try{const{viewHtmlElement:o,rttHTML:a}=e;bi=t||"https://aicc-api.yescloudy.com",Ti=s,Si=i;const c=ni(s,i);await this.#t._agentLogin(r);const{agent_no:h,current_answer_device:d,init_state:l}=_s.agentInfo;l===et.IDLE?(Rs.updateActionConfigs(ws),_s.stateObject={state:l,state_name:"空闲"}):l===et.BUSY&&(Rs.updateActionConfigs(ys),_s.stateObject={state:l,state_name:"忙碌"}),Ui.getInstance(`ws://112.90.183.54:8719/api/v1/ws/call/${h}?Authorization=${c}`),Rs.updateAnswerDevice(d),1===d&&await this.initWebRtc(),e&&o&&(this.#i=!0,new Pi({container:o,rttHTML:a,statusParams:{state:et.IDLE,statusName:"空闲"}},this)),_s.enableBrowserAlert=n,n&&qi.requestPermission()}catch(e){this.#i&&mi("初始化失败"),console.log(e)}}#o=e=>{const{type:t,data:s}=e;ct.emit(t,s)};#a=e=>{};on(e,t){return ct.on(e,t),this}off(e,t){ct.off(e,t)}offAll(){ct.clearAllListeners()}#c(){if(!this.#e)throw new Error("请先初始化SDK");const e=Rs.get("isCalling"),t=_s.sessionId;if(!e)throw new Error("当前没有通话");if(!t)throw new Error("sessionId不存在")}#h(){const e=Rs.get("isHold"),{sessionId:t}=_s;if(t){if(e)throw new Error("当前已处于保持状态");Ui.__internalSend({type:rt.CALL_HOLD,data:{session_id:t}}),Rs.updateDisplayText(ot.HOLD),Rs.updateIsHold(!0)}}#d(){const{isHold:e}=Rs.getState(),{sessionId:t}=_s;if(t){if(!e)throw new Error("当前未处于保持状态");Ui.__internalSend({type:rt.CALL_UNHOLD,data:{session_id:t}}),Rs.updateDisplayText(""),Rs.updateIsHold(!1)}}#l(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t}=Rs.getState();if(!t)throw new Error("当前没有通话");this.#e.sendDTMF(e)}#u(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e,direction:t,outCallIsAnswer:s}=Rs.getState();if(!e)throw new Error("当前没有通话");s||(t===tt.INCOMING?this.#g():t===tt.OUTGOING&&this.#p())}async#f(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:r}=Rs.getState(),n=_s.sessionId;if(i)throw new Error("当前正在咨询");if(!(t||s||r))throw new Error("当前没有通话");if(!n)throw new Error("sessionId不存在");Ui.__internalSend({type:rt.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:e}})}async#m(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");await this.#e.answerCall()}async#g(){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e}=Rs.getState();if(!e)throw new Error("当前没有通话");await this.#e.rejectInCall()}async#v(e){if(!this.#e)throw new Error("请先初始化SDK");if(Rs.getState().isCalling)throw new Error("正在呼叫中,请勿重复点击");Rs.updateIsCalling(!0),Rs.updateDirection(tt.OUTGOING),Ui.__internalSend({type:rt.OUT_CALL,data:{customer_phone:e}})}async#p(){const{isCalling:e}=Rs.getState();if(!this.#e)throw new Error("请先初始化SDK");if(!e)throw new Error("当前没有通话");await this.#e.rejectOutCall()}async#w(){if(!this.#e)throw new Error("请先初始化SDK");if(!Rs.get("isCalling"))throw new Error("当前没有通话");await this.#e.hangup()}#y(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(t)throw new Error("当前未处于静音状态");if(!e.includes("mute"))throw new Error("当前状态请勿调用静音");Ui.__internalSend({type:rt.MUTE,data:{session_id:s}})}#b(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(!t)throw new Error("当前未处于未静音状态");if(!e.includes("unmute"))throw new Error("当前状态请勿调用静音");Ui.__internalSend({type:rt.UNMUTE,data:{session_id:s}})}#T(){this.#c();const e=Rs.get("consultIsAnswer"),t=_s.sessionId;if(!Rs.get("actionConfigs").includes("consult_transfer"))throw new Error("当前状态请勿调用咨询转移");if(!e)throw new Error("当前未处于咨询中");Ui.__internalSend({type:rt.CONSULT_TRANSFER,data:{session_id:t}})}async destroyRtc(){await(this.#e?.destroy())}destroy(){this.destroyRtc(),clearInterval(this.#s),Oi.off("ws-message",this.#a),Ui.__internalClose(),this.offAll(),this.#r?.()}async#n(){return this.#e?this.#e.getNetworkStats():{}}get call_api(){return this.#i?{answerCall:this.#m.bind(this),makeCall:this.#v.bind(this),cancelCall:this.#u.bind(this),hangup:this.#w.bind(this),sendDTMF:this.#l.bind(this),holdCall:this.#h.bind(this),unholdCall:this.#d.bind(this),consultCall:async e=>{try{await this.#f(e)}catch(e){throw console.warn(e),e}},consultTransfer:this.#T.bind(this),mute:this.#y.bind(this),unmute:this.#b.bind(this)}:{}}get agent_api(){return this.#i?{changeDevice:this.#t.changeDevice.bind(this.#t),changeState:this.#t.changeState.bind(this.#t),getIdleAgentList:e=>this.#t.getIdleAgentList(e),getAgentState:e=>this.#t.getAgentState(e)}:{}}}});
|
|
811
|
+
`;gs(i,this.rttHTML)}}const Oi=new class{constructor(){this.events={}}on(e,t){this.events[e]=this.events[e]||[],this.events[e].push(t)}off(e,t){this.events[e]=(this.events[e]||[]).filter(e=>e!==t)}emit(e,...t){(this.events[e]||[]).forEach(e=>e(...t))}};class qi{static requestPermission(){"Notification"in window&&"default"===Notification.permission&&Notification.requestPermission()}static async requestMediaPermissions(){try{const e=await navigator.mediaDevices.enumerateDevices();if(e.some(e=>"audioinput"===e.kind&&""!==e.label))return console.log("已授权麦克风权限,无需再次获取"),null;const t=await navigator.mediaDevices.getUserMedia({audio:!0});return console.log("获取音频权限成功"),t}catch(e){return console.warn("获取音频权限失败:",e),null}}static show(e,t,s){if("Notification"in window&&"granted"===Notification.permission){const i=new Notification(e,{body:t,tag:"xy-global-notification",renotify:!0});i.onclick=()=>{window.focus(),i.close(),s?.()},setTimeout(()=>i.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(e=>"audioinput"===e.kind&&""!==e.label)}catch(e){return console.warn("无法检查设备权限:",e),!1}}}let Li=null;class Ui{constructor(e){this.url=e,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Hi,this.initWebSocket()}static getInstance(e){if(!Li){if(!e)throw new Error("WebSocket 尚未初始化");Li=new Ui(e)}return Li}stateIdleChange(){const{state:e}=_s.stateObject;e!==et.IDLE&&this.apiClient.changeState({data:{state:et.IDLE,state_name:"空闲"}})}putAgentState(){_s.sessionId="";const{post_call_process_time:e}=_s.agentInfo,t=e||0;_s.autoStateTimer&&(clearTimeout(_s.autoStateTimer),_s.autoStateTimer=null),t>0?_s.autoStateTimer=setTimeout(()=>{_s.autoStateTimer=null,this.stateIdleChange()},t):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=e=>{const t=JSON.parse(e.data),{type:s,data:i,code:r,msg:n}=t;if(0!==s&&console.warn(s),s===rt.OUT_CALL&&0!==r&&(ct.emit(it.OUT_FAILED,n),this.stateIdleChange()),s===rt.AGENT_STATE){const{state:e,state_name:t}=i;_s.stateObject={state:e,state_name:t},"振铃中"===t&&Rs.updateDisplayText(ot.AGENT_RINGING),ct.emit(it.AGENT_STATE,{state:e,state_name:t})}s===rt.OUT_CALL_INCOMING_CALL&&(ct.emit(it.OUT_INCOMING_CALL,i),_s.sessionId=i.session_id,Rs.updateActionConfigs(bs)),s===rt.OUT_CALL_END&&(1===i.device_type?(this.putAgentState(),Rs.reset(),ct.emit(it.OUT_HANGUP,i)):2===i.device_type&&(Rs.get("direction")===tt.CONSULT?(Rs.reset(),ct.emit(it.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState()):Rs.get("isCalling")&&(Rs.updateDisplayText(ot.CALLING),ct.emit(it.OTHER_SIDE_CONSULT_HANGUP,i),Rs.updateActionConfigs(Ts)))),s===rt.OUT_CALL_RINGING&&(ct.emit(it.OUT_RINGING,i),Rs.updateDisplayText(ot.RINGING)),s===rt.OUT_CALL_ANSWER&&(ct.emit(it.OUT_OFF_ANSWER,i),Rs.updateOutCallIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_RINGING&&(ct.emit(it.CONSULT_RINGING,i),Rs.updateDisplayText(ot.AGENT_RINGING),Rs.updateActionConfigs([])),s===rt.CONSULT_ANSWER&&(ct.emit(it.CONSULT_OFF_HOOK,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CONSULTING),Rs.updateActionConfigs(Ss)),s===rt.CONSULT_FAIL&&(ct.emit(it.CONSULT_FAILED),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Ts)),s===rt.CONSULT_CALL_IN&&(ct.emit(it.CONSULT_INCOMING,i),Rs.updateIsCalling(!0),Rs.updateDirection(tt.CONSULT),Rs.updateDisplayText(ot.CONSULT_CALL_IN),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&qi.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{agent_mane:i.agent_name})})),s===rt.CONSULT_CALL_IN_SUCCESS&&(_s.sessionId=i.session_id,ct.emit(it.CONSULT_CALL_IN_SUCCESS,i),Rs.updateConsultIsAnswer(!0),Rs.updateDisplayText(ot.CALLING),Rs.updateActionConfigs(Cs)),s===rt.MUTE&&(0===r?(Rs.updateIsMuted(!0),ct.emit(it.MUTE_SUCCESS)):ct.emit(it.MUTE_FAILED,n)),s===rt.UNMUTE&&(0===r?(Rs.updateIsMuted(!1),ct.emit(it.UNMUTE_SUCCESS)):ct.emit(it.UNMUTE_FAILED,n)),s===rt.CONSULT_TRANSFER&&(0===r?ct.emit(it.CONSULT_TRANSFER_SUCCESS):ct.emit(it.CONSULT_TRANSFER_FAILED,n)),s===rt.CONSULT_TRANSFER_FAILED&&ct.emit(it.CONSULT_TRANSFER_FAILED,i.status),s===rt.CONSULT_TRANSFER_OFF_HOOK&&(Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.CALLING),ct.emit(it.CONSULT_TRANSFER_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateIncomingIsAnswer(!0),Rs.updateConsultIsAnswer(!1)),s===rt.INCOMING_CALL&&(_s.sessionId=i.session_id,Rs.updateIsCalling(!0),Rs.updateDirection(tt.INCOMING),Rs.updateDisplayText(ot.INCOMING_CALL),ct.emit(it.INCOMING_CALL,{customer_phone:i.customer_phone}),Rs.updateActionConfigs(Es),_s.enableBrowserAlert&&qi.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{ct.emit(nt.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})})),s===rt.INCOMING_CALL_OFF_HOOK&&(Rs.updateIncomingIsAnswer(!0),ct.emit(it.INCOMING_CALL_OFF_HOOK),Rs.updateActionConfigs(As),Rs.updateDisplayText(ot.CALLING)),s===rt.INCOMING_CALL_END&&1===i.device_type&&(ct.emit(it.INCOMING_CALL_END),Rs.reset(),Rs.updateActionConfigs(ws),this.putAgentState()),0!==s&&Oi.emit("ws-message",t)},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{this.ws?.close()}}startHeartbeat(){const e=new Blob(["\n let timer;\n self.onmessage = function (e) {\n if (e.data === 'start') {\n timer = setInterval(() => {\n self.postMessage('heartbeat');\n }, 14000);\n } else if (e.data === 'stop') {\n clearInterval(timer);\n }\n };\n "],{type:"application/javascript"}),t=URL.createObjectURL(e);this.heartbeatWorker=new Worker(t),this.heartbeatWorker.onmessage=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(e){this.ws?.readyState===WebSocket.OPEN?this.ws.send(JSON.stringify(e)):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Li&&(Li.close(),Li=null)}static __internalSend(e){if(!Li)throw new Error("WebSocket 尚未初始化");Li.sendMessage(e)}}return class{#e=null;#t=new Hi;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const e=await this.#n();Ei.updateRttObject(e)},2e3),qi.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=Rs.subscribeKey("answerDevice",e=>{1===e&&this.initWebRtc()})}async initWebRtc(){const e=_s.agentInfo.sip_account_list.find(e=>1===e.device_type);if(e){const t=e.sip_register_addr;this.#e=new Ai({server:t.split(":")[0],user:e.sip_account,password:e.sip_password,webSocket:`wss://${t}`,callTimeout:3e4},this.#o),await this.#e.start()}}async init({actionNodeParams:e,url:t,appKey:s,appSecret:i,agentNo:r,enableBrowserAlert:n}){try{const{viewHtmlElement:o,rttHTML:a}=e;bi=t||"https://aicc-api.yescloudy.com",Ti=s,Si=i;const c=ni(s,i);await this.#t._agentLogin(r);const{agent_no:h,current_answer_device:d,init_state:l}=_s.agentInfo;l===et.IDLE?(Rs.updateActionConfigs(ws),_s.stateObject={state:l,state_name:"空闲"}):l===et.BUSY&&(Rs.updateActionConfigs(ys),_s.stateObject={state:l,state_name:"忙碌"}),Ui.getInstance(`ws://112.90.183.54:8719/api/v1/ws/call/${h}?Authorization=${c}`),Rs.updateAnswerDevice(d),1===d&&await this.initWebRtc(),e&&o&&(this.#i=!0,new Pi({container:o,rttHTML:a,statusParams:{state:et.IDLE,statusName:"空闲"}},this)),_s.enableBrowserAlert=n,n&&qi.requestPermission()}catch(e){this.#i&&mi("初始化失败"),console.log(e)}}#o=e=>{const{type:t,data:s}=e;ct.emit(t,s)};#a=e=>{};on(e,t){return ct.on(e,t),this}off(e,t){ct.off(e,t)}offAll(){ct.clearAllListeners()}#c(){if(!this.#e)throw new Error("请先初始化SDK");const e=Rs.get("isCalling"),t=_s.sessionId;if(!e)throw new Error("当前没有通话");if(!t)throw new Error("sessionId不存在")}#h(){const e=Rs.get("isHold"),{sessionId:t}=_s;if(t){if(e)throw new Error("当前已处于保持状态");Ui.__internalSend({type:rt.CALL_HOLD,data:{session_id:t}}),Rs.updateDisplayText(ot.HOLD),Rs.updateIsHold(!0)}}#d(){const{isHold:e}=Rs.getState(),{sessionId:t}=_s;if(t){if(!e)throw new Error("当前未处于保持状态");Ui.__internalSend({type:rt.CALL_UNHOLD,data:{session_id:t}}),Rs.updateDisplayText(""),Rs.updateIsHold(!1)}}#l(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t}=Rs.getState();if(!t)throw new Error("当前没有通话");this.#e.sendDTMF(e)}#u(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e,direction:t,outCallIsAnswer:s}=Rs.getState();if(!e)throw new Error("当前没有通话");s||(t===tt.INCOMING?this.#g():t===tt.OUTGOING&&this.#p())}async#f(e){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:r}=Rs.getState(),n=_s.sessionId;if(i)throw new Error("当前正在咨询");if(!(t||s||r))throw new Error("当前没有通话");if(!n)throw new Error("sessionId不存在");Ui.__internalSend({type:rt.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:e}})}async#m(){if(1!==Rs.get("answerDevice"))throw new Error("当前设备不支持此功能");if(!this.#e)throw new Error("请先初始化SDK");await this.#e.answerCall()}async#g(){if(!this.#e)throw new Error("请先初始化SDK");const{isCalling:e}=Rs.getState();if(!e)throw new Error("当前没有通话");await this.#e.rejectInCall()}async#v(e){if(!this.#e)throw new Error("请先初始化SDK");if(Rs.getState().isCalling)throw new Error("正在呼叫中,请勿重复点击");Rs.updateIsCalling(!0),Rs.updateDirection(tt.OUTGOING),Ui.__internalSend({type:rt.OUT_CALL,data:{customer_phone:e}})}async#p(){const{isCalling:e}=Rs.getState();if(!this.#e)throw new Error("请先初始化SDK");if(!e)throw new Error("当前没有通话");await this.#e.rejectOutCall()}async#w(){if(!this.#e)throw new Error("请先初始化SDK");if(!Rs.get("isCalling"))throw new Error("当前没有通话");await this.#e.hangup()}#y(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(t)throw new Error("当前未处于静音状态");if(!e.includes("mute"))throw new Error("当前状态请勿调用静音");Ui.__internalSend({type:rt.MUTE,data:{session_id:s}})}#b(){this.#c();const e=Rs.get("actionConfigs"),t=Rs.get("isMuted"),s=_s.sessionId;if(!t)throw new Error("当前未处于未静音状态");if(!e.includes("unmute"))throw new Error("当前状态请勿调用静音");Ui.__internalSend({type:rt.UNMUTE,data:{session_id:s}})}#T(){this.#c();const e=Rs.get("consultIsAnswer"),t=_s.sessionId;if(!Rs.get("actionConfigs").includes("consult_transfer"))throw new Error("当前状态请勿调用咨询转移");if(!e)throw new Error("当前未处于咨询中");Ui.__internalSend({type:rt.CONSULT_TRANSFER,data:{session_id:t}})}async destroyRtc(){await(this.#e?.destroy())}destroy(){this.destroyRtc(),clearInterval(this.#s),Oi.off("ws-message",this.#a),Ui.__internalClose(),this.offAll(),this.#r?.(),this.#e=null,this.#t=null,this.#i=!1,console.log(1111)}async#n(){return this.#e?this.#e.getNetworkStats():{}}get call_api(){return this.#i?{answerCall:this.#m.bind(this),makeCall:this.#v.bind(this),cancelCall:this.#u.bind(this),hangup:this.#w.bind(this),sendDTMF:this.#l.bind(this),holdCall:this.#h.bind(this),unholdCall:this.#d.bind(this),consultCall:async e=>{try{await this.#f(e)}catch(e){throw console.warn(e),e}},consultTransfer:this.#T.bind(this),mute:this.#y.bind(this),unmute:this.#b.bind(this)}:{}}get agent_api(){return this.#i?{changeDevice:this.#t.changeDevice.bind(this.#t),changeState:this.#t.changeState.bind(this.#t),getIdleAgentList:e=>this.#t.getIdleAgentList(e),getAgentState:e=>this.#t.getAgentState(e)}:{}}}});
|