赞
踩
demo地址:—
vue-advanced-chat的git地址:https://github.com/advanced-chat/vue-advanced-chat
demo地址克隆后在demo目录安装依赖并启动
启动之后的页面如下:
配合事件room-action-handler使用
roomActions: [
{
name: 'inviteUser', title: '测试下拉' },
{
name: 'removeUser', title: 'Remove User' },
{
name: 'deleteRoom', title: 'Delete Room' }
]
配合事件menu-action-handler使用
menuActions: [
{
name: 'inviteUser', title: '测试菜单' },
{
name: 'removeUser', title: 'Remove User' },
{
name: 'deleteRoom', title: 'Delete Room' }
],
messageSelectionActions: [{
name: 'deleteMessages', title: '你确定要删除嘛?' }]
templatesText: [ { tag: '吃好', text: '吃好喝好,一路走好!' }, { tag: 'action', text: 'This is the action' }, { tag: 'action 2', text: 'This is the second action' } ],
textMessages: {
ROOMS_EMPTY: '无聊天',
ROOM_EMPTY: '未选中聊天',
NEW_MESSAGES: '新消息',
MESSAGE_DELETED: '消息已删除',
MESSAGES_EMPTY: '无消息',
CONVERSATION_STARTED: '聊天开始于:',
TYPE_MESSAGE: '请输入',
SEARCH: '搜索',
IS_ONLINE: '在线',
LAST_SEEN: 'last seen ',
IS_TYPING: '正在输入...',
CANCEL_SELECT_MESSAGE: '取消'
}
向下滚动房间列表时触发,应该是实现分页系统的方法
每次打开房间时都会触发。如果房间是第一次打开,options参数将保持reset: true。(其目的是当用户滚动到顶部时加载对话的较旧消息)
fetchMessages({ room, options = { } }) { this.$emit('show-demo-options', false) //如果是第一次打开就初始化房间的参数 if (options.reset) { this.resetMessages() } if (this.previousLastLoadedMessage && !this.lastLoadedMessage) { this.messagesLoaded = true return } //设置当前选中的房间的id值 this.selectedRoom = room.roomId console.info('[fetchMessages] Selected Room(选中的房间id):' + this.selectedRoom) console.info('[fetchMessages] Selected Room messages per page(选中房间消息页码):' + this.messagesPerPage) console.info('[fetchMessages] Selected Room last loaded message(选中房间最后加载的消息):' + this.lastLoadedMessage) firestoreService .getMessages(room.roomId, this.messagesPerPage, this.lastLoadedMessage) .then(({ data, docs }) => { // this.incrementDbCounter('Fetch Room Messages', messages.length) //判空 if (this.selectedRoom !== room.roomId) return //从接口获取到的消息数据为空,或者拿到的数据长度小于本地消息长度,就显示loading if (data.length === 0 || data.length < this.messagesPerPage) { setTimeout(() => { this.messagesLoaded = true }, 0) } //如果是第一次打开就将消息变量messages置为空 if (options.reset) this.messages = [] data.forEach(message => { //格式化消息为模板消息 const formattedMessage = this.formatMessage(room, message) console.info('[fetchMessages] Formatted Message(格式化后的消息):' + JSON.stringify(formattedMessage)) this.messages.unshift(formattedMessage) }) console.info('[fetchMessages] Fetch Room Messages Length(获取到的消息长度):' + this.messages.length) if (this.lastLoadedMessage) { this.previousLastLoadedMessage = this.lastLoadedMessage } this.lastLoadedMessage = docs[docs.length - 1] this.listenMessages(room) }) }
发送消息,点击发送或者enter时触发
async sendMessage({ content, roomId, files, replyMessage }) { //content消息内容 、 roomId房间id 、files文件 、replyMessage(微信引用)回复的消息 const message = { sender_id: this.currentUserId, content, timestamp: new Date() } if (files) { message.files = this.formattedFiles(files) } if (replyMessage) { message.replyMessage = { _id: replyMessage._id, content: replyMessage.content, sender_id: replyMessage.senderId } if (replyMessage.files) { message.replyMessage.files = replyMessage.files } } console.info('[sendMessage] room id is(发送消息的房间id):' + roomId) console.info('[sendMessage] message is:' + JSON.stringify(message)) const { id } = await firestoreService.addMessage(roomId, message) console.info('[sendMessage] message id is:' + id) if (files) { for (let index = 0; index < files.length; index++) { await this.uploadFile({ file: files[index], messageId: id, roomId }) } } console.info('[sendMessage] update room with id:' + roomId) firestoreService.updateRoom(roomId, { lastUpdated: new Date() }) },
编辑消息
async editMessage({ messageId, newContent, roomId, files }) { const newMessage = { edited: new Date() } newMessage.content = newContent if (files) { newMessage.files = this.formattedFiles(files) } else { newMessage.files = firestoreService.deleteDbField } await firestoreService.updateMessage(roomId, messageId, newMessage) if (files) { for (let index = 0; index < files.length; index++) { if (files[index]?.blob) { await this.uploadFile({ file: files[index], messageId, roomId }) } } } },
删除消息
async deleteMessage({ message, roomId }) { await firestoreService.updateMessage(roomId, message._id, { deleted: new Date() }) const { files } = message if (files) { files.forEach(file => { storageService.deleteFile(this.currentUserId, message._id, file) }) } },
下载文件
openFile({
file }) {
window.open(file.file.url, '_blank')
},
当点击消息内的用户标签时触发。通过@在页脚文本区域中输入并发送消息来创建用户标签
添加房间
addRoom() {
this.resetForms()
this.addNewRoom = true
},
配合api中的room-actions、menu-actions一起使用
menuActionHandler({
action, roomId }) {
switch (action.name) {
case 'inviteUser':
return this.inviteUser(roomId)
case 'removeUser':
return this.removeUser(roomId)
case 'deleteRoom':
return this.deleteRoom(roomId)
}
},
配合api中的message-selection-actions使用
messageSelectionActionHandler({
action, messages, roomId }) {
switch (action.name) {
case 'deleteMessages':
messages.forEach(message => {
this.deleteMessage({
message, roomId })
})
}
},
单击消息内的表情符号图标
async sendMessageReaction({
reaction, remove, messageId, roomId }) {
firestoreService.updateMessageReactions(
roomId,
messageId,
this.currentUserId,
reaction.unicode,
remove ? 'remove' : 'add'
)
},
开始输入消息(在对方可以看到“正在输入中。。。”的提示)
typingMessage({ message, roomId }) { if (roomId) { if (message?.length > 1) { this.typingMessageCache = message return } if (message?.length === 1 && this.typingMessageCache) { this.typingMessageCache = message return } this.typingMessageCache = message firestoreService.updateRoomTypingUsers( roomId, this.currentUserId, message ? 'add' : 'remove' ) } },
单击房间标题内的切换图标
重置房间的消息基础变量
resetMessages() {
this.messages = []
this.messagesLoaded = false
this.lastLoadedMessage = null
this.previousLastLoadedMessage = null
this.listeners.forEach(listener => listener())
this.listeners = []
},
格式化消息模板
formatMessage(room, message) { // const senderUser = room.users.find(user => user._id === message.sender_id) const formattedMessage = { ...message, ...{ senderId: message.sender_id, _id: message.id, seconds: message.timestamp.seconds, timestamp: parseTimestamp(message.timestamp, 'HH:mm'), date: parseTimestamp(message.timestamp, 'DD MMMM YYYY'), username: room.users.find(user => message.sender_id === user._id) ?.username, // avatar: senderUser ? senderUser.avatar : null, distributed: true } } if (message.replyMessage) { formattedMessage.replyMessage = { ...message.replyMessage, ...{ senderId: message.replyMessage.sender_id } } } return formattedMessage },
listenMessages(room) { const listener = firestoreService.listenMessages( room.roomId, this.lastLoadedMessage, this.previousLastLoadedMessage, messages => { messages.forEach(message => { const formattedMessage = this.formatMessage(room, message) const messageIndex = this.messages.findIndex( m => m._id === message.id ) if (messageIndex === -1) { console.log('[listenMessages] new formatted message:' + JSON.stringify(formattedMessage)) this.messages = this.messages.concat([formattedMessage]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。