/** * H5公共工具函数 * 避免在多个文件中重复定义相同的函数 */ const ENTRY_SOURCE_KEY = "entrySource"; const ENTRY_SOURCE_MY = "my"; const AUTH_REDIRECT_DONE_KEY = "authRedirectDone"; // 获取URL参数的工具函数 function getUrlParams() { const params = {}; const urlSearchParams = new URLSearchParams(window.location.search); for (const [key, value] of urlSearchParams) { params[key] = decodeURIComponent(value); } return params; } function isAuthPage(pathname = window.location.pathname) { return /\/(login|autoLogin)\.html$/i.test(pathname || ""); } function getCurrentPageUrl() { return `${window.location.origin}${window.location.pathname}${window.location.search}`; } function getStoredAuthToken() { const userInfo = localStorage.getItem("userInfo"); if (userInfo) { try { const parsed = JSON.parse(userInfo); const token = parsed?.yhsbToken || parsed?.onlineToken || ""; if (token) { return token; } } catch (error) { console.warn("解析 userInfo 获取 token 失败:", error); } } return ( localStorage.getItem("yhsbToken") || localStorage.getItem("onlineToken") || "" ); } // 小程序进入 H5 时,只有 my 页面主动点击进入的场景才会带 entrySource=my。 // 因此这里把“from=miniprogram 且不是认证页 且没有 entrySource=my”的页面 // 统一视为消息直达等需先认证的入口,进入登录/自动登录分流。 // 但如果已经带了 authRedirectDone=1,说明当前页是登录成功后回跳回来的, // 本次不应再重复进入登录分流,否则会在业务页和 autoLogin.html 之间循环跳转。 function isMiniProgramMessageEntry(params = getUrlParams()) { return ( params.from === "miniprogram" && params[ENTRY_SOURCE_KEY] !== ENTRY_SOURCE_MY && params[AUTH_REDIRECT_DONE_KEY] !== "1" && !isAuthPage() ); } // 公共层在每个业务 H5 页面初始化前都会先调用这个函数。 // 一旦命中消息直达分流,就立即跳到 login.html 或 autoLogin.html, // 并把当前业务页完整地址放到 redirect 参数里,登录成功后再尝试回到这里。 function handleMessageEntryAuthRedirect() { const params = getUrlParams(); if (!isMiniProgramMessageEntry(params)) { return false; } const redirectUrl = getCurrentPageUrl(); const token = getStoredAuthToken(); const authPage = token ? "autoLogin" : "login"; const authUrl = `/page/${authPage}.html?entryScene=message&redirect=${encodeURIComponent( redirectUrl )}`; console.log("🔐 检测到消息直达页面,准备跳转认证页:", { authPage, redirectUrl, hasToken: !!token, }); window.location.replace(authUrl); return true; } // 获取设备信息 (优先从URL参数获取,备用从localStorage获取) function getDeviceInfo() { const urlParams = getUrlParams(); // 优先从URL参数获取 let deviceId = urlParams.devId || ""; let model = urlParams.sbmc || ""; // 如果URL参数中没有,尝试从localStorage获取 if (!deviceId || !model) { const cachedDeviceInfo = localStorage.getItem("deviceInfo"); if (cachedDeviceInfo) { try { const parsed = JSON.parse(cachedDeviceInfo); deviceId = deviceId || parsed.deviceId || ""; model = model || parsed.model || ""; console.log("🔄 从localStorage获取设备信息:", { deviceId, model }); } catch (e) { console.warn("解析localStorage中的设备信息失败:", e); } } } // 如果获取到了设备信息,保存到localStorage作为备用 if (deviceId && model) { const deviceInfo = { deviceId, model }; localStorage.setItem("deviceInfo", JSON.stringify(deviceInfo)); } return { deviceId: deviceId, model: model, }; } // 获取JSESSIONID (多源获取,确保可用性) function getJSessionId() { // 优先级:localStorage > URL参数 > Cookie let jsessionId = localStorage.getItem("JSESSIONID"); if (!jsessionId) { const urlParams = getUrlParams(); jsessionId = urlParams.JSESSIONID; } if (!jsessionId) { // 尝试从document.cookie中获取 const cookies = document.cookie.split(";"); for (let cookie of cookies) { const [name, value] = cookie.trim().split("="); if (name === "JSESSIONID") { jsessionId = value; break; } } } console.log("🔍 获取JSESSIONID:", { fromLocalStorage: localStorage.getItem("JSESSIONID"), fromURL: getUrlParams().JSESSIONID, final: jsessionId, }); return jsessionId || ""; } // 保存JSESSIONID到localStorage function saveJSessionId(jsessionId) { if (jsessionId) { localStorage.setItem("JSESSIONID", jsessionId); console.log("✅ H5 JSESSIONID已保存:", jsessionId); } } // 模拟微信授权码获取 (H5环境下的处理) function getMockWechatCode() { // 在H5环境下,我们可以生成一个模拟的code // 实际项目中可能需要接入微信H5授权 return "h5_mock_code_" + Date.now(); } // 用户信息管理 const userManager = { // 保存用户信息 saveUserInfo(userInfo) { console.log("💾 H5保存用户信息:", userInfo); localStorage.setItem("userInfo", JSON.stringify(userInfo)); }, // 获取保存的用户信息 getSavedUserInfo() { const userInfo = localStorage.getItem("userInfo"); return userInfo ? JSON.parse(userInfo) : null; }, // 检查登录状态 checkLoginStatus() { const userInfo = localStorage.getItem("userInfo"); const jsessionId = localStorage.getItem("JSESSIONID"); console.log("🔍 H5检查登录状态:", { hasUserInfo: !!userInfo, hasJSessionId: !!jsessionId, }); return { isLoggedIn: !!(userInfo && jsessionId), userInfo: userInfo ? JSON.parse(userInfo) : null, jsessionId: jsessionId, }; }, // 清除登录信息 clearLoginInfo() { localStorage.removeItem("userInfo"); localStorage.removeItem("JSESSIONID"); localStorage.removeItem("deviceInfo"); console.log("🧹 已清除登录信息"); }, }; // 获取图片URL (用于图片回显) function getImageUrl(path) { if (!path) return ""; // 如果已经是完整URL,直接返回 if ( path.startsWith("http://") || path.startsWith("https://") || path.startsWith("blob:") ) { return path; } // 获取baseUrl (从request中获取或使用默认值) const baseUrl = window.request?.defaults?.baseURL || window.location.origin; // 构造图片下载URL return ( baseUrl + "/service?ssServ=dlByHttp&wdConfirmationCaptchaService=0&type=img&path=" + path ); } // 获取文件URL (用于文件下载) function getFileUrl(path) { if (!path) return ""; // 如果已经是完整URL,直接返回 if (path.startsWith("http://") || path.startsWith("https://")) { return path; } // 获取baseUrl const baseUrl = window.request?.defaults?.baseURL || window.location.origin; // 构造文件下载URL return ( baseUrl + "/service?ssServ=dlByHttp&wdConfirmationCaptchaService=0&type=file&path=" + path ); } // 格式化日期时间 (使用 dayjs) function formatDate(dateStr, format = "YYYY-MM-DD HH:mm:ss") { if (!dateStr) { console.log("formatDate: 时间字符串为空"); return ""; } console.log("formatDate 输入:", dateStr, "格式要求:", format); // 检查 dayjs 是否可用 if (typeof dayjs === "undefined") { console.error("❌ dayjs 未加载,无法格式化时间"); return dateStr; } // 清理字符串:移除特殊空格字符(如 \u202F),替换为普通空格 const cleanedDateStr = String(dateStr) .replace(/[\u202F\u00A0]/g, " ") // 替换不间断空格 .replace(/\s+/g, " ") // 多个空格合并为一个 .trim(); console.log("清理后的字符串:", cleanedDateStr); // 尝试使用原生 Date 解析(兼容性最好) let date = null; try { const jsDate = new Date(cleanedDateStr); if (!isNaN(jsDate.getTime())) { date = dayjs(jsDate); console.log("✅ 使用 Date 解析成功"); } } catch (e) { console.warn("Date 解析失败:", e); } // 如果 Date 解析失败,尝试直接用 dayjs if (!date || !date.isValid()) { date = dayjs(cleanedDateStr); console.log("尝试使用 dayjs 直接解析"); } console.log("dayjs 解析结果 isValid:", date ? date.isValid() : "null"); if (!date || !date.isValid()) { console.warn("⚠️ 无效的日期格式:", dateStr); return ""; // 解析失败返回空字符串 } // dayjs 的格式化 (支持常见格式) // dayjs 使用大写的格式标记: YYYY-MM-DD HH:mm:ss const result = date.format(format); console.log("格式化结果:", result); return result; } window.ENTRY_SOURCE_KEY = ENTRY_SOURCE_KEY; window.ENTRY_SOURCE_MY = ENTRY_SOURCE_MY; window.getUrlParams = getUrlParams; window.isAuthPage = isAuthPage; window.getCurrentPageUrl = getCurrentPageUrl; window.getStoredAuthToken = getStoredAuthToken; window.isMiniProgramMessageEntry = isMiniProgramMessageEntry; window.handleMessageEntryAuthRedirect = handleMessageEntryAuthRedirect; window.getDeviceInfo = getDeviceInfo; window.getJSessionId = getJSessionId; window.saveJSessionId = saveJSessionId; window.getMockWechatCode = getMockWechatCode; window.userManager = userManager; window.getImageUrl = getImageUrl; window.getFileUrl = getFileUrl; window.formatDate = formatDate; // 同时挂载到SS.utils下(兼容组件调用) if (!window.SS.utils) { window.SS.utils = {}; } window.SS.utils.getImageUrl = getImageUrl; window.SS.utils.getFileUrl = getFileUrl; window.SS.utils.formatDate = formatDate; console.log("✅ H5公共工具已加载");