index.vue 6.6 KB

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