new_chat.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. // +----------------------------------------------------------------------
  2. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  3. // +----------------------------------------------------------------------
  4. // | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
  5. // +----------------------------------------------------------------------
  6. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  7. // +----------------------------------------------------------------------
  8. // | Author: CRMEB Team <admin@crmeb.com>
  9. // +----------------------------------------------------------------------
  10. import $store from "@/store";
  11. import wechat from "@/libs/wechat";
  12. import {
  13. HTTP_REQUEST_URL,
  14. VUE_APP_WS_URL
  15. } from "@/config/app.js";
  16. import {
  17. getServerType
  18. } from '@/api/api.js';
  19. import {
  20. onNetworkStatusChange
  21. } from '@/libs/network.js';
  22. function wss(wsSocketUrl) {
  23. if (wsSocketUrl.indexOf('wss:') !== -1) {
  24. return wsSocketUrl;
  25. }
  26. // #ifdef H5
  27. let ishttps = document.location.protocol == 'https:';
  28. if (ishttps) {
  29. return wsSocketUrl.replace('ws:', 'wss:');
  30. } else {
  31. return wsSocketUrl.replace('wss:', 'ws:');
  32. }
  33. // #endif
  34. // #ifndef H5
  35. return wsSocketUrl.replace('ws:', 'wss:');
  36. //#endif
  37. }
  38. class Socket {
  39. constructor() {
  40. this.socketTask = null; //socket 任务
  41. this.timer = null; //心跳定时器
  42. this.connectStatus = false; //连接状态
  43. this.wsUrl = ''; //ws地址
  44. this.reconnectTimer = 2000; //重连
  45. this.handClse = false; //手动关闭
  46. this.reconnetime = null; //重连 定时器
  47. this.networkStatus = true;
  48. this.connectLing = false; //连接是否进行中
  49. this.defaultEvenv(); //执行默认事件
  50. this.networkEvent();
  51. }
  52. //网络状态变化监听
  53. networkEvent() {
  54. onNetworkStatusChange((res) => {
  55. console.log('有网了',res)
  56. this.networkStatus = true;
  57. if (this.socketTask) {
  58. this.socketTask.close();
  59. }
  60. uni.$on('timeout', this.timeoutEvent.bind(this))
  61. }, () => {
  62. console.log('断网了')
  63. this.networkStatus = false;
  64. this.connectStatus = false;
  65. clearInterval(this.timer);
  66. this.timer = null;
  67. uni.$off('timeout', this.timeoutEvent)
  68. });
  69. }
  70. //开始连接
  71. startConnect() {
  72. console.log('开始链接')
  73. this.handClse = false;
  74. if (!this.connectStatus) {
  75. this.init();
  76. this.connect();
  77. }
  78. }
  79. //默认事件
  80. defaultEvenv() {
  81. uni.$off('success', this.successEvent);
  82. uni.$off('timeout', this.timeoutEvent);
  83. uni.$on('success', this.successEvent.bind(this));
  84. uni.$on('timeout', this.timeoutEvent.bind(this));
  85. }
  86. timeoutEvent() {
  87. console.log('timeoutEvent')
  88. this.reconne();
  89. }
  90. successEvent() {
  91. console.log('success默认事件');
  92. // this.changOnline();
  93. }
  94. //发送用户状态
  95. changOnline() {
  96. let online = cache.get('kefu_online')
  97. if (online !== undefined && online !== '') {
  98. this.send({
  99. data: {
  100. online: online
  101. },
  102. type: 'online'
  103. });
  104. }
  105. }
  106. //连接websocket
  107. connect() {
  108. this.connectLing = true;
  109. this.socketTask = uni.connectSocket({
  110. url: this.wsUrl,
  111. complete: () => {}
  112. });
  113. this.socketTask.onOpen(this.onOpen.bind(this))
  114. this.socketTask.onError(this.onError.bind(this));
  115. this.socketTask.onMessage(this.onMessage.bind(this))
  116. this.socketTask.onClose(this.onClose.bind(this));
  117. }
  118. init() {
  119. let wsUrl = wss(`${VUE_APP_WS_URL}?type=user`),
  120. form_type = 3;
  121. //#ifdef MP || APP-PLUS
  122. form_type = 2
  123. //#endif
  124. //#ifdef H5
  125. form_type = wechat.isWeixin() ? 1 : 3
  126. //#endif
  127. this.wsUrl = `${wsUrl}&token=${$store.state.app.token}&form_type=${form_type}`
  128. }
  129. //断线重连
  130. reconne() {
  131. if (this.reconnetime || this.connectStatus) {
  132. return;
  133. }
  134. this.reconnetime = setInterval(() => {
  135. if (this.connectStatus) {
  136. return;
  137. }
  138. this.connectLing || this.connect();
  139. }, this.reconnectTimer);
  140. }
  141. onOpen() {
  142. clearInterval(this.reconnetime);
  143. this.reconnetime = null;
  144. this.connectLing = false;
  145. this.connectStatus = true;
  146. this.ping();
  147. }
  148. onError(error) {
  149. console.log('连接发生错误', error)
  150. this.connectStatus = false;
  151. this.connectLing = false;
  152. this.reconne();
  153. }
  154. onClose(err) {
  155. console.log(this.socketTask, err, '关闭连接')
  156. uni.$emit('close');
  157. //手动关闭不用重新连接
  158. if (this.handClse) {
  159. return;
  160. }
  161. clearInterval(this.timer);
  162. this.timer = null;
  163. this.connectStatus = false;
  164. this.connectLing = false;
  165. this.reconne();
  166. }
  167. ping() {
  168. this.timer = setInterval(() => {
  169. this.send({
  170. type: 'ping'
  171. })
  172. }, 10000)
  173. }
  174. onMessage(response) {
  175. let {
  176. type,
  177. data
  178. } = JSON.parse(response.data);
  179. uni.$emit(type, data);
  180. }
  181. send(data) {
  182. let that = this;
  183. //没有网络,或者没有连接
  184. if (!this.connectStatus || !this.networkStatus) {
  185. this.reconne();
  186. }
  187. return new Promise((reslove, reject) => {
  188. this.socketTask.send({
  189. data: JSON.stringify(data),
  190. success() {
  191. reslove();
  192. },
  193. fail(res) {
  194. console.log(res)
  195. if (res.errMsg ==
  196. 'sendSocketMessage:fail WebSocket is not connected' ||
  197. res.errMsg ==
  198. 'sendSocketMessage:fail Error: SocketTask.readyState is not OPEN'
  199. ) {
  200. that.reconne();
  201. }
  202. reject(res);
  203. },
  204. complete(res) {
  205. console.log(res)
  206. }
  207. })
  208. });
  209. }
  210. guid() {
  211. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
  212. var r = Math.random() * 16 | 0,
  213. v = c == 'x' ? r : (r & 0x3 | 0x8);
  214. return v.toString(16);
  215. });
  216. }
  217. clearPing() {
  218. clearInterval(this.timer);
  219. this.timer = null;
  220. if (this.connectStatus) {
  221. this.socketTask.close();
  222. }
  223. this.handClse = true;
  224. this.connectStatus = false;
  225. this.connectLing = false;
  226. }
  227. setBadgeNumber(count) {
  228. //#ifdef APP-PLUS
  229. plus.runtime.setBadgeNumber(Number(count));
  230. //#endif
  231. }
  232. }
  233. export default Socket;