From eaa7c7ba550e951f06e49b530407229fcc919d54 Mon Sep 17 00:00:00 2001 From: gonghaoxing <478185430@qq.com> Date: Tue, 21 Oct 2025 14:56:48 +0800 Subject: [PATCH] =?UTF-8?q?'=E7=99=BB=E5=BD=95=E8=B0=83=E8=AF=95'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/App.vue | 211 +++--- frontend/manifest.json | 4 +- frontend/pages/ccblife/index.vue | 1 + frontend/pages/public/setting.vue | 3 +- .../sheep/components/s-layout/s-layout.vue | 48 +- .../components/s-user-card/s-user-card.vue | 3 +- .../sheep/platform/provider/ccblife/index.js | 645 ++++++++---------- frontend/sheep/request/index.js | 2 +- frontend/sheep/store/user.js | 8 +- 9 files changed, 471 insertions(+), 454 deletions(-) diff --git a/frontend/App.vue b/frontend/App.vue index f0b4487..ec12b25 100644 --- a/frontend/App.vue +++ b/frontend/App.vue @@ -7,20 +7,51 @@ let isLoggingIn = false; onLaunch(() => { - console.log('[App] 应用启动...'); - // 隐藏原生导航栏 使用自定义底部导航 uni.hideTabBar({ fail: () => {}, }); + // 初始化移动端调试控制台(仅H5环境) + // #ifdef H5 + initVConsole(); + // #endif + // 加载Shopro底层依赖 ShoproInit(); // 检测建行生活登录参数 checkCCBLogin(); + + // 启动 JSBridge 监控(每10秒打印一次) + // #ifdef H5 + startJSBridgeMonitor(); + // #endif }); + /** + * 初始化 vConsole 移动端调试控制台 + * 在H5环境下提供类似Chrome DevTools的功能 + */ + const initVConsole = () => { + // 动态导入vConsole,避免打包到非H5平台 + import('vconsole') + .then((module) => { + const VConsole = module.default; + const vConsole = new VConsole({ + defaultPlugins: ['system', 'network', 'element', 'storage'], + maxLogNumber: 1000, + disableLogScrolling: false, + }); + + // 保存实例供后续使用 + window.vConsole = vConsole; + }) + .catch((err) => { + console.error('[App] vConsole加载失败:', err); + }); + }; + onError((err) => { console.log('AppOnError:', err); }); @@ -39,10 +70,63 @@ // #endif }); + /** + * JSBridge 注入情况监控 + * 每10秒打印一次所有建行相关 JSBridge 对象的状态,打印15次后自动停止 + */ + const startJSBridgeMonitor = () => { + let count = 0; + const maxCount = 15; + + // 立即执行一次 + printJSBridgeStatus(++count, maxCount); + + // 每10秒执行一次 + const timer = setInterval(() => { + printJSBridgeStatus(++count, maxCount); + + // 达到15次后清除定时器 + if (count >= maxCount) { + clearInterval(timer); + console.log('[JSBridge] 监控已停止(已打印15次)'); + } + }, 10000); + }; + + /** + * 打印 JSBridge 注入状态(精简版) + */ + const printJSBridgeStatus = (count, maxCount) => { + const timestamp = new Date().toLocaleTimeString('zh-CN', { hour12: false }); + const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent); + const isAndroid = /Android/i.test(navigator.userAgent); + + // 检测各个 Bridge 对象 + const hasMbspay = + typeof window.mbspay !== 'undefined' && typeof window.mbspay.directpay === 'function'; + const hasCCBBridge = typeof window.CCBBridge !== 'undefined'; + const hasWebViewBridge = typeof window.WebViewJavascriptBridge !== 'undefined'; + const hasAnyBridge = hasMbspay || hasCCBBridge || hasWebViewBridge; + + // 支付能力 + const canPay = isIOS || (isAndroid && hasMbspay); + + // 一行输出所有状态(包含计数) + console.log( + `[JSBridge ${timestamp}] (${count}/${maxCount}) ` + + `设备:${isIOS ? 'iOS' : isAndroid ? 'Android' : 'PC'} | ` + + `mbspay:${hasMbspay ? '✅' : '❌'} | ` + + `CCBBridge:${hasCCBBridge ? '✅' : '❌'} | ` + + `WebViewBridge:${hasWebViewBridge ? '✅' : '❌'} | ` + + `支付能力:${canPay ? '✅' : '❌'} | ` + + `Bridge状态:${hasAnyBridge ? '✅就绪' : '❌未就绪'}`, + ); + }; + /** * 检测URL中的建行登录参数并自动登录 * 建行跳转URL格式:url?platform=ccblife&channel=mbs&ccbParamSJ=xxx&CITYID=330100&USERCITYID=440100 - * + * * 逻辑: * 1. 解析URL参数获取ccbParamSJ * 2. 与本地存储的lastCcbParamSJ比较 @@ -51,22 +135,17 @@ */ const checkCCBLogin = () => { // #ifdef H5 - console.log('[App] ========== 开始检测建行登录参数 =========='); - console.log('[App] 完整URL:', window.location.href); - console.log('[App] search:', window.location.search); - try { let ccbParamSJ = null; let platform = null; let cityid = null; - // 优先从search中提取参数(建行标准格式:url?platform=ccblife&ccbParamSJ=xxx) + // 优先从search中提取参数(建行标准格式:url?ccbParamSJ=xxx&CITYID=xxx) if (window.location.search) { const urlParams = new URLSearchParams(window.location.search); ccbParamSJ = urlParams.get('ccbParamSJ'); - platform = urlParams.get('platform'); + platform = urlParams.get('platform') || 'ccblife'; cityid = urlParams.get('CITYID') || urlParams.get('cityid'); - console.log('[App] 从search中解析参数'); } // 备用:从hash中提取参数(UniApp内部跳转可能使用) @@ -75,156 +154,107 @@ if (hashParts.length > 1) { const hashParams = new URLSearchParams(hashParts[1]); ccbParamSJ = hashParams.get('ccbParamSJ'); - platform = hashParams.get('platform'); + platform = hashParams.get('platform') || 'ccblife'; cityid = hashParams.get('CITYID') || hashParams.get('cityid'); - console.log('[App] 从hash中解析参数'); } } - console.log('[App] ====== 参数解析结果 ======'); - console.log('[App] platform:', platform); - console.log('[App] CITYID:', cityid); - console.log('[App] 当前ccbParamSJ:', ccbParamSJ ? ccbParamSJ.substring(0, 50) + '...' : 'null'); - // 获取上次保存的ccbParamSJ const lastCcbParamSJ = uni.getStorageSync('lastCcbParamSJ') || null; - console.log('[App] 上次ccbParamSJ:', lastCcbParamSJ ? lastCcbParamSJ.substring(0, 50) + '...' : 'null'); - - // 判断参数是否变化 - const isParamChanged = ccbParamSJ && (lastCcbParamSJ !== ccbParamSJ); - const isFirstTime = ccbParamSJ && !lastCcbParamSJ; - - console.log('[App] 是否首次登录:', isFirstTime); - console.log('[App] 参数是否变化:', isParamChanged); - console.log('[App] ==========================='); - // 如果有建行参数 - if (ccbParamSJ && platform === 'ccblife') { - + // 判断参数是否变化 + const isParamChanged = ccbParamSJ && lastCcbParamSJ !== ccbParamSJ; + const isFirstTime = ccbParamSJ && !lastCcbParamSJ; + + // 如果有建行参数(固定建行生活环境,只要有ccbParamSJ就执行登录) + if (ccbParamSJ) { // 如果参数未变化,无需重新登录 if (!isParamChanged && !isFirstTime) { - console.log('[App] ℹ️ ccbParamSJ未变化,无需重新登录,跳过'); - // 清除URL参数 - const cleanUrl = window.location.origin + window.location.pathname + '#/pages/index/index'; + console.log('[CCB] 参数未变化,跳过登录'); + const cleanUrl = window.location.origin + '/pages/index/index'; window.history.replaceState({}, '', cleanUrl); - console.log('[App] ========== 检测完成 =========='); - return; - } - - // 参数变化了,需要切换用户 - if (isParamChanged) { - console.log('[App] 🔄🔄🔄 检测到ccbParamSJ变化,需要切换用户!'); - } else { - console.log('[App] 🆕 首次登录'); - } - - // 🔒 防止重复调用:检查是否正在登录中 - if (isLoggingIn) { - console.log('[App] ⚠️ 已有登录流程正在执行,跳过重复调用'); return; } - // 设置登录中标志 + console.log(`[CCB] ${isParamChanged ? '切换用户' : '首次登录'}`); + + // 防止重复调用 + if (isLoggingIn) { + console.log('[CCB] 登录进行中,跳过'); + return; + } + isLoggingIn = true; - console.log('[App] 🔒 设置登录锁定标志'); - + // 延迟执行登录,确保依赖已初始化 setTimeout(async () => { try { - console.log('[App] 开始执行登录流程...'); - // 如果是切换用户,先退出当前用户 const userStore = sheep.$store('user'); if (isParamChanged && userStore && userStore.isLogin) { - console.log('[App] 退出当前用户,准备切换...'); await userStore.logout(); uni.removeStorageSync('token'); uni.removeStorageSync('userInfo'); - console.log('[App] 当前用户已退出'); } // 显示loading const loadingTitle = isParamChanged ? '切换用户中...' : '建行登录中...'; uni.showLoading({ title: loadingTitle, - mask: true - }); - - // 调用建行登录API(只传三个参数) - console.log('[App] 调用登录API,参数:', { - ccbParamSJ: ccbParamSJ.substring(0, 30) + '...', - cityid: cityid || '360100', - CITYID: cityid || '360100' + mask: true, }); + // 调用建行登录API const result = await sheep.$api.third.ccbLogin({ ccbParamSJ: ccbParamSJ, cityid: cityid || '360100', - CITYID: cityid || '360100' + CITYID: cityid || '360100', }); - console.log('[App] 登录API返回:', result); - uni.hideLoading(); if (result.code === 1) { - console.log('[App] ✅✅✅ 建行登录成功!'); - console.log('[App] Token:', result.data.token?.substring(0, 20) + '...'); - console.log('[App] 用户信息:', result.data.user_info); + console.log('[CCB] 登录成功'); // 设置token和用户信息 sheep.$store('user').setToken(result.data.token); uni.setStorageSync('userInfo', result.data.user_info); - - // 🔑 关键:保存当前的ccbParamSJ到本地存储 uni.setStorageSync('lastCcbParamSJ', ccbParamSJ); - console.log('[App] ✅ 已保存ccbParamSJ到本地存储'); // 显示欢迎提示 uni.showToast({ title: `登录成功`, icon: 'success', - duration: 2000 + duration: 2000, }); - // 清除URL中的敏感参数,保留干净的URL - const cleanUrl = window.location.origin + window.location.pathname + '#/pages/index/index'; + // 清除URL中的敏感参数 + const cleanUrl = window.location.origin + '/pages/index/index'; window.history.replaceState({}, '', cleanUrl); - console.log('[App] URL参数已清除'); - } else { throw new Error(result.msg || '登录失败'); } } catch (error) { - console.error('[App] ❌❌❌ 建行登录失败:', error); + console.error('[CCB] 登录失败:', error.message || error.msg); uni.hideLoading(); - + uni.showModal({ title: isParamChanged ? '切换用户失败' : '登录失败', content: error.message || error.msg || '请检查网络连接', showCancel: false, complete: () => { - // 登录失败后也清除URL参数 - const cleanUrl = window.location.origin + window.location.pathname + '#/pages/index/index'; + const cleanUrl = window.location.origin + '/pages/index/index'; window.history.replaceState({}, '', cleanUrl); - } + }, }); } finally { - // 🔓 无论成功失败,都释放登录锁 isLoggingIn = false; - console.log('[App] 🔓 释放登录锁定标志'); } - }, 1200); // 延迟1200ms,确保Shopro和API已加载完成 - } else { - console.log('[App] ℹ️ 未检测到建行登录参数'); - if (ccbParamSJ && platform !== 'ccblife') { - console.warn('[App] ⚠️ 发现ccbParamSJ但platform不是ccblife:', platform); - } + }, 1200); } } catch (error) { - console.error('[App] ❌ 参数解析错误:', error); + console.error('[CCB] 参数解析错误:', error); } - console.log('[App] ========== 检测完成 =========='); // #endif }; @@ -232,4 +262,3 @@ - diff --git a/frontend/manifest.json b/frontend/manifest.json index 7a5afdb..60cc735 100644 --- a/frontend/manifest.json +++ b/frontend/manifest.json @@ -199,8 +199,8 @@ "h5" : { "template" : "index.html", "router" : { - "mode" : "hash", - "base" : "./" + "mode" : "history", + "base" : "/" }, "sdkConfigs" : { "maps" : {} diff --git a/frontend/pages/ccblife/index.vue b/frontend/pages/ccblife/index.vue index c0d9b6b..f551489 100644 --- a/frontend/pages/ccblife/index.vue +++ b/frontend/pages/ccblife/index.vue @@ -1,4 +1,5 @@