Files
danyang-match/h5-demo/src/pages/auth/VerificationPage.vue
T
WorkBuddy 69ebf33e18
CI/CD Pipeline / Backend Build & Test (push) Canceled after 0s
CI/CD Pipeline / Admin Web Build (push) Canceled after 0s
CI/CD Pipeline / Mini Program Compile Check (push) Canceled after 0s
CI/CD Pipeline / Migration Validation (push) Canceled after 0s
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Canceled after 0s
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Canceled after 0s
CI/CD Pipeline / E2E (live stack) (push) Canceled after 0s
release: freeze demo v1.1.0 2026-10-19
2026-10-19 20:36:22 +08:00

229 lines
5.9 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>
<PageLayout title="实名认证">
<div class="vf">
<UiLoading v-if="loading" text="正在读取认证状态…" />
<UiErrorState v-else-if="error" @retry="load" />
<template v-else>
<!-- 已认证 -->
<div v-if="verified" class="vf__done">
<div class="vf__done-icon">✓</div>
<div class="vf__done-title">已完成实名认证</div>
<div class="vf__done-desc">您的身份信息已通过核验,可继续完善资料。</div>
<div class="vf__actions">
<van-button type="primary" block round @click="router.replace('/profile/basic')">
完善资料
</van-button>
</div>
</div>
<!-- 未认证表单 -->
<template v-else>
<div class="vf__hero">
<div class="vf__title">实名认证</div>
<div class="vf__subtitle">真实身份帮助我们提供更安全的公益婚恋服务</div>
</div>
<div class="card">
<van-field
v-model="realName"
label="姓名"
placeholder="请输入真实姓名"
:border="false"
maxlength="20"
@update:model-value="errorText = ''"
/>
<van-field
v-model="idCardNumber"
label="身份证号"
placeholder="请输入18位身份证号码"
maxlength="18"
@update:model-value="onIdInput"
/>
</div>
<van-checkbox v-model="agreed" class="vf__agree" icon-size="16">
我已阅读并同意《用户服务协议》和《隐私政策》
</van-checkbox>
<p v-if="errorText" class="vf__error">{{ errorText }}</p>
<div class="vf__actions">
<van-button
type="primary"
block
round
:loading="submitting"
:disabled="!agreed || submitting"
@click="onSubmit"
>
提交认证
</van-button>
</div>
<div class="vf__tips">
<div class="vf__tips-title">认证说明</div>
<div class="vf__tip">· 身份信息仅用于实名认证,不会向其他用户展示</div>
<div class="vf__tip">· 实名认证是平台安全的重要保障</div>
<div class="vf__tip">· 未满 18 周岁不能使用本平台服务</div>
</div>
</template>
</template>
</div>
</PageLayout>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { verificationService } from '@/api/services'
import { useAppStore } from '@/stores/app'
import { useUserStore } from '@/stores/user'
import PageLayout from '@/layouts/PageLayout.vue'
import UiLoading from '@/components/UiLoading.vue'
import UiErrorState from '@/components/UiErrorState.vue'
const router = useRouter()
const appStore = useAppStore()
const userStore = useUserStore()
const loading = ref(true)
const error = ref(false)
const verified = ref(false)
const realName = ref('')
const idCardNumber = ref('')
const agreed = ref(false)
const submitting = ref(false)
const errorText = ref('')
function onIdInput(value: string) {
idCardNumber.value = value.replace(/\s/g, '')
errorText.value = ''
}
async function load() {
loading.value = true
error.value = false
try {
const status: any = await verificationService.getStatus()
verified.value = !!(status?.verified || status?.status === 'verified' || status?.status === 'approved')
} catch {
error.value = true
} finally {
loading.value = false
}
}
async function onSubmit() {
errorText.value = ''
if (!agreed.value) {
errorText.value = '请先阅读并同意协议'
return
}
if (!realName.value || realName.value.length < 2) {
errorText.value = '请输入真实姓名'
return
}
if (idCardNumber.value.length !== 18) {
errorText.value = '请输入正确的18位身份证号码'
return
}
submitting.value = true
try {
await verificationService.submit({ realName: realName.value, idCardNumber: idCardNumber.value })
appStore.toastSuccess('认证成功')
userStore.userState = { ...(userStore.userState || {}), verified: true }
router.replace('/profile/basic')
} catch (err: any) {
errorText.value = err?.message || '认证失败,请重试'
} finally {
submitting.value = false
}
}
onMounted(load)
</script>
<style scoped>
.vf {
padding: 16px;
}
.vf__hero {
padding: 8px 4px 16px;
}
.vf__title {
font-size: 20px;
font-weight: 600;
color: var(--mini-text-strong);
}
.vf__subtitle {
font-size: 13px;
color: var(--mini-text-secondary);
margin-top: 6px;
}
.card {
background: var(--mini-surface);
border-radius: var(--mini-radius);
box-shadow: var(--mini-shadow);
overflow: hidden;
}
.vf__agree {
margin-top: 14px;
font-size: 12px;
color: var(--mini-text-secondary);
}
.vf__error {
color: var(--mini-danger);
font-size: 13px;
margin: 12px 4px 0;
}
.vf__actions {
margin-top: 20px;
}
.vf__tips {
margin-top: 24px;
background: rgba(79, 140, 255, 0.06);
border: 1px solid rgba(79, 140, 255, 0.14);
border-radius: var(--mini-radius);
padding: 14px;
}
.vf__tips-title {
font-size: 13px;
font-weight: 600;
color: var(--mini-text-strong);
margin-bottom: 8px;
}
.vf__tip {
font-size: 12px;
color: var(--mini-text-secondary);
line-height: 1.8;
}
.vf__done {
text-align: center;
padding: 40px 16px;
}
.vf__done-icon {
width: 64px;
height: 64px;
border-radius: 50%;
margin: 0 auto 16px;
background: var(--mini-success);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 30px;
}
.vf__done-title {
font-size: 18px;
font-weight: 600;
color: var(--mini-text-strong);
}
.vf__done-desc {
font-size: 13px;
color: var(--mini-text-secondary);
margin-top: 8px;
}
</style>