This commit is contained in:
2022-02-23 10:10:18 +08:00
9 changed files with 420 additions and 265 deletions

View File

@@ -0,0 +1,81 @@
<template>
<view v-if="!isRemote">
<view class="state" v-if="isGroup">
<!-- 已发送 -->
<u-icon name="checkbox-mark" :size="iconSize" class="sent"
:color="message.sentStatus >= 30 ? '#34CE98' : '#999999' " />
<!-- 已阅读 -->
<text class="readers">{{ readers }}</text>
</view>
<view class="state" v-else>
<!-- 已发送 -->
<u-icon name="checkbox-mark" :size="iconSize" class="sent"
:color="message.sentStatus >= 30 ? '#34CE98' : '#999999' " />
<!-- 已阅读 -->
<u-icon name="checkbox-mark" :size="iconSize" class="receive"
:color="message.sentStatus >= 50 ? '#34CE98' : '#999999' " />
</view>
</view>
</template>
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import utils from '@/utils/index.js'
export default {
name: 'showText',
props: {
message: {
type: Object,
default: () => {
return {}
}
},
isGroup: {
type: Boolean,
default: false
},
isRemote: {
type: Boolean,
default: false
}
},
computed: {
iconSize() {
return utils.rpx2px(28)
},
readers() {
if (this.message.extra) {
return JSON.parse(this.message.extra).readers || 0
}
return 0
}
}
}
</script>
<style scoped lang="scss">
.state {
padding: 10rpx;
border-radius: 30rpx;
background-color: #ddd;
display: flex;
margin-right: 10rpx;
.sent {
z-index: 2;
}
.receive {
z-index: 1;
margin-left: -20rpx;
}
.readers {
font-size: 20rpx;
margin-left: -6rpx;
color: $text-gray-m;
}
}
</style>

View File

@@ -1,10 +1,9 @@
<template> <template>
<view class="msg--call"> <view class="msg--call">
<view class="name" v-if="!guest && name">{{ name }}</view> <view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="im--text" :class="guest ? 'right': 'left'"> <view class="im--text" :class="isRemote ? 'left': 'right'">
<u-icon name="camera" size="22" v-if="message.mediaType == 1" <u-icon name="camera" size="22" v-if="msg.mediaType == 1" :label="label" />
:label="message.connected ? '通话时长:' + duration : '未接通'" /> <u-icon name="phone" size="22" v-else :label="label" />
<u-icon name="phone" size="22" v-else :label="message.connected ? '通话时长:' + duration : '未接通'" />
</view> </view>
</view> </view>
</template> </template>
@@ -16,24 +15,33 @@
export default { export default {
name: 'showText', name: 'showText',
props: { props: {
msg: { message: {
type: Object, type: Object,
default: () => { default: () => {
return {} return {}
} }
}, },
name: { isGroup: {
type: String,
default: ''
},
guest: {
type: Boolean, type: Boolean,
default: true default: false
} }
}, },
mounted() {
},
computed: { computed: {
message() { msg() {
return JSON.parse(this.msg.message) return JSON.parse(this.message.content.message)
},
label() {
return this.msg.connected ? '通话时长:' + duration : '未接通'
},
isRemote() {
return this.message.messageDirection == 2
},
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
}, },
duration() { duration() {
if (this.message.duration > 3600) { if (this.message.duration > 3600) {

View File

@@ -1,14 +1,19 @@
<template> <template>
<view class=""> <view class="msg--image">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view> <message-state :message="message" :isGroup="isGroup" :isRemote="isRemote" />
<view class="msg--image" :class="isRemote ? 'left': 'right'">
<image class="img" :src="content.thumbnail" @click="previewImage" mode="widthFix"></image> <view class="">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="image" :class="isRemote ? 'left': 'right'">
<image class="img" :src="content.thumbnail" @click="previewImage" mode="widthFix"></image>
</view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import messageState from './messageState'
export default { export default {
name: 'showImage', name: 'showImage',
@@ -24,6 +29,9 @@
default: false default: false
} }
}, },
components: {
messageState
},
computed: { computed: {
isRemote() { isRemote() {
return this.message.messageDirection == 2 return this.message.messageDirection == 2
@@ -84,27 +92,31 @@
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.name {
font-size: 24rpx;
color: $text-gray-m;
}
.msg--image { .msg--image {
.img { display: flex;
width: 180rpx; align-items: flex-end;
.name {
font-size: 24rpx;
color: $text-gray-m;
} }
&.left { .image {
.img { .img {
border-radius: 0 10rpx 10rpx 10rpx; width: 180rpx;
}
&.left {
.img {
border-radius: 0 10rpx 10rpx 10rpx;
}
}
&.right {
.img {
border-radius: 10rpx 0 10rpx 10rpx;
}
} }
} }
&.right {
.img {
border-radius: 10rpx 0 10rpx 10rpx;
}
}
} }
</style> </style>

View File

@@ -1,20 +1,16 @@
<template> <template>
<view class="msg--text"> <view class="msg--text">
<view class="state" v-if="!isGroup && !isRemote"> <message-state :message="message" :isGroup="isGroup" :isRemote="isRemote" />
<!-- 已发送 -->
<u-icon name="checkbox-mark" class="sent" :color="message.sentStatus >= 30 ? '#34CE98' : '#999999' " />
<!-- 已阅读 -->
<u-icon name="checkbox-mark" class="receive" :color="message.sentStatus >= 50 ? '#34CE98' : '#999999' " />
</view>
<view class=""> <view class="">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view> <view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view @longpress="backMessage" :class="['text', isRemote ? 'left': 'right']">{{ content }}</view> <view :class="['text', isRemote ? 'left': 'right']">{{ content }}</view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' import messageState from './messageState'
export default { export default {
name: 'showText', name: 'showText',
@@ -30,6 +26,9 @@
default: false default: false
} }
}, },
components: {
messageState
},
computed: { computed: {
isRemote() { isRemote() {
return this.message.messageDirection == 2 return this.message.messageDirection == 2
@@ -42,42 +41,6 @@
return this.$store.getters.contactInfo(targetId) return this.$store.getters.contactInfo(targetId)
} }
} }
},
methods: {
// 撤回消息测试
backMessage() {
if (this.$store.getters.sender.userId != this.message.senderUserId) {
uni.showToast({
icon: 'none',
title: '不能撤回别人的消息'
})
return
}
// 判断时间超过了多久 就不能撤回 TODO
// this.message.sentTime
const pushContent = this.$store.getters.sender.name + '撤回了一条消息'
RongIMLib.recallMessage(this.message.messageId, pushContent,
({
code,
message
}) => {
if (code === 0) {
uni.showToast({
icon: 'none',
title: '消息撤回成功'
})
RongIMLib.getMessage(this.message.messageId, res => {
uni.$emit('onRecallMessage', res.message)
})
} else {
uni.showToast({
icon: 'none',
title: '撤回失败' + code
})
}
}
)
}
} }
} }
</script> </script>
@@ -87,24 +50,6 @@
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
.state {
padding: 10rpx;
border-radius: 30rpx;
width: 40rpx;
background-color: #ddd;
display: flex;
margin-right: 10rpx;
.sent {
z-index: 2;
}
.receive {
z-index: 1;
margin-left: -20rpx;
}
}
.name { .name {
font-size: 24rpx; font-size: 24rpx;
color: $text-gray-m; color: $text-gray-m;

View File

@@ -1,25 +1,30 @@
<template> <template>
<view class=""> <view class="msg--voice">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view> <message-state :message="message" :isGroup="isGroup" :isRemote="isRemote" />
<view class="msg--voice">
<view :class="['voice', isRemote ? 'left': 'right', {'onPlay': onPlay}]" :style="{width: width + 'rpx'}" <view class="">
@click="startPlay"> <view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<image v-if="isRemote" class="icon" :class="{ 'videoFlicker' : onPlay && msgId == message.messageId }" <view class="msg-voice">
src="@/static/icon/audio_green.png" mode="widthFix"></image> <view :class="['voice', isRemote ? 'left': 'right', {'onPlay': onPlay}]" :style="{width: width + 'rpx'}"
<image v-else class="icon" :class="{ 'videoFlicker' : onPlay && msgId == message.messageId }" @click="startPlay">
src="@/static/icon/audio_white.png" mode="widthFix"></image> <image v-if="isRemote" class="icon"
<text class="duration">{{ duration }}"</text> :class="{ 'videoFlicker' : onPlay && msgId == message.messageId }"
src="@/static/icon/audio_green.png" mode="widthFix"></image>
<image v-else class="icon" :class="{ 'videoFlicker' : onPlay && msgId == message.messageId }"
src="@/static/icon/audio_white.png" mode="widthFix"></image>
<text class="duration">{{ duration }}"</text>
</view>
<u-badge isDot :show="message.content.local =='' && isRemote" />
</view> </view>
<u-badge isDot :show="message.content.local =='' && isRemote" />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import messageState from './messageState'
export default { export default {
name: 'showVoice',
props: { props: {
message: { message: {
type: Object, type: Object,
@@ -32,6 +37,9 @@
default: false default: false
} }
}, },
components: {
messageState
},
data() { data() {
return { return {
onPlay: false, onPlay: false,
@@ -162,59 +170,82 @@
</style> </style>
<style scoped lang="scss"> <style scoped lang="scss">
.name {
font-size: 24rpx;
color: $text-gray-m;
}
.msg--voice { .msg--voice {
display: flex; display: flex;
align-items: center; align-items: flex-end;
.u-badge { .state {
margin-left: 20rpx; padding: 10rpx;
border-radius: 30rpx;
width: 40rpx;
background-color: #ddd;
display: flex;
margin-right: 10rpx;
.sent {
z-index: 2;
}
.receive {
z-index: 1;
margin-left: -20rpx;
}
} }
.voice { .name {
font-size: 24rpx;
color: $text-gray-m;
}
.msg-voice {
display: flex; display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center; align-items: center;
height: 84rpx;
padding: 0 30rpx;
box-sizing: border-box;
.icon { .u-badge {
width: 38rpx; margin-left: 20rpx;
height: 38rpx;
} }
&.left { .voice {
border-radius: 0 20rpx 20rpx 20rpx; display: flex;
background: white; flex-direction: row;
justify-content: space-between;
align-items: center;
height: 84rpx;
padding: 0 30rpx;
box-sizing: border-box;
&.onPlay { .icon {
background-color: #EEEEEE; width: 38rpx;
height: 38rpx;
} }
.duration { &.left {
color: #333; border-radius: 0 20rpx 20rpx 20rpx;
font-size: 30rpx; background: white;
}
}
&.right { &.onPlay {
border-radius: 20rpx 0 20rpx 20rpx; background-color: #EEEEEE;
background: $main-color; }
flex-direction: row-reverse;
&.onPlay { .duration {
background-color: darken($main-color, 10); color: #333;
font-size: 30rpx;
}
} }
.duration { &.right {
color: white; border-radius: 20rpx 0 20rpx 20rpx;
font-size: 30rpx; background: $main-color;
flex-direction: row-reverse;
&.onPlay {
background-color: darken($main-color, 10);
}
.duration {
color: white;
font-size: 30rpx;
}
} }
} }
} }

View File

@@ -7,7 +7,7 @@
<view v-else :class="['cell-item', message.messageDirection == 1 ? 'right' : 'left']"> <view v-else :class="['cell-item', message.messageDirection == 1 ? 'right' : 'left']">
<u-avatar class="avatar" @click="toUser(message)" :size="avatarSize" shape="square" <u-avatar class="avatar" @click="toUser(message)" :size="avatarSize" shape="square"
:src="contact(message.senderUserId).portraitUrl" /> :src="contact(message.senderUserId).portraitUrl" />
<view class="msg"> <view class="msg" @longpress="backMessage">
<show-text v-if="message.objectName === 'RC:TxtMsg'" :message="message" :isGroup="isGroup" /> <show-text v-if="message.objectName === 'RC:TxtMsg'" :message="message" :isGroup="isGroup" />
<show-voice v-else-if="message.objectName === 'RC:HQVCMsg'" :message="message" :isGroup="isGroup" /> <show-voice v-else-if="message.objectName === 'RC:HQVCMsg'" :message="message" :isGroup="isGroup" />
<show-image v-else-if="message.objectName === 'RC:ImgMsg'" :message="message" :isGroup="isGroup" /> <show-image v-else-if="message.objectName === 'RC:ImgMsg'" :message="message" :isGroup="isGroup" />
@@ -22,6 +22,7 @@
</template> </template>
<script> <script>
import * as IMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import showVoice from './show/showVoice' import showVoice from './show/showVoice'
import showImage from './show/showImage' import showImage from './show/showImage'
import showText from './show/showText' import showText from './show/showText'
@@ -73,6 +74,40 @@
url: '/pages/im/friends/info?targetId=' + item.senderUserId url: '/pages/im/friends/info?targetId=' + item.senderUserId
}) })
} }
},
// 撤回消息测试
backMessage() {
if (this.$store.getters.sender.userId != this.message.senderUserId) {
uni.showToast({
icon: 'none',
title: '不能撤回别人的消息'
})
return
}
// 判断时间超过了多久 就不能撤回 TODO
// this.message.sentTime
const pushContent = this.$store.getters.sender.name + '撤回了一条消息'
IMLib.recallMessage(this.message.messageId, pushContent,
({
code,
message
}) => {
if (code === 0) {
uni.showToast({
icon: 'none',
title: '消息撤回成功'
})
IMLib.getMessage(this.message.messageId, res => {
uni.$emit('onRecallMessage', res.message)
})
} else {
uni.showToast({
icon: 'none',
title: '撤回失败' + code
})
}
}
)
} }
} }
} }

View File

@@ -74,8 +74,17 @@
}) })
} }
}) })
// 群已读回执
uni.$on('onReceiptResponse', (msg) => { uni.$on('onReceiptResponse', (msg) => {
console.log('远端消息已读,本地获取有几个人读了', msg); if (msg.targetId == this.targetId) {
this.messages = this.messages.map(item => {
if (msg.messageId == item.messageId) {
return msg
} else {
return item
}
})
}
}) })
// 清理聊天记录 // 清理聊天记录
uni.$once('cleanGroupMessage', this.getMessageList) uni.$once('cleanGroupMessage', this.getMessageList)
@@ -127,9 +136,17 @@
true, true,
(messages) => { (messages) => {
console.log('获取消息列表', messages); console.log('获取消息列表', messages);
RongIMLib.sendReadReceiptResponse(3, this.targetId, messages, (res) => { const msgs = messages.filter(item => item.receivedStatus == 0)
console.error('发送群聊已读回执成功', res); console.log('未读消息', msgs);
}) if (msgs.length) {
RongIMLib.sendReadReceiptResponse(3, this.targetId, msgs, (res) => {
console.error('发送群聊已读回执成功', res);
msgs.map(item => {
RongIMLib.setMessageReceivedStatus(item.messageId, 1)
})
})
}
this.messages = messages this.messages = messages
this.scrollBottom() this.scrollBottom()
}) })

View File

@@ -78,8 +78,20 @@
this.getNewMessage() this.getNewMessage()
} }
}) })
uni.$on('onRecallMessage', (res) => {
if (res.targetId == this.targetId) {
this.messages = this.messages.map(item => {
if (res.messageId == item.messageId) {
return res
} else {
return item
}
})
}
})
}, },
onUnload() { onUnload() {
uni.$off('onRecallMessage')
uni.$off('onReadReceiptReceived') uni.$off('onReadReceiptReceived')
}, },
methods: { methods: {

View File

@@ -103,12 +103,26 @@ const imLibListeners = () => {
IMLib.addReceiptRequestListener(({ IMLib.addReceiptRequestListener(({
data data
}) => { }) => {
console.error('onReceiptRequested', data);
uni.$emit('onReceiptRequest', data) uni.$emit('onReceiptRequest', data)
}) })
// 群消息已读的回执 // 群消息已读的回执
IMLib.addReceiptResponseListener((res) => { IMLib.addReceiptResponseListener(({
console.error('onReceiptResponse', res); data
}) => {
// 获取本地消息
IMLib.getMessageByUId(data.messageUId, ({
message
}) => {
const readers = Object.keys(data.users).length
const extra = JSON.stringify({
readers
})
// 在消息的扩展数据中,设置已读数量
IMLib.setMessageExtra(message.messageId, extra, (result) => {
message.extra = extra
uni.$emit('onReceiptResponse', message)
})
})
}) })
} }