473 lines
12 KiB
Vue
473 lines
12 KiB
Vue
<!-- 产品咨询弹窗公众号 -->
|
||
<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>
|