123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- <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>
|