• vue-advanced-chat使用指南


    demo地址:—
    vue-advanced-chat的git地址:https://github.com/advanced-chat/vue-advanced-chat

    1.搭建demo

    demo地址克隆后在demo目录安装依赖并启动
    在这里插入图片描述
    启动之后的页面如下:
    在这里插入图片描述

    2.前端代码分析

    在这里插入图片描述

    2.1 重点api分析

    current-user-id:当前用户id

    room-id:可随时加载特定房间?

    rooms:?

    messages:消息列表

    room-actions:可用于在单击房间列表中每个房间的下拉图标时显示您自己的按钮

    配合事件room-action-handler使用

    roomActions: [
    {
        name: 'inviteUser', title: '测试下拉' },
    {
        name: 'removeUser', title: 'Remove User' },
    {
        name: 'deleteRoom', title: 'Delete Room' }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    menu-actions:可用于在单击房间内的垂直点图标时显示您自己的按钮

    配合事件menu-action-handler使用

    menuActions: [
    {
        name: 'inviteUser', title: '测试菜单' },
    {
        name: 'removeUser', title: 'Remove User' },
    {
        name: 'deleteRoom', title: 'Delete Room' }
    ],
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    message-selection-actions:选择消息时,您可以使用它在房间标题中显示自定义操作按钮

    messageSelectionActions: [{
        name: 'deleteMessages', title: '你确定要删除嘛?' }]
    
    • 1
    • 2

    在这里插入图片描述

    templates-text:可用于/在房间文本区域中输入内容时添加自动完成模板文本

    templatesText: [
    				{
       
    					tag: '吃好',
    					text: '吃好喝好,一路走好!'
    				},
    				{
       
    					tag: 'action',
    					text: 'This is the action'
    				},
    				{
       
    					tag: 'action 2',
    					text: 'This is the second action'
    				}
    			],
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    text-messages:可用于替换默认的 i18n 文本

    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: '取消'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    2.2 重点事件分析

    fetch-more-rooms ?

    向下滚动房间列表时触发,应该是实现分页系统的方法

    fetch-messages

    每次打开房间时都会触发。如果房间是第一次打开,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)
    })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    send-message

    发送消息,点击发送或者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() })
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    edit-message

    编辑消息

    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 })
    		}
    	}
    }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    delete-message

    删除消息

    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)
    		})
    	}
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    open-file

    下载文件

    openFile({
         file }) {
       
    	window.open(file.file.url, '_blank')
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    open-user-tag ?这个应该用不到

    当点击消息内的用户标签时触发。通过@在页脚文本区域中输入并发送消息来创建用户标签
    在这里插入图片描述

    add-room

    添加房间
    在这里插入图片描述

    addRoom() {
       
    	this.resetForms()
    	this.addNewRoom = true
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    room-action-handler、menu-action-handler

    配合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)
    }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    message-selection-action-handler

    配合api中的message-selection-actions使用

    messageSelectionActionHandler({
         action, messages, roomId }) {
       
    switch (action.name) {
       
    	case 'deleteMessages':
    		messages.forEach(message => {
       
    			this.deleteMessage({
        message, roomId })
    		})
    }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    send-message-reaction

    单击消息内的表情符号图标

    async sendMessageReaction({
         reaction, remove, messageId, roomId }) {
       
    	firestoreService.updateMessageReactions(
    		roomId,
    		messageId,
    		this.currentUserId,
    		reaction.unicode,
    		remove ? 'remove' : 'add'
    	)
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    typing-message

    开始输入消息(在对方可以看到“正在输入中。。。”的提示)

    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'
    		)
    	}
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    toggle-rooms-list

    单击房间标题内的切换图标

    2.3 公用函数

    resetMessages()

    重置房间的消息基础变量

    resetMessages() {
       
    	this.messages = []
    	this.messagesLoaded = false
    	this.lastLoadedMessage = null
    	this.previousLastLoadedMessage = null
    	this.listeners.forEach(listener => listener())
    	this.listeners = []
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    formatMessage()

    格式化消息模板

    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
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    listenMessages() ?

    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]
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    通过memberlist库实现gossip管理集群以及集群数据交互
    华为与开放原子开源基金会携四大开源产品亮相1024程序员节
    后端java部署教程,docker配置解读(linux用docker部署新手入门)
    压力测试-JMeter安装、入门、结果分析
    Spring IOC源码:registerBeanPostProcessors 详解
    Docker 入门流程
    mac,linux环境的基础工具安装【jdk,tomcat】
    SQL审核工具自荐Owls
    如何使用Jenkins持续集成构建接口自动化测试--配置邮件通知
    数据化运营10 运营评估:如何通过数据复盘衡量你的运营策略?
  • 原文地址:https://blog.csdn.net/beekim/article/details/134176752