项目地址服务器源地址:https://github.com/ermu592275254/chat-socket网页源地址:https://github.com/ermu592275254/chat-socket项目设计概述相关技术nodejs使用nodejs搭建后台,由于是单页面应用,前后端通信使用webSocket,所以只用http模块搭建了一个简单的服务器,以及没有使用koa、express等web框架。webSocket使用socket.io实现webSocket,前端会通过importsocket.io方法不断重连,所以是用脚本实现的。constio=require('socket.io-client');//或使用导入语法importiofrom'socket.io-client';//orscriptmongodb使用mongoose操作mongodb。非关系数据库如mongodb的功能比关系数据库少得多。主要表现在复杂的sql语句、事务支持等。Vue使用vue及其衍生产品,使用bootstarp作为样式框架。简单兼容PC和手机。(PC只支持chrome,在firefox、ie等浏览器中,样式和排版会混乱)。该功能点通过用户名和socketId匹配实现私聊。每次用户登录时保存socketId,当对方在线时通过socketId将此信息发送给对方。仅在不在线时保存到数据库中,用户在线时可在私聊中查看。目前不支持消息通知,也不支持未读消息...//每次登录时,将socketId替换为当前登录的socketIduserModel.update({username:data.username},{socketId:socket。ID})。then(res=>{socket.emit('login',user);}).catch(err=>{console.log(err);socket.emit('err','更新用户socketId失败');});...chatModel.findOne({sendTime:time}).populate('senderreceiver').then(newChat=>{letreceiverData={receiver:data.sender,data:newChat};//如果对方在线时发送给对方data.receiver,数据:newCh在};//同时也发送给自己(也可以在前端直接添加,后端不发送)io.sockets.connected[socket.id].emit('newMessage',发件人数据);}).catch(err=>{io.sockets.connected[socket.id].emit('err','找不到newMessage')})群聊通过广播实现群发,并保存对应的聊天记录到组和数据库中的组。当用户进入群聊时,会添加到相应的广播中。socket.on('joinRoom',function(data){if(!common.checkData(data)){io.sockets.connected[socket.id].emit('err','请求参数不能为空');return;}//加入相应的群聊socket.join(data.groupName,function(){letroomName=Object.keys(socket.rooms);io.to(data.groupName,`${data.username}已加入房间`);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','消息数据为空');}头像上传也是使用webSocket,头像ID保存在用户信息表中,图片文件保存在服务器的静态文件夹中uploadIcon(){letfile=this.$refs.uploadEl.files[0];控制台日志(文件);if(file.size>100000){this.Toast('文件大小不能超过1M');this.$refs.uploadEl.value='';返回;}letdata={username:this.user.username,file:file,type:file.type.split('/')[1]};socket.emit('uploadUserIcon',数据);this.$refs.uploadEl.value='';}socket.on('uploadUserIcon',function(data){lettime=newDate().getTime();letsavePath=`/static/userIcon/${time}.${data.type}`;lethostPath='http://'+host+':'+port;//通过fs模块操作fs.writeFile('.'+savePath,data.file,function(err){if(err){console.log(err);io.sockets.connected[socket.id].emit('err','saveuserIconfailed');}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:'uploaduserIconsuccess'});}).catch(err=>{io.sockets.connected[socket.id].emit('err','finduserInfofailed');});}).catch(err=>{io.sockets.connected[socket.id].emit('err','saveuserIconpathfailed');})}})});登录注册将用户名注册为唯一值时无法注册现有用户名。Login支持自动登录,密码保存在localStorage中。pendingbugs和优化打包后静态资源路径有问题(有没有大神帮我QAQ)需要在未读消息红点加表情和发图片最后:这是极录有的一个项目努力了一年,多次放弃又重新拾起。代码写的不好看,也没有精力和热情去优化。让我们暂时这样做......
