183 lines
5.4 KiB
Vue
183 lines
5.4 KiB
Vue
<template>
|
|
<!-- 2026-08-08 对齐企业开户交互样式改造:外层容器从"整屏 min-height: calc(100vh - 46px) +
|
|
fixed footer"改为手风琴步骤行内的普通块级布局(.step-body),不再假设整屏展示,
|
|
参照企业开户 EnterpriseSmsVerifyStep.vue;同时去掉"上一步"按钮及对应 emit,
|
|
本步骤不再支持回退 -->
|
|
<div class="step-body">
|
|
<van-cell-group inset>
|
|
<van-cell title="手机号" :value="mobilePhoneMask || '-'" />
|
|
</van-cell-group>
|
|
|
|
<div class="verify-row">
|
|
<van-field
|
|
v-model="verifyCode"
|
|
type="digit"
|
|
maxlength="6"
|
|
placeholder="请输入短信验证码"
|
|
class="verify-input"
|
|
/>
|
|
<van-button
|
|
size="small"
|
|
type="primary"
|
|
plain
|
|
class="send-btn"
|
|
:disabled="countdown > 0 || sending"
|
|
:loading="sending"
|
|
@click="handleSendCode"
|
|
>
|
|
{{ countdown > 0 ? `${countdown}s后重新获取` : '获取验证码' }}
|
|
</van-button>
|
|
</div>
|
|
|
|
<div class="footer">
|
|
<van-button
|
|
type="primary"
|
|
block
|
|
round
|
|
:disabled="!verifyCode || submitting"
|
|
:loading="submitting"
|
|
loading-text="提交中..."
|
|
@click="handleSubmit"
|
|
>
|
|
确认提交
|
|
</van-button>
|
|
</div>
|
|
|
|
<!-- 耗时操作统一等待态:提交期间整页遮罩,禁止用户进行其它操作 -->
|
|
<van-overlay :show="submitting" class="submit-overlay">
|
|
<div class="overlay-center">
|
|
<van-loading type="spinner" color="#fff" size="28px">提交中,请稍候...</van-loading>
|
|
</div>
|
|
</van-overlay>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
import { showToast } from 'vant'
|
|
import { sendVerifyCodeApi, submitApplicationApi } from '@/api/personalOpen'
|
|
import { showErrorModal } from '@/utils/errorModal'
|
|
|
|
const props = defineProps({
|
|
applicationNo: { type: String, required: true },
|
|
channelNo: { type: String, default: '' },
|
|
mobile: { type: String, default: '' },
|
|
mobilePhoneMask: { type: String, default: '' },
|
|
cardNo: { type: String, default: '' },
|
|
cardName: { type: String, default: '' },
|
|
idNo: { type: String, default: '' },
|
|
// AgreementStep 生成并上传《用户支付服务协议》PDF后拿到的文件编号,提交开户时随
|
|
// mobile/submit 一起传给后端(2026-08-06 新增字段 payAgreementFileNo)
|
|
payAgreementFileNo: { type: String, default: '' }
|
|
})
|
|
const emit = defineEmits(['submitted'])
|
|
|
|
const verifyCode = ref('')
|
|
const sending = ref(false)
|
|
const submitting = ref(false)
|
|
const countdown = ref(0)
|
|
let timer = null
|
|
|
|
function startCountdown() {
|
|
countdown.value = 60
|
|
timer = setInterval(() => {
|
|
countdown.value -= 1
|
|
if (countdown.value <= 0) {
|
|
clearInterval(timer)
|
|
timer = null
|
|
}
|
|
}, 1000)
|
|
}
|
|
|
|
async function handleSendCode() {
|
|
// 2026-08-06 新增前置校验:mobile/channelNo/cardNo/cardName/idNo 均来自 draft-detail 响应
|
|
// (MobileDraftDetailVo),若后端对这条申请单没有返回这些字段(为空/null),即使真的发起请求也
|
|
// 必然被后端业务校验拒绝(报"渠道编号不能为空"/"手机号不能为空",或"该短信类型银行卡号、
|
|
// 户名、证件号码...必须填写"),不如提前拦截并给出明确提示,方便定位是具体某条申请单数据
|
|
// 缺失,而不是误以为是网络问题反复重试。
|
|
if (!props.mobile) {
|
|
showErrorModal('该开户申请缺少手机号信息,无法发送验证码,请联系柜员核实后重新生成二维码', '手机号缺失')
|
|
return
|
|
}
|
|
if (!props.channelNo) {
|
|
showErrorModal('该开户申请缺少渠道信息,无法发送验证码,请联系柜员核实后重新生成二维码', '渠道信息缺失')
|
|
return
|
|
}
|
|
if (!props.cardNo || !props.cardName || !props.idNo) {
|
|
showErrorModal(
|
|
'该开户申请缺少银行卡号/户名/证件号码信息,无法发送验证码,请联系柜员核实后重新生成二维码',
|
|
'开户信息缺失'
|
|
)
|
|
return
|
|
}
|
|
sending.value = true
|
|
try {
|
|
const res = await sendVerifyCodeApi({
|
|
channelNo: props.channelNo,
|
|
mobile: props.mobile,
|
|
cardNo: props.cardNo,
|
|
cardName: props.cardName,
|
|
idNo: props.idNo
|
|
})
|
|
if (res.data?.code === 200) {
|
|
showToast('验证码已发送')
|
|
startCountdown()
|
|
}
|
|
// 非200时全局响应拦截器已弹窗提示,这里无需重复处理
|
|
} finally {
|
|
sending.value = false
|
|
}
|
|
}
|
|
|
|
async function handleSubmit() {
|
|
submitting.value = true
|
|
try {
|
|
const res = await submitApplicationApi(props.applicationNo, verifyCode.value, props.payAgreementFileNo)
|
|
if (res.data?.code === 200) {
|
|
emit('submitted', res.data.data)
|
|
} else {
|
|
// 验证码错误等业务异常:全局拦截器已弹窗提示,停留本页允许重试,清空验证码便于重新输入
|
|
verifyCode.value = ''
|
|
}
|
|
} finally {
|
|
submitting.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.step-body {
|
|
padding: 0 0 4px;
|
|
position: relative;
|
|
}
|
|
.verify-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin: 16px;
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
padding: 4px 12px 4px 0;
|
|
}
|
|
.verify-input {
|
|
flex: 1;
|
|
}
|
|
.send-btn {
|
|
flex-shrink: 0;
|
|
white-space: nowrap;
|
|
}
|
|
.footer {
|
|
padding: 4px 16px 4px;
|
|
}
|
|
.submit-overlay {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.overlay-center {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
</style>
|