fucai-claim/src/pages/home/index.vue

361 lines
13 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-[#FCEEF3] overflow-hidden">
<!-- 顶部头图 -->
<div class="w-full overflow-hidden relative">
<img src="/头图.png" alt="活动宣传" class="w-full h-auto" />
<!-- 顶部Logo和标题 -->
<div class="absolute top-0 left-0 py-4 h-full w-full flex flex-col items-start justify-center px-4">
<div class="flex items-start mb-4">
<img src="/logo.png" alt="中国福利彩票" class="h-8 pl-2" />
</div>
<img src="/ziti.png" alt="宁福您彩 新婚送福" class="h-15" />
</div>
</div>
<!-- 表单区域 -->
<div class="p-4 -mt-10 z-10 relative">
<div class="max-w-md mx-auto bg-white rounded-xl shadow-sm p-6">
<!-- 标题 -->
<div class="flex items-center justify-center text-xl text-[#E8424D] mb-6">
<img src="/爱心点缀1.png" alt="" class="h-5">
<span class="px-2">领取专属喜礼</span>
<img src="/爱心点缀2.png" alt="" class="h-5">
</div>
<div>
<div v-if="![2, 3].includes(activityInfo.status)">
<!-- 手机号输入 -->
<div class="mb-5 flex items-center gap-3 border border-gray-200 rounded-lg px-4">
<input v-model="formData.phone" type="tel" placeholder="请输入手机号码" maxlength="11"
class="outline-none focus:border-[#E8424D] transition-colors flex-1 h-11" />
<button @click="sendVerificationCode" :disabled="countdown > 0 || formData.phone.length !== 11"
class="h-11 rounded-lg text-sm text-[#E8424D] transition-all disabled:text-[#8a8a8a]">
{{ countdown > 0 ? `${countdown}秒后重发` : formData.verifyCode ? '重新获取' : '获取验证码' }}
</button>
</div>
<!-- 验证码输入 -->
<div class="mb-5 flex items-center gap-3 border border-gray-200 rounded-lg px-4">
<input :disabled="formData.verifyCode" v-model="formData.smsCode" type="text" placeholder="请输入验证码"
maxlength="6" class="outline-none focus:border-[#E8424D] transition-colors flex-1 h-11" />
<button v-if="!formData.verifyCode" @click="verifyCode" :disabled="formData.smsCode.length !== 6"
class="h-8 px-4 bg-[#E8424D] text-white rounded-lg text-sm transition-all hover:opacity-90 active:scale-98 disabled:bg-[#8a8a8a]">
验证
</button>
</div>
</div>
<div v-if="formData.verifyCode && !formData.qrCode">
<!-- 结婚证信息 -->
<div class="mb-6">
<h3 class="text-base text-gray-800 mb-3 font-medium">结婚证信息:</h3>
<div v-if="!formData.marriageNo"
class="border border-gray-200 rounded-lg p-5 flex items-center justify-center">
<div class="relative inline-block" @click="handleScanClick">
<img src="/扫描.png" alt="" class="h-20">
<div
class="h-16 w-26 absolute border border-[#f0f0f0] rounded-md top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex justify-center">
<span class="text-[#E2E4E9] text-xs pt-1">结婚证</span>
</div>
<input type="file" ref="ocrUploadId" class="hidden" accept="image/*" @change="handleImageChange" />
</div>
</div>
<div v-if="formData.marriageNo"
class="w-full flex flex-col items-start border border-gray-200 rounded-lg p-5 bg-[#FAFAFA]">
<div>
<span class="inline-block w-25 text-right">结婚证字号:</span>
<span class="pl-2">{{ formData.marriageNo }}</span>
</div>
<div class="mt-2">
<span class="inline-block w-25 text-right">男方姓名:</span>
<span class="pl-2">{{ formData.husbandName }}</span>
</div>
<div class="mt-2">
<span class="inline-block w-25 text-right">女方姓名:</span>
<span class="pl-2">{{ formData.wifeName }}</span>
</div>
</div>
</div>
<!-- 提交按钮 -->
<button @click="submitForm" :disabled="!formData.marriageNo"
class="w-full h-12 bg-gradient-to-r from-[#E8424D] to-[#FF7A7A] text-white rounded-full text-lg font-bold transition-all hover:opacity-90 active:scale-98 disabled:from-[#8a8a8a] disabled:to-[#8a8a8a]">
提交领取喜礼
</button>
</div>
<div v-if="formData.qrCode">
<div>
<h3 class="text-base text-gray-800 mb-3 font-medium">请使用微信扫描下方二维码:</h3>
</div>
<div class="mt-4 flex justify-center items-center">
<qrcode-vue :value="formData.qrCode" :size="200" level="H" render-as="canvas" />
</div>
</div>
</div>
<div v-if="activityInfo.status === 2">
<!-- 活动结束状态 -->
<div class="mt-6 p-4 border border-[#E8424D] bg-[#FFF5F5] rounded-lg text-center">
<div class="text-[#E8424D] text-lg font-semibold mb-2">活动已结束</div>
<div class="text-gray-600 text-sm">【{{ activityInfo.activityName }}】活动已结束,感谢您的参与,敬请期待下一次活动</div>
<div class="mt-4 text-xs text-gray-500">活动时间:{{ activityInfo.activityStartTime }} - {{
activityInfo.activityEndTime }}</div>
</div>
</div>
<div v-else-if="activityInfo.status === 3">
<!-- 活动失败状态 -->
<div class="mt-6 p-4 border border-[#FF7A7A] bg-[#FFF5F5] rounded-lg text-center">
<div class="text-[#FF7A7A] text-lg font-semibold mb-2">活动获取失败</div>
<div class="text-gray-600 text-sm">活动获取失败,请稍后重试</div>
<div class="mt-4 text-xs text-gray-500">活动时间:--</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import message from '../../components/message';
import apiService from '../../services/apiService'
import { ref, onMounted } from 'vue'
import dayjs from 'dayjs'
import QrcodeVue from 'qrcode.vue'
import { showLoading, hideLoading } from '../../components/loading'
const ocrUploadId = ref<HTMLInputElement>();
// 表单数据
const formData = ref({
phone: '',
smsCode: '',
verifyCode: false, // 验证状态
marriageNo: '', // 结婚证号
husbandName: '', // 男方姓名
wifeName: '', // 女方姓名
registerDate: '', // 登记日期
qrCode: '', // 二维码
})
const activityInfo = ref<any>({}); // 活动信息
onMounted(() => {
// 检查活动是否已结束
showLoading();
apiService.getCurrentActivity().then((response: any) => {
if (response.data) {
activityInfo.value = {
...response.data,
activityStartTime: dayjs(response.data.activityStartTime).format('YYYY年MM月DD日'),
activityEndTime: dayjs(response.data.activityEndTime).format('YYYY年MM月DD日'),
};
if (new Date(response.data.activityEndTime) < new Date()) {
message.error('活动已结束');
activityInfo.value.status = 2;
} else {
const user = JSON.parse(localStorage.getItem('userAs') || '{}');
if (user.phone && user.smsCode) {
formData.value.phone = user.phone;
formData.value.smsCode = user.smsCode;
verifyCode();
}
}
}
}).catch((error) => {
message.error('获取活动信息失败,请稍后重试')
activityInfo.value.status = 3;
}).finally(() => {
hideLoading();
})
})
// 倒计时
const countdown = ref(0)
let countdownTimer: number | null = null
// 发送验证码
const sendVerificationCode = () => {
const { phone } = formData.value
// 简单手机号验证
if (!/^1[3-9]\d{9}$/.test(phone)) {
message.error('请输入正确的手机号码')
return
}
showLoading();
// 调用发送短信验证码接口
apiService.sendSms({
mobile: phone,
type: 3,
}).then(() => {
formData.value.verifyCode = false;
formData.value.smsCode = '';
formData.value.qrCode = '';
// 开始倒计时
countdown.value = 60
if (countdownTimer) {
clearInterval(countdownTimer)
}
countdownTimer = window.setInterval(() => {
if (countdown.value > 0) {
countdown.value--
} else {
if (countdownTimer) {
clearInterval(countdownTimer)
}
}
}, 1000)
}).catch((error) => {
console.error('发送验证码失败:', error)
message.error('验证码发送失败,请稍后重试')
}).finally(() => {
hideLoading();
})
}
// 验证验证码
const verifyCode = () => {
const { smsCode } = formData.value
if (smsCode.length !== 6 || !/^\d{6}$/.test(smsCode)) {
message.error('请输入6位数字验证码')
return
}
showLoading();
// 调用验证短信验证码接口
apiService.verifySms({
mobile: formData.value.phone,
smsCode: smsCode,
type: 3,
}).then((res) => {
localStorage.setItem('userAs', JSON.stringify({
phone: formData.value.phone,
smsCode: formData.value.smsCode,
}));
formData.value.verifyCode = true;
// 验证成功后重置倒计时
countdown.value = 0;
// 验证成功如果有二维码,保存到表单
if (res.data.code) {
formData.value = {
...formData.value,
qrCode: res.data.code,
}
} else {
formData.value = {
...formData.value,
marriageNo: "",
husbandName: "",
wifeName: "",
registerDate: "",
qrCode: ""
}
}
}).catch((error) => {
localStorage.removeItem('userAs');
message.error('验证码验证失败,请重试');
formData.value = {
...formData.value,
marriageNo: "",
husbandName: "",
wifeName: "",
registerDate: "",
qrCode: ""
}
}).finally(() => {
hideLoading();
})
}
// 处理扫描点击事件
const handleScanClick = () => {
ocrUploadId.value?.click()
}
const handleImageChange = () => {
const file = ocrUploadId.value?.files?.[0]
if (!file) {
message.error('请选择图片文件')
return
}
// 调用上传OCR图片接口
const formFormData = new FormData()
formFormData.append('file', file)
showLoading();
apiService.uploadOcrImage(formFormData).then((response: any) => {
apiService.parseOcrInfo({
mobile: formData.value.phone,
smsCode: formData.value.smsCode,
uploadId: response.data.uploadId,
}).then((res: any) => {
if (res?.data?.parsed?.marriageNo) {
formData.value.marriageNo = res?.data?.parsed?.marriageNo;
formData.value.husbandName = res?.data?.parsed?.husbandName;
formData.value.wifeName = res?.data?.parsed?.wifeName;
formData.value.registerDate = res?.data?.parsed?.registerDate;
} else {
message.error('解析OCR信息失败请稍后重试');
ocrUploadId.value && (ocrUploadId.value.value = '');
}
}).catch((error) => {
message.error('解析OCR信息失败请稍后重试')
ocrUploadId.value && (ocrUploadId.value.value = '');
}).finally(() => {
hideLoading();
})
}).catch((error) => {
message.error('图片上传失败,请稍后重试')
ocrUploadId.value && (ocrUploadId.value.value = '');
hideLoading();
})
}
// 提交表单
const submitForm = () => {
if (!formData.value.phone || !formData.value.smsCode) {
message.error('请完善所有信息')
return
}
showLoading();
apiService.receiveCheck({
marriageNo: formData.value.marriageNo,
receiveName: formData.value.husbandName,
receiveMobile: formData.value.phone,
smsCode: formData.value.smsCode,
}).then((res: any) => {
formData.value.qrCode = res.data.code;
}).catch((error) => {
message.error(error?.msg || '提交失败,请稍后重试')
}).finally(() => {
hideLoading();
})
}
// 组件卸载时清理定时器
import { onUnmounted } from 'vue'
onUnmounted(() => {
if (countdownTimer) {
clearInterval(countdownTimer)
}
})
</script>