chat-pc/src/hooks/useTalkRecord.ts

154 lines
3.4 KiB
TypeScript
Raw Normal View History

2024-12-24 08:14:21 +00:00
import { reactive, computed, nextTick } from 'vue'
import { ServeTalkRecords } from '@/api/chat'
import { useDialogueStore } from '@/store'
import { ITalkRecord } from '@/types/chat'
import { formatTalkRecord } from '@/utils/talk'
import { addClass, removeClass } from '@/utils/dom'
interface Params {
receiver_id: number
talk_type: number
limit: number
}
export const useTalkRecord = (uid: number) => {
const dialogueStore = useDialogueStore()
const records = computed((): ITalkRecord[] => dialogueStore.records)
const location = reactive({
msgid: '',
num: 0
})
const loadConfig = reactive({
receiver_id: 0,
talk_type: 0,
status: 0,
cursor: 0
})
const onJumpMessage = (msgid: string) => {
const element = document.getElementById(msgid)
if (!element) {
if (location.msgid == '') {
location.msgid = msgid
location.num = 3
} else {
location.num--
if (location.num === 0) {
location.msgid = ''
location.num = 0
window['$message'].info('仅支持查看最近300条的记录')
return
}
}
const el = document.getElementById('imChatPanel')
return el?.scrollTo({
top: 0,
behavior: 'smooth'
})
}
location.msgid = ''
location.num = 0
element?.scrollIntoView({
behavior: 'smooth'
})
addClass(element, 'border')
setTimeout(() => {
element && removeClass(element, 'border')
}, 3000)
}
// 加载数据列表
const load = async (params: Params) => {
const request = {
talk_type: params.talk_type,
receiver_id: params.receiver_id,
cursor: loadConfig.cursor,
limit: 30
}
loadConfig.status = 0
let scrollHeight = 0
const el = document.getElementById('imChatPanel')
if (el) {
scrollHeight = el.scrollHeight
}
const { data, code } = await ServeTalkRecords(request)
if (code != 200) {
return (loadConfig.status = 1)
}
// 防止对话切换过快,数据渲染错误
if (
request.talk_type != loadConfig.talk_type ||
request.receiver_id != loadConfig.receiver_id
) {
return (location.msgid = '')
}
const items = (data.items || []).map((item: ITalkRecord) => formatTalkRecord(uid, item))
if (request.cursor == 0) {
// 判断是否是初次加载
dialogueStore.clearDialogueRecord()
}
dialogueStore.unshiftDialogueRecord(items.reverse())
loadConfig.status = items.length >= request.limit ? 1 : 2
loadConfig.cursor = data.cursor
nextTick(() => {
const el = document.getElementById('imChatPanel')
if (el) {
if (request.cursor == 0) {
el.scrollTop = el.scrollHeight
setTimeout(() => {
el.scrollTop = el.scrollHeight + 1000
}, 50)
} else {
el.scrollTop = el.scrollHeight - scrollHeight
}
}
if (location.msgid) {
onJumpMessage(location.msgid)
}
})
}
const onRefreshLoad = () => {
if (loadConfig.status == 1) {
load({
receiver_id: loadConfig.receiver_id,
talk_type: loadConfig.talk_type,
limit: 30
})
}
}
const onLoad = (params: Params) => {
loadConfig.cursor = 0
loadConfig.receiver_id = params.receiver_id
loadConfig.talk_type = params.talk_type
load(params)
}
return { loadConfig, records, onLoad, onRefreshLoad, onJumpMessage }
}