Files
im-system/uni-im示例/uni_modules/uni-im/pages/index/index.nvue
2023-09-24 17:55:19 +08:00

565 lines
17 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view id="page">
<!-- 底部版权声明栏 -->
<view id="about" v-if="isWidescreen" space="nbsp">
<text>欢迎体验uni-im &#8203;</text>
<uni-link href="https://ext.dcloud.net.cn/plugin?id=9711" text="[点此下载插件]"></uni-link>
</view>
<!-- #ifdef H5 -->
<!-- 布局最左侧 菜单栏 -->
<view id="left-view" v-if="isWidescreen" @click="chatInfoIsShow = false;">
<cloud-image class="user-avatar" @click="toUcenter" :src="avatarUrl" width="40px" height="40px"
borderRadius="100px"></cloud-image>
<!-- {{currentUserInfo.username}} -->
<uni-badge size="small" :text="unreadMsgCount" absolute="rightTop" type="error">
<uni-icons class="chat-icon" @click="showContactsView = false"
:color="showContactsView?'#c5c5c5':'#5fc08e'" size="32" type="chatbubble-filled"></uni-icons>
</uni-badge>
<uni-badge size="small" :text="unreadnotificationCount" absolute="rightTop" type="error">
<uni-icons @click="showContactsView = true" :color="showContactsView?'#5fc08e':'#c5c5c5'" size="32"
type="staff-filled"></uni-icons>
</uni-badge>
</view>
<!-- #endif -->
<!-- 会话列表 -->
<view id="center-view">
<!-- #ifdef H5 -->
<!-- 搜索会话用户、聊天记录... -->
<view id="search-bar-box" v-if="isWidescreen" @click="clickSearchBarBox">
<uni-search-bar :readonly="true" id="search-bar" radius="5" placeholder="搜索" clearButton="auto" cancelButton="none"
></uni-search-bar>
<uni-icons color="#848386" size="26" type="plus"></uni-icons>
</view>
<view id="uni-im-contacts-box" v-show="isWidescreen && showContactsView">
<uni-im-contacts @clickMenu="clickMenu" id="uni-im-contacts"></uni-im-contacts>
</view>
<!-- #endif -->
<!-- #ifdef H5 -->
<scroll-view id="user-list-box" scroll-y="true" @scrolltolower="loadMore()">
<!-- #endif -->
<!-- 会话用户列表 -->
<uni-list class="user-list" :style="{'height':wHeight,'width':'750rpx'}" :border="false">
<uni-list-chat @contextmenu.prevent.native="toChat(item.id)"
v-for="(item,index) in conversationList" :key="item.id" :showBadge="item.unread_count>0"
:badgeText="item.unread_count" link :title="item.title" class="user-list-item"
:class="{activeConversation:currentConversationId==item.id}" :note="item.last_msg_note"
:avatar="item.avatar_file&&item.avatar_file.url ? item.avatar_file.url : '/uni_modules/uni-im/static/avatarUrl.png'"
@click="toChat(item.id)" direction="column" :time="friendlyTime(item.update_time)"
:hasCallMe="item.call_list.length">
<template v-slot:header>
<text class="group-icon" v-if="item.group_id">群</text>
</template>
</uni-list-chat>
<!-- #ifdef APP-NVUE -->
<!-- nvue端appear元素一旦显示在可视窗口中就触发加载更多。-->
<cell v-if="conversationList.length" @appear="loadMore()"></cell>
<!-- #endif -->
<uni-list-item :customStyle="{backgroundColor:'#f5f5f5',padding:0}">
<template v-slot:body>
<uni-load-more class="tip" :contentText="loadMoreContentText"
:status="conversationHasMore?'loading':'noMore'"></uni-load-more>
</template>
</uni-list-item>
</uni-list>
<!-- #ifdef H5 -->
</scroll-view>
<!-- #endif -->
</view>
<!-- #ifdef H5 -->
<view id="right-view" v-if="isWidescreen">
<!-- 聊天窗口 -->
<view id="chat-view-box">
<template v-if="!showContactsView && currentConversationId">
<view id="chat-header" v-if="!showContactsView">
<!-- 群标题 -->
<text :selectable="true">{{currentConversation.title}}</text>
<uni-icons @click="showChatInfo" class="more" type="more-filled" size="20"></uni-icons>
</view>
<view id="chat-view">
<chat-view ref="chat-view"></chat-view>
</view>
<view v-if="chatInfoIsShow" class="chatInfoBox" @click.stop="chatInfoIsShow = false">
<uni-im-group-info @click.native.stop v-if="currentConversation.group_id"
:conversation_id="currentConversation.id"></uni-im-group-info>
<uni-im-chat-info @click.native.stop v-else
:conversation_id="currentConversation.id"></uni-im-chat-info>
</view>
</template>
<view v-else id="ccid-is-null-tip">
未选择会话对象
</view>
</view>
<view id="dynamic-component-box" v-show="showContactsView">
<view class="dynamic-component-title">{{view2Title}}</view>
<component ref="dynamicComponent" :is="dynamicComponentName"></component>
</view>
</view>
<!-- #endif -->
</view>
</template>
<script>
const db = uniCloud.database();
// #ifdef H5
import chatView from '@/uni_modules/uni-im/pages/chat/chat';
// #endif
import uniImUtils from '@/uni_modules/uni-im/common/utils.js';
import {
store as uniIdStore,
mutations as uniIdMutations
} from '@/uni_modules/uni-id-pages/common/store.js';
import uniIm from '@/uni_modules/uni-im/lib/main.js';
import contacts from '@/uni_modules/uni-im/pages/contacts/contacts';
// #ifdef H5
import notification from '@/uni_modules/uni-im/pages/contacts/notification/notification';
import addPeopleGroups from '@/uni_modules/uni-im/pages/contacts/addPeopleGroups/addPeopleGroups';
import groupList from '@/uni_modules/uni-im/pages/contacts/groupList/groupList';
import createGroup from '@/uni_modules/uni-im/pages/contacts/createGroup/createGroup';
import chatInfo from '@/uni_modules/uni-im/pages/chat/info';
import groupInfo from '@/uni_modules/uni-im/pages/group/info';
import {version} from '@/uni_modules/uni-im/package.json'
// #endif
let lastConversationId = false
let sortIndex = 0
export default {
// #ifdef H5
components: {
chatView,
"uni-im-contacts": contacts,
"uni-im-notification": notification,
"uni-im-addPeopleGroups": addPeopleGroups,
"uni-im-groupList": groupList,
"uni-im-createGroup": createGroup,
"uni-im-chat-info": chatInfo,
"uni-im-group-info": groupInfo
},
// #endif
data() {
return {
wHeight: 'auto',
userInfo: {},
dynamicComponentName: 'uni-im-addPeopleGroups', //通过动态组件引入页面在pc端显示
view2Title: '加人/加群',
showContactsView: false,
chatInfoIsShow: false,
currentConversation: {}
};
},
computed: {
conversationList(){
sortIndex ++
// console.log('根据会话时间排序',uniIm.conversation.dataList,sortIndex)
let conversationList = uniIm.conversation.dataList
setTimeout(()=> {
sortIndex = 0
}, 1000);
if(sortIndex > 6){
return conversationList
}
return conversationList.sort(function(a, b) {
if(b.id == uniIm.currentConversationId) {
// 当前会话正在输入时不需要重新排序避免change频繁触发导致排序频繁
return 0
}
// 如果该会话的输入框已经输入了内容未发就排在前面
if(b.chatText){
b.update_time = Date.now()
}
let a_update_time = a.update_time || 0
let b_update_time = b.update_time || 0
let aml = a.msgList.length
let bml = b.msgList.length
if (aml) {
let create_time = a.msgList[aml - 1].create_time
if (create_time > a_update_time) {
a_update_time = create_time
}
}
if (bml) {
let create_time = b.msgList[bml - 1].create_time
if (create_time > b_update_time) {
b_update_time = create_time
}
}
return b_update_time - a_update_time
})
},
loadMoreContentText() {
return {
contentrefresh: "正在加载...",
contentnomore: (this.conversationList.length ? "没有更多数据了" : "没有会话数据")
}
},
conversationHasMore() {
return uniIm.conversation.hasMore
},
// 导入uniIm响应式数据支持别名比如:['a as b']
...uniIm.mapState(['currentConversationId', 'isWidescreen']),
unreadMsgCount() {
return uniIm.conversation.unreadCount()
},
unreadnotificationCount() {
return uniIm.notification.unreadCount()
},
currentUserInfo() {
return uniIdStore.userInfo
},
avatarUrl() {
if (this.currentUserInfo.avatar_file && this.currentUserInfo.avatar_file.url) {
return this.currentUserInfo.avatar_file.url
}
return '/uni_modules/uni-im/static/avatarUrl.png'
}
},
watch: {
unreadMsgCount(unreadMsgCount) {
console.log({
unreadMsgCount
});
// #ifdef APP
plus.runtime.setBadgeNumber(unreadMsgCount)
// #endif
if (unreadMsgCount == 0) {
uni.removeTabBarBadge({
index: 0,
complete: (e) => {
console.log(e)
}
})
} else {
uni.setTabBarBadge({
index: 0,
text: unreadMsgCount + '',
complete: (e) => {
// console.log(e)
}
})
}
},
showContactsView(showContactsView) {
if (showContactsView) {
lastConversationId = this.currentConversationId
uniIm.currentConversationId = false
} else {
if (lastConversationId) {
uniIm.currentConversationId = lastConversationId
this.$nextTick(() => {
this.toChat(lastConversationId)
})
}
}
},
async currentConversationId(id) {
this.currentConversation = await uniIm.conversation.get(id)
}
},
created() {
// #ifdef APP-NVUE
this.wHeight = uni.getSystemInfoSync().windowHeight + 'px'
// #endif
},
async onLoad(param) {
let {
token,
user_id,
conversation_id,
joinGroup
} = param
let version = "2023-05-22-01"
// 发布新版本后清理旧版本下的storage避免脏数据引发问题
let lastVersion = uni.getStorageSync('uni-im-storage-version')
if (lastVersion && lastVersion != version) {
uni.setStorageSync('uni-im-storage-version', version)
uni.clearStorage()
}
let {
tokenExpired
} = uniCloud.getCurrentUserInfo()
if (!tokenExpired || tokenExpired < Date.now()) {
console.info('当前用户的登录状态无效,将自动跳转至登录页面。', param)
let url = '/uni_modules/uni-id-pages/pages/login/login-withpwd?uniIdRedirectUrl='
let paramString = '/uni_modules/uni-im/pages/index/index?'
for (let key in param) {
paramString += `${key}=${param[key]}&`
}
paramString = paramString.substring(0, paramString.length - 1) //携带参数,实现登录成功后 跳回首页时传回
url += encodeURIComponent(paramString)
return uni.reLaunch({
url
})
}
this.$nextTick(() => {
this.init({
user_id,
conversation_id
})
})
this.onLoginSuccess = async () => {
this.init({
user_id,
conversation_id
})
}
uni.$on('uni-id-pages-login-success', this.onLoginSuccess)
uni.$on('uni-im-toChat', param => {
if (param) {
// 关闭最后一次的会话id防止切回后重新显示最后一次会话而邮箱指定显示到某个会话
lastConversationId = false
this.toChat(param)
}
this.showContactsView = false
})
/**
* 在本页面链接传递参数 joinGroup=group_id即可申请加入群
* 比如http://localhost:8082/#/uni_modules/uni-im/pages/index/index?joinGroup=xxx
*/
if(joinGroup){
let group_id = joinGroup
// #ifdef H5
//删除地址栏的token且不刷新页面
history.pushState({}, '', '/#/');
// #endif
console.log('group_id',group_id);
db.collection('uni-im-group-join').add({
group_id,
"message":''
}).then((res) => {
console.log("res: ",res);
uni.showToast({
icon: 'none',
title: '已申请'
})
}).catch((err) => {
uni.showModal({
content: err.message || '请求服务失败',
showCancel: false
})
})
}
},
async onReady() {
// #ifdef H5
let systemInfo = uni.getSystemInfoSync()
uniIm.systemInfo = systemInfo
// console.log('systemInfo',systemInfo);
if (!['edge', 'chrome', 'safari'].includes(systemInfo.browserName)) {
let newElement = document.createElement('div')
newElement.innerHTML = `
<div style="background: #fff9ea;color: #ff9a43;position: fixed;top: 0;left: 0;width: 100vw;padding: 15px;font-size: 18px;">
注意本系统仅兼容chrome、edge、safari浏览器
</div>
`
document.body.appendChild(newElement)
}
// #endif
},
onUnload() {
uni.$off('uni-id-pages-login-success', this.onLoginSuccess)
},
onHide() {},
methods: {
clickSearchBarBox(){
uni.showToast({
title: '暂不支持',
icon: 'none'
});
},
async loadMore() {
let data = await uniIm.conversation.loadMore()
return data
},
clickMenu(data) {
// console.log('79879789798898798978789', data);
this.dynamicComponentName = data.componentName
if (data.title) {
this.view2Title = data.title
}
if (data.param) {
this.$nextTick(() => {
this.$refs.dynamicComponent.setParam(data.param)
})
}
// console.log('data.componentName----',data.componentName);
if (data.componentName == 'uni-im-createGroup') {
this.$nextTick(() => {
this.$refs.dynamicComponent.getFriendsData()
})
}
},
readQrCode() {
uni.scanCode({
complete: (e) => {
// console.log(e);
try {
let data = JSON.parse(e.result)
// console.log(data);
if (data.type == 'uni-im' && data.subType == "groupInfo") {
}
} catch (e) {
//TODO handle the exception
}
}
})
},
async init({
conversation_id,
user_id
}) {
// 初始化会话列表
// console.log('初始化会话列表',{
// conversation_id,
// user_id,
// });
await this.loadMore()
if (conversation_id) {
// console.log('conversation_id', conversation_id);
this.toChat(conversation_id)
} else if (user_id) {
//创建会话
const currentConversation = await uniIm.conversation.get({
friend_uid: user_id
})
// console.log('currentConversation', currentConversation);
// 当前用户给对方发个消息
this.toChat(currentConversation.id)
} else {
if (this.isWidescreen) {
let [firstConversation] = this.conversationList
if (firstConversation) {
this.currentConversation = await uniIm.conversation.get(firstConversation.id)
this.toChat(firstConversation.id)
} else {
// uni.showModal({
// content: '没有任何会话,请先到用户列表选择用户',
// showCancel: false
// });
}
}
}
},
search(e) {
// console.log("search-e: " + JSON.stringify(e));
uni.showToast({
title: '加好友功能入口,暂时在左侧菜单的通讯录中',
icon: 'none',
duration: 3000
});
},
addUser() {
uni.showToast({
title: '加好友功能入口,暂时在左侧菜单的通讯录中',
icon: 'none',
duration: 3000
});
},
async toChat(param) {
this.chatInfoIsShow = false;
// console.log('param',param);
let conversation_id = ''
if (typeof param == 'string') {
conversation_id = param
} else {
if (param.conversation_id) {
conversation_id = param.conversation_id
} else if (param.group_id) {
conversation_id = 'group_' + param.group_id
} else if (param.user_id || param.friend_uid) {
conversation_id = uniImUtils.getConversationId(param.user_id || param.friend_uid)
// console.log('conversation_id',conversation_id)
} else {
throw new Error("toChat param is error")
}
}
uniIm.currentConversationId = conversation_id
if (this.isWidescreen) { //若为宽屏,则触发右侧详情页的自定义事件,通知右侧窗体刷新详情
this.$nextTick(() => {
let chatViewRef = this.$refs['chat-view']
if (chatViewRef) {
chatViewRef.load(conversation_id)
}
})
} else { // 若为窄屏,则打开新窗体,在新窗体打开详情页面
uni.navigateTo({
url: '/uni_modules/uni-im/pages/chat/chat?conversation_id=' + conversation_id,
animationDuration: 300
})
}
},
showChatInfo() {
this.chatInfoIsShow = !this.chatInfoIsShow
},
toUcenter() {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/userinfo/userinfo?showLoginManage=true',
complete(e) {
console.log("e: " + JSON.stringify(e));
}
})
},
friendlyTime(timestamp) {
return uniImUtils.toFriendlyTime(timestamp)
},
},
async onReachBottom() {
await this.loadMore()
},
onNavigationBarButtonTap(e) {
// console.log(e);
if (e.index) {
let data = uni.getStorageInfoSync();
// console.log('data.keys', JSON.stringify(data.keys));
data.keys.forEach(item => {
if (item.includes('uni-im-msg:') || item.includes('uni-im-conversation')) {
// console.log(item);
uni.removeStorageSync(item);
// console.log(uni.getStorageSync(item));
}
});
uni.showToast({
title: 'clear storage ok',
icon: 'none'
});
} else {
uni.navigateTo({
url: '/uni_modules/uni-id-pages/pages/userinfo/userinfo?showLoginManage=true',
complete: e => {
console.log(e);
}
});
}
}
}
</script>
<style lang="scss" scoped>
@import url("./index.scss");
</style>