user5 4 년 전
부모
커밋
d69628fdab

+ 12 - 0
pom.xml

@@ -1043,6 +1043,18 @@
             <artifactId>jsch</artifactId>
             <version>0.1.55</version>
         </dependency>
+
+        <!-- spring websocket-->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-websocket</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-messaging</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 42 - 0
src/main/java/com/jeeplus/common/websocket/config/WebSocketConfig.java

@@ -0,0 +1,42 @@
+package com.jeeplus.common.websocket.config;
+
+import com.jeeplus.common.websocket.service.onchat.LayIMSocketHandler;
+import com.jeeplus.common.websocket.service.onchat.LayIMSocketHandshakeInterceptor;
+import com.jeeplus.common.websocket.service.system.SystemInfoSocketHandler;
+import com.jeeplus.common.websocket.service.system.SystemInfoSocketHandshakeInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+
+@Configuration
+@EnableWebMvc
+@EnableWebSocket
+public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
+    @Override
+    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
+    	//注册layIM socket服务
+        registry.addHandler(layImSocketHandler(),"/layIMSocketServer").addInterceptors(new LayIMSocketHandshakeInterceptor());
+        registry.addHandler(layImSocketHandler(), "/sockjs/layIMSocketServer").addInterceptors(new LayIMSocketHandshakeInterceptor())
+                .withSockJS();
+        
+      //注册 系统通知socket服务
+        registry.addHandler(systemInfoSocketHandler(),"/systemInfoSocketServer").addInterceptors(new SystemInfoSocketHandshakeInterceptor());
+        registry.addHandler(systemInfoSocketHandler(), "/sockjs/systemInfoSocketServer").addInterceptors(new SystemInfoSocketHandshakeInterceptor())
+                .withSockJS();
+    }
+
+    @Bean
+    public WebSocketHandler layImSocketHandler(){
+        return new LayIMSocketHandler();
+    }
+
+    @Bean
+    public WebSocketHandler systemInfoSocketHandler(){
+        return new SystemInfoSocketHandler();
+    }
+}

+ 235 - 0
src/main/java/com/jeeplus/common/websocket/service/onchat/LayIMSocketHandler.java

@@ -0,0 +1,235 @@
+package com.jeeplus.common.websocket.service.onchat;
+
+import com.jeeplus.common.json.AjaxJson;
+import com.jeeplus.common.websocket.utils.Constants;
+import com.jeeplus.modules.iim.entity.ChatHistory;
+import com.jeeplus.modules.iim.entity.LayGroupUser;
+import com.jeeplus.modules.iim.service.ChatHistoryService;
+import com.jeeplus.modules.iim.service.LayGroupService;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.socket.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class LayIMSocketHandler implements WebSocketHandler {
+
+    private static final Logger logger;
+
+    private static final ArrayList<WebSocketSession> users;
+
+    static {
+        users = new ArrayList<>();
+        logger = LoggerFactory.getLogger(LayIMSocketHandler.class);
+    }
+    
+    public ArrayList<String> getOnlineLoginNames(){
+    	 ArrayList<String> onlineLoginNames = new ArrayList<String>();
+    	 for(WebSocketSession user : users){
+    		 String userName = (String) user.getAttributes().get(Constants.WEBSOCKET_LOGINNAME);
+			 if(userName!= null){
+				 User byLoginName = UserUtils.getByLoginName(userName);
+				 if (null != byLoginName)
+    			 	onlineLoginNames.add(byLoginName.getId());
+    		 }
+    	 }
+    	 return onlineLoginNames;
+         
+    }
+
+    @Autowired
+    private ChatHistoryService chatHistoryService;
+    @Autowired
+    private LayGroupService layGroupService;
+
+    //用户上线后触发
+    @Override
+    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
+        logger.debug("connect to the websocket success......");
+        users.add(session);
+        this.updateOnlineStatus();
+        String loginName = (String) session.getAttributes().get(Constants.WEBSOCKET_LOGINNAME);//获取刚上线用户的loginName
+		User user = UserUtils.getByLoginName(loginName);
+		if(loginName!= null){
+        	//读取离线信息
+			ChatHistory chat = new ChatHistory();
+			chat.setUserid2(user.getId());//发给刚上线的用户信息
+			chat.setStatus("0");
+			List<ChatHistory> list =chatHistoryService.findList(chat);
+			for(ChatHistory c : list){
+				
+				if("friend".equals(c.getType())){//如果是个人信息
+					String sender = c.getUserid1();
+					String msg = sender+ Constants._msg_+c.getUserid2()+ Constants._msg_+c.getMsg()+ Constants._msg_+ UserUtils.get(sender).getPhoto()+ Constants._msg_+c.getType()+ Constants._msg_+UserUtils.get(sender).getName()+ Constants._msg_+c.getCreateDate().getTime();
+					this.sendMessageToUser(loginName, msg);
+				}else{//如果是群组信息
+					String groupId = c.getUserid1().split(Constants._msg_)[0];//群组id
+					String sender=c.getUserid1().split(Constants._msg_)[1];//发送者loginName
+					String msg = groupId+ Constants._msg_+c.getUserid2()+ Constants._msg_+c.getMsg()+ Constants._msg_+ UserUtils.getByLoginName(sender).getPhoto()+ Constants._msg_+c.getType()+ Constants._msg_+UserUtils.get(sender).getName()+ Constants._msg_+c.getCreateDate().getTime();
+					this.sendMessageToUser(loginName, msg);
+				}
+				
+				c.setStatus("1");//标记为已读
+				chatHistoryService.save(c);
+			}
+        }
+    }
+
+    //接收js侧发送来的用户信息
+    @Override
+    public void handleMessage(WebSocketSession session, WebSocketMessage<?> socketMessage) throws Exception {
+
+    	String message = socketMessage.getPayload().toString();
+		if(null != message && message.contains(Constants._msg_)){//发送消息
+			String []arr = message.split(Constants._msg_);
+			String sender = arr[0];//信息发送者登录名(loginName)
+			String receiver = arr[1];//信息接收者,如果是私聊就是用户loginName,如果是群聊就是群组id
+			String msg = arr[2];
+			String avatar=arr[3];
+			String type=arr[4];
+			String senderName= arr[5];//发送者姓名(name)
+			String datatime = arr[6];
+			
+			
+			//保存聊天记录
+
+			
+			if("group".equals(type)){//如果是群聊
+				
+				List<LayGroupUser> layGroupUserlist = new ArrayList();
+				//群主
+				LayGroupUser owner = new LayGroupUser();
+				owner.setUser( layGroupService.get(receiver).getCreateBy());
+				layGroupUserlist.add(owner);
+				//群成员
+				List<LayGroupUser> zlist = layGroupService.getUsersByGroup(layGroupService.get(receiver));
+				layGroupUserlist.addAll(zlist);
+				
+				for(LayGroupUser lgUser:layGroupUserlist){
+
+					ChatHistory chat = new ChatHistory();
+					//群聊时信息先发送给群聊id(即receiver),在后台转发给所有非发送者(sender)的人的话,群聊id(即receiver)就变成发送者。
+					String groupId = receiver;
+					//保存聊天记录
+					chat.setUserid1(groupId+ Constants._msg_+sender);//群聊时保存群聊id和发送者id
+					chat.setUserid2(lgUser.getUser().getLoginName());//群中所有信息获得者人员
+					chat.setMsg(msg);
+					chat.setCreateDate(new Date());
+					chat.setType("group");  
+					message = groupId+ Constants._msg_+lgUser.getUser().getLoginName()+ Constants._msg_+msg+ Constants._msg_+avatar+ Constants._msg_+type+ Constants._msg_+senderName+ Constants._msg_+datatime;
+					if(sender.equals(lgUser.getUser().getLoginName())){//群消息不发给自己,但是存一条记录当做聊天记录查询
+							chat.setStatus("1");//发送成功,设置为已读
+					}else{
+						boolean isSuccess = this.sendMessageToUser(lgUser.getUser().getLoginName(), message);
+						if(isSuccess){
+							chat.setStatus("1");//发送成功,设置为已读
+						}else{
+							chat.setStatus("0");//用户不在线,设置为未读
+						}
+					}
+
+					chatHistoryService.save(chat);
+				}
+				
+			}else{//如果是私聊
+				ChatHistory chat = new ChatHistory();
+				chat.setUserid1(sender);
+				chat.setUserid2(receiver);
+				chat.setMsg(msg);
+				chat.setType("friend");
+				chat.setCreateDate(new Date());
+				boolean isSuccess = this.sendMessageToUser(receiver, message);
+				if(isSuccess){//如果信息发送成功
+					chat.setStatus("1");//设置为已读
+				}else{
+					this.sendMessageToUser(sender, receiver+"_sys_对方现在离线,他将在上线后收到你的消息!");//同时向本人发送对方不在线消息
+					chat.setStatus("0");//设置为未读
+				}
+				chatHistoryService.save(chat);
+			}
+			
+
+			
+		}
+	
+    }
+
+    @Override
+    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
+        if(session.isOpen()){
+            session.close();
+        }
+        logger.debug("websocket connection closed......");
+        users.remove(session);
+        this.updateOnlineStatus();
+	
+    }
+
+    @Override
+    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
+        logger.debug("websocket connection closed......");
+        users.remove(session);
+        this.updateOnlineStatus();
+    }
+
+    @Override
+    public boolean supportsPartialMessages() {
+        return false;
+    }
+
+    /**
+     * 给所有在线用户发送消息
+     *
+     * @param message
+     */
+    public void sendMessageToAllUsers( String message) {
+        for (WebSocketSession user : users) {
+            try {
+                if (user.isOpen()) {
+                    user.sendMessage(new TextMessage(message));
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 给某个用户发送消息
+     *
+     * @param loginName
+     * @param message
+     */
+    public boolean sendMessageToUser(String loginName, String message) {
+    	boolean result = false;
+        for (WebSocketSession user : users) {
+			User byLoginName = UserUtils.getByLoginName(user.getAttributes().get(Constants.WEBSOCKET_LOGINNAME).toString());
+            if(null != byLoginName){
+				if (byLoginName.getId().equals(loginName) || byLoginName.getLoginName().equals(loginName)) {//允许用户多个浏览器登录,每个浏览器页面都会收到用户信息
+					try {
+						if (user.isOpen()) {
+							user.sendMessage(new TextMessage(message));
+							result = true;
+						}
+					} catch (IOException e) {
+						e.printStackTrace();
+					}
+					//break;//注释掉此处意味着遍历该用户打开的所有页面并发送信息,否则只会向用户登录的第一个网页发送信息。
+				}
+			}
+        }
+        return result;
+    }
+    
+    public void updateOnlineStatus(){
+    	AjaxJson j = new AjaxJson();
+		j.put("data", this.getOnlineLoginNames());
+		this.sendMessageToAllUsers("_online_all_status_"+j.getJsonStr());//通知所有用户更新在线信息
+    }
+}

+ 37 - 0
src/main/java/com/jeeplus/common/websocket/service/onchat/LayIMSocketHandshakeInterceptor.java

@@ -0,0 +1,37 @@
+package com.jeeplus.common.websocket.service.onchat;
+
+import com.jeeplus.common.websocket.utils.Constants;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.http.server.ServletServerHttpRequest;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.server.HandshakeInterceptor;
+
+import javax.servlet.http.HttpSession;
+import java.util.Map;
+
+public class LayIMSocketHandshakeInterceptor implements HandshakeInterceptor {
+
+    private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);
+    @Override
+    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object
+                > attributes) throws Exception {
+        if (request instanceof ServletServerHttpRequest) {
+            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
+            HttpSession session = servletRequest.getServletRequest().getSession(false);
+            if (session != null) {
+                //使用loginName区分WebSocketHandler,以便定向发送消息
+                String loginName = UserUtils.getUser().getLoginName();//获取当前用户登录名
+                attributes.put(Constants.WEBSOCKET_LOGINNAME,loginName);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
+    }
+}

+ 113 - 0
src/main/java/com/jeeplus/common/websocket/service/system/SystemInfoSocketHandler.java

@@ -0,0 +1,113 @@
+package com.jeeplus.common.websocket.service.system;
+
+import com.jeeplus.common.websocket.utils.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.socket.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class SystemInfoSocketHandler implements WebSocketHandler {
+
+    private static final Logger logger;
+
+    private static final ArrayList<WebSocketSession> users;
+
+    static {
+        users = new ArrayList<>();
+        logger = LoggerFactory.getLogger(SystemInfoSocketHandler.class);
+    }
+    
+    public ArrayList<String> getOnlineLoginNames(){
+    	 ArrayList<String> onlineLoginNames = new ArrayList<String>();
+    	 for(WebSocketSession user : users){
+    		 String userName = (String) user.getAttributes().get(Constants.WEBSOCKET_LOGINNAME);
+    		 if(userName!= null){
+    			 onlineLoginNames.add(userName);
+    		 }
+    	 }
+    	 return onlineLoginNames;
+         
+    }
+
+
+    //建立websocket连接时触发
+    @Override
+    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
+        logger.debug("connect to the websocket success......");
+        users.add(session);
+    }
+
+    //接收js侧发送来的用户信息
+    @Override
+    public void handleMessage(WebSocketSession session, WebSocketMessage<?> socketMessage) throws Exception {
+
+    	String message = socketMessage.getPayload().toString();
+	
+    }
+
+    @Override
+    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
+        if(session.isOpen()){
+            session.close();
+        }
+        logger.debug("websocket connection closed......");
+        users.remove(session);
+	
+    }
+
+    @Override
+    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
+        logger.debug("websocket connection closed......");
+        users.remove(session);
+    }
+
+    @Override
+    public boolean supportsPartialMessages() {
+        return false;
+    }
+
+    /**
+     * 给所用户发送消息
+     *
+     * @param message
+     */
+    public void sendMessageToAllUsers( String message) {
+        for (WebSocketSession user : users) {
+            try {
+                if (user.isOpen()) {
+                    user.sendMessage(new TextMessage(message));
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 给某个用户发送消息
+     *
+     * @param loginName
+     * @param message
+     */
+    public boolean sendMessageToUser(String loginName, String message) {
+    	boolean result = false;
+        for (WebSocketSession user : users) {
+            if (user.getAttributes().get(Constants.WEBSOCKET_LOGINNAME).equals(loginName)) {//允许用户多个浏览器登录,每个浏览器页面都会收到用户信息
+                try {
+                    if (user.isOpen()) {
+                        user.sendMessage(new TextMessage(message));
+                        result = true;
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                
+                //break;//注释掉此处意味着遍历该用户打开的所有页面并发送信息,否则只会向用户登录的第一个网页发送信息。
+            }
+        }
+        return result;
+    }
+    
+}

+ 37 - 0
src/main/java/com/jeeplus/common/websocket/service/system/SystemInfoSocketHandshakeInterceptor.java

@@ -0,0 +1,37 @@
+package com.jeeplus.common.websocket.service.system;
+
+import com.jeeplus.common.websocket.utils.Constants;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.http.server.ServletServerHttpRequest;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.server.HandshakeInterceptor;
+
+import javax.servlet.http.HttpSession;
+import java.util.Map;
+
+public class SystemInfoSocketHandshakeInterceptor implements HandshakeInterceptor {
+
+    private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);
+    @Override
+    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object
+                > attributes) throws Exception {
+        if (request instanceof ServletServerHttpRequest) {
+            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
+            HttpSession session = servletRequest.getServletRequest().getSession(false);
+            if (session != null) {
+                //使用loginName区分WebSocketHandler,以便定向发送消息
+                String loginName = UserUtils.getUser().getLoginName();//获取当前用户登录名
+                attributes.put(Constants.WEBSOCKET_LOGINNAME,loginName);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
+    }
+}

+ 9 - 0
src/main/java/com/jeeplus/common/websocket/utils/Constants.java

@@ -0,0 +1,9 @@
+package com.jeeplus.common.websocket.utils;
+
+public class Constants {
+	
+	public static final String _online_user_  = "_online_user_";
+	public static final String _leave_user_  = "_leave_user_";
+	public static final String _msg_ = "_msg_";
+	public static final String WEBSOCKET_LOGINNAME = "websocket_loginname";
+}

+ 3 - 0
src/main/java/com/jeeplus/modules/iim/service/LayGroupService.java

@@ -260,4 +260,7 @@ public class LayGroupService extends CrudService<LayGroupDao, LayGroup> {
 		return count;
 	}
 
+	public List<LayGroupUser> getUsersByGroup (LayGroup layGroup){
+		return  layGroupUserDao.findList(new LayGroupUser(layGroup));
+	}
 }

+ 10 - 11
src/main/webapp/static/layer-v2.3/layim/layui/lay/pc/modules/layim.js

@@ -15,7 +15,7 @@ layui.define(['jquery', 'layer', 'laytpl', 'upload'], function(exports){
   var laytpl = layui.laytpl;
   
   var SHOW = 'layim-show', THIS = 'layim-this';
-  
+
   //回调
   var call = {};
   
@@ -128,7 +128,6 @@ layui.define(['jquery', 'layer', 'laytpl', 'upload'], function(exports){
           ,'<li {{d.mine.status === "hide" ? "class=layim-this" : ""}} layim-event="status" lay-type="hide"><i class="layui-icon">&#xe618;</i><cite class="layui-icon layim-status-hide">&#xe60f;</cite>隐身</li>'
         ,'</ul>'
       ,'</div>'
-      ,'<p class="layui-layim-remark" title="{{# if(d.mine.sign){ }}{{d.mine.sign}}{{# } }}"><input id="layim_user_sign_box" type="text" value="{{ d.mine.remark||d.mine.sign||"你没有写签名" }}" class="layim-sign-box layim-sign-hide"></p>'
     ,'</div>'
     ,'<ul class="layui-layim-tab{{# if(!d.base.isfriend || !d.base.isgroup){ }}'
       ,' layim-tab-two'
@@ -194,7 +193,7 @@ layui.define(['jquery', 'layer', 'laytpl', 'upload'], function(exports){
       ,'<li class="layui-icon layim-tool-search" layim-event="search" title="搜索">&#xe615;</li>'
       ,'<li class="layui-icon layim-tool-skin" layim-event="skin" title="换肤">&#xe61b;</li>'
       ,'{{# if(d.base.find){ }}'
-      ,'<li class="layui-icon layim-tool-find" layim-event="find" title="查找">&#xe61f;</li>'
+
       ,'{{# } }}'
       ,'{{# if(!d.base.copyright){ }}'
       ,'<li class="layui-icon layim-tool-about" layim-event="about" title="关于">&#xe60b;</li>'
@@ -766,22 +765,22 @@ layui.define(['jquery', 'layer', 'laytpl', 'upload'], function(exports){
     chatListMore();
     thatChat.textarea.val('').focus();
   };
-  
+
   //接受消息
   var getMessage = function(data){
     data = data || {};
     var elem = $('.layim-chatlist-'+ data.type + data.id);
     var group = {}, index = elem.index();
-    
+
     data.timestamp = data.timestamp || new Date().getTime();
     pushChatlog(data);
-    
+
     if((!layimChat && data.content) || index === -1){
       if(cache.message[data.type + data.id]){
         cache.message[data.type + data.id].push(data)
       } else {
         cache.message[data.type + data.id] = [data];
-        
+
         //记录聊天面板队列
         if(data.type === 'friend'){
           var friend;
@@ -833,7 +832,7 @@ layui.define(['jquery', 'layer', 'laytpl', 'upload'], function(exports){
         ,shift: 6
       });
     }
-    
+
     //接受到的消息不在当前Tab
     var thatChat = thisChat();
     if(thatChat.data.type + thatChat.data.id !== data.type + data.id){
@@ -842,15 +841,15 @@ layui.define(['jquery', 'layer', 'laytpl', 'upload'], function(exports){
         elem.removeClass('layui-anim layer-anim-06')
       }, 300);
     }
-    
+
     var cont = layimChat.find('.layim-chat').eq(index);
-    var ul = cont.find('.layim-chat-main ul'); 
+    var ul = cont.find('.layim-chat-main ul');
     if(data.content.replace(/\s/g, '') !== ''){
       ul.append(laytpl(elemChatMain).render(data));
     }
     chatListMore();
   };
-  
+
   //存储最近50条聊天记录到本地
   var pushChatlog = function(message){
     var local = layui.data('layim')[cache.mine.id] || {};

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 5725 - 0
src/main/webapp/static/layer-v2.3/layui/sock.js


+ 249 - 0
src/main/webapp/webpage/include/layIMInit.jsp

@@ -0,0 +1,249 @@
+<!-- 本页面是layIM聊天插件 
+          使用方法 :在需要支持聊天的页面直接引入该页面,<-%@include file=".../common/layIM-init.jsp->
+-->
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<meta name="decorator" content="ani"/>
+<link href="${ctxStatic}/layer-v2.3/layim/layui/css/layui.css" type="text/css" rel="stylesheet"/>
+<script src="${ctxStatic}/layer-v2.3/layim/layui/layui.js"></script>
+<script src="${ctxStatic}/layer-v2.3/layui/sock.js"></script><!-- 如果浏览器不支持socktjs,添加支持 -->
+<script type="text/javascript">
+(function() {
+	//初始化
+	layui.use('layim', function(layim){
+		//---即使聊天服务端地址配置,端口和web服务器端口一样,80可以省略
+        var host = window.document.location.host;
+        var pathName = window.document.location.pathname;
+        var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
+        var wsServer = "ws://" + host + projectName;
+		var currentLoginName = '${fns:getUser().loginName}';
+		var currentId = '${fns:getUser().id}';
+		var currentName = '${fns:getUser().name}';
+		var currentFace ='${fns:getUser().photo}';
+	    var webSocket = null;
+        if ('WebSocket' in window || 'MozWebSocket' in window) {
+            webSocket = new WebSocket(wsServer+"/layIMSocketServer");
+        } else {
+            webSocket = new SockJS( wsServer+"/sockjs/layIMSocketServer");
+        }
+
+	  webSocket.onerror = function(event) {
+	    jp.alert("websockt连接发生错误,请刷新页面重试!")
+	  };
+			
+		// 连接成功建立的回调方法
+		  webSocket.onopen = function(event) {
+		  //  webSocket.send("_online_user_"+currentLoginName);
+		  };
+		// 接收到消息的回调方法
+		  webSocket.onmessage = function(event) {
+		    var res=event.data;
+			if(res.indexOf("_online_all_status_")>=0){
+				var dd = res.substring("_online_all_status_".length);
+				setTimeout(function(){updateOnlineStatus(eval('('+dd+')').body.data);},500);
+				
+			}
+			
+			if(res.indexOf('_sys_')>=0){//系统通知
+				var arra = res.split("_sys_");
+		    	var sender=arra[0];
+		    	var contents=arra[1];
+	            var obj = {
+	                username: "系统通知"
+	                ,avatar: layui.cache.dir+'images/face/notify.png'
+	                ,id:sender
+	                ,type: 'friend'
+	                ,content: contents
+	              }
+	            layim.getMessage(obj);
+	            return;
+				
+			}
+		    if(res.indexOf("_msg_")>=0){
+		    	var arra = res.split("_msg_");
+		    	var sender=arra[0];
+		    	var receiver=arra[1];//发送者登录名
+		    	var content=arra[2];
+		    	var avatar=arra[3];
+		    	var type=arra[4];
+		    	var senderName=arra[5];//发送者姓名
+		    	var sendtime = arra[6];
+		    	 if(sendtime != 'NAN'){//使用历史记录时间
+			        layim.getMessage({
+			            username: senderName
+			            ,avatar: avatar
+			            ,id: sender
+			            ,type: type
+			            ,content: content
+			            ,timestamp:parseFloat(sendtime)
+			          });
+		    	 }else{
+		    		 
+		    		 layim.getMessage({
+				            username: senderName
+				            ,avatar: avatar
+				            ,id: sender
+				            ,type: type
+				            ,content: content
+				          });
+		    	 }
+		    }
+		  };
+		  //发送消息的方法
+		  function send(mine,To) {
+			webSocket.send(currentId+"_msg_"+To.id+"_msg_"+mine.content+"_msg_"+mine.avatar+"_msg_"+To.type+"_msg_"+currentName+"_msg_NAN");
+		  };
+		//切换在线状态的方法
+		  function setonline() {
+			webSocket.send("_online_user_"+currentLoginName);
+		  };
+		//切换离线状态的方法
+		  function sethide() {
+			webSocket.send("_leave_user_"+currentLoginName);
+		  };
+		  
+		//更新在线用户信息
+		  function updateOnlineStatus(arra)//更新在线用户信息
+          {
+              $("div.layui-layim-main ul.layim-list-friend li ul.layui-layim-list li").each(function(){//状态还原
+                  if($(this).attr("id")){
+                      var span = $(this).find("span");
+                      var text=span.text();
+                      var name = $(this).attr("id").substring(12);
+                      if(text.indexOf("(")>=0){
+                          text = text.substring(0,text.indexOf("("));
+                      }
+                      if((','+arra+",").indexOf(','+name+',')>=0){
+
+                          span.html(text +"(<font color='green'>在线</font>)");
+                          var $one_li = $(this).parent().find("li:eq(0)");    //  获取<ul>节点中第一个<li>元素节点
+                          $(this).insertBefore($one_li);    //移动节点
+                      }else{
+
+                          span.html(text+"(<font color='color'>离线</font>)");
+                      }
+                  }
+              });
+          }
+		  
+	  //基础配置
+	  layim.config({
+
+	    //初始化接口
+	    init: {
+		  url: '${ctx}/iim/contact/friend'
+	      ,data: {}
+	    }
+
+	    //简约模式(不显示主面板)
+	    //,brief: true
+
+	    //查看群员接口
+	    ,members: {
+	       url: '${ctx}/iim/contact/getMembers'
+	      ,data: {}
+	    }
+	    
+	    ,uploadImage: {
+	       url: '${ctx}/iim/contact/uploadImage'//(返回的数据格式见下文)
+	      ,type: 'post' //默认post
+	    }
+
+	    ,uploadFile: {
+	       url: '${ctx}/iim/contact/uploadFile' //(返回的数据格式见下文)
+	      ,type: 'post' //默认post
+	    }
+	    
+	  //扩展工具栏,下文会做进一步介绍(如果无需扩展,剔除该项即可)
+	    ,tool: [{
+	       alias: 'code' //工具别名
+	      ,title: '代码' //工具名称
+	      ,icon: '&#xe64e;' //工具图标,参考图标文档
+	    }]
+	    
+	   // ,msgbox: layui.cache.dir + 'css/modules/layim/html/msgbox.html' //消息盒子页面地址,若不开启,剔除该项即可
+	    ,chatLog:'${ctx}/iim/chatHistory' //聊天记录地址
+	    ,find:'${ctx}/iim/contact/layimManager' //发现页面地址,若不开启,剔除该项即可
+	  });
+
+	//监听自定义工具栏点击,以添加代码为例
+	  layim.on('tool(code)', function(insert, send, obj){ //事件中的tool为固定字符,而code则为过滤器,对应的是工具别名(alias)
+	    layer.prompt({
+	      title: '插入代码'
+	      ,formType: 2
+	      ,shade: 0
+	    }, function(text, index){
+	      layer.close(index);
+	      insert('[pre class=layui-code]' + text + '[/pre]'); //将内容插入到编辑器,主要由insert完成
+	      //send(); //自动发送
+	    });
+	  });
+
+	  //监听发送消息
+	  layim.on('sendMessage', function(data){
+		  var mine = data.mine; //包含我发送的消息及我的信息
+		    var To = data.to; //对方的信息
+
+		    //发送消息到WebSocket服务
+		    send(mine,To);
+		    
+	  });
+
+	  //监听在线状态的切换事件
+	  layim.on('online', function(data){
+	    if(data=="online"){
+	    	setonline(); //用户上线
+	    }else{
+	    	sethide();//用户离线
+	    }
+	    
+	  });
+
+
+	  
+	  
+
+
+	  //layim建立就绪
+	  layim.on('ready', function(res){
+		  
+		  //更改签名
+	          var signObj = $('.layui-layim-remark');
+	          signObj.focus(function () {
+	              signObj.removeClass('layim-sign-hide');
+	              console.log('准备更改签名');
+	          });
+	          signObj.blur(function () {
+	              console.log('更改签名完毕');
+	              signObj.addClass('layim-sign-hide');
+	          });
+	          //enter提交
+	          signObj.keydown(function (event) {
+	              if (event.which == 13) {
+	                  console.log('按下了Enter提交签名');
+	                  signObj.addClass('layim-sign-hide');
+	                  signObj.blur();
+	                  var value= signObj.val();
+	                  $.post("${ctx}/sys/user/saveSign",{'sign':value},function(data){
+	                	  
+	                	  top.layer.alert(data.msg, {icon: 1});
+	                  })
+	                  
+	              }
+	          });
+	  
+
+	  });
+
+	  //监听查看群员
+	  layim.on('members', function(data){
+	    console.log(data);
+	  });
+	  
+	  //监听聊天窗口的切换
+	  layim.on('chatChange', function(data){
+	    console.log(data);
+	  });
+	});
+})(jQuery);  		 
+	</script>

+ 32 - 0
src/main/webapp/webpage/include/systemInfoSocketInit.jsp

@@ -0,0 +1,32 @@
+<!-- 本页面是系统socket页面
+          使用方法 :在需要支持websocket消息推送的页面直接引入该页面,<-%@include file=".../common/systemInfoSocket-init.jsp->
+              :在本页面需要配置wsServer.
+-->
+<%@ page contentType="text/html;charset=UTF-8" %>
+<script src="${ctxStatic}/layer-v2.3/layui/sock.js"></script><!-- 如果浏览器不支持socktjs,添加支持 -->
+<script type="text/javascript">
+(function() {
+        var host = window.document.location.host;
+        var pathName = window.document.location.pathname;
+        var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
+        var wsServer = "ws://" + host + projectName;
+		  
+		var webSocket = null;
+		if ('WebSocket' in window || 'MozWebSocket' in window) {
+			  webSocket = new WebSocket(wsServer+"/systemInfoSocketServer");
+		  } else {
+			  webSocket = new SockJS( wsServer+"/sockjs/systemInfoSocketServer");
+		  }
+		
+		  webSocket.onerror = function(event) {
+		    jp.alert("websockt连接发生错误,请刷新页面重试!")
+		  };
+				
+		// 接收到消息的回调方法
+		  webSocket.onmessage = function(event) {
+		    var res=event.data;
+		    jp.toastr.info(res,"系统通知")
+		    jp.voice();
+		  };
+})(jQuery);  
+</script>

+ 4 - 2
src/main/webapp/webpage/modules/sys/sysIndex.jsp

@@ -12,6 +12,8 @@
     <title>首页列表</title>
 
     <%@ include file="/webpage/include/head.jsp"%>
+    <%@ include file="/webpage/include/systemInfoSocketInit.jsp"%>
+    <%@ include file="/webpage/include/layIMInit.jsp"%>
     <script src="${ctxStatic}/common/inspinia.js?v=3.2.0"></script>
     <script src="${ctxStatic}/common/contabs.js"></script>
     <meta name="keywords" content="JeePlus快速开发平台">
@@ -510,7 +512,7 @@
 
 
 <!-- 即时聊天插件  开始-->
-<link href="${ctxStatic}/layer-v2.3/layim/layui/css/layui.css" type="text/css" rel="stylesheet"/>
+<%--<link href="${ctxStatic}/layer-v2.3/layim/layui/css/layui.css" type="text/css" rel="stylesheet"/>
 <script type="text/javascript">
     var currentId = '${fns:getUser().id}';
     var currentName = '${fns:getUser().name}';
@@ -716,6 +718,6 @@
 
 
 
-</script>
+</script>--%>
 
 </html>