This commit is contained in:
zoujiandong
2024-01-22 08:55:30 +08:00
parent 22f3da6c33
commit 2bd2fd31ac
3460 changed files with 136738 additions and 0 deletions
@@ -0,0 +1,338 @@
import { caculateTimeago } from '../../../../utils/common';
const app = getApp();
// eslint-disable-next-line no-undef
Component({
/**
* 组件的属性列表
*/
properties: {
conversation: {
type: Object,
value: {},
observer(conversation) {
this.setData({
conversationName: this.getConversationName(conversation),
setConversationAvatar: this.setConversationAvatar(conversation),
});
this.setMuteIcon(conversation);
this.showMuteIconImg(conversation);
this.$updateTimeAgo(conversation);
this.setPinName(conversation.isPinned);
},
},
charge: {
type: Boolean,
value: {},
observer(charge) {
if (!charge) {
this.setData({
xScale: 0,
});
}
},
},
statusList: {
type: Array,
value: [],
observer(statusList) {
this.setUserStatus(this.data.conversation, statusList);
},
},
},
/**
* 组件的初始数据
*/
data: {
xScale: 0,
conversationName: '',
conversationAvatar: '',
conversation: {},
showName: '',
showMessage: '',
showPin: '置顶聊天',
showMute: '消息免打扰',
popupToggle: false,
isTrigger: false,
num: 0,
setShowName: '',
showMuteIcon: false,
showStatus: false,
},
lifetimes: {
attached() {
},
},
pageLifetimes: {
// 展示已经置顶的消息和更新时间戳
show() {
this.showMuteIconImg(this.data.conversation);
this.setPinName(this.data.conversation.isPinned);
this.setMuteIcon(this.data.conversation);
this.$updateTimeAgo(this.data.conversation);
},
// 隐藏动画
hide() {
this.setData({
xScale: 0,
});
},
},
/**
* 组件的方法列表
*/
methods: {
// 切换置顶聊天状态
setPinName(isPinned) {
this.setData({
showPin: isPinned ? '取消置顶' : '置顶聊天',
});
},
// 切换免打扰状态
setMuteIcon(conversation) {
this.setData({
showMute: (conversation.messageRemindType === 'AcceptNotNotify') ? '取消免打扰' : '消息免打扰',
});
},
// 先查 remark;无 remark 查 (c2c)nick/(group)name;最后查 (c2c)userID/(group)groupID
// 群会话,先展示namecard,无namecard展示nick,最展示UserID
getConversationName(conversation) {
if (conversation.type === '@TIM#SYSTEM') {
return '系统通知';
}
if (conversation.type === 'C2C') {
return conversation.remark || conversation.userProfile.nick || conversation.userProfile.userID;
}
if (conversation.type === 'GROUP') {
if (conversation.lastMessage.nameCard !== '') {
this.data.setShowName = conversation.lastMessage.nameCard;
} else if (conversation.lastMessage.nick !== '') {
this.data.setShowName = conversation.lastMessage.nick;
} else {
if (conversation.lastMessage.fromAccount === wx.$chat_userID) {
this.data.setShowName = '我';
} else {
this.data.setShowName = conversation.lastMessage.fromAccount;
}
}
this.setData({
showName: this.data.setShowName,
});
return conversation.groupProfile.name || conversation.groupProfile.groupID;
}
},
// 设置会话的头像
setConversationAvatar(conversation) {
if (conversation.type === '@TIM#SYSTEM') {
return 'https://web.sdk.qcloud.com/component/TUIKit/assets/system.png';
}
if (conversation.type === 'C2C') {
return conversation.userProfile.avatar || 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png';
}
if (conversation.type === 'GROUP') {
return conversation.groupProfile.avatar || '../../../../static/assets/gruopavatar.svg';
}
},
// 删除会话
deleteConversation() {
wx.showModal({
content: '确认删除会话?',
success: (res) => {
if (res.confirm) {
wx.aegis.reportEvent({
name: 'conversationOptions',
ext1: 'conversation-delete',
ext2: wx.$chat_reportType,
ext3: wx.$chat_SDKAppID,
});
wx.$TUIKit.deleteConversation(this.data.conversation.conversationID);
this.setData({
conversation: {},
xScale: 0,
});
}
},
});
},
// 消息置顶
pinConversation() {
wx.aegis.reportEvent({
name: 'conversationOptions',
ext1: 'conversation-top',
ext2: wx.$chat_reportType,
ext3: wx.$chat_SDKAppID,
});
wx.$TUIKit.pinConversation({ conversationID: this.data.conversation.conversationID, isPinned: true })
.then(() => {
this.setData({
xScale: 0,
});
})
.catch((imError) => {
console.warn('pinConversation error:', imError); // 置顶会话失败的相关信息
});
if (this.data.showPin === '取消置顶') {
wx.$TUIKit.pinConversation({ conversationID: this.data.conversation.conversationID, isPinned: false })
.then(() => {
this.setData({
xScale: 0,
});
})
.catch((imError) => {
console.warn('pinConversation error:', imError); // 置顶会话失败的相关信息
});
}
},
// 是否显示免打扰图标
showMuteIconImg(conversation) {
if (conversation.messageRemindType === 'AcceptNotNotify') {
this.setData({
showMuteIcon: true,
});
} else {
this.setData({
showMuteIcon: false,
});
}
},
// 消息免打扰
muteNotifications() {
wx.aegis.reportEvent({
name: 'conversationOptions',
ext1: 'conversation-mutenotifications',
ext2: wx.$chat_reportType,
ext3: wx.$chat_SDKAppID,
});
let newShowMute = '';
let newShowMuteIcon = false;
let messageRemindType = wx.$TUIKitTIM.TYPES.MSG_REMIND_ACPT_NOT_NOTE;
if (this.data.showMute === '消息免打扰') {
newShowMute = '取消免打扰';
newShowMuteIcon = true;
messageRemindType = wx.$TUIKitTIM.TYPES.MSG_REMIND_ACPT_NOT_NOTE;
}
if (this.data.showMute === '取消免打扰') {
newShowMute = '消息免打扰';
newShowMuteIcon = false;
messageRemindType = wx.$TUIKitTIM.TYPES.MSG_REMIND_ACPT_AND_NOTE;
}
if (this.data.conversation.type === 'C2C') {
// C2C 消息免打扰,一般的实现是在线接收消息,离线不接收消息(在有离线推送的情况下),v2.16.0起支持
const { userID } = this.data.conversation.userProfile;
wx.$TUIKit.setMessageRemindType({
userIDList: [userID],
messageRemindType,
})
.then((imResponse) => {
this.setData({
xScale: 0,
showMuteIcon: newShowMuteIcon,
showMute: newShowMute,
});
})
.catch((imError) => {
console.warn('setMessageRemindType error:', imError);
});
}
if (this.data.conversation.type === 'GROUP') {
const { groupID } = this.data.conversation.groupProfile;
// 群消息免打扰,一般的实现是在线接收消息,离线不接收消息(在有离线推送的情况下)
wx.$TUIKit.setMessageRemindType({
groupID,
messageRemindType,
})
.then((imResponse) => {
this.setData({
xScale: 0,
showMuteIcon: newShowMuteIcon,
showMute: newShowMute,
});
// 设置消息免打扰成功
})
.catch((imError) => {
// 设置消息免打扰失败
console.warn('setMessageRemindType error:', imError);
});
}
},
// 控制左滑动画
handleTouchMove(e) {
this.setData({
num: e.detail.x,
});
if (e.detail.x < 0 && !this.data.isTrigger) {
this.setData({
isTrigger: true,
});
this.triggerEvent('transCheckID', {
checkID: this.data.conversation.conversationID,
});
}
if (e.detail.x === 0) {
this.setData({
isTrigger: false,
});
}
},
handleTouchEnd() {
if (this.data.num < -wx.getSystemInfoSync().windowWidth / 5) {
this.setData({
xScale: -wx.getSystemInfoSync().windowWidth,
});
}
if (this.data.num >= -wx.getSystemInfoSync().windowWidth / 5 && this.data.num < 0) {
this.setData({
xScale: 0,
});
}
},
// 更新会话的时间戳,显示会话里的最后一条消息
$updateTimeAgo(conversation) {
if (conversation.conversationID && conversation.lastMessage.lastTime) {
conversation.lastMessage.timeago = caculateTimeago(conversation.lastMessage.lastTime * 1000);
if (conversation.lastMessage.isRevoked) {
this.setData({
showMessage: '撤回了一条消息',
});
} else {
this.setData({
showMessage: conversation.lastMessage.messageForShow,
});
}
this.setData({
conversation,
});
}
},
// 会话头像显示失败显示的默认头像
handleimageerro() {
this.setData({
setConversationAvatar: '../../../../static/assets/gruopavatar.svg',
});
},
// 判断该用户的状态并展示出来
setUserStatus(conversation, statusList) {
// if (!wx.getStorageSync('showOnlineStatus')) return;
const currentUserID = wx.getStorageSync('currentUserID');
if (currentUserID.includes(wx.$chat_userID)) {
this.setData({
getStatus: wx.getStorageSync(wx.$chat_userID),
});
} else {
this.setData({
getStatus: true,
});
}
if (conversation.type !== wx.$TUIKitTIM.TYPES.CONV_C2C) return;
statusList.forEach((item) => {
if (item.userID !== conversation.userProfile.userID) return;
const showStatus = (item.statusType === 1);
this.setData({
showStatus,
});
});
},
},
});
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
@@ -0,0 +1,59 @@
<movable-area wx:if="{{conversation.conversationID}}" class="t-conversation-item-container">
<movable-view
class="t-conversation-item {{conversation.isPinned && 't-conversation-pinneditem'}}"
bind:touchend="handleTouchEnd" direction="horizontal" bindchange="handleTouchMove" damping="100"
x="{{xScale}}" inertia out-of-bounds
>
<view class="avatar-box">
<image class="t-conversation-item-avatar" src="{{setConversationAvatar}}" binderror="handleimageerro">
</image>
<view class="right-box">
<view
class="unread"
wx:if="{{conversation.unreadCount !== 0 && conversation.messageRemindType !== 'AcceptNotNotify'}}"
>
<view class="read-text" wx:if="{{conversation.unreadCount > 99}}">99+</view>
<view class="read-text" wx:else>{{conversation.unreadCount}}</view>
</view>
<view wx:if="{{conversation.unreadCount !== 0}}">
<view class="unread-mute" wx:if="{{conversation.messageRemindType === 'AcceptNotNotify'}}">
</view>
</view>
<i wx:if="{{conversation.type === 'C2C' && getStatus && showStatus}}" class="status {{showStatus && 'status-online'}}"></i>
<i wx:if="{{conversation.type === 'C2C' && getStatus && !showStatus}}" class="statusType {{!showStatus && 'status-offline'}}"></i>
</view>
</view>
<view class="t-conversation-item-content">
<label class="tui-conversation-item-name">{{conversationName}}</label>
<view class="tui-conversation-box">
<view class="tui-conversation-lastName" wx:if="{{conversation.type === 'GROUP'}}">
<text>{{showName}}:</text>
</view>
<view class="tui-conversation-lastMessage"
wx:if="{{conversation.unreadCount !== 0 && conversation.messageRemindType === 'AcceptNotNotify'}}">
<view class="text-box">
<text>[{{conversation.unreadCount}}条]</text>
<text class="lastMessage-payload">{{showMessage}}</text>
</view>
</view>
<view wx:else class="tui-conversation-lastMessage">
<text class="lastMessage-payload">{{showMessage}}</text>
</view>
</view>
</view>
<view class="t-conversation-item-box">
<view class="t-conversation-item-info">
{{conversation.lastMessage.timeago}}
</view>
<view wx:if="{{showMuteIcon}}" class="t-conversation-item-mutenotifications">
<image class="t-conversation-mutenotifications-img" src="../../../../static/images/mutenotifications.png"/>
</view>
</view>
<view class="t-conversation-box">
<view class="t-conversation-mutenotifications" catchtap="muteNotifications">{{showMute}}</view>
<view class="t-conversation-pinconversation" catchtap="pinConversation">{{showPin}}</view>
<view class="t-conversation-delete" catchtap="deleteConversation">删除</view>
</view>
</movable-view>
</movable-area>
@@ -0,0 +1,188 @@
.t-conversation-item-container {
width: 100vw;
height: 150rpx;
background-color: #FFFFFF;
}
.t-conversation-item {
width: 162vw;
height: 150rpx;
display: flex;
left: 0;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
border-bottom: 2rpx solid #EEF0F3;
}
.t-conversation-pinneditem{
width: 162vw;
height: 150rpx;
display: flex;
left: 0;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
border-bottom: 1rpx solid #999999;
background-color: #EEF0F3
}
.text-box{
display: flex;
}
.avatar-box{
position: relative;
display: inline-flex;
}
.t-conversation-item-avatar{
position: relative;
width: 96rpx;
height: 96rpx;
border-radius: 14rpx;
/*padding-left: 40rpx;*/
/*padding-right: 24rpx;*/
/*padding-bottom: 28rpx;*/
/*padding-top: 28rpx;*/
margin: 0 16rpx;
overflow: auto;
}
.t-conversation-item-content {
flex: 1;
padding-left: 20rpx;
}
.t-conversation-item-info {
line-height: 34rpx;
font-size: 24rpx;
color: #999999;
margin-right: 30rpx;
}
.t-error {
background-color: #fb5250;
color: #fff;
}
.t-conversation-delete {
width: 144rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #E85454;
color: #FFFFFF;
line-height: 44rpx;
font-size: 32rpx;
}
.t-conversation-item-mutenotifications{
margin-right: 40rpx;
}
.t-conversation-mutenotifications-img{
height: 34rpx;
width: 28rpx;
float: right;
}
.t-conversation-pinconversation{
width: 144rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #006EFF;
color: #FFFFFF;
line-height: 44rpx;
font-size: 32rpx;
}
.t-conversation-mutenotifications{
width: 180rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: orange;
color: #FFFFFF;
line-height: 44rpx;
font-size: 32rpx;
}
.tui-conversation-item-name {
line-height: 50rpx;
font-size: 36rpx;
font-family: 'PingFangSC-Regular';
color: #333333;
}
.tui-conversation-lastMessage {
line-height: 40rpx;
font-size: 28rpx;
font-family: 'PingFangSC-Regular';
color: #999999;
max-width: 64vw;
display: inline-block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.right-box{
display:flex;
position: absolute;
top: -10rpx;
right: 31rpx;
}
.unread {
position: absolute;
top: -5rpx;
right: -25rpx;
width: 32rpx;
height: 32rpx;
border-radius: 50%;
display: flex;
align-items: center;
color: #ffffff;
background-color: red;
justify-content: center;
}
.unread-mute{
width: 20rpx;
height: 20rpx;
background: #FA5151;
border-radius: 50%;
position: absolute;
top: 0rpx;
right: -20rpx;
}
.read-text {
line-height: 15px;
font-size: 10px;
}
.tui-conversation-box{
display: flex;
}
.tui-conversation-lastName{
line-height: 40rpx;
font-size: 28rpx;
font-family: 'PingFangSC-Regular';
color: #999999;
}
.t-conversation-box{
height: 150rpx;
display: flex
}
.status {
position: relative;
top: 84rpx;
left: 23rpx;
width: 18rpx;
height: 18rpx;
opacity: 1;
border-radius: 8px;
background: #29CC85;
}
.statusType {
position: relative;
top: 84rpx;
left: 23rpx;
width: 18rpx;
height: 18rpx;
opacity: 1;
border-radius: 8px;
background: #A4A4A4;
}
.status-online {
border: 4rpx solid white;
}
.status-offline{
border: 4rpx solid white;
}
@@ -0,0 +1,89 @@
// eslint-disable-next-line no-undef
// Component Object
Component({
properties: {
myProperty: {
type: String,
value: '',
observer() {},
},
},
data: {
userID: '',
searchUser: {},
myID: '',
},
methods: {
goBack() {
this.triggerEvent('showConversation');
},
// 获取输入的 UserID
userIDInput(e) {
this.setData({
userID: e.detail.value,
searchUser: {},
});
},
// 获取该 UserID 对应的个人资料
getuserProfile() {
wx.$TUIKit.getUserProfile({
userIDList: [this.data.userID],
}).then((imRes) => {
if (imRes.data.length > 0) {
this.setData({
searchUser: imRes.data[0],
});
} else {
wx.showToast({
title: '用户不存在',
icon: 'error',
});
this.setData({
userID: '',
});
}
});
},
// 选择发起会话
handleChoose() {
this.data.searchUser.isChoose = !this.data.searchUser.isChoose;
this.setData({
searchUser: this.data.searchUser,
});
},
// 确认邀请
bindConfirmInvite() {
if (this.data.searchUser.isChoose) {
wx.aegis.reportEvent({
name: 'conversationType',
ext1: 'conversationType-c2c',
ext2: wx.$chat_reportType,
ext3: wx.$chat_SDKAppID,
});
this.triggerEvent('searchUserID', { searchUserID: `C2C${this.data.searchUser.userID}` });
} else {
wx.showToast({
title: '请选择相关用户',
icon: 'none',
});
}
},
},
created() {
},
attached() {
this.setData({
myID: wx.$chat_userID,
});
},
ready() {
},
moved() {
},
detached() {
},
});
@@ -0,0 +1,4 @@
{
"usingComponents": {},
"navigationStyle": "custom"
}
@@ -0,0 +1,25 @@
<view class="TUI-Create-conversation-container">
<view class="tui-navigatorbar">
<image class="tui-navigatorbar-back" bindtap="goBack" src="../../../../static/assets/ic_back_white.svg" />
<view class="conversation-title">发起会话</view>
</view>
<view class="tui-search-area">
<view class="tui-search-bar">
<image class="tui-searchcion" src="../../../../static/assets/serach-icon.svg" />
<input class="tui-search-bar-input" value="{{userID}}" placeholder="请输入用户ID" bindinput='userIDInput' bindconfirm="getuserProfile" bindblur="getuserProfile"/>
</view>
<view class="tui-showID">您的用户ID {{myID}}</view>
</view>
<view class="tui-person-to-invite" wx:if="{{searchUser.userID}}" bindtap="handleChoose" >
<image class="tui-normal-choose" src="{{searchUser.isChoose ? '../../../../static/assets/single-choice-hover.svg' : '../../../../static/assets/single-choice-normal.svg'}}" />
<view class="tui-person-profile">
<image class="tui-person-profile-avatar" src="{{searchUser.avatar || 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png' }}" />
<view>
<view class="tui-person-profile-nick">{{searchUser.nick}}</view>
<view class="tui-person-profile-userID">用户ID{{searchUser.userID}}</view>
</view>
</view>
</view>
<view class="tui-confirm-btn" bindtap="bindConfirmInvite">确认邀请</view>
</view>
@@ -0,0 +1,138 @@
.TUI-Create-conversation-container {
width: 100vw;
height: 100vh;
background-color: #F4F5F9;
}
.tui-navigatorbar{
position: absolute;
top: 0;
width: 750rpx;
height: 170rpx;
background-color: #006EFF;
}
.tui-navigatorbar-back{
position: absolute;
width: 60rpx;
height: 60rpx;
left: 24rpx;
bottom: 15rpx;
}
.conversation-title {
position:absolute;
width: 350rpx;
height: 88rpx;
line-height: 56rpx;
font-size: 36rpx;
color: #FFFFFF;
bottom: 0;
left: 200rpx;
display: flex;
justify-content: center;
align-items: center;
}
.tui-search-area {
position: absolute;
top: 170rpx;
width: 750rpx;
background-color: #006EFF;
}
.tui-showID {
padding-left: 80rpx;
ine-height: 40rpx;
font-size: 28rpx;
color: white;
height: 50rpx;
padding-top: 18rpx;
}
.tui-search-bar {
display: flex;
flex-wrap: nowrap;
align-items: center;
margin-left: 40rpx;
margin-top: 32rpx;
width: 670rpx;
height: 80rpx;
background: #FFFFFF;
border-radius: 40rpx;
border-radius: 40rpx;
}
.tui-searchcion {
display: inline-block;
margin-left: 24rpx;
width: 48rpx;
height: 48rpx;
}
.tui-search-bar-input {
margin-left: 16rpx;
line-height: 40rpx;
font-size: 28rpx;
width: 100%;
display: inline-block;
}
.tui-person-to-invite {
position: absolute;
top: 352rpx;
display: flex;
flex-wrap: nowrap;
width: 750rpx;
height: 150rpx;
background-color: #FFFFFF;
}
.tui-normal-choose {
margin-left: 40rpx;
margin-right: 40rpx;
margin-top: 52rpx;
margin-bottom: 50rpx;
width: 48rpx;
height: 48rpx;
}
.tui-person-profile {
width: 622rpx;
display: flex;
align-items: center;
}
.tui-person-profile-avatar {
width: 96rpx;
height: 96rpx;
margin-right: 24rpx;
}
.tui-person-profile-nick {
color: #333333;
line-height: 50rpx;
font-size: 36rpx;
margin-bottom: 4rpx;
}
.tui-person-profile-userID {
color: #999999;
line-height: 40rpx;
font-size: 28rpx;
}
.tui-confirm-btn {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
bottom: 100rpx;
width: 670rpx;
height: 96rpx;
background: #006EFF;
color: #FFFFFF;
border-radius: 48rpx;
border-radius: 48rpx;
margin-left: 40rpx;
line-height: 44rpx;
font-size: 32rpx;
}
@@ -0,0 +1,105 @@
// miniprogram/pages/TUI-Group/create-group/create.js
import logger from '../../../../utils/logger';
Component({
properties: {
},
data: {
groupTypeList: [
],
groupType: '',
Type: '',
name: '',
groupID: '',
},
methods: {
goBack() {
this.triggerEvent('showConversation');
},
// 展示群列表
showGroupTypeList() {
this.setData({
popupToggle: true,
});
},
// 获取输入的群ID
bindGroupIDInput(e) {
const id = e.detail.value;
this.setData({
groupID: id,
});
},
// 获取输入的群名称
bindGroupNameInput(e) {
const groupname = e.detail.value;
this.setData({
name: groupname,
});
},
// 创建群聊时,传点击事件对应的值
click(e) {
this.setData({
groupType: e.currentTarget.dataset.value.groupType,
Type: e.currentTarget.dataset.value.Type,
name: e.currentTarget.dataset.value.name,
popupToggle: false,
});
},
// 确认创建群聊
bindConfirmCreate() {
logger.log(`| TUI-Group | create-group | bindConfirmCreate | groupID: ${this.data.groupID}`);
wx.$TUIKit.createGroup({
type: this.data.Type,
name: this.data.name,
groupID: this.data.groupID,
}).then((imResponse) => { // 创建成功
this.triggerEvent('createGroupID', { createGroupID: `GROUP${imResponse.data.group.groupID}` });
// 创建的群的资料
wx.aegis.reportEvent({
name: 'conversationType',
ext1: 'conversationType-group',
ext2: wx.$chat_reportType,
ext3: wx.$chat_SDKAppID,
});
})
.catch((imError) => {
if (imError.code === 10021) {
wx.showToast({
title: '该群组ID被使用,请更换群ID',
icon: 'none',
});
}
});
},
// 点击空白区域关闭弹窗
handleChooseToggle() {
this.setData({
popupToggle: false,
});
},
},
created() {
},
attached() {
},
ready() {
const groupTypeList = [
{ groupType: '品牌客户群(Work)', Type: wx.$TUIKitTIM.TYPES.GRP_WORK },
{ groupType: 'VIP专属群(Public)', Type: wx.$TUIKitTIM.TYPES.GRP_PUBLIC },
{ groupType: '临时会议群 (Meeting)', Type: wx.$TUIKitTIM.TYPES.GRP_MEETING },
{ groupType: '直播群(AVChatRoom', Type: wx.$TUIKitTIM.TYPES.GRP_CHATROOM },
];
this.setData({
groupTypeList,
});
},
moved() {
},
detached() {
},
});
@@ -0,0 +1,3 @@
{
"usingComponents": {}
}
@@ -0,0 +1,52 @@
<!--miniprogram/pages/TUI-Group/create-group/create.wxml-->
<view class="container">
<view class="tui-navigatorbar">
<image class="tui-navigatorbar-back" bindtap="goBack" src="../../../../static/assets/ic_back_white.svg" />
<view class="conversation-title">发起群聊</view>
</view>
<view class="group-area">
<view class="item" catchtap="showGroupTypeList">
<view class="group-type" >
<view class="icon-box">
<text class="icon">*</text>
<text class="aside-left">群类型</text>
<text class= "aside-right" bindtap="click">{{groupType}}</text>
</view>
<image class=" listimage" src="../../../static/detail.svg"></image>
</view>
</view>
<view class="item">
<view class="group-ID">
<text class="aside-left">群ID</text>
<input class="input" type="number" placeholder="请输入群ID" bindinput='bindGroupIDInput' placeholder-style="color:#BBBBBB;"/>
</view>
</view>
<view class="item">
<view class="group-name">
<view class="icon-box">
<text class="icon">*</text>
<text class="aside-left">群名称</text>
</view>
<input class="inputname" placeholder="请输入群名称" bindinput='bindGroupNameInput' placeholder-style="color:#BBBBBB;"/>
</view>
</view>
</view>
<view class="create-area">
<view class="group-create" bindtap="bindConfirmCreate">
<text>发起群聊</text></view>
</view>
</view>
<view class="pop-mask" wx:if="{{popupToggle}}" catchtap="handleChooseToggle" >
<view class="popup-main" catchtap="handleCatchTap">
<view wx:for="{{groupTypeList}}" wx:key="id" class="type {{item.groupType === groupType &&'type-active'}}" data-value="{{item}}" bindtap="click">
<view class="group-type-list" data-item="{{item}}">
<view class="list-type">
<view>{{item.groupType}}</view>
</view>
</view>
</view>
</view>
</view>
@@ -0,0 +1,182 @@
/* miniprogram/pages/TUI-Group/create-group/create.wxss */
.container{
background: #EEF0F3;
width: 100vw;
height: 100vh;
}
.tui-navigatorbar{
position: absolute;
top: 0;
width: 750rpx;
height: 170rpx;
background-color: #006EFF;
}
.tui-navigatorbar-back{
position: absolute;
width: 60rpx;
height: 60rpx;
left: 24rpx;
bottom: 15rpx;
}
.conversation-title {
position:absolute;
width: 350rpx;
height: 88rpx;
line-height: 56rpx;
font-size: 36rpx;
color: #FFFFFF;
bottom: 0;
left: 200rpx;
display: flex;
justify-content: center;
align-items: center;
}
.group-area{
position: absolute;
top: 170rpx;
width: 750rpx;
background-color: #006EFF;
}
.item{
display: flex;
width: 100%;
justify-content: left;
align-items: center;
}
.icon-box{
display: flex;
}
.icon{
color:red;
padding-top: 34rpx;
}
.group-type{
background: #FFFFFF;
position: relative;
width: 100%;
height: 56px;
padding-left: 20px;
border-bottom: 1px solid #EEF0F3;
border-top: 8px solid #FFFFFF;
}
.group-ID{
background: #FFFFFF;
position: relative;
width: 100%;
height: 56px;
padding-left: 20px;
border-bottom: 1px solid #EEF0F3;
border-top: 8px solid #FFFFFF;
}
.listimage{
width: 16px;
height: 16px;
position: absolute;
top: 20px;
right: 10px;
}
.group-name{
background: #FFFFFF;
display: flex;
width: 100%;
height: 56px;
padding-left: 20px;
border-bottom: 1px solid #EEF0F3;
border-top: 8px solid #FFFFFF;
}
.aside-left {
display: flex;
align-items: center;
float: left;
font-family: PingFangSC-Regular;
font-size: 16px;
color: #333333;
letter-spacing: 0;
line-height: 56px;
}
.aside-right{
font-family: PingFangSC-Regular;
font-size: 16px;
color: black;
letter-spacing: 0;
padding-left: 104px;
line-height: 56px;
z-index: 999;
}
.input{
float: right;
font-family: PingFangSC-Regular;
font-size: 16px;
color: #999999;
letter-spacing: 0;
text-align: right;
line-height: 56px;
padding-top: 19px;
padding-right: 48px;
width: 70%;
/* z-index: 999; */
}
.inputname{
font-family: PingFangSC-Regular;
font-size: 16px;
color: #999999;
letter-spacing: 0;
text-align: right;
line-height: 56px;
padding-left: 180rpx;
padding-top: 19px;
width: 50%;
}
.group-create{
position: absolute;
display: flex;
justify-content: center;
align-items: center;
bottom: 100rpx;
width: 670rpx;
height: 96rpx;
background: #006EFF;
color: #FFFFFF;
border-radius: 48rpx;
border-radius: 48rpx;
line-height: 44rpx;
font-size: 32rpx;
}
.pop-mask{
width: 100vw;
height: 100vh;
position: fixed;
z-index: 10;
top: 0;
right: 0;
background: rgba(0,0,0,0.60);
display: flex;
align-items: flex-end;
}
.create-area{
display: flex;
align-items: center;
justify-content: center
}
.popup-main{
width: 100vw;
height: 30%;
background: #FFFFFF;
padding: 32px 20px;
}
.group-type-list{
width: 100vw;
height: 112rpx
}
.list-type{
font-family: PingFangSC-Regular;
font-size: 16px;
color: #333333;
letter-spacing: 0;
line-height: 22px;
}
.type-active{
color: #006EFF;
}
@@ -0,0 +1,117 @@
import logger from '../../../../utils/logger';
// Component Object
Component({
properties: {
myProperty: {
type: String,
value: '',
observer() {},
},
},
data: {
groupID: '',
searchGroup: {},
},
methods: {
// 回退
goBack() {
this.triggerEvent('showConversation');
},
// 获取输入的群ID
getGroupIDInput(e) {
this.setData({
groupID: e.detail.value,
});
},
// 通过输入的群ID来查找群
searchGroupByID() {
wx.$TUIKit.searchGroupByID(this.data.groupID)
.then((imResponse) => {
if (imResponse.data.group.groupID !== '') {
this.setData({
searchGroup: imResponse.data.group,
});
}
})
.catch((imError) => {
wx.hideLoading();
if (imError.code === 10007) {
wx.showToast({
title: '讨论组类型群不允许申请加群',
icon: 'none',
});
} else {
wx.showToast({
title: '未找到该群组',
icon: 'none',
});
}
});
},
// 选择查找到的群
handleChoose() {
this.data.searchGroup.isChoose = !this.data.searchGroup.isChoose;
this.setData({
searchGroup: this.data.searchGroup,
});
},
// 确认加入
bindConfirmJoin() {
wx.aegis.reportEvent({
name: 'conversationType',
ext1: 'conversationType-join',
ext2: wx.$chat_reportType,
ext3: wx.$chat_SDKAppID,
});
logger.log(`| TUI-Group | join-group | bindConfirmJoin | groupID: ${this.data.groupID}`);
wx.$TUIKit.joinGroup({ groupID: this.data.groupID, type: this.data.searchGroup.type })
.then((imResponse) => {
if (this.data.searchGroup.isChoose) {
if (imResponse.data.status === 'WaitAdminApproval') {
wx.showToast({
title: '等待管理员同意',
icon: 'none',
});
} else {
this.triggerEvent('searchGroupID', { searchGroupID: `GROUP${this.data.searchGroup.groupID}` });
}
} else {
wx.showToast({
title: '请选择相关群聊',
icon: 'error',
});
}
switch (imResponse.data.status) {
case wx.$TUIKitTIM.TYPES.JOIN_STATUS_WAIT_APPROVAL:
// 等待管理员同意
break;
case wx.$TUIKitTIM.TYPES.JOIN_STATUS_SUCCESS: // 加群成功
break;
case wx.$TUIKitTIM.TYPES.JOIN_STATUS_ALREADY_IN_GROUP: // 已经在群中
break;
default:
break;
}
})
.catch((imError) => {
console.warn('joinGroup error:', imError); // 申请加群失败的相关信息
});
},
},
created() {
},
attached() {
},
ready() {
},
moved() {
},
detached() {
},
});
@@ -0,0 +1,4 @@
{
"usingComponents": {},
"navigationStyle": "custom"
}
@@ -0,0 +1,25 @@
<!--miniprogram/pages/TUI-Group/join-group/join.wxml-->
<view class="TUI-Create-conversation-container">
<view class="tui-navigatorbar">
<image class="tui-navigatorbar-back" bindtap="goBack" src="../../../../static/assets/ic_back_white.svg" />
<view class="conversation-title">加入群聊</view>
</view>
<view class="tui-search-area">
<view class="tui-search-bar">
<image class="tui-searchcion" src="../../../../static/assets/serach-icon.svg" />
<input class="tui-search-bar-input" value="{{groupID}}" placeholder="请输入群ID" bindinput='getGroupIDInput' bindconfirm="searchGroupByID" bindblur="searchGroupByID"/>
</view>
</view>
<view class="tui-person-to-invite" wx:if="{{searchGroup.groupID}}" bindtap="handleChoose">
<image class="tui-normal-choose" src="{{searchGroup.isChoose ? '../../../../static/assets/single-choice-hover.svg' : '../../../../static/assets/single-choice-normal.svg'}}" />
<view class="tui-person-profile">
<image class="tui-person-profile-avatar" src="{{searchGroup.group.avatar || '../../../../static/assets/gruopavatar.svg' }}" />
<view>
<view class="tui-person-profile-nick"> {{searchGroup.name}}</view>
<view class="tui-person-profile-userID">群ID{{searchGroup.groupID}}</view>
</view>
</view>
</view>
<view class="tui-confirm-btn" bindtap="bindConfirmJoin">确认加入</view>
</view>
@@ -0,0 +1,132 @@
.TUI-Create-conversation-container {
width: 100vw;
height: 100vh;
background-color: #F4F5F9;
}
.tui-navigatorbar{
position: absolute;
top: 0;
width: 750rpx;
height: 176rpx;
background-color: #006EFF;
}
.tui-navigatorbar-back{
position: absolute;
width: 60rpx;
height: 60rpx;
left: 24rpx;
bottom: 15rpx;
}
.conversation-title {
position:absolute;
width: 350rpx;
height: 88rpx;
line-height: 56rpx;
font-size: 36rpx;
color: #FFFFFF;
bottom: 0;
left: 200rpx;
display: flex;
justify-content: center;
align-items: center;
}
.tui-search-area {
position: absolute;
top: 176rpx;
width: 750rpx;
height: 144rpx;
background-color: #006EFF;
}
.tui-search-bar {
display: flex;
flex-wrap: nowrap;
align-items: center;
margin-left: 40rpx;
margin-top: 32rpx;
width: 670rpx;
height: 80rpx;
background: #FFFFFF;
border-radius: 40rpx;
border-radius: 40rpx;
}
.tui-searchcion {
display: inline-block;
margin-left: 24rpx;
width: 48rpx;
height: 48rpx;
}
.tui-search-bar-input {
margin-left: 16rpx;
line-height: 40rpx;
font-size: 28rpx;
width: 100%;
display: inline-block;
}
.tui-person-to-invite {
position: absolute;
top: 320rpx;
display: flex;
flex-wrap: nowrap;
width: 750rpx;
height: 150rpx;
background-color: #FFFFFF;
}
.tui-normal-choose {
margin-left: 40rpx;
margin-right: 40rpx;
margin-top: 52rpx;
margin-bottom: 50rpx;
width: 48rpx;
height: 48rpx;
}
.tui-person-profile {
width: 622rpx;
display: flex;
align-items: center;
}
.tui-person-profile-avatar {
width: 96rpx;
height: 96rpx;
margin-right: 24rpx;
}
.tui-person-profile-nick {
color: #333333;
line-height: 50rpx;
font-size: 36rpx;
margin-bottom: 4rpx;
}
.tui-person-profile-userID {
color: #999999;
line-height: 40rpx;
font-size: 28rpx;
}
.tui-confirm-btn {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
bottom: 100rpx;
width: 670rpx;
height: 96rpx;
background: #006EFF;
color: #FFFFFF;
border-radius: 48rpx;
border-radius: 48rpx;
margin-left: 40rpx;
line-height: 44rpx;
font-size: 32rpx;
}
@@ -0,0 +1,255 @@
import constant from "../../utils/constant";
// TUIKitWChat/Conversation/index.js
const app = getApp();
Component({
/**
* 组件的属性列表
*/
properties: {
config: {
type: Object,
value: {},
observer(config) {
},
},
},
/**
* 组件的初始数据
*/
data: {
conversationList: [],
currentConversationID: '',
showSelectTag: false,
array: [
{ id: 1, name: '发起会话' },
{ id: 2, name: '发起群聊' },
{ id: 3, name: '加入群聊' },
],
index: Number,
unreadCount: 0,
conversationInfomation: {},
transChenckID: '',
userIDList: [],
statusList: [],
currentUserIDList: [],
showConversationList: true,
showCreateConversation: false,
showCreateGroup: false,
showJoinGroup: false,
handleChangeStatus: false,
storageList: [],
},
lifetimes: {
attached() {
},
detached() {
wx.$TUIKit.off(wx.$TUIKitTIM.EVENT.CONVERSATION_LIST_UPDATED, this.onConversationListUpdated, this);
wx.$TUIKit.off(wx.$TUIKitTIM.EVENT.USER_STATUS_UPDATED, this.onUserStatusUpdate, this);
},
},
/**
* 组件的方法列表
*/
methods: {
init() {
wx.$TUIKit.on(wx.$TUIKitTIM.EVENT.CONVERSATION_LIST_UPDATED, this.onConversationListUpdated, this);
wx.$TUIKit.on(wx.$TUIKitTIM.EVENT.USER_STATUS_UPDATED, this.onUserStatusUpdate, this);
this.getConversationList();
wx.getStorageInfo({
success(res) {
wx.setStorage({
key: 'storageList',
data: res.keys,
});
},
});
this.setData({
handleChangeStatus: wx.getStorageSync(app?.globalData?.userInfo?.userID) ? wx.getStorageSync(app?.globalData?.userInfo?.userID) : true,
}, () => {
if (!wx.getStorageSync('storageList').includes('showOnlineStatus')) {
this.handleChangeStatus();
}
});
},
goBack() {
if (app?.globalData?.reportType !== constant.OPERATING_ENVIRONMENT) {
wx.navigateBack({
delta: 1,
});
} else {
wx.switchTab({
url: '/pages/TUI-Index/index',
});
}
},
// 更新会话列表
onConversationListUpdated(event) {
this.setData({
conversationList: event.data,
});
this.filterUserIDList(event.data);
},
transCheckID(event) {
this.setData({
transChenckID: event.detail.checkID,
});
},
// 更新状态
onUserStatusUpdate(event) {
event.data.forEach((element) => {
const index = this.data.statusList.findIndex(item => item.userID === element.userID);
if (index === -1) {
return;
}
this.data.statusList[index] = element;
this.setData({
statusList: this.data.statusList,
});
});
},
getConversationList() {
wx.$TUIKit.getConversationList().then((imResponse) => {
this.setData({
conversationList: imResponse.data.conversationList,
});
this.filterUserIDList(imResponse.data.conversationList);
});
},
// 跳转到子组件需要的参数
handleRoute(event) {
const flagIndex = this.data.conversationList.findIndex(item => item.conversationID === event.currentTarget.id);
this.setData({
index: flagIndex,
});
this.getConversationList();
this.setData({
currentConversationID: event.currentTarget.id,
unreadCount: this.data.conversationList[this.data.index].unreadCount,
});
this.triggerEvent('currentConversationID', { currentConversationID: event.currentTarget.id,
unreadCount: this.data.conversationList[this.data.index].unreadCount });
},
// 展示发起会话/发起群聊/加入群聊
showSelectedTag() {
wx.aegis.reportEvent({
name: 'conversationType',
ext1: 'conversationType-all',
});
this.setData({
showSelectTag: !this.data.showSelectTag,
});
},
handleOnTap(event) {
this.setData({
showSelectTag: false,
}, () => {
switch (event.currentTarget.dataset.id) {
case 1:
this.setData({
showCreateConversation: true,
showConversationList: false,
});
break;
case 2:
this.setData({
showCreateGroup: true,
showConversationList: false,
});
break;
case 3:
this.setData({
showJoinGroup: true,
showConversationList: false,
});
break;
default:
break;
}
});
},
// 点击空白区域关闭showMore弹窗
handleEditToggle() {
this.setData({
showSelectTag: false,
});
},
showConversation(event) {
this.setData({
showConversationList: true,
showCreateConversation: false,
showCreateGroup: false,
showJoinGroup: false,
});
},
searchUserID(event) {
this.triggerEvent('currentConversationID', { currentConversationID: event.detail.searchUserID });
},
searchGroupID(event) {
this.triggerEvent('currentConversationID', { currentConversationID: event.detail.searchGroupID });
},
createGroupID(event) {
this.triggerEvent('currentConversationID', { currentConversationID: event.detail.createGroupID });
},
// 处理当前登录账号是否开启在线状态
handleChangeStatus() {
const currentID = wx.$chat_userID;
const cacheList = wx.getStorageSync('currentUserID');
const nowList = [];
nowList.push(wx.$chat_userID);
if (cacheList.length === 0 || !cacheList.includes(wx.$chat_userID)) {
wx.setStorage({
key: 'currentUserID',
data: wx.getStorageSync('currentUserID').concat(nowList),
});
}
wx.setStorage({
key: currentID,
data: this.data.handleChangeStatus,
});
},
// 订阅在线状态
subscribeOnlineStatus(userIDList) {
wx.$TUIKit.getUserStatus({ userIDList }).then((imResponse) => {
const { successUserList } = imResponse.data;
this.setData({
statusList: successUserList,
});
})
.catch((imError) => {
console.warn('getUserStatus error:', imError); // 获取用户状态失败的相关信息
});
wx.$TUIKit.subscribeUserStatus({ userIDList });
},
// 过滤会话列表,找出C2C会话,以及需要订阅状态的userIDList
filterUserIDList(conversationList) {
if (conversationList.length === 0) return;
const userIDList = [];
conversationList.forEach((element) => {
if (element.type === wx.$TUIKitTIM.TYPES.CONV_C2C) {
userIDList.push(element.userProfile.userID);
}
});
const currentUserID = wx.getStorageSync('currentUserID');
if (currentUserID.includes(wx.$chat_userID)) {
const currentStatus = wx.getStorageSync(wx.$chat_userID);
if (currentStatus) {
this.subscribeOnlineStatus(userIDList);
}
} else {
this.subscribeOnlineStatus(userIDList);
}
},
learnMore() {
if (app?.globalData?.reportType !== constant.OPERATING_ENVIRONMENT) return;
wx.navigateTo({
url: '/pages/TUI-User-Center/webview/webview?url=https://cloud.tencent.com/product/im',
});
},
},
});
@@ -0,0 +1,10 @@
{
"component": true,
"usingComponents": {
"ConversationItem": "./components/ConversationItem/index",
"CreateConversation": "./components/CreateConversation/index",
"CreateGroup": "./components/CreateGroup/index",
"JoinGroup": "./components/JoinGroup/index"
},
"navigationStyle": "custom"
}
@@ -0,0 +1,27 @@
<!--TUIKitWChat/Conversation/index.wxml-->
<view class="container" wx:if="{{showConversationList}}">
<view class="container">
<view class="tui-navigatorbar">
<image class="tui-navigatorbar-back" bindtap="goBack" src="../../static/assets/ic_back_white.svg" />
<view class="conversation-title">最近联系人</view>
</view>
<view class="conversation-list-area">
<scroll-view class="scoll-view" scroll-y="true">
<ConversationItem wx:for="{{conversationList}}" wx:key="index" id="{{item.conversationID}}" data-type="{{item.type}}" conversation="{{item}}" bindtap="handleRoute" statusList="{{statusList}}" bind:transCheckID="transCheckID" charge="{{transChenckID===item.conversationID}}">
</ConversationItem>
</scroll-view>
</view>
</view>
<view wx:if="{{showSelectTag}}" class="conversation-bubble" catchtap="handleEditToggle">
<view class="picker" wx:for="{{array}}" wx:key="index" data-name="{{item.name}}" data-id="{{item.id}}" bindtap="handleOnTap">
{{item.name}}
</view>
</view>
<view class="bottom-area">
<image bindtap="showSelectedTag" class="btn-show-more" src="../../static/assets/add.svg" />
<view bindtap="learnMore" class="im-link">了解更多IM功能</view>
</view>
</view>
<CreateConversation wx:if="{{showCreateConversation}}" bind:showConversation="showConversation" bind:searchUserID="searchUserID" ></CreateConversation>
<CreateGroup wx:if="{{showCreateGroup}}" bind:showConversation="showConversation" bind:createGroupID="createGroupID"></CreateGroup>
<JoinGroup wx:if="{{showJoinGroup}}" bind:searchGroupID="searchGroupID" bind:showConversation="showConversation"></JoinGroup>
@@ -0,0 +1,122 @@
.container{
width: 100vw;
height: 100vh;
background-color: #F4F5F9;
}
.tui-navigatorbar{
position: absolute;
top: 0;
width: 750rpx;
height: 170rpx;
background-color: #006EFF;
}
.tui-navigatorbar-back{
position: absolute;
width: 48rpx;
height: 48rpx;
left: 24rpx;
bottom: 20rpx;
}
.conversation-title {
position:absolute;
width: 350rpx;
height: 88rpx;
line-height: 56rpx;
font-size: 36rpx;
color: #FFFFFF;
bottom: 0;
left: 200rpx;
display: flex;
justify-content: center;
align-items: center;
}
.conversation-list-area {
position: absolute;
width: 100vw;
height: calc(100vh - 190px);
top: 172rpx;
}
.scoll-view {
width: 100%;
height: 100%;
}
.btn-show-more {
display: flex;
width: 160rpx;
height: 160rpx;
padding-left: 3rpx;
}
.picker {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 96rpx;
}
.bottom-back{
height: 120px;
width: 100%;
background-color: #F4F5F9;
z-index: 3;
}
.bottom-area {
flex-direction: column;
position: absolute;
bottom: 80rpx;
right: 0;
left: 0;
margin: auto;
width: 100px;
display: flex;
justify-content: center;
align-items: center
}
.im-link {
width: 218rpx;
height: 36rpx;
font-size: 28rpx;
line-height: 36rpx;
margin: 0 auto;
color: #006EFF;
}
.conversation-bubble {
padding-top: 40rpx;
position: absolute;
width: 300rpx;
padding-right: 3px;
background-color: #FFFFFF;
height: 320rpx;
bottom: 300rpx;
left: 220rpx;
z-index: 100;
box-shadow: 0 2px 16px 0 rgba(0,0,0,0.08);
border-radius: 14rpx;
}
.conversation-bubble:before,.conversation-bubble:after{
content: "";
display: block;
border-width: 20px;
position: absolute;
bottom: -40px;
left: 54px;
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
font-size: 0;
line-height: 0;
margin-left:4px
}
.conversation-bubble:after{
bottom: -33px;
border-color: #fff transparent transparent;
}