vue.js+socket.io+express+mongodb打造在线聊天[二]
在线地址观看
介绍
本项目基于vue.js+socket.io+express+mongodb实现的聊天效果, 界面以及功能参考QQ,微信技术栈
- 前端: vue,vue-router,vuex,axios
- 构建: webpack,vue-cli
- 后端: express,multer(上传图片),cors(跨域处理), superagent(调用机器人接口),mongoose(操作数据库)
- 通讯: socket.io
- 数据库: mongodb
- css预处理器: sass
功能列表
- 用户注册
- 用户登录
- 群聊
- 群聊中@小美 和机器人聊天 (注意@小美和消息中间要有空格)
- 机器人聊天
- 留言板
- 更换主题颜色
- 进出聊天群提醒
功能展示
- 登录与注册
- 群聊
- 群聊中与机器人聊天
- 机器人聊天
- 留言板
- 更换主题
好啦~功能差不多就这些啦,这次添加了进出群提醒,主题颜色更换还有布局的一些调整。废话不多说啦,接下来该介绍介绍核心部分,以免被各位小哥哥,小姐姐打。
前端聊天代码
const infoObj = { status: 'userstate', nickname: this.getUserinfo.nickname, roomId: this.roomId } this.socket.emit('join-room', infoObj) this.socket.on('join-room', (joinInfo) => { this.MsgList.push(joinInfo) this.$nextTick(() => { this.msgDOM.scrollTop = this.msgDOM.scrollHeight }) }) // 聊天 this.socket.on('chat-msg', (msg) => { console.log(msg) this.MsgList.push(msg) this.$nextTick(() => { this.msgDOM.scrollTop = this.msgDOM.scrollHeight }) }) // 离开房间 this.socket.on('leave-room', (leaveInfo) => { this.MsgList.push(leaveInfo) this.$nextTick(() => { this.msgDOM.scrollTop = this.msgDOM.scrollHeight }) })
后端聊天代码
io.on('connection', (socket) => { // 进入房间 socket.on('join-room', (info) => { // 添加到房间 socket.join(info.roomId) const joinInfo = { status: info.status, text: info.nickname + '加入了群聊' } socket.to(info.roomId).broadcast.emit('join-room', joinInfo) }) // 群聊天 socket.on('chat-msg', (msg) => { saveChatMsg(msg, () => { io.to(msg.roomId).emit('chat-msg', msg) // 分割聊天消息,判断是否与机器人聊天 const msgArr = msg.text.split(' ') const robotParam = { userId: msg.userId, roomId: msg.roomId || null, timeStamp: msg.timeStamp + 1 || null, text: msgArr[1] } if (msgArr[0] === '@小美') { getRobotMsg(robotParam, (robotmsg) => { saveChatMsg(robotmsg) io.to(msg.roomId).emit('chat-msg', robotmsg) }) } }) }) // 机器人聊天 socket.on('robot-msg', (msg) => { const robotParam = { userId: msg.userId, timeStamp: msg.timeStamp, text: msg.text } getRobotMsg(robotParam, (robotmsg) => { socket.emit('robot-msg', robotmsg) }) }) // 离开房间 socket.on('leave-room', (info) => { socket.leave(info.roomId) const leaveInfo = { status: info.status, text: info.nickname + '离开了群聊' } socket.to(info.roomId).broadcast.emit('leave-room', leaveInfo) })})
vuex
export default new Vuex.Store({ state: { // 主题颜色 themeColor: '', // 存放用户信息 userInfo: { userId: '', nickname: '', headPic: '' }, // 机器人信息 robot: { Info: { userId: 'robot', nickname: '小美', headPic: '/static/img/robot-headpic.jpg' }, // 机器人打招呼 greetMsg: 'hi~ 我是机器人小美,有什么可以帮您的嘛?' } }, getters: { // 获取主题颜色 getThemeColor: state => { return state.themeColor }, // 获取登录用户信息 getUserinfo: state => { return state.userInfo }, // 获取机器人信息 getRobotinfo: state => { return state.robot.Info }, // 获取机器人欢迎语 getRobotGreetMsg: state => { return state.robot.greetMsg } }, mutations: { // 设置用户信息 setUserinfo(state, userInfo) { state.userInfo.userId = userInfo.userId state.userInfo.nickname = userInfo.nickname state.userInfo.headPic = userInfo.headPic }, // 设置聊天记录 setHistoryMsg(state, msgList) { state.msgInfo = msgList }, // 设置主题颜色 setThemeColor(state, color) { state.themeColor = color } }, actions: { // 注册用户 async register({commite}, data) { const res = await url.register(data) if (res.data.state === 0) { return { status: 'fail', data: res.data.data } } return { status: 'success', data: res.data.data } }, // 登录用户 async login({commite}, data) { const res = await url.login(data) if (res.data.state === 0) { return { status: 'fail', data: res.data.data } } return { status: 'success', data: res.data.data } }, // 上传图片 async upload({commite}, data) { await url.upload(data) }, // 获取聊天记录 async getHistoryChatMsg({commite}, data) { const res = await url.gethistorychatmsg(data) return { status: 'success', data: res.data.data.msgList } }, // 保存留言 async saveLeaveMsg({commite}, data) { const res = await url.saveleavemsg(data) return { status: res.data.data.stateText } }, // 获取留言数据 async getLeaveMsg({commite}) { const res = await url.getleavemsg() return { status: res.data.data.stateText, data: res.data.data.leaveMsg } } }})