解决聊天记录页面分页、数据加载、渲染等问题

This commit is contained in:
wangyifeng 2025-03-07 15:02:53 +08:00
parent ea73fa8b9b
commit ba0a5384e0
4 changed files with 82 additions and 31 deletions

View File

@ -7,25 +7,29 @@ import lodash from 'lodash'
export const useTalkRecord = (uid) => {
const dialogueStore = useDialogueStore()
const { getDialogueList,addDialogueRecord,zpagingComplete } = useDialogueListStore()
const {
getDialogueList,
addDialogueRecord,
zpagingComplete,
} = useDialogueListStore()
const records = computed(() => {
const dialogueList = getDialogueList(dialogueStore.index_name)
if(dialogueList){
if (dialogueList) {
return lodash.cloneDeep(dialogueList.records).reverse()
}
return lodash.cloneDeep(dialogueStore.records)?.reverse()
} )
})
const location = reactive({
msgid: '',
num: 0
num: 0,
})
const loadConfig = reactive({
receiver_id: 0,
talk_type: 0,
status: 0,
cursor: 0
cursor: 0,
})
const onJumpMessage = (msgid) => {
@ -49,7 +53,7 @@ export const useTalkRecord = (uid) => {
return el?.scrollTo({
top: 0,
behavior: 'smooth'
behavior: 'smooth',
})
}
@ -57,7 +61,7 @@ export const useTalkRecord = (uid) => {
location.num = 0
element?.scrollIntoView({
behavior: 'smooth'
behavior: 'smooth',
})
addClass(element, 'border')
@ -70,7 +74,7 @@ export const useTalkRecord = (uid) => {
// 加载数据列表
const load = async (params) => {
const request = {
limit:30,
limit: 30,
...params,
talk_type: params.talk_type,
receiver_id: params.receiver_id,
@ -104,8 +108,11 @@ export const useTalkRecord = (uid) => {
const reverseItems = lodash.cloneDeep(items).reverse()
dialogueStore.unshiftDialogueRecord(reverseItems)
addDialogueRecord(params.direction=='down'?reverseItems:items,params.direction=='down'?'add':'unshift')
zpagingComplete(dialogueStore.index_name)
addDialogueRecord(
params.direction == 'down' ? reverseItems : items,
params.direction == 'down' ? 'add' : 'unshift',
)
zpagingComplete(dialogueStore.index_name, reverseItems)
const dialogueList = getDialogueList(dialogueStore.index_name)
loadConfig.status = dialogueList.records?.[0]?.sequence > 1 ? 1 : 2
// loadConfig.cursor = data.cursor
@ -133,17 +140,19 @@ export const useTalkRecord = (uid) => {
const onRefreshLoad = () => {
let dialogueList = getDialogueList(dialogueStore.index_name)
if (dialogueList.records[0].sequence === 1 ) {
if (dialogueList.records[0].sequence === 1) {
return false
}
if (loadConfig.status == 1) {
let filterList = dialogueList.records.filter(item=>item.sequence !== -1)
let filterList = dialogueList.records.filter(
(item) => item.sequence !== -1,
)
loadConfig.cursor = filterList[0].sequence
load({
receiver_id: loadConfig.receiver_id,
talk_type: loadConfig.talk_type,
direction:'up',
no_limit:0,
direction: 'up',
no_limit: 0,
})
}
}
@ -152,12 +161,14 @@ export const useTalkRecord = (uid) => {
let dialogueList = getDialogueList(params.index_name)
if (!dialogueList) {
loadConfig.cursor = 0
}else{
let filterList = dialogueList.records.filter(item=>item.sequence !== -1)
if(params.direction=='up'){
} else {
let filterList = dialogueList.records.filter(
(item) => item.sequence !== -1,
)
if (params.direction == 'up') {
loadConfig.cursor = filterList?.[0]?.sequence
}else{
loadConfig.cursor = filterList?.[filterList.length-1]?.sequence
} else {
loadConfig.cursor = filterList?.[filterList.length - 1]?.sequence
}
}
loadConfig.receiver_id = params.receiver_id

View File

@ -2,15 +2,17 @@
<div class="dialog-page">
<ZPaging
use-chat-record-mode
:refresher-enabled="false"
use-virtual-list
cell-height-mode="dynamic"
:refresher-enabled="true"
:show-scrollbar="false"
:loading-more-enabled="false"
:loading-more-enabled="true"
:hide-empty-view="true"
height="100%"
ref="zpagingRef"
v-model="virtualList"
:loading-more-custom-style="{ display: 'none', height: '0' }"
@scrolltolower="onRefreshLoad"
@scrolltolower="onScrollToLower"
>
<template #top>
<customNavbar :title="talkParams.username">
@ -35,7 +37,7 @@
<!-- <template #top>
<div class="load-toolbar pointer">
<span v-if="loadConfig.status == 0"> 正在加载数据中 ... </span>
<span v-else-if="loadConfig.status == 1" @click="onRefreshLoad"> 查看更多消息 ... </span>
<span v-else-if="loadConfig.status == 1" @click="onScrollToLower"> 查看更多消息 ... </span>
<span v-else class="no-more"> 没有更多消息了 </span>
</div>
</template> -->
@ -166,10 +168,19 @@
</div>
<div class="load-toolbar pointer" style="transform: scaleY(-1);">
<span v-if="loadConfig.status == 0">正在加载数据中 ...</span>
<span v-else-if="loadConfig.status == 1" @click="onRefreshLoad">
<span v-else-if="loadConfig.status == 1" @click="onScrollToLower">
查看更多消息 ...
</span>
<span v-else class="no-more">没有更多消息了</span>
<span
v-else-if="
loadConfig.status != 0 &&
loadConfig.status != 1 &&
state.localPageLoadDone
"
class="no-more"
>
没有更多消息了
</span>
</div>
</div>
<template #bottom>
@ -389,11 +400,12 @@ const state = ref({
showWin: false,
onfocusItem: null,
sessionId: '',
localPageLoadDone: true, //
})
uniOnload((options) => {
if (options.sessionId) {
state.sessionId = options.sessionId
state.value.sessionId = options.sessionId
}
})
@ -814,6 +826,35 @@ watch(
},
)
watch(
() => virtualList.value,
(newValue, oldValue) => {
if (newValue) {
const dialogueList = getDialogueList(talkParams.index_name)
console.log(newValue[newValue.length - 1].sequence, dialogueList.records?.[0]?.sequence)
if (
newValue[newValue.length - 1].sequence ===
dialogueList.records?.[0]?.sequence
) {
//
state.value.localPageLoadDone = true
} else {
state.value.localPageLoadDone = false
}
}
},
{
deep: true,
},
)
const onScrollToLower = () => {
if (state.value.localPageLoadDone) {
//
onRefreshLoad()
}
}
const clearMultiSelect = () => {
dialogueStore.setMultiSelect(false)
virtualList.value.forEach((item) => {
@ -843,7 +884,7 @@ const toChatSettingsPage = () => {
'/pages/chatSettings/index?groupId=' +
talkParams?.receiver_id +
'&sessionId=' +
state.sessionId,
state.value.sessionId,
})
}

View File

@ -5,7 +5,7 @@ import { userInfoApi } from "@/api/user";
import {ref} from 'vue'
export const useAuth = createGlobalState(() => {
// const token = useStorage('token', '', uniStorage)
const token = ref('79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b894eccfe29065fd743ac415f1e8045568a93a27196c8971e441cd5cc24990dfbe85e4d8d1f1f02326e8d07c12fd699cf071f3111eda30eb7dd4259bde655204f7892b1d4a346487a77ece614a65c635649')
const token = ref('79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b894b54078d04d4ee86e494023bfc12a4fe79d044f22bef01b0b5f132e8ca151dcd3a1a4150e348641300c622b8af98cfd5d41fb24a8409b2b49446a766ea3886f587db124e0eb7d849ed33e6618fdf2c7f')
const refreshToken = useStorage('refreshToken', '', uniStorage)
const userInfo = useStorage('userInfo', {}, uniStorage)
const leaderList = useStorage('leaderList', [], uniStorage)

View File

@ -99,9 +99,8 @@ export const useDialogueListStore = createGlobalState(() => {
zpagingRef.value = params
}
const zpagingComplete = (index_name) => {
const item = getDialogueList(index_name)
zpagingRef.value?.complete(lodash.cloneDeep(item.records).reverse())
const zpagingComplete = (index_name, newRecords) => {
zpagingRef.value?.complete(lodash.cloneDeep(newRecords).reverse())
}
const addChatRecord = (indexName, item) => {