<

{{title}}

{{file.summary.functions.pct}}%

Functions
{{file.summary.functions.covered}}/{{file.summary.functions.total}}

{{file.summary.branches.pct}}%

Branches
{{file.summary.branches.covered}}/{{file.summary.branches.total}}

{{file.summary.lines.pct}}%

Lines
{{file.summary.lines.covered}}/{{file.summary.lines.total}}
          
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
                
import webview from '@ohos.web.webview'; 
import { TencentQianWebViewHandlers } from '../../TencentQianWebViewConfigurator'; 
 
/** 进度联动回调类型。 */ 
export type WebProgressListener = (progress: number, visible: boolean) => void; 
/** 标题 / 可后退联动回调类型。 */ 
export type WebTitleListener = (title: string, canGoBack: boolean) => void; 
 
/** 
 * 离线 Web 组件(`BuilderNode`)与容器 struct 之间的**共享状态 + 回调载体**。 
 * 
 * 由于 `@Builder` 是全局函数、无法访问 struct 的 `this`/`@State`,容器与 Web 组件 
 * 的联动(进度条、标题、canGoBack、渲染恢复)统一通过本 `@Observed` 对象完成: 
 * - Web 组件(在 `@Builder` 内)写入这些字段; 
 * - 容器 struct 以 `@ObjectLink`/`@State` 引用同一实例,响应式读取渲染顶栏/进度条。 
 * 
 * 复用关键:预热池与真实页共用同一 `@Builder`,通过替换本 model 的 `url`/`handlers` 
 * 即可把「预热态」切换为「真实签署态」,无需重建 Web 组件。 
 */ 
@Observed 
export class WebHostModel { 
  /** 当前主框架 URL。 */ 
  public url: string = 'about:blank'; 
  /** Web 组件 controller(与容器持有的同一实例)。 */ 
  public controller: webview.WebviewController; 
  /** Configurator 生成的事件处理器集合(controller attach 前可为 null)。 */ 
  public handlers: TencentQianWebViewHandlers | null = null; 
 
  // ── 联动状态(Page 顶栏/进度条读;Component 忽略)── 
  public progress: number = 0; 
  public progressVisible: boolean = false; 
  public title: string = ''; 
  public canGoBack: boolean = false; 
  public isPageLoading: boolean = false; 
 
  /** 
   * 一次性「清历史」标志。池复用(HEAVY 预热)借出后,容器 `loadUrl(signingUrl)` 前置为 true; 
   * 首个 `onPageEnd`(signingUrl 加载完成)时执行一次 `clearHistory()`,清掉预热残留 
   * (warmupUrl / about:blank),使 signingUrl 成为唯一历史项 —— 第一次返回即触发退出而非回到预热页。 
   * 清后立即复位,保证不影响签署页内部的多级前进/后退。自建 node(首页即 signingUrl)无需置位。 
   */ 
  public clearHistoryOnce: boolean = false; 
 
  /** 最近一次主框架导航 URL,用于渲染进程异常兜底重载。 */ 
  public lastVisitedUrl: string = ''; 
 
  /** 
   * 渲染进程崩溃连续恢复计数,防止"必崩页面"死循环 reload。 
   * 每次崩溃恢复 +1,页面成功加载完成(onPageEnd)时清零;连续崩溃达 
   * `MAX_RENDER_RECOVERY` 次仍未成功 → 判定不可恢复,触发 onRenderUnrecoverable 关闭容器。 
   * 对齐 Android renderRecoveryCount。 
   */ 
  public renderRecoveryCount: number = 0; 
 
  /** 
   * 上次渲染进程崩溃的时间戳(毫秒)。用于冷却窗口重置:距上次崩溃超过 
   * `RENDER_RECOVERY_RESET_WINDOW` 视为页面已稳定运行过,本次按全新问题处理并重置 
   * `renderRecoveryCount`,避免长时间运行中的偶发(非连续)崩溃累计触顶被误判为不可恢复。 
   */ 
  public lastRenderTerminateAtMs: number = 0; 
 
  /** 
   * 本实例是否借自预热池。渲染进程崩溃时用于决定是否作废池实例 
   * (避免僵尸实例被后续 `obtain` 复用),对齐 Android `fromPool`。 
   */ 
  public fromPool: boolean = false; 
 
  /** 
   * 进度联动回调(容器 struct 设置,用于把 `@Builder` 内的进度事件驱动到 struct `@State`)。 
   * 采用回调而非 `@Observed` 深层响应式,规避跨 `BuilderNode` 属性观察的不确定性。 
   */ 
  public onProgressChanged: WebProgressListener | null = null; 
  /** 标题 / 可后退联动回调(同上)。 */ 
  public onTitleChanged: WebTitleListener | null = null; 
 
  /** 
   * 渲染进程崩溃且无法恢复时的回调(容器 struct 设置)。 
   * `RenderRecovery` 的 `refresh()` + `loadUrl()` 均失败时触发,容器据此关闭页面, 
   * 避免用户停留在持久白屏。对齐 Android `recoverFromRenderProcessGone` 恢复失败时 `finish()`。 
   */ 
  public onRenderUnrecoverable: (() => void) | null = null; 
 
  /** 
   * 请求作废预热池实例的回调(容器在池复用时绑定为 `HarmonyWebViewPool.invalidate`)。 
   * 
   * 借出态实例渲染进程崩溃时,即便 `RenderRecovery` reload 成功,该实例也已是"渲染进程死过的" 
   * 僵尸,归还后会污染池、被后续 `open` 复用致白屏。故崩溃即作废池(避免僵尸复用), 
   * 关闭时不再归还。通过回调解耦,规避 `TencentQianWebNode` ↔ `HarmonyWebViewPool` 循环依赖。 
   * 对齐 Android 借出态 `invalidatePooledWebView`。 
   */ 
  public onPoolInvalidateRequest: (() => void) | null = null; 
 
  /** 
   * 待执行的延迟恢复 timer id(`RenderRecovery.recover` 返回),-1 表示无。 
   * 
   * 崩溃恢复延迟 1s 执行,若用户在此窗口内关闭页面(`aboutToDisappear`),必须 
   * `clearTimeout` 取消,否则回调会访问已销毁/已归还的 controller,造成无效 reload 
   * 或污染已归还的池实例(野指针)。 
   */ 
  public pendingRecoverTimerId: number = -1; 
 
  constructor(controller: webview.WebviewController) { 
    this.controller = controller; 
  } 
 
  /** 
   * 断开全部指向容器 struct 的联动回调(容器 `aboutToDisappear` 时调用)。 
   * 
   * **防泄漏关键**:池 model 生命周期跟随池单例(长),容器 struct 生命周期短。 
   * 归还池后若不清这些捕获了容器 `this` 的闭包,池 model 会一直持有已销毁容器的引用, 
   * 在"归还后 ~ 下次借出前"窗口内造成内存泄漏(上个 Page/Component 无法被回收)。 
   * 自建 node 归还前一并清理也无副作用(随后即 dispose)。 
   */ 
  public clearContainerListeners(): void { 
    // 取消未执行的延迟恢复,避免回调访问已销毁/已归还的 controller(野指针)。 
    this.cancelPendingRecover(); 
    this.onProgressChanged = null; 
    this.onTitleChanged = null; 
    this.onRenderUnrecoverable = null; 
    this.onPoolInvalidateRequest = null; 
  } 
 
  /** 取消待执行的延迟恢复 timer(若有)。容器销毁/归还池、或恢复重新调度前调用。 */ 
  public cancelPendingRecover(): void { 
    if (this.pendingRecoverTimerId !== -1) { 
      clearTimeout(this.pendingRecoverTimerId); 
      this.pendingRecoverTimerId = -1; 
    } 
  } 
} 

              
Code coverage generated by bjc at {{date}}