gui-im-message.vue 6.5 KB

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