313 lines
8.9 KiB
JavaScript
Raw Normal View History

2026-04-10 01:49:07 +08:00
const auth = require('../../../utils/auth');
const PHONE_RE = /^1[3456789]\d{9}$/;
Page({
data: {
activeTab: 1, // 1=身份证 2=护照
2026-04-10 01:49:07 +08:00
// 上传图片 URL(远程)
idCardImageUrl: '',
idCardBackImageUrl: '',
passportImageUrl: '',
2026-04-10 01:49:07 +08:00
// 识别字段(只读,OCR 自动填充)
name: '',
idCardNumber: '',
birthDate: '',
genderOptions: [
2026-04-10 01:49:07 +08:00
{ value: 0, label: '男' },
{ value: 1, label: '女' }
],
genderIndex: 0,
2026-04-10 01:49:07 +08:00
// 护照识别额外字段(只读)
passportNumber: '',
nationality: '',
issueDate: '',
expiryDate: '',
// 联系方式
mobile: '',
verificationCode: '',
// UI 状态
2026-04-10 01:49:07 +08:00
recognizing: false,
submitting: false,
codeSending: false,
countdown: 0,
2026-04-10 01:49:07 +08:00
ocrDone: false
},
_timer: null,
onLoad() {
this.loadAuth();
},
onShow() {
const accessToken = wx.getStorageSync('accessToken') || '';
if (!accessToken) {
wx.redirectTo({ url: '/subpackages/mine/login/login' });
}
},
onUnload() {
this._clearTimer();
},
onPullDownRefresh() {
this.loadAuth().finally(() => wx.stopPullDownRefresh());
},
onBack() {
if (getCurrentPages().length > 1) {
wx.navigateBack({ delta: 1 });
} else {
wx.switchTab({ url: '/pages/mine/mine' });
}
},
onSwitchTab(e) {
const tab = Number(e.currentTarget.dataset.tab);
if (tab === this.data.activeTab) return;
this.setData({
activeTab: tab,
2026-04-10 01:49:07 +08:00
verificationCode: '',
ocrDone: false,
name: '', idCardNumber: '', birthDate: '', genderIndex: 0,
passportNumber: '', nationality: '', issueDate: '', expiryDate: '',
idCardImageUrl: '', idCardBackImageUrl: '', passportImageUrl: ''
});
2026-04-10 01:49:07 +08:00
this.loadAuth();
},
loadAuth() {
return auth
.fetchMyAuth()
.then((res) => {
const d = res && typeof res === 'object' ? res : {};
const name = d.name || d.realName || '';
const mobile = d.mobile || d.phone || '';
const idCardNumber = d.idCardNumber || d.idNumber || '';
const idCardImageUrl = d.idCardImageUrl || d.idCardFrontImageUrl || '';
const idCardBackImageUrl = d.idCardBackImageUrl || '';
2026-04-10 01:49:07 +08:00
const passportImageUrl = d.passportPhotoUrl || d.passportImageUrl || '';
const birthDate = d.birthDate || d.birthday || '';
2026-04-10 01:49:07 +08:00
const rawGender = d.gender != null ? String(d.gender) : '';
const genderIndex = (rawGender === '1' || rawGender === 'F' || rawGender === '女') ? 1 : 0;
const ocrDone = Boolean(name || idCardNumber || passportImageUrl);
this.setData({
2026-04-10 01:49:07 +08:00
name, mobile, idCardNumber,
idCardImageUrl, idCardBackImageUrl, passportImageUrl,
birthDate, genderIndex, ocrDone
});
})
.catch(() => {});
},
onChooseImage(e) {
const kind = e.currentTarget.dataset.kind;
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album', 'camera'],
success: (res) => {
const tempFilePath = res.tempFiles && res.tempFiles[0] ? res.tempFiles[0].tempFilePath : '';
if (!tempFilePath) return;
2026-04-10 01:49:07 +08:00
this._uploadAndOcr(tempFilePath, kind);
}
});
},
2026-04-10 01:49:07 +08:00
async _uploadAndOcr(tempFilePath, kind) {
wx.showLoading({ title: '上传识别中...', mask: true });
this.setData({ recognizing: true });
try {
const imageUrl = await auth.uploadFile(tempFilePath);
if (kind === 'idFront') this.setData({ idCardImageUrl: imageUrl });
else if (kind === 'idBack') this.setData({ idCardBackImageUrl: imageUrl });
else if (kind === 'passport') this.setData({ passportImageUrl: imageUrl });
if (kind === 'idFront') {
const ocr = await auth.ocrIdCard(imageUrl);
if (ocr && ocr.success === false) {
wx.showToast({ title: ocr.message || '身份证识别失败', icon: 'none' });
return;
}
const genderIndex = (ocr && (ocr.gender === '女' || ocr.gender === 'F' || ocr.gender === '1')) ? 1 : 0;
this.setData({
name: (ocr && ocr.name) || '',
idCardNumber: (ocr && ocr.idCardNumber) || '',
birthDate: (ocr && ocr.birthDate) || '',
genderIndex,
ocrDone: true
});
wx.showToast({ title: '识别成功', icon: 'success' });
} else if (kind === 'passport') {
const ocr = await auth.ocrPassport(imageUrl);
if (ocr && ocr.success === false) {
wx.showToast({ title: ocr.message || '护照识别失败', icon: 'none' });
return;
}
const genderIndex = (ocr && (ocr.gender === '女' || ocr.gender === 'F' || ocr.gender === '1')) ? 1 : 0;
this.setData({
name: (ocr && ocr.name) || '',
passportNumber: (ocr && ocr.passportNumber) || '',
nationality: (ocr && ocr.nationality) || '',
birthDate: (ocr && (ocr.birthDate || ocr.birthDateYmd)) || '',
issueDate: (ocr && (ocr.issueDate || ocr.issueDateYmd)) || '',
expiryDate: (ocr && (ocr.expiryDate || ocr.validToDate)) || '',
genderIndex,
ocrDone: true
});
wx.showToast({ title: '识别成功', icon: 'success' });
} else {
wx.showToast({ title: '上传成功', icon: 'success' });
}
} catch (err) {
wx.showToast({ title: (err && err.message) || '识别失败', icon: 'none' });
} finally {
this.setData({ recognizing: false });
wx.hideLoading();
}
},
onMobileInput(e) {
this.setData({ mobile: (e.detail.value || '').trim() });
},
onCodeInput(e) {
this.setData({ verificationCode: (e.detail.value || '').trim() });
},
onSendCodeTap() {
const { mobile, countdown, codeSending } = this.data;
if (codeSending || countdown > 0) return;
if (!PHONE_RE.test(mobile)) {
wx.showToast({ title: '请输入正确手机号', icon: 'none' });
return;
}
this.setData({ codeSending: true });
wx.showLoading({ title: '发送中...' });
auth
.sendVerificationCode(mobile)
.then(() => {
wx.showToast({ title: '验证码已发送', icon: 'success' });
this._startCountdown(60);
})
.catch(() => {
wx.showToast({ title: '发送失败', icon: 'none' });
})
.finally(() => {
this.setData({ codeSending: false });
wx.hideLoading();
});
},
_startCountdown(sec) {
this._clearTimer();
this.setData({ countdown: sec });
this._timer = setInterval(() => {
const next = this.data.countdown - 1;
if (next <= 0) {
this._clearTimer();
this.setData({ countdown: 0 });
} else {
this.setData({ countdown: next });
}
}, 1000);
},
_clearTimer() {
if (this._timer) {
clearInterval(this._timer);
this._timer = null;
}
},
onSubmitTap() {
if (this.data.submitting) return;
const {
2026-04-10 01:49:07 +08:00
activeTab, idCardImageUrl, passportImageUrl,
name, idCardNumber, birthDate,
genderOptions, genderIndex, mobile, verificationCode
} = this.data;
if (!name) {
2026-04-10 01:49:07 +08:00
wx.showToast({ title: '请先上传证件图片完成识别', icon: 'none' });
return;
}
if (!PHONE_RE.test(mobile)) {
wx.showToast({ title: '请输入正确手机号', icon: 'none' });
return;
}
if (!verificationCode) {
wx.showToast({ title: '请输入验证码', icon: 'none' });
return;
}
2026-04-10 01:49:07 +08:00
const genderValue = genderOptions[genderIndex] ? genderOptions[genderIndex].value : 0;
let payload;
if (activeTab === 1) {
2026-04-10 01:49:07 +08:00
if (!idCardImageUrl) {
wx.showToast({ title: '请上传身份证人像面', icon: 'none' });
return;
}
if (!idCardNumber) {
2026-04-10 01:49:07 +08:00
wx.showToast({ title: '请先完成身份证识别', icon: 'none' });
return;
}
2026-04-10 01:49:07 +08:00
payload = {
authType: 0,
name,
mobile,
smsCode: verificationCode,
gender: genderValue,
birthDate: birthDate || undefined,
idCardNumber,
idCardImageUrl
};
} else {
if (!passportImageUrl) {
wx.showToast({ title: '请上传护照', icon: 'none' });
return;
}
if (!birthDate) {
2026-04-10 01:49:07 +08:00
wx.showToast({ title: '请先完成护照识别', icon: 'none' });
return;
}
2026-04-10 01:49:07 +08:00
payload = {
authType: 1,
name,
mobile,
smsCode: verificationCode,
gender: genderValue,
birthDate,
passportPhotoUrl: passportImageUrl
};
}
this.setData({ submitting: true });
wx.showLoading({ title: '提交中...' });
auth
.submitMyAuth(payload)
.then(() => {
wx.showToast({ title: '提交成功', icon: 'success' });
2026-04-10 01:49:07 +08:00
setTimeout(() => wx.navigateBack({ delta: 1 }), 600);
})
.catch((err) => {
wx.showToast({ title: (err && err.message) || '提交失败', icon: 'none' });
})
.finally(() => {
this.setData({ submitting: false });
wx.hideLoading();
});
}
});