293 lines
11 KiB
Vue
293 lines
11 KiB
Vue
<template>
|
|
<div>
|
|
<!-- 页面标题 -->
|
|
<HeroBanner
|
|
:title="$t('contact.hero.title')"
|
|
:subtitle="$t('contact.hero.subtitle')"
|
|
/>
|
|
|
|
<!-- 联系方式 -->
|
|
<section class="section">
|
|
<div class="container">
|
|
<div class="grid md:grid-cols-3 gap-8 mb-16">
|
|
<div v-for="(contact, index) in contactMethods" :key="index" class="bg-white p-8 rounded-lg shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1">
|
|
<div class="w-20 h-20 bg-gradient-to-br from-secondary/20 to-secondary/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
|
<i :class="['text-secondary text-3xl', contact.icon]"></i>
|
|
</div>
|
|
<h3 class="text-2xl font-semibold mb-4 text-center">{{ $t(contact.titleKey) }}</h3>
|
|
<p class="text-gray-600 mb-2 text-center">{{ $t(contact.subtitleKey) }}</p>
|
|
<p class="text-2xl font-semibold text-secondary text-center">{{ $t(contact.contentKey) }}</p>
|
|
<div v-if="contact.type === 'wechat'" class="w-32 h-32 bg-gradient-to-br from-secondary/20 to-secondary/10 rounded-lg mx-auto flex items-center justify-center mt-4">
|
|
<i class="fas fa-qrcode text-6xl text-secondary"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid md:grid-cols-2 gap-12">
|
|
<!-- 联系表单 -->
|
|
<div class="bg-white p-8 rounded-lg shadow-lg">
|
|
<h2 class="text-3xl font-bold mb-8 text-center">{{ $t('contact.form.title') }}</h2>
|
|
<form @submit.prevent="submitForm" class="space-y-6">
|
|
<div class="grid md:grid-cols-2 gap-6">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2" for="name">
|
|
{{ $t('contact.form.name') }} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="name"
|
|
v-model="form.name"
|
|
required
|
|
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-secondary focus:border-transparent transition-colors duration-300"
|
|
>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2" for="company">
|
|
{{ $t('contact.form.company') }} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="company"
|
|
v-model="form.company"
|
|
required
|
|
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-secondary focus:border-transparent transition-colors duration-300"
|
|
>
|
|
</div>
|
|
</div>
|
|
<div class="grid md:grid-cols-2 gap-6">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2" for="email">
|
|
{{ $t('contact.form.email') }} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
v-model="form.email"
|
|
required
|
|
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-secondary focus:border-transparent transition-colors duration-300"
|
|
>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2" for="phone">
|
|
{{ $t('contact.form.phone') }} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input
|
|
type="tel"
|
|
id="phone"
|
|
v-model="form.phone"
|
|
required
|
|
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-secondary focus:border-transparent transition-colors duration-300"
|
|
>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2" for="service">
|
|
{{ $t('contact.form.service') }} <span class="text-red-500">*</span>
|
|
</label>
|
|
<select
|
|
id="service"
|
|
v-model="form.service"
|
|
required
|
|
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-secondary focus:border-transparent transition-colors duration-300"
|
|
>
|
|
<option value="">{{ $t('contact.form.placeholders.selectService') }}</option>
|
|
<option v-for="(service, index) in services" :key="index" :value="service.value">
|
|
{{ $t(service.labelKey) }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2" for="message">
|
|
{{ $t('contact.form.message') }} <span class="text-red-500">*</span>
|
|
</label>
|
|
<textarea
|
|
id="message"
|
|
v-model="form.message"
|
|
rows="4"
|
|
required
|
|
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-secondary focus:border-transparent transition-colors duration-300"
|
|
></textarea>
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
:disabled="submitting"
|
|
:class="['w-full py-4 px-6 rounded-lg text-white text-lg font-semibold',
|
|
submitting ? 'bg-gray-400' : 'bg-secondary hover:bg-secondary/90 transition-colors duration-300']"
|
|
>
|
|
<span v-if="submitting">
|
|
<i class="fas fa-spinner fa-spin mr-2"></i>{{ $t('contact.form.submitting') }}
|
|
</span>
|
|
<span v-else>{{ $t('contact.form.submit') }}</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- 公司地址 -->
|
|
<div>
|
|
<div class="bg-white p-8 rounded-lg shadow-lg mb-8">
|
|
<h2 class="text-3xl font-bold mb-8 text-center">{{ $t('contact.companyInfo.title') }}</h2>
|
|
<div class="space-y-6">
|
|
<div v-for="(info, index) in companyInfo" :key="index" class="flex items-start">
|
|
<div class="w-12 h-12 bg-gradient-to-br from-secondary/20 to-secondary/10 rounded-full flex items-center justify-center mr-4">
|
|
<i :class="['text-secondary text-xl', info.icon]"></i>
|
|
</div>
|
|
<div>
|
|
<h4 class="text-xl font-semibold mb-2">{{ $t(info.titleKey) }}</h4>
|
|
<p class="text-gray-600">{{ $t(info.contentKey) }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- 地图 -->
|
|
<div class="w-full h-96 rounded-lg shadow-lg overflow-hidden bg-gray-200 flex items-center justify-center">
|
|
<i class="fas fa-map-marked-alt text-6xl text-gray-400"></i>
|
|
<span class="ml-4 text-gray-500">地图加载位置</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 常见问题 -->
|
|
<section class="section bg-gray-50">
|
|
<div class="container">
|
|
<h2 class="text-4xl font-bold text-center mb-6">{{ $t('contact.faq.title') }}</h2>
|
|
<p class="text-xl text-center text-gray-600 mb-12">{{ $t('contact.faq.subtitle') }}</p>
|
|
<div class="grid md:grid-cols-2 gap-8">
|
|
<div v-for="(faq, index) in faqs" :key="index" class="bg-white p-8 rounded-lg shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1">
|
|
<h3 class="text-2xl font-semibold mb-4">{{ $t(faq.questionKey) }}</h3>
|
|
<p class="text-gray-600 leading-relaxed">{{ $t(faq.answerKey) }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 通知组件 -->
|
|
<NotificationToast
|
|
:message="notification.message"
|
|
:type="notification.type"
|
|
@close="notification.message = ''"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
const { t } = useI18n();
|
|
|
|
// 联系方式数据
|
|
const contactMethods = [
|
|
{
|
|
icon: 'fas fa-phone',
|
|
titleKey: 'contact.methods.phone.title',
|
|
subtitleKey: 'contact.methods.phone.subtitle',
|
|
contentKey: 'contact.methods.phone.content',
|
|
type: 'phone'
|
|
},
|
|
{
|
|
icon: 'fas fa-envelope',
|
|
titleKey: 'contact.methods.email.title',
|
|
subtitleKey: 'contact.methods.email.subtitle',
|
|
contentKey: 'contact.methods.email.content',
|
|
type: 'email'
|
|
},
|
|
{
|
|
icon: 'fab fa-weixin',
|
|
titleKey: 'contact.methods.wechat.title',
|
|
subtitleKey: 'contact.methods.wechat.subtitle',
|
|
contentKey: '',
|
|
type: 'wechat'
|
|
}
|
|
];
|
|
|
|
// 公司信息
|
|
const companyInfo = [
|
|
{
|
|
icon: 'fas fa-map-marker-alt',
|
|
titleKey: 'contact.companyInfo.beijing.title',
|
|
contentKey: 'contact.companyInfo.beijing.content'
|
|
},
|
|
{
|
|
icon: 'fas fa-subway',
|
|
titleKey: 'contact.companyInfo.transport.title',
|
|
contentKey: 'contact.companyInfo.transport.content'
|
|
},
|
|
{
|
|
icon: 'far fa-clock',
|
|
titleKey: 'contact.companyInfo.hours.title',
|
|
contentKey: 'contact.companyInfo.hours.content'
|
|
}
|
|
];
|
|
|
|
// 服务选项
|
|
const services = [
|
|
{ value: 'cloud', labelKey: 'contact.form.serviceOptions.cloud' },
|
|
{ value: 'migration', labelKey: 'contact.form.serviceOptions.migration' },
|
|
{ value: 'solution', labelKey: 'contact.form.serviceOptions.solution' },
|
|
{ value: 'price', labelKey: 'contact.form.serviceOptions.price' },
|
|
{ value: 'other', labelKey: 'contact.form.serviceOptions.other' }
|
|
];
|
|
|
|
// 常见问题
|
|
const faqs = [
|
|
{
|
|
questionKey: 'contact.faq.items.q1.question',
|
|
answerKey: 'contact.faq.items.q1.answer'
|
|
},
|
|
{
|
|
questionKey: 'contact.faq.items.q2.question',
|
|
answerKey: 'contact.faq.items.q2.answer'
|
|
},
|
|
{
|
|
questionKey: 'contact.faq.items.q3.question',
|
|
answerKey: 'contact.faq.items.q3.answer'
|
|
},
|
|
{
|
|
questionKey: 'contact.faq.items.q4.question',
|
|
answerKey: 'contact.faq.items.q4.answer'
|
|
}
|
|
];
|
|
|
|
// 表单数据
|
|
const form = reactive({
|
|
name: '',
|
|
company: '',
|
|
email: '',
|
|
phone: '',
|
|
service: '',
|
|
message: ''
|
|
});
|
|
|
|
const submitting = ref(false);
|
|
const notification = reactive({
|
|
message: '',
|
|
type: 'success'
|
|
});
|
|
|
|
// 表单提交方法
|
|
const submitForm = async () => {
|
|
submitting.value = true;
|
|
|
|
try {
|
|
// 模拟API请求
|
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
|
// 显示成功消息
|
|
notification.message = '提交成功!我们会尽快与您联系。';
|
|
notification.type = 'success';
|
|
|
|
// 重置表单
|
|
Object.keys(form).forEach(key => {
|
|
form[key as keyof typeof form] = '';
|
|
});
|
|
} catch (error) {
|
|
// 显示错误消息
|
|
notification.message = '抱歉,提交失败,请稍后重试。';
|
|
notification.type = 'error';
|
|
} finally {
|
|
submitting.value = false;
|
|
}
|
|
};
|
|
</script> |