| xqd
@@ -1,69 +1,93 @@
|
|
|
<template>
|
|
|
<view class="main">
|
|
|
- <view class="cu-chat">
|
|
|
- <view class="cu-item self">
|
|
|
- <view class="main">
|
|
|
- <view class="content bg-green shadow">
|
|
|
- <text>喵喵喵!喵喵喵!喵喵喵!喵喵!喵喵!!喵!喵喵喵!</text>
|
|
|
- </view>
|
|
|
+ <view class="cu-chat" v-for="(item,index) in messages" :key="index">
|
|
|
+ <view class="cu-item self" v-if="item.receiverId!=currentUser.uuid">
|
|
|
+ <view class="time-lag">
|
|
|
+ {{renderMessageDate(message, index)}}
|
|
|
</view>
|
|
|
- <view class="cu-avatar radius" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big107000.jpg);"></view>
|
|
|
- </view>
|
|
|
- <view class="cu-item">
|
|
|
- <view class="cu-avatar radius" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big143004.jpg);"></view>
|
|
|
- <view class="main">
|
|
|
- <view class="content shadow">
|
|
|
- <text>喵喵喵!喵喵喵!</text>
|
|
|
+ <view class="main" v-if="item.type=='text'">
|
|
|
+ <view class="content bg-green shadow">
|
|
|
+ <text>{{item.payload.text}}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
- <view class="cu-item self">
|
|
|
- <view class="main">
|
|
|
- <image src="https://ossweb-img.qq.com/images/lol/web201310/skin/big10006.jpg" class="radius" mode="widthFix"></image>
|
|
|
+ <view class="main" v-else-if="item.type =='image'">
|
|
|
+ <image :src="item.payload.url" @click="yulan(item.payload.url)" :style="'width:'+item.payload.width+'rpx;height'+item.payload.height+'rpx;'"
|
|
|
+ class="radius" mode="widthFix"></image>
|
|
|
</view>
|
|
|
- <view class="cu-avatar radius" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big107000.jpg);"></view>
|
|
|
- </view>
|
|
|
- <view class="cu-item self">
|
|
|
- <view class="main">
|
|
|
- <view class="action text-bold text-grey">
|
|
|
- 3"
|
|
|
- </view>
|
|
|
- <view class="content shadow">
|
|
|
- <text class="cuIcon-sound text-xxl padding-right-xl"> </text>
|
|
|
- </view>
|
|
|
+ <view class="main" v-else="item.type =='audio'">
|
|
|
+ <GoEasyAudioPlayer :src="item.payload.url" :duration="item.payload.duration" />
|
|
|
</view>
|
|
|
- <view class="cu-avatar radius" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big107000.jpg);"></view>
|
|
|
+ <view class="cu-avatar radius" :style="'background-image:url('+currentUser.avatar+');'"></view>
|
|
|
</view>
|
|
|
- <view class="cu-item">
|
|
|
+ <view class="cu-item" v-else>
|
|
|
<view class="cu-avatar radius" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big143004.jpg);"></view>
|
|
|
- <view class="main">
|
|
|
+ <view class="main" v-if="item.type=='text'">
|
|
|
<view class="content shadow">
|
|
|
- xxxxxxs
|
|
|
+ <text>{{item.payload.text}}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
+ <view class="main" v-else-if="item.type =='image'">
|
|
|
+ <image :src="item.payload.url" @click="yulan(item.payload.url)" :style="'width:'+item.payload.width+'rpx;height'+item.payload.height+'rpx;'"
|
|
|
+ class="radius" mode="widthFix"></image>
|
|
|
+ </view>
|
|
|
+ <view class="main" v-else="item.type =='audio'">
|
|
|
+ <GoEasyAudioPlayer :src="item.payload.url" :duration="item.payload.duration" />
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view :class="InputBottom!=0?'cu-bar foot input cur':'cu-bar foot input'" :style="'bottom:'+InputBottom+'px'">
|
|
|
+ <view :class="InputBottom!=0?'cu-bar foot tab input cur':'cu-bar foot input'" :style="'bottom:'+InputBottom+'px'">
|
|
|
<view class="action" @click="sendvoice">
|
|
|
<text class="cuIcon-sound text-grey"></text>
|
|
|
</view>
|
|
|
- <input v-if="!isvoice" class="solid-bottom" @focus="InputFocus" @blur="InputBlur" :adjust-position="false" :focus="false"
|
|
|
- maxlength="300" placeholder="请输入" cursor-spacing="10"></input>
|
|
|
- <button class="flex-sub" style="font-size: 30rpx; height: 64rpx;padding: 0;" v-else>按住发送语音</button>
|
|
|
- <view class="action" style="margin-right: 20rpx;">
|
|
|
+ <input v-if="!isvoice" v-model="keyword" class="solid-bottom" @focus="InputFocus" @blur="InputBlur" :disabled="isinput"
|
|
|
+ :adjust-position="false" :focus="false" maxlength="300" :placeholder="textinput" cursor-spacing="10"></input>
|
|
|
+ <button class="flex-sub" style="font-size: 30rpx; height: 64rpx;padding: 0;" @touchstart.stop="onRecordStart"
|
|
|
+ @touchend.stop="onRecordEnd" v-else>{{audio.recording ? '松开发送':'按住发送语音'}}</button>
|
|
|
+ <view class="action" style="margin-right: 20rpx;" @click="sendImage">
|
|
|
<text class="cuIcon-picfill text-grey"></text>
|
|
|
</view>
|
|
|
- <button class="cu-btn bg-green shadow">发送</button>
|
|
|
+ <button class="cu-btn bg-green shadow" @click="sendMessage">发送</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+ import {
|
|
|
+ sendMessages
|
|
|
+ } from "../../common/goeasyimutil.js"
|
|
|
+ import GoEasyAudioPlayer from "../../components/GoEasyAudioPlayer/GoEasyAudioPlayer.vue";
|
|
|
+ const recorderManager = uni.getRecorderManager()
|
|
|
export default {
|
|
|
components: {
|
|
|
-
|
|
|
+ GoEasyAudioPlayer
|
|
|
},
|
|
|
- onLoad() {
|
|
|
+ onLoad(op) {
|
|
|
+ this.imService = getApp().globalData.imService;
|
|
|
+ this.doctorInfo = JSON.parse(op.doctor)
|
|
|
+ //对话数据
|
|
|
+ this.friend = {
|
|
|
+ uuid: this.doctorInfo.id,
|
|
|
+ name: this.doctorInfo.name,
|
|
|
+ avatar: this.doctorInfo.avatar
|
|
|
+ };
|
|
|
+ this.currentUser = this.imService.currentUser;
|
|
|
+ let privateMessages = this.imService.getPrivateMessages(this.friend.uuid);
|
|
|
+ this.messages = privateMessages.sentMessages;
|
|
|
+ this.pendingMessages = privateMessages.pendingMessages;
|
|
|
+ uni.setNavigationBarTitle({
|
|
|
+ title: this.friend.name
|
|
|
+ });
|
|
|
+
|
|
|
+ this.initialListeners();
|
|
|
+
|
|
|
+
|
|
|
+ //每次进入聊天页面,总是滚动到底部
|
|
|
+ this.scrollToBottom()
|
|
|
+
|
|
|
+ //收到的消息设置为已读
|
|
|
+ if (this.messages.length != 0) {
|
|
|
+ this.imService.markPrivateMessageAsRead(this.friend.uuid);
|
|
|
+ }
|
|
|
|
|
|
},
|
|
|
mounted() {
|
| xqd
@@ -73,10 +97,41 @@
|
|
|
return {
|
|
|
keyword: "",
|
|
|
InputBottom: 0,
|
|
|
- isvoice: false
|
|
|
+ isvoice: false,
|
|
|
+ textinput: "请输入",
|
|
|
+ isinput: false,
|
|
|
+ messages: [],
|
|
|
+ self_messages: [],
|
|
|
+ friend: null,
|
|
|
+ currentUser: null,
|
|
|
+ imService: null,
|
|
|
+ audio: {
|
|
|
+ //语音录音中
|
|
|
+ recording: false,
|
|
|
+ },
|
|
|
+ doctorInfo: {}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onPullDownRefresh: function(e) {
|
|
|
+ this.loadMoreHistoryMessage();
|
|
|
+ },
|
|
|
+ onUnload() {
|
|
|
+ //退出聊天页面之前,清空页面传入的监听器
|
|
|
+ if (this.imService) {
|
|
|
+ this.imService.onNewPrivateMessageReceive = (friendId, message) => {};
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
+ renderMessageDate(message, index) {
|
|
|
+ if (index === 0) {
|
|
|
+ return this.formatDate(message.timestamp)
|
|
|
+ } else {
|
|
|
+ if (message.timestamp - this.messages[index - 1].timestamp > 5 * 60 * 1000) {
|
|
|
+ return this.formatDate(message.timestamp)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+ },
|
|
|
InputFocus(e) {
|
|
|
this.InputBottom = e.detail.height
|
|
|
},
|
| xqd
@@ -85,13 +140,121 @@
|
|
|
},
|
|
|
sendvoice() {
|
|
|
this.isvoice = !this.isvoice
|
|
|
- }
|
|
|
+ },
|
|
|
+ subscribeMessage() { //订阅消息
|
|
|
+
|
|
|
+ },
|
|
|
+ yulan(url) {
|
|
|
+ uni.previewImage({
|
|
|
+ urls: [url],
|
|
|
+ current: url
|
|
|
+ })
|
|
|
+ },
|
|
|
+ initialListeners() {
|
|
|
+ //传入监听器,收到一条私聊消息总是滚到到页面底部
|
|
|
+ this.imService.onNewPrivateMessageReceive = (friendId, message) => {
|
|
|
+ if (friendId == this.friend.uuid) {
|
|
|
+ this.imService.markPrivateMessageAsRead(friendId);
|
|
|
+ //收到新消息,是滚动到最底部
|
|
|
+ this.scrollToBottom()
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 录音监听器
|
|
|
+ this.initRecorderListeners();
|
|
|
+ },
|
|
|
+ initRecorderListeners() {
|
|
|
+ let self = this;
|
|
|
+ // 监听录音开始
|
|
|
+ recorderManager.onStart(function() {
|
|
|
+ self.audio.recording = true;
|
|
|
+ });
|
|
|
+
|
|
|
+ //录音结束后,发送
|
|
|
+ recorderManager.onStop(function(res) {
|
|
|
+ console.log(res)
|
|
|
+ self.audio.recording = false;
|
|
|
+ self.imService.sendPrivateAudioMessage(self.friend.uuid, res)
|
|
|
+ });
|
|
|
+
|
|
|
+ // 监听录音报错
|
|
|
+ recorderManager.onError(function(res) {
|
|
|
+ console.log("录音报错:", res);
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onRecordStart(event) {
|
|
|
+ try {
|
|
|
+ recorderManager.start();
|
|
|
+ } catch (e) {
|
|
|
+ uni.showModal({
|
|
|
+ title: '发送语音错误',
|
|
|
+ content: '请联系客服'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ event.preventDefault();
|
|
|
+ },
|
|
|
+ onRecordEnd() {
|
|
|
+ try {
|
|
|
+ recorderManager.stop();
|
|
|
+ } catch (e) {
|
|
|
+ uni.showModal({
|
|
|
+ title: '发送语音错误',
|
|
|
+ content: '请联系客服'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ sendMessage() { //发送消息
|
|
|
+ if (this.keyword.trim() != '') {
|
|
|
+ console.log(this.friend.uuid)
|
|
|
+ this.imService.sendPrivateTextMessage(this.friend.uuid, this.keyword);
|
|
|
+ }
|
|
|
+ this.keyword = "";
|
|
|
+ },
|
|
|
+ scrollToBottom() {
|
|
|
+ this.$nextTick(function() {
|
|
|
+ uni.pageScrollTo({
|
|
|
+ scrollTop: 2000000,
|
|
|
+ duration: 10
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ sendImage() {
|
|
|
+ uni.chooseImage({
|
|
|
+ count: 1,
|
|
|
+ success: (res) => {
|
|
|
+ this.imService.sendPrivateImageMessage(this.friend.uuid, res);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ loadMoreHistoryMessage() { //历史消息
|
|
|
+ let lastMessageTimeStamp = Date.now();
|
|
|
+ let lastMessage = this.messages[0];
|
|
|
+ if (lastMessage) {
|
|
|
+ lastMessageTimeStamp = lastMessage.timestamp;
|
|
|
+ }
|
|
|
+ var currentLength = this.messages.length;
|
|
|
+ let promise = this.imService.loadPrivateHistoryMessage(this.friend.uuid, lastMessageTimeStamp);
|
|
|
+ promise.then(messages => {
|
|
|
+ if (messages.length == currentLength) {
|
|
|
+ this.allHistoryLoaded = true
|
|
|
+ }
|
|
|
+ this.messages = messages;
|
|
|
+ uni.stopPullDownRefresh();
|
|
|
+ }).catch(e => {
|
|
|
+ console.log(e)
|
|
|
+ uni.stopPullDownRefresh();
|
|
|
+ })
|
|
|
+ },
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
-<style scoped lang="scss">
|
|
|
+<style lang="scss">
|
|
|
page {
|
|
|
padding-bottom: 100rpx;
|
|
|
}
|
|
|
+
|
|
|
+ .time-lag {
|
|
|
+ font-size: 20rpx;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
</style>
|