index.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <div
  3. v-if="Boolean(quoteMessage) && props.displayType !== 'audio'"
  4. :class="{
  5. 'input-quote-content': true,
  6. 'input-quote-container-uni': isUniFrameWork,
  7. 'input-quote-container-h5': isH5,
  8. }"
  9. >
  10. <div class="input-quote-content">
  11. <div class="max-one-line">
  12. {{ quoteMessage.nick || quoteMessage.from }}: {{ quoteContentText }}
  13. </div>
  14. <Icon
  15. class="input-quote-close-icon"
  16. :file="closeIcon"
  17. width="11px"
  18. height="11px"
  19. @onClick="cancelQuote"
  20. />
  21. </div>
  22. </div>
  23. </template>
  24. <script setup lang="ts">
  25. import { ref, computed, onMounted, onUnmounted } from '../../../../adapter-vue';
  26. import TUIChatEngine, {
  27. TUIStore,
  28. StoreName,
  29. TUITranslateService,
  30. IMessageModel,
  31. } from '@tencentcloud/chat-uikit-engine';
  32. import Icon from '../../../common/Icon.vue';
  33. import closeIcon from '../../../../assets/icon/icon-close.svg';
  34. import { isH5, isUniFrameWork } from '../../../../utils/env';
  35. import { decodeTextMessage } from '../../utils/emojiList';
  36. import { InputDisplayType } from '../../../../interface';
  37. interface IProps {
  38. displayType: InputDisplayType;
  39. }
  40. const props = withDefaults(defineProps<IProps>(), {
  41. displayType: 'editor',
  42. });
  43. const TYPES = TUIChatEngine.TYPES;
  44. const quoteMessage = ref<IMessageModel>();
  45. onMounted(() => {
  46. TUIStore.watch(StoreName.CHAT, {
  47. quoteMessage: onQuoteMessageUpdated,
  48. });
  49. TUIStore.watch(StoreName.CONV, {
  50. currentConversationID: onConversationIDUpdated,
  51. });
  52. });
  53. onUnmounted(() => {
  54. TUIStore.unwatch(StoreName.CHAT, {
  55. quoteMessage: onQuoteMessageUpdated,
  56. });
  57. TUIStore.unwatch(StoreName.CONV, {
  58. currentConversationID: onConversationIDUpdated,
  59. });
  60. });
  61. const quoteContentText = computed(() => {
  62. let _quoteContentText;
  63. switch (quoteMessage.value?.type) {
  64. case TYPES.MSG_TEXT:
  65. _quoteContentText = decodeTextMessage(quoteMessage.value.payload?.text);
  66. break;
  67. case TYPES.MSG_IMAGE:
  68. _quoteContentText = TUITranslateService.t('TUIChat.图片');
  69. break;
  70. case TYPES.MSG_AUDIO:
  71. _quoteContentText = TUITranslateService.t('TUIChat.语音');
  72. break;
  73. case TYPES.MSG_VIDEO:
  74. _quoteContentText = TUITranslateService.t('TUIChat.视频');
  75. break;
  76. case TYPES.MSG_FILE:
  77. _quoteContentText = TUITranslateService.t('TUIChat.文件');
  78. break;
  79. case TYPES.MSG_CUSTOM:
  80. _quoteContentText = TUITranslateService.t('TUIChat.自定义');
  81. break;
  82. case TYPES.MSG_FACE:
  83. _quoteContentText = TUITranslateService.t('TUIChat.表情');
  84. break;
  85. default:
  86. _quoteContentText = TUITranslateService.t('TUIChat.消息');
  87. break;
  88. }
  89. return _quoteContentText;
  90. });
  91. function cancelQuote() {
  92. TUIStore.update(StoreName.CHAT, 'quoteMessage', { message: undefined, type: 'quote' });
  93. }
  94. function onQuoteMessageUpdated(options?: { message: IMessageModel; type: string }) {
  95. if (options?.message && options?.type === 'quote') {
  96. quoteMessage.value = options.message;
  97. } else {
  98. quoteMessage.value = undefined;
  99. }
  100. }
  101. function onConversationIDUpdated() {
  102. cancelQuote();
  103. }
  104. </script>
  105. <style lang="scss" scoped>
  106. %common-container-style {
  107. margin: 5px 100px 5px 8px;
  108. display: flex;
  109. flex: 0 1 auto;
  110. .input-quote-content {
  111. display: flex;
  112. flex: 0 1 auto;
  113. background-color: #fafafa;
  114. border-radius: 8px;
  115. padding: 12px;
  116. font-size: 12px;
  117. align-items: center;
  118. line-height: 16px;
  119. max-width: 100%;
  120. box-sizing: border-box;
  121. min-width: 0;
  122. .max-one-line {
  123. flex: 0 1 auto;
  124. overflow: hidden;
  125. text-overflow: ellipsis;
  126. white-space: nowrap;
  127. }
  128. }
  129. .input-quote-close-icon {
  130. margin-left: 5px;
  131. padding: 5px;
  132. }
  133. }
  134. .input-quote-container {
  135. @extend %common-container-style;
  136. }
  137. .input-quote-container-uni {
  138. @extend %common-container-style;
  139. margin: 5px 60px 0 30px;
  140. }
  141. .input-quote-container-h5 {
  142. @extend %common-container-style;
  143. margin: 5px 0 0;
  144. }
  145. </style>