152 lines
3.5 KiB
Vue
152 lines
3.5 KiB
Vue
|
|
<script setup>
|
||
|
|
const route = useRoute()
|
||
|
|
const isOpen = ref(false)
|
||
|
|
const context = ref({ title: '在线客服', source: '' })
|
||
|
|
|
||
|
|
const isInteriorPage = computed(() => route.path !== '/')
|
||
|
|
|
||
|
|
function openFloatingChat() {
|
||
|
|
context.value = {
|
||
|
|
title: '在线客服',
|
||
|
|
source: isInteriorPage.value ? '' : ''
|
||
|
|
}
|
||
|
|
isOpen.value = true
|
||
|
|
}
|
||
|
|
|
||
|
|
function closeChat() {
|
||
|
|
isOpen.value = false
|
||
|
|
}
|
||
|
|
|
||
|
|
function onKeydown(event) {
|
||
|
|
if (event.key === 'Escape' && isOpen.value) closeChat()
|
||
|
|
}
|
||
|
|
|
||
|
|
onMounted(() => window.addEventListener('keydown', onKeydown))
|
||
|
|
onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<Teleport to="body">
|
||
|
|
<Transition name="consult-float">
|
||
|
|
<button
|
||
|
|
v-if="!isOpen"
|
||
|
|
class="consult-float-button"
|
||
|
|
:class="{ 'is-interior': isInteriorPage }"
|
||
|
|
type="button"
|
||
|
|
aria-label="打开在线客服"
|
||
|
|
title="在线客服"
|
||
|
|
@click="openFloatingChat"
|
||
|
|
>
|
||
|
|
<AppIcon name="service" />
|
||
|
|
<span>客服</span>
|
||
|
|
</button>
|
||
|
|
</Transition>
|
||
|
|
|
||
|
|
<Transition name="consult-panel">
|
||
|
|
<div v-if="isOpen" class="consult-chat-shell" :class="{ 'is-interior': isInteriorPage }">
|
||
|
|
<ClientOnly>
|
||
|
|
<ChatOfficialChatWindow :context="context" @close="closeChat" />
|
||
|
|
<template #fallback>
|
||
|
|
<section class="consult-client-loading">
|
||
|
|
<strong>正在打开在线客服...</strong>
|
||
|
|
</section>
|
||
|
|
</template>
|
||
|
|
</ClientOnly>
|
||
|
|
</div>
|
||
|
|
</Transition>
|
||
|
|
</Teleport>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.consult-float-button {
|
||
|
|
position: fixed;
|
||
|
|
z-index: 46;
|
||
|
|
right: clamp(18px, 2.7vw, 12px);
|
||
|
|
bottom: clamp(18px, 25vw, 520px);
|
||
|
|
min-width: 88px;
|
||
|
|
height: 48px;
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
gap: 8px;
|
||
|
|
padding: 0 16px;
|
||
|
|
border: 1px solid rgba(255, 255, 255, 0.28);
|
||
|
|
border-radius: 999px;
|
||
|
|
color: #fff;
|
||
|
|
background: var(--gradient-action);
|
||
|
|
box-shadow: 0 16px 34px rgba(35, 111, 231, 0.26);
|
||
|
|
font-size: 14px;
|
||
|
|
font-weight: 600;
|
||
|
|
transition:
|
||
|
|
transform 0.2s,
|
||
|
|
box-shadow 0.2s,
|
||
|
|
opacity 0.2s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consult-float-button :deep(.app-icon) {
|
||
|
|
width: 20px;
|
||
|
|
height: 20px;
|
||
|
|
}
|
||
|
|
.consult-float-button:hover {
|
||
|
|
transform: translateY(-3px);
|
||
|
|
box-shadow: 0 20px 40px rgba(35, 111, 231, 0.34);
|
||
|
|
}
|
||
|
|
.consult-float-button:active {
|
||
|
|
transform: translateY(1px) scale(0.98);
|
||
|
|
}
|
||
|
|
.consult-chat-shell {
|
||
|
|
position: fixed;
|
||
|
|
z-index: 90;
|
||
|
|
right: clamp(16px, 2.4vw, 36px);
|
||
|
|
bottom: clamp(16px, 2.4vw, 36px);
|
||
|
|
}
|
||
|
|
.consult-chat-shell.is-interior {
|
||
|
|
bottom: calc(clamp(16px, 2.4vw, 36px) + 58px);
|
||
|
|
}
|
||
|
|
.consult-client-loading {
|
||
|
|
width: min(420px, calc(100vw - 32px));
|
||
|
|
height: 180px;
|
||
|
|
display: grid;
|
||
|
|
place-items: center;
|
||
|
|
border-radius: 12px;
|
||
|
|
color: #2f4056;
|
||
|
|
background: #fff;
|
||
|
|
box-shadow: 0 24px 64px rgba(37, 94, 160, 0.18);
|
||
|
|
}
|
||
|
|
.consult-float-enter-active,
|
||
|
|
.consult-float-leave-active,
|
||
|
|
.consult-panel-enter-active,
|
||
|
|
.consult-panel-leave-active {
|
||
|
|
transition:
|
||
|
|
opacity 0.2s,
|
||
|
|
transform 0.24s cubic-bezier(0.22, 1, 0.36, 1);
|
||
|
|
}
|
||
|
|
.consult-float-enter-from,
|
||
|
|
.consult-float-leave-to {
|
||
|
|
opacity: 0;
|
||
|
|
transform: translateY(12px) scale(0.96);
|
||
|
|
}
|
||
|
|
.consult-panel-enter-from,
|
||
|
|
.consult-panel-leave-to {
|
||
|
|
opacity: 0;
|
||
|
|
transform: translateY(16px) scale(0.98);
|
||
|
|
}
|
||
|
|
@media (max-width: 640px) {
|
||
|
|
.consult-float-button {
|
||
|
|
right: 16px;
|
||
|
|
bottom: 16px;
|
||
|
|
min-width: 80px;
|
||
|
|
height: 44px;
|
||
|
|
}
|
||
|
|
.consult-float-button.is-interior {
|
||
|
|
bottom: 70px;
|
||
|
|
}
|
||
|
|
.consult-chat-shell,
|
||
|
|
.consult-chat-shell.is-interior {
|
||
|
|
right: 0;
|
||
|
|
bottom: 0;
|
||
|
|
left: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|