xiang 6 years ago
parent
commit
004c83e5ad
53 changed files with 1445 additions and 439 deletions
  1. 11 0
      chat/src/components/index.vue
  2. 19 3
      pc_chat/src/components/chat.vue
  3. BIN
      service_exe/build/icons/256x256.png
  4. BIN
      service_exe/build/icons/empty.png
  5. BIN
      service_exe/build/icons/icon.ico
  6. BIN
      service_exe/build/icons/icon.png
  7. 16 0
      service_exe/src/index.html
  8. 142 124
      service_exe/src/renderer/App.vue
  9. 1 1
      service_exe/src/renderer/api/http.js
  10. 3 1
      service_exe/src/renderer/api/ports.js
  11. 29 0
      service_exe/src/renderer/assets/common.js
  12. 1 1
      service_exe/src/renderer/components/hader.vue
  13. 1 1
      service_exe/src/renderer/components/historicalRecord.vue
  14. 2 1
      service_exe/src/renderer/components/leftNav.vue
  15. 11 0
      service_exe/src/renderer/css/index.css
  16. 12 12
      service_exe/src/renderer/main.js
  17. 2 2
      service_exe/src/renderer/pages/LeaveMessage.vue
  18. 129 36
      service_exe/src/renderer/pages/TheCurrentSession.vue
  19. 278 256
      service_exe/src/renderer/pages/login.vue
  20. 2 1
      service_exe/src/renderer/store/index.js
  21. BIN
      service_exe/src/static/audio/receive.wav
  22. BIN
      service_exe/src/static/audio/send.wav
  23. 0 0
      service_exe/src/static/css/app.b08f3768c9553af70c3dfb15b68c00a8.css
  24. 0 0
      service_exe/src/static/css/app.b08f3768c9553af70c3dfb15b68c00a8.css.map
  25. BIN
      service_exe/src/static/fonts/element-icons.535877f.woff
  26. BIN
      service_exe/src/static/fonts/element-icons.732389d.ttf
  27. 4 0
      service_exe/src/static/frce.js
  28. BIN
      service_exe/src/static/img/59.1cb4f69.gif
  29. BIN
      service_exe/src/static/img/loginBg.1847fc5.png
  30. 0 0
      service_exe/src/static/js/0.78e6e92dd6f80d447f44.js
  31. 0 0
      service_exe/src/static/js/0.78e6e92dd6f80d447f44.js.map
  32. 0 0
      service_exe/src/static/js/1.2850cac60cc7cb36bc98.js
  33. 0 0
      service_exe/src/static/js/1.2850cac60cc7cb36bc98.js.map
  34. 0 0
      service_exe/src/static/js/2.5988ffaaae4d45954528.js
  35. 0 0
      service_exe/src/static/js/2.5988ffaaae4d45954528.js.map
  36. 0 0
      service_exe/src/static/js/3.bb7138d6aee6b832f1d6.js
  37. 0 0
      service_exe/src/static/js/3.bb7138d6aee6b832f1d6.js.map
  38. 0 0
      service_exe/src/static/js/4.b2ac001ec334e8091243.js
  39. 0 0
      service_exe/src/static/js/4.b2ac001ec334e8091243.js.map
  40. 0 0
      service_exe/src/static/js/5.e4de278f29e86de1e53a.js
  41. 0 0
      service_exe/src/static/js/5.e4de278f29e86de1e53a.js.map
  42. 0 0
      service_exe/src/static/js/6.d9776ecdfcd686aeb8fc.js
  43. 0 0
      service_exe/src/static/js/6.d9776ecdfcd686aeb8fc.js.map
  44. 0 0
      service_exe/src/static/js/app.a9f51c630fb54c84585a.js
  45. 0 0
      service_exe/src/static/js/app.a9f51c630fb54c84585a.js.map
  46. 2 0
      service_exe/src/static/js/manifest.1375f5e568727c7312d8.js
  47. 0 0
      service_exe/src/static/js/manifest.1375f5e568727c7312d8.js.map
  48. 0 0
      service_exe/src/static/js/vendor.ed88eb57e8f88e68c79c.js
  49. 0 0
      service_exe/src/static/js/vendor.ed88eb57e8f88e68c79c.js.map
  50. BIN
      service_exe/src/static/logo.gif
  51. 253 0
      service_exe/src/static/md5.js
  52. 41 0
      service_exe/src/static/paste.js
  53. 486 0
      service_exe/src/static/publicMethods.js

+ 11 - 0
chat/src/components/index.vue

@@ -480,6 +480,7 @@
 	import defaultImgs from "./../assets/timg.jpg"
 	import headPortrait from "./../assets/headPortrait.png"
 	import autoTextarea from 'auto-textarea'
+	import { Loading } from 'vue-ydui/dist/lib.rem/dialog';
 	export default {
 		name: "service",
 		// 模板注册
@@ -557,6 +558,7 @@
 				trueImg:false,
 				innerHeight: 0, // 可视区域高度,不包括键盘
 				areaHeight: 0, // textarea高度
+				loadingobj:null,//加载特效对像
 			};
 		},
 		created() {
@@ -586,6 +588,12 @@
 				this.setInit();
 
 			},
+			nloding(msg){
+					this.$dialog.loading.open(msg);
+			},
+			closeNloading(){
+				this.$dialog.loading.close();
+			},
 			/*******************************************/
 			//设置token加密
 			setApiToken(name, controller, time, modules) {
@@ -1080,6 +1088,7 @@
 			turnArtificial(id) {
 				this.group = id;
 				// this.$dialog.loading.open('转接中...')
+				this.nloding('人工客服转接中');
 				if (this.isTurnArtifcial) {
 					let data = {
 						'type': 'userInit',
@@ -1174,6 +1183,7 @@
 			//获取转接人工客服列表
 			connectionService() {
 				// if (!this.isConnection) return
+				this.nloding('正在读取客服列表');
 				let obj = {
 					headers: {
 						"apiToken": this.setApiToken('index', 'groups', this.currentTime[0], 'index')
@@ -1182,6 +1192,7 @@
 				// this.isConnection = false;
 				//api
 				this.$http.get('/index/groups/index', obj).then(res => {
+					this.closeNloading();
 					if (res.data.code == 1) {
 						this.robot.push({
 							type: 'artificial_service',

+ 19 - 3
pc_chat/src/components/chat.vue

@@ -554,7 +554,7 @@
 	import '../css/index.css';
 	import frce from '../assets/frce.js';
 	import fk from '../assets/st-img/kf.png'
-
+	import { Loading } from 'element-ui';
 	export default {
 		data() {
 			return {
@@ -664,6 +664,7 @@
 				helloNum: true, // 欢迎语限制
 				hisLength: 0, // 历史数量
 				showject: false,
+				loadingobj:null,//加载特效对像
 			}
 		},
 		filters: {
@@ -1101,9 +1102,21 @@
 				this.provShow = false;
 				this.zzShow = false;
 			},
+			nloding(msg){
+					this.loadingobj=Loading.service({lock: true,
+						text: 'Loading',
+						spinner: 'el-icon-loading',
+						background: 'rgba(0, 0, 0, 0.7)',
+						text:msg
+					});
+			},
+			closeNloading(){
+				this.loadingobj.close();
+			},
 
 			/***************转人工客服列表*************** */
 			changeService() {
+				this.nloding("转人工客服中请等待");
 				// if(!this.isConnection) return
 				this.$axios.post('/api/index/groups/index', {}, {
 					headers: {
@@ -1111,12 +1124,14 @@
 						'apiToken': this.setApiToken('index', 'groups', 'index')
 					}
 				}).then(res => {
+					this.closeNloading();
 					if (res.data.code == 1) {
 						this.serviceList = res.data.data;
 						this.chatCont.push({
 							'type': 'artService'
 						})
 						this.automaticRolling();
+						
 					}
 				})
 				// this.isConnection = false;
@@ -1197,8 +1212,8 @@
 			initWebSocket() {
 				let _this = this;
 				let apiToken = this.$md5.hex_md5('customer-service' + window.location.origin);
-				this.websock = new WebSocket('ws://ky.281570.com:9101?apiToken=' + apiToken);
-				// this.websock = new WebSocket('ws://192.168.2.187:9101?apiToken=' + apiToken);
+				this.websock = new WebSocket('ws://127.0.0.1:4431?apiToken=' + apiToken);
+				// this.websock = new WebSocket('ws://192.168.2.187:4431?apiToken=' + apiToken);
 				this.websock.debug = true;
 				// 数据接收
 				this.websock.onmessage = this.websocketonmessage;
@@ -1687,6 +1702,7 @@
 					});
 					return false
 				}
+				this.nloding('正在连接客服中....');
 				this.jumpArtl = true;
 				this.closeByServer = false;
 				this.group = id;

BIN
service_exe/build/icons/256x256.png


BIN
service_exe/build/icons/empty.png


BIN
service_exe/build/icons/icon.ico


BIN
service_exe/build/icons/icon.png


+ 16 - 0
service_exe/src/index.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>智能客服系统</title><link href=./static/css/app.b08f3768c9553af70c3dfb15b68c00a8.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.1375f5e568727c7312d8.js></script><script type=text/javascript src=./static/js/vendor.ed88eb57e8f88e68c79c.js></script><script type=text/javascript src=./static/js/app.a9f51c630fb54c84585a.js></script></body><script>let name = getQueryString('pid');
+    // if(unescape(name) != "这就是一个编码没有什么用啊"){
+    //   document.getElementById("app").remove();
+    //   var parent = document.body;
+    //   var div = document.createElement("div");
+    //   parent.appendChild(div)
+    //   div.innerHTML = "无效访问地址";
+    // }
+    function getQueryString(name) {
+      var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
+      var r = window.location.search.substr(1).match(reg);
+      if (r != null) {
+        return unescape(r[2]);
+      }
+      return null;
+    }</script></html>

+ 142 - 124
service_exe/src/renderer/App.vue

@@ -8,31 +8,28 @@
 
 <script>
 	import Vue from 'vue';
-	import receiveAPP from '../../static/audio/receive.wav';
-	import electron from 'electron'
-
 	export default {
 		name: 'App',
-		data() {
-			return {
-				Messagenum: 0,
-				reconnectData: null,
-				lockReconnect: false,    //避免重复连接,因为onerror之后会立即触发 onclose
-				timeout: 5000,          //10s一次心跳检测
-				timeoutObj: null,
-				serverTimeoutObj: null,
-				apiToken: '',
-				linkfailure: true,
-				receiveMuisc: receiveAPP
+		data(){
+			return{
+				reconnectData:null,
+				lockReconnect:false,    //避免重复连接,因为onerror之后会立即触发 onclose
+				timeout:5000,          //10s一次心跳检测
+				timeoutObj:null,
+				serverTimeoutObj:null,
+				apiToken:'',
+				linkfailure:true,
+				Messagenum:0,
+				kfuser_info:{}
 			}
 		},
-		methods: {
+		methods:{
 			/**************************************/
 			//初始化weosocket
 			initWebSocket(apiToken) {
 				// 书写接口信息
 				// http://stadmin.bocai108.com/
-				const wsuri = "ws://kfadmin.bocai186.com:9101?apiToken=" + apiToken;//www.service.com 线上
+				const wsuri = "ws://ky.281570.com:9101?apiToken=" + apiToken;//www.service.com 线上
 				// const wsuri = "ws://192.168.2.187:9101?apiToken=" + apiToken;//www.service.com //192.168.2.186 本地
 				// 创建websocket实例
 				Vue.prototype.$websocket = new WebSocket(wsuri);
@@ -41,6 +38,17 @@
 				this.$websocket.onerror = this.websocketonerror;//链接错误提示
 				this.$websocket.onclose = this.socket_close;//链接断开提示
 			},
+			// 得到保存好的当前客服信息
+			getCustomerUserInfo()
+			{
+
+				if(typeof this.$store.getters.get_user_info  != 'string'){
+					this.kfuser_info = this.$store.getters.get_user_info;
+				}else if(this.$store.getters.get_user_info!= ""){
+					this.kfuser_info =  JSON.parse(this.$store.getters.get_user_info);
+				}
+				return this.kfuser_info;
+			},
 
 			/**************************************/
 			//连接成功
@@ -48,13 +56,9 @@
 				console.log('已经链接');
 				let user_info = '';
 				// console.log(this.$store.getters.get_user_info != "");
-				if (typeof this.$store.getters.get_user_info != 'string') {
-					user_info = this.$store.getters.get_user_info;
-				} else if (this.$store.getters.get_user_info != "") {
-					user_info = JSON.parse(this.$store.getters.get_user_info);
-				}
+				user_info=this.getCustomerUserInfo();
 
-				if (user_info) {
+				if(user_info){
 					this.$websocket.send(JSON.stringify({
 						type: 'init',
 						data: {
@@ -66,55 +70,71 @@
 						}
 					}));
 				}
-
-
-				this.$store.dispatch("SET_SOCKET_OPEN", true);//列表下标
+		
+			
+				this.$store.dispatch("SET_SOCKET_OPEN",true);//列表下标  
 				this.heatBeat();
 			},
 
 			/*******************************************/
 			//连接关闭触发
-			socket_close(e) {
-				console.log('断开连接', e);
+			socket_close(e){
+				console.log('断开连接',e);
 				//this.init()
 				this.reconnect();
 			},
+			getVisitorList(){
+				this.kfuser_info=this.getCustomerUserInfo();
+				this.$websocket.send(JSON.stringify({
+						type: 'kfusersmaps',
+						data: {
+							kfuid:  this.kfuser_info.id
+						}
+					}));
+			},
 
 			/******************************************/
 			//数据接收
-			websocketonmessage(e) {
+			websocketonmessage(e){
 				this.heatBeat();//收到消息会刷新心跳检测,如果一直收到消息,就推迟心跳发送
 				const redata = JSON.parse(e.data);//接收数据源
+				if(!redata) {
+					return
+				}
 				//
-				if (redata.message_type == "ping") {
+				if(redata.message_type == "ping"){
 					this.$websocket.send('{"type":"pong"}')
 					return false;
 				}
 
-				if (redata.type == "pong") return false;
-				if (redata.type != "pong" || redata.message_type != "ping") {
-					console.log(redata);
+				if(redata.type == "pong") return false;
+				if(redata.type != "pong" || redata.message_type != "ping"){
+		
+					if(redata.message_type === 'connct') {
+						this.$store.dispatch("SET_SESSSION_USER", redata.data.user_info);
+					}
 				}
+				this.getVisitorList();
+				console.log(redata);
 				let getters = this.$store.getters;
+				console.log({'getters':this.$store})
 				//获取vuex数据
 				let session = getters.get_session;//会话列表
-				let offline = getters.get_offline;//离线列表
-				let sessionType = getters.get_type;//选择状态(会话/离线)
-				let dataIndex = getters.get_num;//列表下标
-				let current_session = getters.get_current;//当前会话
-				let session_name = getters.get_session_name;//当前用户名
-
-				this.$store.dispatch("SET_SESSION_MESSAGE", JSON.parse(e.data));
+				let offline  = getters.get_offline;//离线列表
+				let sessionType  = getters.get_type;//选择状态(会话/离线)
+				let dataIndex  = getters.get_num;//列表下标
+				let current_session  = getters.get_current;//当前会话
+				let session_name  = getters.get_session_name;//当前用户名
+				this.$store.dispatch("SET_SESSION_MESSAGE",JSON.parse(e.data));
 
 				// 用户接入数据
-				if (redata.message_type == "connect") {
+				if(redata.message_type == "connect"){
 					this.$message({
 						message: '访客已进入对话',
 						type: 'success'
 					});
-
-					let _this = this;
-					let arr = [
+					let _this  = this;
+					let arr =[
 						redata.data,
 						offline,
 						session,
@@ -123,33 +143,33 @@
 						current_session,
 						session_name,
 					]
-					_this.$public.visitorsConnect(arr, function (data) {
+					_this.$public.visitorsConnect(arr,function(data){
 						//离线匹配列表访客链接回调
-						_this.$store.dispatch("SET_OFFLINE", data);
+						_this.$store.dispatch("SET_OFFLINE",data);
 
-					}, function (data, session, offline, type, num, dataList, name) {
-						//将用户添加到会话列表中
+					},function(data,session,offline,type,num,dataList,name){
+						//将用户添加到会话列表中 
 						// console.log('接入用户昵称',name);
-						if (name) {
+						if(name){
 							data.user_info.name = name;
-							_this.$store.dispatch("SET_SESSION_NAME", name);//当前会话对象名
+							_this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
 						}
 
 						session.push(data.user_info);
 						//获取接入的用户信息
 						//_this.get_user_info(list);
 						//获取接入的用户信息写入vuex
-						_this.$store.dispatch("SET_SESSION", session);//会话列表
-						_this.$store.dispatch("SET_OFFLINE", offline);//离线列表
-						_this.$store.dispatch("SET_TYPE", type);//选择类型(会话/离线)
-						_this.$store.dispatch("SET_NUM", num);//列表下标
-						_this.$store.dispatch("SET_CURRENT", dataList);//当前会话数据
+						_this.$store.dispatch("SET_SESSION",session);//会话列表
+						_this.$store.dispatch("SET_OFFLINE",offline);//离线列表
+						_this.$store.dispatch("SET_TYPE",type);//选择类型(会话/离线)
+						_this.$store.dispatch("SET_NUM",num);//列表下标
+						_this.$store.dispatch("SET_CURRENT",dataList);//当前会话数据
 
 					})
 				}
 
 				//登录验证失败跳转登录页面
-				if (redata.message_type == 'checkfalse') {
+				if(redata.message_type == 'checkfalse'){
 					// this.$router.push({
 					// 	path:'/login',
 					// 	query: { pid:escape("这就是一个编码没有什么用啊") }
@@ -157,9 +177,9 @@
 				}
 
 				//用户离线后会话窗口切换
-				if (redata.message_type == "userClose") {
-					let _this = this;
-					let arr = [
+				if(redata.message_type == "userClose"){
+					let _this =this;
+					let	arr= [
 						redata.data,
 						session,
 						offline,
@@ -168,26 +188,27 @@
 						session_name,
 						current_session,
 					]
-					_this.$public.userOffline(arr, function (session, offline, type, index, name, list, userInfo) {
-						_this.$store.dispatch("SET_CURRENT", list);//当前会话数据
-						_this.$store.dispatch("SET_SESSION_NAME", name);//当前会话对象名
-						_this.$store.dispatch("SET_NUM", index);
-						_this.$store.dispatch("SET_TYPE", type);
-						_this.$store.dispatch("SET_SESSION", session);
-						_this.$store.dispatch("SET_OFFLINE", offline);
+					_this.$public.userOffline(arr,function(session,offline,type,index,name,list,userInfo){
+						_this.$store.dispatch("SET_CURRENT",list);//当前会话数据
+						_this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
+						_this.$store.dispatch("SET_NUM",index);
+						_this.$store.dispatch("SET_TYPE",type);
+						_this.$store.dispatch("SET_SESSION",session);
+						_this.$store.dispatch("SET_OFFLINE",offline);
 						// _this.get_user_info(userInfo);
 					})
 				}
 
 
 				//用户会话结束窗口切换
-				if (redata.message_type == "delUser") {
+				if(redata.message_type == "delUser"){
 					this.$message({
 						message: '访客已退出会话',
 						type: 'warning'
 					});
-					let _this = this;
-					let arr = [
+
+					let _this =this;
+					let	arr= [
 						redata.data,
 						session,
 						offline,
@@ -196,53 +217,50 @@
 						session_name,
 						current_session,
 					]
-					_this.$public.sessionEnd(arr, function (session, offline, type, index, name, list, userInfo) {
-						console.log('session', session);
-						console.log('offline', offline);
-						_this.$store.dispatch("SET_CURRENT", list);//当前会话数据
-						_this.$store.dispatch("SET_SESSION_NAME", name);//当前会话对象名
-						_this.$store.dispatch("SET_NUM", index);
-						_this.$store.dispatch("SET_TYPE", type);
-						_this.$store.dispatch("SET_SESSION", session);
-						_this.$store.dispatch("SET_OFFLINE", offline);
+					_this.$public.sessionEnd(arr,function(session,offline,type,index,name,list,userInfo){
+						console.log('session',session);
+						console.log('offline',offline);
+						_this.$store.dispatch("SET_CURRENT",list);//当前会话数据
+						_this.$store.dispatch("SET_SESSION_NAME",name);//当前会话对象名
+						_this.$store.dispatch("SET_NUM",index);
+						_this.$store.dispatch("SET_TYPE",type);
+						_this.$store.dispatch("SET_SESSION",session);
+						_this.$store.dispatch("SET_OFFLINE",offline);
 						//	_this.get_user_info(userInfo);
 					})
 				}
 
 				//接收用户消息数据
-				if (redata.message_type == "chatMessage") {
-					const ipc = require('electron').ipcRenderer;
-					ipc.send('haveMessage');
-					console.log(ipc, '123')
+				if(redata.message_type == "chatMessage"){
 					this.Messagenum = this.$store.getters.get_megnum;
 					this.Messagenum = ++this.Messagenum;
 					this.$store.dispatch("SET_MEGNNUM", this.Messagenum);
 					this.receiveAudio();
-					let _this = this;
-					this.$public.receivesMessage(redata.data, session, this.$frce, function (data, chatList, index) {
+					let _this =this;
+					this.$public.receivesMessage(redata.data,session,this.$frce,function(data,chatList,index){
 						//判断是否是当前对话信息
-						if (dataIndex == index) {
-							_this.$store.dispatch("SET_CURRENT", chatList.data);//当前会话数据
-						} else {
+						if(dataIndex == index){
+							_this.$store.dispatch("SET_CURRENT",chatList.data);//当前会话数据
+						}else{
 							let num = Number.isInteger(chatList.num) ? chatList.num : 0;
 							// session[index].num = num+1;
-							_this.$set(session[index], 'num', num + 1)
+							_this.$set(session[index],'num',num+1)
 						}
 						//更新会话时间
-						session[index].intime = data.time;
+						session[index].intime =data.time;
 
 						//更新会话列表中最新回复消息
-						if (data.content.text) {
+						if(data.content.text){
 							// _this.$set(chatList,'text',data.content.text)
-							session[index].text = data.content.text;
+							session[index].text =data.content.text;
 						}
-						_this.$store.dispatch("SET_SESSION", session);
+						_this.$store.dispatch("SET_SESSION",session);
 					})
 				}
 				// history
 
 				//reLoginErr
-				if (redata.message_type == "reLoginErr") {
+				if(redata.message_type == "reLoginErr"){
 					// console.log('haha');
 					this.init()
 				}
@@ -252,64 +270,65 @@
 			/**************************************/
 			//连接断开,失败
 			websocketonerror(e) {
-				console.log('失败', e);
-				if (this.linkfailure) {
+				console.log('失败',e);
+				if(this.linkfailure){
 					this.init()
 				}
 			},
 
 			/******************************************/
 			//断开链接数据初始化
-			init() {
-				this.$store.dispatch("SET_STATEVALUE", '在线');
-				this.$store.dispatch("SET_SESSION", []);
-				this.$store.dispatch("SET_USER", '');
-				this.$store.dispatch("SET_OFFLINE", []);
-				this.$store.dispatch("SET_SESSION", []);//会话列表
-				this.$store.dispatch("SET_OFFLINE", []);//离线列表
-				this.$store.dispatch("SET_TYPE", 1);//选择类型(会话/离线)
-				this.$store.dispatch("SET_NUM", 0);//列表下标
-				this.$store.dispatch("SET_CURRENT", []);//当前会话数据
-				this.$store.dispatch("SET_SESSION_NAME", '');//当前会话对象名
-				this.$store.dispatch("SET_SESSION_MESSAGE", {});
-				this.$store.dispatch("SET_NAVSTATE", 'TheCurrentSession');
-				this.$store.dispatch("SET_IS_INIT", false);
+			init(){
+				this.$store.dispatch("SET_STATEVALUE",'在线');
+				this.$store.dispatch("SET_SESSION",[]);
+				this.$store.dispatch("SET_USER",'');
+				this.$store.dispatch("SET_OFFLINE",[]);
+				this.$store.dispatch("SET_SESSION",[]);//会话列表
+				this.$store.dispatch("SET_OFFLINE",[]);//离线列表
+				this.$store.dispatch("SET_TYPE",1);//选择类型(会话/离线)
+				this.$store.dispatch("SET_NUM",0);//列表下标
+				this.$store.dispatch("SET_CURRENT",[]);//当前会话数据
+				this.$store.dispatch("SET_SESSION_NAME",'');//当前会话对象名
+				this.$store.dispatch("SET_SESSION_MESSAGE",{});
+				this.$store.dispatch("SET_NAVSTATE",'TheCurrentSession');
+				this.$store.dispatch("SET_IS_INIT",false);
 				this.$token = '';
 				this.$router.push('/login')
 				this.linkfailure = true;
+				
 				//this.reconnect();
 			},
 
 			/*******************************************/
 			// 接收消息音频提示
 			receiveAudio() {
-				let receive = new Audio();
-				receive.src = this.receiveMuisc;
+				let receive = new Audio()
+				receive.src = "../static/audio/receive.wav";
 				receive.play();
 			},
 			/***************************************/
 			//socket重连
-			reconnect() {
-				if (this.lockReconnect) {   //这里很关键,因为连接失败之后之后会相继触发 连接关闭,不然会连接上两个 WebSocket
+			reconnect(){
+				if(this.lockReconnect){   //这里很关键,因为连接失败之后之后会相继触发 连接关闭,不然会连接上两个 WebSocket
 					return
 				}
 				this.lockReconnect = true;
 				this.reconnectData && clearTimeout(this.reconnectData);
-				this.reconnectData = setTimeout(() => {
+				this.reconnectData = setTimeout(()=>{
 					this.initWebSocket(this.apiToken);
 					this.lockReconnect = false;
-				}, 3000)
+				},3000)
 			},
 
 			/*************************************/
 			//心跳检测
-			heatBeat() {
+			heatBeat(){
 				this.timeoutObj && clearTimeout(this.timeoutObj);
 				this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
-				this.timeoutObj = setTimeout(() => {
+				this.timeoutObj = setTimeout(()=>{
 					// console.log('发送',{type:'ping'});
-					this.$websocket.send(JSON.stringify({type: 'ping'}))   //根据后台要求发送
-					this.serverTimeoutObj = setTimeout(() => {
+					this.$websocket.send(JSON.stringify({type:'ping'}))   //根据后台要求发送
+					this.serverTimeoutObj = setTimeout(()=> {
 						this.$websocket.close(); //如果4秒之后我们没有收到 后台返回的心跳检测数据 断开socket,断开后会启动重连机制
 					}, 4000);
 				}, this.timeout)
@@ -320,10 +339,8 @@
 		},
 		mounted() {
 			Vue.prototype.$socket_open = false;
-			this.apiToken = this.$md5('customer-service' + window.location.origin)
+			this.apiToken = this.$md5('customer-service'+window.location.origin)
 			this.initWebSocket(this.apiToken);
-
-
 			// 获取系统时间
 			//let t = new Date().getTime();
 			//this.get('api'+this.$ports.TIME+'?t='+t).then(res => {
@@ -333,18 +350,19 @@
 			// 		time[0] =(new Date( time[0].replace(/-/g,'/')).getTime()) /1000;
 			// 		sessionStorage.setItem("time",JSON.stringify(time));
 			// 		sessionStorage.setItem("logo",res.data.data.logo);
-
+					
 			// 	}
 			// });
 		},
 		destroyed() {
 			this.lockReconnect = true;
-			this.websock.close()                   //离开路由之后断开websocket连接
+			this.$websocket.close();
+			// this.websock.close()                   //离开路由之后断开websocket连接
 			clearTimeout(this.reconnectData);      //离开清除 timeout
 			clearTimeout(this.timeoutObj);         //离开清除 timeout
 			clearTimeout(this.serverTimeoutObj);   //离开清除 timeout
 			localStorage.removeItem('user');
-			// console.log(123)
+			// console.log(123) 
 		}
 	}
 </script>

+ 1 - 1
service_exe/src/renderer/api/http.js

@@ -4,7 +4,7 @@ import qs from 'qs'  // 序列化字符串
 // 请求超时时间
 axios.defaults.timeout = 10000
 // 线上
-let Base = 'http://kfadmin.bocai186.com'
+let Base = 'http://manage.281570.com'
 // 开发
 //let Base = 'http://sports.5gogo.com'
 function headerUrl (url) {

+ 3 - 1
service_exe/src/renderer/api/ports.js

@@ -11,6 +11,7 @@ export default {
 
     
   },
+
   // 历史会话
   SessionHistory:{
     historyList:'/service/history/historyList',//历史会话列表
@@ -55,6 +56,7 @@ export default {
   overview:{
     allConversation:"/service/history/allConversation",
     chatByTime:'/service/history/chatByTime',
-  }
+  },
+  checkValidCodeEnabledUrl:"/index/index/getConfigs"
 
 }

+ 29 - 0
service_exe/src/renderer/assets/common.js

@@ -0,0 +1,29 @@
+import md5 from 'js-md5';
+import http from '../api/http';
+import ports from '../api/ports.js';
+export default{
+    //检测验证码是否开启
+    checkValidCodeEnabled(cb){
+        let params={
+            headers: {
+                apiToken:this.getApiToken('index','index','getConfigs')
+            }
+        };
+        http.get(ports.checkValidCodeEnabledUrl,params).then(res => {
+           
+            if (res.data.code == 1) {
+                //私有库
+                try{
+                    cb(res.data.data.checkcodeflag);
+                }catch(ex){
+                    cb(0);
+                }
+            }
+      
+        });
+       
+    },
+    getApiToken(m,c,act){
+       return md5(act+'customer-service'+c+m);
+    }
+}

+ 1 - 1
service_exe/src/renderer/components/hader.vue

@@ -161,7 +161,7 @@
 				user_info: '',//
 				userID:null,
 				unreadNum:null, // 未读数量
-				img_http:'http://kfadmin.bocai186.com',//图片路径域
+				img_http:'http://manage.281570.com',//图片路径域
 				innerDrawer:false,//会话总览抽屉开关
 				// img_http: 'http://192.168.2.187:8090',//图片路径域
 				dataTree: [],

+ 1 - 1
service_exe/src/renderer/components/historicalRecord.vue

@@ -132,7 +132,7 @@ export default {
             alarm:'',//评价谢谢
             account:'',//用户信息
             // imgsrc:'http://192.168.2.186:8090'
-            imgsrc:'http://kfadmin.bocai186.com',//图片路径域 
+            imgsrc:'http://manage.281570.com',//图片路径域 
             isShowBt:false,//显示加载按钮
             currentPage:'',//当前页数
         }

+ 2 - 1
service_exe/src/renderer/components/leftNav.vue

@@ -32,7 +32,7 @@
 				megnum: 0,
 				showMeg: false,
 				logo: '',
-				img_http: 'http://kfadmin.bocai186.com',//图片路径域
+				img_http: 'http://manage.281570.com',//图片路径域
 				// img_http: 'http://192.168.2.187:8090',//图片路径域
 				titleActive: "TheCurrentSession",
 				data: [
@@ -90,6 +90,7 @@
 				this.$router.push({path, query: {pid: escape("这就是一个编码没有什么用啊")}});
 			}
 		},
+
 		computed: {
 			getTitleActive() {
 				return this.$store.getters.get_megnum

+ 11 - 0
service_exe/src/renderer/css/index.css

@@ -2,6 +2,17 @@
 * {
   padding: 0;
   margin: 0;
+  -o-user-select: none;
+  -moz-user-select: none;
+  /*火狐 firefox*/
+  -webkit-user-select: none;
+  /*webkit浏览器*/
+  -ms-user-select: none;
+  /*IE10+*/
+  -khtml-user-select: none;
+  /*早期的浏览器*/
+  user-select: none;
+  /*  */
   box-sizing: border-box;
 }
 body,img{

+ 12 - 12
service_exe/src/renderer/main.js

@@ -1,39 +1,39 @@
+// The Vue build version to load with the `import` command
+// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
 import Vue from 'vue'
 import App from './App'
 import router from './router';
 import store from './store';
 import ElementUI from 'element-ui';
-import frce from '../../static/frce';
+import frce from '../static/frce';
 import http from './api/http';
 // import publicMethods from '../static/publicMethods';
 import 'element-ui/lib/theme-chalk/index.css';
 import axios from 'axios'; //引入axios
 import ports from './api/ports.js'; //api接口文档
-import publicMethods from '../../static/publicMethods.js';
+import publicMethods from '../static/publicMethods.js';
 import md5 from 'js-md5';
+import comm from './assets/common.js';
 Vue.use(ElementUI);
 
-if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
-
-Vue.config.productionTip = false
-// The Vue build version to load with the `import` command
-// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
-
-
 Vue.config.productionTip = false;
 // 注册表情包数组
 Vue.prototype.$frce = frce.frce;
 // 注册加密文档
 Vue.prototype.$md5 = md5;
+
 // 公共方法
 Vue.prototype.$ports = ports;
 Vue.prototype.$http = http;
 Vue.prototype.$public = publicMethods;
+Vue.prototype.$comm=comm;
 /* eslint-disable no-new */
-
 new Vue({
-  components: { App },
+  el: '#app',
   router,
   store,
+  components: {
+    App
+  },
   template: '<App/>'
-}).$mount('#app')
+})

+ 2 - 2
service_exe/src/renderer/pages/LeaveMessage.vue

@@ -118,7 +118,7 @@
 										</el-col>
 										<el-col>
 											<el-upload style="margin:10px;"
-													action="http://kfadmin.bocai186.com/index/upload/uploadImg"
+													action="http://manage.281570.com/index/upload/uploadImg"
 													:before-upload="beforeAvatarUpload"
 													:on-change='uploadChange'
 													:on-success='uploadSuccess'
@@ -238,7 +238,7 @@
 				dialogImageUrl: '',
 				userInfo: [], //用户信息
 				getUserItem: [],
-				img_http: 'http://kfadmin.bocai186.com',//图片路径域
+				img_http: 'http://manage.281570.com',//图片路径域
 				// img_http: 'http://192.168.2.187:8090',//图片路径域
 				fileList:[],
 				imgUrl:'',

+ 129 - 36
service_exe/src/renderer/pages/TheCurrentSession.vue

@@ -15,13 +15,13 @@
 							</template>
 							<div :class="{session_choose:dataIndex ==index &&  sessionType ==1}"
 								 class="user session_style" @click="chooseDialogue(1,index)"
-								 v-for="(item,index) in sessionList">
+								 v-for="(item,index) in sessionList" :key="index">
 								<div class="row allAlignment item-center">
 									<span style="font-weight:bold;color:#666;font-size:14px;">{{item.name}}</span>
-									<span style="color:#999;font-size:12px;">{{item.intime}}</span>
+									<span style="color:#999;font-size:.12px;">{{item.intime}}</span>
 								</div>
 								<div class="row allAlignment item-center">
-									<div style="width:90%;font-size:12px;" class="ellipsis">
+									<div style="width:90%;font-size:.12px;" class="ellipsis">
 										<span v-html="item.text"></span>
 									</div>
 									<span v-if="item.num > 0" class="markNumber">{{item.num}}</span>
@@ -34,7 +34,7 @@
 							</template>
 							<div :class="{session_choose:dataIndex == index &&  sessionType ==2}"
 								 class="user session_style" @click="chooseDialogue(2,index)"
-								 v-for="(item,index) in offlineList">
+								 v-for="(item,index) in offlineList" :key="index">
 								<div class="row allAlignment item-center">
 									<span style="font-weight:bold;color:#999;font-size:14px;">{{item.name}}</span>
 									<span style="color:#999;font-size:12px;">{{item.intime}}</span>
@@ -95,6 +95,10 @@
 					</div>
 
 					<div class="chat-box scroll" id='chat_box'>
+						<div class="history-info">
+							<el-button type="text" size="small" :loading="historyLoading" 
+							@click="getHistoryInfo">{{historyProcess}}</el-button>
+						</div>
 						<div v-for="(item,index) in data" :key="index">
 							<!-- 系统转接 -->
 							<!-- <div class="row center" v-if="item.type == 'system'">
@@ -103,7 +107,7 @@
 
 							<!-- 用户消息 -->
 							<div style="padding:0 10px;margin-top:20px;" v-if="item.type == 'user'">
-								<div style="height:37px; font-size:12px; color:#bbb;"
+								<div style="height:37px;font-size:.12px;color:#bbb;"
 									 class="row item-center"
 								>{{item.time}}
 								</div>
@@ -169,7 +173,7 @@
 						<textarea draggable="false" class="input scroll" id="input" v-model.trim="inputValue"
 								  @keyup.enter="listenEnter($event)" @keyup.ctrl.enter="lineFeed()"></textarea>
 						<div class="row rightAlignment" style="width: 100%;">
-							<div @click="sendMessage()" class="msgInputBtn row center">发送</div>
+							<div @click="sendMessage()" @keyup.enter="sendMessage" class="msgInputBtn row center">发送</div>
 						</div>
 					</div>
 					<!-- 发送消息音频提示 -->
@@ -251,6 +255,7 @@
 						<p @dblclick="get_ip_Info" class="get_ip" :data-clipboard-text="terminal_IP.ip">
 							IP地址:{{terminal_IP.ip}}</p>
 						<p>来源终端:{{terminal_IP.system}}</p>
+						<p>来源地区:{{terminal_IP.source}}</p>
 					</div>
 
 					<div style="color:#666;font-weight:bold;font-size:14px; margin-top:30px;">用户信息</div>
@@ -328,13 +333,12 @@
 <script>
 	import "@/css/index.css";
 	import Clipboard from 'clipboard';
-	import {clipboard} from 'electron'
-
 	import {mapState, mapGetters} from 'vuex'; //先要引入
 	import leftNav from "@/components/leftNav";
 	import hader from "@/components/hader";
 	import messageCenter from "@/components/messageCenter";
-	import sendAPP from '../../../static/audio/send.wav'
+	import historicalRecord from "@/components/historicalRecord";
+
 	export default {
 		name: "TheCurrentSession",
 		data() {
@@ -352,7 +356,7 @@
 				lineUp: [],//排队列表
 				conversationId: '',//会话工单
 				session_user_info: {},//当前会话用户信息
-				img_http: 'http://kfadmin.bocai186.com',//图片路径域
+				img_http: 'http://manage.281570.com',//图片路径域
 				// img_http: 'http://192.168.2.187:8090',//图片路径域
 				fit: 'scale-down',//图片渲染样式
 				is_eva_btn: true,//
@@ -376,7 +380,9 @@
 				showHistoryList: false,
 				historyList: [],
 				historyTime:'',
-				sendMuisc: sendAPP
+				historyLoading: false, // 历史记录加载
+				historyProcess: '更多历史记录', // 查看历史历史记录或者加载中
+				historyPage: 1 // 当前的历史记录页
 			}
 		},
 		methods: {
@@ -648,6 +654,11 @@
 				//console.log(12313);
 				this.websocketsend(JSON.stringify({"type": "getkfonlines"}))
 			},
+			getPlatformCN(name){
+				let platforms={'android':'安卓','ios':'苹果','pc':'电脑'};
+				
+				return platforms[name];
+			},
 
 			/*****************切换用户会话对象******************/
 			chooseDialogue(type, index) {
@@ -662,15 +673,17 @@
 						order_id = this.sessionList[index].id;
 						this.$set(this.sessionList[index], 'num', 0);
 						this.terminal_IP = {
-							system: this.sessionList[index].system + '-' + this.sessionList[index].browse,
-							ip: this.sessionList[index].ip
+							system: this.getPlatformCN(this.sessionList[index].system) + '-' + this.sessionList[index].browse,
+							ip: this.sessionList[index].ip,
+							source:this.sessionList[index].ipinfo
 						}
 					} else if (type == 2) {
 						data = this.offlineList[index].data;
 						order_id = this.offlineList[index].id;
 						this.terminal_IP = {
-							system: this.offlineList[index].system + '-' + this.offlineList[index].browse,
-							ip: this.offlineList[index].ip
+							system: this.getPlatformCN(this.offlineList[index].system) + '-' + this.offlineList[index].browse,
+							ip: this.offlineList[index].ip,
+							source:this.offlineList[index].ipinfo
 						}
 					}
 					this.$store.dispatch("SET_CURRENT", data);//当前会话数据
@@ -687,6 +700,7 @@
 			/***************关闭当前和用户聊天对话***************/
 			open() {
 				let _this = this;
+				// console.log(this.sessionList)
 				if (this.sessionType == 1) {
 					if (this.sessionList.length < 1) return
 				} else {
@@ -703,7 +717,7 @@
 					let data = {
 						"type": "kfCloseUser",
 						data: {
-							to_id,
+							to_id: '',
 							kf_id: "KF" + _this.user_info.id,
 							group_id: _this.user_info.group_id,
 							conversationId: conversationId,
@@ -729,10 +743,10 @@
 					
 					this.websocketsend(JSON.stringify(data))
 				}).catch(() => {
-					// this.$message({
-					//   type: 'info',
-					//   message: '已取消删除'
-					// });
+					this.$message({
+					  type: 'info',
+					  message: '已取消删除'
+					});
 				});
 			},
 
@@ -745,12 +759,17 @@
 			// 消息发送声音提示
 			sendAudio() {
 				let send = new Audio()
-				send.src = this.sendMuisc
+				send.src = "../../static/audio/send.wav"
 				send.play()
 			},
 
 			/*********************发送消息*********************/
 			sendMessage() {
+				console.log('websocket',this.$websocket.readyState)
+				console.log('sessionType', this.sessionType)
+				if(this.sessionType == 1) {
+					console.log("???")
+				}
 				console.log(this.inputValue);
 				if (!this.inputValue) return;
 				if (this.sessionType == 2) {
@@ -800,7 +819,8 @@
 						type: 'service', content: {
 							text: this.$public.turnFace(this.inputValue, this.$frce),
 							img: '',
-						}, time: this.time[1]
+						}, 
+						// time: this.time[1]
 					});
 					//this.data = [];
 					//标记当前会话位置
@@ -819,7 +839,7 @@
 					//计算关键词次数
 					this.sensitiveNumber = this.sensitiveNumber + sensitive_data.num;
 				}
-
+				this.historyProcess = '更多历史消息' // 发送信息成功后改变说明
 
 			},
 
@@ -1025,7 +1045,7 @@
 					item = items[0];
 					// 保存在剪贴板中的数据类型
 					types = clipboardData.types || [];
-					for (; i < types.length; i++) {
+					for (let i=0; i < types.length; i++) {
 						if (types[i] === 'Files') {
 							item = items[i];
 							break;
@@ -1094,10 +1114,9 @@
 			},
 
 			get_name() {
-				var clipboard = new Clipboard(".user_text");
-				// clipboard
+				var clipboard = new Clipboard(".user_text")
 				clipboard.on('success', e => {
-					console.log('复制成功',e.text)
+					// console.log('复制成功')
 					this.$message({
 						message: '复制成功',
 						type: 'success'
@@ -1119,7 +1138,9 @@
 			/****************访问信息和评价状态***************/
 			accessTerminal(data) {
 				if (this.sessionType == 1) {
+					console.log('dataIndex', this.dataIndex)
 					let List = this.sessionList[this.dataIndex];
+					console.log('list', List)
 					if (data == 'eva') {
 						if (!List) return false
 						// console.log(List,'对话信息');
@@ -1138,8 +1159,10 @@
 					} else {
 						if (List) {
 							this.terminal_IP = {
-								system: List.system + '-' + List.browse,
-								ip: List.ip
+								system: this.getPlatformCN(List.system) + '-' + List.browse,
+								ip: List.ip,
+								source:List.ipinfo
+
 							}
 						} else {
 							this.terminal_IP = {}
@@ -1149,16 +1172,73 @@
 					let List = this.offlineList[this.dataIndex];
 					if (List) {
 						this.terminal_IP = {
-							system: List.system + '-' + List.browse,
-							ip: List.ip
+							system: this.getPlatformCN(List.system) + '-' + List.browse,
+								ip: List.ip,
+								source:List.ipinfo
 						}
 					} else {
 						this.terminal_IP = {}
 					}
 					// }
 				}
+			},
+			getHistoryInfo() { // 获取历史数据
+				let obj = {
+					headers: {
+						apiToken: this.$md5("userhistory" + "customer-service" + "history" + "service"),
+						// 'apiToken': this.$md5("historylist" + "customer-service" + "history" + "service"),
+						userToken: this.token
+					},
+					params: {
+						// user_name: this.user_info.account_name,
+						account_id: 'KF' + this.user_info.id,
+						currentPage: this.historyPage,
+						pageSize: 10
+					}
+				};
+				this.historyLoading = true
+				this.historyProcess = '加载中'
+				this.$http.get(this.$ports.history.userHistory,obj).then(res => {
+					if(res.data.code == 1) {
+						if(!res.data.data.total ) { // 历史记录总数
+							this.historyProcess = '没有更多历史记录'
+							this.historyLoading = false
+						} else {
+							// 遍历封装数据
+							if(this.historyPage > res.data.data.countPage) {
+								this.historyProcess = '没有更多历史记录'
+							    this.historyLoading = false
+							} else {
+								let list = res.data.data.list
+								if(list) {
+									for(let item of list) {
+										let historyItem = {
+											type: item.from_id.substr(0, 2) === 'KF' ? 'service' : 'user',
+											time: this.$public.customFormatDateTime(item.time_line),
+											content: JSON.parse(item.content)
+										}
+										this.data.unshift(historyItem)
+									}
+									this.historyPage ++ ;
+									this.historyProcess = '更多历史记录'
+									this.historyLoading = false;
+								} else {
+									this.historyProcess = '没有更多历史记录'
+							    	this.historyLoading = false
+								}
+							}
+						}
+					}
+				}).catch(err => {
+					this.$message.error(err.message)
+					this.historyLoading = false;
+					this.historyProcess = '更多历史记录'
+				})
 			}
 		},
+		created() {
+			this.get_vuex_info();
+		},
 		/**
 		 * 挂载前执行
 		 */
@@ -1199,8 +1279,14 @@
 				this.chatMessage(e)
 			},
 
-			sessionList(e) {
-				this.accessTerminal(e)
+			// sessionList(e) {
+			// 	this.accessTerminal(e)
+			// },
+			sessionList: {
+				handler(val) {
+					this.accessTerminal(val)
+				},
+				deep: true
 			},
 			offlineList(e) {
 				this.accessTerminal(e)
@@ -1222,7 +1308,7 @@
 				offlineList: 'get_offline',
 				dataIndex: 'get_num',
 				sessionType: 'get_type',
-				get_user_info: 'get_session_user',
+				get_user_info: 'get_session_user', // 会话人详细信息
 				// is_eva_btn:'get_is_eva_btn',
 			}),
 
@@ -1240,7 +1326,8 @@
 		components: {
 			leftNav,
 			hader,
-			messageCenter
+			messageCenter,
+			historicalRecord
 		}
 	};
 </script>
@@ -1415,6 +1502,8 @@
 
 	.user_info_box {
 		margin: 10px 0;
+		display: flex;
+		justify-content: flex-start;
 	}
 
 	.title_span {
@@ -1586,7 +1675,6 @@
 	.userData p {
 		line-height: 30px;
 		display: block;
-		width: 100%;
 	}
 
 	.message_box {
@@ -1672,4 +1760,9 @@
 	.rightAlignment .el-button {
 		border: none;
 	}
+	.history-info {
+		color: #5399f5;
+		text-align: center;
+		margin-top: 5px;
+	}
 </style>

+ 278 - 256
service_exe/src/renderer/pages/login.vue

@@ -1,269 +1,291 @@
 <template>
-	<div >
-		<form action="">
-			<div class="login">
-				<div class="loginBg">
-					<img src="@/assets/img/loginBg.png" />
-				</div>
-				<div class="loginBox">
-					<div class="row center" style="height:48px;">
-						<img :src="img_http + logo" alt="" style="width: 30px; height: 30px;">
-					</div>
-					<div class="row center"><span style="font-size:16px;color:#666;">客服系统客服登录</span></div>
-					<div class="box row center">
-						<div class="boxData" :class="0?'errBd':''">
-							<input type="text" v-model="account" placeholder="账号">
-							<img src="@/assets/img/account.png">
-							<p v-if="0" style="color:#f60;font-size:14px;margin-top:5px;margin-left:3px;">账号不存在</p>
-						</div>
-					</div>
-					<div class="box row center">
-						<div class="boxData" :class="0?'errBd':''">
-							<input  type="password" v-model="password" placeholder="密码">
-							<img src="@/assets/img/password.png">
-							<p v-if="0" style="color:#f60;font-size:14px;margin-top:5px;margin-left:3px;">密码错误,请重新输入</p>
-						</div>
-					</div>
-					<div class="box row center" v-if="showSecurityCode">
-						<div class="boxData" :class="0?'errBd':''">
-							<input maxlength="6" @keyup.enter="loginBtn()" @blur="testCode()" type="text" v-model="securityCode" placeholder="验证码">
-							<img src="@/assets/img/password.png">
-							<p v-if="0" style="color:#f60;font-size:14px;margin-top:5px;margin-left:3px;">验证码错误,请重新输入</p>
-						</div>
-					</div>
-					<div class="box row center">
-						<div class="btn row center" @click="loginBtn()">登录</div>
-					</div>
-				</div>
-			</div>
-		</form>
-
-	</div>
+  <div>
+    <form action>
+      <div class="login">
+        <div class="loginBg">
+          <img src="@/assets/img/loginBg.png" />
+        </div>
+        <div class="loginBox">
+          <div class="row center" style="height:48px;">
+            <img :src="img_http + logo" alt style="width: 30px; height: 30px;" />
+          </div>
+          <div class="row center">
+            <span style="font-size:16px;color:#666;">客服系统客服登录</span>
+          </div>
+          <div class="box row center">
+            <div class="boxData" :class="0?'errBd':''">
+              <input type="text" v-model="account" placeholder="账号" />
+              <img src="@/assets/img/account.png" />
+              <p v-if="0" style="color:#f60;font-size:14px;margin-top:5px;margin-left:3px;">账号不存在</p>
+            </div>
+          </div>
+          <div class="box row center">
+            <div class="boxData" :class="0?'errBd':''">
+              <input type="password" v-model="password" placeholder="密码" />
+              <img src="@/assets/img/password.png" />
+              <p
+                v-if="0"
+                style="color:#f60;font-size:14px;margin-top:5px;margin-left:3px;"
+              >密码错误,请重新输入</p>
+            </div>
+          </div>
+          <div class="box row center" v-if="showSecurityCode">
+            <div class="boxData" :class="0?'errBd':''">
+              <input
+                maxlength="6"
+                @keyup.enter="loginBtn()"
+                @blur="testCode()"
+                type="text"
+                v-model="securityCode"
+                placeholder="验证码"
+              />
+              <img src="@/assets/img/password.png" />
+              <p
+                v-if="0"
+                style="color:#f60;font-size:14px;margin-top:5px;margin-left:3px;"
+              >验证码错误,请重新输入</p>
+            </div>
+          </div>
+          <div class="box row center">
+            <div class="btn row center" @click="loginBtn()">登录</div>
+          </div>
+        </div>
+      </div>
+    </form>
+  </div>
 </template>
 
 <script>
-	import "@/css/index.css";
-	import Vue from 'vue';
-	export default {
-		name: "login",
-		data() {
-			return {
-				account:'',//账号
-				password:'',//密码
-				securityCode: '', // 验证码
-				time:'',
-				loading:false,
-				showSecurityCode:false,
-				logo: '',
-				verifySystem:"",
-				verifySystemId:"",
-				img_http:'http://kfadmin.bocai186.com',//图片路径域
-				// img_http: 'http://192.168.2.187:8090',//图片路径域
-			}
-		},
-		methods:{
-			testCode(){
-				if(this.showSecurityCode){
-					if (!(/^[0-9]+$/.test(this.securityCode))) {
-						this.$message.error('验证码错误!')
-						this.securityCode = '';
-					}
-				}
-			},
-			loginBtn(){
-				this.time = sessionStorage.getItem('time');
-				if(this.$store.getters.get_socket_open){
-					let apiToken = this.$md5('customer-service' + window.location.origin)
-					if(this.account && this.password){
-						//进程加载条
-						const loading = this.$loading({
-							lock: true,
-							text: 'Loading',
-							spinner: 'el-icon-loading',
-							background: 'rgba(0, 0, 0, 0.7)'
-						});
+import "@/css/index.css";
+import Vue from "vue";
+export default {
+  name: "login",
+  data() {
+    return {
+      account: "", //账号
+      password: "", //密码
+      securityCode: "", // 验证码
+      time: "",
+      loading: false,
+      showSecurityCode: false,
+      logo: "",
+      verifySystem: "",
+      verifySystemId: "",
+      img_http: "http://manage.281570.com" //图片路径域
+      // img_http: 'http://192.168.2.187:8090',//图片路径域
+    };
+  },
+  methods: {
+    testCode() {
+      if (this.showSecurityCode) {
+        if (!/^[0-9]+$/.test(this.securityCode)) {
+          this.$message.error("验证码错误!");
+          this.securityCode = "";
+        }
+      }
+    },
+    loginBtn() {
+      this.time = sessionStorage.getItem("time");
+      if (this.$store.getters.get_socket_open) {
+        let apiToken = this.$md5("customer-service" + window.location.origin);
+        if (this.account && this.password) {
+          //进程加载条
+          const loading = this.$loading({
+            lock: true,
+            text: "Loading",
+            spinner: "el-icon-loading",
+            background: "rgba(0, 0, 0, 0.7)"
+          });
+
+          // console.log(this.verifySystemId)
+          // console.log(this.verifySystem)
+          // console.log(this.securityCode)
+          let parmas;
+          if (this.showSecurityCode) {
+            parmas = {
+              username: this.account,
+              password: this.password,
+              securityCode: this.securityCode
+            };
+          } else {
+            parmas = {
+              username: this.account,
+              password: this.password,
+              verifySystemId: this.verifySystemId,
+              verifySystem: this.verifySystem
+            };
+          }
+          this.$http.post(this.$ports.login, parmas).then(res => {
+            if (res.data.code == 1) {
+              this.$store.dispatch("SET_USER", res.data.data.user);
+              this.$store.dispatch("SET_IS_INIT", true);
+              this.$websocket.send(
+                JSON.stringify({
+                  type: "init",
+                  data: {
+                    uid: "KF" + res.data.data.user.id,
+                    group: res.data.data.user.group_id,
+                    token: res.data.data.user.token,
+                    name: res.data.data.user.user_name,
+                    avatar: res.data.data.user.user_avatar
+                  }
+                })
+              );
+              this.$router.push({
+                path: "/",
+                query: { pid: escape("这就是一个编码没有什么用啊") }
+              });
+            } else if (res.data.code == 100) {
+              this.$message.success(res.data.msg);
+              loading.close();
+            } else {
+              this.$notify({
+                title: "错误",
+                message: res.data.msg,
+                type: "error",
+                duration: 2000
+              });
+            }
 
-						// console.log(this.verifySystemId)
-						// console.log(this.verifySystem)
-						// console.log(this.securityCode)
-						let parmas;
-						if(this.showSecurityCode){
-							 parmas = {
-								username:this.account,
-								password:this.password,
-								securityCode:this.securityCode,
-							}
-						}else {
-							parmas = {
-								username:this.account,
-								password:this.password,
-								verifySystemId:this.verifySystemId,
-								verifySystem:this.verifySystem,
-							}
-						}
-						this.$http.post(this.$ports.login, parmas).then((res)=>{
+            loading.close();
+          });
+        } else {
+          this.$notify({
+            title: "错误提示!",
+            message: "请输入您的账号和密码",
+            type: "error",
+            duration: 2000
+          });
+        }
+      } else {
+        this.$notify({
+          title: "错误提示!",
+          message: "网路链接错误",
+          type: "error",
+          duration: 2000
+        });
+      }
+    },
+    /**************************************/
+    //连接建立
+    websocketonopen() {
+      this.$websocket.onopen();
+      //console.log('已经链接')
+    }
+  },
+  mounted() {
+    // 判断验证码参数
+    let SystemId = this.$public.getQueryString("id");
+    let System = this.$public.getQueryString("code");
 
-							if(res.data.code == 1){
-								this.$store.dispatch("SET_USER",res.data.data.user);
-								this.$store.dispatch("SET_IS_INIT",true);
-								this.$websocket.send( JSON.stringify({
-									type: 'init',
-									data: {
-										uid: 'KF' + res.data.data.user.id,
-										group: res.data.data.user.group_id,
-										token:res.data.data.user.token,
-										name: res.data.data.user.user_name,
-										avatar:res.data.data.user.user_avatar,
-									}
-								}))
-								this.$router.push({
-									path:'/',
-									query: { pid:escape("这就是一个编码没有什么用啊") }
-								})
-							}else if(res.data.code == 100){
-								this.$message.success(res.data.msg);
-								loading.close();
-							}else{
-								this.$notify({
-									title: "错误",
-									message: res.data.msg,
-									type: "error",
-									duration: 2000
-								});
-							}
+    if (!SystemId && !System) {
+      this.showSecurityCode = true;
+    } else {
+      this.showSecurityCode = false;
+      this.verifySystemId = SystemId;
+      this.verifySystem = System;
+      localStorage.clear();
+      sessionStorage.clear();
+    }
+    this.$comm.checkValidCodeEnabled((data)=> {
+      if (data == 0) {
+        this.showSecurityCode = false;
+      } else {
+        this.showSecurityCode = true;
+      }
+    });
 
-							loading.close();
-						})
-					}else{
-						this.$notify({
-							title: "错误提示!",
-							message: '请输入您的账号和密码',
-							type: "error",
-							duration: 2000
-						});
-					}
-				}else{
-					this.$notify({
-						title: "错误提示!",
-						message: '网路链接错误',
-						type: "error",
-						duration: 2000
-					});
-				}
-			},
-			/**************************************/
-			//连接建立
-			websocketonopen() {
-				this.$websocket.onopen();
-				//console.log('已经链接')
-			},
-		},
-		mounted(){
-			// 判断验证码参数
-			let SystemId = this.$public.getQueryString("id");
-			let System = this.$public.getQueryString("code");
-			if( !SystemId && !System ){
-				this.showSecurityCode = true;
-			}else {
-				this.showSecurityCode = false;
-				this.verifySystemId = SystemId;
-				this.verifySystem = System;
-			}
-			this.$http.get(this.$ports.TIME).then(res => {
-				if (res.data.code == 1) {
-					let time = res.data.data.time.split(' ');
-					time[0] =(new Date( time[0].replace(/-/g,'/')).getTime()) /1000;
-					sessionStorage.setItem("time",JSON.stringify(time));
-					this.logo = res.data.data.logo;
-					sessionStorage.setItem("logo",res.data.data.logo);
-					
-				}
-			});
-			// this.logo = sessionStorage.getItem('logo');
-			//console.log(this.logo, '========logo')
-		}
-	};
+    this.$http.get(this.$ports.TIME).then(res => {
+      if (res.data.code == 1) {
+        let time = res.data.data.time.split(" ");
+        time[0] = new Date(time[0].replace(/-/g, "/")).getTime() / 1000;
+        sessionStorage.setItem("time", JSON.stringify(time));
+        this.logo = res.data.data.logo;
+        sessionStorage.setItem("logo", res.data.data.logo);
+      }
+    });
+   
+  }
+};
 </script>
 
 <style scoped>
-	p {
-		display: inline;
-		margin-block-start: 0;
-		margin-block-end:0;
-		margin-inline-start: 0;
-		margin-inline-end:0;
-	}
+p {
+  display: inline;
+  margin-block-start: 0;
+  margin-block-end: 0;
+  margin-inline-start: 0;
+  margin-inline-end: 0;
+}
 
-	.login {
-		width: 100%;
-		height: 100%;
-	}
-	.loginBg {
-		height: 50%;
-	}
-	.loginBg img {
-		width: 100%;
-		height: 100%;
-	}
-	.loginBox {
-		position: fixed;
-		top: 27%;
-		left: 0px;
-		right: 0px;
-		margin: auto;
-		width:300px;
-		height: 280px;
-		background: #fff;
-		border-radius: 2%;
-		box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
-	}
-	.box{
-		/* margin-top: 40px; */
-		height: 50px;
-	}
-	.boxData{
-		width: 200px;
-		/* height: 70px; */
-		/*border: 1px solid #C6DCFF;*/
-		background: #F6F8FF;
-		position: relative;
-	}
-	.boxData img{
-		position: absolute;
-		left: 6px;
-		top:0;
-		bottom: 0;
-		margin:auto 0;
-		height: 55%;
-	}
-	.boxData input{
-		width: 100%;
-		height: 30px;
-		outline: none;
-		padding-left: 30px;
-		font-size: 14px;
-		color: #999;
-	}
-	.boxData input:focus{
-		color: #666;
-	}
-	.errBd{
-		border: 1px solid #F60
-	}
-	.btn{
-		width: 240px;
-		height: 40px;
-		background:#5399F5;
-		font-size: 18px;
-		color: #fff;
-		border: none;
-	}
-	.btn:hover{
+.login {
+  width: 100%;
+  height: 100%;
+}
+.loginBg {
+  height: 50%;
+}
+.loginBg img {
+  width: 100%;
+  height: 100%;
+}
+.loginBox {
+  position: fixed;
+  top: 27%;
+  left: 0px;
+  right: 0px;
+  margin: auto;
+  width: 300px;
+  height: 280px;
+  background: #fff;
+  border-radius: 2%;
+  box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
+}
+.box {
+  /* margin-top: 40px; */
+  height: 50px;
+}
+.boxData {
+  width: 200px;
+  /* height: 70px; */
+  /*border: 1px solid #C6DCFF;*/
+  background: #f6f8ff;
+  position: relative;
+}
+.boxData img {
+  position: absolute;
+  left: 6px;
+  top: 0;
+  bottom: 0;
+  margin: auto 0;
+  height: 55%;
+}
+.boxData input {
+  width: 100%;
+  height: 30px;
+  outline: none;
+  padding-left: 30px;
+  font-size: 14px;
+  color: #999;
+}
+.boxData input:focus {
+  color: #666;
+}
+.errBd {
+  border: 1px solid #f60;
+}
+.btn {
+  width: 240px;
+  height: 40px;
+  background: #5399f5;
+  font-size: 18px;
+  color: #fff;
+  border: none;
+}
+.btn:hover {
+}
 
-	}
-	
-	
-	.btn:active{
-		background: #1d57dd;
-	}
+.btn:active {
+  background: #1d57dd;
+}
 </style>

+ 2 - 1
service_exe/src/renderer/store/index.js

@@ -1,13 +1,14 @@
 import Vue from 'vue';
 import Vuex from 'vuex';
 import fa from "element-ui/src/locale/lang/fa";
+
 Vue.use(Vuex);
 /**
  * 设置全局访问的state对象
  store
  */
 const state = {
-	user_info: localStorage.getItem('user'), //用户信息
+	user_info: localStorage.getItem('user'), //用户(客服)信息
 	sessionList: [],//会话列表
 	offlineList: [],//离线列表
 	current_session: [],//当前会话详情信息

BIN
service_exe/src/static/audio/receive.wav


BIN
service_exe/src/static/audio/send.wav


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/css/app.b08f3768c9553af70c3dfb15b68c00a8.css


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/css/app.b08f3768c9553af70c3dfb15b68c00a8.css.map


BIN
service_exe/src/static/fonts/element-icons.535877f.woff


BIN
service_exe/src/static/fonts/element-icons.732389d.ttf


+ 4 - 0
service_exe/src/static/frce.js

@@ -0,0 +1,4 @@
+export default{
+    frce : ["[微笑]","[嘻嘻]","[哈哈]","[可爱]","[可怜]","[挖鼻]","[吃惊]","[害羞]","[挤眼]","[闭嘴]","[鄙视]","[爱你]","[泪]","[偷笑]","[亲亲]","[生病]","[太开心]","[白眼]","[右哼哼]","[左哼哼]","[嘘]","[衰]","[委屈]","[吐]","[哈欠]","[抱抱]","[怒]","[疑问]","[馋嘴]","[拜拜]","[思考]","[汗]","[困]","[睡]","[钱]","[失望]","[酷]","[色]","[哼]","[鼓掌]","[晕]","[悲伤]","[抓狂]","[黑线]","[阴险]","[怒骂]","[互粉]","[心]","[伤心]","[猪头]","[熊猫]","[兔子]","[ok]","[耶]","[good]","[NO]","[赞]","[来]","[弱]","[草泥马]","[神马]","[囧]","[浮云]","[给力]","[围观]","[威武]","[奥特曼]","[礼物]","[钟]","[话筒]","[蜡烛]","[蛋糕]"],
+    arr : ['1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','P','R','T','V','W','X','Y','Z'],
+}

BIN
service_exe/src/static/img/59.1cb4f69.gif


BIN
service_exe/src/static/img/loginBg.1847fc5.png


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/0.78e6e92dd6f80d447f44.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/0.78e6e92dd6f80d447f44.js.map


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/1.2850cac60cc7cb36bc98.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/1.2850cac60cc7cb36bc98.js.map


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/2.5988ffaaae4d45954528.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/2.5988ffaaae4d45954528.js.map


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/3.bb7138d6aee6b832f1d6.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/3.bb7138d6aee6b832f1d6.js.map


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/4.b2ac001ec334e8091243.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/4.b2ac001ec334e8091243.js.map


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/5.e4de278f29e86de1e53a.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/5.e4de278f29e86de1e53a.js.map


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/6.d9776ecdfcd686aeb8fc.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/6.d9776ecdfcd686aeb8fc.js.map


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/app.a9f51c630fb54c84585a.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/app.a9f51c630fb54c84585a.js.map


+ 2 - 0
service_exe/src/static/js/manifest.1375f5e568727c7312d8.js

@@ -0,0 +1,2 @@
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,a){for(var i,u,f,d=0,s=[];d<r.length;d++)u=r[d],t[u]&&s.push(t[u][0]),t[u]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(n&&n(r,c,a);s.length;)s.shift()();if(a)for(d=0;d<a.length;d++)f=o(o.s=a[d]);return f};var r={},t={9:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],a=document.createElement("script");a.type="text/javascript",a.charset="utf-8",a.async=!0,a.timeout=12e4,o.nc&&a.setAttribute("nonce",o.nc),a.src=o.p+"static/js/"+e+"."+{0:"78e6e92dd6f80d447f44",1:"2850cac60cc7cb36bc98",2:"5988ffaaae4d45954528",3:"bb7138d6aee6b832f1d6",4:"b2ac001ec334e8091243",5:"e4de278f29e86de1e53a",6:"d9776ecdfcd686aeb8fc"}[e]+".js";var i=setTimeout(u,12e4);function u(){a.onerror=a.onload=null,clearTimeout(i);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return a.onerror=a.onload=u,c.appendChild(a),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="./",o.oe=function(e){throw console.error(e),e}}([]);
+//# sourceMappingURL=manifest.1375f5e568727c7312d8.js.map

File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/manifest.1375f5e568727c7312d8.js.map


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/vendor.ed88eb57e8f88e68c79c.js


File diff suppressed because it is too large
+ 0 - 0
service_exe/src/static/js/vendor.ed88eb57e8f88e68c79c.js.map


BIN
service_exe/src/static/logo.gif


+ 253 - 0
service_exe/src/static/md5.js

@@ -0,0 +1,253 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the s you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+export default {
+  hex_md5(s) {
+    return this.binl2hex(this.core_md5(this.str2binl(s), s.length * chrsz));
+  },
+  b64_md5(s) {
+    return this.binl2b64(this.core_md5(this.str2binl(s), s.length * chrsz));
+  },
+  str_md5(s) {
+    return this.binl2str(this.core_md5(this.str2binl(s), s.length * chrsz));
+  },
+  hex_hmac_md5(key, data) {
+    return this.binl2hex(this.core_hmac_md5(key, data));
+  },
+  b64_hmac_md5(key, data) {
+    return this.binl2b64(this.core_hmac_md5(key, data));
+  },
+  str_hmac_md5(key, data) {
+    return this.binl2str(this.core_hmac_md5(key, data));
+  },
+
+  /*
+   * Perform a simple self-test to see if the VM is working
+   */
+  md5_vm_test() {
+    return this.hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+  },
+
+  /*
+   * Calculate the MD5 of an array of little-endian words, and a bit length
+   */
+  core_md5(x, len) {
+    /* append padding */
+    x[len >> 5] |= 0x80 << ((len) % 32);
+    x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+    var a = 1732584193;
+    var b = -271733879;
+    var c = -1732584194;
+    var d = 271733878;
+
+    for (var i = 0; i < x.length; i += 16) {
+      var olda = a;
+      var oldb = b;
+      var oldc = c;
+      var oldd = d;
+
+      a = this.md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
+      d = this.md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
+      c = this.md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
+      b = this.md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
+      a = this.md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
+      d = this.md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
+      c = this.md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
+      b = this.md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
+      a = this.md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
+      d = this.md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
+      c = this.md5_ff(c, d, a, b, x[i + 10], 17, -42063);
+      b = this.md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
+      a = this.md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
+      d = this.md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
+      c = this.md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
+      b = this.md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
+
+      a = this.md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
+      d = this.md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
+      c = this.md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
+      b = this.md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
+      a = this.md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
+      d = this.md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
+      c = this.md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
+      b = this.md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
+      a = this.md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
+      d = this.md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
+      c = this.md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
+      b = this.md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
+      a = this.md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
+      d = this.md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
+      c = this.md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
+      b = this.md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
+
+      a = this.md5_hh(a, b, c, d, x[i + 5], 4, -378558);
+      d = this.md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
+      c = this.md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
+      b = this.md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
+      a = this.md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
+      d = this.md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
+      c = this.md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
+      b = this.md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
+      a = this.md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
+      d = this.md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
+      c = this.md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
+      b = this.md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
+      a = this.md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
+      d = this.md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
+      c = this.md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
+      b = this.md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
+
+      a = this.md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
+      d = this.md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
+      c = this.md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
+      b = this.md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
+      a = this.md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
+      d = this.md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
+      c = this.md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
+      b = this.md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
+      a = this.md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
+      d = this.md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
+      c = this.md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
+      b = this.md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
+      a = this.md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
+      d = this.md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
+      c = this.md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
+      b = this.md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
+
+      a = this.safe_add(a, olda);
+      b = this.safe_add(b, oldb);
+      c = this.safe_add(c, oldc);
+      d = this.safe_add(d, oldd);
+    }
+    return Array(a, b, c, d);
+
+  },
+
+  /*
+   * These s implement the four basic operations the algorithm uses.
+   */
+  md5_cmn(q, a, b, x, s, t) {
+    return this.safe_add(this.bit_rol(this.safe_add(this.safe_add(a, q), this.safe_add(x, t)), s), b);
+  },
+  md5_ff(a, b, c, d, x, s, t) {
+    return this.md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+  },
+  md5_gg(a, b, c, d, x, s, t) {
+    return this.md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+  },
+  md5_hh(a, b, c, d, x, s, t) {
+    return this.md5_cmn(b ^ c ^ d, a, b, x, s, t);
+  },
+  md5_ii(a, b, c, d, x, s, t) {
+    return this.md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+  },
+
+  /*
+   * Calculate the HMAC-MD5, of a key and some data
+   */
+  core_hmac_md5(key, data) {
+    var bkey = this.str2binl(key);
+    if (bkey.length > 16) bkey = this.core_md5(bkey, key.length * chrsz);
+
+    var ipad = Array(16),
+      opad = Array(16);
+    for (var i = 0; i < 16; i++) {
+      ipad[i] = bkey[i] ^ 0x36363636;
+      opad[i] = bkey[i] ^ 0x5C5C5C5C;
+    }
+
+    var hash = this.core_md5(ipad.concat(this.str2binl(data)), 512 + data.length * chrsz);
+    return this.core_md5(opad.concat(hash), 512 + 128);
+  },
+
+  /*
+   * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+   * to work around bugs in some JS interpreters.
+   */
+  safe_add(x, y) {
+    var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+    var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+    return (msw << 16) | (lsw & 0xFFFF);
+  },
+
+  /*
+   * Bitwise rotate a 32-bit number to the left.
+   */
+  bit_rol(num, cnt) {
+    return (num << cnt) | (num >>> (32 - cnt));
+  },
+
+  /*
+   * Convert a string to an array of little-endian words
+   * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+   */
+  str2binl(str) {
+    var bin = Array();
+    var mask = (1 << chrsz) - 1;
+    for (var i = 0; i < str.length * chrsz; i += chrsz)
+      bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (i % 32);
+    return bin;
+  },
+
+  /*
+   * Convert an array of little-endian words to a string
+   */
+  binl2str(bin) {
+    var str = "";
+    var mask = (1 << chrsz) - 1;
+    for (var i = 0; i < bin.length * 32; i += chrsz)
+      str += String.fromCharCode((bin[i >> 5] >>> (i % 32)) & mask);
+    return str;
+  },
+
+  /*
+   * Convert an array of little-endian words to a hex string.
+   */
+  binl2hex(binarray) {
+    var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+    var str = "";
+    for (var i = 0; i < binarray.length * 4; i++) {
+      str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) +
+        hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF);
+    }
+    return str;
+  },
+
+  /*
+   * Convert an array of little-endian words to a base-64 string
+   */
+  binl2b64(binarray) {
+    var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    var str = "";
+    for (var i = 0; i < binarray.length * 4; i += 3) {
+      var triplet = (((binarray[i >> 2] >> 8 * (i % 4)) & 0xFF) << 16) |
+        (((binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 0xFF) << 8) |
+        ((binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4)) & 0xFF);
+      for (var j = 0; j < 4; j++) {
+        if (i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+        else str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
+      }
+    }
+    return str;
+  }
+
+}

+ 41 - 0
service_exe/src/static/paste.js

@@ -0,0 +1,41 @@
+// (function(){
+    var imgReader = function( item ){
+      var blob = item.getAsFile(),
+        reader = new FileReader();
+      // 读取文件后将其显示在网页中
+      reader.onload = function( e ){
+        var img = new Image();
+   
+        img.src = e.target.result;
+        document.body.appendChild( img );
+      };
+      // 读取文件
+      reader.readAsDataURL( blob );
+    };
+    document.getElementById( 'input' ).addEventListener( 'paste', function( e ){
+       // 添加到事件对象中的访问系统剪贴板的接口
+      var clipboardData = e.clipboardData,
+        i = 0,
+        items, item, types;
+   
+      if( clipboardData ){
+        items = clipboardData.items;
+        if( !items ){
+          return;
+        }
+        item = items[0];
+        // 保存在剪贴板中的数据类型
+        types = clipboardData.types || [];
+        for( ; i < types.length; i++ ){
+          if( types[i] === 'Files' ){
+            item = items[i];
+            break;
+          }
+        }
+        // 判断是否为图片数据
+        if( item && item.kind === 'file' && item.type.match(/^image\//i) ){
+          imgReader( item );
+        }
+      }
+    });
+//   })(); 

+ 486 - 0
service_exe/src/static/publicMethods.js

@@ -0,0 +1,486 @@
+import frceArr from './frce';
+
+export default {
+	//获取图片
+	imgPreview(file, callback) {
+		let self = this;
+		let name = file.name.split('.')[0]
+		//判断支不支持FileReader
+		if (!file || !window.FileReader) return;
+		if (/^image/.test(file.type)) {
+			//创建一个reader
+			let reader = new FileReader();
+			//将图片转成base64格式
+			reader.readAsDataURL(file);
+			//读取成功后的回调
+			reader.onloadend = function () {
+				let result = this.result;
+				let img = new Image();
+				let formData = new FormData();
+				img.src = result;
+				img.onload = function () {
+					let data = self.compress(img);
+					let blob = self.dataURItoBlob(data);
+					formData.append("file", blob, name + '.jpeg');
+					//图片预览,配置文件,formData数据;
+					callback && callback(data, formData);
+				};
+			};
+		}
+	},
+	// 压缩图片
+	compress(img) {
+		let canvas = document.createElement("canvas");
+		let ctx = canvas.getContext("2d");
+		// let initSize = img.src.length;
+		let width = img.width;
+		let height = img.height;
+		canvas.width = width;
+		canvas.height = height;
+		// 铺底色
+		ctx.fillStyle = "#fff";
+		ctx.fillRect(0, 0, canvas.width, canvas.height);
+		ctx.drawImage(img, 0, 0, width, height);
+
+		//进行压缩
+		let ndata = canvas.toDataURL("image/jpeg", 0.4);
+		// console.log("*******压缩后的图片大小*******");
+		// console.log(ndata)
+		return ndata;
+	},
+
+	// base64转成bolb对象
+	dataURItoBlob(base64Data) {
+		var byteString;
+		if (base64Data.split(",")[0].indexOf("base64") >= 0)
+			byteString = atob(base64Data.split(",")[1]);
+		else byteString = unescape(base64Data.split(",")[1]);
+		var mimeString = base64Data
+			.split(",")[0]
+			.split(":")[1]
+			.split(";")[0];
+		var ia = new Uint8Array(byteString.length);
+		for (var i = 0; i < byteString.length; i++) {
+			ia[i] = byteString.charCodeAt(i);
+		}
+		return new Blob([ia], {type: mimeString});
+	},
+
+
+	//
+	setApiToken(name, controller, time, modules) {
+		let str = name + 'customer-service' + controller + time + modules
+		return str.toLocaleLowerCase()
+	},
+
+	/**
+	 * 时间戳转日期自定义时间格式
+	 * timeStamp:时间戳
+	 * custom:转换日期时定义年月日用是什么符号隔开
+	 * isDtae:0=月份、1=日期、3=时间
+	 */
+	customFormatDateTime(timeStamp, custom, isDtae) {
+		var date = new Date();
+		date.setTime(timeStamp * 1000);
+		var y = date.getFullYear();
+		var m = date.getMonth() + 1;
+		m = m < 10 ? ('0' + m) : m;
+		var d = date.getDate();
+		d = d < 10 ? ('0' + d) : d;
+		var h = date.getHours();
+		h = h < 10 ? ('0' + h) : h;
+		var minute = date.getMinutes();
+		var second = date.getSeconds();
+		minute = minute < 10 ? ('0' + minute) : minute;
+		second = second < 10 ? ('0' + second) : second;
+		if (isDtae == 0) {
+			return y + custom + m //+'student';
+		} else if (isDtae == 1) {
+			return y + custom + m + custom + d;
+		} else if (isDtae == 3) {
+			return h + ':' + minute //+ ':' + second;
+		} else {
+			return y + '-' + m + '-' + d + ' ' + h + ':' + minute //+ ':' + second;
+		}
+	},
+
+	/*****************提示关键字及记录次数******************/
+	/**
+	 *
+	 * @param {*} data
+	 * @param {*} sensitive
+	 * @param {*}
+	 */
+	shieldingKeyword(data, sensitive) {
+		//将敏感词组用|转换字符串
+		let snstive = sensitive.join('|');
+		let num = 0, text = '';
+		//匹配出会话中的敏感词
+		data.replace(eval('/' + snstive + '/g'), (res) => {
+			text += ',' + res;
+			num++;
+		})
+		return {
+			text,
+			num
+		}
+	},
+
+	/*****************用户屏蔽关键字******************/
+	/**
+	 *
+	 * @param {*} data
+	 * @param {*} sensitive
+	 * @param {*}
+	 */
+	userShieldingKeyword(data, sensitive) {
+		//将敏感词组用|转换字符串
+		let snstive = sensitive.join('|');
+		let num = 0, text = '';
+		//匹配出会话中的敏感词
+		return data.replace(eval('/' + snstive + '/g'), (res) => {
+			var str = '';
+			for (var i = 0; i < res.length; i++) {
+				str += '*';
+			}
+			return str;
+		})
+	},
+
+
+	/******************访客接入*********************/
+	/**
+	 *
+	 * @param {object} redata  接收消息源
+	 * @param {Array} offlineList  访客离线列表
+	 * @param {Array} sessionList  访客会话列表
+	 * @param {int} sessionType 选择列表状态默认未1(1是会话中,2是离线)
+	 * @param {int} dataIndex  定位当前会话,默认是0
+	 * @param {Array} dataList 当前会话信息列表
+	 * @param {string} user_name 当前会话访客名
+	 * @param {function} callback   访客匹配离线列表处理后链接回调方法
+	 * @param {function} callback1   访客正常链接回调方法
+	 */
+	visitorsConnect([redata, offlineList, sessionList, sessionType, dataIndex, dataList, user_name], callback, callback1) {
+		// console.log('将会话工单写入访客信息',redata);
+		// console.log('访客信息评价',evaluate);
+		if (redata.evaluate_id > 0) {
+			redata.user_info.isEva = 10;
+		}
+		//将会话工单写入访客信息
+		redata.user_info.conversationId = redata.conversationId;
+		//默认离线列表没有访客信息
+		let isTrue = true;
+		let name = '';
+		let sessionInfo = '';
+
+		//匹配是否是离线用户上线
+		if (offlineList.length > 0) {
+			for (let i = 0; i < offlineList.length; i++) {
+				//匹配离线列表是否有这个用户
+				if (offlineList[i].id == redata.user_info.id) {
+					//查询离线列表是否有此用户会话工单未结束
+					if (offlineList[i].conversationId == redata.conversationId) {
+						// console.log(sessionType,offlineList);
+						//工单号未结束的数据获取历史聊天消息和对象名字
+						if (sessionType == 2 && i == dataIndex) {//客服选中离线重新链接访客
+							dataList = [];
+							dataList = offlineList[i].data;
+							name = offlineList[i].nick_name ? offlineList[i].nick_name : offlineList[i].name;
+							sessionType = 1;
+							dataIndex = sessionList.length == 0 ? 0 : sessionList.length - 1;
+						} else if (sessionType == 2 && i < dataIndex) {//客服选中离线列表重新链接访客后面的访客
+							if (i > 0) {
+								dataList = offlineList[i].data;
+								name = offlineList[i].nick_name ? offlineList[i].nick_name : offlineList[i].name;
+							}
+						} else {
+							name = redata.user_info.nick_name ? redata.user_info.nick_name : redata.user_info.name;
+						}
+						//将掉线前聊天消息写入到用户对象里面
+						redata.user_info.data = offlineList[i].data;
+					} else {
+						//工单号已结束数据处理
+						if (dataIndex == 0 && sessionList.length == 0) {
+							name = redata.user_info.nick_name ? redata.user_info.nick_name : redata.user_info.name;
+							dataList = [];
+						}
+						redata.user_info.data = [];
+					}
+					//获取离线列表数据
+					sessionInfo = offlineList[i]
+					//将离线状态用户删除
+					offlineList.splice(i, 1);
+
+					isTrue = false;
+					//回调
+					callback && callback(offlineList);
+					break;
+				}
+			}
+		}
+
+		//新访客链接
+		if (isTrue) {
+			if (sessionList.length == 0) {
+				//判断是否选离线用户列表
+				if (offlineList.length > 0 && sessionType == 2) {
+					//不做处理
+
+				} else {
+					dataIndex = 0;
+					sessionType = 1;
+					// console.log(redata.user_info.nick_name,redata.user_info.name);
+					name = redata.user_info.nick_name ? redata.user_info.nick_name : redata.user_info.name;
+					dataList = [];
+				}
+			} else {
+				for (let i = 0; i < sessionList.length; i++) {
+					//匹配离线列表是否有这个用户
+					if (sessionList[i].id == redata.user_info.id) {
+						sessionList.splice(i, 1);
+						break;
+					}
+				}
+
+				//判断接入用户是否有昵称展示
+				redata.user_info.name = redata.user_info.nick_name ? redata.user_info.nick_name : redata.user_info.name;
+			}
+			//历史会话消息
+			if (redata.history.length > 0) {
+				let chatData = [];
+				redata.history.forEach(e => {
+					let content = JSON.parse(e.content);
+					let obj = {
+						text: this.turnFace(content.text, frceArr.frce),
+						img: content.img,
+						type: false,
+					};
+					if (e.from_id.startsWith("KF")) {
+						//this.turnFace(redata.content.text,frceArr.frce);
+						chatData.push({
+							type: 'service',
+							content: obj,
+							time: this.customFormatDateTime(e.time_line, '', 3)
+						})
+					} else {
+						chatData.push({type: 'user', content: obj, time: this.customFormatDateTime(e.time_line, '', 3)})
+					}
+				})
+				redata.user_info.data = chatData;
+				dataList = chatData;
+			} else {
+				redata.user_info.data = [];
+			}
+		} else {
+			redata.user_info.data = sessionInfo.data
+		}
+		// console.log(name);
+		//回调
+		callback1 && callback1(redata, sessionList, offlineList, sessionType, dataIndex, dataList, name);
+	},
+
+	/*****************用户会话离线及相关数据*********************/
+	/**
+	 * @param {object} redata  接收消息源
+	 * @param {Array} sessionList  访客会话列表
+	 * @param {Array} offlineList  访客离线列表
+	 * @param {int} sessionType 选择列表状态默认未1(1是会话中,2是离线)
+	 * @param {int} dataIndex  定位当前会话,默认是0
+	 * @param {string} user_name 当前会话访客名
+	 * @param {Array} dataList 当前会话信息列表
+	 * @param {*} callback  回调函数
+	 */
+	userOffline([redata, sessionList, offlineList, sessionType, dataIndex, user_name, dataList], callback) {
+		let userInfo = [];
+		for (let i = 0; i < sessionList.length; i++) {
+			//匹配会话中离线用户
+			if (sessionList[i].id == redata.id) {
+				//把数据添加到离线列表
+				offlineList.push(sessionList[i]);
+				//用户选中状态会话中处理
+				if (sessionType == 1) {
+					//判断会话中列表长度
+					if (sessionList.length > 1) {
+						//判断是否离线用户是当前选中状态
+						if (dataIndex == i) {
+							dataIndex = 0;
+							user_name = sessionList[0].name;
+							dataList = sessionList[0].data;
+							userInfo = sessionList;
+						}
+						//删除会话列表离线用户
+						sessionList.splice(i, 1);
+					} else {
+						sessionType = 2;
+						dataIndex = 0;
+						user_name = offlineList[0].name;
+						dataList = offlineList[0].data;
+						userInfo = offlineList;
+						sessionList.splice(i, 1);
+					}
+				}
+				callback && callback(sessionList, offlineList, sessionType, dataIndex, user_name, dataList, userInfo);
+				break;
+			}
+		}
+	},
+
+	/**************删除会话中离线用户及相关数据**************/
+	/**
+	 * @param {object} redata  接收消息源
+	 * @param {Array} sessionList  访客会话列表
+	 * @param {Array} offlineList  访客离线列表
+	 * @param {int} sessionType 选择列表状态默认未1(1是会话中,2是离线)
+	 * @param {int} dataIndex  定位当前会话,默认是0
+	 * @param {string} user_name 当前会话访客名
+	 * @param {Array} dataList 当前会话信息列表
+	 * @param {*} callback  回调函数
+	 */
+
+	sessionEnd([redata, sessionList, offlineList, sessionType, dataIndex, user_name, dataList], callback) {
+		let isTrue = true;
+		let userInfo = [];
+		// console.log('哈哈',sessionList);
+		//会话中列表匹配
+		if (sessionList.length > 0) {
+			for (let i = 0; i < sessionList.length; i++) {
+				//检测会话列表中是否有结束的会话对象
+				if (sessionList[i].id == redata.id) {
+					//删除会话列表中结束的会话对象用户信息
+					sessionList.splice(i, 1);
+					// this.$store.dispatch("SET_SESSION",sessionList);
+					if (sessionType == 1) {
+						if (sessionList.length > 1) {
+							//处理会话显现状态
+							if (dataIndex == i) {
+								user_name = sessionList[0].name;
+								dataList = sessionList[0].data;
+								userInfo = sessionList;
+							}
+						} else {
+							if (offlineList.length > 0) {
+								sessionType = 2;
+								dataIndex = 0;
+								userInfo = offlineList;
+							} else {
+								user_name = '';
+								dataList = [];
+								userInfo = '';
+							}
+						}
+					}
+					isTrue = false;
+					break;
+				}
+			}
+		}
+		//离线列表查询
+		if (isTrue) {
+			for (let i = 0; i < offlineList.length; i++) {
+				//判断离线列表是否结束会话
+				if (offlineList[i].id == redata.id) {
+					//删除离线列表中结束会话的用户信息
+					offlineList.splice(i, 1);
+					// this.$store.dispatch("SET_OFFLINE",offlineList);
+					if (sessionType == 2) {
+						if (dataIndex == i) {
+							if (offlineList.length > 1) {
+								if (sessionList.length > 0) {
+									dataList = sessionList[0].data;
+									user_name = sessionList[0].name;
+									userInfo = sessionList;
+								} else {
+									dataList = offlineList[0].data;
+									user_name = offlineList[0].name;
+									userInfo = offlineList;
+								}
+							} else {
+								if (sessionList.length > 0) {
+									dataList = sessionList[0].data;
+									user_name = sessionList[0].name;
+									userInfo = sessionList;
+								} else {
+									dataList = [];
+									user_name = '';
+									userInfo = '';
+								}
+							}
+						}
+					}
+					break;
+				}
+			}
+		}
+		console.log('测试掉线', sessionList);
+		//回调
+		callback && callback(sessionList, offlineList, sessionType, dataIndex, user_name, dataList, userInfo);
+
+	},
+
+
+	/*****************接收用户会话消息***************/
+	/**
+	 *
+	 * @param {*} redata 数据源
+	 * @param {*} sessionList 会话列表
+	 * @param {*} frce 表情数据源
+	 * @param {*} callback  回调
+	 */
+	receivesMessage(redata, sessionList, frce, callback) {
+		let dataIndex = 0;
+		if(sessionList.length<1){
+			return -2001;
+		}
+		//匹配是那个用户回的消息
+		for (let i = 0; i < sessionList.length; i++) {
+			if (sessionList[i].id == redata.id) {
+				dataIndex = i;
+				break;
+			}
+		}
+
+
+		//获取当前回复消息对象
+		let chatList = sessionList[dataIndex]
+
+		redata.type = 'user';
+		redata.content = JSON.parse(redata.content);
+		//这个地方转
+		redata.content.text = this.turnFace(redata.content.text, frce);
+		//将消息添加对应的会话列表中
+		chatList.data.push(redata);
+		callback && callback(redata, chatList, dataIndex);
+	},
+
+	/******************文字信息转表情******************/
+	/**
+	 * @param {*} data
+	 * @param {*} frce
+	 */
+	turnFace(data, frce) {
+		let str = data.match(/\#\[.*?\]\//g);
+		let arr = Array.from(new Set(str));
+		arr.forEach(e => {
+			let imgsrc = '';
+			for (let i = 0; i < frce.length; i++) {
+				let expText = e.slice(1, e.length - 1);
+				if (expText == frce[i]) {
+					imgsrc = '<img class="hover" src="' + require(`@/assets/img/${i}.gif`) + '"/>'
+					break;
+				}
+			}
+			data = data.replace(new RegExp(`\\#\\[${e.substring(2, e.length - 2)}\\]\\/`, 'g'), imgsrc);
+		})
+		return data;
+	},
+
+	getQueryString(name) {
+		var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
+		var r = window.location.search.substr(1).match(reg);
+		if (r != null) {
+			return unescape(r[2]);
+		}
+		return null;
+	}
+}

Some files were not shown because too many files changed in this diff