| | |
| | | |
| | | /** |
| | | * 清除所有 WebView 的缓存、Cookie 和存储数据。 |
| | | * 原生 API 可清掉 HttpOnly cookie 和按域名隔离的 localStorage; |
| | | * evalJS 仅作为兜底,清掉非 HttpOnly cookie 和当前页 storage。 |
| | | */ |
| | | function clearWebViewData() { |
| | | try { |
| | | // #ifdef APP-PLUS |
| | | // 1. 原生 API 清理(核心:能清掉 HttpOnly cookie 和所有域名的 localStorage) |
| | | const platform = String(uni.getSystemInfoSync().platform || '').toLowerCase() |
| | | if (platform === 'android') { |
| | | clearAndroidWebViewData() |
| | | } else if (platform === 'ios') { |
| | | clearIOSWebViewData() |
| | | } |
| | | |
| | | // 2. plus.webview API 兜底:清 HTTP 资源缓存,并注入 JS 清当前页 cookie/storage |
| | | try { |
| | | const allWebviews = plus.webview.all() |
| | | if (allWebviews && allWebviews.length > 0) { |
| | | allWebviews.forEach((webview) => { |
| | | try { |
| | | // 清除 WebView 缓存 |
| | | if (webview && typeof webview.clearCache === 'function') { |
| | | webview.clearCache() |
| | | } |
| | | |
| | | // 清除 Cookie、localStorage 和 sessionStorage |
| | | if (webview && typeof webview.evalJS === 'function') { |
| | | webview.evalJS(` |
| | | try { |
| | |
| | | }); |
| | | if (window.localStorage) localStorage.clear(); |
| | | if (window.sessionStorage) sessionStorage.clear(); |
| | | console.log('[WebView.evalJS] Cookie 和存储已清除'); |
| | | } catch (e) { |
| | | console.error('[WebView.evalJS] 清除失败:', e); |
| | | } |
| | | } catch (e) {} |
| | | `) |
| | | } |
| | | } catch (e) { |
| | | console.error('[WebView] 处理 WebView 失败:', e) |
| | | } |
| | | } catch (e) {} |
| | | }) |
| | | console.log('[WebView] 所有 WebView 缓存、Cookie 和存储已清除,共 ' + allWebviews.length + ' 个') |
| | | console.log('[WebView] 所有 WebView HTTP 缓存已清除,共 ' + allWebviews.length + ' 个') |
| | | } |
| | | } catch (e) {} |
| | | // #endif |
| | | } catch (error) { |
| | | console.error('[WebView] 清除数据失败:', error) |
| | |
| | | } |
| | | |
| | | /** |
| | | * Android 原生清理:清所有域名 Cookie(含 HttpOnly)+ WebStorage + 表单数据。 |
| | | */ |
| | | function clearAndroidWebViewData() { |
| | | try { |
| | | // 清所有域名 Cookie(包括 HttpOnly),CookieManager 是全局按域名共享的 |
| | | const CookieManager = plus.android.importClass('android.webkit.CookieManager') |
| | | if (CookieManager) { |
| | | const cm = CookieManager.getInstance() |
| | | try { cm.removeAllCookie() } catch (e) {} // 老版本 API(API 21 以下) |
| | | try { cm.flush() } catch (e) {} // 立即写入磁盘 |
| | | console.log('[WebView][Android] CookieManager 已清所有 Cookie') |
| | | } |
| | | |
| | | // 清所有域名的 localStorage / sessionStorage(WebStorage 是全局按域名共享的) |
| | | const WebStorage = plus.android.importClass('android.webkit.WebStorage') |
| | | if (WebStorage) { |
| | | const ws = WebStorage.getInstance() |
| | | try { ws.deleteAllData() } catch (e) {} |
| | | console.log('[WebView][Android] WebStorage 已清所有 localStorage') |
| | | } |
| | | |
| | | // 清表单数据和密码(可选) |
| | | try { |
| | | const WebViewDatabase = plus.android.importClass('android.webkit.WebViewDatabase') |
| | | const context = plus.android.runtime.appContext |
| | | if (WebViewDatabase && context) { |
| | | const db = WebViewDatabase.getInstance(context) |
| | | if (db && typeof db.clearFormData === 'function') { |
| | | db.clearFormData() |
| | | } |
| | | } |
| | | } catch (e) {} |
| | | } catch (e) { |
| | | console.error('[WebView][Android] 原生清理失败:', e) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * iOS 原生清理:清 NSHTTPCookieStorage 所有 Cookie;并用 WKWebsiteDataStore 清 WKWebView 数据。 |
| | | */ |
| | | function clearIOSWebViewData() { |
| | | // 1. NSHTTPCookieStorage.deleteAllCookies(UIWebView 与部分 WKWebView 共享) |
| | | try { |
| | | const NSHTTPCookieStorage = plus.ios.importClass('NSHTTPCookieStorage') |
| | | if (NSHTTPCookieStorage) { |
| | | const storage = NSHTTPCookieStorage.sharedHTTPCookieStorage() |
| | | if (storage) { |
| | | try { plus.ios.invoke(storage, 'deleteAllCookies') } catch (e) {} |
| | | console.log('[WebView][iOS] NSHTTPCookieStorage 已清所有 Cookie') |
| | | } |
| | | } |
| | | } catch (e) { |
| | | console.error('[WebView][iOS] NSHTTPCookieStorage 清理失败:', e) |
| | | } |
| | | |
| | | // 2. WKWebsiteDataStore.removeDataOfTypes(iOS 9+,清 WKWebView 的 cookie/localStorage/cache) |
| | | // block 部分用空 block 代替,调用 plus.ios.invoke |
| | | try { |
| | | const WKWebsiteDataStore = plus.ios.importClass('WKWebsiteDataStore') |
| | | if (!WKWebsiteDataStore) { |
| | | return |
| | | } |
| | | const allTypes = WKWebsiteDataStore.allWebsiteDataTypes() |
| | | const defaultStore = WKWebsiteDataStore.defaultDataStore() |
| | | const NSDate = plus.ios.importClass('NSDate') |
| | | const distantPast = NSDate ? NSDate.distantPast() : null |
| | | // completionHandler 传一个空 block,避免 native 崩溃 |
| | | const noopHandler = function () {} |
| | | try { |
| | | plus.ios.invoke(defaultStore, 'removeDataOfTypes:modifiedAt:completionHandler:', allTypes, distantPast, noopHandler) |
| | | console.log('[WebView][iOS] WKWebsiteDataStore 已清所有数据') |
| | | } catch (e) { |
| | | console.error('[WebView][iOS] WKWebsiteDataStore 调用失败:', e) |
| | | } |
| | | } catch (e) { |
| | | console.error('[WebView][iOS] WKWebsiteDataStore 初始化失败:', e) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 解码路由参数,异常时回退为空字符串。 |
| | | */ |
| | | function decodeQueryValue(value: unknown) { |