完成第一版已读未读功能
This commit is contained in:
parent
29dcfac775
commit
3898c637b4
@ -221,3 +221,12 @@ export const ServeReadConditionList = (data) => {
|
|||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取消息已读未读详情
|
||||||
|
export const ServeMessageReadDetail = (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/api/v1/talk/my-records/read/condition',
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
@ -215,6 +215,17 @@
|
|||||||
</div> -->
|
</div> -->
|
||||||
</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/{{ talkParams.num }})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="item.extra.reply"
|
v-if="item.extra.reply"
|
||||||
class="talk-reply pointer"
|
class="talk-reply pointer"
|
||||||
@ -530,6 +541,101 @@
|
|||||||
@getMentionSelectLists="getMentionSelectLists"
|
@getMentionSelectLists="getMentionSelectLists"
|
||||||
></selectMemberByAlphabet>
|
></selectMemberByAlphabet>
|
||||||
</tm-drawer>
|
</tm-drawer>
|
||||||
|
<tm-drawer
|
||||||
|
placement="bottom"
|
||||||
|
v-model:show="state.isShowMessageReadDetail"
|
||||||
|
:hideHeader="true"
|
||||||
|
:round="5"
|
||||||
|
:height="state.mentionSelectHeight"
|
||||||
|
>
|
||||||
|
<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="zPaging"
|
||||||
|
: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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
@ -579,6 +685,7 @@ import {
|
|||||||
ServeClearTalkUnreadNum,
|
ServeClearTalkUnreadNum,
|
||||||
ServeTalkRecords,
|
ServeTalkRecords,
|
||||||
ServeReadConditionList,
|
ServeReadConditionList,
|
||||||
|
ServeMessageReadDetail,
|
||||||
} from '@/api/chat'
|
} from '@/api/chat'
|
||||||
import copy07 from '@/static/image/chatList/copy07@2x.png'
|
import copy07 from '@/static/image/chatList/copy07@2x.png'
|
||||||
import multipleChoices from '@/static/image/chatList/multipleChoices@2x.png'
|
import multipleChoices from '@/static/image/chatList/multipleChoices@2x.png'
|
||||||
@ -676,6 +783,24 @@ const state = ref({
|
|||||||
visibleOutElements: new Set(), //当前需要获取别人发送的已读回执列表的可见元素
|
visibleOutElements: new Set(), //当前需要获取别人发送的已读回执列表的可见元素
|
||||||
setOutMessageReadInterval: null, // 设置我发出的消息,别人已读的定时器
|
setOutMessageReadInterval: null, // 设置我发出的消息,别人已读的定时器
|
||||||
tempWaitDoCheck: [], //当前获取别人发送已读回执的元素
|
tempWaitDoCheck: [], //当前获取别人发送已读回执的元素
|
||||||
|
isShowMessageReadDetail: false, //是否显示消息已读未读详情
|
||||||
|
msgReadDetailTabs: [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
title: '未读',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '0',
|
||||||
|
title: '已读',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
msgReadOrNotDetail: [], //消息已读未读详情
|
||||||
|
currentMsgReadOrNotDetail: null, //当前消息已读未读详情
|
||||||
|
readNumPage: 1, //已读未读详情分页
|
||||||
|
hasMoreReadDetail: true, //是否还有更多已读未读详情
|
||||||
|
currentIsUnread: 1, //当前已读未读状态
|
||||||
|
readDetailHeight: 400, //已读未读详情高度
|
||||||
|
isFirstEnter: true, //是否是第一次进入
|
||||||
})
|
})
|
||||||
|
|
||||||
// 创建一个响应式的 Map 来维护已读数量
|
// 创建一个响应式的 Map 来维护已读数量
|
||||||
@ -685,28 +810,27 @@ const recordReadsMap = ref(new Map())
|
|||||||
watch(
|
watch(
|
||||||
recordReadsMap,
|
recordReadsMap,
|
||||||
(newMap) => {
|
(newMap) => {
|
||||||
console.error(newMap, 'newMap')
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
console.error('requestAnimationFrame')
|
|
||||||
newMap.forEach((readNum, msgId) => {
|
newMap.forEach((readNum, msgId) => {
|
||||||
console.error(readNum, 'readNum')
|
|
||||||
console.error(msgId, 'msgId')
|
|
||||||
const element = document.getElementById(`zp-id-${msgId}`)
|
const element = document.getElementById(`zp-id-${msgId}`)
|
||||||
if (element) {
|
if (element) {
|
||||||
console.error(element, 'element')
|
|
||||||
element.dataset.readNum = readNum
|
element.dataset.readNum = readNum
|
||||||
// const readNumElement = element.querySelector('.read-num')
|
const readNumElement = element.querySelector('.have_read_num')
|
||||||
// if (readNumElement) {
|
if (readNumElement) {
|
||||||
// console.error(readNumElement, 'readNumElement')
|
if (talkParams.type === 1) {
|
||||||
// readNumElement.textContent = readNum
|
readNumElement.textContent = readNum > 0 ? '已读' : '未读'
|
||||||
// }
|
} else {
|
||||||
|
readNumElement.textContent =
|
||||||
|
'已读 (' + readNum + '/' + talkParams.num + ')'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
deep: true
|
deep: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
uniOnload(async (options) => {
|
uniOnload(async (options) => {
|
||||||
@ -1447,7 +1571,6 @@ watch(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
const onScrollToLower = async () => {
|
const onScrollToLower = async () => {
|
||||||
if (state.value.useCustomLoadMore) {
|
if (state.value.useCustomLoadMore) {
|
||||||
const tempVirtualList = lodash.cloneDeep(virtualList.value).reverse()
|
const tempVirtualList = lodash.cloneDeep(virtualList.value).reverse()
|
||||||
@ -1935,6 +2058,9 @@ onMounted(async () => {
|
|||||||
|
|
||||||
state.value.selectAreaHeight =
|
state.value.selectAreaHeight =
|
||||||
rpxToPx(state.value.mentionSelectHeight) - rpxToPx(90) + 'px'
|
rpxToPx(state.value.mentionSelectHeight) - rpxToPx(90) + 'px'
|
||||||
|
|
||||||
|
state.value.readDetailHeight =
|
||||||
|
rpxToPx(state.value.mentionSelectHeight) - rpxToPx(300) + 'px'
|
||||||
})
|
})
|
||||||
|
|
||||||
//设置观察者前设置定时器
|
//设置观察者前设置定时器
|
||||||
@ -2088,36 +2214,40 @@ const checkVisibleOutElements = () => {
|
|||||||
// !prevItem ||
|
// !prevItem ||
|
||||||
// !doCheckItem.msg_ids.every((id) => prevItem.msg_ids.includes(id))
|
// !doCheckItem.msg_ids.every((id) => prevItem.msg_ids.includes(id))
|
||||||
// ) {
|
// ) {
|
||||||
console.error('====调用了已读回执查询接口=====', doCheckItem)
|
console.error('====调用了已读回执查询接口=====', doCheckItem)
|
||||||
let params = Object.assign({}, doCheckItem, {
|
let params = Object.assign({}, doCheckItem, {
|
||||||
talkType: doCheckItem.talk_type, //1私聊2群聊
|
talkType: doCheckItem.talk_type, //1私聊2群聊
|
||||||
receiverId: doCheckItem.talk_type === 1 ? talkParams.uid : talkParams.receiver_id, //私聊的时候是对方用户id,群聊的时候是对方群id
|
receiverId:
|
||||||
msgIds: doCheckItem.msg_ids,
|
doCheckItem.talk_type === 1
|
||||||
type: 'list', //list是列表,detail是详情
|
? talkParams.uid
|
||||||
})
|
: talkParams.receiver_id, //私聊的时候是对方用户id,群聊的时候是对方群id
|
||||||
|
msgIds: doCheckItem.msg_ids,
|
||||||
|
type: 'list', //list是列表,detail是详情
|
||||||
|
})
|
||||||
|
|
||||||
const resp = ServeReadConditionList(params)
|
const resp = ServeReadConditionList(params)
|
||||||
// console.log(resp)
|
// console.log(resp)
|
||||||
resp.then(({ code, data }) => {
|
resp
|
||||||
|
.then(({ code, data }) => {
|
||||||
// console.log(data)
|
// console.log(data)
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
// 处理批量更新
|
// 处理批量更新
|
||||||
if (Array.isArray(data.data)) {
|
if (Array.isArray(data.data)) {
|
||||||
console.error('处理批量更新', data.data)
|
console.error('处理批量更新', data.data)
|
||||||
data.data.forEach(item => {
|
data.data.forEach((item) => {
|
||||||
if (item.msgId && item.readNum !== undefined) {
|
if (item.msgId && item.readNum !== undefined) {
|
||||||
console.error('修改recordReadsMap', item)
|
|
||||||
recordReadsMap.value.set(item.msgId, item.readNum)
|
recordReadsMap.value.set(item.msgId, item.readNum)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else if (data.data && data.data.readNum !== undefined) {
|
} else if (data.data && data.data.readNum !== undefined) {
|
||||||
console.error('处理单个更新', data.data)
|
console.error('处理单个更新', data.data)
|
||||||
doCheckItem.msg_ids.forEach(msgId => {
|
doCheckItem.msg_ids.forEach((msgId) => {
|
||||||
recordReadsMap.value.set(msgId, data.data.readNum)
|
recordReadsMap.value.set(msgId, data.data.readNum)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).catch(() => {})
|
})
|
||||||
|
.catch(() => {})
|
||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -2160,6 +2290,12 @@ const handleIntersection = (entries) => {
|
|||||||
state.value.visibleOutElements.delete(entry.target)
|
state.value.visibleOutElements.delete(entry.target)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if (state.value.isFirstEnter) {
|
||||||
|
state.value.isFirstEnter = false
|
||||||
|
// 立即执行一次
|
||||||
|
// checkVisibleElements()
|
||||||
|
// checkVisibleOutElements()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pxTorPx = (px) => {
|
const pxTorPx = (px) => {
|
||||||
@ -2265,6 +2401,82 @@ const onTextAreaMention = (user) => {
|
|||||||
state.value.isShowMentionSelect = false
|
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', //list是列表,detail是详情
|
||||||
|
talkType: state.value.currentMsgReadOrNotDetail.talk_type, //1私聊2群聊
|
||||||
|
receiverId: state.value.currentMsgReadOrNotDetail.receiver_id, //私聊的时候是对方用户id,群聊的时候是对方群id
|
||||||
|
msgId: state.value.currentMsgReadOrNotDetail.msg_id,
|
||||||
|
isUnread: Number(isUnread), //不送或者送0代表看已读,送1看未读
|
||||||
|
}
|
||||||
|
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 =
|
||||||
|
'未读 (' + (talkParams.num - data.count) + ')'
|
||||||
|
state.value.msgReadDetailTabs[1].title = '已读 (' + data.count + ')'
|
||||||
|
} else if (Number(isUnread) === 1) {
|
||||||
|
state.value.msgReadDetailTabs[0].title = '未读 (' + data.count + ')'
|
||||||
|
state.value.msgReadDetailTabs[1].title =
|
||||||
|
'已读 (' + (talkParams.num - data.count) + ')'
|
||||||
|
}
|
||||||
|
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>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.dialog-page {
|
.dialog-page {
|
||||||
@ -2454,6 +2666,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 {
|
.talk-reply {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@ -2661,25 +2882,37 @@ const onTextAreaMention = (user) => {
|
|||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加已读数量显示样式
|
.msg-read-detail-tabs {
|
||||||
[data-msgid] {
|
padding: 32rpx 0 0;
|
||||||
position: relative;
|
:deep(.noNvueBorder) {
|
||||||
|
padding: 0 !important;
|
||||||
&::after {
|
margin: 0 !important;
|
||||||
content: attr(data-read-num);
|
|
||||||
position: absolute;
|
|
||||||
right: 10px;
|
|
||||||
bottom: 5px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #999;
|
|
||||||
background: rgba(0, 0, 0, 0.1);
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 10px;
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
.msg-read-detail {
|
||||||
&[data-read-num]:not([data-read-num=""])::after {
|
padding: 28rpx 32rpx;
|
||||||
display: block;
|
.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>
|
</style>
|
||||||
|
@ -156,6 +156,7 @@
|
|||||||
"popup.title.phone": "电话",
|
"popup.title.phone": "电话",
|
||||||
"pageTitle.view.deps": "查看部门",
|
"pageTitle.view.deps": "查看部门",
|
||||||
"group.dismiss.confirm": "确定解散本群",
|
"group.dismiss.confirm": "确定解散本群",
|
||||||
|
"chat.msgRead.list": "消息接收人列表",
|
||||||
"chat.settings.report": "投诉",
|
"chat.settings.report": "投诉",
|
||||||
"complaint": {
|
"complaint": {
|
||||||
"title": "投诉举报",
|
"title": "投诉举报",
|
||||||
|
Loading…
Reference in New Issue
Block a user