conversation.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <view class="main">
  3. <view class="cu-chat" v-for="(item,index) in messages" :key="index">
  4. <view class="cu-item self" v-if="item.receiverId!=currentUser.uuid">
  5. <view class="time-lag">
  6. {{renderMessageDate(message, index)}}
  7. </view>
  8. <view class="main" v-if="item.type=='text'">
  9. <view class="content bg-green shadow">
  10. <text>{{item.payload.text}}</text>
  11. </view>
  12. </view>
  13. <view class="main" v-else-if="item.type =='image'">
  14. <image :src="item.payload.url" @click="yulan(item.payload.url)" :style="'width:'+item.payload.width+'rpx;height'+item.payload.height+'rpx;'"
  15. class="radius" mode="widthFix"></image>
  16. </view>
  17. <view class="main" v-else="item.type =='audio'">
  18. <GoEasyAudioPlayer :src="item.payload.url" :duration="item.payload.duration" />
  19. </view>
  20. <view class="cu-avatar radius" :style="'background-image:url('+currentUser.avatar+');'"></view>
  21. </view>
  22. <view class="cu-item" v-else>
  23. <view class="cu-avatar radius" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big143004.jpg);"></view>
  24. <view class="main" v-if="item.type=='text'">
  25. <view class="content shadow">
  26. <text>{{item.payload.text}}</text>
  27. </view>
  28. </view>
  29. <view class="main" v-else-if="item.type =='image'">
  30. <image :src="item.payload.url" @click="yulan(item.payload.url)" :style="'width:'+item.payload.width+'rpx;height'+item.payload.height+'rpx;'"
  31. class="radius" mode="widthFix"></image>
  32. </view>
  33. <view class="main" v-else="item.type =='audio'">
  34. <GoEasyAudioPlayer :src="item.payload.url" :duration="item.payload.duration" />
  35. </view>
  36. </view>
  37. </view>
  38. <view :class="InputBottom!=0?'cu-bar foot tab input cur':'cu-bar foot input'" :style="'bottom:'+InputBottom+'px'">
  39. <view class="action" @click="sendvoice">
  40. <text class="cuIcon-sound text-grey"></text>
  41. </view>
  42. <input v-if="!isvoice" v-model="keyword" class="solid-bottom" @focus="InputFocus" @blur="InputBlur" :disabled="isinput"
  43. :adjust-position="false" :focus="false" maxlength="300" :placeholder="textinput" cursor-spacing="10"></input>
  44. <button class="flex-sub" style="font-size: 30rpx; height: 64rpx;padding: 0;" @touchstart.stop="onRecordStart"
  45. @touchend.stop="onRecordEnd" v-else>{{audio.recording ? '松开发送':'按住发送语音'}}</button>
  46. <view class="action" style="margin-right: 20rpx;" @click="sendImage">
  47. <text class="cuIcon-picfill text-grey"></text>
  48. </view>
  49. <button class="cu-btn bg-green shadow" @click="sendMessage">发送</button>
  50. </view>
  51. </view>
  52. </template>
  53. <script>
  54. import {
  55. sendMessages
  56. } from "../../../common/goeasyimutil.js"
  57. import GoEasyAudioPlayer from "../../../components/GoEasyAudioPlayer/GoEasyAudioPlayer";
  58. const recorderManager = uni.getRecorderManager()
  59. export default {
  60. components: {
  61. GoEasyAudioPlayer
  62. },
  63. onLoad(op) {
  64. this.imService = getApp().globalData.imService;
  65. this.doctorInfo = JSON.parse(op.doctor)
  66. //对话数据
  67. this.friend = {
  68. uuid: this.doctorInfo.id,
  69. name: this.doctorInfo.name,
  70. avatar: this.doctorInfo.avatar
  71. };
  72. this.currentUser = this.imService.currentUser;
  73. let privateMessages = this.imService.getPrivateMessages(this.friend.uuid);
  74. this.messages = privateMessages.sentMessages;
  75. this.pendingMessages = privateMessages.pendingMessages;
  76. uni.setNavigationBarTitle({
  77. title: this.friend.name
  78. });
  79. this.initialListeners();
  80. //每次进入聊天页面,总是滚动到底部
  81. this.scrollToBottom()
  82. //收到的消息设置为已读
  83. if (this.messages.length != 0) {
  84. this.imService.markPrivateMessageAsRead(this.friend.uuid);
  85. }
  86. },
  87. mounted() {
  88. },
  89. data() {
  90. return {
  91. keyword: "",
  92. InputBottom: 0,
  93. isvoice: false,
  94. textinput: "请输入",
  95. isinput: false,
  96. messages: [],
  97. self_messages: [],
  98. friend: null,
  99. currentUser: null,
  100. imService: null,
  101. audio: {
  102. //语音录音中
  103. recording: false,
  104. },
  105. doctorInfo: {}
  106. }
  107. },
  108. onPullDownRefresh: function(e) {
  109. this.loadMoreHistoryMessage();
  110. },
  111. onUnload() {
  112. //退出聊天页面之前,清空页面传入的监听器
  113. if (this.imService) {
  114. this.imService.onNewPrivateMessageReceive = (friendId, message) => {};
  115. }
  116. },
  117. methods: {
  118. renderMessageDate(message, index) {
  119. if (index === 0) {
  120. return this.formatDate(message.timestamp)
  121. } else {
  122. if (message.timestamp - this.messages[index - 1].timestamp > 5 * 60 * 1000) {
  123. return this.formatDate(message.timestamp)
  124. }
  125. }
  126. return ''
  127. },
  128. InputFocus(e) {
  129. this.InputBottom = e.detail.height
  130. },
  131. InputBlur(e) {
  132. this.InputBottom = 0
  133. },
  134. sendvoice() {
  135. this.isvoice = !this.isvoice
  136. },
  137. subscribeMessage() { //订阅消息
  138. },
  139. yulan(url) {
  140. uni.previewImage({
  141. urls: [url],
  142. current: url
  143. })
  144. },
  145. initialListeners() {
  146. //传入监听器,收到一条私聊消息总是滚到到页面底部
  147. this.imService.onNewPrivateMessageReceive = (friendId, message) => {
  148. if (friendId == this.friend.uuid) {
  149. this.imService.markPrivateMessageAsRead(friendId);
  150. //收到新消息,是滚动到最底部
  151. this.scrollToBottom()
  152. }
  153. };
  154. // 录音监听器
  155. this.initRecorderListeners();
  156. },
  157. initRecorderListeners() {
  158. let self = this;
  159. // 监听录音开始
  160. recorderManager.onStart(function() {
  161. self.audio.recording = true;
  162. });
  163. //录音结束后,发送
  164. recorderManager.onStop(function(res) {
  165. console.log(res)
  166. self.audio.recording = false;
  167. self.imService.sendPrivateAudioMessage(self.friend.uuid, res)
  168. });
  169. // 监听录音报错
  170. recorderManager.onError(function(res) {
  171. console.log("录音报错:", res);
  172. })
  173. },
  174. onRecordStart(event) {
  175. try {
  176. recorderManager.start();
  177. } catch (e) {
  178. uni.showModal({
  179. title: '发送语音错误',
  180. content: '请联系客服'
  181. });
  182. }
  183. event.preventDefault();
  184. },
  185. onRecordEnd() {
  186. try {
  187. recorderManager.stop();
  188. } catch (e) {
  189. uni.showModal({
  190. title: '发送语音错误',
  191. content: '请联系客服'
  192. });
  193. }
  194. },
  195. sendMessage() { //发送消息
  196. if (this.keyword.trim() != '') {
  197. console.log(this.friend.uuid)
  198. this.imService.sendPrivateTextMessage(this.friend.uuid, this.keyword);
  199. }
  200. this.keyword = "";
  201. },
  202. scrollToBottom() {
  203. this.$nextTick(function() {
  204. uni.pageScrollTo({
  205. scrollTop: 2000000,
  206. duration: 10
  207. })
  208. })
  209. },
  210. sendImage() {
  211. uni.chooseImage({
  212. count: 1,
  213. success: (res) => {
  214. this.imService.sendPrivateImageMessage(this.friend.uuid, res);
  215. }
  216. })
  217. },
  218. loadMoreHistoryMessage() { //历史消息
  219. let lastMessageTimeStamp = Date.now();
  220. let lastMessage = this.messages[0];
  221. if (lastMessage) {
  222. lastMessageTimeStamp = lastMessage.timestamp;
  223. }
  224. var currentLength = this.messages.length;
  225. let promise = this.imService.loadPrivateHistoryMessage(this.friend.uuid, lastMessageTimeStamp);
  226. promise.then(messages => {
  227. if (messages.length == currentLength) {
  228. this.allHistoryLoaded = true
  229. }
  230. this.messages = messages;
  231. uni.stopPullDownRefresh();
  232. }).catch(e => {
  233. console.log(e)
  234. uni.stopPullDownRefresh();
  235. })
  236. },
  237. }
  238. };
  239. </script>
  240. <style lang="scss">
  241. page {
  242. padding-bottom: 100rpx;
  243. }
  244. .time-lag {
  245. font-size: 20rpx;
  246. text-align: center;
  247. }
  248. </style>