ysyt-agent-sdk 1.0.70 → 1.0.71
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.
package/dist/src/index.d.ts
CHANGED
|
@@ -48,6 +48,9 @@ declare class YSYTAgentSdk {
|
|
|
48
48
|
}>) => Promise<void>;
|
|
49
49
|
getIdleAgentList: (params: RequestBodyType<unknown, AgentItemType[]>) => Promise<void>;
|
|
50
50
|
getAgentState: (params: RequestBodyType<unknown, AgentStateDataType>) => Promise<void>;
|
|
51
|
+
setAgentExplicit: (params: RequestBodyType<{
|
|
52
|
+
number: string;
|
|
53
|
+
}>) => Promise<void>;
|
|
51
54
|
};
|
|
52
55
|
getAgentData(): AgentDataType;
|
|
53
56
|
}
|
|
@@ -920,4 +920,4 @@ const ms=A=>(e,t)=>{void 0!==t?t.addInitializer(()=>{customElements.define(A,e)}
|
|
|
920
920
|
`:""}
|
|
921
921
|
</div>
|
|
922
922
|
</my-popover>
|
|
923
|
-
`;ss(s,this.rttHTML)}}class vs{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){if("Notification"in window&&"granted"===Notification.permission){const s=new Notification(A,{body:e,tag:"xy-global-notification",renotify:!0});s.onclick=()=>{window.focus(),s.close(),t?.()},setTimeout(()=>s.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}let Ks=null;class Os{constructor(A){this.url=A,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Us,this.initWebSocket()}static getInstance(A){if(!Ks){if(!A)throw new Error("WebSocket 尚未初始化");Ks=new Os(A)}return Ks}stateIdleChange(){const{state:A}=Ve.stateObject;A!==exports.AgentStatus.IDLE&&this.apiClient._changeState({data:{...Ve.stateBeforeChange}})}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{const{contact_count:e,customer_name:t,phone:s,city:i,province:r}=A.data;ae.emit(exports.CallSipCallEvent.CUSTOMER_INFO,{customer_name:t||"未知客户",phone:s,city:i||"未知",province:r||"未知",contact_count:e||0})}})}catch(A){}}putAgentState(){Ve.sessionId="";const{post_call_process_time:A}=Ve.agentInfo,e=A||0;Ve.autoStateTimer&&(clearTimeout(Ve.autoStateTimer),Ve.autoStateTimer=null),ae.emit(exports.CallSipCallEvent.CUSTOMER_INFO,void 0),e>0?Ve.autoStateTimer=setTimeout(()=>{Ve.autoStateTimer=null,this.stateIdleChange()},e):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=A=>{const e=JSON.parse(A.data),{type:t,data:s,code:i,msg:r}=e;if(t===exports.WebsocketTypeEnum.OUT_CALL&&(0!==i?(he.reset(),ae.emit(exports.CallSipCallEvent.OUT_FAILED,r),setTimeout(()=>{ae.emit(exports.CallSipCallEvent.CUSTOMER_INFO,void 0)},500),this.stateIdleChange()):0===i&&ae.emit(exports.CallSipCallEvent.OUT_SUCCESS)),t===exports.WebsocketTypeEnum.AGENT_STATE){Ve.stateObject.state!==exports.AgentStatus.IDLE&&Ve.stateObject.state!==exports.AgentStatus.BUSY||(Ve.stateBeforeChange=Ve.stateObject);const{state:A,state_name:e}=s;Ve.stateObject={state:A,state_name:e},"振铃中"===e&&he.updateDisplayText(exports.DisplayTextEnum.AGENT_RINGING),ae.emit(exports.CallSipCallEvent.AGENT_STATE,{state:A,state_name:e})}if(t===exports.WebsocketTypeEnum.OUT_CALL_INCOMING_CALL&&(ae.emit(exports.CallSipCallEvent.OUT_INCOMING_CALL),Ve.sessionId=s.session_id,he.updateActionConfigs(cs)),t===exports.WebsocketTypeEnum.OUT_CALL_END&&(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.OUT_HANGUP,s),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(he.reset(),ae.emit(exports.CallSipCallEvent.OUR_SIDE_CONSULT_HANGUP,s),this.putAgentState(),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no?(he.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)):3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.THREE_WAY_OUR_SIDE_HANGUP),he.updateActionConfigs(as)):4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.TRANSFER_END),he.updateActionConfigs(as))),t===exports.WebsocketTypeEnum.OUT_CALL_RINGING&&1===s.type&&(ae.emit(exports.CallSipCallEvent.OUT_RINGING,s),he.updateDisplayText(exports.DisplayTextEnum.RINGING)),t===exports.WebsocketTypeEnum.OUT_CALL_ANSWER&&(ae.emit(exports.CallSipCallEvent.OUT_OFF_ANSWER,s),he.updateOutCallIsAnswer(!0),he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateActionConfigs(hs)),t===exports.WebsocketTypeEnum.CONSULT_RINGING&&(ae.emit(exports.CallSipCallEvent.CONSULT_RINGING),he.updateDisplayText(exports.DisplayTextEnum.AGENT_RINGING),he.updateActionConfigs([])),t===exports.WebsocketTypeEnum.CONSULT_ANSWER&&(ae.emit(exports.CallSipCallEvent.CONSULT_OFF_HOOK,s),he.updateConsultIsAnswer(!0),he.updateDisplayText(exports.DisplayTextEnum.CONSULTING),he.updateActionConfigs(ls)),t===exports.WebsocketTypeEnum.CONSULT_FAIL&&(ae.emit(exports.CallSipCallEvent.CONSULT_FAILED,{custom_reason:s.custom_reason}),he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateActionConfigs(hs)),t===exports.WebsocketTypeEnum.CONSULT_CALL_IN&&(ae.emit(exports.CallSipCallEvent.CONSULT_INCOMING,s),he.updateIsCalling(!0),he.updateDirection(exports.DirectionEnum.CONSULT),he.updateDisplayText(exports.DisplayTextEnum.CONSULT_CALL_IN),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&vs.show("📞 咨询来电",`坐席 [${s.agent_name}] 正在咨询...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{agent_mane:s.agent_name})})),t===exports.WebsocketTypeEnum.CONSULT_CALL_IN_SUCCESS&&(Ve.sessionId=s.session_id,ae.emit(exports.CallSipCallEvent.CONSULT_CALL_IN_SUCCESS),he.updateConsultIsAnswer(!0),he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateActionConfigs(gs)),t===exports.WebsocketTypeEnum.CONSULT_RETURN_CALL_SUCCESS&&(ae.emit(exports.CallSipCallEvent.CONSULT_RETURN_CALL_SUCCESS),he.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)),t===exports.WebsocketTypeEnum.MUTE&&(0===i?(he.updateIsMuted(!0),ae.emit(exports.CallSipCallEvent.MUTE_SUCCESS),he.updateDisplayText(exports.DisplayTextEnum.MUTING)):ae.emit(exports.CallSipCallEvent.MUTE_FAILED,r)),t===exports.WebsocketTypeEnum.UNMUTE&&(0===i?(he.updateIsMuted(!1),ae.emit(exports.CallSipCallEvent.UNMUTE_SUCCESS),he.updateDisplayText(exports.DisplayTextEnum.CALLING)):ae.emit(exports.CallSipCallEvent.UNMUTE_FAILED,r)),t===exports.WebsocketTypeEnum.CALL_HOLD&&(0===i?(he.updateIsHold(!0),he.updateDisplayText(exports.DisplayTextEnum.HOLDING),ae.emit(exports.CallSipCallEvent.HOLD_SUCCESS)):ae.emit(exports.CallSipCallEvent.HOLD_FAILED,r)),t===exports.WebsocketTypeEnum.CALL_UNHOLD&&(0===i?(he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateIsHold(!1),ae.emit(exports.CallSipCallEvent.UNHOLD_SUCCESS)):ae.emit(exports.CallSipCallEvent.UNHOLD_FAILED,r)),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER&&(0===i?ae.emit(exports.CallSipCallEvent.CONSULT_TRANSFER_SUCCESS):ae.emit(exports.CallSipCallEvent.CONSULT_TRANSFER_FAILED,r)),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER_FAILED&&ae.emit(exports.CallSipCallEvent.CONSULT_TRANSFER_FAILED,s.status),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER_OFF_HOOK&&(he.updateDirection(exports.DirectionEnum.INCOMING),he.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEvent.CONSULT_TRANSFER_OFF_HOOK),he.updateActionConfigs(ps),he.updateIncomingIsAnswer(!0),he.updateConsultIsAnswer(!1)),t===exports.WebsocketTypeEnum.INCOMING_CALL&&(Ve.sessionId=s.session_id,he.updateIsCalling(!0),he.updateDirection(exports.DirectionEnum.INCOMING),he.updateDisplayText(exports.DisplayTextEnum.INCOMING_CALL),ae.emit(exports.CallSipCallEvent.INCOMING_CALL,{customer_phone:s.customer_phone}),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&vs.show("📞 客户来电",`客户 [${s.customer_phone}] 正在呼入...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})})),t===exports.WebsocketTypeEnum.INCOMING_CALL_OFF_HOOK&&(he.updateIncomingIsAnswer(!0),ae.emit(exports.CallSipCallEvent.INCOMING_CALL_OFF_HOOK),he.updateActionConfigs(ps),he.updateDisplayText(exports.DisplayTextEnum.CALLING)),t===exports.WebsocketTypeEnum.INCOMING_CALL_END&&(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.INCOMING_CALL_END),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(he.reset(),ae.emit(exports.CallSipCallEvent.OUR_SIDE_CONSULT_HANGUP,s),this.putAgentState(),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no?(he.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)):3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.THREE_WAY_OUR_SIDE_HANGUP),he.updateActionConfigs(as)):4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.TRANSFER_END),he.updateActionConfigs(as))),t===exports.WebsocketTypeEnum.SATISFACTION_EVALUATION&&(0===i?ae.emit(exports.CallSipCallEvent.SATISFACTION_EVALUATION_SUCCESS):ae.emit(exports.CallSipCallEvent.SATISFACTION_EVALUATION_FAILED,r)),t===exports.WebsocketTypeEnum.CONSULT_THREE_WAY&&(0!==i?ae.emit(exports.CallSipCallEvent.CONSULT_THREE_WAY_FAILED,r):0===i&&he.updateIsMeeting(!0)),t===exports.WebsocketTypeEnum.CONSULT_THREE_WAY_RESULT&&("success"===s.status?(he.updateDirection(exports.DirectionEnum.MEETING),he.updateDisplayText(exports.DisplayTextEnum.MEETING),he.updateActionConfigs(qs),ae.emit(exports.CallSipCallEvent.CONSULT_THREE_WAY_SUCCESS)):(ae.emit(exports.CallSipCallEvent.CONSULT_THREE_WAY_FAILED,{conf_name:s.conf_name}),he.updateIsMeeting(!1))),t===exports.WebsocketTypeEnum.TRANSFER_INCOMING_CALL&&(s.agent_no===Ve.agentInfo.agent_no?(he.updateDisplayText(exports.DisplayTextEnum.TRANSFERRING),ae.emit(exports.CallSipCallEvent.TRANSFER_PROGRESS),he.updateActionConfigs([]),he.updateTransferIsAnswer(!0)):(ae.emit(exports.CallSipCallEvent.TRANSFER_INCOMING_CALL,s),he.updateIsCalling(!0),he.updateDirection(exports.DirectionEnum.TRANSFER),he.updateDisplayText(exports.DisplayTextEnum.TRANSFER_INCOMING_CALL),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&vs.show("📞 转接来电",`坐席 [${s.agent_no}] 正在转接...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{agent_mane:s.agent_no})}))),t===exports.WebsocketTypeEnum.TRANSFER_OFF_HOOK&&(Ve.sessionId=s.session_id,ae.emit(exports.CallSipCallEvent.TRANSFER_OFF_HOOK),he.updateTransferIsAnswer(!0),he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateActionConfigs(ps)),t===exports.WebsocketTypeEnum.TRANSFER_FAILED&&"failed"===s.status){ae.emit(exports.CallSipCallEvent.TRANSFER_FAILED,"未知原因");const A=he.get("direction");A===exports.DirectionEnum.OUTGOING?he.updateActionConfigs(hs):A===exports.DirectionEnum.INCOMING&&he.updateActionConfigs(ps)}},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{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 }, 14000);\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=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(100===A.type&&this.getCustomerInfo(A.data.customer_phone),this.ws.send(JSON.stringify(A))):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Ks&&(Ks.close(),Ks=null)}static __internalSend(A){if(!Ks)throw new Error("WebSocket 尚未初始化");Ks.sendMessage(A)}}class Ns{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:"当前已处于保持状态"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前未处于保持状态"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!he.get("actionConfigs").includes("reject"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用拒接"}));const{isCalling:A,direction:e,outCallIsAnswer:t}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));t||(e===exports.DirectionEnum.INCOMING?this.rejectInCall():e===exports.DirectionEnum.OUTGOING&&this.rejectOutCall())}async consultCall(A){this.roleMute();const{isCalling:e,outCallIsAnswer:t,consultIsAnswer:s,incomingIsAnswer:i}=he.getState(),r=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(!r)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));Os.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_REQUEST,data:{session_id:r,consultation_agent_no:A}})}async answerCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}async rejectInCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));const{isCalling:A}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));await this.sipClient.rejectInCall()}async makeCall(A){const e=he.get("isCalling"),t=he.get("selectOutNumber")||"";if(e)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));he.updateIsCalling(!0),he.updateDirection(exports.DirectionEnum.OUTGOING),Os.__internalSend({type:exports.WebsocketTypeEnum.OUT_CALL,data:{customer_phone:A,caller:t}})}async rejectOutCall(){const{isCalling:A}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=Ve.sessionId;Os.__internalSend({type:exports.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:e}})}async hangup(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前状态请勿调用静音"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前状态请勿调用静音"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前未处于咨询中"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前状态请勿调用满意度评价"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前未处于咨询中"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前未处于咨询中"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前正在转接"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前正在转接"}));Os.__internalSend({type:exports.WebsocketTypeEnum.TRANSFER,data:{session_id:t,transfer_type:2,transfer_dest:A}})}}exports.default=class{#A=null;#e=new Us;#t;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#o();Xe.updateRttObject(A)},2e3),vs.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=he.subscribeKey("answerDevice",A=>{1===A?this.initWebRtc():this.#A=null})}async initWebRtc(){if(this.#A)return;const A=Ve.agentInfo.sip_account_list.find(A=>1===A.device_type);if(A){const e=A.sip_register_addr;this.#A=new _e({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#n),await this.#A.start()}}async init({actionNodeParams:A,url:e,appKey:t,appSecret:s,agentNo:i,enableBrowserAlert:r}){try{const{viewHtmlElement:o,rttHTML:n}=A||{},a=e||"https://aicc.yescloudy.com";je=a,Le=t,We=s;const V=be(t,s);await this.#e._agentLogin(i);const{agent_no:c,current_answer_device:h,init_state:l,out_display_number:g}=Ve.agentInfo;l===exports.AgentStatus.IDLE?(he.updateActionConfigs(as),Ve.stateObject={state:l,state_name:"空闲"}):l===exports.AgentStatus.BUSY&&(he.updateActionConfigs(Vs),Ve.stateObject={state:l,state_name:"忙碌"}),he.updateSelectOutNumber(g);let q="";const d=new URL(a).host;q=a.includes("https")?`wss://${d}`:`ws://${d}`,Os.getInstance(`${q}/ccs-ws/api/v1/ws/call/${c}?Authorization=${V}`),he.updateAnswerDevice(h),1===h&&await this.initWebRtc(),this.#t=new Ns(this.#A),A&&o&&(this.#i=!0,new Zs({container:o,rttHTML:n,statusParams:{state:exports.AgentStatus.IDLE,statusName:"空闲"}},this,this.#t)),Ve.enableBrowserAlert=r,r&&vs.requestPermission(),ae.emit(exports.EventName.AGENT_INIT_STATUS,!0)}catch(A){this.#i&&Fs("初始化失败")}}#n=A=>{const{type:e,data:t}=A;ae.emit(e,t)};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())}destroy(){this.destroyRtc(),clearInterval(this.#s),Os.__internalClose(),this.offAll(),this.#r?.(),this.#A=null,this.#e=null,this.#i=!1}async#o(){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),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))}}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))}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:o}=Ve.agentInfo,{stateObject:n}=Ve,a={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:o,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:a[Number(A)]})),stateObject:n}}};
|
|
923
|
+
`;ss(s,this.rttHTML)}}class vs{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){if("Notification"in window&&"granted"===Notification.permission){const s=new Notification(A,{body:e,tag:"xy-global-notification",renotify:!0});s.onclick=()=>{window.focus(),s.close(),t?.()},setTimeout(()=>s.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}let Ks=null;class Os{constructor(A){this.url=A,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Us,this.initWebSocket()}static getInstance(A){if(!Ks){if(!A)throw new Error("WebSocket 尚未初始化");Ks=new Os(A)}return Ks}stateIdleChange(){const{state:A}=Ve.stateObject;A!==exports.AgentStatus.IDLE&&this.apiClient._changeState({data:{...Ve.stateBeforeChange}})}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{const{contact_count:e,customer_name:t,phone:s,city:i,province:r}=A.data;ae.emit(exports.CallSipCallEvent.CUSTOMER_INFO,{customer_name:t||"未知客户",phone:s,city:i||"未知",province:r||"未知",contact_count:e||0})}})}catch(A){}}putAgentState(){Ve.sessionId="";const{post_call_process_time:A}=Ve.agentInfo,e=A||0;Ve.autoStateTimer&&(clearTimeout(Ve.autoStateTimer),Ve.autoStateTimer=null),ae.emit(exports.CallSipCallEvent.CUSTOMER_INFO,void 0),e>0?Ve.autoStateTimer=setTimeout(()=>{Ve.autoStateTimer=null,this.stateIdleChange()},e):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=A=>{const e=JSON.parse(A.data),{type:t,data:s,code:i,msg:r}=e;if(t===exports.WebsocketTypeEnum.OUT_CALL&&(0!==i?(he.reset(),ae.emit(exports.CallSipCallEvent.OUT_FAILED,r),setTimeout(()=>{ae.emit(exports.CallSipCallEvent.CUSTOMER_INFO,void 0)},500),this.stateIdleChange()):0===i&&ae.emit(exports.CallSipCallEvent.OUT_SUCCESS)),t===exports.WebsocketTypeEnum.AGENT_STATE){Ve.stateObject.state!==exports.AgentStatus.IDLE&&Ve.stateObject.state!==exports.AgentStatus.BUSY||(Ve.stateBeforeChange=Ve.stateObject);const{state:A,state_name:e}=s;Ve.stateObject={state:A,state_name:e},"振铃中"===e&&he.updateDisplayText(exports.DisplayTextEnum.AGENT_RINGING),ae.emit(exports.CallSipCallEvent.AGENT_STATE,{state:A,state_name:e})}if(t===exports.WebsocketTypeEnum.OUT_CALL_INCOMING_CALL&&(ae.emit(exports.CallSipCallEvent.OUT_INCOMING_CALL),Ve.sessionId=s.session_id,he.updateActionConfigs(cs)),t===exports.WebsocketTypeEnum.OUT_CALL_END&&(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.OUT_HANGUP,s),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(he.reset(),ae.emit(exports.CallSipCallEvent.OUR_SIDE_CONSULT_HANGUP,s),this.putAgentState(),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no?(he.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)):3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.THREE_WAY_OUR_SIDE_HANGUP),he.updateActionConfigs(as)):4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.TRANSFER_END),he.updateActionConfigs(as))),t===exports.WebsocketTypeEnum.OUT_CALL_RINGING&&1===s.type&&(ae.emit(exports.CallSipCallEvent.OUT_RINGING,s),he.updateDisplayText(exports.DisplayTextEnum.RINGING)),t===exports.WebsocketTypeEnum.OUT_CALL_ANSWER&&(ae.emit(exports.CallSipCallEvent.OUT_OFF_ANSWER,s),he.updateOutCallIsAnswer(!0),he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateActionConfigs(hs)),t===exports.WebsocketTypeEnum.CONSULT_RINGING&&(ae.emit(exports.CallSipCallEvent.CONSULT_RINGING),he.updateDisplayText(exports.DisplayTextEnum.AGENT_RINGING),he.updateActionConfigs([])),t===exports.WebsocketTypeEnum.CONSULT_ANSWER&&(ae.emit(exports.CallSipCallEvent.CONSULT_OFF_HOOK,s),he.updateConsultIsAnswer(!0),he.updateDisplayText(exports.DisplayTextEnum.CONSULTING),he.updateActionConfigs(ls)),t===exports.WebsocketTypeEnum.CONSULT_FAIL&&(ae.emit(exports.CallSipCallEvent.CONSULT_FAILED,{custom_reason:s.custom_reason}),he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateActionConfigs(hs)),t===exports.WebsocketTypeEnum.CONSULT_CALL_IN&&(ae.emit(exports.CallSipCallEvent.CONSULT_INCOMING,s),he.updateIsCalling(!0),he.updateDirection(exports.DirectionEnum.CONSULT),he.updateDisplayText(exports.DisplayTextEnum.CONSULT_CALL_IN),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&vs.show("📞 咨询来电",`坐席 [${s.agent_name}] 正在咨询...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{agent_mane:s.agent_name})})),t===exports.WebsocketTypeEnum.CONSULT_CALL_IN_SUCCESS&&(Ve.sessionId=s.session_id,ae.emit(exports.CallSipCallEvent.CONSULT_CALL_IN_SUCCESS),he.updateConsultIsAnswer(!0),he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateActionConfigs(gs)),t===exports.WebsocketTypeEnum.CONSULT_RETURN_CALL_SUCCESS&&(ae.emit(exports.CallSipCallEvent.CONSULT_RETURN_CALL_SUCCESS),he.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)),t===exports.WebsocketTypeEnum.MUTE&&(0===i?(he.updateIsMuted(!0),ae.emit(exports.CallSipCallEvent.MUTE_SUCCESS),he.updateDisplayText(exports.DisplayTextEnum.MUTING)):ae.emit(exports.CallSipCallEvent.MUTE_FAILED,r)),t===exports.WebsocketTypeEnum.UNMUTE&&(0===i?(he.updateIsMuted(!1),ae.emit(exports.CallSipCallEvent.UNMUTE_SUCCESS),he.updateDisplayText(exports.DisplayTextEnum.CALLING)):ae.emit(exports.CallSipCallEvent.UNMUTE_FAILED,r)),t===exports.WebsocketTypeEnum.CALL_HOLD&&(0===i?(he.updateIsHold(!0),he.updateDisplayText(exports.DisplayTextEnum.HOLDING),ae.emit(exports.CallSipCallEvent.HOLD_SUCCESS)):ae.emit(exports.CallSipCallEvent.HOLD_FAILED,r)),t===exports.WebsocketTypeEnum.CALL_UNHOLD&&(0===i?(he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateIsHold(!1),ae.emit(exports.CallSipCallEvent.UNHOLD_SUCCESS)):ae.emit(exports.CallSipCallEvent.UNHOLD_FAILED,r)),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER&&(0===i?ae.emit(exports.CallSipCallEvent.CONSULT_TRANSFER_SUCCESS):ae.emit(exports.CallSipCallEvent.CONSULT_TRANSFER_FAILED,r)),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER_FAILED&&ae.emit(exports.CallSipCallEvent.CONSULT_TRANSFER_FAILED,s.status),t===exports.WebsocketTypeEnum.CONSULT_TRANSFER_OFF_HOOK&&(he.updateDirection(exports.DirectionEnum.INCOMING),he.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEvent.CONSULT_TRANSFER_OFF_HOOK),he.updateActionConfigs(ps),he.updateIncomingIsAnswer(!0),he.updateConsultIsAnswer(!1)),t===exports.WebsocketTypeEnum.INCOMING_CALL&&(Ve.sessionId=s.session_id,he.updateIsCalling(!0),he.updateDirection(exports.DirectionEnum.INCOMING),he.updateDisplayText(exports.DisplayTextEnum.INCOMING_CALL),ae.emit(exports.CallSipCallEvent.INCOMING_CALL,{customer_phone:s.customer_phone}),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&vs.show("📞 客户来电",`客户 [${s.customer_phone}] 正在呼入...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})})),t===exports.WebsocketTypeEnum.INCOMING_CALL_OFF_HOOK&&(he.updateIncomingIsAnswer(!0),ae.emit(exports.CallSipCallEvent.INCOMING_CALL_OFF_HOOK),he.updateActionConfigs(ps),he.updateDisplayText(exports.DisplayTextEnum.CALLING)),t===exports.WebsocketTypeEnum.INCOMING_CALL_END&&(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.INCOMING_CALL_END),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(he.reset(),ae.emit(exports.CallSipCallEvent.OUR_SIDE_CONSULT_HANGUP,s),this.putAgentState(),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no?(he.updateDisplayText(exports.DisplayTextEnum.CALLING),ae.emit(exports.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)):3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.THREE_WAY_OUR_SIDE_HANGUP),he.updateActionConfigs(as)):4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(),he.reset(),ae.emit(exports.CallSipCallEvent.TRANSFER_END),he.updateActionConfigs(as))),t===exports.WebsocketTypeEnum.SATISFACTION_EVALUATION&&(0===i?ae.emit(exports.CallSipCallEvent.SATISFACTION_EVALUATION_SUCCESS):ae.emit(exports.CallSipCallEvent.SATISFACTION_EVALUATION_FAILED,r)),t===exports.WebsocketTypeEnum.CONSULT_THREE_WAY&&(0!==i?ae.emit(exports.CallSipCallEvent.CONSULT_THREE_WAY_FAILED,r):0===i&&he.updateIsMeeting(!0)),t===exports.WebsocketTypeEnum.CONSULT_THREE_WAY_RESULT&&("success"===s.status?(he.updateDirection(exports.DirectionEnum.MEETING),he.updateDisplayText(exports.DisplayTextEnum.MEETING),he.updateActionConfigs(qs),ae.emit(exports.CallSipCallEvent.CONSULT_THREE_WAY_SUCCESS)):(ae.emit(exports.CallSipCallEvent.CONSULT_THREE_WAY_FAILED,{conf_name:s.conf_name}),he.updateIsMeeting(!1))),t===exports.WebsocketTypeEnum.TRANSFER_INCOMING_CALL&&(s.agent_no===Ve.agentInfo.agent_no?(he.updateDisplayText(exports.DisplayTextEnum.TRANSFERRING),ae.emit(exports.CallSipCallEvent.TRANSFER_PROGRESS),he.updateActionConfigs([]),he.updateTransferIsAnswer(!0)):(ae.emit(exports.CallSipCallEvent.TRANSFER_INCOMING_CALL,s),he.updateIsCalling(!0),he.updateDirection(exports.DirectionEnum.TRANSFER),he.updateDisplayText(exports.DisplayTextEnum.TRANSFER_INCOMING_CALL),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&vs.show("📞 转接来电",`坐席 [${s.agent_no}] 正在转接...`,()=>{ae.emit(exports.EventName.NOTIFICATION_CLICK,{agent_mane:s.agent_no})}))),t===exports.WebsocketTypeEnum.TRANSFER_OFF_HOOK&&(Ve.sessionId=s.session_id,ae.emit(exports.CallSipCallEvent.TRANSFER_OFF_HOOK),he.updateTransferIsAnswer(!0),he.updateDisplayText(exports.DisplayTextEnum.CALLING),he.updateActionConfigs(ps)),t===exports.WebsocketTypeEnum.TRANSFER_FAILED&&"failed"===s.status){ae.emit(exports.CallSipCallEvent.TRANSFER_FAILED,"未知原因");const A=he.get("direction");A===exports.DirectionEnum.OUTGOING?he.updateActionConfigs(hs):A===exports.DirectionEnum.INCOMING&&he.updateActionConfigs(ps)}},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{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 }, 14000);\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=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(100===A.type&&this.getCustomerInfo(A.data.customer_phone),this.ws.send(JSON.stringify(A))):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Ks&&(Ks.close(),Ks=null)}static __internalSend(A){if(!Ks)throw new Error("WebSocket 尚未初始化");Ks.sendMessage(A)}}class Ns{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:"当前已处于保持状态"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前未处于保持状态"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!he.get("actionConfigs").includes("reject"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用拒接"}));const{isCalling:A,direction:e,outCallIsAnswer:t}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));t||(e===exports.DirectionEnum.INCOMING?this.rejectInCall():e===exports.DirectionEnum.OUTGOING&&this.rejectOutCall())}async consultCall(A){this.roleMute();const{isCalling:e,outCallIsAnswer:t,consultIsAnswer:s,incomingIsAnswer:i}=he.getState(),r=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(!r)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));Os.__internalSend({type:exports.WebsocketTypeEnum.CONSULT_REQUEST,data:{session_id:r,consultation_agent_no:A}})}async answerCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}async rejectInCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));const{isCalling:A}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));await this.sipClient.rejectInCall()}async makeCall(A){const e=he.get("isCalling"),t=he.get("selectOutNumber")||"";if(e)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));he.updateIsCalling(!0),he.updateDirection(exports.DirectionEnum.OUTGOING),Os.__internalSend({type:exports.WebsocketTypeEnum.OUT_CALL,data:{customer_phone:A,caller:t}})}async rejectOutCall(){const{isCalling:A}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=Ve.sessionId;Os.__internalSend({type:exports.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:e}})}async hangup(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前状态请勿调用静音"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前状态请勿调用静音"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前未处于咨询中"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前状态请勿调用满意度评价"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前未处于咨询中"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前未处于咨询中"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前正在转接"}));Os.__internalSend({type:exports.WebsocketTypeEnum.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:"当前正在转接"}));Os.__internalSend({type:exports.WebsocketTypeEnum.TRANSFER,data:{session_id:t,transfer_type:2,transfer_dest:A}})}}exports.default=class{#A=null;#e=new Us;#t;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#o();Xe.updateRttObject(A)},2e3),vs.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=he.subscribeKey("answerDevice",A=>{1===A?this.initWebRtc():this.#A=null})}async initWebRtc(){if(this.#A)return;const A=Ve.agentInfo.sip_account_list.find(A=>1===A.device_type);if(A){const e=A.sip_register_addr;this.#A=new _e({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#n),await this.#A.start()}}async init({actionNodeParams:A,url:e,appKey:t,appSecret:s,agentNo:i,enableBrowserAlert:r}){try{const{viewHtmlElement:o,rttHTML:n}=A||{},a=e||"https://aicc.yescloudy.com";je=a,Le=t,We=s;const V=be(t,s);await this.#e._agentLogin(i);const{agent_no:c,current_answer_device:h,init_state:l,out_display_number:g}=Ve.agentInfo;l===exports.AgentStatus.IDLE?(he.updateActionConfigs(as),Ve.stateObject={state:l,state_name:"空闲"}):l===exports.AgentStatus.BUSY&&(he.updateActionConfigs(Vs),Ve.stateObject={state:l,state_name:"忙碌"}),he.updateSelectOutNumber(g);let q="";const d=new URL(a).host;q=a.includes("https")?`wss://${d}`:`ws://${d}`,Os.getInstance(`${q}/ccs-ws/api/v1/ws/call/${c}?Authorization=${V}`),he.updateAnswerDevice(h),1===h&&await this.initWebRtc(),this.#t=new Ns(this.#A),A&&o&&(this.#i=!0,new Zs({container:o,rttHTML:n,statusParams:{state:exports.AgentStatus.IDLE,statusName:"空闲"}},this,this.#t)),Ve.enableBrowserAlert=r,r&&vs.requestPermission(),ae.emit(exports.EventName.AGENT_INIT_STATUS,!0)}catch(A){this.#i&&Fs("初始化失败")}}#n=A=>{const{type:e,data:t}=A;ae.emit(e,t)};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())}destroy(){this.destroyRtc(),clearInterval(this.#s),Os.__internalClose(),this.offAll(),this.#r?.(),this.#A=null,this.#e=null,this.#i=!1}async#o(){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),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))}}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))}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:o}=Ve.agentInfo,{stateObject:n}=Ve,a={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:o,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:a[Number(A)]})),stateObject:n}}};
|
|
@@ -920,4 +920,4 @@ const ms=A=>(e,t)=>{void 0!==t?t.addInitializer(()=>{customElements.define(A,e)}
|
|
|
920
920
|
`:""}
|
|
921
921
|
</div>
|
|
922
922
|
</my-popover>
|
|
923
|
-
`;ss(s,this.rttHTML)}}class xs{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){if("Notification"in window&&"granted"===Notification.permission){const s=new Notification(A,{body:e,tag:"xy-global-notification",renotify:!0});s.onclick=()=>{window.focus(),s.close(),t?.()},setTimeout(()=>s.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}let Ks=null;class Os{constructor(A){this.url=A,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Us,this.initWebSocket()}static getInstance(A){if(!Ks){if(!A)throw new Error("WebSocket 尚未初始化");Ks=new Os(A)}return Ks}stateIdleChange(){const{state:A}=Ve.stateObject;A!==Ae.IDLE&&this.apiClient._changeState({data:{...Ve.stateBeforeChange}})}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{const{contact_count:e,customer_name:t,phone:s,city:i,province:r}=A.data;ae.emit(se.CUSTOMER_INFO,{customer_name:t||"未知客户",phone:s,city:i||"未知",province:r||"未知",contact_count:e||0})}})}catch(A){}}putAgentState(){Ve.sessionId="";const{post_call_process_time:A}=Ve.agentInfo,e=A||0;Ve.autoStateTimer&&(clearTimeout(Ve.autoStateTimer),Ve.autoStateTimer=null),ae.emit(se.CUSTOMER_INFO,void 0),e>0?Ve.autoStateTimer=setTimeout(()=>{Ve.autoStateTimer=null,this.stateIdleChange()},e):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=A=>{const e=JSON.parse(A.data),{type:t,data:s,code:i,msg:r}=e;if(t===ie.OUT_CALL&&(0!==i?(he.reset(),ae.emit(se.OUT_FAILED,r),setTimeout(()=>{ae.emit(se.CUSTOMER_INFO,void 0)},500),this.stateIdleChange()):0===i&&ae.emit(se.OUT_SUCCESS)),t===ie.AGENT_STATE){Ve.stateObject.state!==Ae.IDLE&&Ve.stateObject.state!==Ae.BUSY||(Ve.stateBeforeChange=Ve.stateObject);const{state:A,state_name:e}=s;Ve.stateObject={state:A,state_name:e},"振铃中"===e&&he.updateDisplayText(oe.AGENT_RINGING),ae.emit(se.AGENT_STATE,{state:A,state_name:e})}if(t===ie.OUT_CALL_INCOMING_CALL&&(ae.emit(se.OUT_INCOMING_CALL),Ve.sessionId=s.session_id,he.updateActionConfigs(cs)),t===ie.OUT_CALL_END&&(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(se.OUT_HANGUP,s),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(he.reset(),ae.emit(se.OUR_SIDE_CONSULT_HANGUP,s),this.putAgentState(),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no?(he.updateDisplayText(oe.CALLING),ae.emit(se.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)):3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(se.THREE_WAY_OUR_SIDE_HANGUP),he.updateActionConfigs(as)):4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(),he.reset(),ae.emit(se.TRANSFER_END),he.updateActionConfigs(as))),t===ie.OUT_CALL_RINGING&&1===s.type&&(ae.emit(se.OUT_RINGING,s),he.updateDisplayText(oe.RINGING)),t===ie.OUT_CALL_ANSWER&&(ae.emit(se.OUT_OFF_ANSWER,s),he.updateOutCallIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(hs)),t===ie.CONSULT_RINGING&&(ae.emit(se.CONSULT_RINGING),he.updateDisplayText(oe.AGENT_RINGING),he.updateActionConfigs([])),t===ie.CONSULT_ANSWER&&(ae.emit(se.CONSULT_OFF_HOOK,s),he.updateConsultIsAnswer(!0),he.updateDisplayText(oe.CONSULTING),he.updateActionConfigs(ls)),t===ie.CONSULT_FAIL&&(ae.emit(se.CONSULT_FAILED,{custom_reason:s.custom_reason}),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(hs)),t===ie.CONSULT_CALL_IN&&(ae.emit(se.CONSULT_INCOMING,s),he.updateIsCalling(!0),he.updateDirection(ee.CONSULT),he.updateDisplayText(oe.CONSULT_CALL_IN),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&xs.show("📞 咨询来电",`坐席 [${s.agent_name}] 正在咨询...`,()=>{ae.emit(re.NOTIFICATION_CLICK,{agent_mane:s.agent_name})})),t===ie.CONSULT_CALL_IN_SUCCESS&&(Ve.sessionId=s.session_id,ae.emit(se.CONSULT_CALL_IN_SUCCESS),he.updateConsultIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(gs)),t===ie.CONSULT_RETURN_CALL_SUCCESS&&(ae.emit(se.CONSULT_RETURN_CALL_SUCCESS),he.updateDisplayText(oe.CALLING),ae.emit(se.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)),t===ie.MUTE&&(0===i?(he.updateIsMuted(!0),ae.emit(se.MUTE_SUCCESS),he.updateDisplayText(oe.MUTING)):ae.emit(se.MUTE_FAILED,r)),t===ie.UNMUTE&&(0===i?(he.updateIsMuted(!1),ae.emit(se.UNMUTE_SUCCESS),he.updateDisplayText(oe.CALLING)):ae.emit(se.UNMUTE_FAILED,r)),t===ie.CALL_HOLD&&(0===i?(he.updateIsHold(!0),he.updateDisplayText(oe.HOLDING),ae.emit(se.HOLD_SUCCESS)):ae.emit(se.HOLD_FAILED,r)),t===ie.CALL_UNHOLD&&(0===i?(he.updateDisplayText(oe.CALLING),he.updateIsHold(!1),ae.emit(se.UNHOLD_SUCCESS)):ae.emit(se.UNHOLD_FAILED,r)),t===ie.CONSULT_TRANSFER&&(0===i?ae.emit(se.CONSULT_TRANSFER_SUCCESS):ae.emit(se.CONSULT_TRANSFER_FAILED,r)),t===ie.CONSULT_TRANSFER_FAILED&&ae.emit(se.CONSULT_TRANSFER_FAILED,s.status),t===ie.CONSULT_TRANSFER_OFF_HOOK&&(he.updateDirection(ee.INCOMING),he.updateDisplayText(oe.CALLING),ae.emit(se.CONSULT_TRANSFER_OFF_HOOK),he.updateActionConfigs(us),he.updateIncomingIsAnswer(!0),he.updateConsultIsAnswer(!1)),t===ie.INCOMING_CALL&&(Ve.sessionId=s.session_id,he.updateIsCalling(!0),he.updateDirection(ee.INCOMING),he.updateDisplayText(oe.INCOMING_CALL),ae.emit(se.INCOMING_CALL,{customer_phone:s.customer_phone}),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&xs.show("📞 客户来电",`客户 [${s.customer_phone}] 正在呼入...`,()=>{ae.emit(re.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})})),t===ie.INCOMING_CALL_OFF_HOOK&&(he.updateIncomingIsAnswer(!0),ae.emit(se.INCOMING_CALL_OFF_HOOK),he.updateActionConfigs(us),he.updateDisplayText(oe.CALLING)),t===ie.INCOMING_CALL_END&&(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(se.INCOMING_CALL_END),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(he.reset(),ae.emit(se.OUR_SIDE_CONSULT_HANGUP,s),this.putAgentState(),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no?(he.updateDisplayText(oe.CALLING),ae.emit(se.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)):3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(se.THREE_WAY_OUR_SIDE_HANGUP),he.updateActionConfigs(as)):4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(),he.reset(),ae.emit(se.TRANSFER_END),he.updateActionConfigs(as))),t===ie.SATISFACTION_EVALUATION&&(0===i?ae.emit(se.SATISFACTION_EVALUATION_SUCCESS):ae.emit(se.SATISFACTION_EVALUATION_FAILED,r)),t===ie.CONSULT_THREE_WAY&&(0!==i?ae.emit(se.CONSULT_THREE_WAY_FAILED,r):0===i&&he.updateIsMeeting(!0)),t===ie.CONSULT_THREE_WAY_RESULT&&("success"===s.status?(he.updateDirection(ee.MEETING),he.updateDisplayText(oe.MEETING),he.updateActionConfigs(qs),ae.emit(se.CONSULT_THREE_WAY_SUCCESS)):(ae.emit(se.CONSULT_THREE_WAY_FAILED,{conf_name:s.conf_name}),he.updateIsMeeting(!1))),t===ie.TRANSFER_INCOMING_CALL&&(s.agent_no===Ve.agentInfo.agent_no?(he.updateDisplayText(oe.TRANSFERRING),ae.emit(se.TRANSFER_PROGRESS),he.updateActionConfigs([]),he.updateTransferIsAnswer(!0)):(ae.emit(se.TRANSFER_INCOMING_CALL,s),he.updateIsCalling(!0),he.updateDirection(ee.TRANSFER),he.updateDisplayText(oe.TRANSFER_INCOMING_CALL),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&xs.show("📞 转接来电",`坐席 [${s.agent_no}] 正在转接...`,()=>{ae.emit(re.NOTIFICATION_CLICK,{agent_mane:s.agent_no})}))),t===ie.TRANSFER_OFF_HOOK&&(Ve.sessionId=s.session_id,ae.emit(se.TRANSFER_OFF_HOOK),he.updateTransferIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(us)),t===ie.TRANSFER_FAILED&&"failed"===s.status){ae.emit(se.TRANSFER_FAILED,"未知原因");const A=he.get("direction");A===ee.OUTGOING?he.updateActionConfigs(hs):A===ee.INCOMING&&he.updateActionConfigs(us)}},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{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 }, 14000);\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=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(100===A.type&&this.getCustomerInfo(A.data.customer_phone),this.ws.send(JSON.stringify(A))):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Ks&&(Ks.close(),Ks=null)}static __internalSend(A){if(!Ks)throw new Error("WebSocket 尚未初始化");Ks.sendMessage(A)}}class Ns{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:"当前已处于保持状态"}));Os.__internalSend({type:ie.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:"当前未处于保持状态"}));Os.__internalSend({type:ie.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(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!he.get("actionConfigs").includes("reject"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用拒接"}));const{isCalling:A,direction:e,outCallIsAnswer:t}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));t||(e===ee.INCOMING?this.rejectInCall():e===ee.OUTGOING&&this.rejectOutCall())}async consultCall(A){this.roleMute();const{isCalling:e,outCallIsAnswer:t,consultIsAnswer:s,incomingIsAnswer:i}=he.getState(),r=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(!r)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));Os.__internalSend({type:ie.CONSULT_REQUEST,data:{session_id:r,consultation_agent_no:A}})}async answerCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}async rejectInCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));const{isCalling:A}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));await this.sipClient.rejectInCall()}async makeCall(A){const e=he.get("isCalling"),t=he.get("selectOutNumber")||"";if(e)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));he.updateIsCalling(!0),he.updateDirection(ee.OUTGOING),Os.__internalSend({type:ie.OUT_CALL,data:{customer_phone:A,caller:t}})}async rejectOutCall(){const{isCalling:A}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=Ve.sessionId;Os.__internalSend({type:ie.AGENT_HANGUP,data:{session_id:e}})}async hangup(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;Os.__internalSend({type:ie.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:"当前状态请勿调用静音"}));Os.__internalSend({type:ie.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:"当前状态请勿调用静音"}));Os.__internalSend({type:ie.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:"当前未处于咨询中"}));Os.__internalSend({type:ie.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:"当前状态请勿调用满意度评价"}));Os.__internalSend({type:ie.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:"当前未处于咨询中"}));Os.__internalSend({type:ie.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:"当前未处于咨询中"}));Os.__internalSend({type:ie.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:"当前正在转接"}));Os.__internalSend({type:ie.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:"当前正在转接"}));Os.__internalSend({type:ie.TRANSFER,data:{session_id:t,transfer_type:2,transfer_dest:A}})}}class bs{#A=null;#e=new Us;#t;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#o();Xe.updateRttObject(A)},2e3),xs.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=he.subscribeKey("answerDevice",A=>{1===A?this.initWebRtc():this.#A=null})}async initWebRtc(){if(this.#A)return;const A=Ve.agentInfo.sip_account_list.find(A=>1===A.device_type);if(A){const e=A.sip_register_addr;this.#A=new _e({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#n),await this.#A.start()}}async init({actionNodeParams:A,url:e,appKey:t,appSecret:s,agentNo:i,enableBrowserAlert:r}){try{const{viewHtmlElement:o,rttHTML:n}=A||{},a=e||"https://aicc.yescloudy.com";je=a,Le=t,We=s;const V=be(t,s);await this.#e._agentLogin(i);const{agent_no:c,current_answer_device:h,init_state:l,out_display_number:g}=Ve.agentInfo;l===Ae.IDLE?(he.updateActionConfigs(as),Ve.stateObject={state:l,state_name:"空闲"}):l===Ae.BUSY&&(he.updateActionConfigs(Vs),Ve.stateObject={state:l,state_name:"忙碌"}),he.updateSelectOutNumber(g);let q="";const d=new URL(a).host;q=a.includes("https")?`wss://${d}`:`ws://${d}`,Os.getInstance(`${q}/ccs-ws/api/v1/ws/call/${c}?Authorization=${V}`),he.updateAnswerDevice(h),1===h&&await this.initWebRtc(),this.#t=new Ns(this.#A),A&&o&&(this.#i=!0,new vs({container:o,rttHTML:n,statusParams:{state:Ae.IDLE,statusName:"空闲"}},this,this.#t)),Ve.enableBrowserAlert=r,r&&xs.requestPermission(),ae.emit(re.AGENT_INIT_STATUS,!0)}catch(A){this.#i&&Fs("初始化失败")}}#n=A=>{const{type:e,data:t}=A;ae.emit(e,t)};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())}destroy(){this.destroyRtc(),clearInterval(this.#s),Os.__internalClose(),this.offAll(),this.#r?.(),this.#A=null,this.#e=null,this.#i=!1}async#o(){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),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))}}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))}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:o}=Ve.agentInfo,{stateObject:n}=Ve,a={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:o,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:a[Number(A)]})),stateObject:n}}}export{Ae as AgentStatus,se as CallSipCallEvent,ee as DirectionEnum,oe as DisplayTextEnum,re as EventName,te as WebRtcCallSipEventEnum,ie as WebsocketTypeEnum,bs as default};
|
|
923
|
+
`;ss(s,this.rttHTML)}}class xs{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){if("Notification"in window&&"granted"===Notification.permission){const s=new Notification(A,{body:e,tag:"xy-global-notification",renotify:!0});s.onclick=()=>{window.focus(),s.close(),t?.()},setTimeout(()=>s.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}let Ks=null;class Os{constructor(A){this.url=A,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Us,this.initWebSocket()}static getInstance(A){if(!Ks){if(!A)throw new Error("WebSocket 尚未初始化");Ks=new Os(A)}return Ks}stateIdleChange(){const{state:A}=Ve.stateObject;A!==Ae.IDLE&&this.apiClient._changeState({data:{...Ve.stateBeforeChange}})}async getCustomerInfo(A){try{await this.apiClient._getInCallCrmDetail({data:{phone:A},success:A=>{const{contact_count:e,customer_name:t,phone:s,city:i,province:r}=A.data;ae.emit(se.CUSTOMER_INFO,{customer_name:t||"未知客户",phone:s,city:i||"未知",province:r||"未知",contact_count:e||0})}})}catch(A){}}putAgentState(){Ve.sessionId="";const{post_call_process_time:A}=Ve.agentInfo,e=A||0;Ve.autoStateTimer&&(clearTimeout(Ve.autoStateTimer),Ve.autoStateTimer=null),ae.emit(se.CUSTOMER_INFO,void 0),e>0?Ve.autoStateTimer=setTimeout(()=>{Ve.autoStateTimer=null,this.stateIdleChange()},e):this.stateIdleChange()}initWebSocket(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.sendMessage({type:0}),this.startHeartbeat()},this.ws.onmessage=A=>{const e=JSON.parse(A.data),{type:t,data:s,code:i,msg:r}=e;if(t===ie.OUT_CALL&&(0!==i?(he.reset(),ae.emit(se.OUT_FAILED,r),setTimeout(()=>{ae.emit(se.CUSTOMER_INFO,void 0)},500),this.stateIdleChange()):0===i&&ae.emit(se.OUT_SUCCESS)),t===ie.AGENT_STATE){Ve.stateObject.state!==Ae.IDLE&&Ve.stateObject.state!==Ae.BUSY||(Ve.stateBeforeChange=Ve.stateObject);const{state:A,state_name:e}=s;Ve.stateObject={state:A,state_name:e},"振铃中"===e&&he.updateDisplayText(oe.AGENT_RINGING),ae.emit(se.AGENT_STATE,{state:A,state_name:e})}if(t===ie.OUT_CALL_INCOMING_CALL&&(ae.emit(se.OUT_INCOMING_CALL),Ve.sessionId=s.session_id,he.updateActionConfigs(cs)),t===ie.OUT_CALL_END&&(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(se.OUT_HANGUP,s),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(he.reset(),ae.emit(se.OUR_SIDE_CONSULT_HANGUP,s),this.putAgentState(),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no?(he.updateDisplayText(oe.CALLING),ae.emit(se.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)):3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(se.THREE_WAY_OUR_SIDE_HANGUP),he.updateActionConfigs(as)):4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(),he.reset(),ae.emit(se.TRANSFER_END),he.updateActionConfigs(as))),t===ie.OUT_CALL_RINGING&&1===s.type&&(ae.emit(se.OUT_RINGING,s),he.updateDisplayText(oe.RINGING)),t===ie.OUT_CALL_ANSWER&&(ae.emit(se.OUT_OFF_ANSWER,s),he.updateOutCallIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(hs)),t===ie.CONSULT_RINGING&&(ae.emit(se.CONSULT_RINGING),he.updateDisplayText(oe.AGENT_RINGING),he.updateActionConfigs([])),t===ie.CONSULT_ANSWER&&(ae.emit(se.CONSULT_OFF_HOOK,s),he.updateConsultIsAnswer(!0),he.updateDisplayText(oe.CONSULTING),he.updateActionConfigs(ls)),t===ie.CONSULT_FAIL&&(ae.emit(se.CONSULT_FAILED,{custom_reason:s.custom_reason}),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(hs)),t===ie.CONSULT_CALL_IN&&(ae.emit(se.CONSULT_INCOMING,s),he.updateIsCalling(!0),he.updateDirection(ee.CONSULT),he.updateDisplayText(oe.CONSULT_CALL_IN),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&xs.show("📞 咨询来电",`坐席 [${s.agent_name}] 正在咨询...`,()=>{ae.emit(re.NOTIFICATION_CLICK,{agent_mane:s.agent_name})})),t===ie.CONSULT_CALL_IN_SUCCESS&&(Ve.sessionId=s.session_id,ae.emit(se.CONSULT_CALL_IN_SUCCESS),he.updateConsultIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(gs)),t===ie.CONSULT_RETURN_CALL_SUCCESS&&(ae.emit(se.CONSULT_RETURN_CALL_SUCCESS),he.updateDisplayText(oe.CALLING),ae.emit(se.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)),t===ie.MUTE&&(0===i?(he.updateIsMuted(!0),ae.emit(se.MUTE_SUCCESS),he.updateDisplayText(oe.MUTING)):ae.emit(se.MUTE_FAILED,r)),t===ie.UNMUTE&&(0===i?(he.updateIsMuted(!1),ae.emit(se.UNMUTE_SUCCESS),he.updateDisplayText(oe.CALLING)):ae.emit(se.UNMUTE_FAILED,r)),t===ie.CALL_HOLD&&(0===i?(he.updateIsHold(!0),he.updateDisplayText(oe.HOLDING),ae.emit(se.HOLD_SUCCESS)):ae.emit(se.HOLD_FAILED,r)),t===ie.CALL_UNHOLD&&(0===i?(he.updateDisplayText(oe.CALLING),he.updateIsHold(!1),ae.emit(se.UNHOLD_SUCCESS)):ae.emit(se.UNHOLD_FAILED,r)),t===ie.CONSULT_TRANSFER&&(0===i?ae.emit(se.CONSULT_TRANSFER_SUCCESS):ae.emit(se.CONSULT_TRANSFER_FAILED,r)),t===ie.CONSULT_TRANSFER_FAILED&&ae.emit(se.CONSULT_TRANSFER_FAILED,s.status),t===ie.CONSULT_TRANSFER_OFF_HOOK&&(he.updateDirection(ee.INCOMING),he.updateDisplayText(oe.CALLING),ae.emit(se.CONSULT_TRANSFER_OFF_HOOK),he.updateActionConfigs(us),he.updateIncomingIsAnswer(!0),he.updateConsultIsAnswer(!1)),t===ie.INCOMING_CALL&&(Ve.sessionId=s.session_id,he.updateIsCalling(!0),he.updateDirection(ee.INCOMING),he.updateDisplayText(oe.INCOMING_CALL),ae.emit(se.INCOMING_CALL,{customer_phone:s.customer_phone}),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&xs.show("📞 客户来电",`客户 [${s.customer_phone}] 正在呼入...`,()=>{ae.emit(re.NOTIFICATION_CLICK,{customer_phone:s.customer_phone})})),t===ie.INCOMING_CALL_OFF_HOOK&&(he.updateIncomingIsAnswer(!0),ae.emit(se.INCOMING_CALL_OFF_HOOK),he.updateActionConfigs(us),he.updateDisplayText(oe.CALLING)),t===ie.INCOMING_CALL_END&&(he.updateDisplayText(""),1===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(se.INCOMING_CALL_END),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(he.reset(),ae.emit(se.OUR_SIDE_CONSULT_HANGUP,s),this.putAgentState(),he.updateActionConfigs(as)):2===s.device_type&&s.agent_no!==Ve.agentInfo.agent_no?(he.updateDisplayText(oe.CALLING),ae.emit(se.OTHER_SIDE_CONSULT_HANGUP,s),he.updateActionConfigs(hs)):3===s.device_type&&s.agent_no===Ve.agentInfo.agent_no?(this.putAgentState(),he.reset(),ae.emit(se.THREE_WAY_OUR_SIDE_HANGUP),he.updateActionConfigs(as)):4===s.device_type&&s.agent_no===Ve.agentInfo.agent_no&&(this.putAgentState(),he.reset(),ae.emit(se.TRANSFER_END),he.updateActionConfigs(as))),t===ie.SATISFACTION_EVALUATION&&(0===i?ae.emit(se.SATISFACTION_EVALUATION_SUCCESS):ae.emit(se.SATISFACTION_EVALUATION_FAILED,r)),t===ie.CONSULT_THREE_WAY&&(0!==i?ae.emit(se.CONSULT_THREE_WAY_FAILED,r):0===i&&he.updateIsMeeting(!0)),t===ie.CONSULT_THREE_WAY_RESULT&&("success"===s.status?(he.updateDirection(ee.MEETING),he.updateDisplayText(oe.MEETING),he.updateActionConfigs(qs),ae.emit(se.CONSULT_THREE_WAY_SUCCESS)):(ae.emit(se.CONSULT_THREE_WAY_FAILED,{conf_name:s.conf_name}),he.updateIsMeeting(!1))),t===ie.TRANSFER_INCOMING_CALL&&(s.agent_no===Ve.agentInfo.agent_no?(he.updateDisplayText(oe.TRANSFERRING),ae.emit(se.TRANSFER_PROGRESS),he.updateActionConfigs([]),he.updateTransferIsAnswer(!0)):(ae.emit(se.TRANSFER_INCOMING_CALL,s),he.updateIsCalling(!0),he.updateDirection(ee.TRANSFER),he.updateDisplayText(oe.TRANSFER_INCOMING_CALL),he.updateActionConfigs(ds),Ve.enableBrowserAlert&&xs.show("📞 转接来电",`坐席 [${s.agent_no}] 正在转接...`,()=>{ae.emit(re.NOTIFICATION_CLICK,{agent_mane:s.agent_no})}))),t===ie.TRANSFER_OFF_HOOK&&(Ve.sessionId=s.session_id,ae.emit(se.TRANSFER_OFF_HOOK),he.updateTransferIsAnswer(!0),he.updateDisplayText(oe.CALLING),he.updateActionConfigs(us)),t===ie.TRANSFER_FAILED&&"failed"===s.status){ae.emit(se.TRANSFER_FAILED,"未知原因");const A=he.get("direction");A===ee.OUTGOING?he.updateActionConfigs(hs):A===ee.INCOMING&&he.updateActionConfigs(us)}},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{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 }, 14000);\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=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(100===A.type&&this.getCustomerInfo(A.data.customer_phone),this.ws.send(JSON.stringify(A))):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Ks&&(Ks.close(),Ks=null)}static __internalSend(A){if(!Ks)throw new Error("WebSocket 尚未初始化");Ks.sendMessage(A)}}class Ns{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:"当前已处于保持状态"}));Os.__internalSend({type:ie.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:"当前未处于保持状态"}));Os.__internalSend({type:ie.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(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!he.get("actionConfigs").includes("reject"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用拒接"}));const{isCalling:A,direction:e,outCallIsAnswer:t}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));t||(e===ee.INCOMING?this.rejectInCall():e===ee.OUTGOING&&this.rejectOutCall())}async consultCall(A){this.roleMute();const{isCalling:e,outCallIsAnswer:t,consultIsAnswer:s,incomingIsAnswer:i}=he.getState(),r=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(!r)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));Os.__internalSend({type:ie.CONSULT_REQUEST,data:{session_id:r,consultation_agent_no:A}})}async answerCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}async rejectInCall(){if(1!==he.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));const{isCalling:A}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));await this.sipClient.rejectInCall()}async makeCall(A){const e=he.get("isCalling"),t=he.get("selectOutNumber")||"";if(e)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));he.updateIsCalling(!0),he.updateDirection(ee.OUTGOING),Os.__internalSend({type:ie.OUT_CALL,data:{customer_phone:A,caller:t}})}async rejectOutCall(){const{isCalling:A}=he.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=Ve.sessionId;Os.__internalSend({type:ie.AGENT_HANGUP,data:{session_id:e}})}async hangup(){if(!he.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const A=Ve.sessionId;Os.__internalSend({type:ie.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:"当前状态请勿调用静音"}));Os.__internalSend({type:ie.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:"当前状态请勿调用静音"}));Os.__internalSend({type:ie.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:"当前未处于咨询中"}));Os.__internalSend({type:ie.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:"当前状态请勿调用满意度评价"}));Os.__internalSend({type:ie.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:"当前未处于咨询中"}));Os.__internalSend({type:ie.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:"当前未处于咨询中"}));Os.__internalSend({type:ie.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:"当前正在转接"}));Os.__internalSend({type:ie.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:"当前正在转接"}));Os.__internalSend({type:ie.TRANSFER,data:{session_id:t,transfer_type:2,transfer_dest:A}})}}class bs{#A=null;#e=new Us;#t;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#o();Xe.updateRttObject(A)},2e3),xs.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=he.subscribeKey("answerDevice",A=>{1===A?this.initWebRtc():this.#A=null})}async initWebRtc(){if(this.#A)return;const A=Ve.agentInfo.sip_account_list.find(A=>1===A.device_type);if(A){const e=A.sip_register_addr;this.#A=new _e({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#n),await this.#A.start()}}async init({actionNodeParams:A,url:e,appKey:t,appSecret:s,agentNo:i,enableBrowserAlert:r}){try{const{viewHtmlElement:o,rttHTML:n}=A||{},a=e||"https://aicc.yescloudy.com";je=a,Le=t,We=s;const V=be(t,s);await this.#e._agentLogin(i);const{agent_no:c,current_answer_device:h,init_state:l,out_display_number:g}=Ve.agentInfo;l===Ae.IDLE?(he.updateActionConfigs(as),Ve.stateObject={state:l,state_name:"空闲"}):l===Ae.BUSY&&(he.updateActionConfigs(Vs),Ve.stateObject={state:l,state_name:"忙碌"}),he.updateSelectOutNumber(g);let q="";const d=new URL(a).host;q=a.includes("https")?`wss://${d}`:`ws://${d}`,Os.getInstance(`${q}/ccs-ws/api/v1/ws/call/${c}?Authorization=${V}`),he.updateAnswerDevice(h),1===h&&await this.initWebRtc(),this.#t=new Ns(this.#A),A&&o&&(this.#i=!0,new vs({container:o,rttHTML:n,statusParams:{state:Ae.IDLE,statusName:"空闲"}},this,this.#t)),Ve.enableBrowserAlert=r,r&&xs.requestPermission(),ae.emit(re.AGENT_INIT_STATUS,!0)}catch(A){this.#i&&Fs("初始化失败")}}#n=A=>{const{type:e,data:t}=A;ae.emit(e,t)};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())}destroy(){this.destroyRtc(),clearInterval(this.#s),Os.__internalClose(),this.offAll(),this.#r?.(),this.#A=null,this.#e=null,this.#i=!1}async#o(){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),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))}}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))}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:o}=Ve.agentInfo,{stateObject:n}=Ve,a={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:o,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:a[Number(A)]})),stateObject:n}}}export{Ae as AgentStatus,se as CallSipCallEvent,ee as DirectionEnum,oe as DisplayTextEnum,re as EventName,te as WebRtcCallSipEventEnum,ie as WebsocketTypeEnum,bs as default};
|
|
@@ -920,4 +920,4 @@ const ms=A=>(e,t)=>{void 0!==t?t.addInitializer(()=>{customElements.define(A,e)}
|
|
|
920
920
|
`:""}
|
|
921
921
|
</div>
|
|
922
922
|
</my-popover>
|
|
923
|
-
`;ss(s,this.rttHTML)}}class xs{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){if("Notification"in window&&"granted"===Notification.permission){const s=new Notification(A,{body:e,tag:"xy-global-notification",renotify:!0});s.onclick=()=>{window.focus(),s.close(),t?.()},setTimeout(()=>s.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}let Ks=null;class Os{constructor(A){this.url=A,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Us,this.initWebSocket()}static getInstance(A){if(!Ks){if(!A)throw new Error("WebSocket 尚未初始化");Ks=new Os(A)}return Ks}stateIdleChange(){const{state:e}=ce.stateObject;e!==A.AgentStatus.IDLE&&this.apiClient._changeState({data:{...ce.stateBeforeChange}})}async getCustomerInfo(e){try{await this.apiClient._getInCallCrmDetail({data:{phone:e},success:e=>{const{contact_count:t,customer_name:s,phone:i,city:r,province:n}=e.data;Ve.emit(A.CallSipCallEvent.CUSTOMER_INFO,{customer_name:s||"未知客户",phone:i,city:r||"未知",province:n||"未知",contact_count:t||0})}})}catch(A){}}putAgentState(){ce.sessionId="";const{post_call_process_time:e}=ce.agentInfo,t=e||0;ce.autoStateTimer&&(clearTimeout(ce.autoStateTimer),ce.autoStateTimer=null),Ve.emit(A.CallSipCallEvent.CUSTOMER_INFO,void 0),t>0?ce.autoStateTimer=setTimeout(()=>{ce.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(s===A.WebsocketTypeEnum.OUT_CALL&&(0!==r?(le.reset(),Ve.emit(A.CallSipCallEvent.OUT_FAILED,n),setTimeout(()=>{Ve.emit(A.CallSipCallEvent.CUSTOMER_INFO,void 0)},500),this.stateIdleChange()):0===r&&Ve.emit(A.CallSipCallEvent.OUT_SUCCESS)),s===A.WebsocketTypeEnum.AGENT_STATE){ce.stateObject.state!==A.AgentStatus.IDLE&&ce.stateObject.state!==A.AgentStatus.BUSY||(ce.stateBeforeChange=ce.stateObject);const{state:e,state_name:t}=i;ce.stateObject={state:e,state_name:t},"振铃中"===t&&le.updateDisplayText(A.DisplayTextEnum.AGENT_RINGING),Ve.emit(A.CallSipCallEvent.AGENT_STATE,{state:e,state_name:t})}if(s===A.WebsocketTypeEnum.OUT_CALL_INCOMING_CALL&&(Ve.emit(A.CallSipCallEvent.OUT_INCOMING_CALL),ce.sessionId=i.session_id,le.updateActionConfigs(cs)),s===A.WebsocketTypeEnum.OUT_CALL_END&&(le.updateDisplayText(""),1===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.OUT_HANGUP,i),le.updateActionConfigs(as)):2===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(le.reset(),Ve.emit(A.CallSipCallEvent.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState(),le.updateActionConfigs(as)):2===i.device_type&&i.agent_no!==ce.agentInfo.agent_no?(le.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,i),le.updateActionConfigs(hs)):3===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.THREE_WAY_OUR_SIDE_HANGUP),le.updateActionConfigs(as)):4===i.device_type&&i.agent_no===ce.agentInfo.agent_no&&(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.TRANSFER_END),le.updateActionConfigs(as))),s===A.WebsocketTypeEnum.OUT_CALL_RINGING&&1===i.type&&(Ve.emit(A.CallSipCallEvent.OUT_RINGING,i),le.updateDisplayText(A.DisplayTextEnum.RINGING)),s===A.WebsocketTypeEnum.OUT_CALL_ANSWER&&(Ve.emit(A.CallSipCallEvent.OUT_OFF_ANSWER,i),le.updateOutCallIsAnswer(!0),le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateActionConfigs(hs)),s===A.WebsocketTypeEnum.CONSULT_RINGING&&(Ve.emit(A.CallSipCallEvent.CONSULT_RINGING),le.updateDisplayText(A.DisplayTextEnum.AGENT_RINGING),le.updateActionConfigs([])),s===A.WebsocketTypeEnum.CONSULT_ANSWER&&(Ve.emit(A.CallSipCallEvent.CONSULT_OFF_HOOK,i),le.updateConsultIsAnswer(!0),le.updateDisplayText(A.DisplayTextEnum.CONSULTING),le.updateActionConfigs(ls)),s===A.WebsocketTypeEnum.CONSULT_FAIL&&(Ve.emit(A.CallSipCallEvent.CONSULT_FAILED,{custom_reason:i.custom_reason}),le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateActionConfigs(hs)),s===A.WebsocketTypeEnum.CONSULT_CALL_IN&&(Ve.emit(A.CallSipCallEvent.CONSULT_INCOMING,i),le.updateIsCalling(!0),le.updateDirection(A.DirectionEnum.CONSULT),le.updateDisplayText(A.DisplayTextEnum.CONSULT_CALL_IN),le.updateActionConfigs(ds),ce.enableBrowserAlert&&xs.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{agent_mane:i.agent_name})})),s===A.WebsocketTypeEnum.CONSULT_CALL_IN_SUCCESS&&(ce.sessionId=i.session_id,Ve.emit(A.CallSipCallEvent.CONSULT_CALL_IN_SUCCESS),le.updateConsultIsAnswer(!0),le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateActionConfigs(gs)),s===A.WebsocketTypeEnum.CONSULT_RETURN_CALL_SUCCESS&&(Ve.emit(A.CallSipCallEvent.CONSULT_RETURN_CALL_SUCCESS),le.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,i),le.updateActionConfigs(hs)),s===A.WebsocketTypeEnum.MUTE&&(0===r?(le.updateIsMuted(!0),Ve.emit(A.CallSipCallEvent.MUTE_SUCCESS),le.updateDisplayText(A.DisplayTextEnum.MUTING)):Ve.emit(A.CallSipCallEvent.MUTE_FAILED,n)),s===A.WebsocketTypeEnum.UNMUTE&&(0===r?(le.updateIsMuted(!1),Ve.emit(A.CallSipCallEvent.UNMUTE_SUCCESS),le.updateDisplayText(A.DisplayTextEnum.CALLING)):Ve.emit(A.CallSipCallEvent.UNMUTE_FAILED,n)),s===A.WebsocketTypeEnum.CALL_HOLD&&(0===r?(le.updateIsHold(!0),le.updateDisplayText(A.DisplayTextEnum.HOLDING),Ve.emit(A.CallSipCallEvent.HOLD_SUCCESS)):Ve.emit(A.CallSipCallEvent.HOLD_FAILED,n)),s===A.WebsocketTypeEnum.CALL_UNHOLD&&(0===r?(le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateIsHold(!1),Ve.emit(A.CallSipCallEvent.UNHOLD_SUCCESS)):Ve.emit(A.CallSipCallEvent.UNHOLD_FAILED,n)),s===A.WebsocketTypeEnum.CONSULT_TRANSFER&&(0===r?Ve.emit(A.CallSipCallEvent.CONSULT_TRANSFER_SUCCESS):Ve.emit(A.CallSipCallEvent.CONSULT_TRANSFER_FAILED,n)),s===A.WebsocketTypeEnum.CONSULT_TRANSFER_FAILED&&Ve.emit(A.CallSipCallEvent.CONSULT_TRANSFER_FAILED,i.status),s===A.WebsocketTypeEnum.CONSULT_TRANSFER_OFF_HOOK&&(le.updateDirection(A.DirectionEnum.INCOMING),le.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEvent.CONSULT_TRANSFER_OFF_HOOK),le.updateActionConfigs(us),le.updateIncomingIsAnswer(!0),le.updateConsultIsAnswer(!1)),s===A.WebsocketTypeEnum.INCOMING_CALL&&(ce.sessionId=i.session_id,le.updateIsCalling(!0),le.updateDirection(A.DirectionEnum.INCOMING),le.updateDisplayText(A.DisplayTextEnum.INCOMING_CALL),Ve.emit(A.CallSipCallEvent.INCOMING_CALL,{customer_phone:i.customer_phone}),le.updateActionConfigs(ds),ce.enableBrowserAlert&&xs.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})})),s===A.WebsocketTypeEnum.INCOMING_CALL_OFF_HOOK&&(le.updateIncomingIsAnswer(!0),Ve.emit(A.CallSipCallEvent.INCOMING_CALL_OFF_HOOK),le.updateActionConfigs(us),le.updateDisplayText(A.DisplayTextEnum.CALLING)),s===A.WebsocketTypeEnum.INCOMING_CALL_END&&(le.updateDisplayText(""),1===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.INCOMING_CALL_END),le.updateActionConfigs(as)):2===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(le.reset(),Ve.emit(A.CallSipCallEvent.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState(),le.updateActionConfigs(as)):2===i.device_type&&i.agent_no!==ce.agentInfo.agent_no?(le.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,i),le.updateActionConfigs(hs)):3===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.THREE_WAY_OUR_SIDE_HANGUP),le.updateActionConfigs(as)):4===i.device_type&&i.agent_no===ce.agentInfo.agent_no&&(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.TRANSFER_END),le.updateActionConfigs(as))),s===A.WebsocketTypeEnum.SATISFACTION_EVALUATION&&(0===r?Ve.emit(A.CallSipCallEvent.SATISFACTION_EVALUATION_SUCCESS):Ve.emit(A.CallSipCallEvent.SATISFACTION_EVALUATION_FAILED,n)),s===A.WebsocketTypeEnum.CONSULT_THREE_WAY&&(0!==r?Ve.emit(A.CallSipCallEvent.CONSULT_THREE_WAY_FAILED,n):0===r&&le.updateIsMeeting(!0)),s===A.WebsocketTypeEnum.CONSULT_THREE_WAY_RESULT&&("success"===i.status?(le.updateDirection(A.DirectionEnum.MEETING),le.updateDisplayText(A.DisplayTextEnum.MEETING),le.updateActionConfigs(qs),Ve.emit(A.CallSipCallEvent.CONSULT_THREE_WAY_SUCCESS)):(Ve.emit(A.CallSipCallEvent.CONSULT_THREE_WAY_FAILED,{conf_name:i.conf_name}),le.updateIsMeeting(!1))),s===A.WebsocketTypeEnum.TRANSFER_INCOMING_CALL&&(i.agent_no===ce.agentInfo.agent_no?(le.updateDisplayText(A.DisplayTextEnum.TRANSFERRING),Ve.emit(A.CallSipCallEvent.TRANSFER_PROGRESS),le.updateActionConfigs([]),le.updateTransferIsAnswer(!0)):(Ve.emit(A.CallSipCallEvent.TRANSFER_INCOMING_CALL,i),le.updateIsCalling(!0),le.updateDirection(A.DirectionEnum.TRANSFER),le.updateDisplayText(A.DisplayTextEnum.TRANSFER_INCOMING_CALL),le.updateActionConfigs(ds),ce.enableBrowserAlert&&xs.show("📞 转接来电",`坐席 [${i.agent_no}] 正在转接...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{agent_mane:i.agent_no})}))),s===A.WebsocketTypeEnum.TRANSFER_OFF_HOOK&&(ce.sessionId=i.session_id,Ve.emit(A.CallSipCallEvent.TRANSFER_OFF_HOOK),le.updateTransferIsAnswer(!0),le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateActionConfigs(us)),s===A.WebsocketTypeEnum.TRANSFER_FAILED&&"failed"===i.status){Ve.emit(A.CallSipCallEvent.TRANSFER_FAILED,"未知原因");const e=le.get("direction");e===A.DirectionEnum.OUTGOING?le.updateActionConfigs(hs):e===A.DirectionEnum.INCOMING&&le.updateActionConfigs(us)}},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{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 }, 14000);\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=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(100===A.type&&this.getCustomerInfo(A.data.customer_phone),this.ws.send(JSON.stringify(A))):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Ks&&(Ks.close(),Ks=null)}static __internalSend(A){if(!Ks)throw new Error("WebSocket 尚未初始化");Ks.sendMessage(A)}}class Ns{constructor(A){this.sipClient=null,this.sipClient=A}roleMute(){const A=le.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=le.get("isHold"),{sessionId:t}=ce;if(!t)return;if(!le.get("actionConfigs").includes("hold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿保持"}));if(e)throw new Error(JSON.stringify({code:1,msg:"当前已处于保持状态"}));Os.__internalSend({type:A.WebsocketTypeEnum.CALL_HOLD,data:{session_id:t}})}unholdCall(){this.roleMute();const{isHold:e}=le.getState(),{sessionId:t}=ce;if(!le.get("actionConfigs").includes("unhold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取消保持"}));if(t){if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于保持状态"}));Os.__internalSend({type:A.WebsocketTypeEnum.CALL_UNHOLD,data:{session_id:t}})}}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(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!le.get("actionConfigs").includes("reject"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用拒接"}));const{isCalling:e,direction:t,outCallIsAnswer:s}=le.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));s||(t===A.DirectionEnum.INCOMING?this.rejectInCall():t===A.DirectionEnum.OUTGOING&&this.rejectOutCall())}async consultCall(e){this.roleMute();const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:r}=le.getState(),n=ce.sessionId;if(!le.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||r))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!n)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));Os.__internalSend({type:A.WebsocketTypeEnum.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:e}})}async answerCall(){if(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}async rejectInCall(){if(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));const{isCalling:A}=le.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));await this.sipClient.rejectInCall()}async makeCall(e){const t=le.get("isCalling"),s=le.get("selectOutNumber")||"";if(t)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));le.updateIsCalling(!0),le.updateDirection(A.DirectionEnum.OUTGOING),Os.__internalSend({type:A.WebsocketTypeEnum.OUT_CALL,data:{customer_phone:e,caller:s}})}async rejectOutCall(){const{isCalling:e}=le.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const t=ce.sessionId;Os.__internalSend({type:A.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:t}})}async hangup(){if(!le.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=ce.sessionId;Os.__internalSend({type:A.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:e}})}mute(){this.roleMute();const e=le.get("actionConfigs"),t=le.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:"当前状态请勿调用静音"}));Os.__internalSend({type:A.WebsocketTypeEnum.MUTE,data:{session_id:s}})}unmute(){this.roleMute();const e=le.get("actionConfigs"),t=le.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:"当前状态请勿调用静音"}));Os.__internalSend({type:A.WebsocketTypeEnum.UNMUTE,data:{session_id:s}})}consultTransfer(){this.roleMute();const e=le.get("consultIsAnswer"),t=ce.sessionId;if(!le.get("actionConfigs").includes("consult_transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询转移"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));Os.__internalSend({type:A.WebsocketTypeEnum.CONSULT_TRANSFER,data:{session_id:t}})}satisfactionEvaluation(){this.roleMute();const e=ce.sessionId;if(!le.get("actionConfigs").includes("satisfaction"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用满意度评价"}));Os.__internalSend({type:A.WebsocketTypeEnum.SATISFACTION_EVALUATION,data:{session_id:e}})}startConference(){this.roleMute();if(!le.get("actionConfigs").includes("conference"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用三方会议"}));const e=ce.sessionId;if(!le.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));Os.__internalSend({type:A.WebsocketTypeEnum.CONSULT_THREE_WAY,data:{session_id:e}})}consultRetrieve(){this.roleMute();if(!le.get("actionConfigs").includes("consult_retrieve"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取回通话"}));const e=ce.sessionId;if(!le.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));Os.__internalSend({type:A.WebsocketTypeEnum.CONSULT_RETURN_CALL,data:{session_id:e}})}async transferAgent(e){this.roleMute();if(!le.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));const{transferIsAnswer:t}=le.getState(),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));Os.__internalSend({type:A.WebsocketTypeEnum.TRANSFER,data:{session_id:s,transfer_type:0,transfer_dest:e}})}async transferOutline(e){this.roleMute();if(!le.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}=le.getState(),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));Os.__internalSend({type:A.WebsocketTypeEnum.TRANSFER,data:{session_id:s,transfer_type:2,transfer_dest:e}})}}A.default=class{#A=null;#e=new Us;#t;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#n();Xe.updateRttObject(A)},2e3),xs.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=le.subscribeKey("answerDevice",A=>{1===A?this.initWebRtc():this.#A=null})}async initWebRtc(){if(this.#A)return;const A=ce.agentInfo.sip_account_list.find(A=>1===A.device_type);if(A){const e=A.sip_register_addr;this.#A=new _e({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#o),await this.#A.start()}}async init({actionNodeParams:e,url:t,appKey:s,appSecret:i,agentNo:r,enableBrowserAlert:n}){try{const{viewHtmlElement:o,rttHTML:a}=e||{},V=t||"https://aicc.yescloudy.com";je=V,Le=s,We=i;const c=be(s,i);await this.#e._agentLogin(r);const{agent_no:h,current_answer_device:l,init_state:g,out_display_number:q}=ce.agentInfo;g===A.AgentStatus.IDLE?(le.updateActionConfigs(as),ce.stateObject={state:g,state_name:"空闲"}):g===A.AgentStatus.BUSY&&(le.updateActionConfigs(Vs),ce.stateObject={state:g,state_name:"忙碌"}),le.updateSelectOutNumber(q);let d="";const u=new URL(V).host;d=V.includes("https")?`wss://${u}`:`ws://${u}`,Os.getInstance(`${d}/ccs-ws/api/v1/ws/call/${h}?Authorization=${c}`),le.updateAnswerDevice(l),1===l&&await this.initWebRtc(),this.#t=new Ns(this.#A),e&&o&&(this.#i=!0,new vs({container:o,rttHTML:a,statusParams:{state:A.AgentStatus.IDLE,statusName:"空闲"}},this,this.#t)),ce.enableBrowserAlert=n,n&&xs.requestPermission(),Ve.emit(A.EventName.AGENT_INIT_STATUS,!0)}catch(A){this.#i&&Fs("初始化失败")}}#o=A=>{const{type:e,data:t}=A;Ve.emit(e,t)};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())}destroy(){this.destroyRtc(),clearInterval(this.#s),Os.__internalClose(),this.offAll(),this.#r?.(),this.#A=null,this.#e=null,this.#i=!1}async#n(){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),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))}}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))}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:n}=ce.agentInfo,{stateObject:o}=ce,a={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:n,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:a[Number(A)]})),stateObject:o}}},Object.defineProperty(A,"__esModule",{value:!0})});
|
|
923
|
+
`;ss(s,this.rttHTML)}}class xs{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){if("Notification"in window&&"granted"===Notification.permission){const s=new Notification(A,{body:e,tag:"xy-global-notification",renotify:!0});s.onclick=()=>{window.focus(),s.close(),t?.()},setTimeout(()=>s.close(),5e3)}}static async checkMediaPermissions(){try{return(await navigator.mediaDevices.enumerateDevices()).some(A=>"audioinput"===A.kind&&""!==A.label)}catch(A){return console.warn("无法检查设备权限:",A),!1}}}let Ks=null;class Os{constructor(A){this.url=A,this.ws=null,this.heartbeatWorker=null,this.reconnectDelay=3e3,this.manualClose=!1,this.apiClient=new Us,this.initWebSocket()}static getInstance(A){if(!Ks){if(!A)throw new Error("WebSocket 尚未初始化");Ks=new Os(A)}return Ks}stateIdleChange(){const{state:e}=ce.stateObject;e!==A.AgentStatus.IDLE&&this.apiClient._changeState({data:{...ce.stateBeforeChange}})}async getCustomerInfo(e){try{await this.apiClient._getInCallCrmDetail({data:{phone:e},success:e=>{const{contact_count:t,customer_name:s,phone:i,city:r,province:n}=e.data;Ve.emit(A.CallSipCallEvent.CUSTOMER_INFO,{customer_name:s||"未知客户",phone:i,city:r||"未知",province:n||"未知",contact_count:t||0})}})}catch(A){}}putAgentState(){ce.sessionId="";const{post_call_process_time:e}=ce.agentInfo,t=e||0;ce.autoStateTimer&&(clearTimeout(ce.autoStateTimer),ce.autoStateTimer=null),Ve.emit(A.CallSipCallEvent.CUSTOMER_INFO,void 0),t>0?ce.autoStateTimer=setTimeout(()=>{ce.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(s===A.WebsocketTypeEnum.OUT_CALL&&(0!==r?(le.reset(),Ve.emit(A.CallSipCallEvent.OUT_FAILED,n),setTimeout(()=>{Ve.emit(A.CallSipCallEvent.CUSTOMER_INFO,void 0)},500),this.stateIdleChange()):0===r&&Ve.emit(A.CallSipCallEvent.OUT_SUCCESS)),s===A.WebsocketTypeEnum.AGENT_STATE){ce.stateObject.state!==A.AgentStatus.IDLE&&ce.stateObject.state!==A.AgentStatus.BUSY||(ce.stateBeforeChange=ce.stateObject);const{state:e,state_name:t}=i;ce.stateObject={state:e,state_name:t},"振铃中"===t&&le.updateDisplayText(A.DisplayTextEnum.AGENT_RINGING),Ve.emit(A.CallSipCallEvent.AGENT_STATE,{state:e,state_name:t})}if(s===A.WebsocketTypeEnum.OUT_CALL_INCOMING_CALL&&(Ve.emit(A.CallSipCallEvent.OUT_INCOMING_CALL),ce.sessionId=i.session_id,le.updateActionConfigs(cs)),s===A.WebsocketTypeEnum.OUT_CALL_END&&(le.updateDisplayText(""),1===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.OUT_HANGUP,i),le.updateActionConfigs(as)):2===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(le.reset(),Ve.emit(A.CallSipCallEvent.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState(),le.updateActionConfigs(as)):2===i.device_type&&i.agent_no!==ce.agentInfo.agent_no?(le.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,i),le.updateActionConfigs(hs)):3===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.THREE_WAY_OUR_SIDE_HANGUP),le.updateActionConfigs(as)):4===i.device_type&&i.agent_no===ce.agentInfo.agent_no&&(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.TRANSFER_END),le.updateActionConfigs(as))),s===A.WebsocketTypeEnum.OUT_CALL_RINGING&&1===i.type&&(Ve.emit(A.CallSipCallEvent.OUT_RINGING,i),le.updateDisplayText(A.DisplayTextEnum.RINGING)),s===A.WebsocketTypeEnum.OUT_CALL_ANSWER&&(Ve.emit(A.CallSipCallEvent.OUT_OFF_ANSWER,i),le.updateOutCallIsAnswer(!0),le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateActionConfigs(hs)),s===A.WebsocketTypeEnum.CONSULT_RINGING&&(Ve.emit(A.CallSipCallEvent.CONSULT_RINGING),le.updateDisplayText(A.DisplayTextEnum.AGENT_RINGING),le.updateActionConfigs([])),s===A.WebsocketTypeEnum.CONSULT_ANSWER&&(Ve.emit(A.CallSipCallEvent.CONSULT_OFF_HOOK,i),le.updateConsultIsAnswer(!0),le.updateDisplayText(A.DisplayTextEnum.CONSULTING),le.updateActionConfigs(ls)),s===A.WebsocketTypeEnum.CONSULT_FAIL&&(Ve.emit(A.CallSipCallEvent.CONSULT_FAILED,{custom_reason:i.custom_reason}),le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateActionConfigs(hs)),s===A.WebsocketTypeEnum.CONSULT_CALL_IN&&(Ve.emit(A.CallSipCallEvent.CONSULT_INCOMING,i),le.updateIsCalling(!0),le.updateDirection(A.DirectionEnum.CONSULT),le.updateDisplayText(A.DisplayTextEnum.CONSULT_CALL_IN),le.updateActionConfigs(ds),ce.enableBrowserAlert&&xs.show("📞 咨询来电",`坐席 [${i.agent_name}] 正在咨询...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{agent_mane:i.agent_name})})),s===A.WebsocketTypeEnum.CONSULT_CALL_IN_SUCCESS&&(ce.sessionId=i.session_id,Ve.emit(A.CallSipCallEvent.CONSULT_CALL_IN_SUCCESS),le.updateConsultIsAnswer(!0),le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateActionConfigs(gs)),s===A.WebsocketTypeEnum.CONSULT_RETURN_CALL_SUCCESS&&(Ve.emit(A.CallSipCallEvent.CONSULT_RETURN_CALL_SUCCESS),le.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,i),le.updateActionConfigs(hs)),s===A.WebsocketTypeEnum.MUTE&&(0===r?(le.updateIsMuted(!0),Ve.emit(A.CallSipCallEvent.MUTE_SUCCESS),le.updateDisplayText(A.DisplayTextEnum.MUTING)):Ve.emit(A.CallSipCallEvent.MUTE_FAILED,n)),s===A.WebsocketTypeEnum.UNMUTE&&(0===r?(le.updateIsMuted(!1),Ve.emit(A.CallSipCallEvent.UNMUTE_SUCCESS),le.updateDisplayText(A.DisplayTextEnum.CALLING)):Ve.emit(A.CallSipCallEvent.UNMUTE_FAILED,n)),s===A.WebsocketTypeEnum.CALL_HOLD&&(0===r?(le.updateIsHold(!0),le.updateDisplayText(A.DisplayTextEnum.HOLDING),Ve.emit(A.CallSipCallEvent.HOLD_SUCCESS)):Ve.emit(A.CallSipCallEvent.HOLD_FAILED,n)),s===A.WebsocketTypeEnum.CALL_UNHOLD&&(0===r?(le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateIsHold(!1),Ve.emit(A.CallSipCallEvent.UNHOLD_SUCCESS)):Ve.emit(A.CallSipCallEvent.UNHOLD_FAILED,n)),s===A.WebsocketTypeEnum.CONSULT_TRANSFER&&(0===r?Ve.emit(A.CallSipCallEvent.CONSULT_TRANSFER_SUCCESS):Ve.emit(A.CallSipCallEvent.CONSULT_TRANSFER_FAILED,n)),s===A.WebsocketTypeEnum.CONSULT_TRANSFER_FAILED&&Ve.emit(A.CallSipCallEvent.CONSULT_TRANSFER_FAILED,i.status),s===A.WebsocketTypeEnum.CONSULT_TRANSFER_OFF_HOOK&&(le.updateDirection(A.DirectionEnum.INCOMING),le.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEvent.CONSULT_TRANSFER_OFF_HOOK),le.updateActionConfigs(us),le.updateIncomingIsAnswer(!0),le.updateConsultIsAnswer(!1)),s===A.WebsocketTypeEnum.INCOMING_CALL&&(ce.sessionId=i.session_id,le.updateIsCalling(!0),le.updateDirection(A.DirectionEnum.INCOMING),le.updateDisplayText(A.DisplayTextEnum.INCOMING_CALL),Ve.emit(A.CallSipCallEvent.INCOMING_CALL,{customer_phone:i.customer_phone}),le.updateActionConfigs(ds),ce.enableBrowserAlert&&xs.show("📞 客户来电",`客户 [${i.customer_phone}] 正在呼入...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{customer_phone:i.customer_phone})})),s===A.WebsocketTypeEnum.INCOMING_CALL_OFF_HOOK&&(le.updateIncomingIsAnswer(!0),Ve.emit(A.CallSipCallEvent.INCOMING_CALL_OFF_HOOK),le.updateActionConfigs(us),le.updateDisplayText(A.DisplayTextEnum.CALLING)),s===A.WebsocketTypeEnum.INCOMING_CALL_END&&(le.updateDisplayText(""),1===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.INCOMING_CALL_END),le.updateActionConfigs(as)):2===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(le.reset(),Ve.emit(A.CallSipCallEvent.OUR_SIDE_CONSULT_HANGUP,i),this.putAgentState(),le.updateActionConfigs(as)):2===i.device_type&&i.agent_no!==ce.agentInfo.agent_no?(le.updateDisplayText(A.DisplayTextEnum.CALLING),Ve.emit(A.CallSipCallEvent.OTHER_SIDE_CONSULT_HANGUP,i),le.updateActionConfigs(hs)):3===i.device_type&&i.agent_no===ce.agentInfo.agent_no?(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.THREE_WAY_OUR_SIDE_HANGUP),le.updateActionConfigs(as)):4===i.device_type&&i.agent_no===ce.agentInfo.agent_no&&(this.putAgentState(),le.reset(),Ve.emit(A.CallSipCallEvent.TRANSFER_END),le.updateActionConfigs(as))),s===A.WebsocketTypeEnum.SATISFACTION_EVALUATION&&(0===r?Ve.emit(A.CallSipCallEvent.SATISFACTION_EVALUATION_SUCCESS):Ve.emit(A.CallSipCallEvent.SATISFACTION_EVALUATION_FAILED,n)),s===A.WebsocketTypeEnum.CONSULT_THREE_WAY&&(0!==r?Ve.emit(A.CallSipCallEvent.CONSULT_THREE_WAY_FAILED,n):0===r&&le.updateIsMeeting(!0)),s===A.WebsocketTypeEnum.CONSULT_THREE_WAY_RESULT&&("success"===i.status?(le.updateDirection(A.DirectionEnum.MEETING),le.updateDisplayText(A.DisplayTextEnum.MEETING),le.updateActionConfigs(qs),Ve.emit(A.CallSipCallEvent.CONSULT_THREE_WAY_SUCCESS)):(Ve.emit(A.CallSipCallEvent.CONSULT_THREE_WAY_FAILED,{conf_name:i.conf_name}),le.updateIsMeeting(!1))),s===A.WebsocketTypeEnum.TRANSFER_INCOMING_CALL&&(i.agent_no===ce.agentInfo.agent_no?(le.updateDisplayText(A.DisplayTextEnum.TRANSFERRING),Ve.emit(A.CallSipCallEvent.TRANSFER_PROGRESS),le.updateActionConfigs([]),le.updateTransferIsAnswer(!0)):(Ve.emit(A.CallSipCallEvent.TRANSFER_INCOMING_CALL,i),le.updateIsCalling(!0),le.updateDirection(A.DirectionEnum.TRANSFER),le.updateDisplayText(A.DisplayTextEnum.TRANSFER_INCOMING_CALL),le.updateActionConfigs(ds),ce.enableBrowserAlert&&xs.show("📞 转接来电",`坐席 [${i.agent_no}] 正在转接...`,()=>{Ve.emit(A.EventName.NOTIFICATION_CLICK,{agent_mane:i.agent_no})}))),s===A.WebsocketTypeEnum.TRANSFER_OFF_HOOK&&(ce.sessionId=i.session_id,Ve.emit(A.CallSipCallEvent.TRANSFER_OFF_HOOK),le.updateTransferIsAnswer(!0),le.updateDisplayText(A.DisplayTextEnum.CALLING),le.updateActionConfigs(us)),s===A.WebsocketTypeEnum.TRANSFER_FAILED&&"failed"===i.status){Ve.emit(A.CallSipCallEvent.TRANSFER_FAILED,"未知原因");const e=le.get("direction");e===A.DirectionEnum.OUTGOING?le.updateActionConfigs(hs):e===A.DirectionEnum.INCOMING&&le.updateActionConfigs(us)}},this.ws.onclose=()=>{this.stopHeartbeat(),this.manualClose||setTimeout(()=>this.initWebSocket(),this.reconnectDelay)},this.ws.onerror=()=>{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 }, 14000);\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=()=>{this.sendMessage({type:0})},this.heartbeatWorker.postMessage("start")}stopHeartbeat(){this.heartbeatWorker&&(this.heartbeatWorker.postMessage("stop"),this.heartbeatWorker.terminate(),this.heartbeatWorker=null)}sendMessage(A){this.ws?.readyState===WebSocket.OPEN?(100===A.type&&this.getCustomerInfo(A.data.customer_phone),this.ws.send(JSON.stringify(A))):console.warn("WebSocket 未连接,消息未发送")}close(){this.manualClose=!0,this.stopHeartbeat(),this.ws?.close()}static __internalClose(){Ks&&(Ks.close(),Ks=null)}static __internalSend(A){if(!Ks)throw new Error("WebSocket 尚未初始化");Ks.sendMessage(A)}}class Ns{constructor(A){this.sipClient=null,this.sipClient=A}roleMute(){const A=le.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=le.get("isHold"),{sessionId:t}=ce;if(!t)return;if(!le.get("actionConfigs").includes("hold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿保持"}));if(e)throw new Error(JSON.stringify({code:1,msg:"当前已处于保持状态"}));Os.__internalSend({type:A.WebsocketTypeEnum.CALL_HOLD,data:{session_id:t}})}unholdCall(){this.roleMute();const{isHold:e}=le.getState(),{sessionId:t}=ce;if(!le.get("actionConfigs").includes("unhold"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取消保持"}));if(t){if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于保持状态"}));Os.__internalSend({type:A.WebsocketTypeEnum.CALL_UNHOLD,data:{session_id:t}})}}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(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));if(!le.get("actionConfigs").includes("reject"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用拒接"}));const{isCalling:e,direction:t,outCallIsAnswer:s}=le.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));s||(t===A.DirectionEnum.INCOMING?this.rejectInCall():t===A.DirectionEnum.OUTGOING&&this.rejectOutCall())}async consultCall(e){this.roleMute();const{isCalling:t,outCallIsAnswer:s,consultIsAnswer:i,incomingIsAnswer:r}=le.getState(),n=ce.sessionId;if(!le.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||r))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));if(!n)throw new Error(JSON.stringify({code:1,msg:"sessionId不存在"}));Os.__internalSend({type:A.WebsocketTypeEnum.CONSULT_REQUEST,data:{session_id:n,consultation_agent_no:e}})}async answerCall(){if(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));await this.sipClient.answerCall()}async rejectInCall(){if(1!==le.get("answerDevice"))throw new Error(JSON.stringify({code:1,msg:"当前设备不支持此功能"}));const{isCalling:A}=le.getState();if(!A)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));await this.sipClient.rejectInCall()}async makeCall(e){const t=le.get("isCalling"),s=le.get("selectOutNumber")||"";if(t)throw new Error(JSON.stringify({code:1,msg:"正在呼叫中,请勿重复点击"}));le.updateIsCalling(!0),le.updateDirection(A.DirectionEnum.OUTGOING),Os.__internalSend({type:A.WebsocketTypeEnum.OUT_CALL,data:{customer_phone:e,caller:s}})}async rejectOutCall(){const{isCalling:e}=le.getState();if(!e)throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const t=ce.sessionId;Os.__internalSend({type:A.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:t}})}async hangup(){if(!le.get("isCalling"))throw new Error(JSON.stringify({code:1,msg:"当前没有通话"}));const e=ce.sessionId;Os.__internalSend({type:A.WebsocketTypeEnum.AGENT_HANGUP,data:{session_id:e}})}mute(){this.roleMute();const e=le.get("actionConfigs"),t=le.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:"当前状态请勿调用静音"}));Os.__internalSend({type:A.WebsocketTypeEnum.MUTE,data:{session_id:s}})}unmute(){this.roleMute();const e=le.get("actionConfigs"),t=le.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:"当前状态请勿调用静音"}));Os.__internalSend({type:A.WebsocketTypeEnum.UNMUTE,data:{session_id:s}})}consultTransfer(){this.roleMute();const e=le.get("consultIsAnswer"),t=ce.sessionId;if(!le.get("actionConfigs").includes("consult_transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用咨询转移"}));if(!e)throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));Os.__internalSend({type:A.WebsocketTypeEnum.CONSULT_TRANSFER,data:{session_id:t}})}satisfactionEvaluation(){this.roleMute();const e=ce.sessionId;if(!le.get("actionConfigs").includes("satisfaction"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用满意度评价"}));Os.__internalSend({type:A.WebsocketTypeEnum.SATISFACTION_EVALUATION,data:{session_id:e}})}startConference(){this.roleMute();if(!le.get("actionConfigs").includes("conference"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿调用三方会议"}));const e=ce.sessionId;if(!le.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));Os.__internalSend({type:A.WebsocketTypeEnum.CONSULT_THREE_WAY,data:{session_id:e}})}consultRetrieve(){this.roleMute();if(!le.get("actionConfigs").includes("consult_retrieve"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿取回通话"}));const e=ce.sessionId;if(!le.get("consultIsAnswer"))throw new Error(JSON.stringify({code:1,msg:"当前未处于咨询中"}));Os.__internalSend({type:A.WebsocketTypeEnum.CONSULT_RETURN_CALL,data:{session_id:e}})}async transferAgent(e){this.roleMute();if(!le.get("actionConfigs").includes("transfer"))throw new Error(JSON.stringify({code:1,msg:"当前状态请勿转接"}));const{transferIsAnswer:t}=le.getState(),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));Os.__internalSend({type:A.WebsocketTypeEnum.TRANSFER,data:{session_id:s,transfer_type:0,transfer_dest:e}})}async transferOutline(e){this.roleMute();if(!le.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}=le.getState(),s=ce.sessionId;if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));if(t)throw new Error(JSON.stringify({code:1,msg:"当前正在转接"}));Os.__internalSend({type:A.WebsocketTypeEnum.TRANSFER,data:{session_id:s,transfer_type:2,transfer_dest:e}})}}A.default=class{#A=null;#e=new Us;#t;#s=null;#i=!1;#r;constructor(){clearInterval(this.#s),this.#s=setInterval(async()=>{const A=await this.#n();Xe.updateRttObject(A)},2e3),xs.requestMediaPermissions(),window.addEventListener("beforeunload",()=>{this.destroy()}),this.#r=le.subscribeKey("answerDevice",A=>{1===A?this.initWebRtc():this.#A=null})}async initWebRtc(){if(this.#A)return;const A=ce.agentInfo.sip_account_list.find(A=>1===A.device_type);if(A){const e=A.sip_register_addr;this.#A=new _e({server:e.split(":")[0],user:A.sip_account,password:A.sip_password,webSocket:`wss://${e}`,callTimeout:3e4},this.#o),await this.#A.start()}}async init({actionNodeParams:e,url:t,appKey:s,appSecret:i,agentNo:r,enableBrowserAlert:n}){try{const{viewHtmlElement:o,rttHTML:a}=e||{},V=t||"https://aicc.yescloudy.com";je=V,Le=s,We=i;const c=be(s,i);await this.#e._agentLogin(r);const{agent_no:h,current_answer_device:l,init_state:g,out_display_number:q}=ce.agentInfo;g===A.AgentStatus.IDLE?(le.updateActionConfigs(as),ce.stateObject={state:g,state_name:"空闲"}):g===A.AgentStatus.BUSY&&(le.updateActionConfigs(Vs),ce.stateObject={state:g,state_name:"忙碌"}),le.updateSelectOutNumber(q);let d="";const u=new URL(V).host;d=V.includes("https")?`wss://${u}`:`ws://${u}`,Os.getInstance(`${d}/ccs-ws/api/v1/ws/call/${h}?Authorization=${c}`),le.updateAnswerDevice(l),1===l&&await this.initWebRtc(),this.#t=new Ns(this.#A),e&&o&&(this.#i=!0,new vs({container:o,rttHTML:a,statusParams:{state:A.AgentStatus.IDLE,statusName:"空闲"}},this,this.#t)),ce.enableBrowserAlert=n,n&&xs.requestPermission(),Ve.emit(A.EventName.AGENT_INIT_STATUS,!0)}catch(A){this.#i&&Fs("初始化失败")}}#o=A=>{const{type:e,data:t}=A;Ve.emit(e,t)};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())}destroy(){this.destroyRtc(),clearInterval(this.#s),Os.__internalClose(),this.offAll(),this.#r?.(),this.#A=null,this.#e=null,this.#i=!1}async#n(){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),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))}}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))}}getAgentData(){const{agent_no:A,agent_name:e,answer_devices:t,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:n}=ce.agentInfo,{stateObject:o}=ce,a={1:"软电话",2:"手机模式",3:"SIP话机"};return{agent_no:A,agent_name:e,init_state:s,default_device:i,out_display_data:r,out_display_select_switch:n,answer_devices:(t||"").split(",").map(A=>({value:Number(A),label:a[Number(A)]})),stateObject:o}}},Object.defineProperty(A,"__esModule",{value:!0})});
|