修复已知问题

This commit is contained in:
cbb
2026-02-02 15:45:24 +08:00
parent f4e3496e3c
commit fa0faa6be6
10 changed files with 220 additions and 194 deletions

View File

@@ -3,8 +3,8 @@
v-show="isShowReadStatus"
:class="{
'message-label': true,
'unread': isUseUnreadStyle,
'finger-point': isHoverFingerPointer,
unread: isUseUnreadStyle,
'finger-point': isHoverFingerPointer
}"
@click="openReadUserPanel"
>
@@ -13,188 +13,209 @@
</template>
<script setup lang="ts">
import { computed, ref, onMounted, onUnmounted } from '../../../../../adapter-vue';
import TUIChatEngine, {
TUIStore,
StoreName,
IMessageModel,
TUITranslateService,
} from '@tencentcloud/chat-uikit-engine-lite';
import TUIChatConfig from '../../../config';
import {
computed,
ref,
onMounted,
onUnmounted
} from '../../../../../adapter-vue'
import TUIChatEngine, {
TUIStore,
StoreName,
IMessageModel,
TUITranslateService
} from '@tencentcloud/chat-uikit-engine-lite'
import TUIChatConfig from '../../../config'
interface IProps {
message: IMessageModel;
}
interface IEmits {
(e: 'openReadUserPanel'): void;
}
const emits = defineEmits<IEmits>();
const props = withDefaults(defineProps<IProps>(), {
message: () => ({}) as IMessageModel,
});
const ReadStatus = TUIChatConfig.getFeatureConfig('ReadStatus');
enum ReadState {
Read,
Unread,
AllRead,
NotShow,
PartiallyRead,
}
const TYPES = TUIChatEngine.TYPES;
// User-level read receipt toggle has the highest priority.
const isDisplayMessageReadReceipt = ref<boolean>(TUIStore.getData(StoreName.USER, 'displayMessageReadReceipt'));
onMounted(() => {
TUIStore.watch(StoreName.USER, {
displayMessageReadReceipt: onDisplayMessageReadReceiptUpdate,
});
});
onUnmounted(() => {
TUIStore.unwatch(StoreName.USER, {
displayMessageReadReceipt: onDisplayMessageReadReceiptUpdate,
});
});
const isShowReadStatus = computed<boolean>(() => {
if (!ReadStatus) {
return false;
}
if (!isDisplayMessageReadReceipt.value) {
return false;
}
const {
ID,
type,
flow,
status,
hasRiskContent,
conversationID,
conversationType,
needReadReceipt = false,
} = props.message;
// Asynchronous message strike: Determine if there is risky content after the message has been sent
if (hasRiskContent) {
return false;
interface IProps {
message: IMessageModel
}
const { groupProfile } = TUIStore.getConversationModel(conversationID) || {};
// AVCHATROOM and COMMUNITY chats do not display read status
if (groupProfile?.type === TYPES.GRP_AVCHATROOM || groupProfile?.type === TYPES.GRP_COMMUNITY) {
return false;
interface IEmits {
(e: 'openReadUserPanel'): void
}
if (type === TYPES.MSG_CUSTOM) {
const message = TUIStore.getMessageModel(ID);
// If it is a signaling message, do not display the read status
if (message?.getSignalingInfo() !== null) {
return false;
const emits = defineEmits<IEmits>()
const props = withDefaults(defineProps<IProps>(), {
message: () => ({}) as IMessageModel
})
const ReadStatus = TUIChatConfig.getFeatureConfig('ReadStatus')
enum ReadState {
Read,
Unread,
AllRead,
NotShow,
PartiallyRead
}
const TYPES = TUIChatEngine.TYPES
// User-level read receipt toggle has the highest priority.
const isDisplayMessageReadReceipt = ref<boolean>(
TUIStore.getData(StoreName.USER, 'displayMessageReadReceipt')
)
onMounted(() => {
TUIStore.watch(StoreName.USER, {
displayMessageReadReceipt: onDisplayMessageReadReceiptUpdate
})
})
onUnmounted(() => {
TUIStore.unwatch(StoreName.USER, {
displayMessageReadReceipt: onDisplayMessageReadReceiptUpdate
})
})
const isShowReadStatus = computed<boolean>(() => {
if (!ReadStatus) {
return false
}
}
// Unsuccessful message: Received messages do not display read status
if (flow !== 'out' || status !== 'success') {
return false;
}
if (conversationType === 'GROUP') {
return needReadReceipt;
} else if (conversationType === 'C2C') {
return true;
}
return false;
});
const readState = computed<ReadState>(() => {
const { conversationType, needReadReceipt = false, isPeerRead = false } = props.message;
const { readCount = 0, unreadCount = 0, isPeerRead: isReceiptPeerRead = false } = props.message.readReceiptInfo;
if (conversationType === 'C2C') {
if (needReadReceipt) {
return isReceiptPeerRead ? ReadState.Read : ReadState.Unread;
} else {
return isPeerRead ? ReadState.Read : ReadState.Unread;
if (!isDisplayMessageReadReceipt.value) {
return false
}
} else if (conversationType === 'GROUP') {
if (needReadReceipt) {
if (readCount === 0) {
return ReadState.Unread;
} else if (unreadCount === 0) {
return ReadState.AllRead;
} else {
return ReadState.PartiallyRead;
const {
ID,
type,
flow,
status,
hasRiskContent,
conversationID,
conversationType,
needReadReceipt = false
} = props.message
// Asynchronous message strike: Determine if there is risky content after the message has been sent
if (hasRiskContent) {
return false
}
const { groupProfile } =
TUIStore.getConversationModel(conversationID) || {}
// AVCHATROOM and COMMUNITY chats do not display read status
if (
groupProfile?.type === TYPES.GRP_AVCHATROOM ||
groupProfile?.type === TYPES.GRP_COMMUNITY
) {
return false
}
if (type === TYPES.MSG_CUSTOM) {
const message = TUIStore.getMessageModel(ID)
// If it is a signaling message, do not display the read status
if (message?.getSignalingInfo() !== null) {
return false
}
} else {
return ReadState.NotShow;
}
// Unsuccessful message: Received messages do not display read status
if (flow !== 'out' || status !== 'success') {
return false
}
if (conversationType === 'GROUP') {
// return needReadReceipt;
return false
} else if (conversationType === 'C2C') {
return true
}
return false
})
const readState = computed<ReadState>(() => {
const {
conversationType,
needReadReceipt = false,
isPeerRead = false
} = props.message
const {
readCount = 0,
unreadCount = 0,
isPeerRead: isReceiptPeerRead = false
} = props.message.readReceiptInfo
if (conversationType === 'C2C') {
if (needReadReceipt) {
return isReceiptPeerRead ? ReadState.Read : ReadState.Unread
} else {
return isPeerRead ? ReadState.Read : ReadState.Unread
}
} else if (conversationType === 'GROUP') {
if (needReadReceipt) {
if (readCount === 0) {
return ReadState.Unread
} else if (unreadCount === 0) {
return ReadState.AllRead
} else {
return ReadState.PartiallyRead
}
} else {
return ReadState.NotShow
}
}
return ReadState.Unread
})
const readStatusText = computed(() => {
const { readCount = 0 } = props.message.readReceiptInfo
switch (readState.value) {
case ReadState.Read:
return TUITranslateService.t('TUIChat.已读')
case ReadState.Unread:
return TUITranslateService.t('TUIChat.未读')
case ReadState.AllRead:
return TUITranslateService.t('TUIChat.全部已读')
case ReadState.PartiallyRead:
return `${readCount}${TUITranslateService.t('TUIChat.人已读')}`
default:
return ''
}
})
const isUseUnreadStyle = computed(() => {
const { conversationType } = props.message
if (conversationType === 'C2C') {
return readState.value !== ReadState.Read
} else if (conversationType === 'GROUP') {
return readState.value !== ReadState.AllRead
}
return false
})
const isHoverFingerPointer = computed<boolean>(() => {
return (
props.message.needReadReceipt &&
props.message.conversationType === 'GROUP' &&
(readState.value === ReadState.PartiallyRead ||
readState.value === ReadState.Unread)
)
})
function openReadUserPanel() {
if (isHoverFingerPointer.value) {
// emits('openReadUserPanel');
}
}
return ReadState.Unread;
});
const readStatusText = computed(() => {
const { readCount = 0 } = props.message.readReceiptInfo;
switch (readState.value) {
case ReadState.Read:
return TUITranslateService.t('TUIChat.已读');
case ReadState.Unread:
return TUITranslateService.t('TUIChat.未读');
case ReadState.AllRead:
return TUITranslateService.t('TUIChat.全部已读');
case ReadState.PartiallyRead:
return `${readCount}${TUITranslateService.t('TUIChat.人已读')}`;
default:
return '';
function onDisplayMessageReadReceiptUpdate(isDisplay: boolean) {
isDisplayMessageReadReceipt.value = isDisplay
}
});
const isUseUnreadStyle = computed(() => {
const { conversationType } = props.message;
if (conversationType === 'C2C') {
return readState.value !== ReadState.Read;
} else if (conversationType === 'GROUP') {
return readState.value !== ReadState.AllRead;
}
return false;
});
const isHoverFingerPointer = computed<boolean>(() => {
return (
props.message.needReadReceipt
&& props.message.conversationType === 'GROUP'
&& (readState.value === ReadState.PartiallyRead || readState.value === ReadState.Unread)
);
});
function openReadUserPanel() {
if (isHoverFingerPointer.value) {
// emits('openReadUserPanel');
}
}
function onDisplayMessageReadReceiptUpdate(isDisplay: boolean) {
isDisplayMessageReadReceipt.value = isDisplay;
}
</script>
<style scoped lang="scss">
.message-label {
align-self: flex-end;
font-size: 12px;
color: #b6b8ba;
word-break: keep-all;
flex: 0 0 auto;
.message-label {
align-self: flex-end;
font-size: 12px;
color: #b6b8ba;
word-break: keep-all;
flex: 0 0 auto;
&.unread {
color: #679ce1 !important;
&.unread {
color: #679ce1 !important;
}
}
}
.finger-point {
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
.finger-point {
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
</style>