This commit is contained in:
唐明明
2022-02-23 16:50:26 +08:00
30 changed files with 777 additions and 513 deletions

View File

@@ -35,7 +35,7 @@
},
methods: {
resolve() {
resolveFriend(this.message.sourceUserId).then(res => {
resolveFriend(this.message.sourceUserId).then(res => {
this.clearMessages()
uni.showToast({
icon: 'none',
@@ -69,8 +69,10 @@
// 不管是通过还是拒绝,都要把相关的信息清理
clearMessages() {
RongIMLib.deleteMessages(RongIMLib.ConversationType.SYSTEM, this.message.sourceUserId)
this.$emit('success')
uni.$emit('onContactNotification')
this.$emit('success')
uni.$emit('onNewContactConversation', message)
uni.$emit('onNewContactFriends', message)
uni.$emit('onNewContactPendings', message)
}
}
}

View File

@@ -54,8 +54,8 @@
return {
users: [],
isOwner: false,
isAdmin: false,
canInvite:false,// 是否可以开启邀请
isAdmin: false,
canInvite: false, // 是否可以开启邀请
adminUid: 0,
members: 0,
actionShow: false,
@@ -82,8 +82,7 @@
},
mounted() {
this.initGroupInfo()
getGroupUsers(this.targetId, this.count).then(res => {
console.log("res..",res)
getGroupUsers(this.targetId, this.count).then(res => {
this.users = res
res.map(item => {
this.$store.dispatch('updateContact', item)
@@ -96,7 +95,7 @@
this.isOwner = res.is_owner
this.isAdmin = res.is_admin
this.adminUid = res.user_id
this.members = res.members
this.members = res.members
this.canInvite = res.can_invite
})
},

View File

@@ -6,8 +6,10 @@
</view>
<view class="content">
<view class="header">
<view class="name">{{ contact(item.targetId).name }} <text v-if="item.conversationType === 3"
class='qun'>[]</text></view>
<view class="name">
{{ contact(item.targetId).name }}
<text v-if="item.conversationType === 3" class='group'>[]</text>
</view>
<view class="time">{{ item.sentTime|timeCustomCN }}</view>
</view>
<message-preview class="preview" :msg="item.latestMessage" :draft="item.draft"
@@ -80,10 +82,8 @@
.name {
font-size: $title-size + 2;
color: #454545;
display: flex;
align-items: center;
.qun {
.group {
color: $main-color;
font-size: $title-size-m - 4;
margin-left: 4px;

View File

@@ -1,12 +1,14 @@
<template>
<view class="send--voice">
<view class="voice" hover-class="chat-hover" @touchstart="startRecord" @touchend="stopRecord">
<view class="voice" hover-class="chat-hover" @click="onShowLay">
<text class="button">按住说话</text>
</view>
<!-- 录音中提示 -->
<view class="modal" v-if="showRecordTip">
<image class="icon" src="@/static/icon/record-icon.png" mode="widthFix"></image>
<text class="text">录音中 {{recordTime}} s</text>
</view>
<!-- 录音中提示 -->
<view class="voice--lay" v-if="showRecordTip" @touchstart="startRecord" @touchend="stopRecord">
<view class="modal">
<image class="icon" src="@/static/icon/record-icon.png" mode="widthFix"></image>
<text class="text">录音中 {{recordTime}} s</text>
</view>
</view>
</view>
</template>
@@ -40,16 +42,24 @@
return this.$store.getters.sender
}
},
created() {
created() {
this.recorderManager = uni.getRecorderManager()
},
methods: {
methods: {
onShowLay(){
// this.showRecordTip = true
uni.vibrateShort({
complete: com => {
console.log(com)
}
})
},
// 检查安卓录制权限
async getAndroidPermission() {
return await permision.requestAndroidPermission('android.permission.RECORD_AUDIO')
},
// 录制语音消息
startRecord() {
startRecord() {
this.getAndroidPermission().then(code => {
switch (code) {
case 1:
@@ -114,6 +124,15 @@
font-size: 30rpx;
color: #333;
}
}
.voice--lay{
position: absolute;
left: 0;
bottom: 0;
background: rgba($color: #000000, $alpha: .2);
height: 100vh;
width: 100vw;
}
.modal {

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,47 +1,55 @@
<template>
<view class="msg--call">
<view class="name" v-if="!guest && name">{{ name }}</view>
<view class="im--text" :class="guest ? 'right': 'left'">
<u-icon name="camera" size="22" v-if="message.mediaType == 1"
:label="message.connected ? '通话时长:' + duration : '未接通'" />
<u-icon name="phone" size="22" v-else :label="message.connected ? '通话时长:' + duration : '未接通'" />
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="im--text" :class="isRemote ? 'left': 'right'">
<u-icon name="camera" size="22" v-if="msg.mediaType == 1" :label="label" />
<u-icon name="phone" size="22" v-else :label="label" />
</view>
</view>
</template>
<script>
import utils from '@/utils/index.js'
import moment from 'moment'
import utils from '@/utils/index.js'
import moment from 'moment'
export default {
name: 'showText',
props: {
msg: {
message: {
type: Object,
default: () => {
return {}
}
},
name: {
type: String,
default: ''
},
guest: {
isGroup: {
type: Boolean,
default: true
default: false
}
},
computed: {
message() {
return JSON.parse(this.msg.message)
},
duration() {
if (this.message.duration > 3600) {
return moment.utc(this.message.duration * 1000).format('HH:mm:ss')
} else {
return moment.utc(this.message.duration * 1000).format('mm:ss')
}
}
mounted() {
},
computed: {
msg() {
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() {
if (this.message.duration > 3600) {
return moment.utc(this.message.duration * 1000).format('HH:mm:ss')
} else {
return moment.utc(this.message.duration * 1000).format('mm:ss')
}
}
}
}
</script>

View File

@@ -1,110 +1,106 @@
<template>
<view class="">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="msg--image" :class="isRemote ? 'left': 'right'">
<image class="img" :src="content.thumbnail" @click="previewImage" mode="widthFix"></image>
</view>
</view>
</template>
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
export default {
name: 'showImage',
props: {
message: {
type: Object,
default: () => {
return {}
}
},
isGroup: {
type: Boolean,
default: false
}
},
computed: {
isRemote() {
return this.message.messageDirection == 2
},
content() {
return this.message.content
},
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
}
},
<template>
<view class="msg--image">
<message-state :message="message" :isGroup="isGroup" :isRemote="isRemote" />
<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>
</template>
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import messageState from './messageState'
export default {
name: 'showImage',
props: {
message: {
type: Object,
default: () => {
return {}
}
},
isGroup: {
type: Boolean,
default: false
}
},
components: {
messageState
},
computed: {
isRemote() {
return this.message.messageDirection == 2
},
content() {
return this.message.content
},
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
}
},
methods: {
showImage(path) {
uni.previewImage({
urls: [
path
]
})
},
previewImage() {
if (this.content.local) {
uni.previewImage({
urls: [
this.content.local
],
success: (e) => {
console.log(e);
},
fail: (er) => {
console.log(er);
}
})
} else {
RongIMLib.downloadMediaMessage(this.messageId, {
success: (path) => {
this.content.local = path
uni.previewImage({
urls: [
path
],
success: (e) => {
console.log(e);
},
fail: (er) => {
console.log(er);
}
})
},
progress: (progress, messageId) => {
console.log('progress', progress);
},
cancel: (messageId) => {
console.log('cancel', messageId);
},
if (this.content.local && this.content.local.indexOf('///data/user/') < 0) {
this.showImage(this.content.local)
} else {
RongIMLib.downloadMediaMessage(this.message.messageId, {
success: (path) => {
this.content.local = path
this.showImage(path)
},
error: (errorCode, messageId) => {
console.log('errorCode', errorCode);
}
})
}
}
}
}
</script>
<style scoped lang="scss">
.name {
font-size: 24rpx;
color: $text-gray-m;
}
.msg--image {
.img {
width: 180rpx;
}
&.left {
.img {
border-radius: 0 10rpx 10rpx 10rpx;
}
}
&.right {
.img {
border-radius: 10rpx 0 10rpx 10rpx;
}
}
}
uni.showToast({
icon: 'none',
title: errorCode
})
}
})
}
}
}
}
</script>
<style scoped lang="scss">
.msg--image {
display: flex;
align-items: flex-end;
.name {
font-size: 24rpx;
color: $text-gray-m;
}
.image {
.img {
width: 180rpx;
}
&.left {
.img {
border-radius: 0 10rpx 10rpx 10rpx;
}
}
&.right {
.img {
border-radius: 10rpx 0 10rpx 10rpx;
}
}
}
}
</style>

View File

@@ -1,20 +1,16 @@
<template>
<view class="msg--text">
<view class="state" v-if="!isGroup && !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>
<message-state :message="message" :isGroup="isGroup" :isRemote="isRemote" />
<view class="">
<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>
</template>
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import messageState from './messageState'
export default {
name: 'showText',
@@ -30,6 +26,9 @@
default: false
}
},
components: {
messageState
},
computed: {
isRemote() {
return this.message.messageDirection == 2
@@ -42,42 +41,6 @@
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>
@@ -87,24 +50,6 @@
display: flex;
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 {
font-size: 24rpx;
color: $text-gray-m;

View File

@@ -1,22 +1,30 @@
<template>
<view class="">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="msg--voice">
<view :class="['voice', isRemote ? 'left': 'right', {'onPlay': onPlay}]" :style="{width: width + 'rpx'}" @click="startPlay">
<image v-if="isRemote" class="icon" :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 class="msg--voice">
<message-state :message="message" :isGroup="isGroup" :isRemote="isRemote" />
<view class="">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="msg-voice">
<view :class="['voice', isRemote ? 'left': 'right', {'onPlay': onPlay}]" :style="{width: width + 'rpx'}"
@click="startPlay">
<image v-if="isRemote" class="icon"
: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>
<u-badge isDot :show="message.content.local =='' && isRemote" />
</view>
</view>
</template>
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import messageState from './messageState'
export default {
name: 'showVoice',
props: {
message: {
type: Object,
@@ -27,13 +35,16 @@
isGroup: {
type: Boolean,
default: false
}
}
},
components: {
messageState
},
data() {
return {
onPlay: false,
innerAC: null,
msgId : null
innerAC: null,
msgId: null
}
},
computed: {
@@ -47,13 +58,13 @@
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
},
width() {
if (this.duration > 3) {
return (this.duration * 5) + 150
} else {
return 120
}
},
width() {
if (this.duration > 3) {
return (this.duration * 5) + 150
} else {
return 120
}
}
},
mounted() {
@@ -63,12 +74,7 @@
this.stopPlay()
}
})
},
created() {
console.log(this.message.messageId)
},
},
methods: {
// 播放语音消息
startPlay() {
@@ -77,8 +83,9 @@
this.stopPlay()
return
}
this.onPlay = true
// 如果下载到了本地,那么直接播放,否则调用下载语音消息接口,下载后再播放
if (this.message.content.local) {
if (this.message.content.local && this.message.content.local.indexOf('///data/user/') < 0) {
this.playVoice(this.message.content.local)
} else {
RongIMLib.downloadMediaMessage(this.message.messageId, {
@@ -88,27 +95,27 @@
},
progress: (progress, messageId) => {},
cancel: (messageId) => {},
error: (errorCode, messageId) => {
uni.showToast({
icon: 'none',
title: '语音播放失败'
})
error: (errorCode, messageId) => {
uni.showToast({
icon: 'none',
title: '语音播放失败'
})
}
})
}
},
playVoice(path) {
playVoice(path) {
console.log('准备播放', this.message.content);
this.innerAC = uni.createInnerAudioContext()
this.innerAC.src = path
this.innerAC.autoplay = false
this.msgId = this.message.messageId
this.innerAC.onCanplay(res => {
this.innerAC.autoplay = false
this.msgId = this.message.messageId
this.innerAC.onCanplay(res => {
console.log('onCanplay')
this.innerAC.play()
})
this.innerAC.onPlay(res => {
this.onPlay = true
})
this.innerAC.onPlay(res => {
console.log('onPlay')
uni.$emit('onVoiceMessagePlay', this.message.messageId)
})
this.innerAC.onEnded(res => {
@@ -117,11 +124,11 @@
this.innerAC.onStop(() => {
this.onPlay = false
this.innerAC.destroy()
this.innerAC = null
this.msgId = null
this.innerAC = null
this.msgId = null
uni.$emit('onVoiceMessageStop', this.message.messageId)
})
this.innerAC.onError(err => {
this.innerAC.onError(err => {
uni.showToast({
icon: 'none',
title: '语音播放失败'
@@ -129,87 +136,111 @@
})
},
stopPlay() {
// 停止播放语音消息
if (this.innerAC) {
this.innerAC.stop()
}
}
}
}
</script>
<style>
@keyframes playFlicker{
0%{
opacity: 1;
}
50%{
opacity: .5;
}
100%{
opacity: 1;
}
}
.videoFlicker{
animation: playFlicker 1s infinite;
}
</script>
<style>
@keyframes playFlicker {
0% {
opacity: 1;
}
50% {
opacity: .5;
}
100% {
opacity: 1;
}
}
.videoFlicker {
animation: playFlicker 1s infinite;
}
</style>
<style scoped lang="scss">
.name {
font-size: 24rpx;
color: $text-gray-m;
}
.msg--voice {
display: flex;
align-items: center;
align-items: flex-end;
.u-badge {
margin-left: 20rpx;
.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;
}
}
.voice {
.name {
font-size: 24rpx;
color: $text-gray-m;
}
.msg-voice {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 84rpx;
padding: 0 30rpx;
box-sizing: border-box;
.icon {
width: 38rpx;
height: 38rpx;
.u-badge {
margin-left: 20rpx;
}
&.left {
border-radius: 0 20rpx 20rpx 20rpx;
background: white;
.voice {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 84rpx;
padding: 0 30rpx;
box-sizing: border-box;
&.onPlay {
background-color: #EEEEEE;
.icon {
width: 38rpx;
height: 38rpx;
}
.duration {
color: #333;
font-size: 30rpx;
}
}
&.left {
border-radius: 0 20rpx 20rpx 20rpx;
background: white;
&.right {
border-radius: 20rpx 0 20rpx 20rpx;
background: $main-color;
flex-direction: row-reverse;
&.onPlay {
background-color: #EEEEEE;
}
&.onPlay {
background-color: darken($main-color, 10);
.duration {
color: #333;
font-size: 30rpx;
}
}
.duration {
color: white;
font-size: 30rpx;
&.right {
border-radius: 20rpx 0 20rpx 20rpx;
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']">
<u-avatar class="avatar" @click="toUser(message)" :size="avatarSize" shape="square"
: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-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" />
@@ -22,6 +22,7 @@
</template>
<script>
import * as IMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import showVoice from './show/showVoice'
import showImage from './show/showImage'
import showText from './show/showText'
@@ -73,6 +74,40 @@
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

@@ -2,40 +2,33 @@
<view>
<u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98">
<view class="friend-flex" @click="toPending">
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_01.png')"></u-avatar>
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_01.png')" />
<u-badge max="99" absolute :offset="[23, 20]" :value="pendingCount" />
<view class="info">新的朋友</view>
</view>
<view class="friend-flex" @click="toGroup">
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_00.png')"></u-avatar>
<u-avatar class="cover" size="40" shape="square" :src="require('@/static/im/im_00.png')" />
<view class="info">我的群聊</view>
</view>
<block v-if="friends.length > 0">
<block v-if="friends.length > 0">
<u-index-item v-for="(item, fkey) in friends" :key="fkey">
<u-index-anchor :text="indexs[fkey]" bgColor="#f9f9f9" height="20" size="12" color="#666"
class="anchor" />
<view v-for="(friendItem, index) in item" :key="index" class="friend-flex"
@click="toFriend(friendItem.targetId)">
<u-avatar class="avatar-img" size="40" shape="square"
:src="contact(friendItem.targetId).portraitUrl" />
<view class="info">
<view class="name">{{ contact(friendItem.targetId).name }}</view>
<!-- <view class="address">地址:{{ friendItem.address }}</view> -->
</view>
<u-index-anchor :text="indexs[fkey]" bgColor="#f9f9f9" height="20" size="12" color="#666" class="anchor" />
<view v-for="(friendItem, index) in item" :key="index" class="friend-flex" @click="toFriend(friendItem.targetId)">
<u-avatar class="avatar-img" size="40" shape="square" :src="contact(friendItem.targetId).portraitUrl" />
<view class="info"> <view class="name">{{ contact(friendItem.targetId).name }}</view> </view>
</view>
</u-index-item>
</block>
<block v-else>
<u-empty class="pages-null" mode="data" text="暂无好友" />
</block>
<view class="no-lists" v-else>
<u-image class="cover" radius="4" width="400rpx" height="400rpx" :src=" require('@/static/imgs/no-friend.png')" :lazy-load="true" />
<span>暂无好友列表~</span>
</view>
</u-index-list>
</view>
</template>
<script>
import {
getFriendsLetter
} from '@/apis/interfaces/im';
import {getFriendsLetter} from '@/apis/interfaces/im';
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import im from '@/utils/im/index.js'
@@ -54,16 +47,20 @@
}
}
},
onLoad() {
onShow() {
this.getFriendList()
this.checkNewFriendPending()
uni.$on('onContactNotification', this.checkNewFriendPending)
},
onUnload() {
uni.$off("onContactNotification")
},
methods: {
getFriendList() {
getFriendsLetter().then(res => {
getFriendsLetter().then(res => {
console.log(res)
this.indexs = res.indexList
this.friends = res.itemArr
this.friends = res.itemArr
})
},
checkNewFriendPending() {
@@ -86,18 +83,9 @@
},
// 新朋友
toPending() {
// if (this.pendingCount > 0) {
uni.navigateTo({
url: '/pages/im/friends/pending'
});
// } else {
// uni.showToast({
// title: ` 暂无好友申请 ~ `,
// icon: "none",
// mask: true,
// duration: 3000
// })
// }
}
},
onNavigationBarButtonTap(e) {
@@ -171,5 +159,19 @@
font-size: 14px;
line-height: 24px;
background-color: #fff;
}
.no-lists {
padding-top: $padding * 3;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: $title-size-m;
color: $text-gray-m;
span {
padding-top: $padding;
}
}
</style>

View File

@@ -113,7 +113,6 @@
onLoad(e) {
this.targetId = e.targetId
getFriendInfo(e.targetId).then(res => {
console.log(res, "获取朋友的信息")
this.userInfo = res
// 获取到用户信息之后,去检查一下要不要更新
this.$store.dispatch('updateContact', res)
@@ -148,7 +147,7 @@
})
},
toPrivate() {
uni.redirectTo({
uni.navigateTo({
url: '/pages/im/private/chat?targetId=' + this.targetId
});
},
@@ -209,7 +208,7 @@
})
return
}
pedingFriend(this.targetId, 'message').then(res => {
pedingFriend(this.targetId, '').then(res => {
uni.showToast({
title: ` 申请成功,等待审核 `,
icon: 'none',
@@ -228,8 +227,9 @@
})
},
singleCall(e) {
uni.redirectTo({
url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type + '&isCall=true'
uni.navigateTo({
url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type +
'&isCall=true'
})
}
}

View File

@@ -6,8 +6,15 @@
:disabled="true" :show-action="false" />
</view>
</u-sticky>
<view v-for="(item, index) in pendings" :key="index">
<apply-cell :message="item.latestMessage" @success="getPendingList" />
<block v-if="pendings.length > 0">
<view v-for="(item, index) in pendings" :key="index">
<apply-cell :message="item.latestMessage" @success="getPendingList" />
</view>
</block>
<view class="no-lists" v-else>
<u-image class="cover" radius="4" width="400rpx" height="400rpx"
:src="require('@/static/imgs/no-friend.png')" :lazy-load="true" />
<span> 暂无好友申请 ~ </span>
</view>
</view>
</template>
@@ -15,23 +22,33 @@
<script>
import applyCell from '../components/friendApplyCell'
import im from '@/utils/im/index.js'
export default {
components: {
applyCell
},
data() {
return {
pendings: []
pendings: [],
bg: '#fff'
}
},
onLoad() {
onShow() {
this.getPendingList()
uni.$on('onContactNotification', this.getPendingList)
uni.$on('onNewContactPendings', this.getPendingList)
},
onUnload() {
uni.$off('onNewContactPendings')
},
methods: {
getPendingList() {
im.getPendingList((pendings) => {
getPendingList() {
im.getPendingList((pendings) => {
console.log(pendings,'res......')
if (pendings.length > 0) {
this.bg = '#f9f9f9'
} else {
this.bg = '#fff'
}
this.pendings = pendings
})
}
@@ -45,18 +62,18 @@
background: $window-color;
}
.no-lists {
padding-top: $padding * 3;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: $title-size-m;
color: $text-gray-m;
span {
padding-top: $padding;
}
.no-lists {
padding-top: $padding * 5;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: $title-size-m;
color: $text-gray-m;
span {
padding-top: $padding;
}
}
</style>

View File

@@ -16,8 +16,12 @@
createGroupAnnouncement,
getGroupAnnouncement
} from '@/apis/interfaces/im.js'
import onGroupDismiss from '@/utils/im/onGroupDismiss.js'
export default {
mixins: [
onGroupDismiss
],
data() {
return {
targetId: '',

View File

@@ -35,8 +35,12 @@
deleteGroupAnnouncement,
topGroupAnnouncement
} from '@/apis/interfaces/im.js'
import onGroupDismiss from '@/utils/im/onGroupDismiss.js'
export default {
mixins: [
onGroupDismiss
],
data() {
return {
targetId: '',
@@ -54,8 +58,8 @@
name: '置顶该公告',
disabled: false
}],
actionTitle: '请选择操作',
bg:'#fff'
actionTitle: '请选择操作',
bg: '#fff'
}
},
onLoad(e) {
@@ -84,11 +88,11 @@
methods: {
// 获取公告信息
initData() {
getGroupAnnouncements(this.targetId).then(res => {
if(res.length>0){
this.bg = '#f9f9f9'
}else{
this.bg = '#fff'
getGroupAnnouncements(this.targetId).then(res => {
if (res.length > 0) {
this.bg = '#f9f9f9'
} else {
this.bg = '#fff'
}
this.announcements = res
this.loading = false
@@ -183,8 +187,8 @@
.item {
background-color: #fff;
padding: $padding $padding + 10 10rpx $padding + 10;
border-bottom: $padding solid #f9f9f9;
border-bottom: $padding solid #f9f9f9;
.user {
display: flex;
@@ -193,7 +197,7 @@
align-items: center;
box-sizing: border-box;
font-size: $title-size-m;
color: $text-gray-m;
color: $text-gray-m;
padding: 10rpx;
.name {
@@ -214,8 +218,8 @@
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
line-height: 1.5;
border-bottom: solid 1rpx #F9F9F9;
line-height: 1.5;
border-bottom: solid 1rpx #F9F9F9;
padding-bottom: 20rpx;
span {

View File

@@ -20,8 +20,12 @@
joinGroupPre,
joinGroup
} from '@/apis/interfaces/im.js'
export default {
import onGroupDismiss from '@/utils/im/onGroupDismiss.js'
export default {
mixins: [
onGroupDismiss
],
data() {
return {
targetId: '',
@@ -45,7 +49,7 @@
mask: true,
duration: 3000
})
})
})
},
methods: {
toGroupChat() {

View File

@@ -21,8 +21,12 @@
import sentMessageBar from '../components/sentMessageBar'
import showMessageCell from '../components/showMessageCell'
import utils from '@/utils/index.js'
export default {
import onGroupDismiss from '@/utils/im/onGroupDismiss.js'
export default {
mixins: [
onGroupDismiss
],
components: {
sentMessageBar,
showMessageCell
@@ -59,11 +63,9 @@
})
// 获取历史消息列表
this.getMessageList()
// 监听收到本群的消息,追加消息
uni.$on('onReceiveMessage', (msg) => {
if (msg.targetId == this.targetId) {
this.getNewMessage()
}
// 监听消息
uni.$on('onReceiveMessage_' + this.targetId, (message) => {
this.getNewMessage()
})
uni.$on('onReceiptRequest', (msg) => {
if (msg.targetId == this.targetId) {
@@ -74,8 +76,17 @@
})
}
})
// 群已读回执
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)
@@ -92,6 +103,7 @@
})
},
onUnload() {
uni.$off('onReceiveMessage_' + this.targetId)
uni.$off('onRecallMessage')
uni.$off('onReceiptRequest')
uni.$off('onReceiptResponse')
@@ -127,9 +139,17 @@
true,
(messages) => {
console.log('获取消息列表', messages);
RongIMLib.sendReadReceiptResponse(3, this.targetId, messages, (res) => {
console.error('发送群聊已读回执成功', res);
})
const msgs = messages.filter(item => item.receivedStatus == 0)
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.scrollBottom()
})
@@ -144,10 +164,10 @@
im.setNotifyBadge()
}
}
},
onHide() {
// console.log(JSON.stringify(this.$refs))
this.$refs.voice.stopPlay()
},
onHide() {
// console.log(JSON.stringify(this.$refs))
// this.$refs.voice.stopPlay()
}
}
</script>

View File

@@ -1,13 +1,20 @@
<template>
<view class="group">
<view class="title"> 群聊 </view>
<view v-for="(item, index) in groups" :key="index" class="friend-flex" @click="toGroup(item.targetId)">
<u-avatar size="38" shape="square" :src="contact(item.targetId).portraitUrl" />
<view class="info">
<view class="name">{{ item.name }}</view>
<view class="group" :style="`background-color:${bg};`">
<block v-if="groups.length > 0">
<view class="title"> 群聊 </view>
<view v-for="(item, index) in groups" :key="index" class="friend-flex" @click="toGroup(item.targetId)">
<u-avatar size="38" shape="square" :src="contact(item.targetId).portraitUrl" />
<view class="info">
<view class="name">{{item.name}} <span class="total">共10人</span></view>
</view>
</view>
<view class="group-count"> {{groups.length}}个群聊 </view>
</block>
<view class="no-lists" v-else>
<u-image class="cover" radius="4" width="400rpx" height="400rpx"
:src="require('@/static/imgs/no-friend.png')" :lazy-load="true" />
<span>空空如也~</span>
</view>
<view class="group-count"> {{groups.length}}个群聊 </view>
<u-modal negativeTop="300" :show="createModal" title="创建群聊" showCancelButton @cancel="onHideModal"
@confirm="onCreateGroup">
<view class="slot-content">
@@ -28,7 +35,8 @@
return {
groups: [],
createModal: false,
groupName: ''
groupName: '',
bg: '#fff'
}
},
computed: {
@@ -41,13 +49,18 @@
onNavigationBarButtonTap() {
this.createModal = true
},
onLoad() {
onShow() {
this.initData()
uni.$on('onGroupDismiss', this.initData)
},
methods: {
initData() {
getMyGroups().then((res) => {
if (res.length > 0) {
this.bg = '#f9f9f9'
} else {
this.bg = '#fff'
}
this.groups = res
res.map(item => {
this.$store.dispatch('updateContact', item)
@@ -88,12 +101,14 @@
.group {
min-height: 100vh;
background-color: $window-color;
.title{
.title {
font-size: $title-size-m;
color: $text-gray-m;
padding: 10rpx $padding;
}
.group-count{
.group-count {
text-align: center;
font-size: $title-size;
color: $text-gray;
@@ -122,6 +137,11 @@
.name {
font-size: $title-size + 1;
color: #454545 !important;
}
.total{
color: $text-gray-m;
font-size: $title-size-m - 5;
padding-left: 10rpx;
}
.address {
@@ -130,4 +150,19 @@
}
}
}
.no-lists {
padding-top: $padding * 5;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: $title-size-m;
color: $text-gray-m;
span {
padding-top: $padding;
}
}
</style>

View File

@@ -9,8 +9,7 @@
<view slot="label" class="announcement-label "> {{announcement}} </view>
</u-cell>
<u-cell :border="false" class="u-border-bottom" isLink title="二维码" @click="showGroupQrCode" />
<u-cell :border="false" class="u-border-bottom" v-if="group.can_makesure" isLink title="群聊邀请确认"
@click="showGroupsSure" />
<u-cell :border="false" class="u-border-bottom" v-if="group.can_makesure" isLink title="群聊邀请确认" @click="showGroupsSure" />
<u-cell :border="false" class="u-border-bottom" title="聊天置顶">
<u-switch slot="value" size="20" v-model="isTop" activeColor="#34CE98" @change="setTop" />
</u-cell>
@@ -25,8 +24,7 @@
<u-cell :border="false" class="u-border-bottom" isLink title="修改群头像" @click="onGroupAvatar">
<u-avatar slot="value" size="25" shape="square" :src="group.cover" />
</u-cell>
<u-cell :border="false" class="u-border-bottom" isLink v-if="group.is_owner" title="准入方式" :value="joinType"
@click="onChangeJoinType" />
<u-cell :border="false" class="u-border-bottom" isLink v-if="group.is_owner" title="准入方式" :value="joinType" @click="onChangeJoinType" />
</u-cell-group>
<view class="cells actions" v-if="loaded">
@@ -35,21 +33,15 @@
<view class="action u-border-bottom" v-else @click="onQuite">删除并退出</view>
</view>
<u-modal negativeTop="300" :show="modalShow" title="修改群名称" showCancelButton @cancel="onHideModal"
@confirm="onChangeGroupName">
<view class="slot-content">
<u--input placeholder="群名称" border="surround" focus v-model="groupName" />
</view>
<u-modal negativeTop="300" :show="modalShow" title="修改群名称" showCancelButton @cancel="onHideModal" @confirm="onChangeGroupName">
<view class="slot-content"> <u--input placeholder="群名称" border="surround" focus v-model="groupName" maxlength="14" /> </view>
</u-modal>
<u-modal :show="qrCodeShow" :title="group.name" @confirm="qrCodeShow = false">
<view class="slot-content">
<uqrcode class="info-code-src" :size="198" :text="qrContent" />
</view>
<view class="slot-content"> <uqrcode class="info-code-src" :size="198" :text="qrContent" /> </view>
</u-modal>
<u-action-sheet @select="doAction" :actions="joinTypeMap" cancelText="取消" :show="showActions"
@close="showActions=false" />
<u-action-sheet @select="doAction" :actions="joinTypeMap" cancelText="取消" :show="showActions" @close="showActions=false" />
</view>
</template>
@@ -64,12 +56,16 @@
uploads
} from '@/apis/interfaces/uploading'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import groupUserList from '../components/groupUserList'
import groupUserList from '../components/groupUserList'
import onGroupDismiss from '@/utils/im/onGroupDismiss.js'
export default {
components: {
groupUserList
},
},
mixins: [
onGroupDismiss
],
data() {
return {
targetId: '',
@@ -133,7 +129,6 @@
return item.key == res.join_type
})[0].name
}).catch(err => {
console.log('getGroupInfo ERR', err);
uni.showToast({
icon: 'none',
title: '群不存在'

View File

@@ -8,8 +8,9 @@
<u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98">
<u-checkbox-group v-if="friends.length > 0" v-model="checkboxValue" placement="column">
<u-index-item v-for="(item, fkey) in friends" :key="fkey">
<u-index-anchor :text="indexs[fkey]" v-if="indexs[fkey]" bgColor="#f9f9f9f" height="20" size="12"
color="#666" style="border:none !important;padding: 10rpx 30rpx;background-color: #f9f9f9 !important;" />
<u-index-anchor :text="indexs[fkey]" v-if="indexs[fkey]" bgColor="#f9f9f9f" height="20"
size="12" color="#666"
style="border:none !important;padding: 10rpx 30rpx;background-color: #f9f9f9 !important;" />
<view v-for="(friendItem, index) in item" :key="index" class="friend-flex"
@click="addContact(friendItem.targetId)">
<u-checkbox :name="friendItem.targetId" shape="circle" activeColor="#34ce98"
@@ -44,10 +45,13 @@
getGroupUsers
} from '@/apis/interfaces/im';
import utils from '@/utils/index.js'
import onGroupDismiss from '@/utils/im/onGroupDismiss.js'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
export default {
mixins: [
onGroupDismiss
],
data() {
return {
searchTxt: '',
@@ -80,11 +84,11 @@
})
return resList
})
this.indexs = this.orignalIndexs.map((t, i) => {
if (this.friends[i].length > 0) {
return t
}
})
this.indexs = this.orignalIndexs.map((t, i) => {
if (this.friends[i].length > 0) {
return t
}
})
} else {
this.friends = this.orignalFriends
this.indexs = this.orignalIndexs
@@ -101,7 +105,7 @@
this.orignalIndexs = res.indexList
})
getGroupUsers(this.targetId).then(res => {
res.map(res => {
res.map(res => {
console.log(res)
this.checkboxValue.push(String(res.targetId))
this.selectValue.push(String(res.targetId))
@@ -122,17 +126,17 @@
}
},
onInvite() {
console.log(this.checkboxValue,'userIds.....')
console.log(this.selectValue,'userIds.....')
let userIds = []
this.checkboxValue.filter(item=>{
if(!utils.inArray(item, this.selectValue)){
userIds.push(item)
}
})
onInvite() {
console.log(this.checkboxValue, 'userIds.....')
console.log(this.selectValue, 'userIds.....')
let userIds = []
this.checkboxValue.filter(item => {
if (!utils.inArray(item, this.selectValue)) {
userIds.push(item)
}
})
// console.log(userIds)
inviteGroupUser(this.targetId, this.checkboxValue,userIds).then(res => {
inviteGroupUser(this.targetId, this.checkboxValue, userIds).then(res => {
uni.navigateBack({
delta: 1,
animationType: 'pop-out',

View File

@@ -3,7 +3,7 @@
<view class="reviewed">
<block v-if="pendings.length > 0">
<view class="reviewed-item" v-for="(item, index) in pendings" :key="index">
<u-avatar class="avatar"
<u-avatar class="avatar"
:src="JSON.parse(item.content.extra).portraitUrl || require('@/static/user/cover.png')"
shape="square" size="46" />
<view style="flex:1;" v-if="item.content.operation == 'GroupPending'">
@@ -34,9 +34,12 @@
} from "@/apis/interfaces/im.js"
import im from '@/utils/im/message.js'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import onGroupDismiss from '@/utils/im/onGroupDismiss.js'
export default {
mixins: [
onGroupDismiss
],
data() {
return {
targetId: '',
@@ -86,21 +89,21 @@
// icon: 'none',
// mask: true,
// duration: 2000
// })
RongIMLib.deleteMessagesByIds([latestMessageId], ({
code
}) => {
console.log('code', code)
if (code == 0) {
uni.showToast({
title:err.message,
icon: 'none',
mask: true,
duration: 2000
})
this.getList()
uni.$emit('groupInvitedUser')
}
// })
RongIMLib.deleteMessagesByIds([latestMessageId], ({
code
}) => {
console.log('code', code)
if (code == 0) {
uni.showToast({
title: err.message,
icon: 'none',
mask: true,
duration: 2000
})
this.getList()
uni.$emit('groupInvitedUser')
}
})
})
// 直接调用通过或拒绝的接口
@@ -153,6 +156,7 @@
}
}
.no-lists {
padding-top: $padding * 5;
display: flex;

View File

@@ -4,7 +4,12 @@
<script>
import groupUserList from '../components/groupUserList'
import onGroupDismiss from '@/utils/im/onGroupDismiss.js'
export default {
mixins: [
onGroupDismiss
],
components: {
groupUserList
},

View File

@@ -57,24 +57,28 @@
// 好友申请数量
this.checkNewFriendPending()
// 监听新的好友申请
uni.$on('onContactNotification', () => {
this.checkNewFriendPending()
})
uni.$on('onNewContactConversation', this.checkNewFriendPending)
},
onShow() {
if (this.$store.state.token !== '') {
this.getConversationList()
}
uni.$on('onConnectionStatusChange', (status) => {
this.connection = status
})
// 监听新消息
uni.$on('onReceiveMessage', (msg) => {
this.getConversationList()
})
// 监听网络状态变化
uni.$on('onConnectionStatusChange', (status) => {
this.connection = status
if (status == 0) {
this.getConversationList()
}
})
},
onHide() {
// 页面隐藏的时候,不监听了,性能可能会好一点
uni.$off('onReceiveMessage')
uni.$off('onConnectionStatusChange')
},
methods: {
checkNewFriendPending() {

View File

@@ -150,7 +150,7 @@
} else {
IMLib.insertIncomingMessage(1, targetId, targetId, sentStatus, messageContent, sentTime)
}
uni.$emit('onReceiveMessage', {
uni.$emit('onReceiveMessage_' + this.targetId, {
targetId: this.targetId
})
},

View File

@@ -4,8 +4,8 @@
<!-- chat -->
<view class="body">
<view class="scroll">
<view class="cell" v-for="(message, index) in messages" :key="index">
<show-message-cell :message="message" />
<view class="cell" v-for="(message, index) in messages" :key="index">
<show-message-cell :message="message" />
</view>
</view>
</view>
@@ -60,6 +60,10 @@
})
// 获取消息列表
this.getMessageList()
// 监听新消息
uni.$on('onReceiveMessage_' + this.targetId, (message) => {
this.getNewMessage()
})
// 监听消息已读状态
uni.$on('onReadReceiptReceived', (data) => {
if (data.targetId == this.targetId) {
@@ -72,14 +76,21 @@
})
}
})
// 监听收到新消息,判断是否是当前会话,更新会话内容
uni.$on('onReceiveMessage', (msg) => {
if (msg.targetId == this.targetId) {
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() {
uni.$off('onReceiveMessage_' + this.targetId)
uni.$off('onRecallMessage')
uni.$off('onReadReceiptReceived')
},
methods: {