vue2.0開發聊天程序(八) 初步完成

圖片描述圖片描述圖片描述圖片描述圖片描述

項目地址

服務器源碼地址: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方式實現。vue

const io = require('socket.io-client');
// or with import syntax
import io from 'socket.io-client';

// or script
<script src="/socket.io/socket.io.js"></script>
<script>
  const socket = io('http://localhost');
</script>

mongodb

使用mongoose操做mongodb。mongodb這類非關係型數據庫,功能較關係型數據庫閹割了許多。主要表如今複雜的sql語句、事務支持等。node

vue

使用vue以及vue的衍生產品,同時用到bootstarp做爲樣式框架。簡單兼容了PC和移動。(PC僅支持chrome,在firefox、ie等瀏覽器中,會出現樣式、佈局混亂的狀況)。git

功能點實現

私聊

經過用戶名和socketId進行匹配。保存用戶每次登陸的socketId,當對方在線時,將此信息經過socketId發送給對方。不在線僅保存到數據庫,用戶上線便可在私聊中查看。目前不支持消息通知,也不支持未讀消息github

...// 每次登陸都將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中。web

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文件夾中。sql

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中。mongodb

待處理bug以及優化

打包後靜態資源路徑有問題(有沒有大神能幫幫我QAQ)

須要未讀消息小紅點

增長表情、圖片發送

最後: 這是本菜雞陸陸續續作了一年的項目,屢次放棄又從新拾起。代碼寫得不堪入目,沒有精力和激情再去作優化了。暫時先這樣吧......chrome

相關文章
相關標籤/搜索