/** * 修改 心跳开始结束的时机;20181212 * 签入后心跳开始;签出后心跳结束; * 增加心跳 false 处理(签出) */ import { Message, MessageBox, Switch } from 'element-ui' import store from '@/store' import router from '@/router' import { Teljournal } from '@/api/commonAPI' let ws // websocket 实例 let cls = 0 let lockReconnect = false // 避免重复连接 let calldDirection = 0 // 呼入 let websocktTimer // 定时器 let wsUrl = null // const wsUrl = 'ws://' + process.env.SOCKET_IP + ':' + process.env.SOCKET_PORT // 创建scoket连接 export function createWebSocket() { wsUrl = 'ws://' + store.getters.serverConfig.SOCKET_IP + ':' + store.getters.serverConfig.SOCKET_PORT // 请求地址 try { if ('WebSocket' in window) { ws = new WebSocket(wsUrl) // 创建一个websocket实例 init() } else { Message.error('当前浏览器不支持Websocket!') } } catch (e) { reconnect() } } // 连接 function init() { ws.onopen = function() { // console.groupCollapsed(`telWebsocket:`) console.log(new Date() + ' telWebsocket ' + '建立连接:' + wsUrl) // signIn() // 修改store 中连接状态 store.dispatch('ConnectWs', true) // 修改 store 中telwebsocket的数据 store.dispatch('ChangeTelWSMsg', { wsUrl: wsUrl, operationType: '建立连接' }) if (Number(window.sessionStorage.getItem('storageSeatState'))) { signIn() } if (Number(window.sessionStorage.getItem('telIsLogin'))) { // heartCheck.reset().start() // heartCheck.sendHeart() } } // 接收到消息的回调方法 ws.onmessage = function(evt) { // 如果获取到消息,心跳检测重置 // 拿到任何消息都说明当前连接是正常的 // heartCheck.reset().start() console.log( '%c' + new Date() + '%c receive%c telWebsocket %ctype:' + JSON.parse(evt.data)[0].Type + '%c ' + evt.data, 'color: #111', 'color: #67C23A', 'color: #111', 'color: #67C23A', 'color: #111' ) dealMsg(JSON.parse(evt.data)[0]) // 修改 store 中telwebsocket的数据 const telWSData = JSON.parse(evt.data) telWSData.operationType = '接收' store.dispatch('ChangeTelWSMsg', telWSData) } // 连接关闭的回调方法 ws.onclose = function(evt) { if (cls === 0) { cls = 1 console.log('telWebsocket连接关闭') // console.groupEnd() // 修改store 中连接状态 store.dispatch('ConnectWs', false) store.dispatch('ChangeLineState', 1) // 修改 store 中telwebsocket的数据 store.dispatch('ChangeTelWSMsg', { wsUrl: wsUrl, operationType: '连接关闭' }) reconnect() } } // 连接发生错误的回调方法 ws.onerror = function(evt) { // 产生异常 // Message({ // dangerouslyUseHTMLString: true, // message: '
telWebsocket连接出现异常!
', // offset: 400, // center: true, // type: 'error', // duration: 2 * 1000 // }) // console.warn('telWebsocket连接出现异常!') // 修改 store 中telwebsocket的数据 store.dispatch('ChangeTelWSMsg', { wsUrl: wsUrl, operationType: '连接异常' }) if (ws == null || ws.readyState !== ws.OPEN) { console.log(new Date() + 'telWebsocket开始重连') // 修改 store 中telwebsocket的数据 store.dispatch('ChangeTelWSMsg', { wsUrl: wsUrl, operationType: '开始重连' }) reconnect() } } } /** * 重新连接 */ function reconnect() { if (lockReconnect) return lockReconnect = true // 没连接上会一直重连,设置延迟避免请求过多 websocktTimer && clearTimeout(websocktTimer) websocktTimer = setTimeout(function() { console.log(new Date() + ' ' + 'telWebsocket重连中……') // 修改 store 中telwebsocket的数据 store.dispatch('ChangeTelWSMsg', { wsUrl: wsUrl, operationType: '重连中……' }) createWebSocket() lockReconnect = false }, 2000) } /** * 发送 * @ socketDatas 发送的数据 type {} */ export function Send(scoketDatas) { if (ws.readyState !== ws.OPEN) { reconnect() } if (ws.readyState === ws.OPEN) { console.log( '%c' + new Date() + '%c send %c telWebsocket ' + JSON.stringify(scoketDatas), 'color: #111', 'color: #409EFF', 'color: #111' ) ws.send(JSON.stringify(scoketDatas)) scoketDatas.operationType = '发送' // 修改 store 中telwebsocket的数据 store.dispatch('ChangeTelWSMsg', scoketDatas) } } // 心跳检测 const heartCheck = { timeout: 20000, // 5秒 timeoutObj: null, serverTimeoutObj: null, reset: function() { clearTimeout(this.timeoutObj) clearTimeout(this.serverTimeoutObj) return this }, start: function() { const _self = this this.timeoutObj = setTimeout(function() { // 这里发送一个心跳,后端收到后,返回一个心跳消息, // onmessage拿到返回的心跳就说明连接正常 _self.sendHeart() _self.aa() }, this.timeout) }, sendHeart: function() { const scoketDatas = { Type: 'Heart', Result: true, AgentID: store.getters.usercode, // 工号 AgentExten: store.getters.extension, // 分机号 // AgentGroup: 1 // 坐席组id AgentGroup: store.getters.groupcode // 坐席组id } Send(scoketDatas) } } // 迁入 function signIn() { // if(!this.groupcode){ // this.$message.error('分机号不存在') // return false // } // if (!store.getters.extension) { // this.$confirm('如果您想进行话务操作,请重新登录并且输入分机号, 是否重新登录?', '提示', { // confirmButtonText: '是', // cancelButtonText: '否', // type: 'warning' // }).then(() => { // this.$store.dispatch('FedLogOut').then(() => { // location.reload() // 为了重新实例化vue-router对象 避免bug // }) // }).catch(() => { // }) // return // } const scoketDatas = { Type: 'Login', AgentID: store.getters.usercode, AgentExten: store.getters.extension, // AgentGroup: window.localStorage.getItem("groupCode"), // 坐席组id window.localStorage.getItem('groupCode') AgentGroup: '364', AgentType: '0', DisposeTime: '0' // 话后处理时长设置,0代表一致话后处理,除非发送置闲 (按照历史习惯,字符串形式) } Send(scoketDatas) } /** * 处理接收的消息 * @ msgData 接收的数据 type {} */ function dealMsg(msgData) { if (msgData) { const rlt = msgData.Result if (rlt === true) { switch (msgData.Type.toLowerCase()) { case 'login': // 签入 LoginBack() break case 'logout': // 签出 LogoutBack() break case 'dropcall': // 挂断 DropCallBack() break case 'makecall': // 外呼 MakeCallBack(msgData) break case 'setstate': // 置忙 置闲 SetState(msgData) break // 置忙置闲 case 'meeting': // 会议 MeetingBack(msgData) break case 'meetingtakeback': MeetingTakeBackFun(msgData) break // 多方通话回签 case 'transfer': // 转移 TransferBack() break // case 'consult': // 协商呼叫 // ConsultBack() // break case 'hold': // 保持 HoldBack(msgData) break case 'retrieve': // 接回 RetrieveBack() break case 'incoming': // 来电 IncomingBack(msgData) break case 'linestateagent': // 线路状态 LineStateAgentBack(msgData) break case 'agentstateagent': // 线路状态 agentstateagentBack(msgData) case 'agentstate': // 线路状态 updateSeatMonitorlists(msgData) break case 'getagentlist': getAgentList(msgData) break case 'callid': getCallid(msgData) break } } else if (rlt === false) { var texs = '' // const errCode = msgData.Error % 10000 if (msgData.Type.toLowerCase() === 'meeting') { window.localStorage.setItem('meetingTransfer', 0) if (window.localStorage.getItem('meetingType') == '转接') { texs = '转接失败' } if (window.localStorage.getItem('meetingType') == '多方通话') { texs = '多方通话失败' } } else if (msgData.Type.toLowerCase() === 'transfer') { texs = '转接失败' } else if (msgData.Type.toLowerCase() === 'makecall') { texs = '外呼失败' } else { texs = msgData.Type } Message({ dangerouslyUseHTMLString: true, message: '
' + texs + '
', offset: 400, center: true, type: 'error', duration: 2 * 1000 }) } else { if (msgData.Type.toLowerCase() === 'linestateagent') { LineStateAgentBack(msgData) } else if (msgData.Type.toLowerCase() === 'monitor') { updateSeatMonitorlists(msgData) } else if (msgData.Type.toLowerCase() === 'waitcount') { console.log(msgData.Type) store.dispatch('ChangeWaitcountNumber', msgData.WaitCount) } else { // Message.error(`${rlt} !`) Message({ dangerouslyUseHTMLString: true, message: '
' + rlt + '
', offset: 400, center: true, type: 'error', duration: 2 * 1000 }) } } } } function updateSeatMonitorlists(msgData) { store.dispatch('ChangeMonitor', true) // 修改监听操作的返回值 store.dispatch('ChangeMonitorstate', msgData.State) // 监控状态 store.dispatch('ChangeMonitoragent', msgData.AgentID) // 监控坐席 store.dispatch('ChangeMonitorexten', msgData.ExtenID) // 监控坐席 } function getCallid(msgData) { window.localStorage.setItem('callid', msgData.CurrID) console.log(window.localStorage.getItem('callid'), '11') } // 签入 function LoginBack(reState) { // 心跳检测开始 // heartCheck.reset().start() cls = 0 store.dispatch('LoginWs') store.dispatch('ChangeTopRightState', ['空闲', true]) // 弹出任务信息 store.dispatch('ChangeTask', true) let scoketDatas = {} if (Number(window.sessionStorage.getItem('storageSeatState')) === 2) { scoketDatas = { Type: 'SayFree', AgentID: window.localStorage.getItem('storageUsercode'), AgentExten: window.localStorage.getItem('ext') } Send(scoketDatas) } else if (Number(window.sessionStorage.getItem('storageSeatState')) === 5) { scoketDatas = { Type: 'SayBusy', AgentID: window.localStorage.getItem('storageUsercode'), AgentExten: window.localStorage.getItem('ext') } Send(scoketDatas) } else { window.sessionStorage.setItem('storageSeatState', 2) } } // 签出 function LogoutBack(reState) { // 心跳检测关闭 // heartCheck.reset() store.dispatch('LogoutWs') store.dispatch('ChangeTopRightState', ['已签出', false]) // 重置初始化状态 resetInitState() window.sessionStorage.setItem('storageSeatState', 0) getOperatonTime('2') console.log('签出2') } // 重置初始化状态 function resetInitState() { store.dispatch('ChangeSeatState', 2) // 坐席状态(空闲) store.dispatch('ChangeLineState', 1) // 线路状态(空闲) store.dispatch('ChangeCallNum', '') // 顶部电话号码('') store.dispatch('ChangeCallType', 'MakeCall') // 发送的通话类型(默认是外呼) store.dispatch('ChangeTask', false) // 外呼任务信息是否显示 store.dispatch('ChangeTaskFirst', true) // 外呼任务信息是否是第一次弹出 } /** * 置忙 置闲 * sayOption (点击置忙置闲后的返回值) * */ function SetState(sayOption) { if (sayOption.State === 5) { store.dispatch('ChangeSeatState', 5) window.sessionStorage.setItem('storageSeatState', 5) window.sessionStorage.setItem('isBusyOrFree', 0)// 0是置忙1是置闲 store.dispatch('ChangeTopRightState', ['忙碌', false]) getOperatonTime('3') console.log('置忙3') } else if (sayOption.State === 2) { store.dispatch('ChangeSeatState', 2) window.sessionStorage.setItem('storageSeatState', 2) window.sessionStorage.setItem('isBusyOrFree', 1)// 0是置忙1是置闲 store.dispatch('ChangeTopRightState', ['空闲', true]) getOperatonTime('4') console.log('置闲4') } } /** * 置忙 * sayOption (点击置忙置闲后的返回值) * */ function SayBusyBack(sayOption) { window.sessionStorage.setItem('isBusyOrFree', 0)// 0是置忙1是置闲 store.dispatch('ChangeSeatState', 5) if (sayOption.Type === 'SayBusy') { store.dispatch('ChangeTopRightState', ['忙碌', false]) } } /** * 置闲 * sayOption (点击置忙置闲后的返回值) * */ function SayFreeBack(sayOption) { window.sessionStorage.setItem('isBusyOrFree', 1)// 0是置忙1是置闲 store.dispatch('ChangeSeatState', 2) if (sayOption.Type === 'SayFree') { store.dispatch('ChangeTopRightState', ['空闲', true]) } } // 坐席状态变化 function agentstateagentBack(msgData) { switch (msgData.AgentState + '') { case '0': store.dispatch('ChangeTopRightState', ['离线', true]) break // 离线 case '1': store.dispatch('ChangeTopRightState', ['登录中', true]) break // 登录中 case '2': store.dispatch('ChangeTopRightState', ['空闲', true]) break // 空闲 case '3': store.dispatch('ChangeTopRightState', ['通话中', true]) break // 通话中 case '4': store.dispatch('ChangeTopRightState', ['话后处理中', true]) break // 话后处理中 case '5': store.dispatch('ChangeTopRightState', ['忙碌', true]) break // 小休 case '6': store.dispatch('ChangeTopRightState', ['振铃', true]) break // 被请求 case '7': store.dispatch('ChangeTopRightState', ['注销', true]) break // 注销 } } // 线路状态通知 function LineStateAgentBack(linedata) { // 0分机不可用,1空闲,2摘机等待拨号,3正在拨号,4呼出振铃,5来电振铃,6通话中,7播放忙音中,8移除IP分机,10通话保持中 // store.dispatch('ChangeTopRightState', [linedata.Result, true]) switch (linedata.State) { // case '空闲': case 1: store.dispatch('ChangeLineState', 1) store.dispatch('ChangeCallNum', '') // 顶部电话号码('') store.dispatch('ChangeTopRightState', ['1111', true]) break // case '摘机等待拨号': case 2: store.dispatch('ChangeLineState', 2) store.dispatch('ChangeTopRightState', ['摘机等待拨号', true]) break // case '正在拨号': case 3: store.dispatch('ChangeLineState', 3) store.dispatch('ChangeTopRightState', ['正在拨号', true]) break // case '呼出振铃': case 4: store.dispatch('ChangeLineState', 4) store.dispatch('ChangeTopRightState', ['呼出振铃', true]) break // case '来电振铃': case 5: store.dispatch('ChangeLineState', 5) store.dispatch('ChangeTopRightState', ['来电振铃', true]) break // case '通话中': case 6: store.dispatch('ChangeLineState', 6) store.dispatch('ChangeTopRightState', ['通话中', true]) break // case '播放忙音中': case 7: store.dispatch('ChangeLineState', 7) store.dispatch('ChangeTopRightState', ['播放忙音中', true]) break // case '移除IP分机': case 8: store.dispatch('ChangeLineState', 8) store.dispatch('ChangeTopRightState', ['移除IP分机', true]) break // case '通话保持中': case 10: store.dispatch('ChangeLineState', 10) store.dispatch('ChangeTopRightState', ['通话保持中', true]) break } } // 来电 function IncomingBack(inComingData) { const inComingCallId = inComingData.CallID let inComingNumber = inComingData.Number calldDirection = 1 store.dispatch('screenPopUpBoole', 1) if (inComingNumber.length > 11) { inComingNumber = inComingNumber.substr(1) // console.log(inComingNumber) } window.localStorage.setItem('callidSave', inComingData.CallID) // 用户的坐席组code router.push({ name: 'CallScreen', path: '/callScreen', fullPath: '/callScreen', params: { callid: inComingCallId, telInNumber: inComingNumber } }) store.dispatch('ChangeCallNum', inComingNumber) } // 挂断 function DropCallBack() { store.dispatch('ChangeCallNum', '') // 顶部电话号码('') store.dispatch('ChangeCallType', 'MakeCall') // 发送的通话类型(默认是外呼) store.dispatch('screenPopUpBoole', 0) // calldDirection if (calldDirection) { const scoketDatas = { Type: 'SayBusy', AgentID: window.localStorage.getItem('storageUsercode'), AgentExten: window.localStorage.getItem('ext') } Send(scoketDatas) setTimeout(() => { if (window.sessionStorage.getItem('isBusyOrFree') === '0') { const scoketDatas = { Type: 'SayFree', AgentID: window.localStorage.getItem('storageUsercode'), AgentExten: window.localStorage.getItem('ext') } Send(scoketDatas) } }, 60000) calldDirection = 0 } else { const scoketDatas = { Type: 'SayFree', AgentID: window.localStorage.getItem('storageUsercode'), AgentExten: window.localStorage.getItem('ext') } Send(scoketDatas) } // 当前在坐席监控中需要 更新坐席监控内坐席的状态 const curentViews = store.state.tagsView.visitedViews for (let i = 0, len = curentViews.length; i < len; i++) { if (curentViews[i].name === 'seatMonitor') { // updateSeatMonitorlists() return } } } // 转接 function TransferBack() { store.dispatch('ChangeCallNum', '') // 顶部电话号码('') store.dispatch('ChangeCallType', 'MakeCall') // 发送的通话类型(默认是外呼) } // 外呼 结果 弹出来电弹屏 function MakeCallBack(callBackData) { const inComingNumber = store.getters.telCallNum const inComingCallId = callBackData.CallID } // 多方通话 function MeetingBack() { store.dispatch('ChangeMeetingBackFlag', true) window.localStorage.setItem('meetingTransfer', 1) } // 多方通话回签 function MeetingTakeBackFun() { store.dispatch('ChangeMeetingBackFlag', false) } // 录音返回 function RecordPathBack() {} // 保持 function HoldBack(holdData) { if (holdData.Result === true) { store.dispatch('ChangeLineState', 10) } } // 接回 function RetrieveBack(RetrieveData) { // if (RetrieveData.Result === true) { // store.dispatch('ChangeLineState', 6) // } } // 更新坐席监控内坐席的状态 // function updateSeatMonitorlists (moitorData) { // console.log(moitorData) // // store.dispatch('ChangeMonitor', true) // 修改监听操作的返回值 // } // 获取当前在线坐席 function getAgentList(data) { store.dispatch('GetOnlineSeatList', data.AgentList) // 监控坐席 } function getOperatonTime(state) { const params = { state: state, token: localStorage.getItem('Admin-Token').split(' ')[1] } Teljournal(params) .then(response => {}) .catch(result => {}) }