m-text.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <template>
  2. <view class="flex_c row">
  3. <view class="flex_r text-box" :class="{ text_box: isMy }" @tap.stop="onClick">
  4. <view
  5. class="text_32 text"
  6. :class="isMy ? 'text_r' : 'text_l'"
  7. :hover-class="isMy ? 'hover_classr' : 'hover_classl'"
  8. :hover-stay-time="60"
  9. :style="{ whiteSpace: 'pre-wrap' }"
  10. v-html="renderTextMessage"
  11. ></view>
  12. </view>
  13. <view class="text_26 flex_r" :class="{ row_: isMy }" v-if="value.type === 'text_quote'">
  14. <view v-if="value.payload.quoteSource.type === 'image' || value.payload.quoteSource.type === 'image_transmit'">
  15. <m-image :value="value.payload.quoteSource"></m-image>
  16. </view>
  17. <view class="" v-else-if="value.payload.quoteSource.type === 'audio' || value.payload.quoteSource.type === 'audio_quote'">
  18. <m-audio :value="value.payload.quoteSource"></m-audio>
  19. </view>
  20. <view class="" v-else-if="value.payload.quoteSource.type === 'text' || value.payload.quoteSource.type === 'text_quote'">
  21. <m-text :value="value.payload.quoteSource"></m-text>
  22. </view>
  23. <view class="" v-else>
  24. <m-other :value="value.payload.quoteSource"></m-other>
  25. </view>
  26. </view>
  27. </view>
  28. </template>
  29. <script>
  30. import mText from './quoteType/m-text.vue';
  31. import mImage from './quoteType/m-image.vue';
  32. import mAudio from './quoteType/m-audio.vue';
  33. import mOther from './quoteType/m-other.vue';
  34. import { EmojiDecoder, emojiMap } from '@/utils/EmojiDecoder.js';
  35. const emojiUrl = 'https://imgcache.qq.com/open/qcloud/tim/assets/emoji/';
  36. const decoder = new EmojiDecoder(emojiUrl, emojiMap);
  37. export default {
  38. components: {
  39. mText,
  40. mImage,
  41. mAudio,
  42. mOther
  43. },
  44. props: {
  45. isMy: {
  46. type: [Boolean, Number],
  47. default: false
  48. },
  49. value: {
  50. type: Object,
  51. default: {}
  52. }
  53. },
  54. data() {
  55. return {};
  56. },
  57. computed: {
  58. //渲染文本消息,如果包含表情,替换为图片
  59. //todo:本不需要该方法,可以在标签里完成,但小程序有兼容性问题,被迫这样实现
  60. renderTextMessage() {
  61. const { text = '' } = this.value.payload;
  62. if (!text) return '<span>' + '[未知内容]' + '</span>';
  63. return '<span>' + decoder.decode(text) + '</span>';
  64. }
  65. },
  66. methods: {
  67. onClick() {
  68. this.$emit('onClick');
  69. }
  70. }
  71. };
  72. </script>
  73. <style scoped lang="scss">
  74. .row {
  75. }
  76. .row_ {
  77. flex-direction: row-reverse;
  78. }
  79. .text_box {
  80. flex-direction: row-reverse;
  81. }
  82. .text {
  83. position: relative;
  84. z-index: 99;
  85. box-sizing: border-box;
  86. padding: 16rpx 26rpx;
  87. border-radius: 8rpx;
  88. background-color: #fff;
  89. word-break: break-all;
  90. vertical-align: center;
  91. }
  92. .text_r {
  93. position: relative;
  94. background-color: #95ec6a;
  95. }
  96. .text_l {
  97. position: relative;
  98. }
  99. .text_r::after {
  100. position: absolute;
  101. z-index: -1;
  102. content: '';
  103. top: 26rpx;
  104. right: -8rpx;
  105. width: 18rpx;
  106. height: 18rpx;
  107. border-radius: 2px;
  108. transform: rotate(45deg);
  109. background-color: #95ec6a;
  110. }
  111. .text_l::after {
  112. position: absolute;
  113. z-index: -1;
  114. content: '';
  115. top: 26rpx;
  116. left: -8rpx;
  117. width: 18rpx;
  118. height: 18rpx;
  119. border-radius: 2px;
  120. transform: rotate(45deg);
  121. background-color: #fff;
  122. }
  123. .hover_classr {
  124. background-color: #89d961;
  125. }
  126. .hover_classl {
  127. background-color: #e2e2e2;
  128. }
  129. .hover_classr::after {
  130. position: absolute;
  131. z-index: -1;
  132. content: '';
  133. top: 26rpx;
  134. right: -8rpx;
  135. width: 18rpx;
  136. height: 18rpx;
  137. border-radius: 2px;
  138. transform: rotate(45deg);
  139. background-color: #89d961;
  140. }
  141. .hover_classl::after {
  142. position: absolute;
  143. z-index: -1;
  144. content: '';
  145. top: 26rpx;
  146. left: -8rpx;
  147. width: 18rpx;
  148. height: 18rpx;
  149. border-radius: 2px;
  150. transform: rotate(45deg);
  151. background-color: #e2e2e2;
  152. }
  153. </style>