Compare commits

55 Commits

Author SHA1 Message Date
唐明明
da6b60131d merge 2022-02-24 14:19:39 +08:00
唐明明
ae0fa1bde3 删除 'pages/im/.DS_Store' 2022-02-24 14:19:22 +08:00
唐明明
8b888e250f 优化语音录制取消功能 2022-02-24 14:15:59 +08:00
4888cf2ad1 消息撤回修复 2022-02-24 13:19:59 +08:00
0eb6be37be 好友关系解除,从会话页返回主页 2022-02-24 13:03:41 +08:00
831776f7dd 删除好友的时候,对方也删除会话 2022-02-24 12:10:06 +08:00
519caab9e5 ... 2022-02-24 11:55:00 +08:00
aead0f5ed1 .. 2022-02-24 11:53:19 +08:00
fb6f5697c7 进入到群会话的时候,更新群信息 2022-02-24 11:52:24 +08:00
4760adc504 个人中信头像可预览 2022-02-24 11:50:33 +08:00
b8291a4222 长按群主,不展示菜单 2022-02-24 11:34:28 +08:00
唐明明
33eacb2a5b merge 2022-02-24 11:28:37 +08:00
唐明明
5c5445d630 merge 2022-02-24 11:27:20 +08:00
056224881e 移除成员 2022-02-24 11:27:06 +08:00
唐明明
f77a91eafe 删除 'pages/im/.DS_Store' 2022-02-24 11:26:14 +08:00
唐明明
54cf21f211 语音播放组件新增取消发送,试听 2022-02-24 11:21:00 +08:00
唐明明
da78a3ac11 merge 2022-02-24 11:19:02 +08:00
7c4874a5e1 marge 2022-02-24 11:12:13 +08:00
6f508d906d marge 2022-02-24 11:11:38 +08:00
08ffc0fa53 修复会话列表弹出层,隐藏的问题 2022-02-24 11:06:11 +08:00
e72d6b3a91 删除公告,消息撤回优化 2022-02-24 10:56:16 +08:00
8b7a259c00 merge 2022-02-24 10:18:11 +08:00
4a31ba32f7 查看消息调准 2022-02-24 10:17:54 +08:00
32e3e0ef30 组件整理 2022-02-24 10:06:33 +08:00
a7dccde63a 组件合并,群公告指向修复 2022-02-24 10:01:22 +08:00
9c7a8c8ee1 聊天样式调整 2022-02-24 09:48:57 +08:00
18173995ab merge 2022-02-24 09:43:32 +08:00
07f707f94a voice-bug 2022-02-24 09:38:11 +08:00
d1f5f75355 ... 2022-02-24 09:36:18 +08:00
2d97294c9d 优化搜索 2022-02-24 09:35:37 +08:00
78d4611fb2 mixins优化 2022-02-24 09:28:59 +08:00
358372cdba 调整目录结构 2022-02-24 09:25:35 +08:00
ef785ab05f ... 2022-02-24 09:15:24 +08:00
8f3c741ad1 同步数据 2022-02-24 09:14:30 +08:00
f4e44de777 im-MIXINS 2022-02-23 17:28:42 +08:00
853c4611ef ... 2022-02-23 17:09:26 +08:00
1d648f2dc1 ... 2022-02-23 17:08:28 +08:00
d9748d0827 图片预览优化 2022-02-23 17:07:14 +08:00
103679c372 好友申请通知优化 2022-02-23 17:01:26 +08:00
唐明明
8c32758e37 merge 2022-02-23 16:50:38 +08:00
唐明明
29757fadeb merge 2022-02-23 16:50:26 +08:00
8a8e55600f uview新版本,search高度修复 2022-02-23 16:49:15 +08:00
768edb8e87 format 2022-02-23 16:38:14 +08:00
2ce4bb827f 消息免打扰消息同步 2022-02-23 16:35:33 +08:00
f68e5fa1fd 同步 2022-02-23 16:31:14 +08:00
8bb646a520 我的群聊+人数+默认头像四个小人 2022-02-23 16:30:35 +08:00
20317cc1df 群公告的群内提醒,链接跳转 2022-02-23 16:29:06 +08:00
a5bd5a898c 资料修改的事件通知 2022-02-23 16:06:41 +08:00
唐明明
00836ac209 合并 2022-02-23 15:54:27 +08:00
c840e9ee6b 限制群名称长度14 2022-02-23 15:46:02 +08:00
18f0ee457c 同步 2022-02-23 15:32:31 +08:00
a12d8a2c40 申请加好友认证信息优化,好友列表无好友状态处理 2022-02-23 15:30:09 +08:00
1407d677de 群解散时,无论在群组中的哪个页面,都退回到会话列表页面 2022-02-23 14:13:38 +08:00
8b10fd95fe Merge branch 'master' of https://git.yuzhankeji.cn/TmOct5/ZhHealth 2022-02-23 11:36:23 +08:00
3b3dda18ca 图片预览,版本更新的版本号调整 2022-02-23 11:36:18 +08:00
47 changed files with 1065 additions and 721 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -12,7 +12,7 @@
// 获取系统版本号 // 获取系统版本号
getVersions({ getVersions({
platform: plus.os.name, platform: plus.os.name,
version: plus.runtime.versionCode version: plus.runtime.version
}).then(res => { }).then(res => {
if (res.update) { if (res.update) {
uni.showModal({ uni.showModal({

View File

@@ -323,6 +323,7 @@ export {
dismissGroup, dismissGroup,
inviteGroupUser, inviteGroupUser,
removeGroupUser, removeGroupUser,
transferGroupOwner,
setGroupAdmin, setGroupAdmin,
removeGroupAdmin, removeGroupAdmin,
groupMakeSure, // 通过审核 groupMakeSure, // 通过审核

View File

@@ -2,8 +2,8 @@
"name" : "ZH-HEALTH", "name" : "ZH-HEALTH",
"appid" : "__UNI__C29473D", "appid" : "__UNI__C29473D",
"description" : "ZH-HEALTH您手上的健康管理专家", "description" : "ZH-HEALTH您手上的健康管理专家",
"versionName" : "1.0.13", "versionName" : "1.0.16",
"versionCode" : 113, "versionCode" : 100,
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus" : {

BIN
pages/.DS_Store vendored

Binary file not shown.

View File

@@ -6,8 +6,10 @@
</view> </view>
<view class="content"> <view class="content">
<view class="header"> <view class="header">
<view class="name">{{ contact(item.targetId).name }} <text v-if="item.conversationType === 3" <view class="name">
class='qun'>[]</text></view> {{ contact(item.targetId).name }}
<text v-if="item.conversationType === 3" class='group'>[]</text>
</view>
<view class="time">{{ item.sentTime|timeCustomCN }}</view> <view class="time">{{ item.sentTime|timeCustomCN }}</view>
</view> </view>
<message-preview class="preview" :msg="item.latestMessage" :draft="item.draft" <message-preview class="preview" :msg="item.latestMessage" :draft="item.draft"
@@ -19,8 +21,12 @@
<script> <script>
import messagePreview from './messagePreview' import messagePreview from './messagePreview'
import utils from '@/utils/index.js' import utils from '@/utils/index.js'
import imBase from '../../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
props: { props: {
item: { item: {
type: Object, type: Object,
@@ -29,21 +35,6 @@
} }
} }
}, },
data() {
return {
avatarRpx: 84
}
},
computed: {
avatarSize() {
return utils.rpx2px(this.avatarRpx)
},
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
}
},
components: { components: {
messagePreview messagePreview
} }
@@ -80,10 +71,8 @@
.name { .name {
font-size: $title-size + 2; font-size: $title-size + 2;
color: #454545; color: #454545;
display: flex;
align-items: center;
.qun { .group {
color: $main-color; color: $main-color;
font-size: $title-size-m - 4; font-size: $title-size-m - 4;
margin-left: 4px; margin-left: 4px;

View File

@@ -1,23 +1,24 @@
<template> <template>
<view> <view>
<view v-for="(item, index) in conversations" :key="index" :class="['message', { 'is-top': item.isTop, 'is-active': pickedItem.targetId == item.targetId }]" <view class="shade" @click="hidePop" @touchmove="hidePop" v-show="showPop">
:data-item="item" @longpress="onLongPress" @click="toDetail(item)">
<message-cell :item="item" />
</view>
<view class="shade" @click="hidePop" v-show="showPop">
<view class="pop" :style="popStyle" :class="{'show':showPop}"> <view class="pop" :style="popStyle" :class="{'show':showPop}">
<view v-for="(item, index) in popButton" :key="index" @click="pickerMenu" :data-index="index"> <view v-for="(item, index) in popButton" :key="index" @click="pickerMenu" :data-index="index">
{{item}} {{item}}
</view> </view>
</view> </view>
</view> </view>
<view v-for="(item, index) in conversations" :key="index"
:class="['message', { 'is-top': item.isTop, 'is-active': pickedItem.targetId == item.targetId }]"
:data-item="item" @longpress="onLongPress" @click="toDetail(item)">
<message-cell :item="item" />
</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 im from '@/utils/im/index.js' import im from '@/utils/im/index.js'
import messageCell from './messageCell' import messageCell from './conversation/messageCell'
export default { export default {
props: { props: {
@@ -142,6 +143,7 @@
position: fixed; position: fixed;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 999;
.pop { .pop {
position: fixed; position: fixed;

View File

@@ -1,7 +1,7 @@
<template> <template>
<view class="apply--cell"> <view class="apply--cell">
<view class="avatar"> <view class="avatar">
<u-avatar :src="user.portraitUrl || require('@/static/user/cover.png')" shape="square" size="46" /> <u-avatar :src="user.portraitUrl || require('@/static/user/cover.png')" shape="square" :size="avatarSize" />
</view> </view>
<view class="info"> <view class="info">
<view class="name"> {{ user.name }}</view> <view class="name"> {{ user.name }}</view>
@@ -20,8 +20,12 @@
resolveFriend, resolveFriend,
rejectFriend rejectFriend
} from '@/apis/interfaces/im.js' } from '@/apis/interfaces/im.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
props: { props: {
message: { message: {
type: Object, type: Object,
@@ -36,7 +40,6 @@
methods: { methods: {
resolve() { resolve() {
resolveFriend(this.message.sourceUserId).then(res => { resolveFriend(this.message.sourceUserId).then(res => {
this.clearMessages()
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
title: '通过好友申请' title: '通过好友申请'
@@ -47,6 +50,8 @@
icon: 'none', icon: 'none',
title: err.message title: err.message
}) })
}).finally(() => {
this.clearMessages()
}) })
}, },
reject() { reject() {
@@ -70,7 +75,9 @@
clearMessages() { clearMessages() {
RongIMLib.deleteMessages(RongIMLib.ConversationType.SYSTEM, this.message.sourceUserId) RongIMLib.deleteMessages(RongIMLib.ConversationType.SYSTEM, this.message.sourceUserId)
this.$emit('success') this.$emit('success')
uni.$emit('onContactNotification') uni.$emit('onNewContactConversation')
uni.$emit('onNewContactFriends')
uni.$emit('onNewContactPendings')
} }
} }
} }

View File

@@ -3,7 +3,7 @@
<block v-for="(item, index) in lists" v-if="lists.length > 0" :key="index"> <block v-for="(item, index) in lists" v-if="lists.length > 0" :key="index">
<view class="lists"> <view class="lists">
<view class="" style="width: 100rpx;height: 100rpx;"> <view class="" style="width: 100rpx;height: 100rpx;">
<u-avatar :src="JSON.parse(item.latestMessage.extra).portraitUrl" shape="square" size="44" /> <u-avatar :src="JSON.parse(item.latestMessage.extra).portraitUrl" shape="square" :size="avatarSize" />
</view> </view>
<view class="right"> <view class="right">
<view class="title"> <view class="title">
@@ -14,7 +14,8 @@
<span v-if="isAgree" @click="action('agree', item)">通过</span> <span v-if="isAgree" @click="action('agree', item)">通过</span>
<span v-if="isAgree" @click="action('reject', item)">拒绝</span> <span v-if="isAgree" @click="action('reject', item)">拒绝</span>
<span v-if="isApply && !item.is_friend" @click="action('apply', item)">查看</span> <span v-if="isApply && !item.is_friend" @click="action('apply', item)">查看</span>
<span class="isFri" v-if="isApply && item.is_friend" @click="action('isFriend', item)">已是好友</span> <span class="isFri" v-if="isApply && item.is_friend"
@click="action('isFriend', item)">已是好友</span>
</view> </view>
</view> </view>
</view> </view>
@@ -23,104 +24,124 @@
</template> </template>
<script> <script>
export default { import imBase from '../mixins/imBase.js'
name: 'friend-apply-reject-agree',
props: { export default {
lists: { mixins:[
type: Array, imBase
default: [] ],
}, name: 'friend-apply-reject-agree',
isAgree: { props: {
type: Boolean, lists: {
default: false type: Array,
}, default: []
isReject: { },
type: Boolean, isAgree: {
default: false type: Boolean,
}, default: false
isApply: { },
type: Boolean, isReject: {
default: false type: Boolean,
} default: false
}, },
created() { isApply: {
console.log(this.lists); type: Boolean,
}, default: false
methods: { }
action(type, item) { },
if (type === 'isFriend') { created() {
// ,后期可以跳转到信息介绍页面,先留在这里 console.log(this.lists);
return uni.showToast({ title: '已是好友,无需重复添加', icon: 'none', duration:2000}); },
methods: {
action(type, item) {
if (type === 'isFriend') {
// ,后期可以跳转到信息介绍页面,先留在这里
return uni.showToast({
title: '已是好友,无需重复添加',
icon: 'none',
duration: 2000
});
}
this.$emit('action', {
type,
item
});
} }
this.$emit('action', { type, item });
} }
} };
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.lists { .lists {
padding: 0 $padding; padding: 0 $padding;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
font-size: $title-size;
color: $text-gray;
.cover {
background-color: #ffffff;
}
.right {
width: 570rpx;
margin-left: $margin - 10;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-between; justify-content: flex-start;
padding: $padding 0; box-sizing: border-box;
border-bottom: solid 1rpx #f9f9f9; font-size: $title-size;
.title { color: $text-gray;
width: 370rpx;
.name { .cover {
width: 100%; background-color: #ffffff;
color: $text-color;
font-size: $title-size + 2;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.des {
width: 100%;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: $title-size-m;
margin-top: $margin - 10;
color: $text-gray-m;
}
} }
.agress-btn {
.right {
width: 570rpx;
margin-left: $margin - 10;
display: flex; display: flex;
color: #fff; flex-direction: row;
font-size: $title-size-m; align-items: center;
span { justify-content: space-between;
display: inline-block; padding: $padding 0;
padding: 6rpx 14rpx; border-bottom: solid 1rpx #f9f9f9;
background-color: $text-price;
border-radius: 10rpx; .title {
width: 370rpx;
.name {
width: 100%;
color: $text-color;
font-size: $title-size + 2;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.des {
width: 100%;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: $title-size-m;
margin-top: $margin - 10;
color: $text-gray-m;
}
} }
span:nth-child(1) {
background-color: $main-color; .agress-btn {
margin-right: 10rpx; display: flex;
} color: #fff;
.isFri { font-size: $title-size-m;
background-color: #f9f9f9 !important;
color: #666; span {
display: inline-block;
padding: 6rpx 14rpx;
background-color: $text-price;
border-radius: 10rpx;
}
span:nth-child(1) {
background-color: $main-color;
margin-right: 10rpx;
}
.isFri {
background-color: #f9f9f9 !important;
color: #666;
}
} }
} }
} }
}
</style> </style>

View File

@@ -3,7 +3,7 @@
<block v-for="(item, index) in lists" v-if="lists.length > 0" :key="index"> <block v-for="(item, index) in lists" v-if="lists.length > 0" :key="index">
<view class="lists"> <view class="lists">
<view class="" style="width: 100rpx;height: 100rpx;"> <view class="" style="width: 100rpx;height: 100rpx;">
<u-avatar :src="item.portraitUrl || require('@/static/user/cover.png')" shape="square" size="44" /> <u-avatar :src="item.portraitUrl || require('@/static/user/cover.png')" shape="square" :size="avatarSize" />
</view> </view>
<view class="right"> <view class="right">
<view class="title"> <view class="title">
@@ -21,7 +21,12 @@
</template> </template>
<script> <script>
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
name: 'friend-apply-reject-agree', name: 'friend-apply-reject-agree',
props: { props: {
lists: { lists: {

View File

@@ -38,8 +38,12 @@
transferGroupOwner transferGroupOwner
} from '@/apis/interfaces/im.js' } from '@/apis/interfaces/im.js'
import utils from '@/utils/index.js' import utils from '@/utils/index.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
props: { props: {
targetId: { targetId: {
type: String, type: String,
@@ -55,35 +59,26 @@
users: [], users: [],
isOwner: false, isOwner: false,
isAdmin: false, isAdmin: false,
canInvite:false,// 是否可以开启邀请 canInvite: false, // 是否可以开启邀请
adminUid: 0, adminUid: 0,
members: 0, members: 0,
actionShow: false, actionShow: false,
actionMap: [], actionMap: [],
actionTitle: '', actionTitle: '',
currentUser: {}, currentUser: {},
avatarSize: 45, avatarSize: 40,
labelSize: 14, labelSize: 14,
iconSize: 14 iconSize: 14
}
},
computed: {
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
} }
}, },
created() { created() {
this.avatarSize = utils.rpx2px(90) this.avatarSize = utils.rpx2px(84)
this.labelSize = utils.rpx2px(24) this.labelSize = utils.rpx2px(24)
this.iconSize = utils.rpx2px(26) this.iconSize = utils.rpx2px(26)
}, },
mounted() { mounted() {
this.initGroupInfo() this.initGroupInfo()
getGroupUsers(this.targetId, this.count).then(res => { getGroupUsers(this.targetId, this.count).then(res => {
console.log("res..",res)
this.users = res this.users = res
res.map(item => { res.map(item => {
this.$store.dispatch('updateContact', item) this.$store.dispatch('updateContact', item)
@@ -110,6 +105,9 @@
this.actionShow = false this.actionShow = false
}, },
showAction(item) { showAction(item) {
if (item.is_admin == 2) {
return
}
this.currentUser = item this.currentUser = item
this.actionTitle = item.name this.actionTitle = item.name
// 只有管理员以上才会弹窗 // 只有管理员以上才会弹窗
@@ -278,7 +276,6 @@
border-radius: 0 8rpx 0 0; border-radius: 0 8rpx 0 0;
position: relative; position: relative;
width: 84rpx; width: 84rpx;
height: 84rpx;
overflow: hidden; overflow: hidden;
.admin { .admin {

View File

@@ -33,9 +33,12 @@
<script> <script>
import im from '@/utils/im/index.js' import im from '@/utils/im/index.js'
import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index' import imBase from '../../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
data() { data() {
return { return {
callActions: [{ callActions: [{
@@ -64,15 +67,11 @@
default: '' default: ''
} }
}, },
computed: {
sender() {
return this.$store.getters.sender
}
},
methods: { methods: {
singleCall(e) { singleCall(e) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type + '&isCall=true' url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type +
'&isCall=true'
}) })
}, },
onPopupsItem(type) { onPopupsItem(type) {
@@ -144,6 +143,7 @@
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
flex-direction: row; flex-direction: row;
.item { .item {
width: 150rpx; width: 150rpx;
margin: 15rpx; margin: 15rpx;

View File

@@ -8,8 +8,12 @@
<script> <script>
import im from '@/utils/im/index.js' import im from '@/utils/im/index.js'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import imBase from '../../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
props: { props: {
conversationType: { conversationType: {
type: Number, type: Number,
@@ -23,9 +27,6 @@
computed: { computed: {
disabled() { disabled() {
return this.inputTxt.length === 0 return this.inputTxt.length === 0
},
sender() {
return this.$store.getters.sender
} }
}, },
mounted() { mounted() {
@@ -71,11 +72,10 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
.input { .input {
background: #F3F6FB; background: #F3F6FB;
height: 70rpx; height: 70rpx;
width: 500rpx; width: 460rpx;
border-radius: 10rpx; border-radius: 10rpx;
margin-right: 15rpx; margin-right: 15rpx;
padding: 0 20rpx; padding: 0 20rpx;

View File

@@ -0,0 +1,276 @@
<template>
<view class="send--voice">
<view class="voice" hover-class="chat-hover" @touchstart="startRecord" @touchend="stopRecord" @touchmove="touchmove">
<text class="button">按住说话</text>
</view>
<!-- 录音层 -->
<view class="lay" v-if="showRecordTip">
<view class="lay-header">
<view class="modal">
<image class="icon" src="@/static/icon/record-icon.png" mode="widthFix"></image>
<text class="text">录音中 {{recordTime}} s</text>
</view>
</view>
<view class="lay-toast">上滑取消</view>
<view class="lay-footer">
<image class="lay-footer-icon videoFlicker" src="@/static/icon/audio_green.png" mode="widthFix"></image>
<view class="lay-footer-text">松开发送</view>
</view>
</view>
</view>
</template>
<script>
import im from '@/utils/im/index.js'
import permision from '@/utils/permission.js'
import imBase from '../../mixins/imBase.js'
export default {
mixins: [
imBase
],
props: {
conversationType: {
type: Number,
default: 0
},
targetId: {
type: String,
default: ''
}
},
data() {
return {
showRecordTip: false,
recordTime: 60,
interval: 0,
maxRecordTime: 60,
recorderManager: null,
mp3AudioSrc: null,
isBetaPlay: false, // 暂时无用
startOffsetTop: 0
}
},
computed: {
sender() {
return this.$store.getters.sender
}
},
created() {
this.recorderManager = uni.getRecorderManager()
},
methods: {
// 检查安卓录制权限
async getAndroidPermission() {
return await permision.requestAndroidPermission('android.permission.RECORD_AUDIO')
},
// 录制语音消息
startRecord(e) {
this.getAndroidPermission().then(code => {
switch (code) {
case 1:
this.showConfirm = true
this.startOffsetTop = e.target.offsetTop
this.showRecordTip = true
this.recorderManager.start()
this.interval = setInterval(() => {
this.recordTime -= 1
if (this.recordTime === 0) {
this.stopRecord()
}
}, 1000)
break;
case 0:
uni.showToast({
title: '暂无麦克风权限,请前往应用设置开启麦克风',
icon: 'none'
})
break;
case -1:
uni.showToast({
title: '应用权限错误',
icon: 'none'
})
break;
}
})
},
// 结束录音
stopRecord(e) {
if (!this.showRecordTip) return
// 延迟500毫秒结束录音
setTimeout(()=> {
this.recorderManager.stop()
clearInterval(this.interval)
// 监听录音结束
this.recorderManager.onStop(res => {
this.mp3AudioSrc = res.tempFilePath
this.showRecordTip = false
this.senVoice()
})
},500)
},
// 发送语音消息
senVoice(){
if(this.mp3AudioSrc === null) {
uni.showToast({
title: '发送失败, 暂无音频信息',
icon : 'none'
})
return
}
im.sentVoice(this.conversationType, this.targetId, this.mp3AudioSrc, (this.maxRecordTime -
this.recordTime), this.sender, () => {
this.recordTime = this.maxRecordTime
this.mp3AudioSrc = null
setTimeout(() => {
this.$emit('success')
}, 500)
})
},
// 移动按钮
touchmove(e){
if(this.startOffsetTop - e.changedTouches[0].pageY > 100){
if(this.showRecordTip){
this.showRecordTip = false
clearInterval(this.interval)
this.recorderManager.stop()
this.recordTime = this.maxRecordTime
this.mp3AudioSrc = null
return
}
}
},
// 试听语音
startPlay() {
let betaAudio = uni.createInnerAudioContext()
betaAudio.src = this.mp3AudioSrc;
// 在播放中
if(this.isBetaPlay){
betaAudio.stop()
betaAudio.onStop(() => {
this.isBetaPlay = false;
betaAudio.destroy()
})
return
}
// 监听音频播放中
betaAudio.play()
betaAudio.onPlay(() => {
this.isBetaPlay = true;
})
// 监听音频结束
betaAudio.onEnded(() => {
this.isBetaPlay = false;
betaAudio.destroy()
})
}
}
}
</script>
<style>
@keyframes playFlicker {
0% {
opacity: 1;
}
50% {
opacity: .5;
}
100% {
opacity: 1;
}
}
.videoFlicker {
animation: playFlicker 1s infinite;
}
</style>
<style scoped lang="scss">
.send--voice {
.voice {
display: flex;
background: $window-color;
height: 70rpx;
line-height: 70rpx;
justify-content: center;
align-items: center;
width: 500rpx;
border-radius: 10rpx;
margin-right: 15rpx;
.button {
font-size: 30rpx;
color: #333;
}
}
.lay{
position: absolute;
left: 0;
top: 0;
z-index: 9;
background: rgba($color: #000000, $alpha: .5);
height: 100vh;
width: 100vw;
box-sizing: border-box;
.lay-header{
height: calc(100vh - 140px);
display: flex;
justify-content: center;
align-items: center;
.modal {
display: flex;
background: rgba(0, 0, 0, .6);
position: fixed;
height: 200rpx;
width: 300rpx;
border-radius: 10rpx;
z-index: 99;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
width: 88rpx;
height: 88rpx;
}
.text {
font-size: 28rpx;
color: #FFFFFF;
}
}
}
.lay-toast{
text-align: center;
color: rgba($color: #fff, $alpha: .8);
font-size: 28rpx;
}
.lay-footer{
background-color: white;
height: 100px;
border-radius: 50% 50% 0 0;
position: absolute;
bottom: 0;
left: 0;
right: 0;
text-align: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.lay-footer-icon{
width: 58rpx;
height: 58rpx;
}
.lay-footer-text{
line-height: 40rpx;
color: gray;
font-size: 28rpx;
}
}
}
}
</style>

View File

@@ -16,9 +16,9 @@
</template> </template>
<script> <script>
import sentText from './sentText' import sentText from './sent/sentText'
import sentVoice from './sentVoice' import sentVoice from './sent/sentVoice'
import sentPopups from './sentPopups' import sentPopups from './sent/sentPopups'
export default { export default {
props: { props: {

View File

@@ -1,143 +0,0 @@
<template>
<view class="send--voice">
<view class="voice" hover-class="chat-hover" @touchstart="startRecord" @touchend="stopRecord">
<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>
</template>
<script>
import im from '@/utils/im/index.js'
import permision from '@/utils/permission.js'
export default {
props: {
conversationType: {
type: Number,
default: 0
},
targetId: {
type: String,
default: ''
}
},
data() {
return {
showRecordTip: false,
recordTime: 60,
interval: 0,
maxRecordTime: 60,
recorderManager: null
}
},
computed: {
sender() {
return this.$store.getters.sender
}
},
created() {
this.recorderManager = uni.getRecorderManager()
},
methods: {
// 检查安卓录制权限
async getAndroidPermission() {
return await permision.requestAndroidPermission('android.permission.RECORD_AUDIO')
},
// 录制语音消息
startRecord() {
this.getAndroidPermission().then(code => {
switch (code) {
case 1:
this.showRecordTip = true
this.recorderManager.start()
this.interval = setInterval(() => {
this.recordTime -= 1
if (this.recordTime === 0) {
this.stopRecord()
}
}, 1000)
break;
case 0:
uni.showToast({
title: '暂无麦克风权限,请前往应用设置开启麦克风',
icon: 'none'
})
break;
case -1:
uni.showToast({
title: '应用权限错误',
icon: 'none'
})
break;
}
})
},
// 结束录音
stopRecord(e) {
if (!this.showRecordTip) return
this.recorderManager.stop()
clearInterval(this.interval)
// 监听录音结束
this.recorderManager.onStop(res => {
im.sentVoice(this.conversationType, this.targetId, res.tempFilePath, (this.maxRecordTime -
this.recordTime), this.sender, () => {
setTimeout(() => {
this.$emit('success')
}, 500)
})
this.recordTime = this.maxRecordTime
this.showRecordTip = false
})
},
}
}
</script>
<style scoped lang="scss">
.send--voice {
.voice {
display: flex;
background: $window-color;
height: 70rpx;
line-height: 70rpx;
justify-content: center;
align-items: center;
width: 500rpx;
border-radius: 10rpx;
margin-right: 15rpx;
.button {
font-size: 30rpx;
color: #333;
}
}
.modal {
display: flex;
background: rgba(0, 0, 0, .6);
position: fixed;
height: 200rpx;
width: 300rpx;
border-radius: 10rpx;
z-index: 99;
top: 550rpx;
left: 225rpx;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
width: 88rpx;
height: 88rpx;
}
.text {
font-size: 28rpx;
color: #FFFFFF;
}
}
}
</style>

View File

@@ -11,8 +11,12 @@
<script> <script>
import utils from '@/utils/index.js' import utils from '@/utils/index.js'
import moment from 'moment' import moment from 'moment'
import imBase from '../../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
name: 'showText', name: 'showText',
props: { props: {
message: { message: {
@@ -38,11 +42,6 @@
isRemote() { isRemote() {
return this.message.messageDirection == 2 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) {
return moment.utc(this.message.duration * 1000).format('HH:mm:ss') return moment.utc(this.message.duration * 1000).format('HH:mm:ss')

View File

@@ -14,8 +14,12 @@
<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' import messageState from './messageState'
import imBase from '../../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
name: 'showImage', name: 'showImage',
props: { props: {
message: { message: {
@@ -38,51 +42,30 @@
}, },
content() { content() {
return this.message.content return this.message.content
},
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
} }
}, },
methods: { methods: {
showImage(path) {
uni.previewImage({
urls: [
path
]
})
},
previewImage() { previewImage() {
if (this.content.local) { if (this.content.local && this.content.local.indexOf('///data/user/') < 0) {
uni.previewImage({ this.showImage(this.content.local)
urls: [
this.content.local
],
success: (e) => {
console.log(e);
},
fail: (er) => {
console.log(er);
}
})
} else { } else {
RongIMLib.downloadMediaMessage(this.messageId, { this.showImage(this.content.remote)
RongIMLib.downloadMediaMessage(this.message.messageId, {
success: (path) => { success: (path) => {
this.content.local = 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);
}, },
error: (errorCode, messageId) => { error: (errorCode, messageId) => {
console.log('errorCode', errorCode); uni.showToast({
icon: 'none',
title: errorCode
})
} }
}) })
} }

View File

@@ -11,9 +11,13 @@
<script> <script>
import messageState from './messageState' import messageState from './messageState'
import imBase from '../../mixins/imBase.js'
export default { export default {
name: 'showText', name: 'showText',
mixins: [
imBase,
],
props: { props: {
message: { message: {
type: Object, type: Object,
@@ -35,11 +39,6 @@
}, },
content() { content() {
return this.message.content.content return this.message.content.content
},
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
} }
} }
} }
@@ -58,7 +57,7 @@
.text { .text {
box-sizing: border-box; box-sizing: border-box;
max-width: 502rpx; max-width: 502rpx;
padding: 20rpx; padding: 20rpx 24rpx;
line-height: 46rpx; line-height: 46rpx;
font-size: 32rpx; font-size: 32rpx;
color: $text-color; color: $text-color;

View File

@@ -23,8 +23,12 @@
<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' import messageState from './messageState'
import imBase from '../../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
props: { props: {
message: { message: {
type: Object, type: Object,
@@ -54,11 +58,6 @@
isRemote() { isRemote() {
return this.message.messageDirection == 2 return this.message.messageDirection == 2
}, },
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
},
width() { width() {
if (this.duration > 3) { if (this.duration > 3) {
return (this.duration * 5) + 150 return (this.duration * 5) + 150
@@ -75,11 +74,6 @@
} }
}) })
}, },
created() {
console.log(this.message.messageId)
},
methods: { methods: {
// 播放语音消息 // 播放语音消息
startPlay() { startPlay() {

View File

@@ -1,6 +1,10 @@
<template> <template>
<view class=""> <view class="">
<view class="notify" v-if="message.objectName === 'RC:GrpNtf'">{{ message.content.message }}</view> <view class="notify" v-if="message.objectName === 'RC:GrpNtf'">
{{ message.content.message }}
<text class="link" @click="toAnnounce(message)" v-if="message.content.operation == 'ANNOUNCEMENT'">点击查看
</text>
</view>
<view class="notify" v-else-if="message.objectName === 'RC:RcNtf'"> <view class="notify" v-else-if="message.objectName === 'RC:RcNtf'">
{{ contact(message.senderUserId).name }} 撤回了一条消息 {{ contact(message.senderUserId).name }} 撤回了一条消息
</view> </view>
@@ -22,14 +26,21 @@
</template> </template>
<script> <script>
import {
getGroupAnnouncement
} from '@/apis/interfaces/im.js'
import * as IMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' 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'
import showCall from './show/showCall' import showCall from './show/showCall'
import utils from '@/utils/index.js' import utils from '@/utils/index.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
components: { components: {
showCall, showCall,
showVoice, showVoice,
@@ -48,21 +59,6 @@
default: false default: false
} }
}, },
data() {
return {
avatarRpx: 84
}
},
computed: {
avatarSize() {
return utils.rpx2px(this.avatarRpx)
},
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
}
},
methods: { methods: {
toUser(item) { toUser(item) {
if (item.messageDirection == 1) { if (item.messageDirection == 1) {
@@ -75,6 +71,34 @@
}) })
} }
}, },
// 跳转群公告
toAnnounce(message) {
if (message.content.extra) {
getGroupAnnouncement(message.targetId, message.content.extra).then(res => {
uni.navigateTo({
url: '/pages/im/group/announceCreate?type=check&targetId=' + message
.targetId + '&aId=' + message.content.extra
})
}).catch(err => {
IMLib.deleteMessagesByIds([message.messageId], ({
code
}) => {
if (code === 0) {
uni.$emit('remove_message_' + message.targetId, message.messageId)
}
})
uni.showToast({
title: '公告不存在或已删除',
icon: 'none',
})
})
} else {
uni.showToast({
icon: 'none',
title: '旧版本,无链接'
})
}
},
// 撤回消息测试 // 撤回消息测试
backMessage() { backMessage() {
if (this.$store.getters.sender.userId != this.message.senderUserId) { if (this.$store.getters.sender.userId != this.message.senderUserId) {
@@ -98,7 +122,7 @@
title: '消息撤回成功' title: '消息撤回成功'
}) })
IMLib.getMessage(this.message.messageId, res => { IMLib.getMessage(this.message.messageId, res => {
uni.$emit('onRecallMessage', res.message) uni.$emit('onRecallMessage_' + this.message.targetId, res.message)
}) })
} else { } else {
uni.showToast({ uni.showToast({
@@ -118,6 +142,11 @@
text-align: center; text-align: center;
font-size: 24rpx; font-size: 24rpx;
color: #666; color: #666;
.link {
color: $main-color;
margin-left: 10rpx;
}
} }
.cell-item { .cell-item {

View File

@@ -2,12 +2,12 @@
<view> <view>
<u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98"> <u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98">
<view class="friend-flex" @click="toPending"> <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" /> <u-badge max="99" absolute :offset="[23, 20]" :value="pendingCount" />
<view class="info">新的朋友</view> <view class="info">新的朋友</view>
</view> </view>
<view class="friend-flex" @click="toGroup"> <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 class="info">我的群聊</view>
</view> </view>
<block v-if="friends.length > 0"> <block v-if="friends.length > 0">
@@ -20,14 +20,15 @@
:src="contact(friendItem.targetId).portraitUrl" /> :src="contact(friendItem.targetId).portraitUrl" />
<view class="info"> <view class="info">
<view class="name">{{ contact(friendItem.targetId).name }}</view> <view class="name">{{ contact(friendItem.targetId).name }}</view>
<!-- <view class="address">地址:{{ friendItem.address }}</view> -->
</view> </view>
</view> </view>
</u-index-item> </u-index-item>
</block> </block>
<block v-else> <view class="no-lists" v-else>
<u-empty class="pages-null" mode="data" text="暂无好友" /> <u-image class="cover" radius="4" width="400rpx" height="400rpx"
</block> :src=" require('@/static/imgs/no-friend.png')" :lazy-load="true" />
<span>暂无好友列表~</span>
</view>
</u-index-list> </u-index-list>
</view> </view>
</template> </template>
@@ -38,8 +39,12 @@
} from '@/apis/interfaces/im'; } from '@/apis/interfaces/im';
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import im from '@/utils/im/index.js' import im from '@/utils/im/index.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
data() { data() {
return { return {
indexs: [], indexs: [],
@@ -55,9 +60,14 @@
} }
}, },
onLoad() { onLoad() {
uni.$on('onNewContactFriends', this.checkNewFriendPending)
},
onShow() {
this.getFriendList() this.getFriendList()
this.checkNewFriendPending() this.checkNewFriendPending()
uni.$on('onContactNotification', this.checkNewFriendPending) },
onUnload() {
uni.$off("onNewContactFriends")
}, },
methods: { methods: {
getFriendList() { getFriendList() {
@@ -73,10 +83,7 @@
}, },
toGroup() { toGroup() {
uni.navigateTo({ uni.navigateTo({
url: '/pages/im/group/index', url: '/pages/im/group/index'
fail(err) {
console.log(err);
}
}) })
}, },
toFriend(targetId) { toFriend(targetId) {
@@ -86,24 +93,15 @@
}, },
// 新朋友 // 新朋友
toPending() { toPending() {
// if (this.pendingCount > 0) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/im/friends/pending' url: '/pages/im/friends/pending'
}); })
// } else {
// uni.showToast({
// title: ` 暂无好友申请 ~ `,
// icon: "none",
// mask: true,
// duration: 3000
// })
// }
} }
}, },
onNavigationBarButtonTap(e) { onNavigationBarButtonTap(e) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/im/friends/search' url: '/pages/im/friends/search'
}); })
} }
}; };
</script> </script>
@@ -172,4 +170,19 @@
line-height: 24px; line-height: 24px;
background-color: #fff; 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> </style>

View File

@@ -30,7 +30,7 @@
<u-icon name="arrow-right" color="#eee" size="16" /> <u-icon name="arrow-right" color="#eee" size="16" />
</view> </view>
<view class="item u-border-bottom"> <view class="item u-border-bottom">
<label>聊天免打扰</label> <label>消息免打扰</label>
<u-switch size="22" v-model="status" activeColor="#34CE98" @change="setStatus"></u-switch> <u-switch size="22" v-model="status" activeColor="#34CE98" @change="setStatus"></u-switch>
</view> </view>
<view class="item"> <view class="item">
@@ -113,7 +113,6 @@
onLoad(e) { onLoad(e) {
this.targetId = e.targetId this.targetId = e.targetId
getFriendInfo(e.targetId).then(res => { getFriendInfo(e.targetId).then(res => {
console.log(res, "获取朋友的信息")
this.userInfo = res this.userInfo = res
// 获取到用户信息之后,去检查一下要不要更新 // 获取到用户信息之后,去检查一下要不要更新
this.$store.dispatch('updateContact', res) this.$store.dispatch('updateContact', res)
@@ -148,7 +147,7 @@
}) })
}, },
toPrivate() { toPrivate() {
uni.redirectTo({ uni.navigateTo({
url: '/pages/im/private/chat?targetId=' + this.targetId url: '/pages/im/private/chat?targetId=' + this.targetId
}); });
}, },
@@ -209,7 +208,7 @@
}) })
return return
} }
pedingFriend(this.targetId, 'message').then(res => { pedingFriend(this.targetId, '').then(res => {
uni.showToast({ uni.showToast({
title: ` 申请成功,等待审核 `, title: ` 申请成功,等待审核 `,
icon: 'none', icon: 'none',
@@ -228,8 +227,9 @@
}) })
}, },
singleCall(e) { singleCall(e) {
uni.redirectTo({ uni.navigateTo({
url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type + '&isCall=true' url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type +
'&isCall=true'
}) })
} }
} }

View File

@@ -4,7 +4,7 @@
<!-- 用户信息 --> <!-- 用户信息 -->
<view class="info-flex"> <view class="info-flex">
<view class="info-flex-item"> <view class="info-flex-item">
<u-avatar :src="infoObj.portraitUrl" shape="square" size="210rpx" bg-color="#fff" class="avatar" /> <u-avatar :src="infoObj.portraitUrl" @click='previewImg(infoObj.portraitUrl)' shape="square" size="210rpx" bg-color="#fff" class="avatar" />
<view class="nickname">{{infoObj.name}}</view> <view class="nickname">{{infoObj.name}}</view>
<view class="address">{{infoObj.address}}</view> <view class="address">{{infoObj.address}}</view>
<view class="info-code"> <view class="info-code">
@@ -23,7 +23,8 @@
<script> <script>
import { import {
getUserInfo getUserInfo
} from '@/apis/interfaces/im' } from '@/apis/interfaces/im.js'
export default { export default {
data() { data() {
return { return {
@@ -47,6 +48,12 @@
}) })
}, },
methods: { methods: {
previewImg(item){
console.log(item)
uni.previewImage({
urls:[item]
})
},
copy() { copy() {
uni.setClipboardData({ uni.setClipboardData({
data: this.downUrl, data: this.downUrl,
@@ -99,7 +106,7 @@
.avatar { .avatar {
// padding: 14rpx; // padding: 14rpx;
border-radius: 10rpx; border-radius: 20rpx;
background-color: #fff; background-color: #fff;
border: solid 14rpx rgba($color: #fff, $alpha:1); border: solid 14rpx rgba($color: #fff, $alpha:1);
} }

View File

@@ -2,7 +2,7 @@
<view class="pending"> <view class="pending">
<u-sticky> <u-sticky>
<view class="header-search" @click="$Router.push({ name: 'SearchFriend' })"> <view class="header-search" @click="$Router.push({ name: 'SearchFriend' })">
<u-search placeholder="输入手机号码搜索" height="74" searchIcon="search" inputAlign="center" bgColor="white" <u-search placeholder="输入手机号码搜索" searchIcon="search" inputAlign="center" bgColor="white"
:disabled="true" :show-action="false" /> :disabled="true" :show-action="false" />
</view> </view>
</u-sticky> </u-sticky>
@@ -33,13 +33,17 @@
bg: '#fff' bg: '#fff'
} }
}, },
onLoad() { onShow() {
this.getPendingList() this.getPendingList()
uni.$on('onContactNotification', this.getPendingList) uni.$on('onNewContactPendings', this.getPendingList)
},
onUnload() {
uni.$off('onNewContactPendings')
}, },
methods: { methods: {
getPendingList() { getPendingList() {
im.getPendingList((pendings) => { im.getPendingList((pendings) => {
console.log(pendings, 'res......')
if (pendings.length > 0) { if (pendings.length > 0) {
this.bg = '#f9f9f9' this.bg = '#f9f9f9'
} else { } else {

View File

@@ -8,17 +8,19 @@
<template> <template>
<view class="search"> <view class="search">
<!-- 搜索 --> <!-- 搜索 -->
<u-sticky> <u-sticky>
<view class="header-search"> <view class="header-search">
<u-search placeholder="输入用户账号、手机号" height="74" searchIcon="search" @custom="search" v-model="searchValue" @search="search" bgColor="#f9f9f9" :focus="focused" /> <u-search placeholder="输入用户账号、手机号" searchIcon="search" @custom="search" v-model="searchValue"
@search="search" bgColor="#F3F6FB" :focus="focused" />
</view> </view>
</u-sticky> </u-sticky>
<block v-if="searchResult.length > 0"> <block v-if="searchResult.length > 0">
<applyFriend :lists="searchResult" :isApply="true" @action="action" /> <applyFriend :lists="searchResult" :isApply="true" @action="action" />
</block> </block>
<view class="no-lists" v-else> <view class="no-lists" v-if="searchResult.length === 0 && searchValue.length > 1">
<u-image class="cover" radius="4" width="400rpx" height="400rpx" :src="require('@/static/imgs/no-search.png')" :lazy-load="true" /> <u-image class="cover" radius="4" width="400rpx" height="400rpx"
:src="require('@/static/imgs/no-search.png')" :lazy-load="true" />
<span>暂无匹配内容~</span> <span>暂无匹配内容~</span>
</view> </view>
</view> </view>
@@ -30,6 +32,7 @@
pedingFriend pedingFriend
} from '@/apis/interfaces/im.js'; } from '@/apis/interfaces/im.js';
import applyFriend from '../components/friendSearchList.vue'; import applyFriend from '../components/friendSearchList.vue';
export default { export default {
components: { components: {
applyFriend applyFriend
@@ -41,13 +44,27 @@
focused: true focused: true
}; };
}, },
watch: {
searchValue(value) {
console.log(value.length, 'length...')
if (value.length > 1) {
this.searchResult = []
this.search()
return
}
if(value.length === 0){
this.searchResult = []
return
}
}
},
methods: { methods: {
search() { search() {
// friendship: '' 没有好友关系 // friendship: '' 没有好友关系
// accepted 好友 // accepted 好友
// pending 申请中 // pending 申请中
// denied 拒绝 // denied 拒绝
// blocked 黑名单 // blocked 黑名单
searchFriend(this.searchValue) searchFriend(this.searchValue)
.then(res => { .then(res => {
this.searchResult = res; this.searchResult = res;

View File

@@ -1,13 +1,15 @@
<template> <template>
<view class="create"> <view class="create">
<view class="create-title">公告内容</view> <view class="create-title">公告内容</view>
<block v-if="type !== 'cheack'">
<block v-if="type === 'check'">
<view class="content"> {{content}} </view>
</block>
<block v-else>
<u--textarea v-model="content" count height="240" maxlength="240" placeholder="请输入公告内容" /> <u--textarea v-model="content" count height="240" maxlength="240" placeholder="请输入公告内容" />
<u-button type="primary" text="发布" :disabled="disabled" @click="onCreate" color="#34CE98" /> <u-button type="primary" text="发布" :disabled="disabled" @click="onCreate" color="#34CE98" />
</block> </block>
<block v-if="type === 'cheack'">
<view class="content-a"> {{content}} </view>
</block>
</view> </view>
</template> </template>
@@ -16,32 +18,42 @@
createGroupAnnouncement, createGroupAnnouncement,
getGroupAnnouncement getGroupAnnouncement
} from '@/apis/interfaces/im.js' } from '@/apis/interfaces/im.js'
import onGroupDismiss from '../mixins/onGroupDismiss.js'
export default { export default {
mixins: [
onGroupDismiss
],
data() { data() {
return { return {
targetId: '', targetId: '',
content: '', content: '',
aId: '', aId: '',
type: '' // check ' 查看详情' type: '' // cheack ' 查看详情'
} }
}, },
onLoad(e) { onLoad(e) {
this.targetId = e.targetId this.targetId = e.targetId
if (e.type) {
this.type = e.type
}
if (e.aId) { if (e.aId) {
this.type = e.type
uni.setNavigationBarTitle({
title: '群公告'
})
this.aId = e.aId this.aId = e.aId
getGroupAnnouncement(this.targetId, this.aId).then(res => { getGroupAnnouncement(this.targetId, this.aId).then(res => {
console.log(res.content)
this.content = res.content this.content = res.content
}).catch(err => { }).catch(err => {
uni.showToast({ if (err.status_code == 404) {
title: err.message, this.$nextTick(() => {
icon: 'none', uni.navigateBack()
mask: true })
}) } else {
uni.showToast({
title: err.message,
icon: 'none',
mask: true
})
}
}) })
} }
}, },
@@ -95,7 +107,7 @@
} }
} }
.content-a { .content {
color: $text-color; color: $text-color;
font-size: $title-size; font-size: $title-size;
line-height: 1.7; line-height: 1.7;

View File

@@ -35,8 +35,14 @@
deleteGroupAnnouncement, deleteGroupAnnouncement,
topGroupAnnouncement topGroupAnnouncement
} from '@/apis/interfaces/im.js' } from '@/apis/interfaces/im.js'
import onGroupDismiss from '../mixins/onGroupDismiss.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase,
onGroupDismiss
],
data() { data() {
return { return {
targetId: '', targetId: '',
@@ -55,7 +61,7 @@
disabled: false disabled: false
}], }],
actionTitle: '请选择操作', actionTitle: '请选择操作',
bg:'#fff' bg: '#fff'
} }
}, },
onLoad(e) { onLoad(e) {
@@ -85,9 +91,9 @@
// 获取公告信息 // 获取公告信息
initData() { initData() {
getGroupAnnouncements(this.targetId).then(res => { getGroupAnnouncements(this.targetId).then(res => {
if(res.length>0){ if (res.length > 0) {
this.bg = '#f9f9f9' this.bg = '#f9f9f9'
}else{ } else {
this.bg = '#fff' this.bg = '#fff'
} }
this.announcements = res this.announcements = res
@@ -115,7 +121,7 @@
}, },
tabA(id) { tabA(id) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/im/group/announceCreate?type=cheack&targetId=' + this.targetId + '&aId=' + id url: '/pages/im/group/announceCreate?type=check&targetId=' + this.targetId + '&aId=' + id
}) })
}, },
onTop(aId) { onTop(aId) {
@@ -128,14 +134,6 @@
uni.$emit('updateAnnouncement') uni.$emit('updateAnnouncement')
this.initData() this.initData()
}) })
// uni.showModal({
// title: ' 置顶该公告',
// success: (res) => {
// if (res.confirm) {
// }
// }
// })
}, },
// 删除公告 // 删除公告
onDelete(aId) { onDelete(aId) {
@@ -148,14 +146,6 @@
uni.$emit('updateAnnouncement') uni.$emit('updateAnnouncement')
this.initData() this.initData()
}) })
// uni.showModal({
// title: '删除该公告',
// success: (res) => {
// if (res.confirm) {
// }
// }
// })
} }
} }
} }
@@ -194,7 +184,8 @@
box-sizing: border-box; box-sizing: border-box;
font-size: $title-size-m; font-size: $title-size-m;
color: $text-gray-m; color: $text-gray-m;
padding: 10rpx; padding: 20rpx 10rpx 10rpx 10rpx;
border-top: solid 1rpx #F9F9F9;
.name { .name {
padding-left: 10rpx; padding-left: 10rpx;
@@ -215,8 +206,6 @@
-webkit-line-clamp: 3; -webkit-line-clamp: 3;
overflow: hidden; overflow: hidden;
line-height: 1.5; line-height: 1.5;
border-bottom: solid 1rpx #F9F9F9;
padding-bottom: 20rpx;
span { span {
color: #fff; color: #fff;

View File

@@ -20,8 +20,14 @@
joinGroupPre, joinGroupPre,
joinGroup joinGroup
} from '@/apis/interfaces/im.js' } from '@/apis/interfaces/im.js'
import onGroupDismiss from '../mixins/onGroupDismiss.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase,
onGroupDismiss
],
data() { data() {
return { return {
targetId: '', targetId: '',

View File

@@ -21,8 +21,14 @@
import sentMessageBar from '../components/sentMessageBar' import sentMessageBar from '../components/sentMessageBar'
import showMessageCell from '../components/showMessageCell' import showMessageCell from '../components/showMessageCell'
import utils from '@/utils/index.js' import utils from '@/utils/index.js'
import onGroupDismiss from '../mixins/onGroupDismiss.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase,
onGroupDismiss
],
components: { components: {
sentMessageBar, sentMessageBar,
showMessageCell showMessageCell
@@ -49,21 +55,16 @@
} }
} }
}, },
onShow() {
this.initGroupInfo()
},
onLoad(e) { onLoad(e) {
this.targetId = e.targetId this.targetId = e.targetId
// 获取群成员数量
getGroupBase(this.targetId).then(res => {
uni.setNavigationBarTitle({
title: res.name + `(${res.members})`
})
})
// 获取历史消息列表 // 获取历史消息列表
this.getMessageList() this.getMessageList()
// 监听收到本群的消息,追加消息 // 监听消息
uni.$on('onReceiveMessage', (msg) => { uni.$on('onReceiveMessage_' + this.targetId, (message) => {
if (msg.targetId == this.targetId) { this.getNewMessage()
this.getNewMessage()
}
}) })
uni.$on('onReceiptRequest', (msg) => { uni.$on('onReceiptRequest', (msg) => {
if (msg.targetId == this.targetId) { if (msg.targetId == this.targetId) {
@@ -88,20 +89,24 @@
}) })
// 清理聊天记录 // 清理聊天记录
uni.$once('cleanGroupMessage', this.getMessageList) uni.$once('cleanGroupMessage', this.getMessageList)
uni.$on('onRecallMessage', (res) => { uni.$on('onRecallMessage_' + this.targetId, (message) => {
if (res.targetId == this.targetId) { this.messages = this.messages.map(item => {
this.messages = this.messages.map(item => { if (message.messageId == item.messageId) {
if (res.messageId == item.messageId) { return message
return res } else {
} else { return item
return item }
} })
}) })
} uni.$on('remove_message_' + this.targetId, (messageId) => {
this.messages = this.messages.filter(item => item.messageId != messageId)
}) })
}, },
onUnload() { onUnload() {
uni.$off('onRecallMessage') uni.$off('remove_message_' + this.targetId)
uni.$off('onReceiveMessage_' + this.targetId)
uni.$off('onUpdateProfile_' + this.targetId)
uni.$off('onRecallMessage_' + this.targetId)
uni.$off('onReceiptRequest') uni.$off('onReceiptRequest')
uni.$off('onReceiptResponse') uni.$off('onReceiptResponse')
}, },
@@ -111,6 +116,14 @@
}) })
}, },
methods: { methods: {
initGroupInfo() {
// 获取群信息,成员数量,设置标题
getGroupBase(this.targetId).then(res => {
uni.setNavigationBarTitle({
title: res.name + `(${res.members})`
})
})
},
onScroll(e) { onScroll(e) {
this.$refs.messageBar.onHidePopus() this.$refs.messageBar.onHidePopus()
}, },
@@ -164,7 +177,7 @@
}, },
onHide() { onHide() {
// console.log(JSON.stringify(this.$refs)) // console.log(JSON.stringify(this.$refs))
this.$refs.voice.stopPlay() // this.$refs.voice.stopPlay()
} }
} }
</script> </script>

View File

@@ -3,16 +3,15 @@
<block v-if="groups.length > 0"> <block v-if="groups.length > 0">
<view class="title"> 群聊 </view> <view class="title"> 群聊 </view>
<view v-for="(item, index) in groups" :key="index" class="friend-flex" @click="toGroup(item.targetId)"> <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" /> <u-avatar size="36" shape="square" :src="contact(item.targetId).portraitUrl" />
<view class="info"> <view class="info">
<view class="name">{{ item.name }}</view> <view class="name">{{ item.name }} <span class="total">{{ item.members }} 成员</span></view>
</view> </view>
</view> </view>
<view class="group-count"> {{groups.length}}个群聊 </view> <view class="group-count"> {{ groups.length }}个群聊 </view>
</block> </block>
<view class="no-lists" v-else> <view class="no-lists" v-else>
<u-image class="cover" radius="4" width="400rpx" height="400rpx" <u-image class="cover" radius="4" width="400rpx" height="400rpx" :src="require('@/static/imgs/no-friend.png')" :lazy-load="true" />
:src="require('@/static/imgs/no-friend.png')" :lazy-load="true" />
<span>空空如也~</span> <span>空空如也~</span>
</view> </view>
<u-modal negativeTop="300" :show="createModal" title="创建群聊" showCancelButton @cancel="onHideModal" <u-modal negativeTop="300" :show="createModal" title="创建群聊" showCancelButton @cancel="onHideModal"
@@ -49,13 +48,14 @@
onNavigationBarButtonTap() { onNavigationBarButtonTap() {
this.createModal = true this.createModal = true
}, },
onLoad() { onShow() {
this.initData() this.initData()
uni.$on('onGroupDismiss', this.initData) uni.$on('onGroupDismiss', this.initData)
}, },
methods: { methods: {
initData() { initData() {
getMyGroups().then((res) => { getMyGroups().then((res) => {
console.log(res,'res...')
if (res.length > 0) { if (res.length > 0) {
this.bg = '#f9f9f9' this.bg = '#f9f9f9'
} else { } else {
@@ -138,6 +138,11 @@
font-size: $title-size + 1; font-size: $title-size + 1;
color: #454545 !important; color: #454545 !important;
} }
.total{
color: $text-gray-m;
font-size: $title-size-m - 5;
padding-left: 10rpx;
}
.address { .address {
color: $text-gray-m; color: $text-gray-m;

View File

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

View File

@@ -8,8 +8,9 @@
<u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98"> <u-index-list :index-list="indexs" inactiveColor="#666" activeColor="#34CE98">
<u-checkbox-group v-if="friends.length > 0" v-model="checkboxValue" placement="column"> <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-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" <u-index-anchor :text="indexs[fkey]" v-if="indexs[fkey]" bgColor="#f9f9f9f" height="20"
color="#666" style="border:none !important;padding: 10rpx 30rpx;background-color: #f9f9f9 !important;" /> 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" <view v-for="(friendItem, index) in item" :key="index" class="friend-flex"
@click="addContact(friendItem.targetId)"> @click="addContact(friendItem.targetId)">
<u-checkbox :name="friendItem.targetId" shape="circle" activeColor="#34ce98" <u-checkbox :name="friendItem.targetId" shape="circle" activeColor="#34ce98"
@@ -44,10 +45,15 @@
getGroupUsers getGroupUsers
} from '@/apis/interfaces/im'; } from '@/apis/interfaces/im';
import utils from '@/utils/index.js' import utils from '@/utils/index.js'
import onGroupDismiss from '../mixins/onGroupDismiss.js'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase,
onGroupDismiss
],
data() { data() {
return { return {
searchTxt: '', searchTxt: '',
@@ -60,13 +66,6 @@
selectValue: [] selectValue: []
}; };
}, },
computed: {
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
}
},
onLoad(e) { onLoad(e) {
this.targetId = e.targetId this.targetId = e.targetId
this.getFriendList() this.getFriendList()
@@ -123,16 +122,16 @@
}, },
onInvite() { onInvite() {
console.log(this.checkboxValue,'userIds.....') console.log(this.checkboxValue, 'userIds.....')
console.log(this.selectValue,'userIds.....') console.log(this.selectValue, 'userIds.....')
let userIds = [] let userIds = []
this.checkboxValue.filter(item=>{ this.checkboxValue.filter(item => {
if(!utils.inArray(item, this.selectValue)){ if (!utils.inArray(item, this.selectValue)) {
userIds.push(item) userIds.push(item)
} }
}) })
// console.log(userIds) // console.log(userIds)
inviteGroupUser(this.targetId, this.checkboxValue,userIds).then(res => { inviteGroupUser(this.targetId, this.checkboxValue, userIds).then(res => {
uni.navigateBack({ uni.navigateBack({
delta: 1, delta: 1,
animationType: 'pop-out', animationType: 'pop-out',

View File

@@ -3,7 +3,7 @@
<view class="reviewed"> <view class="reviewed">
<block v-if="pendings.length > 0"> <block v-if="pendings.length > 0">
<view class="reviewed-item" v-for="(item, index) in pendings" :key="index"> <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')" :src="JSON.parse(item.content.extra).portraitUrl || require('@/static/user/cover.png')"
shape="square" size="46" /> shape="square" size="46" />
<view style="flex:1;" v-if="item.content.operation == 'GroupPending'"> <view style="flex:1;" v-if="item.content.operation == 'GroupPending'">
@@ -22,7 +22,7 @@
<view class="no-lists" v-else> <view class="no-lists" v-else>
<u-image class="cover" radius="4" width="400rpx" height="400rpx" <u-image class="cover" radius="4" width="400rpx" height="400rpx"
:src="require('@/static/imgs/no-friend.png')" :lazy-load="true" /> :src="require('@/static/imgs/no-friend.png')" :lazy-load="true" />
<span> 暂无群聊申请数据~</span> <span>暂无群聊申请数据</span>
</view> </view>
</view> </view>
</template> </template>
@@ -34,9 +34,14 @@
} from "@/apis/interfaces/im.js" } from "@/apis/interfaces/im.js"
import im from '@/utils/im/message.js' import im from '@/utils/im/message.js'
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import onGroupDismiss from '../mixins/onGroupDismiss.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase,
onGroupDismiss
],
data() { data() {
return { return {
targetId: '', targetId: '',
@@ -79,7 +84,6 @@
uni.$emit('groupInvitedUser') uni.$emit('groupInvitedUser')
} }
}) })
}).catch(err => { }).catch(err => {
// uni.showToast({ // uni.showToast({
// title: err.message, // title: err.message,
@@ -93,7 +97,7 @@
console.log('code', code) console.log('code', code)
if (code == 0) { if (code == 0) {
uni.showToast({ uni.showToast({
title:err.message, title: err.message,
icon: 'none', icon: 'none',
mask: true, mask: true,
duration: 2000 duration: 2000
@@ -153,6 +157,7 @@
} }
} }
.no-lists { .no-lists {
padding-top: $padding * 5; padding-top: $padding * 5;
display: flex; display: flex;

View File

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

View File

@@ -46,7 +46,8 @@
return { return {
conversations: [], // 会话列表 conversations: [], // 会话列表
connection: 0, connection: 0,
hasNewFriends: 0 hasNewFriends: 0,
perPage: 200
} }
}, },
components: { components: {
@@ -54,27 +55,35 @@
connectionStatus connectionStatus
}, },
onLoad() { onLoad() {
// 好友申请数量
this.checkNewFriendPending()
// 监听新的好友申请 // 监听新的好友申请
uni.$on('onContactNotification', () => { uni.$on('onNewContactConversation', () => {
console.log('更新好友申请数量');
// 更新好友申请数量
this.checkNewFriendPending() this.checkNewFriendPending()
}) })
}, },
onShow() { onShow() {
// 好友申请数量
this.checkNewFriendPending()
if (this.$store.state.token !== '') { if (this.$store.state.token !== '') {
this.getConversationList() this.getConversationList()
} }
uni.$on('onConnectionStatusChange', (status) => {
this.connection = status
})
// 监听新消息 // 监听新消息
uni.$on('onReceiveMessage', (msg) => { uni.$on('onReceiveMessage', (msg) => {
this.getConversationList() this.getConversationList()
}) })
// 监听网络状态变化
uni.$on('onConnectionStatusChange', (status) => {
this.connection = status
if (status == 0) {
this.getConversationList()
}
})
}, },
onHide() { onHide() {
uni.$off('onReceiveMessage') uni.$off('onReceiveMessage')
uni.$off('onConnectionStatusChange')
}, },
methods: { methods: {
checkNewFriendPending() { checkNewFriendPending() {
@@ -91,11 +100,9 @@
} }
return true return true
}, },
// 获取私聊的会话列表 // 获取会话列表,最新的一千条
getConversationList() { getConversationList() {
const count = 1000 RongIMLib.getConversationList([1, 3], this.perPage, 0, ({
const timestamp = 0
RongIMLib.getConversationList([1, 3], count, timestamp, ({
code, code,
conversations conversations
}) => { }) => {

17
pages/im/mixins/imBase.js Normal file
View File

@@ -0,0 +1,17 @@
import utils from '@/utils/index.js'
export default {
computed: {
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
},
avatarSize() {
return utils.rpx2px(84)
},
sender() {
return this.$store.getters.sender
}
}
}

View File

@@ -0,0 +1,34 @@
// 监听群解散的消息,直接跳转到会话列表页面
export default {
data() {
return {
currentTargetId: ''
}
},
onLoad(e) {
this.currentTargetId = e.targetId
uni.$once('onGroupDismiss_' + e.targetId, () => {
uni.showToast({
icon: 'none',
title: '当前群已解散'
})
uni.switchTab({
url: '/pages/im/index'
})
})
uni.$once('onGroupRemoveYou_' + e.targetId, () => {
uni.showToast({
icon: 'none',
title: '您已被移出群聊'
})
uni.switchTab({
url: '/pages/im/index'
})
})
},
onUnload() {
uni.$off('onGroupDismiss_' + this.currentTargetId)
uni.$off('onGroupRemoveYou_' + this.currentTargetId)
}
}

View File

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

View File

@@ -18,8 +18,12 @@
import sentMessageBar from '../components/sentMessageBar' import sentMessageBar from '../components/sentMessageBar'
import showMessageCell from '../components/showMessageCell' import showMessageCell from '../components/showMessageCell'
import utils from '@/utils/index.js' import utils from '@/utils/index.js'
import imBase from '../mixins/imBase.js'
export default { export default {
mixins: [
imBase
],
components: { components: {
sentMessageBar, sentMessageBar,
showMessageCell showMessageCell
@@ -45,11 +49,6 @@
sentTime: 0 sentTime: 0
} }
} }
},
contact() {
return function(targetId) {
return this.$store.getters.contactInfo(targetId)
}
} }
}, },
onLoad(e) { onLoad(e) {
@@ -60,6 +59,10 @@
}) })
// 获取消息列表 // 获取消息列表
this.getMessageList() this.getMessageList()
// 监听新消息
uni.$on('onReceiveMessage_' + this.targetId, (message) => {
this.getNewMessage()
})
// 监听消息已读状态 // 监听消息已读状态
uni.$on('onReadReceiptReceived', (data) => { uni.$on('onReadReceiptReceived', (data) => {
if (data.targetId == this.targetId) { if (data.targetId == this.targetId) {
@@ -72,25 +75,29 @@
}) })
} }
}) })
// 监听收到新消息,判断是否是当前会话,更新会话内容 uni.$on('onRecallMessage_' + this.targetId, (message) => {
uni.$on('onReceiveMessage', (msg) => { this.messages = this.messages.map(item => {
if (msg.targetId == this.targetId) { if (message.messageId == item.messageId) {
this.getNewMessage() return message
} } else {
return item
}
})
}) })
uni.$on('onRecallMessage', (res) => { uni.$once('onUserDelete_' + this.targetId, () => {
if (res.targetId == this.targetId) { uni.showToast({
this.messages = this.messages.map(item => { icon: 'none',
if (res.messageId == item.messageId) { title: '好友关系已解除'
return res })
} else { uni.switchTab({
return item url: '/pages/im/index'
} })
})
}
}) })
}, },
onUnload() { onUnload() {
uni.$off('onUserDelete_' + this.targetId)
uni.$off('onReceiveMessage_' + this.targetId)
uni.$off('onRecallMessage_' + this.targetId)
uni.$off('onRecallMessage') uni.$off('onRecallMessage')
uni.$off('onReadReceiptReceived') uni.$off('onReadReceiptReceived')
}, },

BIN
static/.DS_Store vendored

Binary file not shown.

BIN
static/user/cover-s.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -76,7 +76,8 @@ export default {
name: contactInfo.name, name: contactInfo.name,
hash: contactInfo.hash, hash: contactInfo.hash,
portraitUrl: contactInfo.portraitUrl, portraitUrl: contactInfo.portraitUrl,
localAvatar: savedFilePath localAvatar: savedFilePath,
type: contactInfo.type
} }
model.update('targetId="' + contactInfo.targetId + '"', info, (err, model.update('targetId="' + contactInfo.targetId + '"', info, (err,
res) => { res) => {
@@ -90,7 +91,8 @@ export default {
name: contactInfo.name, name: contactInfo.name,
hash: contactInfo.hash, hash: contactInfo.hash,
portraitUrl: contactInfo.portraitUrl, portraitUrl: contactInfo.portraitUrl,
localAvatar: result[0].localAvatar localAvatar: result[0].localAvatar,
type: contactInfo.type
} }
model.update('targetId="' + contactInfo.targetId + '"', info, (err, res) => { model.update('targetId="' + contactInfo.targetId + '"', info, (err, res) => {
console.log('UPDATE NAME, ERR', err, info); console.log('UPDATE NAME, ERR', err, info);
@@ -117,7 +119,8 @@ export default {
name: contactInfo.name, name: contactInfo.name,
hash: contactInfo.hash, hash: contactInfo.hash,
portraitUrl: contactInfo.portraitUrl, portraitUrl: contactInfo.portraitUrl,
localAvatar: savedFilePath localAvatar: savedFilePath,
type: contactInfo.type
} }
model.insert(info, (err, res) => {}) model.insert(info, (err, res) => {})
// 保存头像后,更新信息 // 保存头像后,更新信息
@@ -130,7 +133,8 @@ export default {
name: contactInfo.name, name: contactInfo.name,
hash: contactInfo.hash, hash: contactInfo.hash,
portraitUrl: contactInfo.portraitUrl, portraitUrl: contactInfo.portraitUrl,
localAvatar: '' localAvatar: '',
type: contactInfo.type
} }
model.insert(info, (err, res) => {}) model.insert(info, (err, res) => {})
} }

View File

@@ -62,7 +62,7 @@ const connect = (token, userInfo, callback) => {
// 设置未读消息数量 // 设置未读消息数量
setNotifyBadge() setNotifyBadge()
// 首次运行获取好友列表 // 首次运行获取好友列表
const FK = 'ZHKD_' + userInfo.targetId const FK = 'ZH_V_' + userInfo.targetId
uni.getStorage({ uni.getStorage({
key: FK, key: FK,

View File

@@ -20,7 +20,30 @@ const onReceiveMessage = (message) => {
} }
}) })
im.setNotifyBadge() im.setNotifyBadge()
// 发布全局事件,有新消息,刷新会话列表
uni.$emit('onReceiveMessage', message) uni.$emit('onReceiveMessage', message)
// 这个是为了更新消息列表页的
uni.$emit('onReceiveMessage_' + message.targetId, message)
}
// 检测联系人信息,不存在的时候,从服务端获取
const checkContactExists = (message) => {
if (!store.getters.contactIsExist(message.targetId)) {
getUserInfo(message.targetId).then(res => {
console.log('targetId', res);
store.dispatch('initContact', res)
}).catch(err => {
console.error('getUserInfo ERR', err)
})
}
if (!store.getters.contactIsExist(message.senderUserId)) {
getUserInfo(message.senderUserId).then(res => {
console.log('senderUserId', message.senderUserId, res);
store.dispatch('initContact', res)
}).catch(err => {
console.error('getUserInfo ERR', err)
})
}
} }
// 允许通知的消息类型,触发更新消息列表操作,提示音 // 允许通知的消息类型,触发更新消息列表操作,提示音
@@ -32,10 +55,7 @@ const notifyMsgTypes = [
IMLib.ObjectName.Location, IMLib.ObjectName.Location,
IMLib.ObjectName.Voice, IMLib.ObjectName.Voice,
IMLib.ObjectName.HQVoice, IMLib.ObjectName.HQVoice,
IMLib.ObjectName.Sight, IMLib.ObjectName.Sight
IMLib.ObjectName.Text,
IMLib.ObjectName.Text,
IMLib.ObjectName.Text
] ]
const imLibListeners = () => { const imLibListeners = () => {
@@ -48,40 +68,54 @@ const imLibListeners = () => {
IMLib.addReceiveMessageListener((res) => { IMLib.addReceiveMessageListener((res) => {
const message = res.data.message const message = res.data.message
console.error('[收到消息]', message) console.error('[收到消息]', message)
checkContactExists(message)
if (utils.inArray(message.objectName, notifyMsgTypes)) { if (utils.inArray(message.objectName, notifyMsgTypes)) {
if (!store.getters.contactIsExist(message.targetId)) {
getUserInfo(message.targetId).then(res => {
store.dispatch('initContact', res)
}).catch(err => {
console.error('getUserInfo ERR', err)
})
}
if (!store.getters.contactIsExist(message.senderUserId)) {
getUserInfo(message.senderUserId).then(res => {
store.dispatch('initContact', res)
}).catch(err => {
console.error('getUserInfo ERR', err)
})
}
onReceiveMessage(message) onReceiveMessage(message)
} else if (message.objectName === IMLib.ObjectName.ProfileNotification) { } else if (message.objectName === IMLib.ObjectName.ProfileNotification) {
// 更新会话信息 uni.$emit('onUpdateProfile_' + message.targetId)
// 更新联系人信息
store.dispatch('updateContact', JSON.parse(message.content.data)) store.dispatch('updateContact', JSON.parse(message.content.data))
// 调用完更新之后,删除这条消息 // 调用完更新之后,删除这条消息
IMLib.deleteMessagesByIds([message.messageId]) IMLib.deleteMessagesByIds([message.messageId])
} else if (message.objectName === IMLib.ObjectName.ContactNotification) { } else if (message.objectName === IMLib.ObjectName.ContactNotification) {
console.error('触发一个新好友的通知事件', message); if (message.content.operation === 'Request') {
// 触发一个新好友的通知事件 // 触发一个新好友的通知事件,【会话列表,通讯录,新朋友】页面
uni.$emit('onContactNotification', message) uni.$emit('onNewContactConversation', message)
uni.$emit('onNewContactFriends', message)
uni.$emit('onNewContactPendings', message)
} else if (message.content.operation === 'Delete') {
IMLib.cleanHistoryMessages(1, message.targetId, message.sentTime, false)
// 解散了就删了吧
IMLib.removeConversation(1, message.targetId)
// 刷新会话列表
uni.$emit('onUserDelete_' + message.targetId)
uni.$emit('onReceiveMessage', message)
}
} else if (message.objectName === IMLib.ObjectName.GroupNotification) { } else if (message.objectName === IMLib.ObjectName.GroupNotification) {
// 解散群 // 解散群
if (message.content.operation === 'Dismiss') { if (message.content.operation === 'Dismiss') {
IMLib.cleanHistoryMessages(message.conversationType, message.targetId, message.sentTime, IMLib.cleanHistoryMessages(3, message.targetId, message.sentTime,
false) false)
// 解散了就删了吧 // 解散了就删了吧
IMLib.removeConversation(message.conversationType, message.targetId) IMLib.removeConversation(3, message.targetId)
uni.$emit('onGroupDismiss', message.targetId) // 发布群解散的消息
uni.$emit('onGroupDismiss')
uni.$emit('onGroupDismiss_' + message.targetId)
} else if (message.content.operation === 'REMOVE') {
// 要判断是否当前用户,然后把当前用户踢出到主页去, 删除聊天记录,会话列表
if (message.content.extra == store.getters.sender.userId) {
IMLib.cleanHistoryMessages(3, message.targetId, message.sentTime,
false)
// 解散了就删了吧
IMLib.removeConversation(3, message.targetId)
// 为了更新群列表
uni.$emit('onGroupDismiss')
uni.$emit('onGroupRemoveYou_' + message.targetId)
}
uni.$emit('onReceiveMessage_' + message.targetId, message)
// 这个是为了更新消息列表页的
} }
// 触发刷新会话列表
uni.$emit('onReceiveMessage', message) uni.$emit('onReceiveMessage', message)
} }
}) })
@@ -93,10 +127,16 @@ const imLibListeners = () => {
uni.$emit('onReadReceiptReceived', data) uni.$emit('onReadReceiptReceived', data)
}) })
// 监听消息撤回操作 // 监听消息撤回操作
IMLib.addRecallMessageListener((res) => { IMLib.addRecallMessageListener(({
IMLib.getMessage(res.data.messageId, (res) => { data
console.error("消息撤回: ", res.message); }) => {
uni.$emit('onRecallMessage', res.message) IMLib.getMessage(data.messageId, ({
message
}) => {
console.error("消息撤回: ", message);
im.setNotifyBadge()
uni.$emit('onReceiveMessage', message)
uni.$emit('onRecallMessage_' + message.targetId, message)
}) })
}) })
// 监听需要群聊消息回执 // 监听需要群聊消息回执

View File

@@ -13,6 +13,10 @@ const contactModel = usqlite.model('contacts', {
type: String, type: String,
unique: true unique: true
}, },
type: {
type: Number,
default: 0
},
portraitUrl: String, portraitUrl: String,
localAvatar: String localAvatar: String
}) })