socket 内聊工具另一个版本

1. 后台结构:







2.需求的jar 包





3. WSConfig.java


/**
 * 
 */
package com.ws.config;

import java.util.Set;

import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;

/**
 * @author zhong
 *
 */
public class WSConfig implements ServerApplicationConfig {


	/**
	 * 用注解的方式实现
	 */
	@Override
	public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scand) {
		System.out.println("=======> WSConfig:"+scand.size());
		return scand;
	}

	
	/**
	 * 用接口的方式实现
	 */
	@Override
	public Set<ServerEndpointConfig> getEndpointConfigs(
			Set<Class<? extends Endpoint>> arg0) {
		return null;
	}

}




4.ChatSocket.java


/**
 * 
 */
package com.ws.socket;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import com.alibaba.fastjson.JSON;
import com.ws.bean.Content;
import com.ws.bean.Message;
import com.ws.bean.User;


/**
 * @author zhong
 *
 */
@ServerEndpoint(value="/echo")
public class ChatSocket {
	
	private static String user = null;
	private static List<Session> sessions = new ArrayList<Session>();
	private static List<Map<String,Object>> userList = new ArrayList<Map<String,Object>>();
	private static Map<String, Session> map = new HashMap<String, Session>();
	
	public ChatSocket(){
		
	}
	
	
	@OnOpen
	public void open(Session session){
		
		user = getSessionUser(session);
		
		Session ms = map.get(user);
		if(ms == null){
			map.put(user, session);
			sessions.add(session);
			
			User u = new User();
			u.setGroup("myfriend");
			u.setNickname(user);
			u.setSignature("我就是我,大名叫"+user+"的我~");

			userList.add(getUserMap(u));
		
			Message message = new Message();
			message.setType("online");
			message.setUsers(userList);
			message.setFrom(user);

			broadcast(sessions,JSON.toJSONString(message));

			System.out.println("===== 欢迎 "+user+" 进入IM, 当前共 "+userList.size() +" 人在线!");
		}
	}
	
	
	/**
	 * 消息广播
	 * @param sessions
	 * @param json
	 */
	private void broadcast(List<Session> sessions, String msg) {
		for(Iterator<Session> iterator = sessions.iterator(); iterator.hasNext();){
			Session session = (Session) iterator.next();
			try {
				if(session != null){
					session.getBasicRemote().sendText(msg);
				}else{
					System.out.println("======> broadcast session is NUll. by "+user);
				}
			} catch (IOException e) {
				System.out.println("=======> broadcast:"+user+" 已退出");
				e.printStackTrace();
			}
		}
	}


	@OnClose
	public void close(Session session){
		
		user = getSessionUser(session);
		sessions.remove(session);
		
		if(userList != null && userList.size() > 0){
			for (int i=0; i<userList.size(); i++) {
				Map<String, Object> map = userList.get(i);
				if(map.get(user) != null){
					userList.remove(map);
				}
				
			}
		}
		
		map.remove(user);
		Message message = new Message();
		message.setType("offline");
		message.setUsers(userList);
		System.out.println("======> "+user +" 已离线, 当前在线共 "+userList.size() +" 人!");
		

		broadcast(sessions,JSON.toJSONString(message));
	}
	
	
	/**
	 * 消息响应方法
	 * @param session
	 * @param json
	 */
	@OnMessage
	public void message(Session session,String json){
	
		String fromUser = getSessionUser(session);
		String toUser = null;
		
		Content content = (Content) JSON.parseArray(json, Content.class);
		if(content == null){
			return;
		}
		System.out.println("===== message:"+content.getMsg());
		
		//null 或 single
		if(content.getMode() == null){
			String to = content.getTo();
			if(to != null && to != ""){
				String toArr[] = to.split(","); 
				if(toArr == null || toArr.length == 0 ){
					return;
				}
				
				for(int i=0; i<toArr.length; i++){
					Session toSession = map.get(toArr[i]);
					
					if(toSession == null){
						continue;
					}
					
					toUser = getSessionUser(toSession);
					
					try {
						Message message = new Message();
						message.setType("message");
						message.setFrom(fromUser);
						message.setTo(toUser);
						message.setLayer(content.getLayer());
						message.setContent(content.getMsg());
						toSession.getBasicRemote().sendText(JSON.toJSONString(message));
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}else if(("model").equalsIgnoreCase(content.getMode())){
			Message message = new Message();
			message.setLayer(content.getLayer());
			message.setFrom(user);
			message.setType("message");
			message.setContent(content.getMsg());
			broadcast(sessions, JSON.toJSONString(message));
		}
		
	}
	
	
	
	/**
	 * 获取用户map
	 * @author zhong
	 * @param u
	 * @return
	 */
	public static Map<String, Object> getUserMap(User u){
		Map<String, Object> umap = null;
		if(u != null){
			umap = new HashMap<String, Object>();
			umap.put(user, JSON.toJSONString(u));
		}
		return umap;
	}
	
	
	/**
	 * 获取session用户
	 * @author zhong
	 * @param session
	 * @return
	 */
	public static String getSessionUser(Session session){
		String result = null;
		if(session != null){
			String parms = session.getQueryString();
			String[] parmArr = parms.split("=");
			if(parmArr != null && parmArr.length > 1){
				result = parmArr[1];
			}
		}
		return result;
		
	}
	
}





另外的消息类我就不贴代码了


6.前台核心代码:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
	pageContext.setAttribute("basePath", basePath);
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>PQ - 内聊版</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<%@ include file="include.jsp" %>
	<style type="text/css">
		form {
			margin:0 auto;
			margin-top:10%;
		}
	</style>
	
  </head>
  
  <body>

	<div class="content">

	</div>

	<script type="text/javascript">
		var ws = null;
		var userName = "${userName}"; //当前登录用户
		var host = "192.168.1.100:8080";
		var isOpen = false; //主窗口是否打开
		var sidx; //im主窗口index
		var slayero;
		var wsMsg;
		var wins = []; //存放当前打开的layer窗口
    	$(function(){
    		initWs();
    	});

    	function initWs(){
    		//页面打开后,连接socket
        	var target = "ws://"+host+"/pwtchat/echo?userName="+userName;

            if ('WebSocket' in window) {
                ws = new WebSocket(target);
                console.log("WebSocket 请求成功");
            } else if ('MozWebSocket' in window) {
                ws = new MozWebSocket(target);
                console.log("MozWebSocket 请求成功");
            } else {
                alert('WebSocket is not supported by this browser.');
                return;
            }
            
            
            //注册接收消息监听方法
            ws.onmessage = function(event){
            	console.log(event);
            	wsMsg = eval("("+event.data+")"); 
            	var type = wsMsg.type;
            	if(!isOpen){
                    //显示im主窗口
                    isOpen = true;
                  	showIm(wsMsg); 
            	}else{
            		//更新好友上线或下线
            		if("online" == type || "offline" == type){
            			var imWin = window[slayero.find('iframe')[0]['name']];
            			imWin.updateFirendGroup(wsMsg.users);
            		}
            	}
            	
            	
            	//好友消息接收
            	if(undefined != wsMsg.content && "message" == type){
             		console.log(wsMsg);
             		var from = wsMsg.from;
					var idx = getLayerIdx(from); 
            		var body = layer.getChildFrame('body', idx); 
            		if(undefined != body){
	            		var $show = body.find("#msg-show");
	            		if(undefined != $show && $show.length> 0){
	            			var msg = {
	            				nickname: from,
	            				msg: wsMsg.content,
	            				time: FY.getFormatLongDate(new Date())
	            			};
	            			
		            		$show.append(getMsgTemplate(msg));
		            		//滚动条保持底部
		            		$show.scrollTop( $show[0].scrollHeight );
	            		}
            		}
            	}

            };
            
            
            ws.onclose = function (event) {
            	console.log(event);
            }; 
            

    	};
    	
    	
    	//发送一条消息
    	function wsSend(msgs){
    		ws.send(JSON.stringify(msgs));
    	}
    	
    	/* 显示主窗口 */
	    function showIm(msg){
	     	return layer.open({
	    		  type: 2,
	    		  id: "im-main",
	    		  title: ['PQ - 内聊版', 'font-size:14px;'],
	    		  area: ['270px', '430px'],
	    		  fix: false, //不固定
	    		  maxmin: true,
	    		  shade :0.1,
	    		  content: "chat/chat-main-template.jsp",
		  		  success: function(layero, index){
		  			var win = {
		  				name: "im-main",
		  				idx: index
		  			};
		  			wins.push(win);
		  			slayero = layero;
		  			sidx = index;
			  	  },
	    		  end: function(){
	    			  window.location.href= "login.jsp";
	    		  }
	    	}); 
	    };
	    
	    
	    /* 显示聊天窗口 */
		function showMsgWindow(user){
	    	if(userName == user.nickname){
	    		FY.alert({
	    			type: "warning",msg : "跟自家自儿发消息就没意思了!"
	    		});
	    		return false;
	    	}
	    	
			var smidx = layer.open({
		  		  type: 2,
		  		  id: user.nickname,
		  		  title: ['PQ - 内聊版', 'font-size:14px;'],
		  		  area: ['450px', '370px'],
		  		  fix: false, //不固定
		  		  maxmin: false,
		  		  shade :0,
		  		  content: 'chat/chat-msg-template.jsp',
		  		  success: function(layero, index){
			  			var win = {
			  				name: "im-msg",
			  				idx: index,
			  				user: user.nickname == null ? "pwt_" : user.nickname
			  			};
			  			wins.push(win);	console.log(wins);			  
		  			  
		  		  	  	var body = layer.getChildFrame('body', index);
		  		  	  	
		  		  	  	//更新当前用户信息
		  		  	  	body.find("#nickname").text(user.nickname);
		  		  		body.find("#signature").text(user.signature);
		  		  		
		  		  		//动态绑定send事件
		  		  		body.find("#msg-send").bind("click",function(){
			  				var $inp = body.find("#msg-input"); 
			  				var msg = $inp.text();
			  				if(msg){
			  					var msgs = {
			  						layer: index,
			  						msg: msg,
			  						to: user.nickname
			  					};
			  					//提交给socket
			  					wsSend(msgs); 
			  					
			  					//显示在自己的界面上
			  					var msg = {
			  						nickname : userName,
			  						msg: msg,
			  						time: FY.getFormatLongDate(new Date())
			  					};
			  					
			  					
			  					var $show = body.find("#msg-show");
			  					$show.append(getMsgTemplate(msg));
			  					$show.scrollTop($show[0].scrollHeight );
			  					//清空输入框
			  					$inp.text("");
			  				}
		  		  	});
		  		  },
		  		  end: function(){
		  			removeLayerWin(smidx);
		  		  }
	  		}); 
		};
    
		
		
		
		function getMsgTemplate(msg){
			var html="";
			if(msg){
				html+="<div class='msg-item'>"+
					  "	<div class='msg-title'>"+
					  "		<img class='mt-face' alt='' src='${basePath}images/face.jpg'>"+
					  "		<div class='mt-name'>"+
					  "			<span class='nickname'>"+msg.nickname+"</span>"+
					  "			<span class='datetime'>"+msg.time+"</span>"+
					  "		</div>"+
					  " </div>"+
					  "	<div class='msg-content'>"+msg.msg+"</div>"+
					  "</div>";	
			}
			return html;
		}
		
		
		/* 根据用户信息获取layer的index  */
		function getLayerIdx(user){
			var idx = -1;
			if(FY.isEmpty(user)){
				return;
			}
			for(w in wins){
				if(wins[w].user == user){
					return wins[w].idx;
				}
			}
			return idx;
		}
		
		
		/* 关闭窗口时删除wins中的窗口信息 */
		function removeLayerWin(smidx){
			if(FY.isEmpty(smidx)){
				return;
			}
			for(w in wins){
				if(wins[w].idx == smidx){
					wins.splice(w,1);
				}
			}
		}
		
		
		
    </script>
  </body>
</html>




主页面代码:

chat/chat-main-template.jsp


<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
	pageContext.setAttribute("basePath", basePath);
%>
<link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/bootstrap.css">
<link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/bootstrap-theme.css">
<link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/fileinput.min.css">
<link rel="stylesheet" type="text/css" href="${basePath}js/layer.2.4/layui.css">


<script type="text/javascript" src='${basePath}js/jquery.min.js'></script>
<script type="text/javascript" src='${basePath}js/bootstrap/bootstrap.min.js'></script>
<script type="text/javascript" src='${basePath}js/layer.2.4/layer.js'></script>
<script type="text/javascript" src='${basePath}js/fy.utils.js'></script>
<style>
	body,html {
		padding: 0;
		margin: 0;
	}
	
	.im-header {
		width:100%;
		height: 75px;
		background: #F9f9f9;
		border-bottom:1px solid #eee;
	}
	
	.im-header .im-face-box,.im-info-box {
		float: left;
	}
	
	.im-header .im-face-box {
		width: 80px;
		height: 54px;
		border-radius: 54px;
		padding: 5px 5px 5px 20px;
	}
	
	.im-header .im-face-box>img {
		width: 54px;
		height: 54px;
		border-radius: 54px;
	}
	
	.im-header .im-info-box {
		width:165px;
		margin-left: 10px;
		overflow: hidden;
	}
	
	.im-header .im-info-box p {
		font-size: 12px;
		line-height: 20px;
		height: 20px;
		padding: 2px;
		margin: 2px;
	}
	
	/* 好友列表 */
	.im-friends {
		
	}
	
	.im-friends .friend-group {
		height:auto;
		margin:0 10px;
		line-height:30px;
		cursor: pointer;
	}
	
	.im-group-collapse {
		/* 分组折叠   */
	}
	
	.im-friends .friend-group .iconfont {
		padding-right:2px;
		font-size:10px;
	}	
	
	.im-friends .im-ul-box  {
		display:none;
	}	
	
	.im-friends .im-ul-box .im-li {
		width:100%;
		height:50px;
		overflow: hidden;
		padding-left:30px;
		list-style: none;
		padding-top:3px;
		padding-bottom:3px;
	}		
	
	.im-friends .im-li:hover {
		background: #eee;
	}	
	
	.im-friends .im-li:hover .nickname {
		color:#000;
	}
	
	.im-friends .im-li .im-li-img,.im-li-text {
		float:left;
	}
	
	.im-friends .im-li .im-li-img  {
		width:40px;
		border-radius:40px;
	}	
	
	.im-friends .im-li .im-li-text {
		margin-left:10px;
		color:#888;
	}
	
	.im-friends .im-li-text .nickname,.signature {
		height:20px;
		line-height:15px;
		font-size:8px;
		cursor: default;
	}
	
	.im-friends .im-li-text .nickname {
		font-size:14px;
	}	
		
</style>

<div class="im-header">
	<div class="im-face-box">
		<img alt="" src="${basePath}images/face.jpg" width="100%">
	</div>
	<div class="im-info-box">
		<p>在线  <i class="iconfont icon-nryc"></i></p>
		<p id="nickname">vip 88888</p>
		<p>IM实验田,来搞一个自己的聊天工具</p>
	</div>
</div>
<div class="im-friends">
	<div class="friend-group" data-idx="0" data-name="myfriend">
		<span class="iconfont icon-nextpage"></span> 我的好友
	</div>
	<div class="im-ul-box" data-name="myfriend">
		<ul class="im-group-ul collapse">
			<li class="im-li">
				<img class="im-li-img" alt="" src="${basePath}images/face.jpg">
				<div class="im-li-text">
					<div class="nickname">zeke</div>
					<div class="signature">每天进步一点</div>
				</div>
			</li>
			<li class="im-li">
				<img class="im-li-img" alt="" src="${basePath}images/face.jpg">
				<div class="im-li-text">
					<div class="nickname">zzw</div>
					<div class="signature">最近爱好js了</div>
				</div>
			</li>
			<li class="im-li">
				<img class="im-li-img" alt="" src="${basePath}images/face.jpg">
				<div class="im-li-text">
					<div class="nickname">kobe</div>
					<div class="signature">牛哄哄</div>
				</div>
			</li>						
		</ul>
	</div>

	<div class="friend-group" data-idx="1" data-name="myworker">
		<span class="iconfont icon-nextpage"></span> 我的同事
	</div>
	<div class="im-ul-box" data-name="myworker">
		<ul class="im-group-ul collapse">
			<li class="im-li">
				<img class="im-li-img" alt="" src="${basePath}images/face.jpg">
				<div class="im-li-text">
					<div class="nickname">zeke</div>
					<div class="signature">每天进步一点</div>
				</div>
			</li>
			<li class="im-li">
				<img class="im-li-img" alt="" src="${basePath}images/face.jpg">
				<div class="im-li-text">
					<div class="nickname">zzw</div>
					<div class="signature">最近爱好js了</div>
				</div>
			</li>
			<li class="im-li">
				<img class="im-li-img" alt="" src="${basePath}images/face.jpg">
				<div class="im-li-text">
					<div class="nickname">kobe</div>
					<div class="signature">牛哄哄</div>
				</div>
			</li>						
		</ul>
	</div>	
</div>





<script type="text/javascript">

	$(function(){
		$("#nickname").text("${nickname}");
		var wsMsg = parent.wsMsg;//console.log(wsMsg);
		var users = wsMsg.users;//console.log(users);
		/* 更新用户自己的信息 */
		updateInfo(wsMsg.from);
		/* 更新好友列表 */
		updateFirendGroup(users);
		
	});
	
	/* 更新用户信息方法 */
	function updateInfo(name){
		$("#nickname").text(name);
	}
	
	/* 更新好友列表方法 */
	function updateFirendGroup(users){
		$(".im-group-ul").html("");
		var myfriends = '';
		var myworkers = '';		
		if(users && users.length > 0){
			for(var i=0; i<users.length; i++){
				for(u in users[i]){
					var key = u; 
					var user = FY.strToJson(users[i][u]);
					if(user && user.group){
						if(user.group == "myfriend"){
							myfriends += friendTempate(key,user);
						}else if(user.group == "myworker"){
							myworkers +=friendTempate(key,user);
						}
					}
					
				}
			}
			//更新列表
			var $uls = $(".im-ul-box");
			for(var g=0; g<$uls.length ; g++){
				var $ul = $uls.eq(g);
				var gname = $ul.data("name");
				if(gname == "myfriend"){
					$ul.find("ul").html(myfriends).fadeIn();
				}else if(gname == "myworder"){
					$ul.find("ul").html(myworkers).fadeIn();
				}
			}
			
			//绑定事件
			$(".im-li").each(function(){
				$(this).bind("dblclick",function(evt){
					var nickname = $(this).find(".nickname").text().trim();
					var signature = $(this).find(".signature").text().trim();
					var user = {
							nickname: nickname,
							signature: signature
					};
					parent.showMsgWindow(user);
				});
			});
			
		}
	}
	
	//好友列表模板
	function friendTempate(key,user){
		return "<li class='im-li'>"+
		 "	<img class='im-li-img' alt='' src='${basePath}images/face.jpg'>"+
		 "	<div class='im-li-text'>"+
		 "		<div class='nickname'>"+key+"</div>"+
		 "		<div class='signature'>"+user.signature+"</div>"+
		 "	</div>"+
		 "</li>";
	}
	
	

	/* 折叠分组 */
	$(".friend-group").on("click",function(evt){
		var name = $(this).data("name"); 
		var idx=0;
		$(".friend-group").each(function(){
			if($(this).data("name") == name){
				return false;
			}
			idx++;
		});
		firendsCollapse(idx);
	});

	
	/* 统一折叠好友分组的方法  */
	function firendsCollapse(idx){
		var $uls = $(".im-ul-box");
		var $groups = $(".friend-group");
		var clsName = "group-collapse";
		var $group = $groups.eq(idx);
		var $group_ul = $uls.eq(idx).find("ul");
		$group.toggleClass(clsName);
		if($group.hasClass(clsName)){
			$group.children("span").removeClass("iconfont icon-nextpage")
			.addClass("iconfont icon-xla");
			$uls.eq(idx).css({"display":"block"});
			$group_ul.slideDown("fast");
		}else{
			$group.children("span").removeClass("iconfont icon-xla")
			.addClass("iconfont icon-nextpage");	
			$uls.eq(idx).css({"display":"block"});
			$group_ul.slideUp("fast");
		}
	}




</script>





消息弹窗页面


chat/chat-msg-template.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
	pageContext.setAttribute("basePath", basePath);
%>
<link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/bootstrap.css">
<link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/bootstrap-theme.css">
<link rel="stylesheet" type="text/css" href="${basePath}css/bootstrap/fileinput.min.css">
<link rel="stylesheet" type="text/css" href="${basePath}js/layer.2.4/layui.css">


<script type="text/javascript" src='${basePath}js/jquery.min.js'></script>
<script type="text/javascript" src='${basePath}js/bootstrap/bootstrap.min.js'></script>
<script type="text/javascript" src='${basePath}js/layer.2.4/layer.js'></script>
<script type="text/javascript" src='${basePath}js/fy.utils.js'></script>
<style>
	body,html {
		padding: 0;
		margin: 0;
	}
	
	.im-header {
		width:100%;
		height: 65px;
		background: #F9f9f9;
		border-bottom:1px solid #eee;
	}
	
	.im-header .im-face-box,.im-info-box {
		float: left;
	}
	
	.im-header .im-face-box {
		width: 80px;
		height: 54px;
		border-radius: 54px;
		padding: 5px 5px 5px 20px;
	}
	
	.im-header .im-face-box>img {
		width: 54px;
		height: 54px;
		border-radius: 54px;
	}
	
	.im-header .im-info-box {
		width:205px;
		margin-left: 10px;
		overflow: hidden;
	}
	
	.im-header .im-info-box p {
		font-size: 12px;
		line-height: 20px;
		height: 20px;
		padding: 2px;
		margin: 2px;
	}
	
	/* 消息显示框样式  */
	.im-content {
		
	}
	
	.im-content #msg-show,#msg-input,#msg-btns {
		width:100%;
	}	
	
	.im-content #msg-show {
		height:160px;
		padding:5px;
		overflow-y: auto;
	}	
	
	.im-content #msg-show .msg-item {
		height:auto;
	}	
	
	#msg-show .msg-item .msg-title,.msg-content {
		min-height:40px;
	}
	
	#msg-show .msg-item .msg-content {
		padding:5px;
		margin-bottom:10px;
	}	

	#msg-show .msg-title .mt-face  {
		width:32px;
		height:32px;
		border-radius:32px;
		margin-right:5px;
	}		
	
	#msg-show .msg-title .mt-face,.mt-name {
		float:left;
	}

	#msg-show .msg-title .mt-name {
		line-height:35px;
		font-size:14px;
	}
	
	#msg-show .msg-title .mt-name span {
		padding-left:5px;
	}	
	
	/* 消息输入框格式   */		
	.im-content #msg-input {
		height:60px;
		position: absolute;
		bottom:40px;
		padding:5px;
		border-top:5px solid #eee;
		overflow-y: auto;
		word-wrap: break-word;
		outline:none;
	}	
	
	.im-content #msg-btns {
		height:40px;
		position: absolute;
		bottom:0;
		padding-right:5px;
		padding-top:2px;
	}
	
	.im-content #msg-btns button {
		font-size:12px !important;
	}
		
	
</style>

<div class="im-header">
	<div class="im-face-box">
		<img alt="" src="${basePath}images/face.jpg" width="100%">
	</div>
	<div class="im-info-box">
		<p id="nickname">zeke</p>
		<p id="signature">PQ 实验田,来搞一个自己的聊天工具</p>
	</div>
</div>


<div class="im-content">
	<div id="msg-show"></div>
	<div id="msg-input" contenteditable="true"> </div>
	<div id="msg-btns" >
		<button type="button" id="msg-send" class="btn btn-success btn-xs pull-right">
			<i class="iconfont icon-qtsfkuan"></i> 发  送 
		</button>
	</div>
</div>





<script type="text/javascript">
	$(function(){
		/* 打开窗口光标设置在输入框 */
		$("#msg-input").focus();
	});
	

</script>





利用 TensorFlow 训练自己的目标识别器。本文内容来自于我的毕业设计,基于 TensorFlow 1.15.0,其他 TensorFlow 版本运行可能存在问题。.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值