index.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <!-- 顶栏订单状态通知 -->
  2. <template>
  3. <div class="order-notify-socket m-t-5 m-b-5 font-32">
  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. const app = getApp();
  26. import api from '@/utils/api'
  27. import util from '@/utils/util'
  28. import __config from '@/config/env';
  29. export default {
  30. name: 'OrderNotifySocket',
  31. props: {
  32. },
  33. data() {
  34. return {
  35. deviceInfo: uni.$u.sys(),
  36. //在线状态 0:CONNECTING 1:OPEN 2:CLOSING 3:CLOSED
  37. socketOnlineStatus: 0,
  38. // websocket相关
  39. socketObj: undefined, // websocket实例对象
  40. //心跳检测
  41. heartCheck: {
  42. // vue实例
  43. vueThis: this,
  44. // 超时时间
  45. timeout: 1000 * 3,
  46. // 计时器对象——向后端发送心跳检测
  47. timeoutObj: null,
  48. // 计时器对象——等待后端心跳检测的回复
  49. serverTimeoutObj: null,
  50. // 心跳Key(和后台协商一致)
  51. heartBeatString: 'RS_OM_ORDER_PAY_STATUS_NOTICE_HEART_BEAT',
  52. // 心跳检测重置
  53. reset: function() {
  54. clearTimeout(this.timeoutObj);
  55. clearTimeout(this.serverTimeoutObj);
  56. return this;
  57. },
  58. // 心跳检测启动
  59. start: function() {
  60. this.timeoutObj && clearTimeout(this.timeoutObj);
  61. this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
  62. this.timeoutObj = setTimeout(() => {
  63. // 这里向后端发送一个心跳检测,后端收到后,会返回一个心跳回复
  64. this.vueThis.socketObj.send({
  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. created() {
  85. console.log('【支付通知】WebSocket', `离开标记: ${this.socketLeaveFlag}`)
  86. },
  87. mounted() {
  88. // websocket启动
  89. this.createWebSocket();
  90. },
  91. destroyed() {
  92. // 离开标记
  93. this.socketLeaveFlag = true;
  94. if(this.socketObj){
  95. // 关闭WebSocket
  96. this.socketObj.close();
  97. }
  98. },
  99. methods: {
  100. // websocket启动
  101. createWebSocket() {
  102. let baseSocketUrl = __config.socketBasePath;
  103. //let baseSocketUrl = process.env.VUE_APP_WS_BASE_URL;
  104. let webSocketLink = `${baseSocketUrl}/ws/om/order/notice/${__config.tenantId}/${this.deviceInfo.deviceId}`;
  105. console.log('【支付通知】WebSocket', `远程连接地址: ${webSocketLink}`)
  106. try {
  107. this.socketObj = uni.connectSocket({
  108. url: webSocketLink,
  109. complete: () => {}
  110. });
  111. // websocket事件绑定
  112. this.socketEventBind();
  113. } catch (e) {
  114. console.error("catch" + e);
  115. // websocket重连
  116. this.socketReconnect();
  117. }
  118. },
  119. // websocket事件绑定
  120. socketEventBind() {
  121. // 连接成功建立的回调
  122. this.socketObj.onOpen(this.onopenCallback);
  123. // 连接发生错误的回调
  124. this.socketObj.onError(this.onerrorCallback);
  125. // 连接关闭的回调
  126. this.socketObj.onClose(this.oncloseCallback);
  127. // 向后端发送数据的回调
  128. //this.socketObj.onSend = this.onsendCallback;
  129. // 接收到消息的回调
  130. this.socketObj.onMessage(this.getMessageCallback);
  131. },
  132. // websocket重连
  133. socketReconnect() {
  134. if (this.socketReconnectLock) {
  135. return;
  136. }
  137. this.socketReconnectLock = true;
  138. this.socketReconnectTimer && clearTimeout(this.socketReconnectTimer);
  139. this.socketReconnectTimer = setTimeout(() => {
  140. console.log('【支付通知】WebSocket', '重连中......')
  141. this.socketOnlineStatus = this.socketObj.readyState
  142. this.socketReconnectLock = false;
  143. // websocket启动
  144. this.createWebSocket();
  145. }, 4000);
  146. },
  147. // websocket 给后台发送消息
  148. sendSocketMessage(msgBody) {
  149. if (this.socketOnlineStatus === 1) {
  150. // 普通发送——正常处理
  151. console.log('【支付通知】WebSocket', '发送Message到后台: ' + JSON.stringify(msgBody, 'null', '\t'))
  152. uni.sendSocketMessage({
  153. data: JSON.stringify(msgBody)
  154. });
  155. } else {
  156. }
  157. },
  158. // 连接成功建立的回调
  159. onopenCallback: function(event) {
  160. console.log('【支付通知】WebSocket', '已连接 SUCCESS ')
  161. this.socketOnlineStatus = 1
  162. // 心跳检测重置
  163. this.heartCheck.reset().start();
  164. },
  165. // 连接发生错误的回调
  166. onerrorCallback: function(event) {
  167. console.error('【支付通知】WebSocket', '发生错误')
  168. console.error(event)
  169. this.socketOnlineStatus = 3
  170. // websocket重连
  171. this.socketReconnect();
  172. },
  173. // 连接关闭的回调
  174. oncloseCallback: function(event) {
  175. console.error('【支付通知】WebSocket', '已关闭 CLOSE')
  176. this.socketOnlineStatus = 2
  177. // 心跳检测重置
  178. this.heartCheck.reset();
  179. if (!this.socketLeaveFlag) {
  180. // 没有离开——重连
  181. // websocket重连
  182. this.socketReconnect();
  183. }
  184. },
  185. // 向后端发送数据的回调
  186. onsendCallback: function() {
  187. console.log('【支付通知】WebSocket', '发送信息给后端')
  188. },
  189. // 接收到消息的回调
  190. getMessageCallback: function(msg) {
  191. if (JSON.stringify(msg.data).indexOf(this.heartCheck.heartBeatString) > -1) {
  192. // 心跳回复——心跳检测重置
  193. // 收到心跳检测回复就说明连接正常
  194. console.log('【支付通知】WebSocket', `收到心跳检测回复[KEY: ${this.heartCheck.heartBeatString}]`)
  195. // 心跳检测重置
  196. this.heartCheck.reset().start();
  197. } else {
  198. // 普通推送——正常处理
  199. // console.log('【支付通知】WebSocket', '收到推送消息: ' + JSON.stringify(JSON.parse(msg.data), 'null', '\t'))
  200. let data = msg.data;
  201. // 相关处理
  202. //console.log('【支付通知】WebSocket', `接收到的数据并做相关处理: ${JSON.stringify(data)}`)
  203. this.$emit('receivedMessage', JSON.parse(data))
  204. }
  205. },
  206. },
  207. }
  208. </script>
  209. <style lang="scss" scoped>
  210. .order-notify-socket {
  211. text-align: right;
  212. }
  213. </style>