聊天室应用——jquery + node.js + websocket

1.index.js
var app = require('express')();
var express = require('express');
var Server = require('http').createServer(app);
var io = require('socket.io')(Server);
var path = require('path');
var Router = require('./Router');
//配置body-parser
var BodyParser = require('body-parser');
app.use(BodyParser.urlencoded({
     extend: false}));
app.use(BodyParser.json());
//配置默认可以访问的静态资源目录
app.use('/views/',express.static(path.join(__dirname , './views')));
/*
  配置使用 art-template  模板引擎,第一个参数表示,当渲染以  .art 结尾的文件的时候(也可以修改为其他后缀,如: .html ), 使用
  art-template  模板引擎, express-art-template  是专门用来在 Express 中把art-template 整合到Express 中,原因在于 express-art-template 依赖了 art-template
*/
app.engine('html',require('express-art-template'));

//服务器监听端口
Server.listen(5000,() => {
     
   console.log('Listening on *:5000');
});

//加载路由
app.use(Router);

//定义获取现在时间的函数
function Time(){
     
   var D = new Date();
   var Hours = D.getHours();
   var Minutes = D.getMinutes();
   var Seconds = D.getSeconds(); 
   if(Minutes <10 && Minutes >=0 && Seconds < 10 && Seconds >= 0) {
     
      return Hours + ':0' + Minutes  + ':0'+Seconds ; 
   }
   if(Minutes <10 && Minutes >=0 && Seconds > 10 ){
     
      return Hours + ':0' + Minutes + ':' + Seconds ; 
   }
   if(Minutes > 10 &&  Seconds < 10 && Seconds >= 0){
     
      return Hours +':' + Minutes + ':0' + Seconds ; 
   }
   return Hours + ':' + Minutes + ':' + Seconds;
}

var User = new Map();    //定义一个数组,登记相应用户的socket.id,便于通信
var count = 0 ;    //定义一个变量用来维护当前在线人数

//socket信道内容处理
//处理登录信息
io.on('connection',(socket)=>{
     
   var SaveName = Router.SaveName; 

    count++;
    //上线通知,获取服务的Save数组里的用户数据
    console.log(SaveName +' had connected!');
   
   //socket通道连接后,向客户端发送在线用户数量
   io.emit('online',{
     
      count: count
   })

   //接收聊天信息
   socket.on('chat',(msg)=>{
     
      console.log( msg.Name + ':   ——'+msg.Message);
      User.set(socket.id,msg.Name);  //存储用户与socket.id的关系
      //除了发送者以外,连接到客户端的用户都可以收到这个信息
      io.emit('Saying',{
     
         data: msg.Message,
         name: msg.Name  ,  //表示当前信息是由哪个用户发出
         time: Time(),    //信息发送时间
         src: msg.Anvarta
      });
   });
   
   //用于渲染用户列表接收base64格式的图片,再群发给连接当前服务器用户
   socket.on('ListAnvarta',(msg)=>{
     
       io.emit('listAnvarta',{
     
         Src: msg.Src,
         Name: SaveName
       })
   })

   //监听断开连接
   socket.on('disconnect',()=>{
     
      count--;
      //发送离线用户数量
      io.emit('offline',{
     
         count: count
      })
      io.emit('offList',{
     
         Name: User.get(socket.id)
      })
      //离线通知
      console.log(User.get(socket.id) + " had off-line! onlines: " + count);
      User.delete('socket.id');  //删除下线用户
   });

});



2.Router.js
    //导包
    const {
      response } = require('express');
    var express =  require('express');
    var Router = express.Router();

    //变量,函数区域
    Router.SaveName ='';  //保存当前登录用户的用户名

    //登录页面发送
    Router.get('/',(req,res) => {
     
    res.render('D:\\web\\commute\\views\\html\\login.html');
    });

    //主页面的发送
    Router.post('/index',(req,res) =>{
     
        var body = req.body;
        // console.log(body.UserName  +','+ body.Account);
        Router.SaveName = body.UserName;
        //发送渲染页面
        res.render('D:\\web\\commute\\views\\html\\index.html',{
     
            UserName: body.UserName,
            Account: body.Account
        })
    });

    //导出包含路由的容器
    module.exports = Router;





1.index.html
DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Socket.IO chattitle>
    <link rel="stylesheet" href="views/css/index.css">
<head>
  <body>
  <div id="WeChat">
    
    <div id="Bar">
     
      <div id="Photo">
         <div id='Instead'>上传头像div>
         <input type='file' id='File' value='获取图片' />
         <img src="" id="Anvarta" >
      div>    
    
      <div id=NA>
        <div id="Name">{
    {UserName}}div>
        <div id="Account" >{
    {Account}}div>
      div> 
    
      <div id="Onlines">
      div>

    div>
    
    <div id="UserList">
    div>
   
    <div id="Right"> 
      
      <div id="DisplayMessage">
      div>
    
      
      <div id="SentBoard">
          <textarea name="" id="message">textarea>
          <button id="Send">Sendbutton>  
  
      div>
      
  
    div>
   
  div>
    
    
    <script src="/socket.io/socket.io.js">script>
    <script src="https://code.jquery.com/jquery-1.11.1.js" rel="external nofollow" >script>
    <script type="text/javascript">
   
    $(function(){
       
       //创建socket通道 
      var Info = io.connect('127.0.0.1:5000');
      //获取添加头像有关的元素
      var GetImg = document.getElementById('File');
      var Anvarta = document.getElementById('Anvarta');
      var Instead = document.getElementById('Instead');
      var ChatAnvarta =document.getElementById('ChatAnvarta');
      var Onlines = document.getElementById('Onlines');
      var SId = '';     //暂存当前socket的专用ID
  
      //获取用户信息
      var Name = $('#Name').text();
      
      //用户上线后,接收服务端发来的在线用户数量
      Info.on('online',(msg)=>{
       
         $('#Onlines').html('Onlines users : ' + msg.count);
      })
       //用户离线后,接收服务端发来的在线用户数量
       Info.on('offline',(msg)=>{
       
         $('#Onlines').html('Onlines users : ' + msg.count);
      })
      //发送信息 
       $('#Send').click(()=>{
       
         //发送聊天信息
           Info.emit('chat',{
       
              Message: $('#message').val(),
              Name: $('#Name').text(),
              Anvarta: $('#Anvarta').attr('src')        //发送当前用户的base64编码后的头像信息
           });
           $('#message').val('');  //消息发送后,清空聊天框
       });

      //渲染聊天信息到聊天界面
      Info.on('Saying',(msg)=>{
       
        console.log( msg.name + ': '+msg.data);
        /*
          
23:05:43
*/
//如果是本身发送的信息,就渲染在右侧 if(msg.name == Name){ $Time = '
'+ msg.time+'
'
; $TimeBar = '
'+ $Time +'
'
; $RAnvarta = '+ msg.src +'" id="RAnvarta">'; $Rmessages = '
'+ msg.data +'
'
; $RContent = '
'+$TimeBar+$Rmessages+$RAnvarta+'
'
; $('#DisplayMessage').append($RContent); } else{ $Time = '
'+ msg.time+'
'
; $TimeBar = '
'+ $Time +'
'
; $LAnvarta = '+ msg.src +'" id="LAnvarta">'; $Lmessages = '
'+ msg.data +'
'
; $LContent = '
'+$TimeBar+$LAnvarta+$Lmessages+'
'
; $('#DisplayMessage').append($LContent); } }); //添加头像 GetImg.onchange = function(){ var file = this.files[0]; //若选择多张图片时,用第一张 if(window.FileReader){ //如果当前浏览器可以使用FileReader var fr = new FileReader(); //定义一个读取文件对象 fr.readAsDataURL(file); //输入要读取的文件,定义读取完毕后的文件格式 fr.onloadend = (event)=>{ //读取完毕后 Anvarta.src = event.target.result; Src = event.target.result; //将头像图片发送到服务器,再由服务器选择是否发送到其他对象 Info.emit('ListAnvarta',{ //向服务端发送base64编码格式的照片 Src: event.target.result, }); } } //隐形与显形切换 Instead.style.opacity = 0; Anvarta.style.opacity = 1; } //渲染上线用户列表 Info.on('listAnvarta',(msg)=>{ //新增一个用户,jquery的字符串拼接 var $Abord ="
"
; var $UserName = "
" +msg.Name+ "
"
; var $User = "
"+$Abord+$UserName+ "
"
; $('#UserList').append($User); var AnvartaList = document.getElementsByClassName('UserAnvarta'); for ( index = 0 ; index < AnvartaList.length ; ++index){ AnvartaList[index].style.opacity = 1; } }); //渲染离线用户列表 Info.on('offList',(msg)=>{ //用jquery的find()方法找到相应的子元素,再对整个元素删除 var index = 0 ; var UserLists = document.getElementsByClassName('UserName'); //通过名字检测,找到相应元素的序号 for( ; index < UserLists.length; index++){ if(UserLists[index].innerHTML == msg.Name){ //在一个大的范围下,于相同的元素中选择删除第n个进行删除,冒号之间不能有空格,泪的教训 break; } } //加一是因为nth-child是从一开始,而不是零 index += 1; $('#UserList > .User:nth-child('+index+')').remove(); }); });
script> body> html> 2.login.html DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>聊天室登录界面title> <link rel="stylesheet" href="/views/css/login.css"> head> <body> <form action="/index" method="POST" id="LoginForm"> <div id="Title">We are Chatting!div> <input type="text" id="UserName" name="UserName" placeholder="UserName:"> <input type="text" id="Account" name="Account" placeholder="Account:"> <button id="Enter" type="submit">Join us!!!button> form> <script src="https://code.jquery.com/jquery-1.11.1.js" rel="external nofollow" >script> <script> script> body> html> 3.login.css body{ display:flex; flex-direction: column; align-items: center; padding: 0px; margin: 0px; background-image:linear-gradient(to right, aqua,orange); } #LoginForm { display:flex; width: 300px; height: 500px; margin-top: 100px; flex-direction: column; align-items: center; justify-content: center; border-radius:16px; box-shadow:3px 3px 10px black ; transition: 0.3s; background-image: radial-gradient(to right ,orange,aqua); } #LoginForm:hover{ box-shadow: 10px 10px 15px black ; cursor:pointer; } #Title{ display: flex; align-items: flex-start; justify-content: center; width: 250px; height: 60px; font-size: 30px; color:white; } #UserName , #Account{ display:flex; flex-direction: flex-start; align-items: center; justify-content: flex-start; padding-left: 10px; width: 250px; height: 50px; margin-top: 30px; border-radius: 16px; font-size: 20px; border:none; outline-style:none; } #Enter{ display:flex; flex-direction: flex-start; align-items: center; justify-content: center; width: 100px; height: 40px; margin-top: 50px; border-radius:20px; font-size: 20px; border: none; color:white; background-image: linear-gradient(to right , rgba(34, 214, 202, 0.612),rgba(255, 230, 0, 0.809)); } #Enter:hover{ cursor:pointer; color:black ; } 4.index.css * { margin: 0; padding: 0; box-sizing: border-box; } body { display:flex; flex-direction:column; justify-content: center; align-items: center; background-image: linear-gradient(to right , rgb(13, 243, 228),rgb(245, 233, 62)); } #WeChat{ display: flex; justify-content: center; align-items: flex-start; width: 800px; height: 600px; margin-top: 80px; border-radius: 15px; box-shadow: 5px 5px 10px black; flex-wrap: wrap; overflow: hidden; background-image: linear-gradient(to right , rgba(13, 243, 228, 0.34),rgba(245, 233, 62, 0.395)) ; } #Bar{ display: flex; justify-content: center; align-items: flex-start; width: 800px; height: 80px; background-image: linear-gradient( to right , rgba(13, 243, 228, 0.748),rgba(13, 243, 228, 0.639),rgba(245, 233, 62, 0.639)); } #Photo{ display: flex; justify-content: center; align-items: center; width: 100px; height: 80px; margin-left: 30px; } #Anvarta{ position: absolute; width: 70px; height: 70px; border-radius: 50%; border:none; opacity: 0; background-color: aliceblue; } #File{ position:absolute; width: 70px; height: 70px; border-radius: 50%; opacity: 0; z-index: 10; background-color: aliceblue; } #Instead{ position: absolute; display: flex; justify-content: center; align-items: center; width: 70px; height: 70px; border-radius: 50%; font-size: 10px; background-color: white; } #NA{ display:flex; flex-direction: column; justify-content: center; align-items: center; width: 220px; margin-left: 15px; height: inherit; } #Name { display: flex; justify-content:flex-start; align-items: flex-start; width: 200px; height: 30px; color:rgb(255, 255, 255); text-shadow: 2px 2px 3px black; } #Account{ display: flex; justify-content:flex-start; align-items: flex-start; width: 200px; height: 30px; color:rgb(255, 255, 255); text-shadow: 2px 2px 3px black; } #Onlines{ display: flex; justify-content: center; align-items: center; width: 300px; height: inherit; text-shadow: 2px 2px 2px black; margin-left: 240px; border-radius: 15px ; color: rgb(255, 255, 255); } #UserList{ display: inline-block; width: 180px; height: 520px; background-image: linear-gradient(to left , rgba(13, 243, 228, 0.639),rgba(62, 245, 239, 0.673)); overflow: auto; } .User{ display:flex; justify-content: center; align-items: center; width: 150px; height: 60px; margin-top: 10px; margin-left: 8px; background-image: linear-gradient(to right , rgba(13, 243, 228, 0.639),rgba(245, 233, 62, 0.639)) ; border-radius: 16px; box-shadow:1px 1px 3px black; } #Abord{ display: inline-block; width: 45px; height: 45px; margin-top: 3px; margin-left: 5px; border-radius: 50%; overflow: hidden; background-color: aliceblue; } .UserAnvarta{ display: inline-block; width: 45px; height: 45px; border-radius: 50%; border:none; background-color: aliceblue; opacity: 0; /*待服务端发送头像过来,再显示*/ } .UserName{ display: inline-block; width:100px; height: 20px; padding-left: 5px; color:aliceblue; overflow: hidden; } .UserName:hover{ color:black; cursor:pointer; } /* 滚动条样式设置 ::-webkit-scrollbar //滚动条整体部分 ::-webkit-scrollbar-button //滚动条两端的按钮 ::-webkit-scrollbar-track // 外层轨道 ::-webkit-scrollbar-track-piece //内层轨道,滚动条中间部分(除去) ::-webkit-scrollbar-thumb //滚动条里面可以拖动的那个 ::-webkit-scrollbar-corner //边角 ::-webkit-resizer ///定义右下角拖动块的样式 */ ::-webkit-scrollbar { height: auto; width: 5px; } /* 定义滚动条轨道内阴影+圆角*/ ::-webkit-scrollbar-track{ border-radius: 10px; background-image: linear-gradient(to bottom , rgba(13, 243, 228, 0.639),rgba(245, 233, 62, 0.639)); } /* 定义滑块内阴影+圆角 */ ::-webkit-scrollbar-thumb{ border-radius: 5px; background-color: rgb(240, 248, 255); } #Right{ display:flex; flex-direction: column; justify-content: flex-start; align-items: flex-start; width: 620px; } #DisplayMessage{ display:inline-block; width: 620px; height: 300px; box-shadow: 2px 2px 5px black inset; overflow:auto; background-image: linear-gradient(to right , rgba(0, 255, 255, 0.667),rgba(255, 255, 0, 0.177)); } #LContent{ display:flex; justify-content: flex-start; align-items: center; width: inherit; height: 100px; margin-top:10px; } #LAnvarta{ display: inline-block; width:50px; height: 50px; border-radius: 50%; margin-left: -607px; box-shadow: 2px 2px 3px black; background-color: aliceblue; } #Lmessages{ display: flex; justify-content: flex-start; align-items: center; overflow-wrap:normal ; padding-left: 10px; padding-right: 10px; width:400px; height:55px; box-shadow: 2px 2px 3px black; border-radius: 20px; margin-left: 10px; font-size: 10px; background-image: linear-gradient(to right,rgba(255, 255, 255, 0.531),rgba(137, 228, 238, 0.313)); } .TimeBar{ display:inline-block; width: inherit; height: 20px; margin-top:-78px; } .Time{ display:flex; justify-content: center; align-items: center; width: 80px; height: inherit; color:aliceblue; margin-left:265px; border-radius: 20px; background-color: rgba(0, 0, 0, 0.544); } #RContent{ display:flex; justify-content: flex-start; align-items: center; width: inherit; height: 100px; margin-top:10px; } #Rmessages{ display: flex; justify-content: flex-end; align-items: center; overflow-wrap:normal ; padding-left: 10px; padding-right: 10px ; width:500px; height:55px; box-shadow: 2px 2px 3px black; border-radius: 20px; margin-left: -350px; font-size: 10px; background-image: linear-gradient(to right,rgba(255, 255, 255, 0.531),rgba(137, 228, 238, 0.313)); } #RAnvarta{ display: inline-block; width:50px; height: 50px; border-radius: 50%; margin-right: 10px; margin-left: 10px; box-shadow: 2px 2px 3px black; background-color: aliceblue; } #SentBoard{ display: flex; justify-content: center; align-items: flex-start; width: 620px; height: 200px; margin-top: 22px; box-shadow: 2px 2px 5px black inset; } #message{ display: flex; justify-content: flex-start; align-items: flex-start; width: 620px; font-size: 20px; height: 200px; padding-top: 10px; padding-left: 10px; border:none; resize:none; outline: none; border-bottom-right-radius: 16px; box-shadow: 2px 2px 5px black inset; background-image: linear-gradient(to right,rgba(0, 255, 255, 0.299),rgba(255, 255, 0, 0.265)); } #Send{ position:absolute; width:50px; height:50px; color: black; border-radius: 50%; border: none; outline-style: none; margin-top: 143px; margin-left: 550px; box-shadow: 2px 2px 3px black; background-image: linear-gradient(to right,rgba(0, 255, 255, 0.524),rgba(255, 255, 0, 0.401)) ; } #Send:hover{ cursor:pointer; color:white; }

1.具有聊天,用户上下线功能,其他具体功能还可以利用数据库等技术再进行添加,应用效果图:



你可能感兴趣的:(JS,css,node.js,jquery,javascript)