完善:多步 H5 授权流程

This commit is contained in:
2026-01-25 19:01:17 +08:00
parent 0f90faa595
commit d1b2388616
6 changed files with 689 additions and 90 deletions

View File

@@ -1075,3 +1075,239 @@ body.modal-open {
.back-home-btn:active { .back-home-btn:active {
transform: translateY(0); transform: translateY(0);
} }
/* ==================== 授权流程样式 ==================== */
.auth-flow-container {
max-width: 800px;
margin: 0 auto;
padding: 16px;
min-height: 100vh;
}
/* 授权进度区域 */
.auth-progress-section {
background: #fff;
border-radius: 12px;
padding: 16px;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.auth-progress-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #f0f0f0;
}
.auth-progress-title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.auth-progress-count {
font-size: 14px;
color: #666;
}
.auth-progress-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.auth-progress-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
background: #f8f9fa;
border-radius: 8px;
transition: all 0.3s ease;
}
.auth-progress-item.active {
background: #e8f0ff;
border: 1px solid #3474fe;
}
.auth-progress-item.completed {
background: #f0fff4;
}
.auth-progress-item.completed .auth-progress-icon {
color: #19be6b;
}
.auth-progress-item.completed .auth-progress-status {
color: #19be6b;
}
.auth-progress-item.failed {
background: #fff5f5;
}
.auth-progress-item.failed .auth-progress-icon {
color: #ff4444;
}
.auth-progress-item.failed .auth-progress-status {
color: #ff4444;
}
.auth-progress-item.timeout {
background: #fffbe6;
}
.auth-progress-item.timeout .auth-progress-icon {
color: #faad14;
}
.auth-progress-item.timeout .auth-progress-status {
color: #faad14;
}
.auth-progress-icon {
font-size: 18px;
width: 24px;
text-align: center;
color: #999;
}
.auth-progress-item.active .auth-progress-icon {
color: #3474fe;
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.auth-progress-name {
flex: 1;
font-size: 14px;
color: #333;
font-weight: 500;
}
.auth-progress-status {
font-size: 12px;
color: #999;
}
.auth-progress-item.active .auth-progress-status {
color: #3474fe;
}
/* iframe 区域 */
.auth-iframe-section {
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.auth-iframe-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px 16px;
background: linear-gradient(135deg, #3474fe 0%, #5b8def 100%);
color: #fff;
}
.auth-iframe-title {
font-size: 16px;
font-weight: 600;
}
.auth-iframe-hint {
font-size: 12px;
opacity: 0.9;
}
.auth-iframe {
width: 100%;
height: calc(100vh - 350px);
min-height: 400px;
border: none;
display: block;
}
/* 授权完成区域 */
.auth-complete-section {
background: #fff;
border-radius: 12px;
padding: 40px 20px;
text-align: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.auth-complete-icon {
width: 72px;
height: 72px;
line-height: 72px;
margin: 0 auto 20px;
background: linear-gradient(135deg, #19be6b 0%, #47d88a 100%);
color: #fff;
font-size: 36px;
border-radius: 50%;
box-shadow: 0 4px 12px rgba(25, 190, 107, 0.3);
}
.auth-complete-title {
font-size: 22px;
font-weight: 600;
color: #333;
margin-bottom: 8px;
}
.auth-complete-desc {
font-size: 14px;
color: #666;
margin-bottom: 24px;
}
.auth-countdown {
font-size: 14px;
color: #999;
margin-bottom: 20px;
}
.auth-countdown #countdownSeconds {
font-size: 24px;
font-weight: 600;
color: #3474fe;
margin: 0 4px;
}
.auth-redirect-btn {
display: inline-block;
padding: 14px 48px;
background: linear-gradient(135deg, #3474fe 0%, #5b8def 100%);
color: #fff;
font-size: 16px;
font-weight: 500;
border: none;
border-radius: 24px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(52, 116, 254, 0.3);
}
.auth-redirect-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(52, 116, 254, 0.4);
}
.auth-redirect-btn:active {
transform: translateY(0);
}

View File

@@ -27,6 +27,9 @@ export const API_CONFIG = {
SUBMIT_DRAFT_FORM: '/partnerh5/save_draft', SUBMIT_DRAFT_FORM: '/partnerh5/save_draft',
GET_DRAFT_FORM: '/partnerh5/get_draft', GET_DRAFT_FORM: '/partnerh5/get_draft',
// 授权状态查询接口
CHECK_AUTH_STATUS: '/partnerh5/check_auth_status',
// 区域数据接口 // 区域数据接口
AREA_LIST: '/partnerh5/area_list', AREA_LIST: '/partnerh5/area_list',
}, },

View File

@@ -9,6 +9,7 @@ import { DraftManager, FormIdGenerator, UserCache } from '../core/index.js';
import { ASSET_CONFIG, BASIC_INFO_CONFIG, PROVINCE_CITY_DATA, CACHE_CONFIG } from '../config/index.js'; import { ASSET_CONFIG, BASIC_INFO_CONFIG, PROVINCE_CITY_DATA, CACHE_CONFIG } from '../config/index.js';
import { showToast } from '../ui/toast.js'; import { showToast } from '../ui/toast.js';
import { AreaService } from '../services/area.service.js'; import { AreaService } from '../services/area.service.js';
import { AuthFlowService, AUTH_STATUS } from '../services/index.js';
export class BasicInfoPage { export class BasicInfoPage {
constructor() { constructor() {
@@ -655,85 +656,242 @@ export class BasicInfoPage {
} }
/** /**
* 显示提交成功页面 * 显示提交成功页面(授权流程)
* @param {Object} data - 返回数据 { formdataid, h5Urls } * @param {Object} data - 返回数据 { formdataid, h5Urls, redirectUrl }
*/ */
showSubmitSuccessDialog(data) { showSubmitSuccessDialog(data) {
const h5Urls = data.h5Urls; const { formdataid, h5Urls, redirectUrl } = data;
const urlEntries = Object.entries(h5Urls);
// 隐藏表单内容 // 隐藏表单相关的所有内容
document.getElementById('assetList').style.display = 'none'; const topCard = document.querySelector('.top-card');
document.getElementById('basicInfoSection').style.display = 'none'; const assetSection = document.querySelector('.asset-section');
this.elements.submitBtn.style.display = 'none'; const basicInfoSection = document.getElementById('basicInfoSection');
const bottomSection = document.getElementById('bottomSection');
// 创建成功提示区域 if (topCard) topCard.style.display = 'none';
const successContainer = document.createElement('div'); if (assetSection) assetSection.style.display = 'none';
successContainer.className = 'submit-success-container'; if (basicInfoSection) basicInfoSection.style.display = 'none';
successContainer.innerHTML = ` if (bottomSection) bottomSection.style.display = 'none';
<div class="success-header">
<div class="success-icon">✅</div>
<h2>信息提交成功</h2>
<p class="formdata-id">表单ID${data.formdataid}</p>
</div>
${urlEntries.length > 0 ? ` // 创建授权流程容器
<div class="iframe-container"> const authContainer = document.createElement('div');
${urlEntries.map(([name, url], index) => ` authContainer.className = 'auth-flow-container';
<div class="iframe-wrapper ${index === 0 ? 'active' : ''}" data-index="${index}"> authContainer.id = 'authFlowContainer';
<div class="iframe-header">
<span class="product-name">${name}</span> // 如果没有 h5Urls显示成功提示
<span class="iframe-hint">请在下方完成申请流程</span> if (!h5Urls || h5Urls.length === 0) {
</div> authContainer.innerHTML = `
<iframe src="${url}" class="product-iframe" frameborder="0"></iframe> <div class="auth-complete-section">
<div class="auth-complete-icon">✓</div>
<div class="auth-complete-title">信息提交成功</div>
<div class="auth-complete-desc">您的申请已提交成功!</div>
${redirectUrl ? `
<div class="auth-countdown">
<span id="countdownSeconds">5</span> 秒后自动跳转...
</div>
<button class="auth-redirect-btn" id="redirectNowBtn">立即跳转</button>
` : `
<button class="auth-redirect-btn" onclick="window.location.reload()">返回首页</button>
`}
</div>
`;
const mainContainer = document.querySelector('.container') || document.body;
mainContainer.insertBefore(authContainer, mainContainer.firstChild);
// 如果有 redirectUrl启动倒计时
if (redirectUrl) {
this.startFinalCountdown(redirectUrl);
}
return;
}
// 有 h5Urls显示授权流程界面
authContainer.innerHTML = `
<div class="auth-progress-section">
<div class="auth-progress-header">
<span class="auth-progress-title">授权进度</span>
<span class="auth-progress-count">(<span id="currentIndex">1</span>/${h5Urls.length})</span>
</div>
<div class="auth-progress-list" id="authProgressList">
${h5Urls.map((item, index) => `
<div class="auth-progress-item" data-apicode="${item.apicode}" data-index="${index}">
<span class="auth-progress-icon" id="icon-${item.apicode}">○</span>
<span class="auth-progress-name">${item.apiname}</span>
<span class="auth-progress-status" id="status-${item.apicode}">等待中</span>
</div> </div>
`).join('')} `).join('')}
${urlEntries.length > 1 ? `
<div class="product-tabs">
${urlEntries.map(([name, url], index) => `
<button class="product-tab ${index === 0 ? 'active' : ''}" data-index="${index}">
${name}
</button>
`).join('')}
</div>
` : ''}
</div> </div>
` : ` </div>
<div class="no-urls-message"> <div class="auth-iframe-section">
<p>您的申请已提交成功!</p> <div class="auth-iframe-header">
<p>我们会尽快处理您的申请。</p> <span class="auth-iframe-title" id="currentProductName">${h5Urls[0].apiname}</span>
<span class="auth-iframe-hint">请在下方完成授权</span>
</div> </div>
`} <iframe src="" class="auth-iframe" id="authIframe" frameborder="0"></iframe>
<div class="success-footer">
<button onclick="window.location.reload()" class="back-home-btn">返回首页</button>
</div> </div>
`; `;
// 插入到页面顶部
const mainContainer = document.querySelector('.container') || document.body; const mainContainer = document.querySelector('.container') || document.body;
mainContainer.insertBefore(successContainer, mainContainer.firstChild); mainContainer.insertBefore(authContainer, mainContainer.firstChild);
// 绑定 Tab 切换事件 // 启动授权流程
if (urlEntries.length > 1) { this.runAuthFlow(formdataid, h5Urls, redirectUrl);
const tabs = successContainer.querySelectorAll('.product-tab'); }
const iframes = successContainer.querySelectorAll('.iframe-wrapper');
tabs.forEach(tab => { /**
tab.addEventListener('click', () => { * 执行授权流程
const index = parseInt(tab.dataset.index); * @param {number} formdataid - 表单数据ID
* @param {Array} h5Urls - H5 URL 列表
* @param {string} redirectUrl - 最终跳转 URL
*/
async runAuthFlow(formdataid, h5Urls, redirectUrl) {
const iframe = document.getElementById('authIframe');
const currentIndexEl = document.getElementById('currentIndex');
const currentProductNameEl = document.getElementById('currentProductName');
// 更新 Tab 状态 await AuthFlowService.startAuthFlow(formdataid, h5Urls, {
tabs.forEach(t => t.classList.remove('active')); // 开始处理某个产品
tab.classList.add('active'); onStart: (item, index) => {
console.log('[BasicInfoPage] 开始处理:', item.apiname);
// 更新进度显示
if (currentIndexEl) {
currentIndexEl.textContent = index + 1;
}
if (currentProductNameEl) {
currentProductNameEl.textContent = item.apiname;
}
// 更新 iframe 显示 // 更新进度列表状态
iframes.forEach(iframe => iframe.classList.remove('active')); const iconEl = document.getElementById(`icon-${item.apicode}`);
iframes[index].classList.add('active'); const statusEl = document.getElementById(`status-${item.apicode}`);
if (iconEl) iconEl.textContent = '●';
if (statusEl) statusEl.textContent = '授权中...';
// 高亮当前项
document.querySelectorAll('.auth-progress-item').forEach(el => {
el.classList.remove('active');
}); });
const currentItem = document.querySelector(`.auth-progress-item[data-apicode="${item.apicode}"]`);
if (currentItem) {
currentItem.classList.add('active');
}
},
// iframe 切换
onIframeChange: (url) => {
console.log('[BasicInfoPage] iframe 切换到:', url);
if (iframe && url) {
iframe.src = url;
}
},
// 状态更新
onProgress: (item, index, status) => {
console.log('[BasicInfoPage] 状态更新:', item.apiname, status);
},
// 单个完成
onComplete: (item, index, result) => {
console.log('[BasicInfoPage] 完成:', item.apiname, result);
const iconEl = document.getElementById(`icon-${item.apicode}`);
const statusEl = document.getElementById(`status-${item.apicode}`);
const progressItem = document.querySelector(`.auth-progress-item[data-apicode="${item.apicode}"]`);
if (result.timeout) {
// 超时
if (iconEl) iconEl.textContent = '○';
if (statusEl) statusEl.textContent = '已超时';
if (progressItem) progressItem.classList.add('timeout');
} else if (result.status === AUTH_STATUS.APPLY_FAIL) {
// 失败
if (iconEl) iconEl.textContent = '✗';
if (statusEl) statusEl.textContent = '失败';
if (progressItem) progressItem.classList.add('failed');
} else {
// 成功
if (iconEl) iconEl.textContent = '✓';
if (statusEl) statusEl.textContent = '已完成';
if (progressItem) progressItem.classList.add('completed');
}
},
// 全部完成
onAllComplete: () => {
console.log('[BasicInfoPage] 全部授权完成');
this.showAuthComplete(redirectUrl);
}
});
}
/**
* 显示授权完成界面
* @param {string} redirectUrl - 跳转 URL
*/
showAuthComplete(redirectUrl) {
const container = document.getElementById('authFlowContainer');
if (!container) return;
// 隐藏 iframe 区域,显示完成提示
const iframeSection = container.querySelector('.auth-iframe-section');
if (iframeSection) {
iframeSection.style.display = 'none';
}
// 创建完成提示
const completeSection = document.createElement('div');
completeSection.className = 'auth-complete-section';
completeSection.innerHTML = `
<div class="auth-complete-icon">✓</div>
<div class="auth-complete-title">全部授权完成</div>
<div class="auth-complete-desc">您的申请已全部提交成功!</div>
${redirectUrl ? `
<div class="auth-countdown">
<span id="countdownSeconds">5</span> 秒后自动跳转...
</div>
<button class="auth-redirect-btn" id="redirectNowBtn">立即跳转</button>
` : `
<button class="auth-redirect-btn" onclick="window.location.reload()">返回首页</button>
`}
`;
container.appendChild(completeSection);
// 启动倒计时
if (redirectUrl) {
this.startFinalCountdown(redirectUrl);
}
}
/**
* 启动最终倒计时
* @param {string} redirectUrl - 跳转 URL
*/
startFinalCountdown(redirectUrl) {
const countdownEl = document.getElementById('countdownSeconds');
const redirectBtn = document.getElementById('redirectNowBtn');
// 立即跳转按钮
if (redirectBtn) {
redirectBtn.addEventListener('click', () => {
AuthFlowService.redirect(redirectUrl);
}); });
} }
// 启动倒计时
AuthFlowService.startCountdown(
AuthFlowService.COUNTDOWN_SECONDS,
(remaining) => {
if (countdownEl) {
countdownEl.textContent = remaining;
}
},
() => {
AuthFlowService.redirect(redirectUrl);
}
);
} }
/** /**

View File

@@ -0,0 +1,220 @@
/**
* 授权流程服务
* 处理多个 H5 授权页面的逐个加载、轮询检测、超时控制和最终跳转
*/
import { ApiClient } from '../core/api.js';
import { API_CONFIG } from '../config/index.js';
// 授权状态常量
const AUTH_STATUS = {
WAITING: 1, // 等待授权
CALLBACK: 2, // 已回调
APPLY_OK: 3, // 进件成功
APPLY_FAIL: 4 // 进件失败
};
export class AuthFlowService {
// 配置常量
static POLL_INTERVAL = 3000; // 轮询间隔3秒
static POLL_TIMEOUT = 10 * 60 * 1000; // 超时时间10分钟
static COUNTDOWN_SECONDS = 5; // 倒计时5秒
/**
* 检查单个 API 的授权状态
* @param {number} formdataid - 表单数据ID
* @param {string} apicode - API编码
* @returns {Promise<Object>} - 状态信息 { apicode, apiname, status, h5url }
*/
static async checkAuthStatus(formdataid, apicode) {
try {
const response = await ApiClient.xpost(API_CONFIG.ENDPOINTS.CHECK_AUTH_STATUS, {
formdataid,
apicode
});
if (response.retcode === 0 && response.result) {
return response.result;
}
console.warn('[AuthFlowService] 检查授权状态失败:', response.retinfo);
return null;
} catch (error) {
console.error('[AuthFlowService] 检查授权状态出错:', error);
return null;
}
}
/**
* 等待授权完成(轮询)
* @param {number} formdataid - 表单数据ID
* @param {string} apicode - API编码
* @param {Function} onStatusChange - 状态变化回调
* @returns {Promise<Object>} - { success: boolean, status: number, timeout: boolean }
*/
static async waitForAuth(formdataid, apicode, onStatusChange) {
const startTime = Date.now();
while (true) {
// 检查超时
if (Date.now() - startTime > this.POLL_TIMEOUT) {
console.log('[AuthFlowService] 轮询超时:', apicode);
return { success: false, status: AUTH_STATUS.WAITING, timeout: true };
}
// 查询状态
const result = await this.checkAuthStatus(formdataid, apicode);
if (result) {
// 通知状态变化
if (onStatusChange) {
onStatusChange(result);
}
// 状态 >= 2 表示已回调/成功/失败,可以进入下一个
if (result.status >= AUTH_STATUS.CALLBACK) {
return {
success: result.status === AUTH_STATUS.CALLBACK || result.status === AUTH_STATUS.APPLY_OK,
status: result.status,
timeout: false
};
}
}
// 等待下次轮询
await this.sleep(this.POLL_INTERVAL);
}
}
/**
* 执行授权流程
* @param {number} formdataid - 表单数据ID
* @param {Array} h5Urls - H5 URL 列表 [{ apicode, apiname, h5url }]
* @param {Object} callbacks - 回调函数集合
* - onStart(item, index) - 开始处理某个产品
* - onProgress(item, index, status) - 状态更新
* - onComplete(item, index, result) - 单个产品完成
* - onAllComplete() - 全部完成
* - onIframeChange(url) - iframe 需要切换 URL
* @returns {Promise<void>}
*/
static async startAuthFlow(formdataid, h5Urls, callbacks = {}) {
const { onStart, onProgress, onComplete, onAllComplete, onIframeChange } = callbacks;
console.log('[AuthFlowService] 开始授权流程, formdataid:', formdataid, 'h5Urls:', h5Urls);
for (let i = 0; i < h5Urls.length; i++) {
const item = h5Urls[i];
console.log('[AuthFlowService] 处理第', i + 1, '个产品:', item.apiname);
// 通知开始处理
if (onStart) {
onStart(item, i);
}
// 切换 iframe
if (onIframeChange && item.h5url) {
onIframeChange(item.h5url);
}
// 轮询等待授权完成
const result = await this.waitForAuth(formdataid, item.apicode, (status) => {
if (onProgress) {
onProgress(item, i, status);
}
});
console.log('[AuthFlowService] 产品授权结果:', item.apiname, result);
// 通知单个完成
if (onComplete) {
onComplete(item, i, result);
}
}
// 全部完成
console.log('[AuthFlowService] 全部授权流程完成');
if (onAllComplete) {
onAllComplete();
}
}
/**
* 开始倒计时
* @param {number} seconds - 倒计时秒数
* @param {Function} onTick - 每秒回调,参数为剩余秒数
* @param {Function} onComplete - 倒计时完成回调
* @returns {Function} - 取消函数
*/
static startCountdown(seconds, onTick, onComplete) {
let remaining = seconds;
let cancelled = false;
const tick = () => {
if (cancelled) return;
if (onTick) {
onTick(remaining);
}
if (remaining <= 0) {
if (onComplete) {
onComplete();
}
return;
}
remaining--;
setTimeout(tick, 1000);
};
tick();
// 返回取消函数
return () => {
cancelled = true;
};
}
/**
* 跳转到目标页面
* @param {string} url - 目标 URL
*/
static redirect(url) {
if (url) {
window.location.href = url;
}
}
/**
* 辅助函数:延时
* @param {number} ms - 毫秒
* @returns {Promise}
*/
static sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* 获取状态文本
* @param {number} status - 状态码
* @returns {string}
*/
static getStatusText(status) {
switch (status) {
case AUTH_STATUS.WAITING:
return '等待授权';
case AUTH_STATUS.CALLBACK:
return '已完成';
case AUTH_STATUS.APPLY_OK:
return '授权成功';
case AUTH_STATUS.APPLY_FAIL:
return '授权失败';
default:
return '未知状态';
}
}
}
// 导出状态常量
export { AUTH_STATUS };

View File

@@ -7,3 +7,4 @@ export { AuthService } from './auth.service.js';
export { LoanService } from './loan.service.js'; export { LoanService } from './loan.service.js';
export { FormService } from './form.service.js'; export { FormService } from './form.service.js';
export { JVerifyService, getJVerifyService } from './jverify.service.js'; export { JVerifyService, getJVerifyService } from './jverify.service.js';
export { AuthFlowService, AUTH_STATUS } from './auth-flow.service.js';

View File

@@ -4,34 +4,15 @@
*/ */
import { getJVerifyService } from '../services/index.js'; import { getJVerifyService } from '../services/index.js';
import { showToast } from './toast.js';
import { API_CONFIG } from '../config/api.config.js';
/** // 极光一键登录错误码
* 简单的 Toast 提示工具 const JVERIFY_ERROR_CODES = {
* @param {string} message - 提示消息 AUTH_FAILED: '2002', // 运营商授权失败
* @param {number} duration - 持续时间(毫秒) TIMEOUT: '2006', // 登录超时
*/ NOT_SUPPORTED: 'not support' // 当前环境不支持
function showToast(message, duration = 2000) { };
// 移除现有的 toast
const existingToast = document.querySelector('.one-click-toast');
if (existingToast) {
existingToast.remove();
}
// 创建新的 toast
const toast = document.createElement('div');
toast.className = 'one-click-toast';
toast.textContent = message;
document.body.appendChild(toast);
// 触发动画
setTimeout(() => toast.classList.add('show'), 10);
// 自动移除
setTimeout(() => {
toast.classList.remove('show');
setTimeout(() => toast.remove(), 300);
}, duration);
}
export class OneClickLoginButton { export class OneClickLoginButton {
/** /**
@@ -178,7 +159,7 @@ export class OneClickLoginButton {
this.setButtonState('verifying'); this.setButtonState('verifying');
// 调用后端验证 // 调用后端验证
const response = await fetch('/zcore/jpush/login', { const response = await fetch(API_CONFIG.ENDPOINTS.JPUSH_LOGIN, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@@ -206,11 +187,11 @@ export class OneClickLoginButton {
// 判断错误类型,提供友好提示 // 判断错误类型,提供友好提示
let message = '登录失败,请使用短信验证码登录'; let message = '登录失败,请使用短信验证码登录';
if (error.message && error.message.includes('2002')) { if (error.message && error.message.includes(JVERIFY_ERROR_CODES.AUTH_FAILED)) {
message = '运营商授权失败,请使用短信验证码登录'; message = '运营商授权失败,请使用短信验证码登录';
} else if (error.message && error.message.includes('2006')) { } else if (error.message && error.message.includes(JVERIFY_ERROR_CODES.TIMEOUT)) {
message = '登录超时,请重试或使用短信验证码登录'; message = '登录超时,请重试或使用短信验证码登录';
} else if (error.message && error.message.includes('not support')) { } else if (error.message && error.message.includes(JVERIFY_ERROR_CODES.NOT_SUPPORTED)) {
message = '当前环境不支持一键登录,请使用短信验证码登录'; message = '当前环境不支持一键登录,请使用短信验证码登录';
} }