This commit is contained in:
18631081161 2026-01-28 00:58:48 +08:00
parent 914b5b3d2b
commit 7b0b5ac9a4
2 changed files with 103 additions and 169 deletions

View File

@ -103,31 +103,35 @@
</view>
</view>
<!-- 步骤2: 身份证上传页面 (Requirements 12.2, 12.3) -->
<view v-if="currentStep === 2" class="step-upload">
<view class="upload-content">
<!-- 提示文字 -->
<view class="upload-tip-text">
<text class="tip-main">请上传您的身份证正反面</text>
<text class="tip-sub">(我们仅用于实名认证)</text>
<!-- 步骤2: 身份信息输入页面 -->
<view v-if="currentStep === 2" class="step-input">
<view class="input-content">
<!-- 身份证号输入 -->
<view class="input-group">
<text class="input-label">请输入您的身份证号码</text>
<view class="input-box">
<input
type="idcard"
v-model="idCardNumber"
placeholder="请输入身份证号码"
maxlength="18"
class="input-field"
/>
</view>
</view>
<!-- 身份证正面 -->
<view class="upload-card-new" @click="chooseIdCardFront">
<view class="card-frame">
<image v-if="idCardFront" :src="idCardFront" mode="aspectFill" class="card-image-uploaded" />
<image v-else src="/static/real_name_card_1.png" mode="aspectFit" class="card-placeholder-img" />
<!-- 姓名输入 -->
<view class="input-group">
<text class="input-label">请输入您的姓名</text>
<view class="input-box">
<input
type="text"
v-model="realName"
placeholder="请输入姓名"
maxlength="20"
class="input-field"
/>
</view>
<text class="card-label-new">拍照上传身份证正面</text>
</view>
<!-- 身份证反面 -->
<view class="upload-card-new" @click="chooseIdCardBack">
<view class="card-frame">
<image v-if="idCardBack" :src="idCardBack" mode="aspectFill" class="card-image-uploaded" />
<image v-else src="/static/real_name_card_2.png" mode="aspectFit" class="card-placeholder-img" />
</view>
<text class="card-label-new">拍照上传身份证反面</text>
</view>
</view>
</view>
@ -214,16 +218,13 @@
maskIdNumber
} from '@/utils/format.js'
import {
get
get,
post
} from '@/api/request.js'
import {
getToken
} from '@/utils/storage.js'
import Loading from '@/components/Loading/index.vue'
import config from '@/config/index.js'
// API
const BASE_URL = config.API_BASE_URL
export default {
name: 'RealnamePage',
@ -247,9 +248,9 @@
// -
const verificationFee = computed(() => configStore.realNamePrice || 88)
//
const idCardFront = ref('')
const idCardBack = ref('')
//
const idCardNumber = ref('')
const realName = ref('')
//
const verificationResult = ref(null)
@ -277,8 +278,9 @@
//
const canSkipPayment = computed(() => userStore.isMember || isPaid.value)
// 18 +
const canSubmit = computed(() => {
return idCardFront.value && idCardBack.value
return idCardNumber.value.length === 18 && realName.value.trim().length > 0
})
const maskedName = computed(() => {
@ -455,54 +457,39 @@
}
/**
* 选择身份证正面照片
*/
const chooseIdCardFront = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
idCardFront.value = res.tempFilePaths[0]
}
})
}
/**
* 选择身份证反面照片
*/
const chooseIdCardBack = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
idCardBack.value = res.tempFilePaths[0]
}
})
}
/**
* 提交实名认证 (Requirements 12.3)
* 提交实名认证二要素验证姓名+身份证号
*/
const handleSubmitVerification = async () => {
if (!canSubmit.value || submitting.value) return
//
const idCardRegex = /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/
if (!idCardRegex.test(idCardNumber.value)) {
uni.showToast({
title: '请输入正确的身份证号',
icon: 'none'
})
return
}
submitting.value = true
try {
//
const result = await uploadIdCards()
//
const result = await post('/realname/submit', {
realName: realName.value.trim(),
idCard: idCardNumber.value.trim()
})
if (result && (result.success || result.code === 0)) {
if (result && (result.success || result.code === 0) && result.data?.success) {
//
userStore.setRealNameStatus(true)
verificationResult.value = {
name: result.data.name,
idNumber: result.data.idNumber
name: result.data.maskedName,
idNumber: result.data.maskedIdCard
}
// (Requirements 12.4)
//
currentStep.value = 3
uni.showToast({
@ -511,7 +498,7 @@
})
} else {
uni.showToast({
title: result?.message || '认证失败,请重试',
title: result?.data?.message || result?.message || '认证失败,请检查信息是否正确',
icon: 'none'
})
}
@ -526,103 +513,6 @@
}
}
/**
* 上传身份证照片进行实名认证
*/
const uploadIdCards = () => {
return new Promise((resolve, reject) => {
const token = getToken()
//
uni.uploadFile({
url: `${BASE_URL}/api/app/realname/verify`,
filePath: idCardFront.value,
name: 'frontImage',
header: {
'Authorization': `Bearer ${token}`
},
success: async (uploadRes) => {
if (uploadRes.statusCode === 200) {
try {
const response = JSON.parse(uploadRes.data)
// API
if (response.success || response.code === 0) {
const data = response.data
//
if (data.needBackImage) {
const backResult = await uploadBackImage(token)
resolve(backResult)
} else {
resolve(response)
}
} else {
reject(new Error(response.message || '认证失败'))
}
} catch (e) {
reject(new Error('解析响应失败'))
}
} else if (uploadRes.statusCode === 401) {
reject(new Error('未授权,请重新登录'))
} else {
try {
const errorData = JSON.parse(uploadRes.data)
reject(new Error(errorData.message || '认证失败'))
} catch (e) {
reject(new Error('认证失败'))
}
}
},
fail: (err) => {
console.error('上传失败:', err)
reject(new Error('网络连接失败'))
}
})
})
}
/**
* 上传身份证反面
*/
const uploadBackImage = (token) => {
return new Promise((resolve, reject) => {
uni.uploadFile({
url: `${BASE_URL}/api/app/realname/verify/back`,
filePath: idCardBack.value,
name: 'backImage',
header: {
'Authorization': `Bearer ${token}`
},
success: (uploadRes) => {
if (uploadRes.statusCode === 200) {
try {
const response = JSON.parse(uploadRes.data)
if (response.success || response.code === 0) {
resolve(response)
} else {
reject(new Error(response.message || '上传失败'))
}
} catch (e) {
reject(new Error('解析响应失败'))
}
} else {
try {
const errorData = JSON.parse(uploadRes.data)
reject(new Error(errorData.message || '上传失败'))
} catch (e) {
reject(new Error('上传失败'))
}
}
},
fail: () => {
reject(new Error('网络连接失败'))
}
})
})
}
/**
* 完成认证返回上一页
*/
@ -679,8 +569,8 @@
submitting,
currentStep,
verificationFee,
idCardFront,
idCardBack,
idCardNumber,
realName,
isVerified,
canSubmit,
canSkipPayment,
@ -692,8 +582,6 @@
handleNextStep,
handleContactService,
handleStepClick,
chooseIdCardFront,
chooseIdCardBack,
handleSubmitVerification,
handleDone
}
@ -1190,7 +1078,44 @@
}
}
// 2:
// 2:
.step-input {
.input-content {
padding: 40rpx 30rpx;
display: flex;
flex-direction: column;
gap: 40rpx;
.input-group {
background: #fff;
border-radius: 24rpx;
padding: 32rpx;
.input-label {
display: block;
font-size: 30rpx;
color: #333;
font-weight: 500;
margin-bottom: 24rpx;
}
.input-box {
background: #F6F8FA;
border-radius: 16rpx;
padding: 0 24rpx;
.input-field {
width: 100%;
height: 96rpx;
font-size: 32rpx;
color: #333;
}
}
}
}
}
// 2:
.step-upload {
.upload-content {
padding: 40rpx 30rpx;

View File

@ -98,5 +98,14 @@
"SecretId": "AKIDVyMfzKZdZP8zkNyOdsFuSsBJDB7EScs0",
"SecretKey": "89GWr7JPWYTL8ueHlAYowGZnvzKZjqs9",
"Region": "ap-shanghai"
},
"RealName": {
"Provider": "Tencent",
"Tencent": {
"SecretId": "AKIDVyMfzKZdZP8zkNyOdsFuSsBJDB7EScs0",
"SecretKey": "89GWr7JPWYTL8ueHlAYowGZnvzKZjqs9",
"Region": "ap-shanghai",
"SimilarityThreshold": 80
}
}
}