// pages/auth/real-name-auth.js import http from '../../../utils/api' Page({ data: { // 表单数据 name: '', idNumber: '', // 焦点状态 nameFocus: false, idNumberFocus: false, // 错误提示 nameError: '', idNumberError: '', // 提示显示控制 showNameHint: false, showIdNumberHint: false, // 验证状态 isNameValid: false, isIdNumberValid: false, // 协议状态 agreed: false, // 提交状态 canSubmit: false, isSubmitting: false, // 进度条 currentStep: 1, lineProgress1: 0, lineProgress2: 0, // 弹窗数据 showModal: false, modalTitle: '', modalContent: '', // 成功弹窗数据 showSuccessModal: false, maskedIdNumber: '', // 错误弹窗数据 showErrorModal: false, errorTitle: '', errorMessage: '' }, onLoad() { // 页面加载时启动进度条动画 setTimeout(() => { this.setData({ lineProgress1: 50 }); }, 600); }, // 姓名输入处理 onNameInput(e) { const value = e.detail.value.trim(); let error = ''; let showHint = true; let isValid = false; if (value) { if (!/^[\u4e00-\u9fa5]{2,10}$/.test(value)) { error = '姓名应为2-10个汉字'; } else { isValid = true; // 验证通过时保持提示显示,但无错误 } } else { // 内容为空时显示正常提示 error = ''; } this.setData({ name: value, nameError: error, showNameHint: showHint, isNameValid: isValid }, () => { this.checkForm(); }); }, onNameFocus() { this.setData({ nameFocus: true, showNameHint: true // 获得焦点时显示提示 }); }, onNameBlur() { const { name } = this.data; this.setData({ nameFocus: false, // 失去焦点时,如果内容为空或验证失败,保持提示显示 showNameHint: !!(name && !this.data.isNameValid) }); }, // 清除姓名 clearName() { this.setData({ name: '', nameError: '', showNameHint: false, isNameValid: false }, () => { this.checkForm(); }); }, // 身份证号输入处理 onIdNumberInput(e) { const value = e.detail.value.trim().toUpperCase(); let error = ''; let showHint = true; let isValid = false; if (value) { if (value.length < 18) { error = '还需输入' + (18 - value.length) + '位'; } else if (value.length === 18) { if (this.validateIdNumber(value)) { isValid = true; // 验证通过时保持提示显示,但无错误 } else { error = '身份证号格式不正确'; } } } else { // 内容为空时显示正常提示 error = ''; } this.setData({ idNumber: value, idNumberError: error, showIdNumberHint: showHint, isIdNumberValid: isValid }, () => { this.checkForm(); }); }, onIdNumberFocus() { this.setData({ idNumberFocus: true, showIdNumberHint: true // 获得焦点时显示提示 }); }, onIdNumberBlur() { const { idNumber } = this.data; let error = ''; let isValid = false; // 最终验证 if (idNumber) { if (idNumber.length < 18) { error = '还需输入' + (18 - idNumber.length) + '位'; } else if (idNumber.length === 18) { if (this.validateIdNumber(idNumber)) { isValid = true; } else { error = '身份证号格式不正确'; } } } this.setData({ idNumberFocus: false, idNumberError: error, isIdNumberValid: isValid, // 失去焦点时,如果内容为空或验证失败,保持提示显示 showIdNumberHint: !!(idNumber && !isValid) }); }, // 清除身份证号 clearIdNumber() { this.setData({ idNumber: '', idNumberError: '', showIdNumberHint: false, isIdNumberValid: false }, () => { this.checkForm(); }); }, // 身份证验证函数 validateIdNumber(idNumber) { // 基础格式验证 if (!/^\d{17}[\dXx]$/.test(idNumber)) { return false; } // 地区码验证(简化的验证,实际应该更严谨) const areaCode = idNumber.substring(0, 2); const validAreaCodes = ['11', '12', '13', '14', '15', '21', '22', '23', '31', '32', '33', '34', '35', '36', '37', '41', '42', '43', '44', '45', '46', '50', '51', '52', '53', '54', '61', '62', '63', '64', '65']; if (!validAreaCodes.includes(areaCode)) { return false; } // 出生日期验证 const year = parseInt(idNumber.substring(6, 10)); const month = parseInt(idNumber.substring(10, 12)); const day = parseInt(idNumber.substring(12, 14)); const currentYear = new Date().getFullYear(); if (year < 1900 || year > currentYear) return false; if (month < 1 || month > 12) return false; if (day < 1 || day > 31) return false; // 校验码验证 const checkCode = idNumber.charAt(17).toUpperCase(); const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; let sum = 0; for (let i = 0; i < 17; i++) { sum += parseInt(idNumber.charAt(i)) * weights[i]; } const mod = sum % 11; return checkCode === checkCodes[mod]; }, // 协议处理 toggleAgreement() { const newAgreed = !this.data.agreed; this.setData({ agreed: newAgreed }, () => { this.checkForm(); }); }, // 显示协议弹窗 showAgreementModal() { const title = '用户服务协议'; const content = `欢迎您使用"与牧同行"服务!\n\n在使用我们的服务前,请您仔细阅读并同意以下协议:\n\n1. 服务条款\n您在使用与牧同行提供的各项服务时,应当遵守相关法律法规,不得从事任何非法行为。\n\n2. 用户责任\n您需要保证所提供信息的真实性、准确性和完整性。\n\n3. 服务变更\n我们保留随时修改、暂停或终止服务的权利。\n\n4. 免责声明\n在法律法规允许的最大范围内,我们对因使用服务而产生的任何间接损失不承担责任。\n\n5. 法律适用\n本协议的订立、执行和解释及争议的解决均适用中华人民共和国法律。\n\n请您确保已阅读并理解以上条款。`; this.showModal(title, content); }, // 显示隐私弹窗 showPrivacyModal() { const title = '隐私保护协议'; const content = `我们非常重视您的隐私保护,请您仔细阅读以下隐私政策:\n\n1. 信息收集\n我们仅收集为您提供服务所必需的信息,包括姓名、身份证号等实名信息。\n\n2. 信息使用\n您的信息仅用于身份验证和服务提供,不会用于其他商业用途。\n\n3. 信息保护\n我们采用先进的安全技术保护您的信息,防止未经授权的访问、使用或泄露。\n\n4. 信息共享\n除非获得您的明确同意,我们不会向第三方共享您的个人信息。\n\n5. 您的权利\n您可以随时查看、更正或删除您的个人信息。\n\n6. 政策更新\n我们可能会不时更新本隐私政策,更新后的政策将在本页面公布。\n\n我们承诺严格遵守相关法律法规,保护您的个人信息安全。`; this.showModal(title, content); }, // 显示弹窗 showModal(title, content) { this.setData({ modalTitle: title, modalContent: content, showModal: true }); }, // 关闭弹窗 closeModal() { this.setData({ showModal: false }); }, // 显示错误弹窗 showErrorModal(title, message) { this.setData({ errorTitle: title || '认证失败', errorMessage: message || '请检查信息后重试', showErrorModal: true }); }, // 关闭错误弹窗 closeErrorModal() { this.setData({ showErrorModal: false, isSubmitting: false // 关闭错误弹窗时重置提交状态 }); }, // 阻止事件冒泡 stopPropagation(e) { // 阻止冒泡 }, // 检查表单 checkForm() { const { isNameValid, isIdNumberValid, agreed } = this.data; const isValid = isNameValid && isIdNumberValid && agreed; this.setData({ canSubmit: isValid }); }, // 提交认证 async submitAuth() { if (!this.data.canSubmit || this.data.isSubmitting) return; // 最终验证 const { name, idNumber } = this.data; if (!/^[\u4e00-\u9fa5]{2,10}$/.test(name)) { this.setData({ nameError: '姓名应为2-10个汉字', showNameHint: true, canSubmit: false }); return; } if (!this.validateIdNumber(idNumber)) { this.setData({ idNumberError: '身份证号格式不正确', showIdNumberHint: true, canSubmit: false }); return; } this.setData({ isSubmitting: true, currentStep: 2, lineProgress1: 100, lineProgress2: 50 }); // 显示加载动画 wx.showLoading({ title: '正在验证...', mask: true }); try { // 调用实名认证接口 const result = await this.callRealNameApi(name, idNumber); wx.hideLoading(); if (result.success) { // 处理身份证号脱敏显示 const maskedId = idNumber.substring(0, 4) + '**********' + idNumber.substring(14); // 显示成功弹窗 this.showSuccessModal(maskedId); this.setData({ isSubmitting: false, currentStep: 3, lineProgress2: 100 }); } else { // 接口返回失败 this.handleApiError(result); } } catch (error) { wx.hideLoading(); this.setData({ isSubmitting: false, currentStep: 1, lineProgress2: 0 }); this.showErrorModal('网络错误', '认证请求失败,请检查网络连接后重试'); console.error('实名认证错误:', error); } }, // 调用实名认证API async callRealNameApi(realName, idCard) { return new Promise((resolve, reject) => { http.realName({ data: { realName: realName, // 姓名字段 idCard: idCard // 身份证号字段 }, success: (res) => { console.log('API响应:', res); // 根据实际API响应结构调整 if (res.code === 200 || res.code === 0) { resolve({ success: true, data: res.data || {} }); } else { resolve({ success: false, code: res.code, message: res.msg || '认证失败' }); } }, fail: (err) => { reject(err); } }); }); }, // 处理API错误 handleApiError(result) { console.log('API错误:', result); this.setData({ isSubmitting: false, currentStep: 1, lineProgress2: 0 }); // 根据错误码显示不同提示 let title = '认证失败'; let message = result.message || '请检查信息后重试'; // 根据不同的错误码定制提示信息 if (result.code === 500) { message = result.message || '服务器内部错误,请稍后重试'; } else if (result.code === 400) { message = result.message || '请求参数错误,请检查填写的信息'; } else if (result.code === 401) { message = result.message || '身份验证失败,请重新登录'; } else if (result.code === 403) { message = result.message || '认证信息不正确,请核对姓名和身份证号'; } this.showErrorModal(title, message); }, // 显示成功弹窗 showSuccessModal(maskedId) { this.setData({ maskedIdNumber: maskedId, showSuccessModal: true }); }, // 关闭成功弹窗 closeSuccessModal() { this.setData({ showSuccessModal: false }); }, // 返回 goToHome() { this.closeSuccessModal(); wx.switchTab({ url: '/pages/personal/personal' }); } });