430 lines
13 KiB
Vue
430 lines
13 KiB
Vue
<template>
|
|
<div
|
|
v-if="typeof contactInfoData === 'object' && Object.keys(contactInfoData).length"
|
|
:class="['tui-contact-info', !isPC && 'tui-contact-info-h5']"
|
|
>
|
|
<div
|
|
v-if="!isPC"
|
|
:class="[
|
|
'tui-contact-info-header',
|
|
!isPC && 'tui-contact-info-h5-header',
|
|
]"
|
|
>
|
|
<div
|
|
:class="[
|
|
'tui-contact-info-header-icon',
|
|
!isPC && 'tui-contact-info-h5-header-icon',
|
|
]"
|
|
@click="resetContactSearchingUIData"
|
|
>
|
|
<Icon :file="backSVG" />
|
|
</div>
|
|
<div
|
|
:class="[
|
|
'tui-contact-info-header-title',
|
|
!isPC && 'tui-contact-info-h5-header-title',
|
|
]"
|
|
>
|
|
{{ TUITranslateService.t("TUIContact.添加好友/群聊") }}
|
|
</div>
|
|
</div>
|
|
<div :class="['tui-contact-info-basic', !isPC && 'tui-contact-info-h5-basic']">
|
|
<div
|
|
:class="[
|
|
'tui-contact-info-basic-text',
|
|
!isPC && 'tui-contact-info-h5-basic-text',
|
|
]"
|
|
>
|
|
<div
|
|
:class="[
|
|
'tui-contact-info-basic-text-name',
|
|
!isPC && 'tui-contact-info-h5-basic-text-name',
|
|
]"
|
|
>
|
|
{{ generateContactInfoName(contactInfoData) }}
|
|
</div>
|
|
<div
|
|
v-for="item in contactInfoBasicList"
|
|
:key="item.label"
|
|
:class="[
|
|
'tui-contact-info-basic-text-other',
|
|
!isPC && 'tui-contact-info-h5-basic-text-other',
|
|
]"
|
|
>
|
|
{{
|
|
`${TUITranslateService.t(`TUIContact.${item.label}`)}:
|
|
${item.data}`
|
|
}}
|
|
</div>
|
|
</div>
|
|
<img
|
|
:class="[
|
|
'tui-contact-info-basic-avatar',
|
|
!isPC && 'tui-contact-info-h5-basic-avatar',
|
|
]"
|
|
:src="generateAvatar(contactInfoData)"
|
|
>
|
|
</div>
|
|
<div
|
|
v-if="contactInfoMoreList[0]"
|
|
:class="['tui-contact-info-more', !isPC && 'tui-contact-info-h5-more']"
|
|
>
|
|
<div
|
|
v-for="item in contactInfoMoreList"
|
|
:key="item.key"
|
|
:class="[
|
|
'tui-contact-info-more-item',
|
|
!isPC && 'tui-contact-info-h5-more-item',
|
|
item.labelPosition === CONTACT_INFO_LABEL_POSITION.TOP
|
|
? 'tui-contact-info-more-item-top'
|
|
: 'tui-contact-info-more-item-left',
|
|
]"
|
|
>
|
|
<div
|
|
:class="[
|
|
'tui-contact-info-more-item-label',
|
|
!isPC && 'tui-contact-info-h5-more-item-label',
|
|
]"
|
|
>
|
|
{{ `${TUITranslateService.t(`TUIContact.${item.label}`)}` }}
|
|
</div>
|
|
<div
|
|
:class="[
|
|
'tui-contact-info-more-item-content',
|
|
!isPC && 'tui-contact-info-h5-more-item-content',
|
|
]"
|
|
>
|
|
<div
|
|
v-if="!item.editing"
|
|
:class="[
|
|
'tui-contact-info-more-item-content-text',
|
|
!isPC && 'tui-contact-info-h5-more-item-content-text',
|
|
]"
|
|
>
|
|
<div
|
|
:class="[
|
|
'tui-contact-info-more-item-content-text-data',
|
|
!isPC && 'tui-contact-info-h5-more-item-content-text-data',
|
|
]"
|
|
>
|
|
{{ item.data }}
|
|
</div>
|
|
<div
|
|
v-if="item.editable"
|
|
:class="[
|
|
'tui-contact-info-more-item-content-text-icon',
|
|
!isPC && 'tui-contact-info-h5-more-item-content-text-icon',
|
|
]"
|
|
@click="setEditing(item)"
|
|
>
|
|
<Icon
|
|
:file="editSVG"
|
|
width="14px"
|
|
height="14px"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<input
|
|
v-else-if="item.editType === CONTACT_INFO_MORE_EDIT_TYPE.INPUT"
|
|
v-model="item.data"
|
|
:class="[
|
|
'tui-contact-info-more-item-content-input',
|
|
!isPC && 'tui-contact-info-h5-more-item-content-input',
|
|
]"
|
|
type="text"
|
|
@confirm="onContactInfoEmitSubmit(item)"
|
|
@keyup.enter="onContactInfoEmitSubmit(item)"
|
|
>
|
|
<textarea
|
|
v-else-if="item.editType === CONTACT_INFO_MORE_EDIT_TYPE.TEXTAREA"
|
|
v-model="item.data"
|
|
:class="[
|
|
'tui-contact-info-more-item-content-textarea',
|
|
!isPC && 'tui-contact-info-h5-more-item-content-textarea',
|
|
]"
|
|
confirm-type="done"
|
|
/>
|
|
<div
|
|
v-else-if="item.editType === CONTACT_INFO_MORE_EDIT_TYPE.SWITCH"
|
|
@click="onContactInfoEmitSubmit(item)"
|
|
>
|
|
<SwitchBar :value="item.data" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
:class="[
|
|
'tui-contact-info-button',
|
|
!isPC && 'tui-contact-info-h5-button',
|
|
]"
|
|
>
|
|
<button
|
|
v-for="item in contactInfoButtonList"
|
|
:key="item.key"
|
|
:class="[
|
|
'tui-contact-info-button-item',
|
|
!isPC && 'tui-contact-info-h5-button-item',
|
|
item.type === CONTACT_INFO_BUTTON_TYPE.CANCEL
|
|
? `tui-contact-info-button-item-cancel`
|
|
: `tui-contact-info-button-item-submit`,
|
|
]"
|
|
@click="onContactInfoButtonClicked(item)"
|
|
>
|
|
{{ TUITranslateService.t(`TUIContact.${item.label}`) }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import TUIChatEngine, {
|
|
TUIStore,
|
|
StoreName,
|
|
TUITranslateService,
|
|
IGroupModel,
|
|
Friend,
|
|
FriendApplication,
|
|
} from '@tencentcloud/chat-uikit-engine';
|
|
import { TUIGlobal } from '@tencentcloud/universal-api';
|
|
import { ref, computed, onMounted, onUnmounted } from '../../../adapter-vue';
|
|
import { isPC } from '../../../utils/env';
|
|
|
|
import {
|
|
generateAvatar,
|
|
generateContactInfoName,
|
|
generateContactInfoBasic,
|
|
isFriend,
|
|
isApplicationType,
|
|
} from '../utils/index';
|
|
import {
|
|
contactMoreInfoConfig,
|
|
contactButtonConfig,
|
|
} from './contact-info-config';
|
|
import Icon from '../../common/Icon.vue';
|
|
import editSVG from '../../../assets/icon/edit.svg';
|
|
import backSVG from '../../../assets/icon/back.svg';
|
|
import SwitchBar from '../../common/SwitchBar/index.vue';
|
|
import {
|
|
IBlackListUserItem,
|
|
IContactInfoMoreItem,
|
|
IContactInfoButton,
|
|
} from '../../../interface';
|
|
import {
|
|
CONTACT_INFO_LABEL_POSITION,
|
|
CONTACT_INFO_MORE_EDIT_TYPE,
|
|
CONTACT_INFO_BUTTON_TYPE,
|
|
} from '../../../constant';
|
|
import { deepCopy } from '../../TUIChat/utils/utils';
|
|
|
|
type IContactInfoType = IGroupModel | Friend | FriendApplication | IBlackListUserItem;
|
|
|
|
const emits = defineEmits(['switchConversation']);
|
|
|
|
const contactInfoData = ref<IContactInfoType>({} as IContactInfoType);
|
|
const contactInfoBasicList = ref<Array<{ label: string; data: string }>>([]);
|
|
const contactInfoMoreList = ref<IContactInfoMoreItem[]>([]);
|
|
const contactInfoButtonList = ref<IContactInfoButton[]>([]);
|
|
|
|
const setEditing = (item: any) => {
|
|
item.editing = true;
|
|
};
|
|
|
|
const isGroup = computed((): boolean =>
|
|
(contactInfoData.value as IGroupModel)?.groupID ? true : false,
|
|
);
|
|
|
|
const isApplication = computed((): boolean => {
|
|
return isApplicationType(contactInfoData?.value);
|
|
});
|
|
|
|
// is both friend, if is group type always false
|
|
const isBothFriend = ref<boolean>(false);
|
|
|
|
// is group member, including ordinary member, admin, group owner
|
|
const isGroupMember = computed((): boolean => {
|
|
return (contactInfoData.value as IGroupModel)?.selfInfo?.userID ? true : false;
|
|
});
|
|
|
|
// is in black list, if is group type always false
|
|
const isInBlackList = computed((): boolean => {
|
|
return (
|
|
!isGroup.value
|
|
&& blackList.value?.findIndex(
|
|
(item: IBlackListUserItem) =>
|
|
item?.userID === (contactInfoData.value as IBlackListUserItem)?.userID,
|
|
) >= 0
|
|
);
|
|
});
|
|
|
|
const blackList = ref<IBlackListUserItem[]>([]);
|
|
|
|
onMounted(() => {
|
|
TUIStore.watch(StoreName.CUSTOM, {
|
|
currentContactInfo: onCurrentContactInfoUpdated,
|
|
});
|
|
TUIStore.watch(StoreName.USER, {
|
|
userBlacklist: onUserBlacklistUpdated,
|
|
});
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
TUIStore.unwatch(StoreName.CUSTOM, {
|
|
currentContactInfo: onCurrentContactInfoUpdated,
|
|
});
|
|
TUIStore.unwatch(StoreName.USER, {
|
|
userBlacklist: onUserBlacklistUpdated,
|
|
});
|
|
});
|
|
|
|
const resetContactInfoUIData = () => {
|
|
contactInfoData.value = {} as IContactInfoType;
|
|
contactInfoBasicList.value = [];
|
|
contactInfoMoreList.value = [];
|
|
contactInfoButtonList.value = [];
|
|
};
|
|
|
|
const resetContactSearchingUIData = () => {
|
|
TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', {});
|
|
TUIStore.update(StoreName.CUSTOM, 'currentContactSearchingStatus', false);
|
|
TUIGlobal?.closeSearching && TUIGlobal?.closeSearching();
|
|
};
|
|
|
|
const onContactInfoEmitSubmit = (item: any) => {
|
|
item.editSubmitHandler
|
|
&& item.editSubmitHandler({
|
|
item,
|
|
contactInfoData: contactInfoData.value,
|
|
isBothFriend: isBothFriend.value,
|
|
isInBlackList: isInBlackList.value,
|
|
});
|
|
};
|
|
|
|
const onContactInfoButtonClicked = (item: any) => {
|
|
item.onClick
|
|
&& item.onClick({
|
|
contactInfoData: contactInfoData.value,
|
|
contactInfoMoreList: contactInfoMoreList.value,
|
|
});
|
|
if (
|
|
item.key === 'enterGroupConversation'
|
|
|| item.key === 'enterC2CConversation'
|
|
) {
|
|
emits('switchConversation', contactInfoData.value);
|
|
resetContactSearchingUIData();
|
|
}
|
|
};
|
|
|
|
const generateMoreInfo = async () => {
|
|
if (!isApplication.value) {
|
|
if (
|
|
(!isGroup.value && !isBothFriend.value && !isInBlackList.value)
|
|
|| (isGroup.value
|
|
&& !isGroupMember.value
|
|
&& (contactInfoData.value as IGroupModel)?.type !== TUIChatEngine?.TYPES?.GRP_AVCHATROOM)
|
|
) {
|
|
contactMoreInfoConfig.setWords.data = '';
|
|
contactInfoMoreList.value.push(contactMoreInfoConfig.setWords);
|
|
}
|
|
if (!isGroup.value && !isInBlackList.value) {
|
|
contactMoreInfoConfig.setRemark.data
|
|
= (contactInfoData.value as Friend)?.remark || '';
|
|
contactMoreInfoConfig.setRemark.editing = false;
|
|
contactInfoMoreList.value.push(contactMoreInfoConfig.setRemark);
|
|
}
|
|
if (!isGroup.value && (isBothFriend.value || isInBlackList.value)) {
|
|
contactMoreInfoConfig.blackList.data = isInBlackList.value || false;
|
|
contactInfoMoreList.value.push(contactMoreInfoConfig.blackList);
|
|
}
|
|
} else {
|
|
contactMoreInfoConfig.displayWords.data
|
|
= (contactInfoData.value as FriendApplication)?.wording || '';
|
|
contactInfoMoreList.value.push(contactMoreInfoConfig.displayWords);
|
|
}
|
|
};
|
|
|
|
const generateButton = () => {
|
|
if (isInBlackList.value) {
|
|
return;
|
|
}
|
|
if (isApplication.value) {
|
|
if (
|
|
(contactInfoData.value as FriendApplication)?.type
|
|
=== TUIChatEngine?.TYPES?.SNS_APPLICATION_SENT_TO_ME
|
|
) {
|
|
contactInfoButtonList?.value?.push(
|
|
contactButtonConfig.refuseFriendApplication,
|
|
);
|
|
contactInfoButtonList?.value?.push(
|
|
contactButtonConfig.acceptFriendApplication,
|
|
);
|
|
}
|
|
} else {
|
|
if (isGroup.value && isGroupMember.value) {
|
|
switch ((contactInfoData.value as IGroupModel)?.selfInfo?.role) {
|
|
case 'Owner':
|
|
contactInfoButtonList?.value?.push(contactButtonConfig.dismissGroup);
|
|
break;
|
|
default:
|
|
contactInfoButtonList?.value?.push(contactButtonConfig.quitGroup);
|
|
break;
|
|
}
|
|
contactInfoButtonList?.value?.push(
|
|
contactButtonConfig.enterGroupConversation,
|
|
);
|
|
} else if (!isGroup.value && isBothFriend.value) {
|
|
contactInfoButtonList?.value?.push(contactButtonConfig.deleteFriend);
|
|
contactInfoButtonList?.value?.push(
|
|
contactButtonConfig.enterC2CConversation,
|
|
);
|
|
} else {
|
|
if (isGroup.value) {
|
|
contactInfoButtonList?.value?.push(
|
|
(contactInfoData.value as IGroupModel)?.type === TUIChatEngine?.TYPES?.GRP_AVCHATROOM
|
|
? contactButtonConfig.joinAVChatGroup
|
|
: contactButtonConfig.joinGroup,
|
|
);
|
|
} else {
|
|
contactInfoButtonList?.value?.push(contactButtonConfig.addFriend);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
function onUserBlacklistUpdated(userBlacklist: IBlackListUserItem[]) {
|
|
blackList.value = userBlacklist;
|
|
}
|
|
|
|
async function onCurrentContactInfoUpdated(contactInfo: IContactInfoType) {
|
|
if (
|
|
contactInfoData.value
|
|
&& contactInfo
|
|
&& JSON.stringify(contactInfoData.value) === JSON.stringify(contactInfo)
|
|
) {
|
|
return;
|
|
}
|
|
resetContactInfoUIData();
|
|
// deep clone
|
|
contactInfoData.value = deepCopy(contactInfo) || {};
|
|
if (!contactInfoData.value || Object.keys(contactInfoData.value)?.length === 0) {
|
|
return;
|
|
}
|
|
contactInfoBasicList.value = generateContactInfoBasic(
|
|
contactInfoData.value,
|
|
);
|
|
isBothFriend.value = await isFriend(contactInfoData.value);
|
|
generateMoreInfo();
|
|
generateButton();
|
|
if (contactInfo.infoKeyList) {
|
|
contactInfoMoreList.value = contactInfo.infoKeyList.map((key: string) => {
|
|
return (contactMoreInfoConfig as any)[key];
|
|
});
|
|
}
|
|
if (contactInfo.btnKeyList) {
|
|
contactInfoButtonList.value = contactInfo.btnKeyList.map((key: string) => {
|
|
return (contactButtonConfig as any)[key];
|
|
});
|
|
}
|
|
}
|
|
</script>
|
|
<style lang="scss" scoped src="./style/index.scss"></style>
|