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 chat</title>
<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">Send</button>
</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);
/*
<div id="RContent">
<div class="TimeBar">
<div class="Time">23:05:43</div>
</div>
<img src="" id="RAnvarta">
<div id="Rmessages"></div>
</div>
*/
//如果是本身發送的資訊,就渲染在右側
if(msg.name == Name){
$Time = '<div class="Time">'+ msg.time+'</div>';
$TimeBar = '<div class="TimeBar">'+ $Time +'</div>' ;
$RAnvarta = '<img src= "'+ msg.src +'" id="RAnvarta">';
$Rmessages = '<div id="Rmessages">'+ msg.data +'</div>';
$RContent = '<div id="RContent">'+$TimeBar+$Rmessages+$RAnvarta+'</div>';
$('#DisplayMessage').append($RContent);
}
else{
$Time = '<div class="Time">'+ msg.time+'</div>';
$TimeBar = '<div class="TimeBar">'+ $Time +'</div>' ;
$LAnvarta = '<img src= "'+ msg.src +'" id="LAnvarta">';
$Lmessages = '<div id="Lmessages">'+ msg.data +'</div>';
$LContent = '<div id="LContent">'+$TimeBar+$LAnvarta+$Lmessages+'</div>';
$('#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 ="<div id='Abord'><img src= ' "+ msg.Src +" ' alt='' class='UserAnvarta'></div>" ;
var $UserName = "<div class='UserName'>" +msg.Name+ "</div>";
var $User = "<div class='User'>"+$Abord+$UserName+ "</div>";
$('#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.具有聊天,用戶上下線功能,其他具體功能還可以利用資料庫等技術再進行添加,應用效果圖:




轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/286340.html
標籤:其他
上一篇:一小時入門vue組件(建議收藏)
