Files
hjc-web/app/components/ConsultDialog.vue
T
gxwebsoft 2b69686795 feat(app): 添加多模板关于我们页面及相关路由和404页面
- 新增404页面,优化未找到页面体验,避免被搜索引擎索引
- 增加文件代理接口,隐藏真实文件服务器地址,支持文件请求代理
- 实现/article、/case、/product及/page动态路由兼容列表与详情展示
- 添加动态CMS页面兼容入口处理旧式路径,统一路由与SEO设置
- 新增模板1、模板7、模板2、模板3关于我们页面,实现多模板支持
- 模板增强支持CMS单页内容加载及SEO信息动态设置
- 配置环境变量及Git忽略文件规则辅助开发和构建环境管理
2026-09-08 12:13:44 +08:00

154 lines
4.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<ClientOnly>
<Teleport to="body">
<Transition name="consult-fade">
<div
v-if="isOpen"
class="fixed inset-0 z-[100] flex items-center justify-center p-4"
@click.self="closeConsult"
>
<!-- 遮罩 -->
<div class="absolute inset-0 bg-black/50 backdrop-blur-sm" />
<!-- 弹窗卡片 -->
<Transition name="consult-pop" appear>
<div
v-if="isOpen"
class="relative bg-white rounded-2xl shadow-2xl w-full max-w-md p-6 sm:p-8 max-h-[90vh] overflow-y-auto"
role="dialog"
aria-modal="true"
aria-label="立即咨询"
>
<!-- 关闭按钮 -->
<button
type="button"
class="absolute top-4 right-4 w-8 h-8 flex items-center justify-center rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors"
aria-label="关闭"
@click="closeConsult"
>
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<!-- 成功态 -->
<div v-if="submitted" class="text-center py-6">
<div class="w-14 h-14 mx-auto mb-4 rounded-full bg-green-100 flex items-center justify-center">
<svg class="w-7 h-7 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
</div>
<h3 class="text-lg font-bold text-gray-900 mb-2">提交成功</h3>
<p class="text-gray-600 text-sm">我们会尽快与您联系请保持电话畅通</p>
</div>
<!-- 表单态 -->
<div v-else>
<div class="mb-6 pr-8">
<h2 class="text-xl font-bold text-gray-900 mb-1">立即咨询</h2>
<p class="text-sm text-gray-500">留下您的联系方式我们将尽快与您联系</p>
</div>
<ContactForm
type="consult"
content-label="需求"
submit-text="立即提交"
:content-required="false"
:preset-content="presetNeed"
:source="source"
accent="#1a6dff"
@success="onSuccess"
/>
</div>
</div>
</Transition>
</div>
</Transition>
</Teleport>
</ClientOnly>
</template>
<script setup lang="ts">
/**
* 全站咨询弹窗
* 通过 useConsult() 控制开关,内部复用共享 ContactForm(与 /contact 功能对齐:
* 手机号段校验、蜜罐、滑块验证码(按后台配置)、频率限制、去重、提交)。
* 挂载在 layouts/default.vue,全站可用。
*/
import ContactForm from './ContactForm.vue'
const { isOpen, presetNeed, source, closeConsult } = useConsult()
const submitted = ref(false)
let successTimer: ReturnType<typeof setTimeout> | null = null
// 打开时锁定背景滚动;关闭时复位成功态
watch(isOpen, (open) => {
if (open) {
submitted.value = false
if (import.meta.client) {
document.body.style.overflow = 'hidden'
}
} else {
if (import.meta.client) {
document.body.style.overflow = ''
}
}
})
// ESC 关闭
function onKeydown(e: KeyboardEvent) {
if (e.key === 'Escape' && isOpen.value) closeConsult()
}
// 提交成功后显示成功态,2.5s 自动关闭
function onSuccess() {
submitted.value = true
successTimer = setTimeout(() => {
if (submitted.value) {
submitted.value = false
closeConsult()
}
}, 2500)
}
onMounted(() => {
window.addEventListener('keydown', onKeydown)
})
onBeforeUnmount(() => {
window.removeEventListener('keydown', onKeydown)
if (successTimer) clearTimeout(successTimer)
if (import.meta.client) {
document.body.style.overflow = ''
}
})
</script>
<style scoped>
.consult-fade-enter-active,
.consult-fade-leave-active {
transition: opacity 0.2s ease;
}
.consult-fade-enter-from,
.consult-fade-leave-to {
opacity: 0;
}
.consult-pop-enter-active {
transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s ease;
}
.consult-pop-leave-active {
transition: transform 0.2s ease, opacity 0.2s ease;
}
.consult-pop-enter-from {
transform: scale(0.95) translateY(10px);
opacity: 0;
}
.consult-pop-leave-to {
transform: scale(0.95);
opacity: 0;
}
</style>