Compare commits
3 Commits
6361aa9ac3
...
49fbeead9a
| Author | SHA1 | Date | |
|---|---|---|---|
| 49fbeead9a | |||
| cefc3d67dc | |||
| 57daf0f0f8 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -7,4 +7,4 @@
|
|||||||
/idea/
|
/idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
/unpackage/
|
/unpackage/
|
||||||
.hbuilderx/launch.json
|
.hbuilderx/launch.json
|
||||||
6
App.vue
6
App.vue
@ -266,8 +266,8 @@ body {
|
|||||||
// html,
|
// html,
|
||||||
// body,
|
// body,
|
||||||
// page {
|
// page {
|
||||||
// width: 100% !important;
|
// width: 100% ;
|
||||||
// height: 100% !important;
|
// height: 100% ;
|
||||||
// overflow: hidden;
|
// overflow: hidden;
|
||||||
// }
|
// }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
60
TUIKit/assets/styles/common.scss
Normal file
60
TUIKit/assets/styles/common.scss
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
body, div, ul, ol, dt, dd, li, dl, h1, h2, h3, h4, p {
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
font-style:normal;
|
||||||
|
|
||||||
|
/* font:12px/22px"\5B8B\4F53",Arial,Helvetica,sans-serif; */
|
||||||
|
}
|
||||||
|
|
||||||
|
ol, ul, li {
|
||||||
|
list-style:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border:0;
|
||||||
|
vertical-align:middle;
|
||||||
|
pointer-events:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
height: 100% important;
|
||||||
|
color:#000;
|
||||||
|
background:#FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear {
|
||||||
|
clear:both;
|
||||||
|
height:1px;
|
||||||
|
width:100%;
|
||||||
|
overflow:hidden;
|
||||||
|
margin-top:-1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color:#000;
|
||||||
|
text-decoration:none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, textarea {
|
||||||
|
user-select: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus, input:active, textarea:focus, textarea:active {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-aside {
|
||||||
|
position: absolute;
|
||||||
|
top: 50px;
|
||||||
|
right: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 360px !important;
|
||||||
|
border-radius: 8px 0 0 8px;
|
||||||
|
z-index: 9999;
|
||||||
|
max-height: calc(100% - 50px);
|
||||||
|
}
|
||||||
314
TUIKit/components/TUIChat/index.vue
Normal file
314
TUIKit/components/TUIChat/index.vue
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chat" :style="{height:fn+'px'}">
|
||||||
|
<div :style="{height:'100%'}" :class="['tui-chat', !isPC && 'tui-chat-h5']">
|
||||||
|
<div
|
||||||
|
v-if="!currentConversationID"
|
||||||
|
:class="['tui-chat-default', !isPC && 'tui-chat-h5-default']"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="currentConversationID"
|
||||||
|
:class="['tui-chat', !isPC && 'tui-chat-h5']"
|
||||||
|
>
|
||||||
|
<ChatHeader
|
||||||
|
:class="[
|
||||||
|
'tui-chat-header',
|
||||||
|
!isPC && 'tui-chat-H5-header',
|
||||||
|
isUniFrameWork && 'tui-chat-uniapp-header',
|
||||||
|
]"
|
||||||
|
:isGroup="isGroup"
|
||||||
|
:headerExtensionList="headerExtensionList"
|
||||||
|
@closeChat="closeChat"
|
||||||
|
@openGroupManagement="handleGroup"
|
||||||
|
/>
|
||||||
|
<Forward @toggleMultipleSelectMode="toggleMultipleSelectMode" />
|
||||||
|
<MessageList
|
||||||
|
ref="messageListRef"
|
||||||
|
:class="['tui-chat-message-list', !isPC && 'tui-chat-h5-message-list']"
|
||||||
|
:isGroup="isGroup"
|
||||||
|
:groupID="groupID"
|
||||||
|
:isNotInGroup="isNotInGroup"
|
||||||
|
:isMultipleSelectMode="isMultipleSelectMode"
|
||||||
|
@handleEditor="handleEditor"
|
||||||
|
@closeInputToolBar="() => changeToolbarDisplayType('none')"
|
||||||
|
@toggleMultipleSelectMode="toggleMultipleSelectMode"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="isNotInGroup"
|
||||||
|
:class="{
|
||||||
|
'tui-chat-leave-group': true,
|
||||||
|
'tui-chat-leave-group-mobile': isMobile,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ leaveGroupReasonText }}
|
||||||
|
</div>
|
||||||
|
<MultipleSelectPanel
|
||||||
|
v-else-if="isMultipleSelectMode"
|
||||||
|
@oneByOneForwardMessage="oneByOneForwardMessage"
|
||||||
|
@mergeForwardMessage="mergeForwardMessage"
|
||||||
|
@toggleMultipleSelectMode="toggleMultipleSelectMode"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<MessageInputToolbar
|
||||||
|
v-if="isInputToolbarShow"
|
||||||
|
:class="[
|
||||||
|
'tui-chat-message-input-toolbar',
|
||||||
|
!isPC && 'tui-chat-h5-message-input-toolbar',
|
||||||
|
isUniFrameWork && 'tui-chat-uni-message-input-toolbar'
|
||||||
|
]"
|
||||||
|
:displayType="inputToolbarDisplayType"
|
||||||
|
@insertEmoji="insertEmoji"
|
||||||
|
@changeToolbarDisplayType="changeToolbarDisplayType"
|
||||||
|
@scrollToLatestMessage="scrollToLatestMessage"
|
||||||
|
/>
|
||||||
|
<MessageInput
|
||||||
|
ref="messageInputRef"
|
||||||
|
:class="[
|
||||||
|
'tui-chat-message-input',
|
||||||
|
!isPC && 'tui-chat-h5-message-input',
|
||||||
|
isUniFrameWork && 'tui-chat-uni-message-input',
|
||||||
|
isWeChat && 'tui-chat-wx-message-input',
|
||||||
|
]"
|
||||||
|
:enableAt="featureConfig.InputMention"
|
||||||
|
:isMuted="false"
|
||||||
|
:muteText="TUITranslateService.t('TUIChat.您已被管理员禁言')"
|
||||||
|
:placeholder="TUITranslateService.t('TUIChat.请输入消息')"
|
||||||
|
:inputToolbarDisplayType="inputToolbarDisplayType"
|
||||||
|
@changeToolbarDisplayType="changeToolbarDisplayType"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<!-- Group Management -->
|
||||||
|
<div
|
||||||
|
v-if="!isNotInGroup && !isApp && isUniFrameWork && isGroup && headerExtensionList.length > 0"
|
||||||
|
class="group-profile"
|
||||||
|
@click="handleGroup"
|
||||||
|
>
|
||||||
|
{{ headerExtensionList[0].text }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onMounted, onUnmounted, computed } from '../../adapter-vue';
|
||||||
|
import TUIChatEngine, {
|
||||||
|
TUITranslateService,
|
||||||
|
TUIConversationService,
|
||||||
|
TUIStore,
|
||||||
|
StoreName,
|
||||||
|
IMessageModel,
|
||||||
|
IConversationModel,
|
||||||
|
} from '@tencentcloud/chat-uikit-engine';
|
||||||
|
import TUICore, { TUIConstants, ExtensionInfo } from '@tencentcloud/tui-core';
|
||||||
|
import ChatHeader from './chat-header/index.vue';
|
||||||
|
import MessageList from './message-list/index.vue';
|
||||||
|
import MessageInput from './message-input/index.vue';
|
||||||
|
import MultipleSelectPanel from './mulitple-select-panel/index.vue';
|
||||||
|
import Forward from './forward/index.vue';
|
||||||
|
import MessageInputToolbar from './message-input-toolbar/index.vue';
|
||||||
|
import { isPC, isWeChat, isUniFrameWork, isMobile, isApp } from '../../utils/env';
|
||||||
|
import { ToolbarDisplayType } from '../../interface';
|
||||||
|
import TUIChatConfig from './config';
|
||||||
|
// @Start uniapp use Chat only
|
||||||
|
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||||
|
import { initChat, logout } from './entry-chat-only.ts';
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
initChat(options);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnload(() => {
|
||||||
|
// Whether logout is decided by yourself when the page is unloaded. The default is false.
|
||||||
|
logout(false).then(() => {
|
||||||
|
// Handle success result from promise.then when you set true.
|
||||||
|
}).catch(() => {
|
||||||
|
// handle error
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// @End uniapp use Chat only
|
||||||
|
|
||||||
|
const emits = defineEmits(['closeChat']);
|
||||||
|
const fn = uni.getSystemInfoSync().windowHeight
|
||||||
|
const groupID = ref(undefined);
|
||||||
|
const isGroup = ref(false);
|
||||||
|
const isNotInGroup = ref(false);
|
||||||
|
const notInGroupReason = ref<number>();
|
||||||
|
const currentConversationID = ref();
|
||||||
|
const isMultipleSelectMode = ref(false);
|
||||||
|
const inputToolbarDisplayType = ref<ToolbarDisplayType>('none');
|
||||||
|
const messageInputRef = ref();
|
||||||
|
const messageListRef = ref<InstanceType<typeof MessageList>>();
|
||||||
|
const headerExtensionList = ref<ExtensionInfo[]>([]);
|
||||||
|
const featureConfig = TUIChatConfig.getFeatureConfig();
|
||||||
|
const ht = uni.getSystemInfoSync().windowHeight
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
TUIStore.watch(StoreName.CONV, {
|
||||||
|
currentConversation: onCurrentConversationUpdate,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
TUIStore.unwatch(StoreName.CONV, {
|
||||||
|
currentConversation: onCurrentConversationUpdate,
|
||||||
|
});
|
||||||
|
reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
const isInputToolbarShow = computed<boolean>(() => {
|
||||||
|
return isUniFrameWork ? inputToolbarDisplayType.value !== 'none' : true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const leaveGroupReasonText = computed<string>(() => {
|
||||||
|
let text = '';
|
||||||
|
switch (notInGroupReason.value) {
|
||||||
|
case 4:
|
||||||
|
text = TUITranslateService.t('TUIChat.您已被管理员移出群聊');
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
text = TUITranslateService.t('TUIChat.该群聊已被解散');
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
text = TUITranslateService.t('TUIChat.您已退出该群聊');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
text = TUITranslateService.t('TUIChat.您已退出该群聊');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
});
|
||||||
|
|
||||||
|
const reset = () => {
|
||||||
|
TUIConversationService.switchConversation('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeChat = (conversationID: string) => {
|
||||||
|
emits('closeChat', conversationID);
|
||||||
|
reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertEmoji = (emojiObj: object) => {
|
||||||
|
messageInputRef.value?.insertEmoji(emojiObj);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditor = (message: IMessageModel, type: string) => {
|
||||||
|
if (!message || !type) return;
|
||||||
|
switch (type) {
|
||||||
|
case 'reference':
|
||||||
|
// todo
|
||||||
|
break;
|
||||||
|
case 'reply':
|
||||||
|
// todo
|
||||||
|
break;
|
||||||
|
case 'reedit':
|
||||||
|
if (message?.payload?.text) {
|
||||||
|
messageInputRef?.value?.reEdit(message?.payload?.text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGroup = () => {
|
||||||
|
headerExtensionList.value[0].listener.onClicked({ groupID: groupID.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
function changeToolbarDisplayType(type: ToolbarDisplayType) {
|
||||||
|
inputToolbarDisplayType.value = inputToolbarDisplayType.value === type ? 'none' : type;
|
||||||
|
if (inputToolbarDisplayType.value !== 'none' && isUniFrameWork) {
|
||||||
|
uni.$emit('scroll-to-bottom');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToLatestMessage() {
|
||||||
|
messageListRef.value?.scrollToLatestMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleMultipleSelectMode(visible?: boolean) {
|
||||||
|
isMultipleSelectMode.value = visible === undefined ? !isMultipleSelectMode.value : visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeForwardMessage() {
|
||||||
|
messageListRef.value?.mergeForwardMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
function oneByOneForwardMessage() {
|
||||||
|
messageListRef.value?.oneByOneForwardMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUIUserNotInGroup(conversation: IConversationModel) {
|
||||||
|
if (conversation?.operationType > 0) {
|
||||||
|
headerExtensionList.value = [];
|
||||||
|
isNotInGroup.value = true;
|
||||||
|
/**
|
||||||
|
* 4 - be removed from the group
|
||||||
|
* 5 - group is dismissed
|
||||||
|
* 8 - quit group
|
||||||
|
*/
|
||||||
|
notInGroupReason.value = conversation?.operationType;
|
||||||
|
} else {
|
||||||
|
isNotInGroup.value = false;
|
||||||
|
notInGroupReason.value = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCurrentConversationUpdate(conversation: IConversationModel) {
|
||||||
|
updateUIUserNotInGroup(conversation);
|
||||||
|
// return when currentConversation is null
|
||||||
|
if (!conversation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// return when currentConversationID.value is the same as conversation.conversationID.
|
||||||
|
if (currentConversationID.value === conversation?.conversationID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isGroup.value = false;
|
||||||
|
let conversationType = TUIChatEngine.TYPES.CONV_C2C;
|
||||||
|
const conversationID = conversation.conversationID;
|
||||||
|
if (conversationID.startsWith(TUIChatEngine.TYPES.CONV_GROUP)) {
|
||||||
|
conversationType = TUIChatEngine.TYPES.CONV_GROUP;
|
||||||
|
isGroup.value = true;
|
||||||
|
groupID.value = conversationID.replace(TUIChatEngine.TYPES.CONV_GROUP, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
headerExtensionList.value = [];
|
||||||
|
isMultipleSelectMode.value = false;
|
||||||
|
// Initialize chatType
|
||||||
|
TUIChatConfig.setChatType(conversationType);
|
||||||
|
// While converstaion change success, notify callkit and roomkit、or other components.
|
||||||
|
TUICore.notifyEvent(TUIConstants.TUIChat.EVENT.CHAT_STATE_CHANGED, TUIConstants.TUIChat.EVENT_SUB_KEY.CHAT_OPENED, { groupID: groupID.value });
|
||||||
|
// The TUICustomerServicePlugin plugin determines if the current conversation is a customer service conversation, then sets chatType and activates the conversation.
|
||||||
|
TUICore.callService({
|
||||||
|
serviceName: TUIConstants.TUICustomerServicePlugin.SERVICE.NAME,
|
||||||
|
method: TUIConstants.TUICustomerServicePlugin.SERVICE.METHOD.ACTIVE_CONVERSATION,
|
||||||
|
params: { conversationID: conversationID },
|
||||||
|
});
|
||||||
|
// When open chat in room, close main chat ui and reset theme.
|
||||||
|
if (TUIChatConfig.getChatType() === TUIConstants.TUIChat.TYPE.ROOM) {
|
||||||
|
if (TUIChatConfig.getFeatureConfig(TUIConstants.TUIChat.FEATURE.InputVoice) === true) {
|
||||||
|
TUIChatConfig.setTheme('light');
|
||||||
|
currentConversationID.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get chat header extensions
|
||||||
|
if (TUIChatConfig.getChatType() === TUIConstants.TUIChat.TYPE.GROUP) {
|
||||||
|
headerExtensionList.value = TUICore.getExtensionList(TUIConstants.TUIChat.EXTENSION.CHAT_HEADER.EXT_ID);
|
||||||
|
}
|
||||||
|
TUIStore.update(StoreName.CUSTOM, 'activeConversation', conversationID);
|
||||||
|
currentConversationID.value = conversationID;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss" src="./style/index.scss">
|
||||||
|
.chat{
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100vh !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
243
TUIKit/components/TUIChat/message-input/index.vue
Normal file
243
TUIKit/components/TUIChat/message-input/index.vue
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="['message-input', !isPC && 'message-input-h5']">
|
||||||
|
<div class="audio-main-content-line">
|
||||||
|
<MessageInputAudio
|
||||||
|
v-if="(isWeChat || isApp) && isRenderVoice"
|
||||||
|
:class="{
|
||||||
|
'message-input-wx-audio-open': displayType === 'audio',
|
||||||
|
}"
|
||||||
|
:isEnableAudio="displayType === 'audio'"
|
||||||
|
@changeDisplayType="changeDisplayType"
|
||||||
|
/>
|
||||||
|
<MessageInputEditor
|
||||||
|
v-show="displayType === 'editor'"
|
||||||
|
ref="editor"
|
||||||
|
class="message-input-editor"
|
||||||
|
:placeholder="props.placeholder"
|
||||||
|
:isMuted="props.isMuted"
|
||||||
|
:muteText="props.muteText"
|
||||||
|
:enableInput="props.enableInput"
|
||||||
|
:enableAt="props.enableAt"
|
||||||
|
:enableTyping="props.enableTyping"
|
||||||
|
:isGroup="isGroup"
|
||||||
|
@onTyping="onTyping"
|
||||||
|
@onAt="onAt"
|
||||||
|
@onFocus="onFocus"
|
||||||
|
/>
|
||||||
|
<MessageInputAt
|
||||||
|
v-if="props.enableAt"
|
||||||
|
ref="messageInputAtRef"
|
||||||
|
@insertAt="insertAt"
|
||||||
|
@onAtListOpen="onAtListOpen"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
v-if="isRenderEmojiPicker"
|
||||||
|
class="icon icon-face"
|
||||||
|
:file="faceIcon"
|
||||||
|
:size="'23px'"
|
||||||
|
:hotAreaSize="'3px'"
|
||||||
|
@onClick="changeToolbarDisplayType('emojiPicker')"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
v-if="isRenderMore"
|
||||||
|
class="icon icon-more"
|
||||||
|
:file="moreIcon"
|
||||||
|
:size="'23px'"
|
||||||
|
:hotAreaSize="'3px'"
|
||||||
|
@onClick="changeToolbarDisplayType('tools')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<MessageQuote
|
||||||
|
:style="{minWidth: 0}"
|
||||||
|
:displayType="displayType"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import TUIChatEngine, {
|
||||||
|
TUIStore,
|
||||||
|
StoreName,
|
||||||
|
IMessageModel,
|
||||||
|
IConversationModel,
|
||||||
|
} from '@tencentcloud/chat-uikit-engine';
|
||||||
|
import { ref, watch, onMounted, onUnmounted } from '../../../adapter-vue';
|
||||||
|
import MessageInputEditor from './message-input-editor.vue';
|
||||||
|
import MessageInputAt from './message-input-at/index.vue';
|
||||||
|
import MessageInputAudio from './message-input-audio.vue';
|
||||||
|
import MessageQuote from './message-input-quote/index.vue';
|
||||||
|
import Icon from '../../common/Icon.vue';
|
||||||
|
import faceIcon from '../../../assets/icon/face-uni.png';
|
||||||
|
import moreIcon from '../../../assets/icon/more-uni.png';
|
||||||
|
import { isPC, isH5, isWeChat, isApp } from '../../../utils/env';
|
||||||
|
import { sendTyping } from '../utils/sendMessage';
|
||||||
|
import { ToolbarDisplayType, InputDisplayType } from '../../../interface';
|
||||||
|
import TUIChatConfig from '../config';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
placeholder: string;
|
||||||
|
isMuted?: boolean;
|
||||||
|
muteText?: string;
|
||||||
|
enableInput?: boolean;
|
||||||
|
enableAt?: boolean;
|
||||||
|
enableTyping?: boolean;
|
||||||
|
replyOrReference?: Record<string, any>;
|
||||||
|
inputToolbarDisplayType: ToolbarDisplayType;
|
||||||
|
}
|
||||||
|
interface IEmits {
|
||||||
|
(e: 'changeToolbarDisplayType', displayType: ToolbarDisplayType): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emits = defineEmits<IEmits>();
|
||||||
|
const props = withDefaults(defineProps<IProps>(), {
|
||||||
|
placeholder: 'this is placeholder',
|
||||||
|
replyOrReference: () => ({}),
|
||||||
|
isMuted: true,
|
||||||
|
muteText: '',
|
||||||
|
enableInput: true,
|
||||||
|
enableAt: true,
|
||||||
|
enableTyping: true,
|
||||||
|
inputToolbarDisplayType: 'none',
|
||||||
|
});
|
||||||
|
|
||||||
|
const editor = ref();
|
||||||
|
const messageInputAtRef = ref();
|
||||||
|
const currentConversation = ref<IConversationModel>();
|
||||||
|
const isGroup = ref<boolean>(false);
|
||||||
|
const displayType = ref<InputDisplayType>('editor');
|
||||||
|
const featureConfig = TUIChatConfig.getFeatureConfig();
|
||||||
|
const isRenderVoice = ref<boolean>(featureConfig.InputVoice);
|
||||||
|
const isRenderEmojiPicker = ref<boolean>(featureConfig.InputEmoji || featureConfig.InputStickers);
|
||||||
|
const isRenderMore = ref<boolean>(featureConfig.InputImage || featureConfig.InputVideo || featureConfig.InputEvaluation || featureConfig.InputQuickReplies);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
TUIStore.watch(StoreName.CONV, {
|
||||||
|
currentConversation: onCurrentConversationUpdated,
|
||||||
|
});
|
||||||
|
|
||||||
|
TUIStore.watch(StoreName.CHAT, {
|
||||||
|
quoteMessage: onQuoteMessageUpdated,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
TUIStore.unwatch(StoreName.CONV, {
|
||||||
|
currentConversation: onCurrentConversationUpdated,
|
||||||
|
});
|
||||||
|
|
||||||
|
TUIStore.unwatch(StoreName.CHAT, {
|
||||||
|
quoteMessage: onQuoteMessageUpdated,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => props.inputToolbarDisplayType, (newVal: ToolbarDisplayType) => {
|
||||||
|
if (newVal !== 'none') {
|
||||||
|
changeDisplayType('editor');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeDisplayType(display: InputDisplayType) {
|
||||||
|
displayType.value = display;
|
||||||
|
if (display === 'audio') {
|
||||||
|
emits('changeToolbarDisplayType', 'none');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeToolbarDisplayType(displayType: ToolbarDisplayType) {
|
||||||
|
emits('changeToolbarDisplayType', displayType);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onTyping = (inputContentEmpty: boolean, inputBlur: boolean) => {
|
||||||
|
sendTyping(inputContentEmpty, inputBlur);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAt = (show: boolean) => {
|
||||||
|
messageInputAtRef?.value?.toggleAtList(show);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFocus = () => {
|
||||||
|
// if (isH5) {
|
||||||
|
emits('changeToolbarDisplayType', 'none');
|
||||||
|
// }
|
||||||
|
// 新增隐藏加号控制显示内容的逻辑
|
||||||
|
// emits('changeToolbarDisplayType', 'none');
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertEmoji = (emoji: any) => {
|
||||||
|
editor?.value?.addEmoji && editor?.value?.addEmoji(emoji);
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertAt = (atInfo: any) => {
|
||||||
|
editor?.value?.insertAt && editor?.value?.insertAt(atInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAtListOpen = () => {
|
||||||
|
editor?.value?.blur && editor?.value?.blur();
|
||||||
|
};
|
||||||
|
|
||||||
|
const reEdit = (content: any) => {
|
||||||
|
editor?.value?.resetEditor();
|
||||||
|
editor?.value?.setEditorContent(content);
|
||||||
|
};
|
||||||
|
|
||||||
|
function onCurrentConversationUpdated(conversation: IConversationModel) {
|
||||||
|
currentConversation.value = conversation;
|
||||||
|
isGroup.value = currentConversation.value?.type === TUIChatEngine.TYPES.CONV_GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onQuoteMessageUpdated(options?: { message: IMessageModel; type: string }) {
|
||||||
|
// switch text input mode when there is a quote message
|
||||||
|
if (options?.message && options?.type === 'quote') {
|
||||||
|
changeDisplayType('editor');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
insertEmoji,
|
||||||
|
reEdit,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "../../../assets/styles/common";
|
||||||
|
|
||||||
|
:not(not) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-input {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: none;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #ebf0f6;
|
||||||
|
|
||||||
|
&-h5 {
|
||||||
|
padding: 10px 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-editor {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-wx-audio-open {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.audio-main-content-line {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
285
TUIKit/components/TUIChat/message-input/message-input-editor.vue
Normal file
285
TUIKit/components/TUIChat/message-input/message-input-editor.vue
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="{
|
||||||
|
'message-input-container': true,
|
||||||
|
'message-input-container-h5': !isPC,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="props.isMuted"
|
||||||
|
class="message-input-mute"
|
||||||
|
>
|
||||||
|
{{ props.muteText }}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
id="editor"
|
||||||
|
ref="inputRef"
|
||||||
|
v-model="inputText"
|
||||||
|
:adjust-position="true"
|
||||||
|
cursor-spacing="20"
|
||||||
|
confirm-type="send"
|
||||||
|
:confirm-hold="true"
|
||||||
|
maxlength="140"
|
||||||
|
type="text"
|
||||||
|
placeholder-class="input-placeholder"
|
||||||
|
class="message-input-area"
|
||||||
|
:placeholder="props.placeholder"
|
||||||
|
auto-blur
|
||||||
|
@confirm="handleSendMessage"
|
||||||
|
@input="onInput"
|
||||||
|
@blur="onBlur"
|
||||||
|
@focus="onFocus"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch, onMounted, onUnmounted } from '../../../adapter-vue';
|
||||||
|
import { TUIStore, StoreName, IConversationModel, IMessageModel } from '@tencentcloud/chat-uikit-engine';
|
||||||
|
import { TUIGlobal } from '@tencentcloud/universal-api';
|
||||||
|
import DraftManager from '../utils/conversationDraft';
|
||||||
|
import { transformTextWithEmojiNamesToKeys } from '../emoji-config';
|
||||||
|
import { isPC } from '../../../utils/env';
|
||||||
|
import { sendMessages } from '../utils/sendMessage';
|
||||||
|
import { ISendMessagePayload } from '../../../interface';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: 'this is placeholder',
|
||||||
|
},
|
||||||
|
replayOrReferenceMessage: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
isMuted: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
muteText: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
enableInput: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
enableAt: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
enableTyping: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
isGroup: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(['onTyping', 'onFocus', 'onAt']);
|
||||||
|
const inputText = ref('');
|
||||||
|
const inputRef = ref();
|
||||||
|
const inputBlur = ref(true);
|
||||||
|
const inputContentEmpty = ref(true);
|
||||||
|
const allInsertedAtInfo = new Map();
|
||||||
|
const currentConversation = ref<IConversationModel>();
|
||||||
|
const currentConversationID = ref<string>('');
|
||||||
|
const currentQuoteMessage = ref<{ message: IMessageModel; type: string }>();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
TUIStore.watch(StoreName.CONV, {
|
||||||
|
currentConversation: onCurrentConversationUpdated,
|
||||||
|
});
|
||||||
|
|
||||||
|
TUIStore.watch(StoreName.CHAT, {
|
||||||
|
quoteMessage: onQuoteMessageUpdated,
|
||||||
|
});
|
||||||
|
|
||||||
|
uni.$on('insert-emoji', (data) => {
|
||||||
|
inputText.value += data?.emoji?.name;
|
||||||
|
});
|
||||||
|
|
||||||
|
uni.$on('send-message-in-emoji-picker', () => {
|
||||||
|
handleSendMessage();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (currentConversationID.value) {
|
||||||
|
DraftManager.setStore(currentConversationID.value, inputText.value, inputText.value, currentQuoteMessage.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.$off('insertEmoji');
|
||||||
|
uni.$off('send-message-in-emoji-picker');
|
||||||
|
|
||||||
|
TUIStore.unwatch(StoreName.CONV, {
|
||||||
|
currentConversation: onCurrentConversationUpdated,
|
||||||
|
});
|
||||||
|
|
||||||
|
TUIStore.unwatch(StoreName.CHAT, {
|
||||||
|
quoteMessage: onQuoteMessageUpdated,
|
||||||
|
});
|
||||||
|
|
||||||
|
reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSendMessage = () => {
|
||||||
|
const messageList = getEditorContent();
|
||||||
|
resetEditor();
|
||||||
|
sendMessages(messageList as any, currentConversation.value!);
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertAt = (atInfo: any) => {
|
||||||
|
if (!allInsertedAtInfo?.has(atInfo?.id)) {
|
||||||
|
allInsertedAtInfo?.set(atInfo?.id, atInfo?.label);
|
||||||
|
}
|
||||||
|
inputText.value += atInfo?.label;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getEditorContent = () => {
|
||||||
|
let text = inputText.value;
|
||||||
|
text = transformTextWithEmojiNamesToKeys(text);
|
||||||
|
const atUserList: string[] = [];
|
||||||
|
allInsertedAtInfo?.forEach((value: string, key: string) => {
|
||||||
|
if (text?.includes('@' + value)) {
|
||||||
|
atUserList.push(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const payload: ISendMessagePayload = {
|
||||||
|
text,
|
||||||
|
};
|
||||||
|
if (atUserList?.length) {
|
||||||
|
payload.atUserList = atUserList;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
payload,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetEditor = () => {
|
||||||
|
inputText.value = '';
|
||||||
|
inputContentEmpty.value = true;
|
||||||
|
allInsertedAtInfo?.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
const setEditorContent = (content: any) => {
|
||||||
|
inputText.value = content;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onBlur = () => {
|
||||||
|
inputBlur.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFocus = (e: any) => {
|
||||||
|
inputBlur.value = false;
|
||||||
|
emits('onFocus', e?.detail?.height);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEditorContentEmpty = () => {
|
||||||
|
inputContentEmpty.value = inputText?.value?.length ? false : true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onInput = (e: any) => {
|
||||||
|
// uni-app recognizes mention messages
|
||||||
|
const text = e?.detail?.value;
|
||||||
|
isEditorContentEmpty();
|
||||||
|
if (props.isGroup && (text.endsWith('@') || text.endsWith('@\n'))) {
|
||||||
|
// TUIGlobal?.hideKeyboard();
|
||||||
|
emits('onAt', true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [inputContentEmpty.value, inputBlur.value],
|
||||||
|
(newVal: any, oldVal: any) => {
|
||||||
|
if (newVal !== oldVal) {
|
||||||
|
emits('onTyping', inputContentEmpty.value, inputBlur.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
function onCurrentConversationUpdated(conversation: IConversationModel) {
|
||||||
|
const prevConversationID = currentConversationID.value;
|
||||||
|
currentConversation.value = conversation;
|
||||||
|
currentConversationID.value = conversation?.conversationID;
|
||||||
|
if (prevConversationID !== currentConversationID.value) {
|
||||||
|
if (prevConversationID) {
|
||||||
|
DraftManager.setStore(
|
||||||
|
prevConversationID,
|
||||||
|
inputText.value,
|
||||||
|
inputText.value,
|
||||||
|
currentQuoteMessage.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
resetEditor();
|
||||||
|
if (currentConversationID.value) {
|
||||||
|
DraftManager.getStore(currentConversationID.value, setEditorContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onQuoteMessageUpdated(options?: { message: IMessageModel; type: string }) {
|
||||||
|
currentQuoteMessage.value = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
inputBlur.value = true;
|
||||||
|
currentConversation.value = null;
|
||||||
|
currentConversationID.value = '';
|
||||||
|
currentQuoteMessage.value = null;
|
||||||
|
resetEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
insertAt,
|
||||||
|
resetEditor,
|
||||||
|
setEditorContent,
|
||||||
|
getEditorContent,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../../assets/styles/common";
|
||||||
|
|
||||||
|
.message-input-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
padding: 3px 10px 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&-h5 {
|
||||||
|
flex: 1;
|
||||||
|
height: auto;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 7px 0 7px 10px;
|
||||||
|
font-size: 16px !important;
|
||||||
|
max-height: 86px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-input-mute {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-input-area {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: scroll;
|
||||||
|
min-height: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
430
TUIKit/components/TUIContact/contact-info/index.vue
Normal file
430
TUIKit/components/TUIContact/contact-info/index.vue
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:style="{height: '100%'}"
|
||||||
|
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>
|
||||||
138
TUIKit/components/TUIContact/index.vue
Normal file
138
TUIKit/components/TUIContact/index.vue
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<template>
|
||||||
|
<SelectFriend v-if="isShowSelectFriend" />
|
||||||
|
<div
|
||||||
|
v-else-if="isShowContactList"
|
||||||
|
:class="['tui-contact', !isPC && 'tui-contact-h5']"
|
||||||
|
>
|
||||||
|
<div :class="['tui-contact-left', !isPC && 'tui-contact-h5-left']" :style="{height:ht+'px'}">
|
||||||
|
<!-- <ContactSearch /> -->
|
||||||
|
<ContactList :class="['tui-contact-left-list', !isPC && 'tui-contact-h5-left-list']" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isShowContactInfo"
|
||||||
|
:class="['tui-contact-right', !isPC && 'tui-contact-h5-right']"
|
||||||
|
:style="{height:ht+'px'}"
|
||||||
|
>
|
||||||
|
<ContactInfo @switchConversation="switchConversation" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { TUIStore, StoreName } from '@tencentcloud/chat-uikit-engine';
|
||||||
|
import { TUIGlobal } from '@tencentcloud/universal-api';
|
||||||
|
import { ref, watchEffect,defineProps } from '../../adapter-vue';
|
||||||
|
import { isPC, isUniFrameWork } from '../../utils/env';
|
||||||
|
const ht = uni.getSystemInfoSync().windowHeight
|
||||||
|
import SelectFriend from './select-friend/index.vue';
|
||||||
|
import ContactSearch from './contact-search/index.vue';
|
||||||
|
import ContactList from './contact-list/index.vue';
|
||||||
|
import ContactInfo from './contact-info/index.vue';
|
||||||
|
|
||||||
|
const emits = defineEmits(['switchConversation']);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// web/h5 single page application display format, uniapp please ignore
|
||||||
|
displayType: {
|
||||||
|
type: String,
|
||||||
|
default: 'contactList', // "contactList" / "selectFriend"
|
||||||
|
require: false,
|
||||||
|
|
||||||
|
},
|
||||||
|
stu: {
|
||||||
|
type: Number, // 这里可以根据实际类型修改,如 String, Number, Object 等
|
||||||
|
require: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const displayTypeRef = ref<string>(props.displayType || 'contactList');
|
||||||
|
const isShowSelectFriend = ref(false);
|
||||||
|
const isShowContactList = ref(true);
|
||||||
|
const isShowContactInfo = ref(true);
|
||||||
|
const isstu=ref(props.stu);
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
isShowContactList.value = props?.displayType !== 'selectFriend';
|
||||||
|
});
|
||||||
|
|
||||||
|
TUIStore.watch(StoreName.CUSTOM, {
|
||||||
|
isShowSelectFriendComponent: (data: any) => {
|
||||||
|
if (!isUniFrameWork && props?.displayType === 'selectFriend') {
|
||||||
|
isShowSelectFriend.value = data;
|
||||||
|
isShowContactList.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
isShowSelectFriend.value = true;
|
||||||
|
if (isUniFrameWork) {
|
||||||
|
displayTypeRef.value = 'selectFriend';
|
||||||
|
TUIGlobal?.hideTabBar();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isShowSelectFriend.value = false;
|
||||||
|
if (isUniFrameWork) {
|
||||||
|
displayTypeRef.value = props.displayType;
|
||||||
|
TUIGlobal?.showTabBar()?.catch(() => { /* ignore */ });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
currentContactInfo: (contactInfo: any) => {
|
||||||
|
isShowContactInfo.value = isPC || (contactInfo && typeof contactInfo === 'object' && Object.keys(contactInfo)?.length > 0);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const switchConversation = (data: any) => {
|
||||||
|
isUniFrameWork
|
||||||
|
&& TUIGlobal?.navigateTo({
|
||||||
|
url: '/TUIKit/components/TUIChat/index',
|
||||||
|
});
|
||||||
|
emits('switchConversation', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../assets/styles/common";
|
||||||
|
|
||||||
|
.tui-contact {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&-left {
|
||||||
|
min-width: 285px;
|
||||||
|
flex: 0 0 24%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-right {
|
||||||
|
border-left: 1px solid #f4f5f9;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tui-contact-h5 {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&-left,
|
||||||
|
&-right {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-right {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-left {
|
||||||
|
&-list {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
139
TUIKit/components/TUIContact/indexsea.vue
Normal file
139
TUIKit/components/TUIContact/indexsea.vue
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<SelectFriend v-if="isShowSelectFriend" />
|
||||||
|
<div
|
||||||
|
v-else-if="isShowContactList"
|
||||||
|
:class="['tui-contact', !isPC && 'tui-contact-h5']"
|
||||||
|
>
|
||||||
|
<div :class="['tui-contact-left', !isPC && 'tui-contact-h5-left']" :style="{height:ht+'px'}" >
|
||||||
|
<ContactSearch />
|
||||||
|
<ContactList :class="['tui-contact-left-list', !isPC && 'tui-contact-h5-left-list']" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isShowContactInfo"
|
||||||
|
:class="['tui-contact-right', !isPC && 'tui-contact-h5-right']"
|
||||||
|
:style="{height:ht+'px'}"
|
||||||
|
>
|
||||||
|
<ContactInfo @switchConversation="switchConversation" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { TUIStore, StoreName } from '@tencentcloud/chat-uikit-engine';
|
||||||
|
import { TUIGlobal } from '@tencentcloud/universal-api';
|
||||||
|
import { ref, watchEffect,defineProps } from '../../adapter-vue';
|
||||||
|
import { isPC, isUniFrameWork } from '../../utils/env';
|
||||||
|
|
||||||
|
import SelectFriend from './select-friend/index.vue';
|
||||||
|
import ContactSearch from './contact-search/index.vue';
|
||||||
|
import ContactList from './contact-list/indexsea.vue';
|
||||||
|
import ContactInfo from './contact-info/index.vue';
|
||||||
|
|
||||||
|
const emits = defineEmits(['switchConversation']);
|
||||||
|
const ht = uni.getSystemInfoSync().windowHeight
|
||||||
|
const props = defineProps({
|
||||||
|
// web/h5 single page application display format, uniapp please ignore
|
||||||
|
displayType: {
|
||||||
|
type: String,
|
||||||
|
default: 'contactList', // "contactList" / "selectFriend"
|
||||||
|
require: false,
|
||||||
|
|
||||||
|
},
|
||||||
|
stu: {
|
||||||
|
type: Number, // 这里可以根据实际类型修改,如 String, Number, Object 等
|
||||||
|
require: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const displayTypeRef = ref<string>(props.displayType || 'contactList');
|
||||||
|
const isShowSelectFriend = ref(false);
|
||||||
|
const isShowContactList = ref(true);
|
||||||
|
const isShowContactInfo = ref(true);
|
||||||
|
const isstu=ref(props.stu);
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
isShowContactList.value = props?.displayType !== 'selectFriend';
|
||||||
|
});
|
||||||
|
|
||||||
|
TUIStore.watch(StoreName.CUSTOM, {
|
||||||
|
isShowSelectFriendComponent: (data: any) => {
|
||||||
|
if (!isUniFrameWork && props?.displayType === 'selectFriend') {
|
||||||
|
isShowSelectFriend.value = data;
|
||||||
|
isShowContactList.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
isShowSelectFriend.value = true;
|
||||||
|
if (isUniFrameWork) {
|
||||||
|
displayTypeRef.value = 'selectFriend';
|
||||||
|
TUIGlobal?.hideTabBar();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isShowSelectFriend.value = false;
|
||||||
|
if (isUniFrameWork) {
|
||||||
|
displayTypeRef.value = props.displayType;
|
||||||
|
TUIGlobal?.showTabBar()?.catch(() => { /* ignore */ });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
currentContactInfo: (contactInfo: any) => {
|
||||||
|
isShowContactInfo.value = isPC || (contactInfo && typeof contactInfo === 'object' && Object.keys(contactInfo)?.length > 0);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const switchConversation = (data: any) => {
|
||||||
|
isUniFrameWork
|
||||||
|
&& TUIGlobal?.navigateTo({
|
||||||
|
url: '/TUIKit/components/TUIChat/index',
|
||||||
|
});
|
||||||
|
emits('switchConversation', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../assets/styles/common";
|
||||||
|
|
||||||
|
.tui-contact {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&-left {
|
||||||
|
min-width: 285px;
|
||||||
|
flex: 0 0 24%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-right {
|
||||||
|
border-left: 1px solid #f4f5f9;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tui-contact-h5 {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&-left,
|
||||||
|
&-right {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-right {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-left {
|
||||||
|
&-list {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
23
api/home.js
23
api/home.js
@ -12,6 +12,17 @@ export function getAdvertisement() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 像后端传递经纬度
|
||||||
|
*/
|
||||||
|
export function postAdvertisementjw(data) {
|
||||||
|
return http.request({
|
||||||
|
url: "/member/address/location",
|
||||||
|
method: Method.POST,
|
||||||
|
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +61,17 @@ export function getFloorData() {
|
|||||||
method: "get",
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 获取本地生活楼层数据
|
||||||
|
* @param client_type
|
||||||
|
* @param page_type
|
||||||
|
*/
|
||||||
|
export function getFloorgetBendi() {
|
||||||
|
return http.request({
|
||||||
|
url: `/other/pageData/getBendi?clientType=H5`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 获取获取首页分类数据
|
* 获取获取首页分类数据
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import {http, Method} from '@/utils/request.js';
|
|||||||
*/
|
*/
|
||||||
export function getStoreList(params) {
|
export function getStoreList(params) {
|
||||||
return http.request({
|
return http.request({
|
||||||
url: '/store',
|
url: '/store/store',
|
||||||
method: Method.GET,
|
method: Method.GET,
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -284,9 +284,11 @@ export default {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const storedSte = uni.getStorageSync('ste');
|
||||||
let data = {
|
let data = {
|
||||||
skuId: this.goodsDetail.id,
|
skuId: this.goodsDetail.id,
|
||||||
num: this.num,
|
num: this.num,
|
||||||
|
ste:storedSte
|
||||||
};
|
};
|
||||||
|
|
||||||
if (val == "cart") {
|
if (val == "cart") {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export default {
|
|||||||
shareLink: "https://m-b2b2c.pickmall.cn", //分享地址,也就是在h5中默认的复制地址
|
shareLink: "https://m-b2b2c.pickmall.cn", //分享地址,也就是在h5中默认的复制地址
|
||||||
appid: "wx6f10f29075dc1b0b", //小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
|
appid: "wx6f10f29075dc1b0b", //小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
|
||||||
appSecret: "6dfbe0c72380dce5d49d65b3c91059b1", //可在 manifest.json 查看
|
appSecret: "6dfbe0c72380dce5d49d65b3c91059b1", //可在 manifest.json 查看
|
||||||
aMapKey: "d649892b3937a5ad20b76dacb2bcb5bd", //在高德中申请web端key
|
aMapKey: "AOHBZ-VCEL3-XX73N-O623U-FMTP6-ASBTD", //在腾讯的中申请web端key
|
||||||
scanAuthNavigation:['https://m-b2b2c.pickmall.cn/'], //扫码认证跳转域名配置 会根据此处配置的路由进行跳转
|
scanAuthNavigation:['https://m-b2b2c.pickmall.cn/'], //扫码认证跳转域名配置 会根据此处配置的路由进行跳转
|
||||||
iosAppId:"id1564638363", //AppStore的应用地址id 具体在分享->拷贝链接中查看
|
iosAppId:"id1564638363", //AppStore的应用地址id 具体在分享->拷贝链接中查看
|
||||||
logo:"https://lilishop-oss.oss-cn-beijing.aliyuncs.com/4c864e133c2944efad1f7282ac8a3b9e.png", //logo地址
|
logo:"https://lilishop-oss.oss-cn-beijing.aliyuncs.com/4c864e133c2944efad1f7282ac8a3b9e.png", //logo地址
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name" : "wzj4",
|
"name" : "wzj4",
|
||||||
"appid" : "__UNI__6DB512D",
|
"appid" : "__UNI__1F0975C",
|
||||||
"description" : "",
|
"description" : "admin",
|
||||||
"versionName" : "4.0.0",
|
"versionName" : "4.0.0",
|
||||||
"versionCode" : 4000049,
|
"versionCode" : 4000049,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
|
|||||||
2084
pages.json
2084
pages.json
File diff suppressed because it is too large
Load Diff
@ -541,13 +541,15 @@ export default {
|
|||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
client = "APP";
|
client = "APP";
|
||||||
// #endif
|
// #endif
|
||||||
|
const storedSte = uni.getStorageSync('ste');
|
||||||
let submit = {
|
let submit = {
|
||||||
client,
|
client,
|
||||||
way: this.routerVal.way,
|
way: this.routerVal.way,
|
||||||
remark: this.remarkVal,
|
remark: this.remarkVal,
|
||||||
parentOrderSn: "",
|
parentOrderSn: "",
|
||||||
|
ste:storedSte
|
||||||
};
|
};
|
||||||
|
console.log(submit,'===')
|
||||||
// 如果是拼团并且当前用户不是团长
|
// 如果是拼团并且当前用户不是团长
|
||||||
this.routerVal.parentOrder && this.routerVal.parentOrder.orderSn
|
this.routerVal.parentOrder && this.routerVal.parentOrder.orderSn
|
||||||
? (submit.parentOrderSn = this.routerVal.parentOrder.orderSn)
|
? (submit.parentOrderSn = this.routerVal.parentOrder.orderSn)
|
||||||
|
|||||||
@ -788,7 +788,7 @@ export default {
|
|||||||
id: this.productId,
|
id: this.productId,
|
||||||
};
|
};
|
||||||
storage.setCartBackbtn(obj);
|
storage.setCartBackbtn(obj);
|
||||||
uni.switchTab({
|
uni.navigateTo({
|
||||||
url: "/pages/tabbar/cart/cartList",
|
url: "/pages/tabbar/cart/cartList",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -63,6 +63,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
tostorePage(val) {
|
tostorePage(val) {
|
||||||
|
console.log(val);
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: "../product/shopPage?id=" + val.storeId,
|
url: "../product/shopPage?id=" + val.storeId,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,21 +7,22 @@
|
|||||||
<div class="wrapper" v-if="storeList.length!=0">
|
<div class="wrapper" v-if="storeList.length!=0">
|
||||||
<div class="store-item" @click="handleClickStore(item)" v-for="(item,index) in storeList" :key="index">
|
<div class="store-item" @click="handleClickStore(item)" v-for="(item,index) in storeList" :key="index">
|
||||||
<div>
|
<div>
|
||||||
<u-image shape="circle" width="100" height="100" :src="item.storeLogo">
|
<u-image shape="square" width="100" height="100" :src="item.storeLogo">
|
||||||
</u-image>
|
</u-image>
|
||||||
</div>
|
</div>
|
||||||
<div class="store-msg">
|
<div class="store-msg">
|
||||||
<div class="store-name">
|
<div class="store-name">
|
||||||
{{item.storeName}}
|
<div> {{item.storeName}}</div>
|
||||||
|
<div class="typeof" >{{item.selfOperated?'自营':'非自营'}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="goods-num">
|
<div class="goods-num">
|
||||||
商品 {{item.goodsNum}}
|
商品 {{item.goodsNum}} <span class="line">|</span> <span class="store-collection">收藏 {{item.collectionNum}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex store-distance">
|
<div class="flex store-distance">
|
||||||
<div>
|
<div>
|
||||||
<span class="store-score">{{item.serviceScore | unitPrice}}</span>
|
<template v-for="i in 5">
|
||||||
<span class="line">|</span>
|
<u-icon :name="i <= item.serviceScore ? 'star-fill' : 'star'" color="#FF0000" size="30"></u-icon>
|
||||||
<span class="store-collection">收藏 {{item.collectionNum}}</span>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -113,11 +114,19 @@ export default {
|
|||||||
padding: 24rpx;
|
padding: 24rpx;
|
||||||
}
|
}
|
||||||
.store-msg {
|
.store-msg {
|
||||||
|
width: 100%;
|
||||||
margin-left: 20rpx;
|
margin-left: 20rpx;
|
||||||
}
|
}
|
||||||
.store-name {
|
.store-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 30rpx;
|
font-size: 35rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
.typeof{
|
||||||
|
border: 1px solid red;
|
||||||
|
color: red;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.goods-num,
|
.goods-num,
|
||||||
.store-collection {
|
.store-collection {
|
||||||
|
|||||||
@ -1,7 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<!-- 楼层装修组件 -->
|
<!-- 楼层装修组件 -->
|
||||||
<tpl ref="tpl" />
|
<u-navbar class="navbar" :is-back="false" :is-fixed="false">
|
||||||
|
<div class="tab-container">
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in list1"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: currentTabIndex === index }"
|
||||||
|
@click="click(item)"
|
||||||
|
>
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</u-navbar>
|
||||||
|
<!-- 商城 -->
|
||||||
|
<tpl ref="tpl" v-if="currentTabIndex == 1" :ste="1" />
|
||||||
|
<!-- 本地生活 -->
|
||||||
|
<tpl ref="tpl" v-if="currentTabIndex == 0" :ste="0" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@ -13,21 +29,55 @@ export default {
|
|||||||
background: {
|
background: {
|
||||||
backgroundColor: "#fff",
|
backgroundColor: "#fff",
|
||||||
},
|
},
|
||||||
|
list1: [
|
||||||
|
{
|
||||||
|
name: "本地生活",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "商城",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
currentTabIndex: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onPullDownRefresh() {
|
|
||||||
this.$refs.tpl.init();
|
|
||||||
|
|
||||||
uni.stopPullDownRefresh();
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
tpl,
|
tpl,
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
click(item) {
|
||||||
|
this.currentTabIndex = this.list1.indexOf(item);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
this.$refs.tpl.init();
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.wrapper{
|
.tab-container {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
// background-color: #f0f0f0;
|
||||||
|
// padding: 0 16rpx 0 0;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
.tab-container div {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
.tab-container div.active {
|
||||||
|
border-bottom: 2px solid #F50505;
|
||||||
|
color:#F50505;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
// background: red;
|
||||||
|
}
|
||||||
|
.navbar{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
103
pages/tabbar/home/template/Talent.vue
Normal file
103
pages/tabbar/home/template/Talent.vue
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout">
|
||||||
|
<div class="con_view">
|
||||||
|
<div class="-item-tilte">
|
||||||
|
<img class="image-mode" style="height: 150px" :src="model.imgs" />
|
||||||
|
<span> {{ model.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="sea" @click="clickSwiper">更多></div>
|
||||||
|
</div>
|
||||||
|
<!-- <div>自己代码编辑</div> -->
|
||||||
|
<div class="menu-list" style="overflow-x: auto; white-space: nowrap; scrollbar-width: none; -ms-overflow-style: none;">
|
||||||
|
<div class="menu-item" v-for="(item, index) in res.list" :key="index">
|
||||||
|
<div>
|
||||||
|
<img class="menu-img" :src="item.img" alt="" @click="tostorePage(item)" />
|
||||||
|
</div>
|
||||||
|
<!-- <div class="menu-title">{{ item.title }}</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { modelNavigateTo } from "./tpl";
|
||||||
|
export default {
|
||||||
|
title: "达人店",
|
||||||
|
props: ["res","model"],
|
||||||
|
watch: {
|
||||||
|
res: {
|
||||||
|
handler(newValue, oldValue) {
|
||||||
|
this.$set(this, "res", newValue);
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//跳转个人店铺
|
||||||
|
tostorePage(val) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/product/shopPage?id=" + val.url.id,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//跳转店铺
|
||||||
|
clickSwiper(index) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/product/shopList",
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "./tpl.scss";
|
||||||
|
.carousel,
|
||||||
|
.image-mode {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px !important;
|
||||||
|
}
|
||||||
|
.layout{
|
||||||
|
background: url('@/static/tanback.png') no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
.con_view {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.-item-tilte {
|
||||||
|
display: flex;
|
||||||
|
& > span {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: 800;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sea {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.menu-list {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
// flex-wrap: wrap;
|
||||||
|
|
||||||
|
> .menu-item {
|
||||||
|
text-align: center;
|
||||||
|
width: 200px;
|
||||||
|
margin: 10px 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.menu-img {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
.menu-title {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.menu-list::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
20
pages/tabbar/home/template/tpl_activity.vue
Normal file
20
pages/tabbar/home/template/tpl_activity.vue
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout">
|
||||||
|
<img :src="res.list[0].img" alt="">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
title: "活动",
|
||||||
|
props: ["res"],
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "./tpl.scss";
|
||||||
|
.layout{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@ -1,38 +1,261 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<div class="search" @click="handleSearch">
|
<div class="addres" @click="showPicker" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
||||||
<u-icon name="search"></u-icon>
|
{{ cityOrCounty == "" ? "请选择" : cityOrCounty }}
|
||||||
{{ res.list[0].title }}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="search">{{ res.list[0].title }}</div>
|
||||||
|
<div class="shop" @click="toshop"></div>
|
||||||
|
<m-city
|
||||||
|
:provinceData="list"
|
||||||
|
headTitle="区域选择"
|
||||||
|
ref="cityPicker"
|
||||||
|
@funcValue="getpickerParentValue"
|
||||||
|
pickerSize="3"
|
||||||
|
>
|
||||||
|
</m-city>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import config from "@/config/config";
|
||||||
|
import { postAdvertisementjw } from "@/api/home.js";
|
||||||
|
import gkcity from "@/components/m-city/m-city.vue";
|
||||||
|
import { Icon } from "uview-ui";
|
||||||
export default {
|
export default {
|
||||||
title:"搜索栏",
|
components: {
|
||||||
|
"m-city": gkcity,
|
||||||
|
Icon,
|
||||||
|
},
|
||||||
|
title: "搜索栏",
|
||||||
props: ["res"],
|
props: ["res"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
location: null,
|
||||||
|
// 确保默认值正确读取
|
||||||
|
cityOrCounty: uni.getStorageSync("cityOrCounty") || "",
|
||||||
|
form: {},
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: "",
|
||||||
|
localName: "请选择",
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// 添加本地存储的经纬度
|
||||||
|
storedLat: uni.getStorageSync("latitude") || null,
|
||||||
|
storedLon: uni.getStorageSync("longitude") || null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 页面加载时,若本地有存储数据就使用
|
||||||
|
if (this.storedLat && this.storedLon) {
|
||||||
|
this.form.lat = this.storedLat;
|
||||||
|
this.form.lon = this.storedLon;
|
||||||
|
this.getAdvertisementByLocation();
|
||||||
|
}
|
||||||
|
// 确保地区名称也被读取
|
||||||
|
this.cityOrCounty = uni.getStorageSync("cityOrCounty") || "";
|
||||||
|
// this.getLocation();
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
toshop() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/tabbar/cart/cartList",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 三级地址联动回调
|
||||||
|
async getpickerParentValue(e) {
|
||||||
|
// 将需要绑定的地址设置为空,并赋值
|
||||||
|
this.form.consigneeAddressIdPath = [];
|
||||||
|
this.form.consigneeAddressPath = [];
|
||||||
|
let name = "";
|
||||||
|
|
||||||
|
e.forEach((item, index) => {
|
||||||
|
if (item.id) {
|
||||||
|
// 遍历数据
|
||||||
|
this.form.consigneeAddressIdPath.push(item.id);
|
||||||
|
this.form.consigneeAddressPath.push(item.localName);
|
||||||
|
name += item.localName;
|
||||||
|
this.form.___path = name;
|
||||||
|
}
|
||||||
|
if (index == e.length - 1) {
|
||||||
|
//如果是最后一个
|
||||||
|
let _town = item.children.filter((_child) => {
|
||||||
|
return _child.id == item.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form.lat = _town[0].center.split(",")[1];
|
||||||
|
this.form.lon = _town[0].center.split(",")[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const jwobj = {
|
||||||
|
longitude: Number(this.form.lon),
|
||||||
|
latitude: Number(this.form.lat),
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data } = await postAdvertisementjw(jwobj);
|
||||||
|
if (data.success) {
|
||||||
|
// 确保保存的城市名称正确
|
||||||
|
this.cityOrCounty = this.form.consigneeAddressPath[2];
|
||||||
|
uni.setStorageSync("cityOrCounty", this.cityOrCounty);
|
||||||
|
// 存储经纬度
|
||||||
|
uni.setStorageSync("longitude", this.form.lon);
|
||||||
|
uni.setStorageSync("latitude", this.form.lat);
|
||||||
|
// 更新本地存储的经纬度
|
||||||
|
this.storedLat = this.form.lat;
|
||||||
|
this.storedLon = this.form.lon;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 根据经纬度获取广告信息
|
||||||
|
async getAdvertisementByLocation() {
|
||||||
|
const jwobj = {
|
||||||
|
longitude: Number(this.storedLon),
|
||||||
|
latitude: Number(this.storedLat),
|
||||||
|
};
|
||||||
|
const { data } = await postAdvertisementjw(jwobj);
|
||||||
|
if (data.success) {
|
||||||
|
// 更新页面内容
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showPicker() {
|
||||||
|
this.$refs.cityPicker.show();
|
||||||
|
},
|
||||||
handleSearch() {
|
handleSearch() {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: "/pages/navigation/search/searchPage",
|
url: "/pages/navigation/search/searchPage",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// async getLocation() {
|
||||||
|
// const permision = await import("@/js_sdk/wa-permission/permission.js");
|
||||||
|
// // #ifdef APP-PLUS
|
||||||
|
// if (plus.os.name == "iOS") {
|
||||||
|
// if (permision.judgeIosPermissionLocation()) {
|
||||||
|
// this.getLocationInfo();
|
||||||
|
// } else {
|
||||||
|
// this.refuseLocation();
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// const result = await permision.requestAndroidPermission(
|
||||||
|
// "android.permission.ACCESS_FINE_LOCATION"
|
||||||
|
// );
|
||||||
|
// if (result == 1) {
|
||||||
|
// this.getLocationInfo();
|
||||||
|
// } else {
|
||||||
|
// this.refuseLocation();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // #endif
|
||||||
|
// // #ifndef APP-PLUS
|
||||||
|
// this.getLocationInfo();
|
||||||
|
// // #endif
|
||||||
|
// },
|
||||||
|
// getLocationInfo() {
|
||||||
|
// uni.getLocation({
|
||||||
|
// type: "wgs84",
|
||||||
|
// success: async (resss) => {
|
||||||
|
// this.location = resss;
|
||||||
|
// console.log("当前位置:", resss);
|
||||||
|
// const jwobj = {
|
||||||
|
// latitude: resss.latitude,
|
||||||
|
// longitude: resss.longitude,
|
||||||
|
// };
|
||||||
|
// const { data } = await postAdvertisementjw(jwobj);
|
||||||
|
// if (data.success) {
|
||||||
|
// uni.request({
|
||||||
|
// url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${resss.latitude},${resss.longitude}&key=${config.aMapKey}`,
|
||||||
|
// success: (res) => {
|
||||||
|
// console.log("腾讯地图API接口返回信息", res);
|
||||||
|
// this.cityOrCounty = res.data.result.address_component.district || res.data.result.address_component.city;
|
||||||
|
// uni.setStorageSync('cityOrCounty', this.cityOrCounty);
|
||||||
|
// // 存储经纬度
|
||||||
|
// uni.setStorageSync('longitude', resss.longitude);
|
||||||
|
// uni.setStorageSync('latitude', resss.latitude);
|
||||||
|
// // 更新本地存储的经纬度
|
||||||
|
// this.storedLat = resss.latitude;
|
||||||
|
// this.storedLon = resss.longitude;
|
||||||
|
// },
|
||||||
|
// fail: (error) => {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: "获取位置信息失败222腾讯",
|
||||||
|
// icon: "none"
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// fail: (err) => {
|
||||||
|
// console.error("获取位置失败:", err);
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// refuseLocation() {
|
||||||
|
// uni.showModal({
|
||||||
|
// title: "温馨提示",
|
||||||
|
// content: "您已拒绝定位,请开启",
|
||||||
|
// confirmText: "去设置",
|
||||||
|
// success(res) {
|
||||||
|
// if (res.confirm) {
|
||||||
|
// //打开授权设置
|
||||||
|
// // #ifndef MP-WEIXIN
|
||||||
|
// uni.getSystemInfo({
|
||||||
|
// success(res) {
|
||||||
|
// if (res.platform == "ios") {
|
||||||
|
// //IOS
|
||||||
|
// plus.runtime.openURL("app-settings://");
|
||||||
|
// } else if (res.platform == "android") {
|
||||||
|
// //安卓
|
||||||
|
// let main = plus.android.runtimeMainActivity();
|
||||||
|
// let Intent = plus.android.importClass(
|
||||||
|
// "android.content.Intent"
|
||||||
|
// );
|
||||||
|
// let mIntent = new Intent("android.settings.ACTION_SETTINGS");
|
||||||
|
// main.startActivity(mIntent);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// // #endif
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "./tpl.scss";
|
@import "./tpl.scss";
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
height: 64rpx;
|
width: 68%;
|
||||||
border-radius: 10rpx;
|
height: 32px;
|
||||||
|
border-radius: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: #ededed;
|
background: #ededed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
background: #fff;
|
// background: #fff;
|
||||||
padding: 0 16rpx;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.addres {
|
||||||
|
// width: 15%;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.layout {
|
||||||
|
// background: #fff;
|
||||||
|
background: transparent;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.shop {
|
||||||
|
width: 10%;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
background: url("@/static/shop.png") no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<!-- uni 中不能使用 vue component 所以用if判断每个组件 -->
|
<!-- uni 中不能使用 vue component 所以用if判断每个组件 -->
|
||||||
<div v-for="(item,index) in pageData.list" :key="index">
|
<div v-for="(item,index) in pageData.list" :key="index">
|
||||||
<!-- 搜索栏,如果在楼层装修顶部则会自动浮动,否则不浮动 -->
|
<!-- 搜索栏,如果在楼层装修顶部则会自动浮动,否则不浮动 -->
|
||||||
<u-navbar class="navbar" v-if="item.type == 'search'" :is-back="false" :is-fixed="index ===1 ? false : true">
|
<div class="navbar" v-if="item.type == 'search'" :is-back="false" :is-fixed="false">
|
||||||
<search style="width:100%" :res="item.options" />
|
<search style="width:100%" :res="item.options" />
|
||||||
<!-- #ifndef H5 -->
|
<!-- #ifndef H5 -->
|
||||||
<!-- 扫码功能 不兼容h5 详情文档: https://uniapp.dcloud.io/api/system/barcode?id=scancode -->
|
<!-- 扫码功能 不兼容h5 详情文档: https://uniapp.dcloud.io/api/system/barcode?id=scancode -->
|
||||||
@ -11,21 +11,24 @@
|
|||||||
<u-icon name="scan" @click="scan()" color="#666" size="50"></u-icon>
|
<u-icon name="scan" @click="scan()" color="#666" size="50"></u-icon>
|
||||||
</div>
|
</div>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
</u-navbar>
|
</div>
|
||||||
<carousel v-if="item.type == 'carousel'" :res="item.options" />
|
<carousel v-if="item.type == 'carousel'" :res="item.options" />
|
||||||
<titleLayout v-if="item.type == 'title'" :res="item.options" />
|
<titleLayout v-if="item.type == 'title'" :res="item.options" />
|
||||||
<leftOneRightTwo v-if="item.type == 'leftOneRightTwo'" :res="item.options" />
|
<leftOneRightTwo v-if="item.type == 'leftOneRightTwo'" :res="item.options" />
|
||||||
<leftTwoRightOne v-if="item.type == 'leftTwoRightOne'" :res="item.options" />
|
<leftTwoRightOne v-if="item.type == 'leftTwoRightOne'" :res="item.options" />
|
||||||
<topOneBottomTwo v-if="item.type == 'topOneBottomTwo'" :res="item.options" />
|
<topOneBottomTwo v-if="item.type == 'topOneBottomTwo'" :res="item.options" />
|
||||||
<topTwoBottomOne v-if="item.type == 'topTwoBottomOne'" :res="item.options" />
|
<topTwoBottomOne v-if="item.type == 'topTwoBottomOne'" :res="item.options" />
|
||||||
<flexThree v-if="item.type == 'flexThree'" :res="item.options" />
|
|
||||||
|
|
||||||
|
<flexThree v-if="item.type == 'flexThree'" :res="item.options" />
|
||||||
<flexFive v-if="item.type == 'flexFive'" :res="item.options" />
|
<flexFive v-if="item.type == 'flexFive'" :res="item.options" />
|
||||||
<flexFour v-if="item.type == 'flexFour'" :res="item.options" />
|
<flexFour v-if="item.type == 'flexFour'" :res="item.options" />
|
||||||
<flexTwo v-if="item.type == 'flexTwo'" :res="item.options" />
|
<flexTwo v-if="item.type == 'flexTwo'" :res="item.options" />
|
||||||
<textPicture v-if="item.type == 'textPicture'" :res="item.options" />
|
<textPicture v-if="item.type == 'textPicture'" :res="item.options" />
|
||||||
<menuLayout v-if="item.type == 'menu'" :res="item.options" />
|
<menuLayout v-if="item.type == 'menu'" :res="item.options" />
|
||||||
<flexOne v-if="item.type == 'flexOne'" :res="item.options" />
|
<flexOne v-if="item.type == 'flexOne'" :res="item.options" />
|
||||||
|
<activity v-if="item.type == 'activity'" :res="item.options" />
|
||||||
|
<Talent v-if="item.type == 'talent'" :res="item.options" :model="item" />
|
||||||
<goods v-if="item.type == 'goods'" :res="item.options" />
|
<goods v-if="item.type == 'goods'" :res="item.options" />
|
||||||
|
|
||||||
<group v-if="item.type == 'group'" :res="item.options" />
|
<group v-if="item.type == 'group'" :res="item.options" />
|
||||||
@ -56,8 +59,10 @@ import tpl_menu from "@/pages/tabbar/home/template/tpl_menu"; //五列菜单模
|
|||||||
import tpl_search from "@/pages/tabbar/home/template/tpl_search"; //搜索栏
|
import tpl_search from "@/pages/tabbar/home/template/tpl_search"; //搜索栏
|
||||||
import tpl_group from "@/pages/tabbar/home/template/tpl_group"; //
|
import tpl_group from "@/pages/tabbar/home/template/tpl_group"; //
|
||||||
import tpl_goods from "@/pages/tabbar/home/template/tpl_goods"; //商品分类以及分类中的商品
|
import tpl_goods from "@/pages/tabbar/home/template/tpl_goods"; //商品分类以及分类中的商品
|
||||||
|
import Talent from "@/pages/tabbar/home/template/Talent"; //达人店
|
||||||
|
import tpl_activity from "@/pages/tabbar/home/template/tpl_activity"; //活动
|
||||||
// 结束引用组件
|
// 结束引用组件
|
||||||
import { getFloorData } from "@/api/home"; //获取楼层装修接口
|
import { getFloorData ,getFloorgetBendi} from "@/api/home"; //获取楼层装修接口
|
||||||
import permision from "@/js_sdk/wa-permission/permission.js"; //权限工具类
|
import permision from "@/js_sdk/wa-permission/permission.js"; //权限工具类
|
||||||
import config from "@/config/config";
|
import config from "@/config/config";
|
||||||
// TODO 后续开发
|
// TODO 后续开发
|
||||||
@ -90,11 +95,23 @@ export default {
|
|||||||
flexOne: tpl_flex_one,
|
flexOne: tpl_flex_one,
|
||||||
goods: tpl_goods,
|
goods: tpl_goods,
|
||||||
group: tpl_group,
|
group: tpl_group,
|
||||||
|
Talent,
|
||||||
|
activity: tpl_activity,
|
||||||
// spike: tpl_spike,
|
// spike: tpl_spike,
|
||||||
// joinGroup: tpl_join_group,
|
// joinGroup: tpl_join_group,
|
||||||
// integral: tpl_integral,
|
// integral: tpl_integral,
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
ste: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
ste(val) {
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init();
|
this.init();
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
@ -102,18 +119,32 @@ export default {
|
|||||||
uni.showShareMenu({ withShareTicket: true });
|
uni.showShareMenu({ withShareTicket: true });
|
||||||
// #endif
|
// #endif
|
||||||
},
|
},
|
||||||
|
// provide() {
|
||||||
|
// return {
|
||||||
|
// ste: this.ste,
|
||||||
|
// };
|
||||||
|
// },
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* 实例化首页数据楼层
|
* 实例化首页数据楼层
|
||||||
*/
|
*/
|
||||||
init() {
|
init() {
|
||||||
|
uni.setStorageSync('ste', this.ste); // 存储 ste 的值
|
||||||
this.pageData = "";
|
this.pageData = "";
|
||||||
getFloorData().then((res) => {
|
if (this.ste == 1) {
|
||||||
|
getFloorData().then((res) => {
|
||||||
if (res.data.success) {
|
if (res.data.success) {
|
||||||
this.pageData = JSON.parse(res.data.result.pageData);
|
this.pageData = JSON.parse(res.data.result.pageData);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}else{
|
||||||
|
getFloorgetBendi().then((res) => {
|
||||||
|
if (res.data.success) {
|
||||||
|
this.pageData = JSON.parse(res.data.result.pageData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,7 +159,6 @@ export default {
|
|||||||
uni.scanCode({
|
uni.scanCode({
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
let path = encodeURIComponent(res.result);
|
let path = encodeURIComponent(res.result);
|
||||||
|
|
||||||
// WX_CODE 为小程序码
|
// WX_CODE 为小程序码
|
||||||
if (res.scanType == "WX_CODE") {
|
if (res.scanType == "WX_CODE") {
|
||||||
console.log(res)
|
console.log(res)
|
||||||
@ -208,16 +238,26 @@ export default {
|
|||||||
this.seacnCode();
|
this.seacnCode();
|
||||||
// #endif
|
// #endif
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.wrapper{
|
.wrapper{
|
||||||
height: auto;
|
height: 100%;
|
||||||
overflow-y: auto; /* 当内容超出时显示垂直滚动条 */
|
}
|
||||||
|
.navbar{
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background:white;
|
||||||
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
.navbar-right {
|
.navbar-right {
|
||||||
padding: 0 16rpx 0 0;
|
// padding: 0 16rpx 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,3 +1,289 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>im</div>
|
<div style="height: 100%">
|
||||||
</template>
|
<div class="jolkp">
|
||||||
|
<div class="fan" :style="{ marginRight: statue == 0 ? '56%' : '70%' }">
|
||||||
|
<span @click="hui(0)">消息</span>
|
||||||
|
</div>
|
||||||
|
<!-- <TUIContact v-else-if="statue==1" :stu="2" /> -->
|
||||||
|
<div @click="hui(1)" class="jolkp_h" v-if="statue == 0"></div>
|
||||||
|
<div @click="fnkiopl" class="jolkp_l"></div>
|
||||||
|
<!-- 弹出框 -->
|
||||||
|
<div v-if="isPopupVisible" class="popup">
|
||||||
|
<ul>
|
||||||
|
<li @click="handleAddFriend">添加好友/群聊</li>
|
||||||
|
<li @click="handleMenu()">发起群聊</li>
|
||||||
|
<li>扫一扫</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="three">
|
||||||
|
<div class="con">
|
||||||
|
<div class="three_div1"></div>
|
||||||
|
<div class="title">点赞</div>
|
||||||
|
</div>
|
||||||
|
<div class="con">
|
||||||
|
<div class="three_div2"></div>
|
||||||
|
<div class="title">关注</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="con">
|
||||||
|
<div class="three_div3"></div>
|
||||||
|
<div class="title">评论</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 搜索添加 -->
|
||||||
|
<TUIContactsea v-if="statue == 2" />
|
||||||
|
<!-- 联系人 -->
|
||||||
|
<TUIContact v-else-if="statue == 1" style="height: 100%;" />
|
||||||
|
<SelectFriend v-else-if="statue == 3" @con="confn" />
|
||||||
|
<SelectFriendqlioa v-else-if="statue == 4" @concen="concen" />
|
||||||
|
<!-- 会话 -->
|
||||||
|
<TUIConversation style="height: 100%;" v-else />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 导入组件
|
||||||
|
import TUIConversation from "@/TUIKit/components/TUIConversation/index";
|
||||||
|
import TUIContact from "@/TUIKit/components/TUIContact/index";
|
||||||
|
import TUIContactsea from "@/TUIKit/components/TUIContact/indexsea";
|
||||||
|
import { TUILogin } from "@tencentcloud/tui-core";
|
||||||
|
import ContactSearch from "@/TUIKit/components/TUIContact/contact-search/index.vue";
|
||||||
|
import { TUIChatKit } from "@/TUIKit";
|
||||||
|
import SelectFriend from "@/TUIKit/components/TUIContact/select-friend/index.vue";
|
||||||
|
import SelectFriendqlioa from "@/TUIKit/components/TUIGroup/index.vue";
|
||||||
|
import TUICore, { ExtensionInfo, TUIConstants } from "@tencentcloud/tui-core";
|
||||||
|
import storage from "@/utils/storage.js";
|
||||||
|
import { getUserimInfo } from "@/api/members";
|
||||||
|
TUIChatKit.init();
|
||||||
|
let vueVersion = 2;
|
||||||
|
// vueVersion = 3;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 注册组件
|
||||||
|
components: {
|
||||||
|
TUIConversation,
|
||||||
|
TUIContact,
|
||||||
|
TUIContactsea,
|
||||||
|
ContactSearch,
|
||||||
|
SelectFriend,
|
||||||
|
SelectFriendqlioa,
|
||||||
|
TUIChatKit,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
statue: 0, //1联系人 2添加好友/群聊 0对话记录 3建群 4群名称
|
||||||
|
isPopupVisible: false, // 控制弹出框的显示与隐藏
|
||||||
|
isq: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {},
|
||||||
|
onShow() {
|
||||||
|
// 每次进入页面时调用的方法
|
||||||
|
//获取用户信息
|
||||||
|
getUserimInfo()
|
||||||
|
.then(({ data }) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
const par = data.result;
|
||||||
|
TUILogin.login({
|
||||||
|
SDKAppID: par.sdkAppId,
|
||||||
|
userID: par.userID,
|
||||||
|
userSig: par.userSig,
|
||||||
|
useUploadPlugin: true, // If you need to send rich media messages, please set to true.
|
||||||
|
framework: `vue${vueVersion}`, // framework used vue2 / vue3
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 接口返回非 200 状态码,跳转登录页面
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/passport/login",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// 请求失败,跳转登录页面
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/passport/login",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
methods: {
|
||||||
|
//完成跳转群名
|
||||||
|
confn() {
|
||||||
|
this.statue = 4;
|
||||||
|
},
|
||||||
|
concen() {
|
||||||
|
this.statue = 0;
|
||||||
|
this.isPopupVisible = false;
|
||||||
|
},
|
||||||
|
hui(index) {
|
||||||
|
this.statue = index;
|
||||||
|
},
|
||||||
|
fnkiopl() {
|
||||||
|
this.isPopupVisible = !this.isPopupVisible;
|
||||||
|
},
|
||||||
|
handleMenu() {
|
||||||
|
const fn = [
|
||||||
|
...TUICore.getExtensionList(
|
||||||
|
TUIConstants.TUISearch.EXTENSION.SEARCH_MORE.EXT_ID
|
||||||
|
),
|
||||||
|
];
|
||||||
|
const item = fn[1];
|
||||||
|
const {
|
||||||
|
listener = {
|
||||||
|
onClicked: () => {},
|
||||||
|
},
|
||||||
|
} = item;
|
||||||
|
listener?.onClicked?.(item);
|
||||||
|
this.statue = 3;
|
||||||
|
},
|
||||||
|
// 处理添加好友/群聊点击事件
|
||||||
|
handleAddFriend() {
|
||||||
|
this.statue = 2;
|
||||||
|
this.isPopupVisible = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// // 打开会话列表
|
||||||
|
// openConversationList() {
|
||||||
|
// uni.navigateTo({
|
||||||
|
// url: '/TUIKit/components/TUIConversation/index'
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// // 打开联系人
|
||||||
|
// openContact() {
|
||||||
|
// uni.navigateTo({
|
||||||
|
// url: '/TUIKit/components/TUIContact/index'
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
uni-page-body,
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
page {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.jolkp {
|
||||||
|
height: 66px;
|
||||||
|
display: flex;
|
||||||
|
font-size: 15px;
|
||||||
|
justify-content: end;
|
||||||
|
/* 设置背景图 */
|
||||||
|
background-image: url("@/static/im/Rectangle.png");
|
||||||
|
/* 让背景图覆盖整个元素 */
|
||||||
|
background-size: cover;
|
||||||
|
/* 背景图不重复 */
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jolkp_l {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
background-image: url("@/static/im/Frame.png");
|
||||||
|
/* 让背景图覆盖整个元素 */
|
||||||
|
background-size: cover;
|
||||||
|
/* 背景图不重复 */
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
margin-top: 35px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jolkp_h {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
background-image: url("@/static/im/user.png");
|
||||||
|
/* 让背景图覆盖整个元素 */
|
||||||
|
background-size: cover;
|
||||||
|
/* 背景图不重复 */
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
margin-top: 35px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup {
|
||||||
|
position: absolute;
|
||||||
|
top: 65px;
|
||||||
|
/* 调整弹出框的位置 */
|
||||||
|
right: 5px;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup li {
|
||||||
|
padding: 10px 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup li:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fan {
|
||||||
|
width: 10%;
|
||||||
|
height: "100%";
|
||||||
|
font-size: 18px;
|
||||||
|
display: flex;
|
||||||
|
align-items: end;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.three {
|
||||||
|
width: 100%;
|
||||||
|
height: 10%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
background: rgb(255, 255, 255);
|
||||||
|
}
|
||||||
|
.con{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.three_div1 {
|
||||||
|
height: 3rem;
|
||||||
|
width: 40%;
|
||||||
|
background-image: url("@/static/im/kf.png");
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.three_div2 {
|
||||||
|
width: 40%;
|
||||||
|
height: 3rem;
|
||||||
|
background-image: url("@/static/im/hy.png");
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.three_div3 {
|
||||||
|
height: 3rem;
|
||||||
|
background-image: url("@/static/im/da.png");
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|||||||
BIN
static/shop.png
Normal file
BIN
static/shop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
static/tabbar/bei.png
Normal file
BIN
static/tabbar/bei.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 496 KiB |
BIN
static/tabbar/shop.png
Normal file
BIN
static/tabbar/shop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
static/tanback.png
Normal file
BIN
static/tanback.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
Loading…
x
Reference in New Issue
Block a user