2026-07-08 16:00:30 +08:00

473 lines
12 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>
<el-dialog
:title="title"
:visible.sync="dialogVisible"
:width="responsiveWidth"
:center="center"
:top="responsiveTop"
@close="handleClose"
custom-class="product-consult-dialog"
:modal-append-to-body="false"
:close-on-click-modal="false"
>
<!-- 头部提示 -->
<div class="dialog-tit">
<div class="pc-tip">
<i class="el-icon-warning-outline"></i>
<span>如需购买资源请移步PC端哦~</span>
</div>
<div class="url_box">
<div class="url-container" @mouseenter="showTooltip = true" @mouseleave="showTooltip = false">
官网地址:
<span class="url" @click="copyUrl" :class="{ 'copied': isCopied }">
https://www.opencomputing.cn
</span>
<div v-if="showTooltip && !isCopied" class="tooltip" :class="{ 'tooltip-visible': showTooltip }">
点击复制链接
</div>
</div>
<div class="url_btn">
<span class="copy-hint">{{ isCopied ? '✓ 已复制' : '点击复制' }}</span>
</div>
</div>
</div>
<!-- 表单区域 -->
<el-form ref="ruleForm" :rules="rules" label-position="top" :model="formData" :disabled="loading">
<el-form-item label="需求描述">
<el-input
:autosize="{ minRows: 6, maxRows: 6 }"
type="textarea"
v-model="formData.content"
placeholder="请输入您的具体需求"
resize="none"
@focus="handleInputFocus"
></el-input>
</el-form-item>
<el-form-item label="客户类型">
<el-radio v-model="formData.custom_type" label="1">企业</el-radio>
<el-radio v-model="formData.custom_type" label="0">个人</el-radio>
</el-form-item>
<el-form-item prop="name" label="联系人姓名">
<el-input
v-model="formData.name"
placeholder="请输入联系人姓名"
maxlength="20"
@focus="handleInputFocus"
></el-input>
</el-form-item>
<el-form-item prop="phone" label="联系人手机">
<el-input
v-model="formData.phone"
placeholder="请输入联系人手机"
type="tel"
maxlength="11"
@focus="handleInputFocus"
></el-input>
</el-form-item>
<el-form-item v-show="formData.custom_type === '1'" label="公司名称">
<el-input
v-model="formData.company"
placeholder="请输入公司名称"
maxlength="50"
@focus="handleInputFocus"
></el-input>
</el-form-item>
<el-form-item label="联系人邮箱">
<el-input
v-model="formData.email"
placeholder="请输入联系人邮箱"
type="email"
maxlength="50"
@focus="handleInputFocus"
></el-input>
</el-form-item>
</el-form>
<!-- 协议勾选 -->
<el-checkbox v-model="formData.checked" class="agreement-checkbox">
<div class="agreement-text">
<p class="check-tit">
勾选表示您同意<span v-if="platformName">{{ platformName }}</span>及其授权的合作伙伴通过您填写的联系方式联系您
</p>
<p class="check-tit">
且数据仅用于与您沟通当您注销平台账号后您的数据会被销毁
</p>
</div>
</el-checkbox>
<!-- 二维码区域可选 -->
<div v-if="qrCode" class="qrcode-section">
<img :src="qrCode" alt="客服二维码" />
<span>扫码联系客服</span>
</div>
<!-- 底部按钮 -->
<span slot="footer" class="dialog-footer">
<el-button type="primary" :loading="loading" @click="handleSubmit">
</el-button>
</span>
</el-dialog>
</template>
<script>
import { reqProductConsult } from '@/api/H5/index.js'
export default {
name: 'ProductConsultDialog',
props: {
// 控制弹窗显示
visible: {
type: Boolean,
default: false
},
// 弹窗标题
title: {
type: String,
default: '产品咨询'
},
// 弹窗宽度(使用响应式默认值)
width: {
type: String,
default: ''
},
// 弹窗位置
top: {
type: String,
default: ''
},
// 是否居中
center: {
type: Boolean,
default: true
},
// 平台名称(用于协议文本)
platformName: {
type: String,
default: ''
},
// 客服二维码
qrCode: {
type: String,
default: ''
},
// 提交接口函数(可自定义)
submitApi: {
type: Function,
default: null
},
// 当前页面URL
currentUrl: {
type: String,
default: ''
},
// 默认表单数据
defaultFormData: {
type: Object,
default: () => ({
content: '',
custom_type: '1',
name: '',
phone: '',
company: '',
email: '',
checked: false
})
}
},
data() {
// 手机号验证规则
const validatePhone = (rule, value, callback) => {
if (!value) {
callback(new Error('请输入手机号'))
} else if (!/^1[3-9]\d{9}$/.test(value)) {
callback(new Error('请输入正确的手机号码'))
} else {
callback()
}
}
return {
loading: false,
rules: {
name: [
{ required: true, message: '请输入姓名', trigger: 'blur' },
{ max: 20, message: '姓名不能超过20个字符', trigger: 'blur' }
],
phone: [
{ required: true, validator: validatePhone, trigger: 'blur' }
],
email: [
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
],
content: [
{ required: true, message: '请输入需求描述', trigger: 'blur' },
{ min: 10, message: '需求描述至少10个字符', trigger: 'blur' },
{ max: 500, message: '需求描述不能超过500个字符', trigger: 'blur' }
]
},
formData: { ...this.defaultFormData },
showTooltip: false,
isCopied: false,
copyTimer: null,
originalOverflow: '' // 保存原始overflow样式
}
},
computed: {
// 控制弹窗显示的计算属性
dialogVisible: {
get() {
return this.visible
},
set(value) {
this.$emit('update:visible', value)
}
},
// 响应式宽度计算
responsiveWidth() {
if (this.width) return this.width
const screenWidth = window.innerWidth || document.documentElement.clientWidth
if (screenWidth <= 750) {
return '90%' // 移动端
} else if (screenWidth <= 1200) {
return '70%' // 平板
} else {
return '40rem' // 桌面端
}
},
// 响应式位置计算
responsiveTop() {
if (this.top) return this.top
const screenHeight = window.innerHeight || document.documentElement.clientHeight
if (screenHeight <= 667) {
return '10vh' // 小屏幕
} else {
return '15vh' // 正常屏幕
}
}
},
watch: {
// 监听visible变化
visible: {
immediate: true,
handler(newVal) {
if (newVal) {
this.resetForm()
// 弹窗打开时禁止背景滚动
this.disableBodyScroll()
} else {
// 弹窗关闭时恢复背景滚动
this.enableBodyScroll()
}
}
},
// 监听defaultFormData变化
defaultFormData: {
deep: true,
handler(newVal) {
this.formData = { ...newVal }
}
}
},
methods: {
// 禁止背景滚动
disableBodyScroll() {
const body = document.body
this.originalOverflow = body.style.overflow
body.style.overflow = 'hidden'
},
// 恢复背景滚动
enableBodyScroll() {
const body = document.body
body.style.overflow = this.originalOverflow || ''
},
// 处理输入框获得焦点(移动端优化)
handleInputFocus() {
// 移动端优化:确保输入框可见
if (window.innerWidth <= 750) {
setTimeout(() => {
const activeElement = document.activeElement
if (activeElement && activeElement.scrollIntoView) {
activeElement.scrollIntoView({
behavior: 'smooth',
block: 'center'
})
}
}, 300)
}
},
// 复制URL到剪贴板
async copyUrl() {
const urlToCopy = 'https://www.opencomputing.cn'
try {
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(urlToCopy)
} else {
// 使用document.execCommand作为备选
const textArea = document.createElement('textarea')
textArea.value = urlToCopy
textArea.style.position = 'fixed'
textArea.style.left = '-999999px'
textArea.style.top = '-999999px'
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
}
this.handleCopySuccess()
} catch (err) {
console.error('复制失败:', err)
this.$message.error('复制失败,请手动复制链接')
}
},
// 处理复制成功
handleCopySuccess() {
this.$message.success('链接已复制到剪贴板')
this.isCopied = true
// 清除之前的定时器
if (this.copyTimer) {
clearTimeout(this.copyTimer)
}
// 3秒后重置复制状态
this.copyTimer = setTimeout(() => {
this.isCopied = false
}, 3000)
this.showTooltip = false
},
// 重置表单
resetForm() {
this.formData = {
content: '',
custom_type: '1',
name: '',
phone: '',
company: '',
email: '',
checked: false,
...this.defaultFormData
}
// 清除表单验证
if (this.$refs.ruleForm) {
this.$refs.ruleForm.clearValidate()
}
},
// 关闭弹窗
handleClose() {
this.dialogVisible = false
this.$emit('close')
},
// 提交表单
handleSubmit() {
// 验证是否勾选协议
if (!this.formData.checked) {
this.$message.warning('请勾选同意协议后再提交!')
return
}
// 验证表单
this.$refs.ruleForm.validate(valid => {
if (valid) {
this.submitForm()
} else {
this.$message.error('请完善表单信息')
}
})
},
// 提交表单数据
async submitForm() {
this.loading = true
try {
const submitData = {
...this.formData,
url_link: this.currentUrl || window.location.href,
submit_time: new Date().toISOString()
}
let response
// 如果有自定义提交函数,使用自定义函数
if (this.submitApi) {
response = await this.submitApi(submitData)
} else {
// 否则使用默认的reqProductConsult
response = await reqProductConsult(submitData)
}
this.handleResponse(response)
} catch (error) {
console.error('提交咨询失败:', error)
this.$message.error('提交失败,请稍后再试!')
} finally {
this.loading = false
}
},
handleResponse(response) {
// 根据你的API响应结构status为true表示成功
if (response && response.status === 'true') {
this.handleClose()
this.$message.success('提交成功')
} else {
this.$message.error('提交失败,请稍后再试!')
}
}
},
beforeDestroy() {
// 清除定时器
if (this.copyTimer) {
clearTimeout(this.copyTimer)
}
// 恢复背景滚动
this.enableBodyScroll()
}
}
</script>
<style scoped lang="less">
@import url(../../less/dialog/index.less);
</style>