index.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <template>
  2. <div
  3. v-if="quoteContent"
  4. :class="{
  5. 'reference-content': true,
  6. 'reverse': message.flow === 'out',
  7. }"
  8. @click="scrollToOriginalMessage"
  9. >
  10. <div class="max-double-line">
  11. {{ quoteContent.messageSender }}: {{ decodeTextMessage(quoteContent.messageAbstract) }}
  12. </div>
  13. </div>
  14. </template>
  15. <script lang="ts" setup>
  16. import { computed } from '../../../../../adapter-vue';
  17. import {
  18. TUIStore,
  19. StoreName,
  20. IMessageModel,
  21. TUITranslateService,
  22. } from '@tencentcloud/chat-uikit-engine';
  23. import { getBoundingClientRect, getScrollInfo } from '@tencentcloud/universal-api';
  24. import { isUniFrameWork } from '../../../../../utils/env';
  25. import { Toast, TOAST_TYPE } from '../../../../../components/common/Toast/index';
  26. import type { ICloudCustomData, IQuoteContent } from './interface.ts';
  27. import { decodeTextMessage } from '../../../utils/emojiList';
  28. export interface IProps {
  29. message: IMessageModel;
  30. }
  31. export interface IEmits {
  32. (e: 'scrollTo', scrollHeight: number): void;
  33. (e: 'blinkMessage', messageID: string | undefined): void;
  34. }
  35. const emits = defineEmits<IEmits>();
  36. const props = withDefaults(defineProps<IProps>(), {
  37. message: () => ({} as IMessageModel),
  38. });
  39. let selfAddValue = 0;
  40. let messageList: IMessageModel[] = [];
  41. TUIStore.watch(StoreName.CHAT, {
  42. messageList(list: IMessageModel[]) {
  43. messageList = list;
  44. },
  45. });
  46. const quoteContent = computed<IQuoteContent | undefined>(() => {
  47. try {
  48. const cloudCustomData: ICloudCustomData = JSON.parse(props.message?.cloudCustomData || '{}');
  49. return cloudCustomData.messageReply;
  50. } catch (error) {
  51. return undefined;
  52. }
  53. });
  54. async function scrollToOriginalMessage() {
  55. const originMessageID = quoteContent.value?.messageID;
  56. const isOriginalMessageInScreen = messageList.some(msg => msg.ID === originMessageID);
  57. if (originMessageID && isOriginalMessageInScreen) {
  58. try {
  59. const scrollViewRect = await getBoundingClientRect('#messageScrollList', 'messageList');
  60. const originalMessageRect = await getBoundingClientRect('#tui-' + originMessageID, 'messageList');
  61. const { scrollTop } = await getScrollInfo('#messageScrollList', 'messageList');
  62. const finalScrollTop = originalMessageRect.top + scrollTop - scrollViewRect.top - (selfAddValue++ % 2);
  63. const isNeedScroll = originalMessageRect.top < scrollViewRect.top;
  64. if (!isUniFrameWork && window) {
  65. const scrollView = document.getElementById('messageScrollList');
  66. if (isNeedScroll && scrollView) {
  67. scrollView.scrollTop = finalScrollTop;
  68. }
  69. } else if (isUniFrameWork && isNeedScroll) {
  70. emits('scrollTo', finalScrollTop);
  71. }
  72. emits('blinkMessage', originMessageID);
  73. } catch (error) {
  74. console.error(error);
  75. }
  76. } else {
  77. Toast({
  78. message: TUITranslateService.t('TUIChat.无法定位到原消息'),
  79. type: TOAST_TYPE.WARNING,
  80. });
  81. }
  82. }
  83. </script>
  84. <style lang="scss" scoped>
  85. .reference-content {
  86. max-width: 272px;
  87. margin-top: 4px;
  88. margin-left: 44px;
  89. padding: 12px;
  90. font-size: 12px;
  91. color: #666;
  92. word-wrap: break-word;
  93. word-break: break-all;
  94. background-color: #fbfbfb;
  95. border-radius: 8px;
  96. line-height: 16.8px;
  97. cursor: pointer;
  98. -webkit-tap-highlight-color: transparent;
  99. }
  100. .reverse.reference-content {
  101. margin-right: 44px;
  102. margin-left: auto;
  103. }
  104. .max-double-line {
  105. word-break: break-all;
  106. overflow: hidden;
  107. display: -webkit-box;
  108. max-height: 33px;
  109. -webkit-line-clamp: 2;
  110. -webkit-box-orient: vertical;
  111. }
  112. </style>