chat-pc/src/event/talk.js

285 lines
7.1 KiB
JavaScript
Raw Normal View History

2024-12-24 08:14:21 +00:00
import Base from './base'
import { nextTick } from 'vue'
import ws from '@/connect'
import { parseTime } from '@/utils/datetime'
import * as message from '@/constant/message'
import { formatTalkItem, palyMusic, formatTalkRecord } from '@/utils/talk'
import { isElectronMode } from '@/utils/common'
import { ServeClearTalkUnreadNum, ServeCreateTalkList } from '@/api/chat'
import { useTalkStore, useDialogueStore, useSettingsStore } from '@/store'
import { isScrollAtBottom, scrollToBottom } from '@/utils/dom'
2024-12-24 08:14:21 +00:00
/**
* 好友状态事件
*/
class Talk extends Base {
/**
* @var resource 资源
*/
resource
/**
* 发送者ID
*/
sender_id = 0
/**
* 接收者ID
*/
receiver_id = 0
/**
* 聊天类型[1:私聊;2:群聊;]
*/
talk_type = 0
/**
* 初始化构造方法
*
* @param {Object} resource Socket消息
*/
constructor(resource) {
super()
this.sender_id = resource.sender_id
this.receiver_id = resource.receiver_id
this.talk_type = resource.talk_type
this.resource = resource.data
this.handle()
}
/**
* 判断消息发送者是否来自于我
* @returns
*/
isCurrSender() {
return this.sender_id == this.getAccountId()
}
/**
* 获取对话索引
*
* @return String
*/
getIndexName() {
if (this.talk_type == 2) {
return `${this.talk_type}_${this.receiver_id}`
}
let receiver_id = this.isCurrSender() ? this.receiver_id : this.sender_id
return `${this.talk_type}_${receiver_id}`
}
/**
* 获取聊天列表左侧的对话信息
*/
getTalkText() {
let text = ''
if (this.resource.msg_type != message.ChatMsgTypeText) {
text = message.ChatMsgTypeMapping[this.resource.msg_type]
} else {
text = this.resource.extra.content.replace(/<img .*?>/g, '')
}
return text
}
// 播放提示音
play() {
// 客户端有消息提示
if (isElectronMode()) return
useSettingsStore().isPromptTone && palyMusic()
}
async handle() {
2024-12-24 08:14:21 +00:00
// 不是自己发送的消息则需要播放提示音
if (!this.isCurrSender()) {
this.play()
}
// 判断会话列表是否存在,不存在则创建
if (useTalkStore().findTalkIndex(this.getIndexName()) == -1) {
if (this.resource.msg_type == 1102) {
//被邀请进入群聊时,需要热更新会话列表
await useTalkStore().loadTalkList()
} else if (this.resource.msg_type == 1106) {
//群解散时,需要热更新会话列表
await useTalkStore().loadTalkList()
} else if (this.resource.msg_type == 1104 || this.resource.msg_type == 1115) {
//群成员被移出时,需要热更新会话列表
await useTalkStore().loadTalkList()
} else {
return this.addTalkItem()
}
2024-12-24 08:14:21 +00:00
}
// 判断当前是否正在和好友对话
if (this.isTalk(this.talk_type, this.receiver_id, this.sender_id)) {
this.insertTalkRecord()
} else {
this.updateTalkItem()
}
}
/**
* 显示消息提示
* @returns
*/
showMessageNocice() {
if (useSettingsStore().isLeaveWeb) {
const notification = new Notification('IM 在线聊天', {
2024-12-24 08:14:21 +00:00
dir: 'auto',
lang: 'zh-CN',
body: '您有新的消息请注意查收'
})
notification.onclick = () => {
notification.close()
}
} else {
window['$notification'].create({
title: '消息通知',
content: '您有新的消息请注意查收',
duration: 3000
})
}
}
/**
* 加载对接节点
*/
addTalkItem() {
let receiver_id = this.sender_id
let talk_type = this.talk_type
if (talk_type == 1 && this.receiver_id != this.getAccountId()) {
receiver_id = this.receiver_id
} else if (talk_type == 2) {
receiver_id = this.receiver_id
}
ServeCreateTalkList({
talk_type,
receiver_id
}).then(({ code, data }) => {
if (code == 200) {
let item = formatTalkItem(data)
item.unread_num = 1
useTalkStore().addItem(item)
}
})
}
/**
* 插入对话记录
*/
insertTalkRecord() {
let record = this.resource
// 群成员变化的消息,需要更新群成员列表
if ([1102, 1103, 1104, 1115].includes(record.msg_type)) {
2024-12-24 08:14:21 +00:00
useDialogueStore().updateGroupMembers()
}
//群解散时,需要更新群成员权限
if ([1106].includes(record.msg_type)) {
useDialogueStore().updateDismiss(true)
}
//群成员被移出时,需要更新群成员权限
if ([1104, 1115].includes(record.msg_type)) {
if (this.resource?.extra?.members?.length > 0) {
const isMeQuit = this.resource.extra.members.find(
(item) => item.user_id === this.getAccountId()
)
if (isMeQuit) {
useDialogueStore().updateQuit(true)
}
}
}
// 群信息变更时,需要更新群信息
if ([1116].includes(record.msg_type)) {
// 更新会话信息
useDialogueStore().updateDialogueTalk({
username: record.extra.group_name,
avatar: record.extra.group_avatar
})
//更新会话列表中的会话信息
useTalkStore().updateItem({
index_name: this.getIndexName(),
name: record.extra.group_name,
avatar: record.extra.group_avatar
})
}
2024-12-24 08:14:21 +00:00
useDialogueStore().addDialogueRecord(formatTalkRecord(this.getAccountId(), this.resource))
if (!this.isCurrSender()) {
// 推送已读消息
setTimeout(() => {
ws.emit('im.message.read', {
receiver_id: this.sender_id,
msg_ids: [this.resource.msg_id]
})
}, 1000)
}
console.log('输出加载1')
2024-12-24 08:14:21 +00:00
// 获取聊天面板元素节点
const el = document.getElementById('imChatPanel')
if (!el) return
// 判断的滚动条是否在底部
const isBottom = isScrollAtBottom(el)
2024-12-24 08:14:21 +00:00
if (isBottom || record.user_id == this.getAccountId()) {
scrollToBottom()
2024-12-24 08:14:21 +00:00
} else {
useDialogueStore().setUnreadBubble()
}
useTalkStore().updateItem({
index_name: this.getIndexName(),
msg_text: this.getTalkText(),
updated_at: parseTime(new Date())
})
if (this.talk_type == 1 && this.getAccountId() !== this.sender_id) {
ServeClearTalkUnreadNum({
talk_type: 1,
receiver_id: this.sender_id
})
}
}
/**
* 更新对话列表记录
*/
updateTalkItem() {
useTalkStore().updateMessage({
index_name: this.getIndexName(),
msg_text: this.getTalkText(),
updated_at: parseTime(new Date())
})
//收到新消息时,同时判断是否有人@我
if (this.resource.msg_type === 1 && this.resource?.extra?.mentions?.length > 0) {
const findMention = this.resource?.extra?.mentions?.find(
(mention) => mention === this.getAccountId()
)
//有人@我或者@所有人,则更新会话列表
if (findMention || this.resource?.extra?.mentions?.includes(0)) {
// useTalkStore().loadTalkList()
useTalkStore().updateItem({
index_name: this.getIndexName(),
msg_text: this.getTalkText(),
atsign_num: 1
})
}
}
2024-12-24 08:14:21 +00:00
}
}
export default Talk