xlqx/app/components/ContactFloatingButton.vue

244 lines
7.0 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.

<!-- components/ContactFloatingButton.vue -->
<template>
<div class="fixed right-2 lg:right-6 top-1/2 transform -translate-y-1/2 z-50 flex items-center">
<!-- PC端弹窗 -->
<UPopover
v-if="isDesktop"
arrow
mode="click"
:popper="{ placement: 'left-start' }"
:content="{
align: 'center',
side: 'left',
sideOffset: 6
}"
>
<UButton
class="bg-primary hover:bg-primary-600 text-white px-4 py-3 rounded-l-lg shadow-lg transition-all duration-300"
color="neutral"
label="商家加盟"
variant="subtle"/>
<template #content>
<div class="w-75 lg:w-100 h-120 lg:h-160 p-4 bg-white rounded-lg shadow-xl overflow-y-auto">
<img src="https://api.ccttiot.com/image-1762158125769.png" alt="">
<h3 class="text-lg font-semibold mb-1 text-gray-800">商家加盟申请</h3>
<UForm
ref="formRef"
:state="formState"
class="space-y-4 w-full"
@submit="onSubmit"
>
<UFormGroup label="姓名" name="name" required>
<UInput
v-model="formState.name"
placeholder="请输入您的姓名"
size="md"
class="w-full mb-2"
/>
</UFormGroup>
<UFormGroup label="手机号" name="mobile" required>
<UInput
v-model="formState.mobile"
type="tel"
placeholder="请输入您的手机号"
size="md"
class="w-full mb-2"
/>
</UFormGroup>
<UFormGroup label="城市" name="city" required>
<UInput
v-model="formState.city"
placeholder="请输入您的意向合作城市"
size="md"
class="w-full mb-2"
/>
</UFormGroup>
<UFormGroup label="是否有设备" name="hasDevice">
<div class="flex gap-4">
<label class="flex items-center gap-2 cursor-pointer">
<input
type="radio"
v-model="formState.hasDevice"
:value="1"
class="w-4 h-4 text-primary"
/>
<span class="text-sm">有设备</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input
type="radio"
v-model="formState.hasDevice"
:value="0"
class="w-4 h-4 text-primary"
/>
<span class="text-sm">无设备</span>
</label>
</div>
</UFormGroup>
<UFormGroup label="留言内容" name="content" required>
<UTextarea
v-model="formState.content"
placeholder="请输入您想要了解的信息"
:rows="3"
size="md"
class="w-full mt-1"
/>
</UFormGroup>
<div class="flex gap-2 pt-2 ">
<UButton
type="submit"
:loading="isSubmitting"
:disabled="isSubmitting"
class="flex-1 bg-primary hover:bg-primary-600 justify-center items-center"
size="md"
>
{{ isSubmitting ? '提交中...' : '马上加盟 立即挣钱' }}
</UButton>
<UButton
type="button"
variant="outline"
@click="resetForm"
size="md"
>
重置
</UButton>
</div>
</UForm>
<img class="mt-2" src="https://api.ccttiot.com/image-1762158608753.png" alt="">
<img src="https://api.ccttiot.com/image-1762159041739.png" alt="">
<img src="https://api.ccttiot.com/image-1762159105486.png" alt="">
<img src="https://api.ccttiot.com/image-1762158699504.png" alt="">
</div>
</template>
</UPopover>
<!-- 移动端:跳转链接 -->
<NuxtLink
v-else-if="isMounted"
to="/merchantFranchise"
class="block"
>
<UButton
class="bg-primary hover:bg-primary-600 text-white px-4 py-3 rounded-l-lg shadow-lg transition-all duration-300"
color="neutral"
label="商家加盟"
variant="subtle"/>
</NuxtLink>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import { submitMchApply, type MchApplyParams } from '~/config/api'
const toast = useToast()
const formRef = ref()
const isSubmitting = ref(false)
const windowWidth = ref(0)
const isMounted = ref(false)
// 检测是否为桌面端lg断点1024px
const isDesktop = computed(() => isMounted.value && windowWidth.value >= 1024)
// 监听窗口大小变化
const updateWindowWidth = () => {
windowWidth.value = window.innerWidth
}
onMounted(() => {
isMounted.value = true
updateWindowWidth()
window.addEventListener('resize', updateWindowWidth)
})
onUnmounted(() => {
if (process.client) {
window.removeEventListener('resize', updateWindowWidth)
}
})
const formState = reactive<MchApplyParams>({
name: '',
mobile: '',
content: '',
hasDevice: 0,
city: ''
})
const showToast = (title: string, type: 'success' | 'error' = 'success') => {
toast.add({
title,
color: type === 'success' ? 'success' : 'error',
icon: type === 'success' ? 'i-heroicons-check-circle' : 'i-heroicons-exclamation-circle',
})
}
const resetForm = () => {
formState.name = ''
formState.mobile = ''
formState.content = ''
formState.hasDevice = 0
formState.city = ''
formRef.value?.clear()
}
const validateForm = (): boolean => {
if (!formState.name.trim()) {
showToast('请输入姓名', 'error')
return false
}
if (!formState.mobile.trim()) {
showToast('请输入手机号', 'error')
return false
}
// 简单的手机号验证
const mobileRegex = /^1[3-9]\d{9}$/
if (!mobileRegex.test(formState.mobile)) {
showToast('请输入正确的手机号', 'error')
return false
}
if (!formState.city.trim()) {
showToast('请输入所在城市', 'error')
return false
}
if (!formState.content.trim()) {
showToast('请输入留言内容', 'error')
return false
}
return true
}
const onSubmit = async () => {
if (!validateForm()) {
return
}
isSubmitting.value = true
try {
const response = await submitMchApply(formState)
if (response.code === 200) {
showToast('申请提交成功!我们会尽快与您联系。', 'success')
resetForm()
} else {
showToast(response.msg || '提交失败,请稍后重试', 'error')
}
} catch (error) {
console.error('提交申请失败:', error)
showToast('提交失败,请检查网络连接后重试', 'error')
} finally {
isSubmitting.value = false
}
}
</script>