足力健前端,vue版本

telWebsocket.js 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /**
  2. * 修改 心跳开始结束的时机;20181212
  3. * 签入后心跳开始;签出后心跳结束;
  4. * 增加心跳 false 处理(签出)
  5. */
  6. import { Message, MessageBox, Switch } from 'element-ui'
  7. import store from '@/store'
  8. import router from '@/router'
  9. let ws // websocket 实例
  10. let cls = 0
  11. let lockReconnect = false // 避免重复连接
  12. let websocktTimer // 定时器
  13. let wsUrl = null
  14. // const wsUrl = 'ws://' + process.env.SOCKET_IP + ':' + process.env.SOCKET_PORT
  15. // 创建scoket连接
  16. export function createWebSocket () {
  17. wsUrl = 'ws://' + store.getters.serverConfig.SOCKET_IP + ':' + store.getters.serverConfig.SOCKET_PORT
  18. try {
  19. if ('WebSocket' in window) {
  20. ws = new WebSocket(wsUrl)
  21. init()
  22. } else {
  23. Message.error('当前浏览器不支持Websocket!')
  24. }
  25. } catch (e) {
  26. reconnect()
  27. }
  28. }
  29. // 连接
  30. function init () {
  31. ws.onopen = function () {
  32. // console.groupCollapsed(`telWebsocket:`)
  33. console.log(new Date() + ' telWebsocket ' + '建立连接:' + wsUrl)
  34. // 修改store 中连接状态
  35. store.dispatch('ConnectWs', true)
  36. // 修改 store 中telwebsocket的数据
  37. store.dispatch('ChangeTelWSMsg', {
  38. 'wsUrl': wsUrl,
  39. 'operationType': '建立连接'
  40. })
  41. console.log(window.sessionStorage.getItem('telIsLogin'))
  42. if (Number(window.sessionStorage.getItem('telIsLogin'))) {
  43. // heartCheck.reset().start()
  44. // heartCheck.sendHeart()
  45. }
  46. }
  47. // 接收到消息的回调方法
  48. ws.onmessage = function (evt) {
  49. // 如果获取到消息,心跳检测重置
  50. // 拿到任何消息都说明当前连接是正常的
  51. // heartCheck.reset().start()
  52. console.log('%c' + new Date() + '%c receive%c telWebsocket %ctype:' + JSON.parse(evt.data).Type + '%c ' + evt.data, 'color: #111', 'color: #67C23A', 'color: #111', 'color: #67C23A', 'color: #111')
  53. dealMsg(JSON.parse(evt.data))
  54. // 修改 store 中telwebsocket的数据
  55. const telWSData = JSON.parse(evt.data)
  56. telWSData.operationType = '接收'
  57. store.dispatch('ChangeTelWSMsg', telWSData)
  58. }
  59. // 连接关闭的回调方法
  60. ws.onclose = function (evt) {
  61. if (cls === 0) {
  62. cls = 1
  63. console.log('telWebsocket连接关闭')
  64. // console.groupEnd()
  65. // 修改store 中连接状态
  66. store.dispatch('ConnectWs', false)
  67. store.dispatch('ChangeLineState', 1)
  68. // 修改 store 中telwebsocket的数据
  69. store.dispatch('ChangeTelWSMsg', {
  70. 'wsUrl': wsUrl,
  71. 'operationType': '连接关闭'
  72. })
  73. reconnect()
  74. }
  75. }
  76. // 连接发生错误的回调方法
  77. ws.onerror = function (evt) {
  78. // 产生异常
  79. console.warn('telWebsocket连接出现异常!')
  80. // 修改 store 中telwebsocket的数据
  81. store.dispatch('ChangeTelWSMsg', {
  82. 'wsUrl': wsUrl,
  83. 'operationType': '连接异常'
  84. })
  85. if (ws == null || ws.readyState !== ws.OPEN) {
  86. console.log(new Date() + 'telWebsocket开始重连')
  87. // 修改 store 中telwebsocket的数据
  88. store.dispatch('ChangeTelWSMsg', {
  89. 'wsUrl': wsUrl,
  90. 'operationType': '开始重连'
  91. })
  92. reconnect()
  93. }
  94. }
  95. }
  96. /**
  97. * 重新连接
  98. */
  99. function reconnect () {
  100. if (lockReconnect) return
  101. lockReconnect = true
  102. // 没连接上会一直重连,设置延迟避免请求过多
  103. websocktTimer && clearTimeout(websocktTimer)
  104. websocktTimer = setTimeout(function () {
  105. console.log(new Date() + ' ' + 'telWebsocket重连中……')
  106. // 修改 store 中telwebsocket的数据
  107. store.dispatch('ChangeTelWSMsg', {
  108. 'wsUrl': wsUrl,
  109. 'operationType': '重连中……'
  110. })
  111. createWebSocket()
  112. lockReconnect = false
  113. }, 2000)
  114. }
  115. /**
  116. * 发送
  117. * @ socketDatas 发送的数据 type {}
  118. */
  119. export function Send (scoketDatas) {
  120. if (ws.readyState !== ws.OPEN) {
  121. reconnect()
  122. }
  123. if (ws.readyState === ws.OPEN) {
  124. console.log('%c' + new Date() + '%c send %c telWebsocket ' + JSON.stringify(scoketDatas), 'color: #111', 'color: #409EFF', 'color: #111')
  125. ws.send(JSON.stringify(scoketDatas))
  126. scoketDatas.operationType = '发送'
  127. // 修改 store 中telwebsocket的数据
  128. store.dispatch('ChangeTelWSMsg', scoketDatas)
  129. }
  130. }
  131. // 心跳检测
  132. const heartCheck = {
  133. timeout: 20000, // 5秒
  134. timeoutObj: null,
  135. serverTimeoutObj: null,
  136. reset: function () {
  137. clearTimeout(this.timeoutObj)
  138. clearTimeout(this.serverTimeoutObj)
  139. return this
  140. },
  141. start: function () {
  142. const _self = this
  143. this.timeoutObj = setTimeout(function () {
  144. // 这里发送一个心跳,后端收到后,返回一个心跳消息,
  145. // onmessage拿到返回的心跳就说明连接正常
  146. _self.sendHeart()
  147. }, this.timeout)
  148. },
  149. sendHeart: function () {
  150. const scoketDatas = {
  151. 'Type': 'Heart',
  152. 'Result': true,
  153. 'AgentID': store.getters.usercode, // 工号
  154. 'AgentExten': store.getters.extension, // 分机号
  155. 'AgentGroup': store.getters.groupcode // 坐席组id
  156. }
  157. Send(scoketDatas)
  158. }
  159. }
  160. /**
  161. * 处理接收的消息
  162. * @ msgData 接收的数据 type {}
  163. */
  164. function dealMsg (msgData) {
  165. if (msgData) {
  166. const rlt = msgData.Result
  167. if (rlt === true) {
  168. switch (msgData.Type.toLowerCase()) {
  169. case 'login': // 签入
  170. LoginBack()
  171. break
  172. case 'logout': // 签出
  173. LogoutBack()
  174. break
  175. case 'dropcall': // 挂断
  176. DropCallBack()
  177. break
  178. case 'makecall': // 外呼
  179. MakeCallBack(msgData)
  180. break
  181. case 'saybusy': // 置忙
  182. SayBusyBack(msgData)
  183. break
  184. case 'sayfree': // 置闲
  185. SayFreeBack(msgData)
  186. break
  187. case 'meeting': // 会议
  188. MeetingBack()
  189. break
  190. case 'transfer': // 转移
  191. TransferBack()
  192. break
  193. // case 'consult': // 协商呼叫
  194. // ConsultBack()
  195. // break
  196. case 'hold': // 保持
  197. HoldBack(msgData)
  198. break
  199. case 'retrieve': // 接回
  200. RetrieveBack()
  201. break
  202. case 'incoming': // 来电
  203. IncomingBack(msgData)
  204. break
  205. }
  206. } else if (rlt === false) {
  207. const errCode = msgData.Error % 10000
  208. // console.error(`telWebsocket错误信息: ${errTips}(errorCode:${errCode})!`)
  209. } else {
  210. if (msgData.Type.toLowerCase() === 'linestate') {
  211. LineStateAgentBack(msgData)
  212. } else if (msgData.Type.toLowerCase() === 'monitor') {
  213. //console.log(msgData)
  214. updateSeatMonitorlists(msgData)
  215. } else {
  216. Message.error(`telWebsocket错误信息: ${rlt} !`)
  217. }
  218. // Message.error(`telWebsocket错误信息: ${rlt} !`)
  219. }
  220. }
  221. }
  222. function updateSeatMonitorlists (msgData) {
  223. store.dispatch('ChangeMonitor', true) // 修改监听操作的返回值
  224. store.dispatch('ChangeMonitorstate', msgData.Result) // 监控状态
  225. store.dispatch('ChangeMonitoragent', msgData.AgentID) // 监控坐席
  226. }
  227. // 签入
  228. function LoginBack (reState) {
  229. // 心跳检测开始
  230. // heartCheck.reset().start()
  231. cls = 0
  232. store.dispatch('LoginWs')
  233. store.dispatch('ChangeTopRightState', ['空闲', true])
  234. // 弹出任务信息
  235. store.dispatch('ChangeTask', true)
  236. }
  237. // 签出
  238. function LogoutBack (reState) {
  239. // 心跳检测关闭
  240. // heartCheck.reset()
  241. store.dispatch('LogoutWs')
  242. store.dispatch('ChangeTopRightState', ['已签出', false])
  243. // 重置初始化状态
  244. resetInitState()
  245. }
  246. // 重置初始化状态
  247. function resetInitState () {
  248. store.dispatch('ChangeSeatState', 2) // 坐席状态(空闲)
  249. store.dispatch('ChangeLineState', 1) // 线路状态(空闲)
  250. store.dispatch('ChangeCallNum', '') // 顶部电话号码('')
  251. store.dispatch('ChangeCallType', 'MakeCall') // 发送的通话类型(默认是外呼)
  252. store.dispatch('ChangeTask', false) // 外呼任务信息是否显示
  253. store.dispatch('ChangeTaskFirst', true) // 外呼任务信息是否是第一次弹出
  254. }
  255. /**
  256. * 置忙
  257. * sayOption (点击置忙置闲后的返回值)
  258. * */
  259. function SayBusyBack (sayOption) {
  260. store.dispatch('ChangeSeatState', 5)
  261. if (sayOption.Type === 'SayBusy') {
  262. console.log(sayOption.Type)
  263. store.dispatch('ChangeTopRightState', ['忙碌', false])
  264. }
  265. }
  266. /**
  267. * 置闲
  268. * sayOption (点击置忙置闲后的返回值)
  269. * */
  270. function SayFreeBack (sayOption) {
  271. store.dispatch('ChangeSeatState', 2)
  272. if (sayOption.Type === 'SayFree') {
  273. console.log(sayOption.Type)
  274. store.dispatch('ChangeTopRightState', ['空闲', true])
  275. }
  276. }
  277. // 线路状态通知
  278. function LineStateAgentBack (linedata) {
  279. // 0分机不可用,1空闲,2摘机等待拨号,3正在拨号,4呼出振铃,5来电振铃,6通话中,7播放忙音中,8移除IP分机,10通话保持中
  280. store.dispatch('ChangeTopRightState', [linedata.Result, true])
  281. switch (linedata.Result) {
  282. case '空闲':
  283. store.dispatch('ChangeLineState', 1)
  284. store.dispatch('ChangeCallNum', '') // 顶部电话号码('')
  285. break
  286. case '摘机等待拨号':
  287. store.dispatch('ChangeLineState', 2)
  288. break
  289. case '正在拨号':
  290. store.dispatch('ChangeLineState', 3)
  291. break
  292. case '呼出振铃':
  293. store.dispatch('ChangeLineState', 4)
  294. break
  295. case '来电振铃':
  296. store.dispatch('ChangeLineState', 5)
  297. break
  298. case '通话中':
  299. store.dispatch('ChangeLineState', 6)
  300. break
  301. case '播放忙音中':
  302. store.dispatch('ChangeLineState', 7)
  303. break
  304. case '移除IP分机':
  305. store.dispatch('ChangeLineState', 8)
  306. break
  307. case '通话保持中':
  308. store.dispatch('ChangeLineState', 10)
  309. break
  310. }
  311. }
  312. // 来电
  313. function IncomingBack (inComingData) {
  314. const inComingCallId = inComingData.CallID
  315. let inComingNumber = inComingData.Number
  316. // 组id和groupid一致是正常弹屏;不一致是预测外呼弹屏;
  317. if (inComingData.IncomintType === 1) {
  318. // 来电弹屏 TaskIcon 的值是坐席组id , query: {selected: "2"}
  319. inComingNumber = inComingData.Number
  320. //this.$router.push({path: '/backend/order'}); view.path = `/callScreen` view.fullPath = `/callScreen`
  321. router.push({ name: 'callScreen', path: '/callScreen', fullPath: '/callScreen', params: { callid: inComingCallId, telInNumber: inComingNumber } })
  322. // router.push({ name: 'callScreenHY', params: { callid: inComingCallId, telInNumber: inComingNumber }}) // 售后
  323. //router.push({ name: 'callScreen', params: { callid: inComingCallId, telInNumber: inComingNumber } })
  324. // router.push({ name: 'autoCallScreen', params: { callid: inComingCallId, telInNumber: inComingNumber }})
  325. // router.push({ path: '/callScreen', query: { callid: inComingCallId, telInNumber: inComingNumber }})
  326. } else if (inComingData.IncomintType === 2) {
  327. if (store.getters.telOutboundScreen) {
  328. inComingNumber = inComingData.CalleeNumber
  329. router.push({ name: 'clickCallScreen', params: { callid: inComingCallId, telInNumber: inComingNumber } })
  330. } else {
  331. store.dispatch('UpdateOutboundScreen', true)
  332. }
  333. // 自动外呼弹屏 TaskIcon值是任务id
  334. // router.push({ name: 'autoCallScreen', params: { callid: inComingCallId, telInNumber: inComingNumber, taskId: inComingData.TaskIcon }})
  335. }
  336. store.dispatch('ChangeCallNum', inComingNumber)
  337. }
  338. // 挂断
  339. function DropCallBack () {
  340. store.dispatch('ChangeCallNum', '') // 顶部电话号码('')
  341. store.dispatch('ChangeCallType', 'MakeCall') // 发送的通话类型(默认是外呼)
  342. // 当前在坐席监控中需要 更新坐席监控内坐席的状态
  343. const curentViews = store.state.tagsView.visitedViews
  344. for (let i = 0, len = curentViews.length; i < len; i++) {
  345. if (curentViews[i].name === 'seatMonitor') {
  346. // updateSeatMonitorlists()
  347. return
  348. }
  349. }
  350. }
  351. // 转接
  352. function TransferBack () {
  353. store.dispatch('ChangeCallNum', '') // 顶部电话号码('')
  354. store.dispatch('ChangeCallType', 'MakeCall') // 发送的通话类型(默认是外呼)
  355. }
  356. // 外呼 结果 弹出来电弹屏
  357. function MakeCallBack (callBackData) {
  358. const inComingNumber = store.getters.telCallNum
  359. const inComingCallId = callBackData.CallID
  360. // 点击外呼弹屏
  361. // router.push({ name: 'clickCallScreen', params: { callid: inComingCallId, telInNumber: inComingNumber } })
  362. // router.push({ name: 'callScreen', params: { callid: inComingCallId, telInNumber: inComingNumber } })
  363. }
  364. // 多方通话
  365. function MeetingBack () { }
  366. // 录音返回
  367. function RecordPathBack () { }
  368. // 保持
  369. function HoldBack (holdData) {
  370. if (holdData.Result === true) {
  371. store.dispatch('ChangeLineState', 10)
  372. }
  373. }
  374. // 接回
  375. function RetrieveBack (RetrieveData) {
  376. // if (RetrieveData.Result === true) {
  377. // store.dispatch('ChangeLineState', 6)
  378. // }
  379. }
  380. // 更新坐席监控内坐席的状态
  381. // function updateSeatMonitorlists (moitorData) {
  382. // console.log(moitorData)
  383. // // store.dispatch('ChangeMonitor', true) // 修改监听操作的返回值
  384. // }