2025-09-03 17:13:10 +08:00

666 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>
<view class="idcard-auth-page">
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
:title="currentStep === 1 ? '身份验证' : '添加银行卡'"
@clickLeft="goBack()"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eeeeee"
>
</uni-nav-bar>
<!-- 内容区域 -->
<view class="content-area">
<!-- 进度指示器 -->
<view class="progress-bar">
<view class="barbox">
<view class="imgbox">
<up-image :src="currentStep >= 1 ? stepActiveImg : stepImg" width="46rpx" height="46rpx"></up-image>
<view class="desc" :class="{ active: currentStep >= 1 }">身份信息</view>
</view>
<view class="line" :class="{ active: currentStep >= 2 }"></view>
<view class="imgbox">
<up-image :src="currentStep >= 2 ? stepActiveImg : stepImg" width="46rpx" height="46rpx"></up-image>
<view class="desc" :class="{ active: currentStep >= 2 }">添加银行卡</view>
</view>
<view class="line" :class="{ active: currentStep >= 3 }"></view>
<view class="imgbox">
<up-image :src="currentStep >= 3 ? stepActiveImg : stepImg" width="46rpx" height="46rpx"></up-image>
<view class="desc" :class="{ active: currentStep >= 3 }">完成</view>
</view>
</view>
<!-- <view class="progress-step active">
<view class="step-icon">
<uni-icons type="checkmarkempty" color="#ff0000" size="20"></uni-icons>
</view>
<text class="step-text">身份信息</text>
</view>
<view class="progress-line active"></view>
<view class="progress-step">
<view class="step-icon">
<uni-icons type="checkmarkempty" color="#cccccc" size="20"></uni-icons>
</view>
<text class="step-text">添加银行卡</text>
</view>
<view class="progress-line"></view>
<view class="progress-step">
<view class="step-icon">
<uni-icons type="checkmarkempty" color="#cccccc" size="20"></uni-icons>
</view>
<text class="step-text">完成</text>
</view> -->
</view>
<!-- 输入表单 -->
<view class="form-section">
<!-- 第一步身份信息 -->
<view v-if="currentStep === 1">
<view class="form-item">
<text class="form-label">姓名</text>
<input
class="form-input"
placeholder="请输入您的姓名"
v-model="formData.name"
placeholder-style="color: #cccccc"
/>
</view>
<view class="form-item">
<text class="form-label">身份证号</text>
<input
class="form-input"
placeholder="请输入您的身份证号"
v-model="formData.idNumber"
placeholder-style="color: #cccccc"
/>
</view>
</view>
<!-- 第二步:添加银行卡 -->
<view v-if="currentStep === 2">
<view class="form-item">
<text class="form-label">银行卡号</text>
<view class="input-container">
<input
class="form-input"
placeholder="仅限借记卡"
v-model="formData.cardNumber"
placeholder-style="color: #cccccc"
/>
<view class="info-icon">
<text class="icon-text">!</text>
</view>
</view>
</view>
<view class="form-item">
<text class="form-label">手机号</text>
<view class="input-container">
<input
class="form-input"
placeholder="银行预留手机号"
v-model="formData.mobile"
placeholder-style="color: #cccccc"
/>
<view class="info-icon">
<text class="icon-text">!</text>
</view>
</view>
</view>
</view>
</view>
<!-- 提示文字 -->
<view class="warning-text">
平台不支持绑定多人银行卡,请务必绑定本人卡,实名认证信息,谨慎填写!
</view>
<!-- 下一步按钮 -->
<view class="bottom-actions">
<button class="next-btn" :class="{ loading: isLoading }" @click="onNextStep" :disabled="isLoading">
<text v-if="!isLoading">下一步</text>
<text v-else>验证中...</text>
</button>
</view>
<!-- 短信验证码弹框 -->
<view v-if="showSmsDialog" class="sms-mask">
<view class="sms-dialog">
<view class="sms-title">短信验证码</view>
<view class="sms-subtitle">请输入手机{{ maskedMobile }}收到的验证码</view>
<view class="sms-input-row">
<input class="sms-input" v-model="smsCode" placeholder="请输入验证码" placeholder-style="color: #cccccc" />
<button class="sms-code-btn" :disabled="countdown > 0 || sendingCode" @click="onGetSmsCode">
<text v-if="countdown === 0">获取验证码</text>
<text v-else>{{ countdown }}s</text>
</button>
</view>
<view class="sms-actions">
<button class="sms-cancel" @click="onCancelSms">取消</button>
<button class="sms-confirm" @click="onConfirmSms">确定</button>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue';
import stepImg from "@/static/add_card_no.png"
import stepActiveImg from "@/static/add_card_yes.png"
import navTo from '@/utils/navTo';
import api from '@/api/api';
const formData = ref({
name: '',
idNumber: '',
cardNumber: '',
mobile: ''
});
const isLoading = ref(false);
const currentStep = ref(1); // 当前步骤1表示身份信息2表示添加银行卡
// 短信弹框相关
const showSmsDialog = ref(false);
const smsCode = ref('');
const sendingCode = ref(false);
const countdown = ref(0);
let countdownTimer = null;
const maskedMobile = computed(() => {
const m = formData.value.mobile || '';
if (m && m.length >= 7) {
return `${m.slice(0,3)}****${m.slice(-4)}`;
}
return m || '***********';
});
const goBack = () => {
uni.navigateBack();
};
// 身份证号格式验证
const validateIdNumber = (idNumber) => {
const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
return reg.test(idNumber);
};
// 姓名格式验证
const validateName = (name) => {
const reg = /^[\u4e00-\u9fa5]{2,10}$/;
return reg.test(name);
};
// 银行卡号验证
const validateCardNumber = (cardNumber) => {
const reg = /^\d{16,19}$/;
return reg.test(cardNumber);
};
// 手机号验证
const validateMobile = (mobile) => {
const reg = /^1[3-9]\d{9}$/;
return reg.test(mobile);
};
const onNextStep = async () => {
if (currentStep.value === 1) {
// 第一步:身份信息验证
if (!formData.value.name.trim()) {
uni.showToast({ title: '请输入姓名', icon: 'none' });
return;
}
if (!validateName(formData.value.name)) {
uni.showToast({ title: '请输入正确的姓名2-10个汉字', icon: 'none' });
return;
}
if (!formData.value.idNumber.trim()) {
uni.showToast({ title: '请输入身份证号', icon: 'none' });
return;
}
if (!validateIdNumber(formData.value.idNumber)) {
uni.showToast({ title: '请输入正确的身份证号', icon: 'none' });
return;
}
// 显示加载状态
isLoading.value = true;
try {
// 调用身份验证API
const res = {code:200}
if (res.code === 200) {
uni.showToast({ title: '身份验证成功', icon: 'success' });
currentStep.value = 2;
isLoading.value = false;
} else {
uni.showToast({ title: res.msg || '身份验证失败', icon: 'none' });
isLoading.value = false;
}
} catch (error) {
console.error('身份验证失败:', error);
uni.showToast({ title: '网络错误,请重试', icon: 'none' });
isLoading.value = false;
}
} else if (currentStep.value === 2) {
// 第二步:银行卡信息验证
if (!formData.value.cardNumber.trim()) {
uni.showToast({ title: '请输入银行卡号', icon: 'none' });
return;
}
if (!validateCardNumber(formData.value.cardNumber)) {
uni.showToast({ title: '请输入正确的银行卡号', icon: 'none' });
return;
}
if (!formData.value.mobile.trim()) {
uni.showToast({ title: '请输入手机号', icon: 'none' });
return;
}
if (!validateMobile(formData.value.mobile)) {
uni.showToast({ title: '请输入正确的手机号', icon: 'none' });
return;
}
// 弹出短信验证码弹框
showSmsDialog.value = true;
}
};
const onGetSmsCode = async () => {
if (countdown.value > 0) return;
const res = await api.smsSend({
mobile: formData.value.mobile,
type: 3
});
if (res.code === 200) {
uni.showToast({ title: '短信验证码发送成功', icon: 'success' });
// 开始60秒倒计时
countdown.value = 60;
if (countdownTimer) clearInterval(countdownTimer);
countdownTimer = setInterval(() => {
if (countdown.value > 0) {
countdown.value -= 1;
} else {
clearInterval(countdownTimer);
countdownTimer = null;
}
}, 1000);
} else {
uni.showToast({ title: res.msg || '短信验证码发送失败', icon: 'none' });
}
};
const onConfirmSms = async () => {
if (!smsCode.value) {
uni.showToast({ title: '请输入短信验证码', icon: 'none' });
return;
}
const res = await api.identificationBankCardNew({
phone_number: formData.value.mobile,
sms: smsCode.value,
id_number: formData.value.idNumber,
card_number: formData.value.cardNumber,
id_name: formData.value.name
});
if (res.code === 200) {
uni.showToast({ title: '银行卡添加成功', icon: 'success' });
navTo({
url: '/pages_app/idcardAuth/bankCardList'
});
} else {
uni.showToast({ title: res.msg || '银行卡添加失败', icon: 'none' });
}
};
const onCancelSms = () => {
showSmsDialog.value = false;
};
</script>
<style lang="scss" scoped>
.idcard-auth-page {
min-height: 100vh;
background: #f5f5f5;
}
.content-area {
padding-top: 160rpx;
padding: 0rpx 0rpx 0;
}
.progress-bar {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #ffffff;
padding: 80rpx 20rpx 120rpx;
border-radius: 16rpx;
margin-bottom: 30rpx;
.barbox{
display: flex;
align-items: center;
justify-content: center;
.imgbox{
flex:1;
position: relative;
.desc{
position: absolute;
left:-50%;
color:#d0d0d0;
top:80rpx;
font-size: 28rpx;
margin-left: -10rpx;
white-space: nowrap;
transform: translateY(-50%);
&.active{
color:#8B2316;
}
}
}
.imgbox:last-child{
.desc{
margin-left: 15rpx;
}
}
.line{
width:240rpx;
margin:0 -2rpx;
height: 16rpx;
background:#cccccc;
&.active{
background:#8B2316;
}
}
}
.steptext{
margin:0 30rpx;
display: flex;
width:900rpx;
justify-content: space-between;
align-items:center ;
}
.progress-step {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
.step-icon {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
background: #f0f0f0;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
&.active {
background: #ff0000;
}
}
.step-text {
font-size: 24rpx;
color: #666666;
&.active {
color: #000000;
}
}
&.active {
.step-icon {
background: #ff0000;
}
.step-text {
color: #000000;
}
}
}
.progress-line {
flex: 1;
height: 4rpx;
background: #f0f0f0;
margin: 0 20rpx;
&.active {
background: #ff0000;
}
}
}
.form-section {
background: #ffffff;
border-radius: 16rpx;
padding: 0;
.form-item {
margin-bottom: 30rpx;
display: flex;
align-items: center;
border-bottom: 2rpx solid #eee;
padding: 0 30rpx 20rpx;
&:last-child {
margin-bottom: 0;
padding-bottom: 0;
}
.form-label {
display: block;
font-size: 28rpx;
color: #000000;
width: 120rpx;
font-weight: 500;
}
.form-input {
flex: 1;
height: 80rpx;
padding: 0 20rpx;
font-size: 28rpx;
background: #ffffff;
border: none;
outline: none;
&:focus {
border-color: #8B2316;
}
}
.input-container {
display: flex;
align-items: center;
position: relative;
width: 80%;
.form-input {
flex: 9;
height: 80rpx;
padding: 0 20rpx;
font-size: 28rpx;
background: #ffffff;
border: none;
border-radius: 0;
outline: none;
&:focus {
/* 去除边框后无需变更边框颜色 */
}
}
.info-icon {
flex:1;
position: absolute;
right: 20rpx;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background: #f0f0f0;
display: flex;
align-items: center;
justify-content: center;
.icon-text {
font-size: 20rpx;
color: #cccccc;
font-weight: bold;
}
}
}
}
}
.warning-text {
background: #fff3cd;
border: 2rpx solid #ffeaa7;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 60rpx;
font-size: 26rpx;
color: #856404;
line-height: 1.6;
position: relative;
&::before {
content: "⚠️";
position: absolute;
left: 30rpx;
top: 30rpx;
font-size: 32rpx;
}
padding-left: 80rpx;
}
.bottom-actions {
padding: 0 30rpx 40rpx;
.next-btn {
width: 100%;
height: 88rpx;
background: #8B2316;
color: #ffffff;
border: none;
border-radius: 8rpx;
font-size: 32rpx;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&:active {
background: #6B1A0F;
}
&.loading {
background: #cccccc;
opacity: 0.7;
}
&:disabled {
background: #cccccc;
opacity: 0.7;
}
}
}
/* 短信弹框样式 */
.sms-mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.sms-dialog {
width: 680rpx;
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
}
.sms-title {
text-align: center;
font-size: 34rpx;
color: #000000;
font-weight: 600;
margin-bottom: 20rpx;
}
.sms-subtitle {
text-align: center;
font-size: 28rpx;
color: #333333;
margin-bottom: 24rpx;
}
.sms-input-row {
display: flex;
align-items: center;
gap: 16rpx;
margin: 10rpx 0 30rpx;
}
.sms-input {
flex: 1;
height: 88rpx;
border: 2rpx solid #eeeeee;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
.sms-code-btn {
width: 200rpx;
height: 88rpx;
border-radius: 8rpx;
background: #eeeeee;
color: #8B2316;
font-size: 26rpx;
}
.sms-actions {
display: flex;
justify-content: space-between;
margin-top: 10rpx;
}
.sms-cancel,
.sms-confirm {
flex: 1;
height: 88rpx;
border-radius: 8rpx;
font-size: 32rpx;
}
.sms-cancel { background: #f5f5f5; color: #000000; margin-right: 20rpx; }
.sms-confirm { background: #8B2316; color: #ffffff; margin-left: 20rpx; }
</style>