Compare commits
No commits in common. "49fbeead9a5af9e049bf4407ca926c51e9f91231" and "6361aa9ac323b3bd2464abcfa5f45830e595d86a" have entirely different histories.
49fbeead9a
...
6361aa9ac3
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% ;
|
// width: 100% !important;
|
||||||
// height: 100% ;
|
// height: 100% !important;
|
||||||
// overflow: hidden;
|
// overflow: hidden;
|
||||||
// }
|
// }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,60 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
@ -1,314 +0,0 @@
|
|||||||
<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>
|
|
||||||
@ -1,243 +0,0 @@
|
|||||||
<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>
|
|
||||||
@ -1,285 +0,0 @@
|
|||||||
<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>
|
|
||||||
@ -1,430 +0,0 @@
|
|||||||
<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>
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
<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>
|
|
||||||
@ -1,139 +0,0 @@
|
|||||||
<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,17 +12,6 @@ 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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,17 +50,7 @@ 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/store',
|
url: '/store',
|
||||||
method: Method.GET,
|
method: Method.GET,
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -284,11 +284,9 @@ 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: "AOHBZ-VCEL3-XX73N-O623U-FMTP6-ASBTD", //在腾讯的中申请web端key
|
aMapKey: "d649892b3937a5ad20b76dacb2bcb5bd", //在高德中申请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__1F0975C",
|
"appid" : "__UNI__6DB512D",
|
||||||
"description" : "admin",
|
"description" : "",
|
||||||
"versionName" : "4.0.0",
|
"versionName" : "4.0.0",
|
||||||
"versionCode" : 4000049,
|
"versionCode" : 4000049,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
|
|||||||
2012
pages.json
2012
pages.json
File diff suppressed because it is too large
Load Diff
@ -541,15 +541,13 @@ 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.navigateTo({
|
uni.switchTab({
|
||||||
url: "/pages/tabbar/cart/cartList",
|
url: "/pages/tabbar/cart/cartList",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -63,7 +63,6 @@ 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,22 +7,21 @@
|
|||||||
<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="square" width="100" height="100" :src="item.storeLogo">
|
<u-image shape="circle" 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">
|
||||||
<div> {{item.storeName}}</div>
|
{{item.storeName}}
|
||||||
<div class="typeof" >{{item.selfOperated?'自营':'非自营'}}</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="goods-num">
|
<div class="goods-num">
|
||||||
商品 {{item.goodsNum}} <span class="line">|</span> <span class="store-collection">收藏 {{item.collectionNum}}</span>
|
商品 {{item.goodsNum}}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex store-distance">
|
<div class="flex store-distance">
|
||||||
<div>
|
<div>
|
||||||
<template v-for="i in 5">
|
<span class="store-score">{{item.serviceScore | unitPrice}}</span>
|
||||||
<u-icon :name="i <= item.serviceScore ? 'star-fill' : 'star'" color="#FF0000" size="30"></u-icon>
|
<span class="line">|</span>
|
||||||
</template>
|
<span class="store-collection">收藏 {{item.collectionNum}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -114,19 +113,11 @@ 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: 35rpx;
|
font-size: 30rpx;
|
||||||
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,23 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<!-- 楼层装修组件 -->
|
<!-- 楼层装修组件 -->
|
||||||
<u-navbar class="navbar" :is-back="false" :is-fixed="false">
|
<tpl ref="tpl" />
|
||||||
<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>
|
||||||
@ -29,55 +13,21 @@ export default {
|
|||||||
background: {
|
background: {
|
||||||
backgroundColor: "#fff",
|
backgroundColor: "#fff",
|
||||||
},
|
},
|
||||||
list1: [
|
|
||||||
{
|
|
||||||
name: "本地生活",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "商城",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
currentTabIndex: 0,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
components: {
|
|
||||||
tpl,
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
click(item) {
|
|
||||||
this.currentTabIndex = this.list1.indexOf(item);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
onPullDownRefresh() {
|
onPullDownRefresh() {
|
||||||
this.$refs.tpl.init();
|
this.$refs.tpl.init();
|
||||||
|
|
||||||
uni.stopPullDownRefresh();
|
uni.stopPullDownRefresh();
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
tpl,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.tab-container {
|
.wrapper{
|
||||||
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>
|
||||||
|
|||||||
@ -1,103 +0,0 @@
|
|||||||
<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>
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
<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,261 +1,38 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<div class="addres" @click="showPicker" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
<div class="search" @click="handleSearch">
|
||||||
{{ cityOrCounty == "" ? "请选择" : cityOrCounty }}
|
<u-icon name="search"></u-icon>
|
||||||
|
{{ 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 {
|
||||||
components: {
|
title:"搜索栏",
|
||||||
"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 {
|
||||||
width: 68%;
|
height: 64rpx;
|
||||||
height: 32px;
|
border-radius: 10rpx;
|
||||||
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;
|
||||||
display: flex;
|
padding: 0 16rpx;
|
||||||
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">
|
||||||
<!-- 搜索栏,如果在楼层装修顶部则会自动浮动,否则不浮动 -->
|
<!-- 搜索栏,如果在楼层装修顶部则会自动浮动,否则不浮动 -->
|
||||||
<div class="navbar" v-if="item.type == 'search'" :is-back="false" :is-fixed="false">
|
<u-navbar class="navbar" v-if="item.type == 'search'" :is-back="false" :is-fixed="index ===1 ? false : true">
|
||||||
<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,24 +11,21 @@
|
|||||||
<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 -->
|
||||||
</div>
|
</u-navbar>
|
||||||
<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" />
|
||||||
@ -59,10 +56,8 @@ 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 ,getFloorgetBendi} from "@/api/home"; //获取楼层装修接口
|
import { getFloorData } 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 后续开发
|
||||||
@ -95,23 +90,11 @@ 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
|
||||||
@ -119,32 +102,18 @@ 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 = "";
|
||||||
if (this.ste == 1) {
|
getFloorData().then((res) => {
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,6 +128,7 @@ 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)
|
||||||
@ -238,26 +208,16 @@ export default {
|
|||||||
this.seacnCode();
|
this.seacnCode();
|
||||||
// #endif
|
// #endif
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.wrapper{
|
.wrapper{
|
||||||
height: 100%;
|
height: auto;
|
||||||
}
|
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,289 +1,3 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="height: 100%">
|
<div>im</div>
|
||||||
<div class="jolkp">
|
</template>
|
||||||
<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
BIN
static/shop.png
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 496 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 97 KiB |
Loading…
x
Reference in New Issue
Block a user