App.vue 12 KB

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