App.vue 11 KB

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