Files
nl_cms-view/src/views/contact/index.vue
2025-07-29 12:43:09 +08:00

355 lines
14 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>
<div class="min-h-screen bg-gray-50">
<!-- 页面头部 -->
<div class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div class="text-center">
<h1 class="text-4xl font-bold text-gray-900 mb-4">联系我们</h1>
<p class="text-xl text-gray-600 max-w-3xl mx-auto">
我们随时准备为您提供帮助欢迎通过以下方式与我们取得联系
</p>
</div>
</div>
</div>
<!-- 联系方式和表单 -->
<section class="py-16">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12">
<!-- 联系信息 -->
<div class="space-y-8">
<div>
<h2 class="text-2xl font-bold text-gray-900 mb-6">联系信息</h2>
<div class="space-y-6">
<div class="flex items-start">
<div class="flex-shrink-0">
<LocationIcon class="w-6 h-6 text-blue-600 mt-1" />
</div>
<div class="ml-4">
<h3 class="text-lg font-semibold text-gray-900 mb-1">公司地址</h3>
<p class="text-gray-600">深圳市南山区科技园南区深圳湾科技生态园</p>
<p class="text-gray-600">10栋A座5层501室</p>
</div>
</div>
<div class="flex items-start">
<div class="flex-shrink-0">
<PhoneIcon class="w-6 h-6 text-blue-600 mt-1" />
</div>
<div class="ml-4">
<h3 class="text-lg font-semibold text-gray-900 mb-1">联系电话</h3>
<p class="text-gray-600">客服热线400-123-4567</p>
<p class="text-gray-600">技术支持0755-8888-9999</p>
<p class="text-gray-600">周一至周五9:00 - 18:00</p>
<p class="text-gray-600">周六10:00 - 16:00</p>
</div>
</div>
<div class="flex items-start">
<div class="flex-shrink-0">
<EmailIcon class="w-6 h-6 text-blue-600 mt-1" />
</div>
<div class="ml-4">
<h3 class="text-lg font-semibold text-gray-900 mb-1">电子邮箱</h3>
<p class="text-gray-600">商务合作business@example.com</p>
<p class="text-gray-600">技术支持support@example.com</p>
<p class="text-gray-600">人事招聘hr@example.com</p>
</div>
</div>
</div>
</div>
<!-- 工作时间 -->
<div class="bg-blue-50 rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">工作时间</h3>
<div class="space-y-2 text-gray-600">
<div class="flex justify-between">
<span>周一至周五</span>
<span>9:00 - 18:00</span>
</div>
<div class="flex justify-between">
<span>周六</span>
<span>10:00 - 16:00</span>
</div>
<div class="flex justify-between">
<span>周日</span>
<span>休息</span>
</div>
</div>
</div>
</div>
<!-- 联系表单 -->
<div class="bg-white rounded-lg shadow-lg p-8">
<h2 class="text-2xl font-bold text-gray-900 mb-6">发送消息</h2>
<form @submit.prevent="submitForm" class="space-y-6">
<div>
<label for="name" class="block text-sm font-medium text-gray-700 mb-2">
姓名 <span class="text-red-500">*</span>
</label>
<input
id="name"
v-model="form.name"
type="text"
:class="[
'w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors',
errors.name ? 'border-red-500' : 'border-gray-300'
]"
placeholder="请输入您的姓名"
/>
<p v-if="errors.name" class="mt-1 text-sm text-red-600">{{ errors.name }}</p>
</div>
<div>
<label for="email" class="block text-sm font-medium text-gray-700 mb-2">
邮箱 <span class="text-red-500">*</span>
</label>
<input
id="email"
v-model="form.email"
type="email"
:class="[
'w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors',
errors.email ? 'border-red-500' : 'border-gray-300'
]"
placeholder="请输入您的邮箱"
/>
<p v-if="errors.email" class="mt-1 text-sm text-red-600">{{ errors.email }}</p>
</div>
<div>
<label for="phone" class="block text-sm font-medium text-gray-700 mb-2">
联系电话
</label>
<input
id="phone"
v-model="form.phone"
type="tel"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
placeholder="请输入您的联系电话"
/>
</div>
<div>
<label for="subject" class="block text-sm font-medium text-gray-700 mb-2">
主题 <span class="text-red-500">*</span>
</label>
<select
id="subject"
v-model="form.subject"
:class="[
'w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors',
errors.subject ? 'border-red-500' : 'border-gray-300'
]"
>
<option value="">请选择主题</option>
<option value="business">商务合作</option>
<option value="technical">技术支持</option>
<option value="feedback">意见反馈</option>
<option value="other">其他</option>
</select>
<p v-if="errors.subject" class="mt-1 text-sm text-red-600">{{ errors.subject }}</p>
</div>
<div>
<label for="message" class="block text-sm font-medium text-gray-700 mb-2">
消息内容 <span class="text-red-500">*</span>
</label>
<textarea
id="message"
v-model="form.message"
rows="5"
:class="[
'w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors resize-none',
errors.message ? 'border-red-500' : 'border-gray-300'
]"
placeholder="请详细描述您的问题或需求..."
></textarea>
<p v-if="errors.message" class="mt-1 text-sm text-red-600">{{ errors.message }}</p>
</div>
<div class="flex items-center">
<input
id="agree"
v-model="form.agree"
type="checkbox"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/>
<label for="agree" class="ml-2 text-sm text-gray-600">
我同意<a href="#" class="text-blue-600 hover:text-blue-800">隐私政策</a> <a href="#" class="text-blue-600 hover:text-blue-800">服务条款</a>
</label>
</div>
<p v-if="errors.agree" class="text-sm text-red-600">{{ errors.agree }}</p>
<button
type="submit"
:disabled="loading"
class="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-6 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center"
>
<LoadingIcon v-if="loading" class="animate-spin -ml-1 mr-3 h-5 w-5" />
<span v-if="loading">发送中...</span>
<span v-else>发送消息</span>
</button>
</form>
</div>
</div>
</div>
</section>
<!-- 地图区域 -->
<section class="py-16 bg-white">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-8">
<h2 class="text-3xl font-bold text-gray-900 mb-4">找到我们</h2>
<p class="text-gray-600">我们位于深圳市南山区交通便利欢迎您的到访</p>
</div>
<div class="bg-gray-200 rounded-lg h-96 flex items-center justify-center">
<div class="text-center">
<MapIcon class="w-16 h-16 text-gray-400 mx-auto mb-4" />
<p class="text-gray-600">地图加载中...</p>
<p class="text-sm text-gray-500 mt-2">深圳市南山区科技园南区深圳湾科技生态园</p>
</div>
</div>
</div>
</section>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 图标组件
const LocationIcon = {
template: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>`
}
const PhoneIcon = {
template: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"></path></svg>`
}
const EmailIcon = {
template: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg>`
}
const MapIcon = {
template: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7"></path></svg>`
}
const LoadingIcon = {
template: `<svg fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>`
}
// 响应式数据
const loading = ref(false)
const form = ref({
name: '',
email: '',
phone: '',
subject: '',
message: '',
agree: false
})
const errors = ref({})
// 表单验证
const validateForm = () => {
errors.value = {}
if (!form.value.name.trim()) {
errors.value.name = '请输入您的姓名'
}
if (!form.value.email.trim()) {
errors.value.email = '请输入邮箱地址'
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.value.email)) {
errors.value.email = '请输入有效的邮箱地址'
}
if (!form.value.subject) {
errors.value.subject = '请选择主题'
}
if (!form.value.message.trim()) {
errors.value.message = '请输入消息内容'
} else if (form.value.message.trim().length < 10) {
errors.value.message = '消息内容至少需要10个字符'
}
if (!form.value.agree) {
errors.value.agree = '请同意隐私政策和服务条款'
}
return Object.keys(errors.value).length === 0
}
// 提交表单
const submitForm = async () => {
if (!validateForm()) {
return
}
loading.value = true
try {
// 这里应该调用API发送消息
console.log('发送消息:', form.value)
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 2000))
alert('消息发送成功!我们会尽快回复您。')
// 重置表单
form.value = {
name: '',
email: '',
phone: '',
subject: '',
message: '',
agree: false
}
} catch (error) {
console.error('发送失败', error)
alert('发送失败,请稍后重试。')
} finally {
loading.value = false
}
}
</script>
<style scoped>
/* 响应式优化 */
@media (max-width: 768px) {
.grid-cols-1.lg\:grid-cols-2 {
grid-template-columns: 1fr;
}
.space-y-8 > * + * {
margin-top: 2rem;
}
.space-y-6 > * + * {
margin-top: 1.5rem;
}
}
/* 表单样式优化 */
input:focus,
select:focus,
textarea:focus {
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
/* 加载动画 */
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.animate-spin {
animation: spin 1s linear infinite;
}
</style>