App.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <template>
  2. <div id="app">
  3. <transition name='fade' mode="out-in">
  4. <router-view/>
  5. </transition>
  6. </div>
  7. </template>
  8. <script>
  9. import Vue from 'vue';
  10. export default {
  11. name: 'App',
  12. data(){
  13. return{
  14. reconnectData:null,
  15. lockReconnect:false, //避免重复连接,因为onerror之后会立即触发 onclose
  16. timeout:5000, //10s一次心跳检测
  17. timeoutObj:null,
  18. serverTimeoutObj:null,
  19. apiToken:'',
  20. linkfailure:true,
  21. }
  22. },
  23. methods:{
  24. /**************************************/
  25. //初始化weosocket
  26. initWebSocket(apiToken) {
  27. // 书写接口信息
  28. const wsuri = "ws://103.108.43.176:9101?apiToken=" + apiToken;//www.service.com 线上
  29. // const wsuri = "ws://192.168.2.187:9101?apiToken=" + apiToken;//www.service.com //192.168.2.186 本地
  30. // 创建websocket实例
  31. Vue.prototype.$websocket = new WebSocket(wsuri);
  32. this.$websocket.onopen = this.websocketonopen; //连接成功
  33. this.$websocket.onmessage = this.websocketonmessage; //接收消息
  34. this.$websocket.onerror = this.websocketonerror;//链接错误提示
  35. this.$websocket.onclose = this.socket_close;//链接断开提示
  36. },
  37. /**************************************/
  38. //连接成功
  39. websocketonopen() {
  40. console.log('已经链接');
  41. let user_info = '';
  42. // console.log(this.$store.getters.get_user_info != "");
  43. if(typeof this.$store.getters.get_user_info != 'string'){
  44. user_info = this.$store.getters.get_user_info;
  45. }else if(this.$store.getters.get_user_info!= ""){
  46. user_info = JSON.parse(this.$store.getters.get_user_info);
  47. }
  48. if(user_info){
  49. this.$websocket.send(JSON.stringify({
  50. type: 'init',
  51. data: {
  52. uid: 'KF' + user_info.id,
  53. group: user_info.group_id,
  54. token: user_info.token,
  55. name: user_info.user_name,
  56. avatar: user_info.user_avatar,
  57. }
  58. }));
  59. }
  60. this.$store.dispatch("SET_SOCKET_OPEN",true);//列表下标
  61. this.heatBeat();
  62. },
  63. /*******************************************/
  64. //连接关闭触发
  65. socket_close(e){
  66. console.log('断开连接',e);
  67. //this.init()
  68. this.reconnect();
  69. },
  70. /******************************************/
  71. //数据接收
  72. websocketonmessage(e){
  73. this.heatBeat();//收到消息会刷新心跳检测,如果一直收到消息,就推迟心跳发送
  74. const redata = JSON.parse(e.data);//接收数据源
  75. //
  76. if(redata.message_type == "ping"){
  77. this.$websocket.send('{"type":"pong"}')
  78. return false;
  79. }
  80. if(redata.type == "pong") return false;
  81. if(redata.type != "pong" || redata.message_type != "ping"){
  82. console.log(redata);
  83. }
  84. let getters = this.$store.getters;
  85. //获取vuex数据
  86. let session = getters.get_session;//会话列表
  87. let offline = getters.get_offline;//离线列表
  88. let sessionType = getters.get_type;//选择状态(会话/离线)
  89. let dataIndex = getters.get_num;//列表下标
  90. let current_session = getters.get_current;//当前会话
  91. let session_name = getters.get_session_name;//当前用户名
  92. this.$store.dispatch("SET_SESSION_MESSAGE",JSON.parse(e.data));
  93. // 用户接入数据
  94. if(redata.message_type == "connect"){
  95. let _this = this;
  96. let arr =[
  97. redata.data,
  98. offline,
  99. session,
  100. sessionType,
  101. dataIndex,
  102. current_session,
  103. session_name,
  104. ]
  105. _this.$public.visitorsConnect(arr,function(data){
  106. //离线匹配列表访客链接回调
  107. _this.$store.dispatch("SET_OFFLINE",data);
  108. },function(data,session,offline,type,num,dataList,name){
  109. //将用户添加到会话列表中
  110. // console.log('接入用户昵称',name);
  111. if(name){
  112. data.user_info.name = name;
  113. _this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
  114. }
  115. session.push(data.user_info);
  116. //获取接入的用户信息
  117. //_this.get_user_info(list);
  118. //获取接入的用户信息写入vuex
  119. _this.$store.dispatch("SET_SESSION",session);//会话列表
  120. _this.$store.dispatch("SET_OFFLINE",offline);//离线列表
  121. _this.$store.dispatch("SET_TYPE",type);//选择类型(会话/离线)
  122. _this.$store.dispatch("SET_NUM",num);//列表下标
  123. _this.$store.dispatch("SET_CURRENT",dataList);//当前会话数据
  124. })
  125. }
  126. //登录验证失败跳转登录页面
  127. if(redata.message_type == 'checkfalse'){
  128. // this.$router.push({
  129. // path:'/login',
  130. // query: { pid:escape("这就是一个编码没有什么用啊") }
  131. // })
  132. }
  133. //用户离线后会话窗口切换
  134. if(redata.message_type == "userClose"){
  135. let _this =this;
  136. let arr= [
  137. redata.data,
  138. session,
  139. offline,
  140. sessionType,
  141. dataIndex,
  142. session_name,
  143. current_session,
  144. ]
  145. _this.$public.userOffline(arr,function(session,offline,type,index,name,list,userInfo){
  146. _this.$store.dispatch("SET_CURRENT",list);//当前会话数据
  147. _this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
  148. _this.$store.dispatch("SET_NUM",index);
  149. _this.$store.dispatch("SET_TYPE",type);
  150. _this.$store.dispatch("SET_SESSION",session);
  151. _this.$store.dispatch("SET_OFFLINE",offline);
  152. // _this.get_user_info(userInfo);
  153. })
  154. }
  155. //用户会话结束窗口切换
  156. if(redata.message_type == "delUser"){
  157. let _this =this;
  158. let arr= [
  159. redata.data,
  160. session,
  161. offline,
  162. sessionType,
  163. dataIndex,
  164. session_name,
  165. current_session,
  166. ]
  167. _this.$public.sessionEnd(arr,function(session,offline,type,index,name,list,userInfo){
  168. _this.$store.dispatch("SET_CURRENT",list);//当前会话数据
  169. _this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
  170. _this.$store.dispatch("SET_NUM",index);
  171. _this.$store.dispatch("SET_TYPE",type);
  172. _this.$store.dispatch("SET_SESSION",session);
  173. _this.$store.dispatch("SET_OFFLINE",offline);
  174. // _this.get_user_info(userInfo);
  175. })
  176. }
  177. //接收用户消息数据
  178. if(redata.message_type == "chatMessage"){
  179. this.receiveAudio();
  180. let _this =this;
  181. this.$public.receivesMessage(redata.data,session,this.$frce,function(data,chatList,index){
  182. //判断是否是当前对话信息
  183. if(dataIndex == index){
  184. _this.$store.dispatch("SET_CURRENT",chatList.data);//当前会话数据
  185. }else{
  186. let num = Number.isInteger(chatList.num) ? chatList.num : 0;
  187. // session[index].num = num+1;
  188. _this.$set(session[index],'num',num+1)
  189. }
  190. //更新会话时间
  191. session[index].intime =data.time;
  192. //更新会话列表中最新回复消息
  193. if(data.content.text){
  194. // _this.$set(chatList,'text',data.content.text)
  195. session[index].text =data.content.text;
  196. }
  197. _this.$store.dispatch("SET_SESSION",session);
  198. })
  199. }
  200. // history
  201. //reLoginErr
  202. if(redata.message_type == "reLoginErr"){
  203. // console.log('haha');
  204. this.init()
  205. }
  206. },
  207. /**************************************/
  208. //连接断开,失败
  209. websocketonerror(e) {
  210. console.log('失败',e);
  211. if(this.linkfailure){
  212. this.init()
  213. }
  214. },
  215. /******************************************/
  216. //断开链接数据初始化
  217. init(){
  218. this.$store.dispatch("SET_STATEVALUE",'在线');
  219. this.$store.dispatch("SET_SESSION",[]);
  220. this.$store.dispatch("SET_USER",'');
  221. this.$store.dispatch("SET_OFFLINE",[]);
  222. this.$store.dispatch("SET_SESSION",[]);//会话列表
  223. this.$store.dispatch("SET_OFFLINE",[]);//离线列表
  224. this.$store.dispatch("SET_TYPE",1);//选择类型(会话/离线)
  225. this.$store.dispatch("SET_NUM",0);//列表下标
  226. this.$store.dispatch("SET_CURRENT",[]);//当前会话数据
  227. this.$store.dispatch("SET_SESSION_NAME",'');//当前会话对象名
  228. this.$store.dispatch("SET_SESSION_MESSAGE",{});
  229. this.$store.dispatch("SET_NAVSTATE",'TheCurrentSession');
  230. this.$store.dispatch("SET_IS_INIT",false);
  231. this.$token = '';
  232. this.$router.push('/login')
  233. this.linkfailure = true;
  234. //this.reconnect();
  235. },
  236. /*******************************************/
  237. // 接收消息音频提示
  238. receiveAudio() {
  239. let receive = new Audio()
  240. receive.src = "../static/audio/receive.wav";
  241. receive.play();
  242. },
  243. /***************************************/
  244. //socket重连
  245. reconnect(){
  246. if(this.lockReconnect){ //这里很关键,因为连接失败之后之后会相继触发 连接关闭,不然会连接上两个 WebSocket
  247. return
  248. }
  249. this.lockReconnect = true;
  250. this.reconnectData && clearTimeout(this.reconnectData);
  251. this.reconnectData = setTimeout(()=>{
  252. this.initWebSocket(this.apiToken);
  253. this.lockReconnect = false;
  254. },3000)
  255. },
  256. /*************************************/
  257. //心跳检测
  258. heatBeat(){
  259. this.timeoutObj && clearTimeout(this.timeoutObj);
  260. this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
  261. this.timeoutObj = setTimeout(()=>{
  262. // console.log('发送',{type:'ping'});
  263. this.$websocket.send(JSON.stringify({type:'ping'})) //根据后台要求发送
  264. this.serverTimeoutObj = setTimeout(()=> {
  265. this.$websocket.close(); //如果4秒之后我们没有收到 后台返回的心跳检测数据 断开socket,断开后会启动重连机制
  266. }, 4000);
  267. }, this.timeout)
  268. },
  269. /******************************/
  270. },
  271. mounted() {
  272. Vue.prototype.$socket_open = false;
  273. // 获取系统时间
  274. let t = new Date().getTime();
  275. //this.get('api'+this.$ports.TIME+'?t='+t).then(res => {
  276. this.get('http://kfadmin.bocai186.com'+this.$ports.TIME+'?t='+t).then(res => {
  277. if (res.data.code == 1) {
  278. let time = res.data.data.time.split(' ');
  279. time[0] =(new Date( time[0].replace(/-/g,'/')).getTime()) /1000;
  280. sessionStorage.setItem("time",JSON.stringify(time));
  281. sessionStorage.setItem("logo",res.data.data.logo);
  282. this.apiToken = this.$md5('customer-service'+window.location.origin)
  283. this.initWebSocket(this.apiToken);
  284. }
  285. });
  286. },
  287. destroyed() {
  288. this.lockReconnect = true;
  289. this.websock.close() //离开路由之后断开websocket连接
  290. clearTimeout(this.reconnectData); //离开清除 timeout
  291. clearTimeout(this.timeoutObj); //离开清除 timeout
  292. clearTimeout(this.serverTimeoutObj); //离开清除 timeout
  293. }
  294. }
  295. </script>
  296. <style>
  297. .fade-enter-active, .fade-leave-active {
  298. transition: opacity .5s;
  299. }
  300. .fade-enter, .fade-leave-to {
  301. opacity: 0;
  302. }
  303. </style>