index.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <!-- 顶栏订单状态通知 -->
  2. <template>
  3. <div class="order-notify-socket m-t-5 m-b-5 font-45">
  4. <text class="p-r-10">
  5. <text v-if="socketOnlineStatus === 0" class="text-yellow">
  6. <text class="cuIcon-wifi"></text>
  7. <text class="m-l-8">连接中···</text>
  8. </text>
  9. <text v-if="socketOnlineStatus === 1" class="text-green">
  10. <text class="cuIcon-wifi"></text>
  11. <text class="m-l-8">在线</text>
  12. </text>
  13. <text v-if="socketOnlineStatus === 2" class="text-red">
  14. <text class="cuIcon-wifi"></text>
  15. <text class="m-l-8">关闭中</text>
  16. </text>
  17. <text v-if="socketOnlineStatus === 3" class="text-red">
  18. <text class="cuIcon-wifi"></text>
  19. <text class="m-l-8">已断开</text>
  20. </text>
  21. </text>
  22. </div>
  23. </template>
  24. <script>
  25. import api from '@/utils/api'
  26. import util from '@/utils/util'
  27. import __config from '@/config/env';
  28. export default {
  29. name: 'OrderNotifySocket',
  30. props: {
  31. },
  32. data() {
  33. return {
  34. deviceInfo: uni.$u.sys(),
  35. //在线状态 0:CONNECTING 1:OPEN 2:CLOSING 3:CLOSED
  36. socketOnlineStatus: 0,
  37. // websocket相关
  38. socketObj: undefined, // websocket实例对象
  39. //心跳检测
  40. heartCheck: {
  41. // vue实例
  42. vueThis: this,
  43. // 超时时间
  44. timeout: 1000 * 60,
  45. // 计时器对象——向后端发送心跳检测
  46. timeoutObj: null,
  47. // 计时器对象——等待后端心跳检测的回复
  48. serverTimeoutObj: null,
  49. // 心跳Key(和后台协商一致)
  50. heartBeatString: 'RS_OM_ORDER_PAY_STATUS_NOTICE_HEART_BEAT',
  51. // 心跳检测重置
  52. reset: function() {
  53. clearTimeout(this.timeoutObj);
  54. clearTimeout(this.serverTimeoutObj);
  55. return this;
  56. },
  57. // 心跳检测启动
  58. start: function() {
  59. console.log("开始发送心跳检测")
  60. this.timeoutObj && clearTimeout(this.timeoutObj);
  61. this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
  62. this.timeoutObj = setTimeout(() => {
  63. // 这里向后端发送一个心跳检测,后端收到后,会返回一个心跳回复
  64. uni.sendSocketMessage({
  65. data: this.vueThis.heartCheck.heartBeatString
  66. });
  67. //this.vueThis.socketObj.send(this.vueThis.heartCheck.heartBeatString);
  68. console.log('WebSocket',
  69. `发送心跳检测[KEY: ${this.vueThis.heartCheck.heartBeatString}]`)
  70. this.serverTimeoutObj = setTimeout(() => {
  71. // 如果超过一定时间还没重置计时器,说明websocket与后端断开了
  72. console.log('WebSocket', `未收到心跳检测回复`)
  73. // 关闭WebSocket
  74. this.vueThis.socketObj.close();
  75. }, this.timeout);
  76. }, this.timeout);
  77. },
  78. },
  79. socketReconnectTimer: null, // 计时器对象——重连
  80. socketReconnectLock: false, // WebSocket重连的锁
  81. socketLeaveFlag: false, // 离开标记(解决 退出登录再登录 时出现的 多次相同推送 问题,出现的本质是多次建立了WebSocket连接)
  82. };
  83. },
  84. onUnload(){ //清除定时器
  85. if(this.socketReconnectTimer) {
  86. clearTimeout(this.socketReconnectTimer);
  87. this.socketReconnectTimer = null;
  88. }
  89. if(this.timeoutObj) {
  90. clearTimeout(this.timeoutObj);
  91. this.timeoutObj = null;
  92. }
  93. if(this.serverTimeoutObj) {
  94. clearTimeout(this.serverTimeoutObj);
  95. this.serverTimeoutObj = null;
  96. }
  97. },
  98. created() {
  99. console.log('WebSocket', `离开标记: ${this.socketLeaveFlag}`)
  100. },
  101. mounted() {
  102. // websocket启动
  103. this.createWebSocket();
  104. },
  105. destroyed() {
  106. // 离开标记
  107. this.socketLeaveFlag = true;
  108. // 关闭WebSocket
  109. this.socketObj.close();
  110. },
  111. methods: {
  112. // websocket启动
  113. createWebSocket() {
  114. let baseSocketUrl = __config.socketBasePath;
  115. //let baseSocketUrl = process.env.VUE_APP_WS_BASE_URL;
  116. let webSocketLink = `${baseSocketUrl}/ws/om/order/notice/${__config.tenantId}/${this.deviceInfo.deviceId}`;
  117. console.log('WebSocket', `远程连接地址: ${webSocketLink}`)
  118. try {
  119. this.socketObj = uni.connectSocket({
  120. url: webSocketLink,
  121. complete: () => {}
  122. });
  123. // websocket事件绑定
  124. this.socketEventBind();
  125. } catch (e) {
  126. console.error("catch" + e);
  127. // websocket重连
  128. this.socketReconnect();
  129. }
  130. },
  131. // websocket事件绑定
  132. socketEventBind() {
  133. // 连接成功建立的回调
  134. uni.onSocketOpen(this.onopenCallback);
  135. // 连接发生错误的回调
  136. uni.onSocketError(this.onerrorCallback);
  137. // 连接关闭的回调
  138. uni.onSocketClose(this.oncloseCallback);
  139. // 向后端发送数据的回调
  140. //this.socketObj.onSend = this.onsendCallback;
  141. // 接收到消息的回调
  142. uni.onSocketMessage(this.getMessageCallback);
  143. },
  144. // websocket重连
  145. socketReconnect() {
  146. if (this.socketReconnectLock) {
  147. return;
  148. }
  149. this.socketReconnectLock = true;
  150. this.socketReconnectTimer && clearTimeout(this.socketReconnectTimer);
  151. this.socketReconnectTimer = setTimeout(() => {
  152. console.log('WebSocket', '重连中......')
  153. this.socketOnlineStatus = this.socketObj.readyState
  154. this.socketReconnectLock = false;
  155. // websocket启动
  156. this.createWebSocket();
  157. }, 4000);
  158. },
  159. // websocket 给后台发送消息
  160. sendSocketMessage(msgBody) {
  161. if (this.socketOnlineStatus === 1) {
  162. // 普通发送——正常处理
  163. console.log('WebSocket', '发送Message到后台: ' + JSON.stringify(msgBody, 'null', '\t'))
  164. uni.sendSocketMessage({
  165. data: JSON.stringify(msgBody)
  166. });
  167. } else {
  168. }
  169. },
  170. // 连接成功建立的回调
  171. onopenCallback: function(event) {
  172. console.log('WebSocket', '已连接 SUCCESS ')
  173. this.socketOnlineStatus = 1
  174. // 心跳检测重置
  175. this.heartCheck.reset().start();
  176. },
  177. // 连接发生错误的回调
  178. onerrorCallback: function(event) {
  179. console.error('WebSocket', '发生错误')
  180. console.error(event)
  181. this.socketOnlineStatus = 3
  182. // websocket重连
  183. this.socketReconnect();
  184. },
  185. // 连接关闭的回调
  186. oncloseCallback: function(event) {
  187. console.error('WebSocket', '已关闭 CLOSE')
  188. this.socketOnlineStatus = 2
  189. // 心跳检测重置
  190. this.heartCheck.reset();
  191. if (!this.socketLeaveFlag) {
  192. // 没有离开——重连
  193. // websocket重连
  194. this.socketReconnect();
  195. }
  196. },
  197. // 向后端发送数据的回调
  198. onsendCallback: function() {
  199. console.log('WebSocket', '发送信息给后端')
  200. },
  201. // 接收到消息的回调
  202. getMessageCallback: function(msg) {
  203. console.log(msg.data)
  204. if (JSON.stringify(msg.data).indexOf(this.heartCheck.heartBeatString) > -1) {
  205. // 心跳回复——心跳检测重置
  206. // 收到心跳检测回复就说明连接正常
  207. console.log('WebSocket', `收到心跳检测回复[KEY: ${this.heartCheck.heartBeatString}]`)
  208. // 心跳检测重置
  209. this.heartCheck.reset().start();
  210. } else {
  211. // 普通推送——正常处理
  212. console.log('WebSocket', '收到推送消息: ' + JSON.stringify(JSON.parse(msg.data), 'null', '\t'))
  213. let data = msg.data;
  214. // 相关处理
  215. console.log('WebSocket', `接收到的数据并做相关处理: ${JSON.stringify(data)}`)
  216. this.$emit('receivedMessage', JSON.parse(data))
  217. this.$emit('socketIcon', false)
  218. }
  219. },
  220. },
  221. }
  222. </script>
  223. <style lang="scss" scoped>
  224. .order-notify-socket {
  225. text-align: right;
  226. }
  227. </style>