vue.js+socket.io+express+mongodb打造在线聊天[二]
在线地址观看
http://www.chenleiming.com/vuechat
github地址
https://github.com/clm960227/...
有喜欢的小哥哥,小姐姐请反手来个star,谢谢!有issue的欢迎提出
介绍
本项目基于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
}
}
}
})