218 lines
6.3 KiB
Vue
218 lines
6.3 KiB
Vue
<script setup lang="ts">
|
||
import { ref } from 'vue'
|
||
|
||
// 表单数据
|
||
const formData = ref({
|
||
name: '',
|
||
email: '',
|
||
phone: '',
|
||
message: ''
|
||
})
|
||
|
||
// 错误信息
|
||
const errors = ref({
|
||
name: '',
|
||
email: '',
|
||
phone: '',
|
||
message: ''
|
||
})
|
||
|
||
// 表单验证
|
||
const validateForm = () => {
|
||
let isValid = true
|
||
errors.value = { name: '', email: '', phone: '', message: '' }
|
||
|
||
// 姓名验证
|
||
if (!formData.value.name.trim()) {
|
||
errors.value.name = '请输入姓名'
|
||
isValid = false
|
||
} else if (formData.value.name.length < 2) {
|
||
errors.value.name = '姓名至少需要2个字符'
|
||
isValid = false
|
||
}
|
||
|
||
// 邮箱验证
|
||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||
if (!formData.value.email) {
|
||
errors.value.email = '请输入邮箱'
|
||
isValid = false
|
||
} else if (!emailRegex.test(formData.value.email)) {
|
||
errors.value.email = '请输入有效的邮箱地址'
|
||
isValid = false
|
||
}
|
||
|
||
// 电话验证
|
||
const phoneRegex = /^1[3-9]\d{9}$/
|
||
if (!formData.value.phone) {
|
||
errors.value.phone = '请输入电话'
|
||
isValid = false
|
||
} else if (!phoneRegex.test(formData.value.phone)) {
|
||
errors.value.phone = '请输入有效的手机号码'
|
||
isValid = false
|
||
}
|
||
|
||
// 留言验证
|
||
if (!formData.value.message.trim()) {
|
||
errors.value.message = '请输入留言内容'
|
||
isValid = false
|
||
} else if (formData.value.message.length < 10) {
|
||
errors.value.message = '留言内容至少需要10个字符'
|
||
isValid = false
|
||
}
|
||
|
||
return isValid
|
||
}
|
||
|
||
// 提交表单
|
||
const submitForm = (event: Event) => {
|
||
event.preventDefault()
|
||
|
||
if (validateForm()) {
|
||
// 在控制台打印表单值
|
||
console.log('表单提交数据:', JSON.parse(JSON.stringify(formData.value)))
|
||
|
||
// 这里可以添加实际的提交逻辑,如API请求
|
||
// axios.post('/api/submit', formData.value)
|
||
|
||
// 提交成功后重置表单
|
||
formData.value = { name: '', email: '', phone: '', message: '' }
|
||
alert('表单提交成功!')
|
||
} else {
|
||
console.log('表单验证失败:', errors.value)
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div>
|
||
<form class="space-y-6" @submit="submitForm">
|
||
<!-- 姓名 -->
|
||
<div data-aos="fade-up" data-aos-delay="200">
|
||
<label for="name" class="block text-sm font-medium text-blue-200 mb-1">姓名</label>
|
||
<input
|
||
type="text"
|
||
id="name"
|
||
v-model="formData.name"
|
||
class="w-full px-4 py-2 rounded-lg border border-blue-200 focus:outline-none focus:ring-2 focus:ring-blue-400 bg-blue-900/50 text-white"
|
||
placeholder="请输入您的姓名"
|
||
:class="{ 'border-red-500': errors.name }"
|
||
>
|
||
<div v-if="errors.name" class="text-red-400 text-sm mt-1">{{ errors.name }}</div>
|
||
</div>
|
||
|
||
<!-- 邮箱 -->
|
||
<div data-aos="fade-up" data-aos-delay="250">
|
||
<label for="email" class="block text-sm font-medium text-blue-200 mb-1">邮箱</label>
|
||
<input
|
||
type="email"
|
||
id="email"
|
||
v-model="formData.email"
|
||
class="w-full px-4 py-2 rounded-lg border border-blue-200 focus:outline-none focus:ring-2 focus:ring-blue-400 bg-blue-900/50 text-white"
|
||
placeholder="请输入您的邮箱"
|
||
:class="{ 'border-red-500': errors.email }"
|
||
>
|
||
<div v-if="errors.email" class="text-red-400 text-sm mt-1">{{ errors.email }}</div>
|
||
</div>
|
||
|
||
<!-- 电话 -->
|
||
<div data-aos="fade-up" data-aos-delay="300">
|
||
<label for="phone" class="block text-sm font-medium text-blue-200 mb-1">电话</label>
|
||
<input
|
||
type="tel"
|
||
id="phone"
|
||
v-model="formData.phone"
|
||
class="w-full px-4 py-2 rounded-lg border border-blue-200 focus:outline-none focus:ring-2 focus:ring-blue-400 bg-blue-900/50 text-white"
|
||
placeholder="请输入您的电话"
|
||
:class="{ 'border-red-500': errors.phone }"
|
||
>
|
||
<div v-if="errors.phone" class="text-red-400 text-sm mt-1">{{ errors.phone }}</div>
|
||
</div>
|
||
|
||
<!-- 留言 -->
|
||
<div data-aos="fade-up" data-aos-delay="350">
|
||
<label for="message" class="block text-sm font-medium text-blue-200 mb-1">留言内容</label>
|
||
<textarea
|
||
id="message"
|
||
v-model="formData.message"
|
||
rows="4"
|
||
class="w-full px-4 py-2 rounded-lg border border-blue-200 focus:outline-none focus:ring-2 focus:ring-blue-400 bg-blue-900/50 text-white"
|
||
placeholder="请输入您的留言内容"
|
||
:class="{ 'border-red-500': errors.message }"
|
||
></textarea>
|
||
<div v-if="errors.message" class="text-red-400 text-sm mt-1">{{ errors.message }}</div>
|
||
</div>
|
||
|
||
<!-- 提交按钮 - 优化版 -->
|
||
<button
|
||
type="submit"
|
||
class="w-full bg-gradient-to-r from-blue-500 to-indigo-600 hover:from-blue-600 hover:to-indigo-700 text-white font-medium py-3 px-6 rounded-lg flex items-center justify-center transition-all duration-300 transform hover:-translate-y-1 shadow-lg hover:shadow-xl active:translate-y-0 active:shadow-md"
|
||
data-aos="fade-up"
|
||
data-aos-delay="400"
|
||
>
|
||
<i class="fas fa-paper-plane mr-2 transform group-hover:translate-x-1 transition-transform"></i>
|
||
<span class="group-hover:font-semibold transition-all">提交申请</span>
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
/* 添加输入框聚焦时的动画效果 */
|
||
input:focus, textarea:focus {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
/* 错误提示动画 */
|
||
.text-red-400 {
|
||
animation: fadeIn 0.3s ease;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; transform: translateY(-5px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
/* 按钮悬停效果 */
|
||
button {
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
button::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
width: 5px;
|
||
height: 5px;
|
||
background: rgba(255, 255, 255, 0.5);
|
||
opacity: 0;
|
||
border-radius: 100%;
|
||
transform: scale(1, 1) translate(-50%);
|
||
transform-origin: 50% 50%;
|
||
}
|
||
|
||
button:focus:not(:active)::after {
|
||
animation: ripple 1s ease-out;
|
||
}
|
||
|
||
@keyframes ripple {
|
||
0% {
|
||
transform: scale(0, 0);
|
||
opacity: 0.7;
|
||
}
|
||
100% {
|
||
transform: scale(50, 50);
|
||
opacity: 0;
|
||
}
|
||
}
|
||
|
||
/* 按钮图标动画 */
|
||
button:hover i {
|
||
transform: translateX(5px);
|
||
transition: transform 0.3s ease;
|
||
}
|
||
</style>
|