摘要:主要表现在复杂的语句事务支持等。仅支持,在等浏览器中,会出现样式布局混乱的情况。将群群对应的聊天记录保存在数据库。用户进入群聊,则将其加入到对应的中。文件大小不能超过通过模块操作登录注册将用户名作为唯一值。登录支持自动登录,将密码保存在中。
项目地址
服务器源码地址:https://github.com/ermu592275254/chat-socket 网页源码地址:https://github.com/ermu592275254/chat-socket项目设计概述 相关技术 nodejs
使用nodejs搭建后台,因为是一个单页应用,并且前后端通信使用了webSocket,所有只用http模块搭建一个简单的服务器,未使用koa、express等web框架。
webSocket使用socket.io实现webSocket,前端通过import socket.io 的方式会出现不断重连的情况,于是使用script方式实现。
const io = require("socket.io-client"); // or with import syntax import io from "socket.io-client"; // or scriptmongodb
使用mongoose操作mongodb。mongodb这类非关系型数据库,功能较关系型数据库阉割了许多。主要表现在复杂的sql语句、事务支持等。
vue使用vue以及vue的衍生产品,同时用到bootstarp作为样式框架。简单兼容了PC和移动。(PC仅支持chrome,在firefox、ie等浏览器中,会出现样式、布局混乱的情况)。
功能点实现 私聊通过用户名和socketId进行匹配。保存用户每次登录的socketId,当对方在线时,将此信息通过socketId发送给对方。不在线仅保存到数据库,用户上线即可在私聊中查看。目前不支持消息通知,也不支持未读消息
...// 每次登录都将socketId替换为当前登录的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 }; // 如果对方在线就发送给对方 if (io.sockets.connected[user.socketId]) { io.sockets.connected[user.socketId].emit("newMessage", receiverData); } let senderData = { receiver: data.receiver, data: newChat }; // 同时也发送给自己(也可直接在前端添加,后端不发送) io.sockets.connected[socket.id].emit("newMessage", senderData); }).catch(err=>{ io.sockets.connected[socket.id].emit("err", "can`t find the newMessage") })群聊
通过broadcast实现组发送。将群、群对应的聊天记录保存在数据库。用户进入群聊,则将其加入到对应的broadcast中。
socket.on("joinRoom", function(data) { if (!common.checkData(data)) { io.sockets.connected[socket.id].emit("err", "request params Can`t be empty"); return; } // 加入对应的群聊 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){ // 发送给自己 io.sockets.connected[socket.id].emit("newMsgOfGroup", res); // 将消息发送给群里的所有人除了自己 socket.broadcast.in(data.groupName).emit("newMsgOfGroup", res); } else { io.sockets.connected[socket.id].emit("err", "the message data is null"); }头像上传
同样使用webSocket,将头像ID保存在用户信息表中,将图片文件保存在服务器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"); }) } }) });登录注册
将用户名作为唯一值。注册时不能注册已存在的用户名。登录支持自动登录,将密码保存在localStorage中。
待处理bug以及优化 打包后静态资源路径有问题(有没有大神能帮帮我QAQ) 需要未读消息小红点 增加表情、图片发送最后: 这是本菜鸡陆陆续续做了一年的项目,多次放弃又重新拾起。代码写得不堪入目,没有精力和激情再去做优化了。暂时先这样吧......
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/92941.html
摘要:先看看兼容性创建连接构造函数接收两个参数这里的不能是或者而是对应的或者和是定义的两种方案,类似于类似于协议名称,是可选的。服务端和客户端的协议名称必须一致。协议有三种注册协议,开放协议,自定义协议。限制以内就是在构造函数中选传的参数。 愿天下所有的情侣,都是失散多年的兄妹 ——好妹妹webScoket是html5提出的一个协议,咱们用的http是无状态...
摘要:在离开过渡被触发时生效,在完成之后移除。可以链式的多次使用和用法相同,但是的元素会始终渲染并保存在中,只是改变值。用法如下对应前面的数据 在我一生的黄金时代,我有好多奢望。我想爱,想吃,还想在一瞬间变成天上半明半暗的云。 ——王小波上一章研究了vue中组件的通信,算是对vue的组件通信有了大致的了解。综合上三章对搭建项...
摘要:用法如下注册全局的指令注册一个全局自定义指令当绑定元素插入到中。具体代码如下当组件中需要用到其他的组件时,需要使用属性去创建一个哈希表。具体用法如下包含组件引入组件在中添加组件的哈希表收尾除了上面这些属性,还有一些杂项详情请看官网 后来我才知道,生活就是个缓慢受锤的过程,人一天天老下去,奢望也一天天消失,最后变得像挨了锤的牛一样。 ...
摘要:为安装文件,无需再配置环境变量。连接操作有以下包作者并未查到除此之外的包,但不代表没有。等于是每个默认配置的主键属性,属性名为可自己定义一个来覆盖此属性。需要注意的是,在新版本的文档中,为。通过创建限于篇幅,本小节暂时写到这里。 我的琴声呜咽,我的泪水全无。我把远方的远归还草原。 - 海子《九月》 mongodb安装 什么是Mongodb?就是一个基...
阅读 693·2021-11-22 13:52
阅读 1498·2021-09-27 13:36
阅读 2800·2021-09-24 09:47
阅读 2130·2021-09-22 15:48
阅读 3575·2021-09-22 15:39
阅读 1437·2019-08-30 12:43
阅读 2905·2019-08-29 18:39
阅读 3157·2019-08-29 12:51