gui-im-message.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template name="gui-im-messages">
  2. <view class="gui-im"
  3. :style="{'background-color':background}">
  4. <block v-for="(item, index) in msgs" :key="index">
  5. <block v-if="item.group == group">
  6. <!-- 系统消息 -->
  7. <view class="gui-im-msg gui-flex gui-rows gui-justify-content-center"
  8. v-if="item.contentType == 'system'">
  9. <view class="gui-im-system-msg gui-bg-black">{{item.msg}}</view>
  10. </view>
  11. <!-- 用户消息 -->
  12. <view v-else>
  13. <view class="gui-im-msg"
  14. :class="[userid == item.uindex ? 'gui-im-msg-right' : 'gui-im-msg-left']">
  15. <view class="gui-im-face">
  16. <image class="gui-im-face-image" :src="item.uface" mode="widthFix"></image>
  17. </view>
  18. <view class="gui-im-content-spacing"></view>
  19. <view class="gui-im-content-in">
  20. <view class="gui-im-name" v-if="userid != item.uindex">
  21. <text :style="unameStyle">{{item.uname}}</text>
  22. </view>
  23. <!-- 文本消息 -->
  24. <view v-if="item.contentType == 'txt'"
  25. :class="[userid == item.uindex ? 'gui-im-flex-end' : '']">
  26. <view class="gui-im-content-txt"
  27. :class="[userid == item.uindex ? 'gui-bg-green' : '']">
  28. <text :style="txtContentStyle"
  29. :class="[userid == item.uindex ? 'gui-color-white' : '']">{{item.content}}</text>
  30. </view>
  31. </view>
  32. <!-- 图片消息 -->
  33. <view v-if="item.contentType == 'img'"
  34. :class="[userid == item.uindex ? 'gui-im-flex-end' : '']">
  35. <view class="gui-img-in gui-im-img"> <image class="gui-im-img" :src="item.content" :data-img="item.content" @tap="showImgs" mode="widthFix"></image> </view>
  36. </view>
  37. <!-- 语言消息 -->
  38. <view v-if="item.contentType == 'voice'"
  39. :class="[userid == item.uindex ? 'gui-im-flex-end' : '']">
  40. <view
  41. class="gui-flex gui-rows gui-nowrap gui-align-items-center"
  42. :class="[
  43. 'gui-im-voice-msg',
  44. index == playIndex ? 'gui-bg-green' : '',
  45. userid != item.uindex ? 'gui-im-flex-end' : ''
  46. ]"
  47. :data-voice="item.content"
  48. :data-index='index' @tap='playVoice'
  49. :style="{'width':(item.length*3)+'px'}">
  50. <text class="gui-icons"
  51. :class="[index == playIndex ? 'gui-color-white' : '']">&#xe800;</text>
  52. <text class="gui-im-voice-msg-text"
  53. :class="[index == playIndex ? 'gui-color-white' : '']">{{item.length}} ”</text>
  54. </view>
  55. </view>
  56. <view :class="[userid == item.uindex ? 'gui-text-right' : '']">
  57. <text class="gui-im-timer gui-block-text">{{item.date}}</text>
  58. </view>
  59. </view>
  60. </view>
  61. </view>
  62. </block>
  63. </block>
  64. <view style="height:100px;"></view>
  65. </view>
  66. </template>
  67. <script>
  68. export default {
  69. name : "gui-im-messages",
  70. props : {
  71. msgs : { type : Array, default : function(){ return []; }},
  72. userid : { type : String, default:''},
  73. group : { type : String, default : "" },
  74. background : { type : String, default : "#F7FBFE" },
  75. unameStyle : { type : String, default : 'line-height:28rpx; height:28rpx; font-size:26rpx; color:#666666;'},
  76. txtContentStyle : { type : String, default : 'line-height:38rpx; font-size:30rpx; color:#2B2E3D;'}
  77. },
  78. data() {
  79. return {
  80. player : null,
  81. playIndex : -1
  82. }
  83. },
  84. created: function(){
  85. this.player = uni.createInnerAudioContext();
  86. this.player.onPlay(() => {console.log('play');});
  87. this.player.onEnded(() => {
  88. var cIndex = Number(this.playIndex);
  89. this.playIndex = -1;
  90. for(let i = cIndex + 1; i < this.msgs.length; i++) {
  91. if (this.msgs[i].contentType == 'voice') {
  92. this.playNow(this.msgs[i].content, i);
  93. break;
  94. return;
  95. }
  96. }
  97. });
  98. this.player.onError((E)=>{console.log(E);});
  99. },
  100. methods: {
  101. // 播放语音
  102. playVoice: function (e) {
  103. var voicelUrl = e.currentTarget.dataset.voice;
  104. var index = e.currentTarget.dataset.index;
  105. if (this.playIndex == -1){
  106. return this.playNow(voicelUrl, index);
  107. }
  108. if (this.playIndex == index) {
  109. this.player.stop();
  110. this.playIndex = -1;
  111. } else {
  112. this.player.stop();
  113. this.playIndex = -1;
  114. this.playNow(voicelUrl, index);
  115. }
  116. },
  117. // 语音播放基础函数
  118. playNow: function (voicelUrl, index){
  119. this.playIndex = index;
  120. this.player.src = voicelUrl;
  121. this.player.play();
  122. return true;
  123. },
  124. // 图片预览
  125. showImgs : function(e){
  126. var imgs = [];
  127. var imgsCurrent = e.currentTarget.dataset.img;
  128. for (var i = 0; i < this.msgs.length; i++) {
  129. if (this.msgs[i].contentType == 'img') {
  130. imgs.push(this.msgs[i].content);
  131. }
  132. }
  133. uni.previewImage({urls : imgs, current : imgsCurrent});
  134. }
  135. }
  136. }
  137. </script>
  138. <style scoped>
  139. .gui-im{padding:30rpx;}
  140. .gui-im-system-msg{color:#FFFFFF; font-size:26rpx; line-height:38rpx; padding:5px 10px; display:block; border-radius:6rpx;}
  141. .gui-im-msg{margin-bottom:28px; display:flex; flex-direction:row; flex-wrap:nowrap;}
  142. .gui-im-face{width:88rpx; height:88rpx; overflow:hidden; flex-shrink:0; border-radius:6rpx; overflow:hidden; font-size:0;}
  143. .gui-im-face-image{width:88rpx;}
  144. .gui-im-name{padding-bottom:10rpx; margin-top:-5rpx; }
  145. .gui-im-content-spacing{width:25rpx; height:50rpx; flex-shrink:0;}
  146. .gui-im-content-in{width:600rpx; overflow:hidden;}
  147. .gui-im-content-txt{background-color:#E7F0F3; padding:15rpx 20rpx; border-radius:6rpx; min-width:100rpx; word-break:break-all;}
  148. .gui-im-msg-right{flex-direction:row-reverse;}
  149. .gui-im-timer{margin-top:5px; line-height:30rpx; font-size:22rpx; color:#8788A3;}
  150. .gui-im-img{width:358rpx; border-radius:6rpx;}
  151. .gui-im-flex-end{display:flex; flex-direction:row; flex-wrap:nowrap; justify-content:flex-end;}
  152. .gui-im-voice-msg{height:80rpx; padding:0 20rpx; background-color:#E7F0F3; border-radius:6rpx; color:#2B2E3D; min-width:100rpx; max-width:400rpx;}
  153. .gui-im-voice-msg-text{font-size:22rpx; margin:0 5rpx;}
  154. @font-face {
  155. font-family: "guiimfont";
  156. src:url('data:font/ttf;charset=utf-8;base64,d09GRgABAAAAAARIAAsAAAAABpAOfljMqxyszBwQAGoSFheJxjYGRgYADih0telMfz23xl4GZhAIEblhYmCPr/ZxYGZl4gl4OBCSQKAC7VCZ8AeJxjYGRgYG7438AQw8IAAkCSkQEVMAEARGInC9nJQTHaVXQA5E8EE500AB910O4UPCXntWPc3ndFsU1P9zhQEC9M9cU7qy0nk6T4E9XxtSdXQrbsuelDSRXs1JErJCXta2VELqATZlV44RelzRiT8oZ0j/AAlabsgAAAB4nGNgYoAALgbsgImRiZGZgTWxNCUzn4EBAAzjAi0AAA==');
  157. }
  158. .graceIMFont{font-family:"graceIMFont"; font-size:30rpx; color:#2B2E3D;}
  159. </style>