|
|
|
@ -9,8 +9,8 @@ |
|
|
|
<scroll-view class="scroll-box" scroll-y="true" upper-threshold="200" @scrolltoupper="onScrollToTop" |
|
|
|
:scroll-into-view="'chat-item-'+scrollMsgIdx"> |
|
|
|
<view v-if="chat" v-for="(msgInfo,idx) in chat.messages" :key="idx"> |
|
|
|
<chat-message-item v-if="idx>=showMinIdx" :headImage="headImage(msgInfo)" |
|
|
|
@call="onRtCall(msgInfo)" :showName="showName(msgInfo)" @recall="onRecallMessage" |
|
|
|
<chat-message-item v-if="idx>=showMinIdx" :headImage="headImage(msgInfo)" @call="onRtCall(msgInfo)" |
|
|
|
:showName="showName(msgInfo)" @recall="onRecallMessage" @copy="onCopyMessage" |
|
|
|
@delete="onDeleteMessage" @longPressHead="onLongPressHead(msgInfo)" @download="onDownloadFile" |
|
|
|
:id="'chat-item-'+idx" :msgInfo="msgInfo" :groupMembers="groupMembers"> |
|
|
|
</chat-message-item> |
|
|
|
@ -50,47 +50,46 @@ |
|
|
|
<view class="chat-tools-item"> |
|
|
|
<image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore" |
|
|
|
:onSuccess="onUploadImageSuccess" :onError="onUploadImageFail"> |
|
|
|
<view class="tool-icon iconfont icon-picture" ></view> |
|
|
|
<view class="tool-icon iconfont icon-picture"></view> |
|
|
|
</image-upload> |
|
|
|
<view class="tool-name">相册</view> |
|
|
|
</view> |
|
|
|
<view class="chat-tools-item"> |
|
|
|
<image-upload sourceType="camera" :onBefore="onUploadImageBefore" :onSuccess="onUploadImageSuccess" |
|
|
|
:onError="onUploadImageFail"> |
|
|
|
<view class="tool-icon iconfont icon-camera" ></view> |
|
|
|
<view class="tool-icon iconfont icon-camera"></view> |
|
|
|
</image-upload> |
|
|
|
<view class="tool-name">拍摄</view> |
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
<view class="chat-tools-item"> |
|
|
|
<file-upload :onBefore="onUploadFileBefore" :onSuccess="onUploadFileSuccess" |
|
|
|
:onError="onUploadFileFail"> |
|
|
|
<view class="tool-icon iconfont icon-folder" ></view> |
|
|
|
<view class="tool-icon iconfont icon-folder"></view> |
|
|
|
</file-upload> |
|
|
|
<view class="tool-name">文件</view> |
|
|
|
</view> |
|
|
|
|
|
|
|
|
|
|
|
<view class="chat-tools-item" @click="onRecorderInput()"> |
|
|
|
<view class="tool-icon iconfont icon-microphone" ></view> |
|
|
|
<view class="tool-icon iconfont icon-microphone"></view> |
|
|
|
<view class="tool-name">语音消息</view> |
|
|
|
</view> |
|
|
|
<view v-if="chat.type == 'GROUP'" class="chat-tools-item" @click="switchReceipt()"> |
|
|
|
<view class="tool-icon iconfont icon-receipt" |
|
|
|
:class="isReceipt?'active':''"></view> |
|
|
|
<view class="tool-icon iconfont icon-receipt" :class="isReceipt?'active':''"></view> |
|
|
|
<view class="tool-name">回执消息</view> |
|
|
|
</view> |
|
|
|
<!-- #ifndef MP-WEIXIN --> |
|
|
|
<!-- 音视频不支持小程序 --> |
|
|
|
<view v-if="chat.type == 'PRIVATE'" class="chat-tools-item" @click="onPriviteVideo()"> |
|
|
|
<view class="tool-icon iconfont icon-video" ></view> |
|
|
|
<view class="tool-icon iconfont icon-video"></view> |
|
|
|
<view class="tool-name">视频通话</view> |
|
|
|
</view> |
|
|
|
<view v-if="chat.type == 'PRIVATE'" class="chat-tools-item" @click="onPriviteVoice()"> |
|
|
|
<view class="tool-icon iconfont icon-call" ></view> |
|
|
|
<view class="tool-icon iconfont icon-call"></view> |
|
|
|
<view class="tool-name">语音通话</view> |
|
|
|
</view> |
|
|
|
<view v-if="chat.type == 'GROUP'" class="chat-tools-item" @click="onGroupVideo()"> |
|
|
|
<view class="tool-icon iconfont icon-call" ></view> |
|
|
|
<view class="tool-icon iconfont icon-call"></view> |
|
|
|
<view class="tool-name">语音通话</view> |
|
|
|
</view> |
|
|
|
<!-- #endif --> |
|
|
|
@ -109,8 +108,7 @@ |
|
|
|
@complete="onAtComplete"></chat-at-box> |
|
|
|
<!-- 群语音通话时选择成员 --> |
|
|
|
<!-- #ifndef MP-WEIXIN --> |
|
|
|
<group-member-selector ref="selBox" :members="groupMembers" |
|
|
|
:maxSize="configStore.webrtc.maxChannel" |
|
|
|
<group-member-selector ref="selBox" :members="groupMembers" :maxSize="configStore.webrtc.maxChannel" |
|
|
|
@complete="onInviteOk"></group-member-selector> |
|
|
|
<group-rtc-join ref="rtcJoin" :groupId="group.id"></group-rtc-join> |
|
|
|
<!-- #endif --> |
|
|
|
@ -136,8 +134,8 @@ |
|
|
|
keyboardHeight: 322, |
|
|
|
atUserIds: [], |
|
|
|
needScrollToBottom: false, // 需要滚动到底部 |
|
|
|
showMinIdx: 0, // 下标小于showMinIdx的消息不显示,否则可能很卡 |
|
|
|
reqQueue: [], // 请求队列 |
|
|
|
showMinIdx: 0, // 下标小于showMinIdx的消息不显示,否则可能很卡 |
|
|
|
reqQueue: [], // 请求队列 |
|
|
|
isSending: false // 是否正在发送请求 |
|
|
|
} |
|
|
|
}, |
|
|
|
@ -189,23 +187,13 @@ |
|
|
|
}) |
|
|
|
}, |
|
|
|
onGroupVideo() { |
|
|
|
this.$http({ |
|
|
|
url: "/webrtc/group/info?groupId="+this.group.id, |
|
|
|
method: 'GET' |
|
|
|
}).then((rtcInfo)=>{ |
|
|
|
if(rtcInfo.isChating){ |
|
|
|
// 已在通话中,可以直接加入通话 |
|
|
|
this.$refs.rtcJoin.open(rtcInfo); |
|
|
|
}else { |
|
|
|
// 邀请成员发起通话 |
|
|
|
let ids = [this.mine.id]; |
|
|
|
this.$refs.selBox.init(ids, ids); |
|
|
|
this.$refs.selBox.open(); |
|
|
|
} |
|
|
|
}) |
|
|
|
// 邀请成员发起通话 |
|
|
|
let ids = [this.mine.id]; |
|
|
|
this.$refs.selBox.init(ids, ids); |
|
|
|
this.$refs.selBox.open(); |
|
|
|
}, |
|
|
|
onInviteOk(ids) { |
|
|
|
if(ids.length < 2){ |
|
|
|
if (ids.length < 2) { |
|
|
|
return; |
|
|
|
} |
|
|
|
let users = []; |
|
|
|
@ -264,7 +252,6 @@ |
|
|
|
} |
|
|
|
}, |
|
|
|
sendTextMessage() { |
|
|
|
const timeStamp = new Date().getTime(); |
|
|
|
if (!this.sendText.trim() && this.atUserIds.length == 0) { |
|
|
|
return uni.showToast({ |
|
|
|
title: "不能发送空白信息", |
|
|
|
@ -283,10 +270,8 @@ |
|
|
|
// 填充对方id |
|
|
|
this.fillTargetId(msgInfo, this.chat.targetId); |
|
|
|
this.sendMessageRequest(msgInfo).then((m) => { |
|
|
|
console.log("请求耗时:",new Date().getTime()-timeStamp) |
|
|
|
m.selfSend = true; |
|
|
|
this.chatStore.insertMessage(m); |
|
|
|
console.log("insertMessage耗时:",new Date().getTime()-timeStamp) |
|
|
|
// 会话置顶 |
|
|
|
this.moveChatToTop(); |
|
|
|
}).finally(() => { |
|
|
|
@ -368,6 +353,7 @@ |
|
|
|
this.showKeyBoard = true; |
|
|
|
this.switchChatTabBox('none', false) |
|
|
|
this.keyboardHeight = this.rpxTopx(e.detail.height); |
|
|
|
this.scrollToBottom(); |
|
|
|
} else { |
|
|
|
this.showKeyBoard = false; |
|
|
|
} |
|
|
|
@ -505,6 +491,17 @@ |
|
|
|
} |
|
|
|
}) |
|
|
|
}, |
|
|
|
onCopyMessage(msgInfo) { |
|
|
|
uni.setClipboardData({ |
|
|
|
data: msgInfo.content, |
|
|
|
success: () => { |
|
|
|
uni.showToast({ title: '已复制', icon: 'none' }); |
|
|
|
}, |
|
|
|
fail: () => { |
|
|
|
uni.showToast({ title: '复制失败', icon: 'none' }); |
|
|
|
} |
|
|
|
}); |
|
|
|
}, |
|
|
|
onDownloadFile(msgInfo) { |
|
|
|
let url = JSON.parse(msgInfo.content).url; |
|
|
|
uni.downloadFile({ |
|
|
|
@ -622,14 +619,14 @@ |
|
|
|
let px = info.windowWidth * rpx / 750; |
|
|
|
return Math.floor(rpx); |
|
|
|
}, |
|
|
|
sendMessageRequest(msgInfo){ |
|
|
|
return new Promise((resolve,reject)=>{ |
|
|
|
sendMessageRequest(msgInfo) { |
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
// 请求入队列,防止请求"后发先至",导致消息错序 |
|
|
|
this.reqQueue.push({msgInfo,resolve,reject}); |
|
|
|
this.reqQueue.push({ msgInfo, resolve, reject }); |
|
|
|
this.processReqQueue(); |
|
|
|
}) |
|
|
|
}, |
|
|
|
processReqQueue(){ |
|
|
|
processReqQueue() { |
|
|
|
if (this.reqQueue.length && !this.isSending) { |
|
|
|
this.isSending = true; |
|
|
|
const reqData = this.reqQueue.shift(); |
|
|
|
@ -637,18 +634,18 @@ |
|
|
|
url: this.messageAction, |
|
|
|
method: 'post', |
|
|
|
data: reqData.msgInfo |
|
|
|
}).then((res)=>{ |
|
|
|
}).then((res) => { |
|
|
|
reqData.resolve(res) |
|
|
|
}).catch((e)=>{ |
|
|
|
}).catch((e) => { |
|
|
|
reqData.reject(e) |
|
|
|
}).finally(()=>{ |
|
|
|
}).finally(() => { |
|
|
|
this.isSending = false; |
|
|
|
// 发送下一条请求 |
|
|
|
this.processReqQueue(); |
|
|
|
}) |
|
|
|
} |
|
|
|
}, |
|
|
|
generateId(){ |
|
|
|
generateId() { |
|
|
|
// 生成临时id |
|
|
|
return String(new Date().getTime()) + String(Math.floor(Math.random() * 1000)); |
|
|
|
} |
|
|
|
@ -706,10 +703,10 @@ |
|
|
|
// 接收到消息时滚动到底部 |
|
|
|
if (newSize > oldSize) { |
|
|
|
let pages = getCurrentPages(); |
|
|
|
let curPage = pages[pages.length-1].route; |
|
|
|
if(curPage == "pages/chat/chat-box"){ |
|
|
|
let curPage = pages[pages.length - 1].route; |
|
|
|
if (curPage == "pages/chat/chat-box") { |
|
|
|
this.scrollToBottom(); |
|
|
|
}else { |
|
|
|
} else { |
|
|
|
this.needScrollToBottom = true; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -743,8 +740,8 @@ |
|
|
|
// 复位回执消息 |
|
|
|
this.isReceipt = false; |
|
|
|
}, |
|
|
|
onShow(){ |
|
|
|
if(this.needScrollToBottom){ |
|
|
|
onShow() { |
|
|
|
if (this.needScrollToBottom) { |
|
|
|
// 页面滚到底部 |
|
|
|
this.scrollToBottom(); |
|
|
|
this.needScrollToBottom = false; |
|
|
|
@ -839,6 +836,7 @@ |
|
|
|
border: #dddddd solid 1px; |
|
|
|
background-color: #f7f8fd; |
|
|
|
height: 80rpx; |
|
|
|
|
|
|
|
.iconfont { |
|
|
|
font-size: 68rpx; |
|
|
|
margin: 6rpx; |
|
|
|
@ -857,6 +855,7 @@ |
|
|
|
border-radius: 20rpx; |
|
|
|
font-size: 30rpx; |
|
|
|
box-sizing: border-box; |
|
|
|
|
|
|
|
.send-text-area { |
|
|
|
width: 100%; |
|
|
|
} |
|
|
|
@ -883,13 +882,14 @@ |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
align-items: center; |
|
|
|
|
|
|
|
|
|
|
|
.tool-icon { |
|
|
|
padding: 28rpx; |
|
|
|
font-size: 60rpx; |
|
|
|
border-radius: 20%; |
|
|
|
background-color: white; |
|
|
|
color: black; |
|
|
|
|
|
|
|
&.active { |
|
|
|
background-color: #ddd; |
|
|
|
} |
|
|
|
|