123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- <template>
- <div
- v-show="isShowReadStatus"
- :class="{
- 'message-label': true,
- 'unread': isUseUnreadStyle,
- 'finger-point': isHoverFingerPointer,
- }"
- @click="openReadUserPanel"
- >
- <span>{{ readStatusText }}</span>
- </div>
- </template>
- <script setup lang="ts">
- import { computed, ref, onMounted, onUnmounted } from '../../../../../adapter-vue';
- import TUIChatEngine, {
- TUIStore,
- StoreName,
- IMessageModel,
- TUITranslateService,
- } from '@tencentcloud/chat-uikit-engine';
- 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;
- }
- 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;
- }
- }
- // 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;
- }
- } 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');
- }
- }
- 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;
- &.unread {
- color: #679ce1 !important;
- }
- }
- .finger-point {
- cursor: pointer;
- -webkit-tap-highlight-color: transparent;
- }
- </style>
|