MediaMessageRender.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <view class="media_message_container" @click="clickMediaItem">
  3. <!-- <view :style="{height:wrapperHeight}" class="media_message_container"> -->
  4. <u--image :showLoading="true" :width="imageLayout.width" :height="imageLayout.height" mode="scaleToFill" :src="getImgUrl" @click="clickMediaItem">
  5. <template v-slot:loading>
  6. <u-loading-icon color="#FF5030"></u-loading-icon>
  7. </template>
  8. </u--image>
  9. <image v-if="isVideo" class="play_icon" src="../../../../../static/images/chating_message_video_play.png" alt="" srcset="" />
  10. <text v-if="isVideo" class="video_duration">{{ getDuration }}</text>
  11. </view>
  12. </template>
  13. <script>
  14. import { mapGetters } from 'vuex';
  15. import { checkFileIsExist } from '../../../../../util/common';
  16. import { secFormat } from '../../../../../util/imCommon';
  17. import { myPreview } from '../../../../../util/preview';
  18. import { MessageType } from 'openim-uniapp-polyfill';
  19. export default {
  20. name: '',
  21. props: {
  22. message: Object
  23. },
  24. data() {
  25. return {};
  26. },
  27. computed: {
  28. ...mapGetters(['storeCacheMap']),
  29. isVideo() {
  30. return this.message.contentType === MessageType.VideoMessage;
  31. },
  32. getImgUrl() {
  33. if (this.isVideo) {
  34. return this.message.videoElem.snapshotUrl;
  35. }
  36. return this.message.pictureElem.snapshotPicture?.url ?? this.message.pictureElem.sourcePath;
  37. },
  38. getDuration() {
  39. if (!this.isVideo) {
  40. return 0;
  41. }
  42. return secFormat(this.message.videoElem.duration);
  43. },
  44. imageLayout() {
  45. let width = this.isVideo ? this.message.videoElem.snapshotWidth : this.message.pictureElem.sourcePicture.width;
  46. let height = this.isVideo ? this.message.videoElem.snapshotHeight : this.message.pictureElem.sourcePicture.height;
  47. if (!width || !height) return { width: 150, height: 150 };
  48. const MAX_W = 200;
  49. const MAX_H = 200;
  50. const MIN_SIZE = 100;
  51. let finalWidth = width;
  52. let finalHeight = height;
  53. const ratio = width / height;
  54. // Scale down if larger than max dimensions
  55. if (finalWidth > MAX_W) {
  56. finalWidth = MAX_W;
  57. finalHeight = finalWidth / ratio;
  58. }
  59. if (finalHeight > MAX_H) {
  60. finalHeight = MAX_H;
  61. finalWidth = finalHeight * ratio;
  62. }
  63. // Scale up if smaller than min dimensions
  64. if (finalWidth < MIN_SIZE && finalHeight < MIN_SIZE) {
  65. if (ratio > 1) {
  66. finalWidth = MIN_SIZE;
  67. finalHeight = finalWidth / ratio;
  68. } else {
  69. finalHeight = MIN_SIZE;
  70. finalWidth = finalHeight * ratio;
  71. }
  72. }
  73. return {
  74. width: finalWidth,
  75. height: finalHeight
  76. };
  77. }
  78. },
  79. methods: {
  80. async clickMediaItem() {
  81. if (this.isVideo) {
  82. const path = this.storeCacheMap[this.message.clientMsgID]?.path;
  83. const localPath = await checkFileIsExist({
  84. key: this.message.clientMsgID,
  85. path
  86. });
  87. const previewVideoUrl = localPath || this.message.videoElem.videoUrl;
  88. uni.navigateTo({
  89. url: `/pages_im/pages/conversation/previewVideo/index?clientMsgID=${this.message.clientMsgID}&previewVideoUrl=${previewVideoUrl}&snapshotUrl=${this.message.videoElem.snapshotUrl}`
  90. });
  91. } else {
  92. const list = this.$store.getters.storePreviewImageList;
  93. const idx = list.findIndex((item) => item === this.message.pictureElem.sourcePicture.url);
  94. myPreview(idx, list);
  95. }
  96. }
  97. }
  98. };
  99. </script>
  100. <style lang="scss" scoped>
  101. .media_message_container {
  102. position: relative;
  103. border-radius: 4rpx;
  104. overflow: hidden;
  105. .play_icon {
  106. width: 30px;
  107. height: 30px;
  108. position: absolute;
  109. top: 50%;
  110. left: 50%;
  111. transform: translate(-50%, -50%);
  112. }
  113. .video_duration {
  114. position: absolute;
  115. bottom: 12rpx;
  116. right: 24rpx;
  117. color: #fff;
  118. font-size: 16px;
  119. }
  120. }
  121. </style>