Compare commits

...

11 Commits

Author SHA1 Message Date
eb1523516c Merge branch 'main' into wyfMain-dev-useBase 2025-04-22 17:10:41 +08:00
02999dc782 解决解散等场景下会出现已读/未读/总人数为-1的情况
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
2025-04-22 15:20:24 +08:00
dd0ccb9818 新增收起应用时同时停止已读未读定时器,并在恢复后打开;解决群聊踢人后自己也看不到右上角的管理按钮问题
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
2025-04-22 14:49:08 +08:00
71d97f069f 处理媒体文件因为预加载导致的观察者监听错误问题;解决未读消息列表中会有自己的问题;解决多个媒体文件已读未读状态错误的问题
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
2025-04-21 16:21:54 +08:00
7be32e930c Merge branch 'LiWenHao'
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
2025-04-21 11:15:12 +08:00
885707f328 群聊按钮新增防抖 全选按钮可以点击 2025-04-21 11:13:19 +08:00
f76198b674 解决资源文件无法监听已读的问题
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
2025-04-21 11:06:48 +08:00
66828a254c 处理已读未读样式优化;处理@功能新问题
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
2025-04-21 09:52:59 +08:00
3898c637b4 完成第一版已读未读功能 2025-04-18 17:17:13 +08:00
29dcfac775 增加对两个视角已读未读消息的处理,并调整触发时机;增加map维护已读数量 2025-04-17 17:05:42 +08:00
676ad46ab5 新增已读未读功能对两种视角的处理,等待接口和socket联调 2025-04-16 17:19:31 +08:00
6 changed files with 762 additions and 64 deletions

View File

@ -212,3 +212,21 @@ export const detailGetRecordsContext = (data) => {
data,
})
}
// 获取自己消息已读回执列表
export const ServeReadConditionList = (data) => {
return request({
url: '/api/v1/talk/my-records/read/condition',
method: 'POST',
data,
})
}
// 获取消息已读未读详情
export const ServeMessageReadDetail = (data) => {
return request({
url: '/api/v1/talk/my-records/read/condition',
method: 'POST',
data,
})
}

View File

@ -244,7 +244,15 @@ class Talk extends Base {
//群成员被移出时,需要更新群成员权限
if ([1104, 1115].includes(record.msg_type)) {
useDialogueStore().updateQuit()
console.error(this.resource.extra.members, 'this.resource.extra.members')
if (this.resource?.extra?.members?.length > 0) {
const isMeQuit = this.resource.extra.members.find(
(item) => item.user_id === this.getAccountId(),
)
if (isMeQuit) {
useDialogueStore().updateQuit()
}
}
}
//群禁言变化时,需要更新群禁言状态——即更新群成员列表
@ -286,12 +294,12 @@ class Talk extends Base {
if (!this.isCurrSender()) {
// 推送已读消息
setTimeout(() => {
ws.emit('im.message.read', {
receiver_id: this.sender_id,
msg_ids: [this.resource.msg_id],
})
}, 1000)
// setTimeout(() => {
// ws.emit('im.message.read', {
// receiver_id: this.sender_id,
// msg_ids: [this.resource.msg_id],
// })
// }, 1000)
}
// 获取聊天面板元素节点

View File

@ -56,7 +56,7 @@
@click="() => allCheck(allCheckStatus)"
>
<div class="mr-[20rpx]">
<checkBox :modelValue="allCheckStatus"></checkBox>
<checkBox @change="(val) => allCheck(allCheckStatus)" :modelValue="allCheckStatus"></checkBox>
</div>
<div class="font-medium text-[28rpx] leading-[40rpx]">
{{ $t('radio.btn.selectAll') }}

View File

@ -106,7 +106,7 @@
</div>
<template #bottom>
<customBtn :isBottom="true" :btnText="$t('pageTitle.create.group')" @click="handleConfirm"
:disabled="confirmBtnStatus"></customBtn>
:isLoading="isLoading" :disabled="confirmBtnStatus || isLoading"></customBtn>
</template>
</zPaging>
</div>
@ -219,58 +219,63 @@
url: '/pages/chooseByDeps/index?chooseMode=2',
})
}
const isLoading = ref(false)
//
//
const handleConfirm = async () => {
console.log(allChooseMembers.value)
let erp_ids = ''
if (allChooseMembers?.value?.length > 0) {
allChooseMembers?.value?.forEach((ele) => {
if (!erp_ids) {
erp_ids = String(ele.ID)
} else {
erp_ids += ',' + ele.ID
if (isLoading.value) return
isLoading.value = true
try {
let erp_ids = ''
if (allChooseMembers?.value?.length > 0) {
allChooseMembers.value.forEach((ele) => {
if (!erp_ids) {
erp_ids = String(ele.ID)
} else {
erp_ids += ',' + ele.ID
}
})
}
let res = null
if (groupActiveIndex.value === 0) {
//
const params = {
avatar: '',
name: groupName.value,
erp_ids: erp_ids,
type: 1,
profile: '',
}
})
console.log('普通群参数:', params)
res = await ServeCreateGroup(params)
} else if (groupActiveIndex.value === 1) {
//
res = await createDepGroup()
} else if (groupActiveIndex.value === 2) {
//
const params = {
avatar: '',
name: groupName.value,
erp_ids: erp_ids,
type: 3,
profile: '',
}
console.log('项目群参数:', params)
res = await ServeCreateGroup(params)
}
if (res?.code === 200) {
resetGroupInfo()
uni.navigateBack()
}
} catch (err) {
console.error(err)
} finally {
isLoading.value = false
}
if (groupActiveIndex.value === 0) {
//
let params = {
avatar: '',
name: groupName.value,
erp_ids: erp_ids,
type: 1,
profile: '',
}
console.log(params)
const res = await ServeCreateGroup(params)
if (res.code === 200) {
resetGroupInfo()
uni.navigateBack()
}
} else if (groupActiveIndex.value === 1) {
//
const res = await createDepGroup()
if (res.code === 200) {
resetGroupInfo()
uni.navigateBack()
}
} else if (groupActiveIndex.value === 2) {
//
let params = {
avatar: '',
name: groupName.value,
erp_ids: erp_ids,
type: 3,
profile: '',
}
console.log(params)
const res = await ServeCreateGroup(params)
if (res.code === 200) {
resetGroupInfo()
uni.navigateBack()
}
} else {}
}
//
const confirmBtnStatus = computed(() => {

View File

@ -67,7 +67,21 @@
v-for="item in virtualList"
:id="`zp-id-${item.msg_id}`"
:key="item.zp_index"
:data-msgid="item.msg_id"
:data-msgtype="item.msg_type"
:data-userid="item.user_id"
:data-talktype="talkParams.type"
:data-receiverid="talkParams.receiver_id"
style="transform: scaleY(-1);"
:ref="
(el) => {
if (el) {
if (item.zp_index !== undefined) {
messageRecordElementRefs[item.zp_index] = el
}
}
}
"
>
<!-- 系统消息 -->
<div v-if="item.msg_type >= 1000" class="message-box">
@ -205,6 +219,17 @@
</div> -->
</div>
<div
class="talk-tools have_read_num"
v-if="item.user_id === talkParams.uid"
@click="toShowMessageReadDetail(item)"
>
<span v-if="talkParams.type === 1">未读</span>
<span v-if="talkParams.type === 2">
已读 (0/{{ (Number(talkParams.num)-1) > 0 ? Number(talkParams.num)-1 : 0 }})
</span>
</div>
<div
v-if="item.extra.reply"
class="talk-reply pointer"
@ -540,6 +565,102 @@
@getMentionSelectLists="getMentionSelectLists"
></selectMemberByAlphabet>
</tm-drawer>
<tm-drawer
placement="bottom"
v-model:show="state.isShowMessageReadDetail"
:hideHeader="true"
:round="5"
:height="state.mentionSelectHeight"
:inContent="true"
>
<div
class="mention-select-drawer flex flex-row flex-1 flex-row flex-row-center-between"
>
<div
class="cancel-btns flex-row flex flex-row-center-start"
style="width: 210rpx;"
@click="hideMessageReadDetail"
>
<span
style="flex-shrink: 0; display: block;"
class="text-[32rpx] font-regular text-[#191919]"
>
{{ $t('cancel') }}
</span>
</div>
<div
class="flex flex-row-center-center flex-col"
style="padding: 6rpx 0;"
>
<text>{{ $t('chat.msgRead.list') }}</text>
</div>
<div
class="flex-row flex flex-row-center-end"
style="width: 210rpx;"
></div>
</div>
<div class="msg-read-detail-tabs">
<tm-sheet>
<tm-tabs
:list="state.msgReadDetailTabs"
showTabsLineAni
activeFontColor="#7A58DE"
tabsLineAniColor="#7A58DE"
:item-width="375"
:width="750"
@change="msgReadDetailTabsChange"
:default-name="state.msgReadDetailTabs[0].key"
></tm-tabs>
<div class="msg-read-detail">
<ZPaging
ref="zPagingReadDetails"
:show-scrollbar="false"
:fixed="false"
:height="state.readDetailHeight"
:safe-area-inset-bottom="true"
:inside-more="true"
:hide-no-more-inside="true"
@scrolltolower="loadMoreReadDetails"
>
<div
class="msg-read-detail-each"
v-for="(item, index) in state.msgReadOrNotDetail"
:key="index"
>
<div class="msg-read-detail-each-avatar">
<avatarModule
:mode="2"
:groupType="item?.group_type"
:avatar="item?.avatar"
:userName="item?.nickName"
:customStyle="{ width: '72rpx', height: '72rpx' }"
:customTextStyle="{
fontSize: '24rpx',
fontWeight: 'bold',
color: '#fff',
lineHeight: '34rpx',
}"
></avatarModule>
</div>
<div class="msg-read-detail-each-info">
<span>{{ item.nickName }}</span>
<span
style="
font-size: 20rpx;
color: #747474;
font-weight: 400;
line-height: 28rpx;
"
>
{{ item.jobNum }}
</span>
</div>
</div>
</ZPaging>
</div>
</tm-sheet>
</div>
</tm-drawer>
</div>
</template>
<script setup>
@ -591,6 +712,8 @@ import {
detailGetRecordsContext,
ServeClearTalkUnreadNum,
ServeTalkRecords,
ServeReadConditionList,
ServeMessageReadDetail,
} from '@/api/chat'
import copy07 from '@/static/image/chatList/copy07@2x.png'
import multipleChoices from '@/static/image/chatList/multipleChoices@2x.png'
@ -604,12 +727,24 @@ import zu6053 from '@/static/image/chatList/zu6053@2x.png'
import deepBubble from '@/components/deep-bubble/deep-bubble.vue'
import { isRevoke } from './menu'
import useConfirm from '@/components/x-confirm/useConfirm.js'
import { onLoad as uniOnload, onUnload as uniOnUnload } from '@dcloudio/uni-app'
import {
onLoad as uniOnload,
onUnload as uniOnUnload,
onShow,
onHide,
} from '@dcloudio/uni-app'
import ws from '@/connect'
Quill.register('formats/emoji', EmojiBlot)
import 'quill-mention'
const selectMemberByAlphabetRef = ref(null)
//
let observer
//
const messageRecordElementRefs = ref([])
const messageRecordElementRefsWithoutIndex = ref([])
const {
getDialogueList,
updateZpagingRef,
@ -676,8 +811,65 @@ const state = ref({
canUseQuillEditor: true, //使quill使
textAreaValue: '', //
isUseSpeech: true, //使
visibleElements: new Set(), //
lastUpdateTime: 0, //
setMessageReadInterval: null, //
tempWaitDoRead: [], //
visibleOutElements: new Set(), //
setOutMessageReadInterval: null, //
tempWaitDoCheck: [], //
isShowMessageReadDetail: false, //
msgReadDetailTabs: [
{
key: '1',
title: '未读',
},
{
key: '0',
title: '已读',
},
],
msgReadOrNotDetail: [], //
currentMsgReadOrNotDetail: null, //
readNumPage: 1, //
hasMoreReadDetail: true, //
currentIsUnread: 1, //
readDetailHeight: 400, //
isFirstEnter: true, //
isFromHide: false, //hide
})
// Map
const recordReadsMap = ref(new Map())
// Map UI
watch(
recordReadsMap,
(newMap) => {
requestAnimationFrame(() => {
newMap.forEach((readNum, msgId) => {
const element = document.getElementById(`zp-id-${msgId}`)
if (element) {
element.dataset.readNum = readNum
const readNumElement = element.querySelector('.have_read_num')
if (readNumElement) {
if (talkParams.type === 1) {
readNumElement.textContent = readNum > 0 ? '已读' : '未读'
} else {
readNumElement.textContent =
'已读 (' + readNum + '/' + (Number(talkParams.num) - 1 > 0 ? Number(talkParams.num) - 1 : 0) + ')'
}
}
}
})
})
},
{
deep: true,
immediate: true,
},
)
uniOnload(async (options) => {
console.log('onLoad' + JSON.stringify(options))
if (options.sessionId) {
@ -999,7 +1191,9 @@ const onEmoticonEvent = (data) => {
quill.insertText(index, data.value)
}
quill.setSelection(index + 1, 0, 'user')
if (index) {
quill.setSelection(index + 1, 0, 'user')
}
} else {
let fn = emitCall('emoticon_event', data.value, () => {})
emit('editor-event', fn)
@ -1013,15 +1207,19 @@ const onEditorChange = () => {
}
// @
const qtext = getQuill().getText()
let selectIdx = getQuill().getSelection().index
let selectIdx = getQuill()?.getSelection()?.index
const textBeforeCursor = qtext.substring(0, selectIdx)
if (textBeforeCursor[0]?.charCodeAt(0) === 10) {
const delta = getQuill().getContents()
const ops = delta.ops || []
if (ops[0].insert === '\n') {
ops.splice(0, 1)
getQuill().setContents(delta)
getQuill().setSelection(getQuill().getText().length, 0)
if (ops.length > 0) {
nextTick(() => {
getQuill().setContents(delta)
getQuill().setSelection(getQuill().getText().length, 0)
})
}
}
// for (let i = 0; i < ops.length; i++) {
// if (ops[i].insert === '\n') {
@ -1381,6 +1579,57 @@ watch(
state.value.localPageLoadDone = false
}
}
//
if (oldValue && oldValue.length > 0) {
const lastOldMsgId = oldValue[0].msg_id
const lastIndex = newValue.findIndex(
(msg) => msg.msg_id === lastOldMsgId,
)
console.error(lastIndex, 'lastIndex')
if (lastIndex === -1) {
// lastOldMsgId
newValue.forEach((msg) => {
nextTick(() => {
const element = document.getElementById(`zp-id-${msg.msg_id}`)
if (element) {
messageRecordElementRefs.value.unshift(element)
}
})
})
} else if (lastIndex > 0) {
// lastOldMsgId
for (let i = 0; i < lastIndex; i++) {
const msg = newValue[i]
console.error(msg, '新消息msg')
nextTick(() => {
const element = document.getElementById(`zp-id-${msg.msg_id}`)
if (element) {
messageRecordElementRefs.value.unshift(element)
}
})
}
} else if (lastIndex === 0) {
messageRecordElementRefsWithoutIndex.value = []
// id
for (let i = 0; i < newValue.length; i++) {
if (!newValue[i].zp_index && newValue[i].zp_index !== 0) {
if (newValue[i]?.file_num === newValue[i].msg_id) {
return
}
nextTick(() => {
const element = document.getElementById(
`zp-id-${newValue[i].msg_id}`,
)
if (element) {
messageRecordElementRefsWithoutIndex.value.unshift(element)
}
})
}
}
}
}
}
},
{
@ -1850,8 +2099,8 @@ const handleAvatarTouchEnd = () => {
onMounted(async () => {
if (uni.getSystemInfoSync().osName === 'ios') {
let versions = uni.getSystemInfoSync().osVersion.split('.')
if (Number(versions[0]) < 17) {
console.error('ios版本低于17')
if (Number(versions[0]) < 16) {
console.error('ios版本低于16')
state.value.canUseQuillEditor = false
}
}
@ -1875,9 +2124,260 @@ onMounted(async () => {
state.value.selectAreaHeight =
rpxToPx(state.value.mentionSelectHeight) - rpxToPx(90) + 'px'
state.value.readDetailHeight =
rpxToPx(state.value.mentionSelectHeight) - rpxToPx(300) + 'px'
})
//
if (state.value.setMessageReadInterval) {
clearInterval(state.value.setMessageReadInterval)
state.value.setMessageReadInterval = null
}
state.value.setMessageReadInterval = setInterval(() => {
checkVisibleElements()
}, 2000)
if (state.value.setOutMessageReadInterval) {
clearInterval(state.value.setOutMessageReadInterval)
state.value.setOutMessageReadInterval = null
}
state.value.setOutMessageReadInterval = setInterval(() => {
checkVisibleOutElements()
}, 2000)
//
const options = {
root: null, // 使
threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], //
rootMargin: '50px 0px', //
}
observer = new IntersectionObserver(handleIntersection, options)
nextTick(() => {
watch(
messageRecordElementRefs,
(newMessageRecordElementRefs) => {
if (Array.isArray(newMessageRecordElementRefs)) {
newMessageRecordElementRefs.forEach((el, index) => {
observeElement(el, index)
})
}
},
{
immediate: true,
deep: true,
},
)
watch(
messageRecordElementRefsWithoutIndex,
(newMessageRecordElementRefs) => {
if (Array.isArray(newMessageRecordElementRefs)) {
newMessageRecordElementRefs.forEach((el, index) => {
observeElement(el, index)
})
}
},
{
immediate: true,
deep: true,
},
)
if (messageRecordElementRefs.value.length > 0) {
messageRecordElementRefs.value.forEach((el, index) =>
observeElement(el, index),
)
}
})
})
//
const checkVisibleElements = () => {
if (state.value.visibleElements.size > 0) {
// console.error(':', state.value.visibleElements)
let waitDoRead = []
state.value.visibleElements.forEach((el) => {
// console.log(el)
const msgId = el.dataset.msgid
const talkType = Number(el.dataset.talktype)
const receiverId = Number(el.dataset.receiverid)
// console.log(msgId, talkType, receiverId)
if (waitDoRead.length === 0) {
waitDoRead.push({
msg_ids: [msgId],
talk_type: talkType,
receiver_id: receiverId,
})
} else {
const existingItem = waitDoRead.find(
(item) =>
item.talk_type === talkType && item.receiver_id === receiverId,
)
if (existingItem) {
existingItem.msg_ids.push(msgId)
} else {
waitDoRead.push({
msg_ids: [msgId],
talk_type: talkType,
receiver_id: receiverId,
})
}
}
})
// console.error(waitDoRead)
if (waitDoRead.length > 0) {
waitDoRead.forEach((doReadItem) => {
//
const prevItem = state.value.tempWaitDoRead.find(
(prev) =>
prev.talk_type === doReadItem.talk_type &&
prev.receiver_id === doReadItem.receiver_id,
)
// msg_ids
if (
!prevItem ||
!doReadItem.msg_ids.every((id) => prevItem.msg_ids.includes(id))
) {
console.error('====发送了已读回执=====', doReadItem)
//
ws.emit('im.message.read', doReadItem)
}
})
}
//
state.value.tempWaitDoRead = JSON.parse(JSON.stringify(waitDoRead))
}
}
//
const checkVisibleOutElements = () => {
if (state.value.visibleOutElements.size > 0) {
// console.error(':', state.value.visibleOutElements)
let waitDoCheck = []
state.value.visibleOutElements.forEach((el) => {
// console.log(el)
const msgId = el.dataset.msgid
const talkType = Number(el.dataset.talktype)
const receiverId = Number(el.dataset.receiverid)
if (waitDoCheck.length === 0) {
waitDoCheck.push({
msg_ids: [msgId],
talk_type: talkType,
receiver_id: receiverId,
})
} else {
const existingItem = waitDoCheck.find(
(item) =>
item.talk_type === talkType && item.receiver_id === receiverId,
)
if (existingItem) {
existingItem.msg_ids.push(msgId)
} else {
waitDoCheck.push({
msg_ids: [msgId],
talk_type: talkType,
receiver_id: receiverId,
})
}
}
})
// console.error(waitDoCheck)
if (waitDoCheck.length > 0) {
waitDoCheck.forEach((doCheckItem) => {
//
// const prevItem = state.value.tempWaitDoCheck.find(
// (prev) =>
// prev.talk_type === doCheckItem.talk_type &&
// prev.receiver_id === doCheckItem.receiver_id,
// )
// // msg_ids
// if (
// !prevItem ||
// !doCheckItem.msg_ids.every((id) => prevItem.msg_ids.includes(id))
// ) {
console.error('====调用了已读回执查询接口=====', doCheckItem)
let params = Object.assign({}, doCheckItem, {
talkType: doCheckItem.talk_type, //12
receiverId:
doCheckItem.talk_type === 1
? talkParams.uid
: talkParams.receiver_id, //idid
msgIds: doCheckItem.msg_ids,
type: 'list', //listdetail
})
const resp = ServeReadConditionList(params)
// console.log(resp)
resp
.then(({ code, data }) => {
// console.log(data)
if (code == 200) {
//
if (Array.isArray(data.data)) {
console.error('处理批量更新', data.data)
data.data.forEach((item) => {
if (item.msgId && item.readNum !== undefined) {
recordReadsMap.value.set(item.msgId, item.readNum)
}
})
} else if (data.data && data.data.readNum !== undefined) {
console.error('处理单个更新', data.data)
doCheckItem.msg_ids.forEach((msgId) => {
recordReadsMap.value.set(msgId, data.data.readNum)
})
}
}
})
.catch(() => {})
// }
})
}
//
state.value.tempWaitDoCheck = JSON.parse(JSON.stringify(waitDoCheck))
}
}
//
const observeElement = (el, index) => {
if (el && observer) {
// 使 requestAnimationFrame DOM
requestAnimationFrame(() => {
observer.unobserve(el) //
observer.observe(el) //
})
}
}
//
const handleIntersection = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
//
//
let elData = entry.target.dataset
const msgType = elData.msgtype
const userId = elData.userid
if (Number(msgType) < 1000 && Number(userId) !== Number(talkParams.uid)) {
//
state.value.visibleElements.add(entry.target)
}
if (Number(msgType) < 1000 && Number(userId) === Number(talkParams.uid)) {
//
state.value.visibleOutElements.add(entry.target)
}
} else {
//
state.value.visibleElements.delete(entry.target)
state.value.visibleOutElements.delete(entry.target)
}
})
if (state.value.isFirstEnter) {
state.value.isFirstEnter = false
//
// checkVisibleElements()
// checkVisibleOutElements()
}
}
const pxTorPx = (px) => {
const sysInfo = uni.getSystemInfoSync()
const rpx = px / (sysInfo.screenWidth / 750)
@ -1905,6 +2405,53 @@ onUnmounted(() => {
if (uploadsStore.isUploading) {
uploadsStore.clearUpload()
}
if (observer) {
observer.disconnect()
}
if (state.value.setMessageReadInterval) {
clearInterval(state.value.setMessageReadInterval)
state.value.setMessageReadInterval = null
checkVisibleElements()
}
if (state.value.setOutMessageReadInterval) {
clearInterval(state.value.setOutMessageReadInterval)
state.value.setOutMessageReadInterval = null
checkVisibleOutElements()
}
})
onShow(() => {
if (state.value.isFromHide) {
if (state.value.setMessageReadInterval) {
clearInterval(state.value.setMessageReadInterval)
state.value.setMessageReadInterval = null
}
state.value.setMessageReadInterval = setInterval(() => {
checkVisibleElements()
}, 2000)
if (state.value.setOutMessageReadInterval) {
clearInterval(state.value.setOutMessageReadInterval)
state.value.setOutMessageReadInterval = null
}
state.value.setOutMessageReadInterval = setInterval(() => {
checkVisibleOutElements()
}, 2000)
state.value.isFromHide = false
}
})
onHide(() => {
state.value.isFromHide = true
if (state.value.setMessageReadInterval) {
clearInterval(state.value.setMessageReadInterval)
state.value.setMessageReadInterval = null
checkVisibleElements()
}
if (state.value.setOutMessageReadInterval) {
clearInterval(state.value.setOutMessageReadInterval)
state.value.setOutMessageReadInterval = null
checkVisibleOutElements()
}
})
//
@ -1968,6 +2515,82 @@ const onTextAreaMention = (user) => {
state.value.isShowMentionSelect = false
}
}
//
const hideMessageReadDetail = () => {
state.value.isShowMessageReadDetail = false
}
//
const toShowMessageReadDetail = (item) => {
console.log(item)
if (talkParams.type === 1) {
return
}
state.value.isShowMessageReadDetail = true
state.value.currentMsgReadOrNotDetail = item
getMessageReadDetail(1)
}
///
const msgReadDetailTabsChange = (e) => {
// console.log(e)
if (Number(e) !== Number(state.value.currentIsUnread)) {
state.value.readNumPage = 1
}
state.value.currentIsUnread = Number(e)
getMessageReadDetail(e)
}
//
const getMessageReadDetail = (isUnread) => {
let params = {
page: state.value.readNumPage,
pageSize: 10,
type: 'detail', //listdetail
talkType: state.value.currentMsgReadOrNotDetail.talk_type, //12
receiverId: state.value.currentMsgReadOrNotDetail.receiver_id, //idid
msgId: state.value.currentMsgReadOrNotDetail.msg_id,
isUnread: Number(isUnread), //01
}
const resp = ServeMessageReadDetail(params)
// console.log(resp)
resp
.then(({ code, data }) => {
console.log(data)
if (code == 200) {
if (Number(isUnread) === 0) {
state.value.msgReadDetailTabs[0].title =
'未读 ' + (Number(talkParams.num) - 1 - data.count > 0 ? Number(talkParams.num) - 1 - data.count : 0) + ''
state.value.msgReadDetailTabs[1].title = '已读 ' + data.count + ''
} else if (Number(isUnread) === 1) {
state.value.msgReadDetailTabs[0].title = '未读 ' + data.count + ''
state.value.msgReadDetailTabs[1].title =
'已读 ' + (Number(talkParams.num) - 1 - data.count > 0 ? Number(talkParams.num) - 1 - data.count : 0) + ''
}
if (state.value.readNumPage === 1) {
state.value.msgReadOrNotDetail = data.data
} else {
state.value.msgReadOrNotDetail = [
...state.value.msgReadOrNotDetail,
...data.data,
]
}
if (!data?.data || data?.data?.length < 10) {
state.value.hasMoreReadDetail = false
} else {
state.value.hasMoreReadDetail = true
}
}
})
.catch(() => {})
}
//
const loadMoreReadDetails = () => {
if (!state.value.hasMoreReadDetail) {
return
}
state.value.readNumPage += 1
getMessageReadDetail(state.value.currentIsUnread)
}
</script>
<style scoped lang="less">
.dialog-page {
@ -2157,6 +2780,15 @@ const onTextAreaMention = (user) => {
}
}
.have_read_num {
text-align: right;
color: #7a58de;
font-size: 22rpx;
font-weight: 400;
line-height: 34rpx;
margin: 5rpx 0 0;
}
.talk-reply {
display: flex;
align-items: flex-start;
@ -2364,4 +2996,38 @@ const onTextAreaMention = (user) => {
:deep(.mention) {
color: #1890ff;
}
.msg-read-detail-tabs {
padding: 32rpx 0 0;
:deep(.noNvueBorder) {
padding: 0 !important;
margin: 0 !important;
}
.msg-read-detail {
padding: 28rpx 32rpx;
.msg-read-detail-each {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 20rpx 32rpx;
border-bottom: 1rpx solid #f8f8f8;
.msg-read-detail-each-avatar {
margin: 0 20rpx 0 0;
}
.msg-read-detail-each-info {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
span {
font-size: 28rpx;
color: #191919;
font-weight: 500;
line-height: 40rpx;
}
}
}
}
}
</style>

View File

@ -156,6 +156,7 @@
"popup.title.phone": "电话",
"pageTitle.view.deps": "查看部门",
"group.dismiss.confirm": "确定解散本群",
"chat.msgRead.list": "消息接收人列表",
"chat.settings.report": "投诉",
"complaint": {
"title": "投诉举报",