/** * H5与小程序通信桥接工具函数库 * 提供统一的小程序原生功能调用接口 */ // 全局变量 window.H5_PAGE_NAME = window.H5_PAGE_NAME || "default"; /** * 设置当前页面名称 * @param {string} pageName 页面名称 */ function setPageName(pageName) { window.H5_PAGE_NAME = pageName; } /** * 检查微信小程序环境 * @returns {boolean} 是否在微信小程序环境 */ function checkEnvironment() { return typeof wx !== "undefined" && wx.miniProgram; } /** * 解析URL参数(兼容性处理) * @param {string} search URL查询字符串 * @returns {Object} 参数对象 */ function parseUrlParams(search) { const params = {}; if (search) { search .substring(1) .split("&") .forEach((param) => { const [key, value] = param.split("="); if (key && value) { params[decodeURIComponent(key)] = decodeURIComponent(value); } }); } return params; } /** * 检查是否有返回的结果数据 * @param {Function} onResult 结果处理回调 */ function checkResult(onResult) { const search = window.location.search; console.log("🔍 检查URL参数:", search); if (search) { const params = parseUrlParams(search); console.log("🔍 解析的参数:", params); if (params.result) { try { const resultData = JSON.parse(decodeURIComponent(params.result)); console.log("🔍 解析的结果数据:", resultData); // 调用回调处理结果 if (onResult) { onResult(resultData); } } catch (error) { console.error("解析结果数据失败:", error); } } else { console.log("🔍 URL中没有result参数"); } } else { console.log("🔍 URL中没有查询参数"); } } /** * 调用小程序原生功能 * @param {string} action 操作类型 * @param {string} message 消息描述 * @param {Object} data 附加数据 */ function callNative(action, message = "", data = null) { if (!checkEnvironment()) { console.error("❌ 不在微信小程序环境"); return; } const params = { action: action, message: message || "", source: window.H5_PAGE_NAME, }; // 处理附加数据 if (data && typeof data === "object") { try { const jsonString = JSON.stringify(data); params.data = encodeURIComponent(jsonString); console.log("📦 数据编码:", { original: data, json: jsonString, encoded: params.data, }); } catch (error) { console.error("❌ JSON序列化失败:", error); return; } } // 构建URL参数 const queryParts = []; Object.keys(params).forEach((key) => { if (params[key] !== undefined && params[key] !== null) { if (key === "data") { queryParts.push(`${key}=${params[key]}`); } else { queryParts.push(`${key}=${encodeURIComponent(params[key])}`); } } }); const controllerUrl = `/pages/common/h5-controller?${queryParts.join("&")}`; console.log("🎛️ 跳转到控制器:", controllerUrl); // 调用微信小程序API,添加降级处理 wx.miniProgram.navigateTo({ url: controllerUrl, success: (res) => { console.log("✅ 成功跳转到控制器", res); }, fail: (err) => { console.error("❌ 控制器调用失败,尝试降级方案:", err); // 降级方案:使用URL参数通信(兼容老版本webview) fallbackUrlCommunication(action, message, data); }, }); } /** * 降级通信方案:通过URL参数与webview通信 * @param {string} action 操作类型 * @param {string} message 消息描述 * @param {Object} data 附加数据 */ function fallbackUrlCommunication(action, message = "", data = null) { console.log("🔄 使用降级通信方案"); const params = { h5_action: action, h5_message: message, timestamp: Date.now(), }; // 如果有额外数据,编码后添加 if (data && typeof data === "object") { try { params.h5_data = encodeURIComponent(JSON.stringify(data)); } catch (error) { console.error("❌ 数据编码失败:", error); } } // 保留原有的非指令参数 const currentParams = parseUrlParams(window.location.search); Object.keys(currentParams).forEach((key) => { if ( !key.startsWith("h5_") && !key.startsWith("mp_") && key !== "timestamp" ) { params[key] = currentParams[key]; } }); // 构建新URL const baseUrl = `${window.location.origin}${window.location.pathname}`; const queryParts = []; Object.keys(params).forEach((key) => { if (params[key] !== undefined && params[key] !== null) { queryParts.push( `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}` ); } }); const url = `${baseUrl}?${queryParts.join("&")}`; console.log("🔄 降级跳转URL:", url); // 使用location.href触发webview的load事件 window.location.href = url; } /** * 扫码 * @param {string} message 消息描述 * @returns {Promise} 调用结果 */ function scanCode(message = "扫描二维码") { return callNative("scanCode", message); } /** * 选择图片 * @param {string} message 消息描述 * @returns {Promise} 调用结果 */ function chooseImage(message = "选择图片") { return callNative("chooseImage", message); } /** * 拨打电话 * @param {string} phoneNumber 电话号码 * @param {string} message 消息描述 * @returns {Promise} 调用结果 */ function makePhoneCall(phoneNumber, message = "拨打电话") { return callNative("makePhoneCall", message, { phoneNumber }); } /** * 设置存储 * @param {string} key 存储键 * @param {*} value 存储值 * @param {string} message 消息描述 * @returns {Promise} 调用结果 */ function setStorage(key, value, message = "设置存储数据") { return callNative("setStorage", message, { key, value }); } /** * 获取存储 * @param {string} key 存储键 * @param {string} message 消息描述 * @returns {Promise} 调用结果 */ function getStorage(key, message = "获取存储数据") { return callNative("getStorage", message, { key }); } /** * 返回小程序 * @param {string} message 消息描述 * @returns {Promise} 调用结果 */ function goBack(message = "返回小程序") { return callNative("goBack", message); } /** * 页面跳转 * @param {string} page 目标页面 * @param {Object} params 跳转参数 */ function navigateTo(page, params = {}) { const queryString = Object.keys(params).length > 0 ? "?" + Object.keys(params) .map((key) => `${key}=${encodeURIComponent(params[key])}`) .join("&") : ""; window.location.href = `./${page}.html${queryString}`; } /** * 保存数据到localStorage * @param {string} key 存储键 * @param {*} data 存储数据 */ function saveData(key, data) { try { const storageKey = `h5_${window.H5_PAGE_NAME}_${key}`; localStorage.setItem(storageKey, JSON.stringify(data)); console.log("💾 数据已保存:", storageKey); } catch (error) { console.error("保存数据失败:", error); } } /** * 从localStorage加载数据 * @param {string} key 存储键 * @param {*} defaultValue 默认值 * @returns {*} 加载的数据 */ function loadData(key, defaultValue = null) { try { const storageKey = `h5_${window.H5_PAGE_NAME}_${key}`; const savedData = localStorage.getItem(storageKey); if (savedData) { return JSON.parse(savedData); } } catch (error) { console.error("加载数据失败:", error); } return defaultValue; } /** * 清除保存的数据 * @param {string} key 存储键 */ function clearData(key) { try { const storageKey = `h5_${window.H5_PAGE_NAME}_${key}`; localStorage.removeItem(storageKey); console.log("🗑️ 数据已清除:", storageKey); } catch (error) { console.error("清除数据失败:", error); } } /** * 默认的结果处理函数 * @param {Object} data 结果数据 */ function defaultResultHandler(data) { const { action, success, result, error } = data; if (success) { console.log(`✅ ${action} 操作成功`, result); } else { console.error(`❌ ${action} 操作失败`, error); } } /** * 初始化页面(可选调用) * @param {string} pageName 页面名称 * @param {Function} onResult 结果处理回调,不传则使用默认处理 */ function initPage(pageName, onResult) { setPageName(pageName); checkEnvironment(); // 如果没有提供自定义处理,使用默认处理 const resultHandler = onResult || defaultResultHandler; checkResult(resultHandler); } // ==================== UI工具函数 ==================== /** * 显示Toast效果(H5页面UI) * @param {string} message Toast消息 * @param {number} duration 显示时长(毫秒) * @param {string} type 类型:success|error|warning|info */ function showToastEffect(message, duration = 2000, type = "success") { const colors = { success: "rgba(40, 167, 69, 0.9)", error: "rgba(220, 53, 69, 0.9)", warning: "rgba(255, 193, 7, 0.9)", info: "rgba(23, 162, 184, 0.9)", }; const toast = document.createElement("div"); toast.textContent = message; toast.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: ${colors[type] || colors.success}; color: white; padding: 12px 24px; border-radius: 8px; z-index: 9999; font-size: 14px; pointer-events: none; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); `; document.body.appendChild(toast); setTimeout(() => { if (toast.parentNode) { toast.parentNode.removeChild(toast); } }, duration); } /** * 显示加载中效果 * @param {string} message 加载消息 * @returns {Function} 关闭加载的函数 */ function showLoading(message = "加载中...") { const loading = document.createElement("div"); loading.innerHTML = `