jiuyiUniapp/jiuyi2/TUIKit/components/TUIContact/contact-list/index.vue

364 lines
12 KiB
Vue

<template>
<ul
v-if="!contactSearchingStatus"
:class="['tui-contact-list', !isPC && 'tui-contact-list-h5']"
>
<li
v-for="(contactListObj, key) in contactListMap"
:key="key"
class="tui-contact-list-item"
>
<header
class="tui-contact-list-item-header"
@click="toggleCurrentContactList(key)"
>
<div class="tui-contact-list-item-header-left">
<Icon
:file="currentContactListKey === key ? downSVG : rightSVG"
width="16px"
height="16px"
/>
<div>{{ TUITranslateService.t(`TUIContact.${contactListObj.title}`) }}</div>
</div>
<div class="tui-contact-list-item-header-right">
<span
v-if="contactListObj.unreadCount"
class="tui-contact-list-item-header-right-unread"
>
{{ contactListObj.unreadCount }}
</span>
</div>
</header>
<ul :class="['tui-contact-list-item-main', currentContactListKey === key ? '' : 'hidden']">
<li
v-for="contactListItem in contactListObj.list"
:key="contactListItem.renderKey"
class="tui-contact-list-item-main-item"
:class="['selected']"
@click="selectItem(contactListItem)"
>
<ContactListItem
:item="contactListItem"
:displayOnlineStatus="displayOnlineStatus && key === 'friendList'"
/>
</li>
</ul>
</li>
</ul>
<ul
v-else
class="tui-contact-list"
>
<li
v-for="(item, key) in contactSearchResult"
:key="key"
class="tui-contact-list-item"
>
<div
v-if="item.list[0]"
class="tui-contact-search-list"
>
<div class="tui-contact-search-list-title">
{{ TUITranslateService.t(`TUIContact.${item.label}`) }}
</div>
<div
v-for="(listItem, index) in item.list"
:key="index"
class="tui-contact-search-list-item"
:class="['selected']"
@click="selectItem(listItem)"
>
<ContactListItem
:item="listItem"
:displayOnlineStatus="false"
/>
</div>
</div>
</li>
<div
v-if="isContactSearchNoResult"
class="tui-contact-search-list-default"
>
{{ TUITranslateService.t("TUIContact.无搜索结果") }}
</div>
</ul>
</template>
<script setup lang="ts">
import {
TUITranslateService,
TUIStore,
StoreName,
IGroupModel,
TUIFriendService,
Friend,
FriendApplication,
TUIUserService,
} from '@tencentcloud/chat-uikit-engine';
import TUICore, { TUIConstants } from '@tencentcloud/tui-core';
import { ref, computed, onMounted, onUnmounted, provide } from '../../../adapter-vue';
import Icon from '../../common/Icon.vue';
import downSVG from '../../../assets/icon/down-icon.svg';
import rightSVG from '../../../assets/icon/right-icon.svg';
import {
IContactList,
IContactSearchResult,
IBlackListUserItem,
IUserStatus,
IUserStatusMap,
IContactInfoType,
} from '../../../interface';
import ContactListItem from './contact-list-item/index.vue';
import { isPC } from '../../../utils/env';
const currentContactListKey = ref<keyof IContactList>('');
const currentContactInfo = ref<IContactInfoType>({} as IContactInfoType);
const contactListMap = ref<IContactList>({
friendApplicationList: {
key: 'friendApplicationList',
title: '新的联系人',
list: [] as FriendApplication[],
unreadCount: 0,
},
blackList: {
key: 'blackList',
title: '黑名单',
list: [] as IBlackListUserItem[],
},
groupList: {
key: 'groupList',
title: '我的群聊',
list: [] as IGroupModel[],
},
friendList: {
key: 'friendList',
title: '我的好友',
list: [] as Friend[],
},
});
const contactSearchingStatus = ref<boolean>(false);
const contactSearchResult = ref<IContactSearchResult>();
const displayOnlineStatus = ref<boolean>(false);
const userOnlineStatusMap = ref<IUserStatusMap>();
const isContactSearchNoResult = computed((): boolean => {
return (
!contactSearchResult?.value?.user?.list[0]
&& !contactSearchResult?.value?.group?.list[0]
);
});
onMounted(() => {
TUIStore.watch(StoreName.APP, {
enabledCustomerServicePlugin: onCustomerServiceCommercialPluginUpdated,
});
TUIStore.watch(StoreName.GRP, {
groupList: onGroupListUpdated,
});
TUIStore.watch(StoreName.USER, {
userBlacklist: onUserBlacklistUpdated,
displayOnlineStatus: onDisplayOnlineStatusUpdated,
userStatusList: onUserStatusListUpdated,
});
TUIStore.watch(StoreName.FRIEND, {
friendList: onFriendListUpdated,
friendApplicationList: onFriendApplicationListUpdated,
friendApplicationUnreadCount: onFriendApplicationUnreadCountUpdated,
});
TUIStore.watch(StoreName.CUSTOM, {
currentContactSearchingStatus: onCurrentContactSearchingStatusUpdated,
currentContactSearchResult: onCurrentContactSearchResultUpdated,
currentContactListKey: onCurrentContactListKeyUpdated,
currentContactInfo: onCurrentContactInfoUpdated,
});
});
onUnmounted(() => {
TUIStore.unwatch(StoreName.APP, {
enabledCustomerServicePlugin: onCustomerServiceCommercialPluginUpdated,
});
TUIStore.unwatch(StoreName.GRP, {
groupList: onGroupListUpdated,
});
TUIStore.unwatch(StoreName.USER, {
userBlacklist: onUserBlacklistUpdated,
displayOnlineStatus: onDisplayOnlineStatusUpdated,
userStatusList: onUserStatusListUpdated,
});
TUIStore.unwatch(StoreName.FRIEND, {
friendList: onFriendListUpdated,
friendApplicationList: onFriendApplicationListUpdated,
friendApplicationUnreadCount: onFriendApplicationUnreadCountUpdated,
});
TUIStore.unwatch(StoreName.CUSTOM, {
currentContactSearchingStatus: onCurrentContactSearchingStatusUpdated,
currentContactSearchResult: onCurrentContactSearchResultUpdated,
currentContactListKey: onCurrentContactListKeyUpdated,
currentContactInfo: onCurrentContactInfoUpdated,
});
});
function toggleCurrentContactList(key: keyof IContactList) {
if (currentContactListKey.value === key) {
currentContactListKey.value = '';
currentContactInfo.value = {} as IContactInfoType;
TUIStore.update(StoreName.CUSTOM, 'currentContactListKey', '');
TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', {} as IContactInfoType);
} else {
currentContactListKey.value = key;
TUIStore.update(StoreName.CUSTOM, 'currentContactListKey', key);
if (key === 'friendApplicationList') {
TUIFriendService.setFriendApplicationRead();
}
}
}
function selectItem(item: any) {
currentContactInfo.value = item;
// For a result in the search list, before viewing the contactInfo details,
// it is necessary to update the data for the "already in the group list/already in the friend list" situation to obtain more detailed information
if (contactSearchingStatus.value) {
let targetListItem;
if ((currentContactInfo.value as Friend)?.userID) {
targetListItem = contactListMap.value?.friendList?.list?.find(
(item: IContactInfoType) => (item as Friend)?.userID === (currentContactInfo.value as Friend)?.userID,
);
} else if ((currentContactInfo.value as IGroupModel)?.groupID) {
targetListItem = contactListMap.value?.groupList?.list?.find(
(item: IContactInfoType) => (item as IGroupModel)?.groupID === (currentContactInfo.value as IGroupModel)?.groupID,
);
}
if (targetListItem) {
currentContactInfo.value = targetListItem;
}
}
TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', currentContactInfo.value);
}
function onDisplayOnlineStatusUpdated(status: boolean) {
displayOnlineStatus.value = status;
}
function onUserStatusListUpdated(list: Map<string, IUserStatus>) {
if (list?.size > 0) {
userOnlineStatusMap.value = Object.fromEntries(list?.entries());
}
}
function onCustomerServiceCommercialPluginUpdated(isEnabled: boolean) {
if (!isEnabled) {
return;
}
// After the customer purchases the customer service plug-in,
// the engine updates the enabledCustomerServicePlugin to true through the commercial capability bit.
const contactListExtensionID = TUIConstants.TUIContact.EXTENSION.CONTACT_LIST.EXT_ID;
const tuiContactExtensionList = TUICore.getExtensionList(contactListExtensionID);
const customerData = tuiContactExtensionList.find((extension: any) => {
const { name, accountList = [] } = extension.data || {};
return name === 'customer' && accountList.length > 0;
});
if (customerData) {
const { data, text } = customerData;
const { accountList } = (data || {}) as { accountList: string[] };
TUIUserService.getUserProfile({ userIDList: accountList })
.then((res) => {
if (res.data.length > 0) {
const customerList = {
title: text,
list: res.data.map((item: any, index: number) => {
return {
...item,
renderKey: generateRenderKey('customerList', item, index),
infoKeyList: [],
btnKeyList: ['enterC2CConversation'],
};
}),
key: 'customerList',
};
contactListMap.value = { ...contactListMap.value, customerList };
}
})
.catch(() => { });
}
}
function onGroupListUpdated(groupList: IGroupModel[]) {
updateContactListMap('groupList', groupList);
}
function onUserBlacklistUpdated(userBlacklist: IBlackListUserItem[]) {
updateContactListMap('blackList', userBlacklist);
}
function onFriendApplicationUnreadCountUpdated(friendApplicationUnreadCount: number) {
contactListMap.value.friendApplicationList.unreadCount = friendApplicationUnreadCount;
}
function onFriendListUpdated(friendList: Friend[]) {
updateContactListMap('friendList', friendList);
}
function onFriendApplicationListUpdated(friendApplicationList: FriendApplication[]) {
updateContactListMap('friendApplicationList', friendApplicationList);
}
function updateContactListMap(key: keyof IContactList, list: IContactInfoType[]) {
contactListMap.value[key].list = list;
contactListMap.value[key].list.map((item: IContactInfoType, index: number) => item.renderKey = generateRenderKey(key, item, index));
updateCurrentContactInfoFromList(contactListMap.value[key].list, key);
}
function updateCurrentContactInfoFromList(list: IContactInfoType[], type: keyof IContactList) {
if (
!(currentContactInfo.value as Friend)?.userID
&& !(currentContactInfo.value as IGroupModel)?.groupID
) {
return;
}
if (type === currentContactListKey.value || contactSearchingStatus.value) {
currentContactInfo.value = list?.find(
(item: any) =>
(item?.groupID && item?.groupID === (currentContactInfo.value as IGroupModel)?.groupID) || (item?.userID && item?.userID === (currentContactInfo.value as Friend)?.userID),
) || {} as IContactInfoType;
TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', currentContactInfo.value);
}
}
function generateRenderKey(contactListMapKey: keyof IContactList, contactInfo: IContactInfoType, index: number) {
return `${contactListMapKey}-${(contactInfo as Friend).userID || (contactInfo as IGroupModel).groupID || ('index' + index)}`;
}
function onCurrentContactSearchResultUpdated(searchResult: IContactSearchResult) {
contactSearchResult.value = searchResult;
}
function onCurrentContactSearchingStatusUpdated(searchingStatus: boolean) {
contactSearchingStatus.value = searchingStatus;
TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', {} as IContactInfoType);
TUIStore.update(StoreName.CUSTOM, 'currentContactListKey', '');
}
function onCurrentContactInfoUpdated(contactInfo: IContactInfoType) {
currentContactInfo.value = contactInfo;
}
function onCurrentContactListKeyUpdated(contactListKey: string) {
currentContactListKey.value = contactListKey;
}
provide('userOnlineStatusMap', userOnlineStatusMap);
</script>
<style lang="scss" scoped src="./style/index.scss"></style>