webview.bridge.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // WebView 事件类型定义
  2. const WebviewEvents = {
  3. /**
  4. * 获取平台信息
  5. */
  6. GET_PLATFORM: 'getPlatform',
  7. /**
  8. * 获取状态栏高度
  9. */
  10. GET_STATUS_BAR_HEIGHT: 'getStatusBarHeight',
  11. /**
  12. * 扫码
  13. */
  14. SCAN: 'scan',
  15. /**
  16. * 苹果支付
  17. */
  18. APPLE_PAY: 'applePay',
  19. APPLE_PAY_RESTORE: 'applePayRestore',
  20. /**
  21. * 微信是否安装
  22. */
  23. CHECK_WECHAT_INSTALLED: 'checkWechatInstalled',
  24. /**
  25. * 获取升级信息
  26. */
  27. GET_UPGRADE_INFO: 'getUpgradeInfo',
  28. /**
  29. * 下载升级
  30. */
  31. DOWNLOAD_UPGRADE: 'downloadAndInstall',
  32. /**
  33. * 打开 iframe
  34. */
  35. OPEN_IFRAME: 'openIframe'
  36. } as const;
  37. // 定义 WebView 事件键类型
  38. type WebviewEventKey = keyof typeof WebviewEvents;
  39. type WebviewEventValue = typeof WebviewEvents[WebviewEventKey];
  40. // 定义 uni.webView 类型
  41. interface UniWebView {
  42. postMessage: (options: {
  43. data: {
  44. action: string;
  45. data: {
  46. callbackAction: string;
  47. data?: any;
  48. };
  49. };
  50. }) => void;
  51. }
  52. // 扩展 uni 命名空间
  53. declare global {
  54. interface Uni {
  55. webView?: UniWebView;
  56. }
  57. // 扩展 Window 接口
  58. interface Window {
  59. // 平台标识
  60. platform?: string;
  61. // WebView Bridge 实例
  62. webviewBridge: WebviewBridge;
  63. // 下载进度回调
  64. onDownloadProgress?: (progress: any) => void;
  65. // 动态回调函数
  66. [key: `webviewCallback_${string}`]: ((data: any) => void) | undefined;
  67. }
  68. }
  69. /**
  70. * 重置 window 回调函数
  71. * @param callbackEvent 回调事件名称
  72. */
  73. function resetWindowCallback(callbackEvent: string): void {
  74. const key = callbackEvent as keyof Window;
  75. if (window[key]) {
  76. window[key] = undefined as never;
  77. delete window[key];
  78. }
  79. }
  80. /**
  81. * 获取 WebView 回调
  82. * @param event 事件名称
  83. * @param args 参数
  84. * @returns Promise
  85. */
  86. async function getWebviewCallback<T = any>(
  87. event: string,
  88. args?: any
  89. ): Promise<T> {
  90. if (!uni.webView) {
  91. return Promise.reject(new Error('uni环境异常,请检查uni.webview是否正确引入'));
  92. }
  93. if (window.platform === 'h5') {
  94. return Promise.reject(new Error('请在app中使用'));
  95. }
  96. const callbackEvent = `webviewCallback_${event}`;
  97. try {
  98. return await new Promise<T>((resolve, reject) => {
  99. // 设置回调函数
  100. (window as any)[callbackEvent] = (data: T) => {
  101. resolve(data);
  102. resetWindowCallback(callbackEvent);
  103. };
  104. // 发送消息到 WebView
  105. uni.webView?.postMessage({
  106. data: {
  107. action: event,
  108. data: {
  109. callbackAction: callbackEvent,
  110. data: args
  111. }
  112. }
  113. });
  114. });
  115. } catch (error) {
  116. return Promise.reject(new Error('webview初始化失败,请检查是否正确引入uni.webview'));
  117. }
  118. }
  119. /**
  120. * WebView Bridge 类
  121. * 用于与原生 App 进行通信
  122. */
  123. class WebviewBridge {
  124. constructor() {}
  125. /**
  126. * 获取平台信息
  127. * @returns Promise<string>
  128. */
  129. getPaltform(): Promise<string> {
  130. return getWebviewCallback<string>(WebviewEvents.GET_PLATFORM);
  131. }
  132. /**
  133. * 扫码功能
  134. * @param args 扫码参数
  135. * @returns Promise
  136. */
  137. scan(...args: any[]): Promise<any> {
  138. return getWebviewCallback(WebviewEvents.SCAN, args);
  139. }
  140. /**
  141. * 苹果支付
  142. * @param args 支付参数
  143. * @returns Promise
  144. */
  145. applePay(...args: any[]): Promise<any> {
  146. return getWebviewCallback(WebviewEvents.APPLE_PAY, args);
  147. }
  148. /**
  149. * 苹果支付恢复
  150. * @param args 恢复参数
  151. * @returns Promise
  152. */
  153. applePayRestore(...args: any[]): Promise<any> {
  154. return getWebviewCallback(WebviewEvents.APPLE_PAY_RESTORE, args);
  155. }
  156. /**
  157. * 检查微信是否已安装
  158. * @param args 参数
  159. * @returns Promise<boolean>
  160. */
  161. checkWechatInstalled(...args: any[]): Promise<boolean> {
  162. return getWebviewCallback<boolean>(WebviewEvents.CHECK_WECHAT_INSTALLED, args);
  163. }
  164. /**
  165. * 获取状态栏高度
  166. * @returns Promise<number>
  167. */
  168. getStatusBarHeight(): Promise<number> {
  169. return getWebviewCallback<number>(WebviewEvents.GET_STATUS_BAR_HEIGHT);
  170. }
  171. /**
  172. * 获取升级信息
  173. * @param args 参数
  174. * @returns Promise
  175. */
  176. getUpgradeInfo(...args: any[]): Promise<any> {
  177. return getWebviewCallback(WebviewEvents.GET_UPGRADE_INFO, args);
  178. }
  179. /**
  180. * 打开 iframe
  181. * @param args 参数
  182. * @returns Promise
  183. */
  184. openIframe(...args: any[]): Promise<any> {
  185. return getWebviewCallback(WebviewEvents.OPEN_IFRAME, args);
  186. }
  187. /**
  188. * 下载升级包
  189. * @param url 下载地址
  190. * @param progressCb 进度回调函数
  191. * @returns Promise
  192. */
  193. downloadUpgrade(url: string, progressCb?: (progress: any) => void): Promise<any> {
  194. if (progressCb) {
  195. window.onDownloadProgress = progressCb;
  196. }
  197. return getWebviewCallback(WebviewEvents.DOWNLOAD_UPGRADE, {
  198. url,
  199. progressCb: 'onDownloadProgress'
  200. });
  201. }
  202. }
  203. // 创建实例并挂载到 window
  204. const webviewBridge = new WebviewBridge();
  205. window.webviewBridge = webviewBridge;
  206. export default webviewBridge;
  207. export { WebviewBridge, WebviewEvents };