摘要:主要表現(xiàn)在復(fù)雜的語句事務(wù)支持等。僅支持,在等瀏覽器中,會出現(xiàn)樣式布局混亂的情況。將群群對應(yīng)的聊天記錄保存在數(shù)據(jù)庫。用戶進(jìn)入群聊,則將其加入到對應(yīng)的中。文件大小不能超過通過模塊操作登錄注冊將用戶名作為唯一值。登錄支持自動登錄,將密碼保存在中。
項(xiàng)目地址
服務(wù)器源碼地址:https://github.com/ermu592275254/chat-socket 網(wǎng)頁源碼地址:https://github.com/ermu592275254/chat-socket項(xiàng)目設(shè)計(jì)概述 相關(guān)技術(shù) nodejs
使用nodejs搭建后臺,因?yàn)槭且粋€(gè)單頁應(yīng)用,并且前后端通信使用了webSocket,所有只用http模塊搭建一個(gè)簡單的服務(wù)器,未使用koa、express等web框架。
webSocket使用socket.io實(shí)現(xiàn)webSocket,前端通過import socket.io 的方式會出現(xiàn)不斷重連的情況,于是使用script方式實(shí)現(xiàn)。
const io = require("socket.io-client"); // or with import syntax import io from "socket.io-client"; // or scriptmongodb
使用mongoose操作mongodb。mongodb這類非關(guān)系型數(shù)據(jù)庫,功能較關(guān)系型數(shù)據(jù)庫閹割了許多。主要表現(xiàn)在復(fù)雜的sql語句、事務(wù)支持等。
vue使用vue以及vue的衍生產(chǎn)品,同時(shí)用到bootstarp作為樣式框架。簡單兼容了PC和移動。(PC僅支持chrome,在firefox、ie等瀏覽器中,會出現(xiàn)樣式、布局混亂的情況)。
功能點(diǎn)實(shí)現(xiàn) 私聊通過用戶名和socketId進(jìn)行匹配。保存用戶每次登錄的socketId,當(dāng)對方在線時(shí),將此信息通過socketId發(fā)送給對方。不在線僅保存到數(shù)據(jù)庫,用戶上線即可在私聊中查看。目前不支持消息通知,也不支持未讀消息
...// 每次登錄都將socketId替換為當(dāng)前登錄的socketId userModel.update({username: data.username}, {socketId: socket.id}).then(res => { socket.emit("login", user); }).catch(err => { console.log(err); socket.emit("err", "update user socketId was failed"); }); ...
chatModel.findOne({sendTime: time}).populate("sender receiver").then(newChat=>{ let receiverData = { receiver: data.sender, data: newChat }; // 如果對方在線就發(fā)送給對方 if (io.sockets.connected[user.socketId]) { io.sockets.connected[user.socketId].emit("newMessage", receiverData); } let senderData = { receiver: data.receiver, data: newChat }; // 同時(shí)也發(fā)送給自己(也可直接在前端添加,后端不發(fā)送) io.sockets.connected[socket.id].emit("newMessage", senderData); }).catch(err=>{ io.sockets.connected[socket.id].emit("err", "can`t find the newMessage") })群聊
通過broadcast實(shí)現(xiàn)組發(fā)送。將群、群對應(yīng)的聊天記錄保存在數(shù)據(jù)庫。用戶進(jìn)入群聊,則將其加入到對應(yīng)的broadcast中。
socket.on("joinRoom", function(data) { if (!common.checkData(data)) { io.sockets.connected[socket.id].emit("err", "request params Can`t be empty"); return; } // 加入對應(yīng)的群聊 socket.join(data.groupName, function() { let roomName = Object.keys(socket.rooms); io.to(data.groupName, `${data.username} has joined the room`); socket.broadcast.in("data.groupName").emit("newUserJoin", { groupName: data.groupName, username: data.username }) }); })
groupChatModel.findOne({"sendTime": time}).populate("sender").then(res=>{ if(res){ // 發(fā)送給自己 io.sockets.connected[socket.id].emit("newMsgOfGroup", res); // 將消息發(fā)送給群里的所有人除了自己 socket.broadcast.in(data.groupName).emit("newMsgOfGroup", res); } else { io.sockets.connected[socket.id].emit("err", "the message data is null"); }頭像上傳
同樣使用webSocket,將頭像ID保存在用戶信息表中,將圖片文件保存在服務(wù)器static文件夾中。
uploadIcon(){ let file = this.$refs.uploadEl.files[0]; console.log(file); if(file.size > 100000){ this.Toast("文件大小不能超過1M"); this.$refs.uploadEl.value = ""; return; } let data = { username: this.user.username, file: file, type: file.type.split("/")[1] }; socket.emit("uploadUserIcon", data); this.$refs.uploadEl.value = ""; }
socket.on("uploadUserIcon", function(data) { let time = new Date().getTime(); let savePath = `/static/userIcon/${time}.${data.type}`; let hostPath = "http://" + host + ":" + port; // 通過fs模塊操作 fs.writeFile("."+ savePath, data.file, function(err) { if (err) { console.log(err); io.sockets.connected[socket.id].emit("err", "save userIcon failed"); } else { userModel.update({username: data.username}, {$set: {userIcon: hostPath + savePath}}).then(res => { userModel.findOne({username: data.username}).then(user=>{ io.sockets.connected[socket.id].emit("uploadUserIcon", { user: user, message: "upload userIcon success" }); }).catch(err =>{ io.sockets.connected[socket.id].emit("err", "find userInfo failed"); }); }).catch(err => { io.sockets.connected[socket.id].emit("err", "save userIcon path failed"); }) } }) });登錄注冊
將用戶名作為唯一值。注冊時(shí)不能注冊已存在的用戶名。登錄支持自動登錄,將密碼保存在localStorage中。
待處理bug以及優(yōu)化 打包后靜態(tài)資源路徑有問題(有沒有大神能幫幫我QAQ) 需要未讀消息小紅點(diǎn) 增加表情、圖片發(fā)送最后: 這是本菜雞陸陸續(xù)續(xù)做了一年的項(xiàng)目,多次放棄又重新拾起。代碼寫得不堪入目,沒有精力和激情再去做優(yōu)化了。暫時(shí)先這樣吧......
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/92941.html
摘要:先看看兼容性創(chuàng)建連接構(gòu)造函數(shù)接收兩個(gè)參數(shù)這里的不能是或者而是對應(yīng)的或者和是定義的兩種方案,類似于類似于協(xié)議名稱,是可選的。服務(wù)端和客戶端的協(xié)議名稱必須一致。協(xié)議有三種注冊協(xié)議,開放協(xié)議,自定義協(xié)議。限制以內(nèi)就是在構(gòu)造函數(shù)中選傳的參數(shù)。 愿天下所有的情侶,都是失散多年的兄妹 ——好妹妹webScoket是html5提出的一個(gè)協(xié)議,咱們用的http是無狀態(tài)...
摘要:在離開過渡被觸發(fā)時(shí)生效,在完成之后移除。可以鏈?zhǔn)降亩啻问褂煤陀梅ㄏ嗤?,但是的元素會始終渲染并保存在中,只是改變值。用法如下對應(yīng)前面的數(shù)據(jù) 在我一生的黃金時(shí)代,我有好多奢望。我想愛,想吃,還想在一瞬間變成天上半明半暗的云?! 跣〔ㄉ弦徽卵芯苛藇ue中組件的通信,算是對vue的組件通信有了大致的了解。綜合上三章對搭建項(xiàng)...
摘要:用法如下注冊全局的指令注冊一個(gè)全局自定義指令當(dāng)綁定元素插入到中。具體代碼如下當(dāng)組件中需要用到其他的組件時(shí),需要使用屬性去創(chuàng)建一個(gè)哈希表。具體用法如下包含組件引入組件在中添加組件的哈希表收尾除了上面這些屬性,還有一些雜項(xiàng)詳情請看官網(wǎng) 后來我才知道,生活就是個(gè)緩慢受錘的過程,人一天天老下去,奢望也一天天消失,最后變得像挨了錘的牛一樣?! ?..
摘要:為安裝文件,無需再配置環(huán)境變量。連接操作有以下包作者并未查到除此之外的包,但不代表沒有。等于是每個(gè)默認(rèn)配置的主鍵屬性,屬性名為可自己定義一個(gè)來覆蓋此屬性。需要注意的是,在新版本的文檔中,為。通過創(chuàng)建限于篇幅,本小節(jié)暫時(shí)寫到這里。 我的琴聲嗚咽,我的淚水全無。我把遠(yuǎn)方的遠(yuǎn)歸還草原?! ? 海子《九月》 mongodb安裝 什么是Mongodb?就是一個(gè)基...
閱讀 746·2021-11-22 13:52
閱讀 1553·2021-09-27 13:36
閱讀 2863·2021-09-24 09:47
閱讀 2224·2021-09-22 15:48
閱讀 3625·2021-09-22 15:39
閱讀 1493·2019-08-30 12:43
閱讀 2947·2019-08-29 18:39
閱讀 3221·2019-08-29 12:51