@yuwenovo/ocr-result-view 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -293,6 +293,7 @@ const viewer = ref<OcrResultViewExpose>()
293
293
  **如何修改主题?**
294
294
 
295
295
  默认深色。可在组件或祖先元素上覆盖 CSS 变量,例如 `--viewer-bg`、`--viewer-panel`、`--viewer-border`、`--viewer-card-text`。例如:
296
+
296
297
  ```vue
297
298
  <template>
298
299
  <div class="viewer-container">
@@ -310,3 +311,7 @@ const viewer = ref<OcrResultViewExpose>()
310
311
  }
311
312
  </style>
312
313
  ```
314
+
315
+ ## 自定义图片加载
316
+
317
+ `imageLoader?: (url: string) => Promise<HTMLImageElement>` 可由宿主提供带鉴权的图片加载器,返回已完成加载/解码的图片。组件仍控制可见页调度、四路并发和图片缓存;不提供时沿用 `imageCrossOrigin` 和原始图片地址。请求头、会话、取消和临时 Blob URL 的释放由宿主管理,组件不持有业务凭据。
@@ -1,2 +1,2 @@
1
- [data-v-61738111],[data-v-61738111]:before,[data-v-61738111]:after{box-sizing:border-box}button[data-v-61738111]{font:inherit;color:inherit;background:0 0;border:0;padding:0}h2[data-v-61738111],h3[data-v-61738111],p[data-v-61738111]{margin:0}svg[data-v-61738111]{vertical-align:middle;display:inline-block}.diff-cards[data-v-61738111]{flex-direction:column;gap:10px;display:flex}.diff-card[data-v-61738111]{--change-color:var(--diff-modify-dot,#f80);border:1px solid var(--viewer-border,#ffffff17);background:var(--diff-card-bg,#ffffff09);border-radius:12px;flex-shrink:0;min-width:0;padding:10px 12px;transition:border-color .15s,box-shadow .15s}.diff-card--insert[data-v-61738111]{--change-color:var(--diff-insert-dot,#00a870)}.diff-card--delete[data-v-61738111]{--change-color:var(--diff-delete-dot,#e34d59)}.diff-card[data-v-61738111]:hover{border-color:color-mix(in srgb, var(--viewer-card-text,#cbd5e1) 30%, transparent)}.diff-card.is-active[data-v-61738111]{border-color:var(--diff-active-border,#38bdf899);box-shadow:0 0 0 2px color-mix(in srgb, var(--diff-active-border,#38bdf899) 10%, transparent)}.diff-card.is-ignored[data-v-61738111]{--change-color:var(--ui-text-subtle,#64748b)}.card-heading[data-v-61738111]{align-items:center;gap:6px;display:flex}.card-select[data-v-61738111]{text-align:left;cursor:pointer;flex:1;align-items:center;gap:8px;min-width:0;display:flex}.type-icon[data-v-61738111]{width:24px;height:24px;color:var(--change-color);background:color-mix(in srgb, var(--change-color) 10%, transparent);border-radius:7px;flex-shrink:0;place-items:center;display:grid}.type-icon svg[data-v-61738111],.card-action svg[data-v-61738111]{width:14px;height:14px}.card-type[data-v-61738111]{color:var(--viewer-card-title,#e2e8f0);font-size:12px;font-weight:600}.card-number[data-v-61738111]{color:var(--ui-text-subtle,#64748b);font-variant-numeric:tabular-nums;font-size:10px}.card-action[data-v-61738111]{width:28px;height:28px;color:var(--ui-text-subtle,#64748b);cursor:pointer;border-radius:7px;flex-shrink:0;place-items:center;display:grid}.card-action[data-v-61738111]:hover{color:var(--viewer-card-title,#e2e8f0);background:var(--viewer-card,#ffffff09)}.card-action[data-v-61738111]:disabled{opacity:.35;cursor:wait}.card-action[data-v-61738111]:focus-visible,.card-select[data-v-61738111]:focus-visible{outline:2px solid var(--diff-active-border,#38bdf899);outline-offset:3px;border-radius:6px}.ignored-label[data-v-61738111]{color:var(--ui-text-subtle,#64748b);white-space:nowrap;font-size:10px}.card-content[data-v-61738111]{cursor:pointer}.text-row[data-v-61738111]{background:var(--viewer-card,#ffffff09);border-radius:7px;align-items:flex-start;gap:10px;margin-top:8px;padding:8px 10px;display:flex}.text-row--single[data-v-61738111]{background:color-mix(in srgb, var(--change-color) 6%, transparent)}.text-label[data-v-61738111]{color:var(--ui-text-subtle,#64748b);flex-shrink:0;padding-top:1px;font-size:10px;line-height:20px}.card-text[data-v-61738111]{min-width:0;color:var(--viewer-card-text,#cbd5e1);overflow-wrap:anywhere;white-space:pre-wrap;font-size:13px;line-height:1.65}.change-mark[data-v-61738111]{background:color-mix(in srgb, var(--change-color) 16%, transparent);border-radius:2px;font-weight:600}.card-location[data-v-61738111]{color:var(--ui-text-subtle,#64748b);margin:8px 0 0;font-size:10px;line-height:14px}[data-v-c65c6ace],[data-v-c65c6ace]:before,[data-v-c65c6ace]:after{box-sizing:border-box}button[data-v-c65c6ace]{font:inherit;color:inherit;background:0 0;border:0;padding:0}h2[data-v-c65c6ace],h3[data-v-c65c6ace],p[data-v-c65c6ace]{margin:0}svg[data-v-c65c6ace]{vertical-align:middle;display:inline-block}.ocr-result-view[data-v-c65c6ace]{flex-direction:column;height:100%;min-height:0;display:flex}.page-btn svg[data-v-c65c6ace]{width:14px;height:14px}.ocr-diff-viewer[data-v-c65c6ace]{min-height:0;color:var(--viewer-card-text,#cbd5e1);background:var(--viewer-bg,#0b1220);flex:1;font-family:Segoe UI,Microsoft YaHei,system-ui,sans-serif;display:flex}.viewer-main[data-v-c65c6ace]{flex-direction:column;flex:1;min-width:0;display:flex}.compare-row[data-v-c65c6ace]{background:var(--viewer-workspace,#080f1c);box-sizing:border-box;flex:1;gap:12px;min-height:0;padding:12px;display:flex;position:relative}.canvas-col[data-v-c65c6ace]{border:1px solid var(--viewer-border,#ffffff17);background:var(--viewer-panel,#111827);border-radius:10px;flex-direction:column;flex:1;min-width:0;display:flex;overflow:hidden}.canvas-info-bar[data-v-c65c6ace]{height:45px;color:var(--viewer-card-title,#e2e8f0);background:var(--viewer-toolbar,#111a2b);border-bottom:1px solid var(--viewer-border,#ffffff17);white-space:nowrap;text-overflow:ellipsis;flex-shrink:0;align-items:center;padding:6px 10px;font-size:12px;font-weight:600;display:flex;overflow:hidden}.canvas-info-bar-left[data-v-c65c6ace]{flex:1;align-items:center;gap:6px;min-width:0;display:flex}.canvas-info-bar-right[data-v-c65c6ace]{flex-shrink:0;align-items:center;gap:4px;margin-left:8px;display:flex}.page-num[data-v-c65c6ace]{color:var(--ui-text-muted,#94a3b8);text-align:center;-webkit-user-select:none;user-select:none;min-width:50px;font-size:12px}.page-btn[data-v-c65c6ace]{border:1px solid var(--viewer-border,#ffffff17);background:var(--viewer-card,#ffffff09);width:24px;height:24px;color:var(--ui-text-muted,#94a3b8);cursor:pointer;border-radius:6px;justify-content:center;align-items:center;padding:0;font-size:10px;line-height:1;transition:background .15s,border-color .15s;display:flex}.page-btn[data-v-c65c6ace]:hover:not(:disabled){color:#bfdbfe;background:#3b82f61f;border-color:#60a5fa52}.page-btn[data-v-c65c6ace]:disabled{opacity:.35;cursor:default}.canvas-info-bar-left-tag[data-v-c65c6ace]{color:#fff;background-color:#10b9812e;border:1px solid #34d39940;border-radius:6px;padding:2px 7px;font-size:12px;line-height:20px}.canvas-info-bar-left-tag.gray[data-v-c65c6ace]{color:var(--viewer-card-text,#cbd5e1);background-color:#94a3b824;border-color:#94a3b833}.canvas-info-bar-left-filename[data-v-c65c6ace]{white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.canvas-scroll[data-v-c65c6ace]{background:var(--viewer-scroll,#1a2230);flex:1;min-height:0;position:relative;overflow-y:scroll}.canvas-scroll--flip[data-v-c65c6ace]{direction:rtl}.virtual-spacer[data-v-c65c6ace]{direction:ltr;width:100%;position:relative}.viewport-canvas-stack[data-v-c65c6ace]{direction:ltr;width:100%;position:sticky;top:0}.compare-canvas[data-v-c65c6ace],.annotation-canvas[data-v-c65c6ace]{width:100%;display:block;position:absolute;inset:0}.compare-canvas[data-v-c65c6ace]{pointer-events:none}.annotation-canvas[data-v-c65c6ace]{z-index:1}.line-svg[data-v-c65c6ace]{pointer-events:none;position:absolute;top:0;left:0}.side-panel[data-v-c65c6ace]{border-left:1px solid var(--viewer-border,#ffffff17);background:var(--viewer-side,#0d1626);flex-direction:column;flex-shrink:0;width:clamp(300px,23vw,360px);min-height:0;display:flex;overflow:hidden}.review-header[data-v-c65c6ace]{flex-shrink:0;padding:18px 16px 12px}.review-title-row[data-v-c65c6ace]{justify-content:space-between;align-items:center;gap:12px;display:flex}.review-title-row h2[data-v-c65c6ace]{color:var(--viewer-card-title,#e2e8f0);align-items:center;gap:8px;font-size:14px;font-weight:650;display:flex}.review-title-row svg[data-v-c65c6ace]{width:16px;height:16px;color:var(--ui-text-subtle,#64748b)}.review-total[data-v-c65c6ace]{color:var(--ui-text-subtle,#64748b);font-variant-numeric:tabular-nums;font-size:11px}.review-segments[data-v-c65c6ace]{background:var(--viewer-card,#ffffff09);border-radius:9px;gap:3px;margin-top:16px;padding:3px;display:flex}.review-segments button[data-v-c65c6ace]{min-width:0;color:var(--ui-text-subtle,#64748b);white-space:nowrap;cursor:pointer;border-radius:7px;flex:1;justify-content:center;align-items:center;gap:6px;padding:7px 4px;font-size:12px;transition:background .15s,color .15s;display:flex}.review-segments button[aria-pressed=true][data-v-c65c6ace]{background:var(--viewer-side,#0d1626);color:var(--viewer-card-title,#e2e8f0);font-weight:600;box-shadow:0 1px 4px #00000014}.review-segments span[data-v-c65c6ace]{font-variant-numeric:tabular-nums;opacity:.65;font-size:10px}.review-types[data-v-c65c6ace]{border-bottom:1px solid var(--viewer-border,#ffffff17);flex-shrink:0;align-items:center;gap:4px;padding:0 12px 12px;display:flex}.review-type[data-v-c65c6ace]{color:var(--ui-text-subtle,#64748b);white-space:nowrap;cursor:pointer;border-radius:6px;flex:1;justify-content:center;align-items:center;gap:4px;padding:5px 3px;font-size:11px;display:flex}.review-type span[data-v-c65c6ace]{opacity:.65;font-variant-numeric:tabular-nums;font-size:10px}.review-type[data-v-c65c6ace]:hover,.review-type[aria-pressed=true][data-v-c65c6ace]{color:var(--viewer-card-title,#e2e8f0);background:var(--viewer-card,#ffffff09)}.review-type[aria-pressed=true][data-v-c65c6ace]{font-weight:600}.side-panel[data-v-c65c6ace] .diff-cards{overscroll-behavior:contain;scrollbar-gutter:stable;background:color-mix(in srgb, var(--viewer-card,#ffffff09) 38%, var(--viewer-side,#0d1626));flex:1;min-height:0;padding:14px 12px 16px;overflow-y:auto}.review-footer[data-v-c65c6ace]{border-top:1px solid var(--viewer-border,#ffffff17);background:var(--viewer-side,#0d1626);flex-shrink:0;align-items:center;gap:8px;padding:12px;display:flex}.review-footer button[data-v-c65c6ace]{cursor:pointer;border-radius:8px;justify-content:center;align-items:center;gap:7px;min-width:0;padding:9px 10px;font-size:12px;transition:background .15s;display:flex}.review-footer svg[data-v-c65c6ace]{flex-shrink:0;width:14px;height:14px}.batch-ignore[data-v-c65c6ace]{color:var(--viewer-card-title,#e2e8f0);background:var(--viewer-card,#ffffff09);flex:1}.batch-ignore span[data-v-c65c6ace]{color:var(--ui-text-subtle,#64748b);font-variant-numeric:tabular-nums;font-size:10px}.batch-restore[data-v-c65c6ace]{color:var(--ui-text-subtle,#64748b)}.review-footer button[data-v-c65c6ace]:hover:not(:disabled){background:var(--diff-card-hover,#3b82f611);color:var(--viewer-card-title,#e2e8f0)}.review-footer button[data-v-c65c6ace]:disabled{opacity:.35;cursor:default}.side-panel button[data-v-c65c6ace]:focus-visible{outline:2px solid var(--diff-active-border,#38bdf899);outline-offset:2px}.review-empty[data-v-c65c6ace]{text-align:center;min-height:0;color:var(--ui-text-subtle,#64748b);flex:1;padding:42px 20px;overflow-y:auto}.empty-symbol[data-v-c65c6ace]{background:var(--viewer-card,#ffffff09);border-radius:14px;place-items:center;width:44px;height:44px;margin:0 auto 14px;display:grid}.empty-symbol svg[data-v-c65c6ace]{width:22px;height:22px}.empty-symbol.is-passed[data-v-c65c6ace]{color:var(--diff-insert-dot,#00a870);background:var(--diff-insert-bg,#34d3991a)}.review-empty h3[data-v-c65c6ace]{color:var(--viewer-card-title,#e2e8f0);font-size:14px;font-weight:600}.review-empty p[data-v-c65c6ace]{margin-top:8px;font-size:12px;line-height:1.6}.review-empty button[data-v-c65c6ace]{color:var(--viewer-card-text,#cbd5e1);cursor:pointer;text-underline-offset:4px;margin-top:20px;font-size:12px;text-decoration:underline}.page-loading[data-v-c65c6ace]{height:200px;color:var(--ui-text-muted,#94a3b8);justify-content:center;align-items:center;font-size:13px;display:flex}
1
+ [data-v-7344a999],[data-v-7344a999]:before,[data-v-7344a999]:after{box-sizing:border-box}button[data-v-7344a999]{font:inherit;color:inherit;background:0 0;border:0;padding:0}h2[data-v-7344a999],h3[data-v-7344a999],p[data-v-7344a999]{margin:0}svg[data-v-7344a999]{vertical-align:middle;display:inline-block}.diff-cards[data-v-7344a999]{flex-direction:column;gap:10px;display:flex}.diff-card[data-v-7344a999]{--change-color:var(--diff-modify-dot,#f80);border:1px solid var(--viewer-border,#ffffff17);background:var(--diff-card-bg,#ffffff09);border-radius:12px;flex-shrink:0;min-width:0;padding:10px 12px;transition:border-color .15s,box-shadow .15s}.diff-card--insert[data-v-7344a999]{--change-color:var(--diff-insert-dot,#00a870)}.diff-card--delete[data-v-7344a999]{--change-color:var(--diff-delete-dot,#e34d59)}.diff-card[data-v-7344a999]:hover{border-color:color-mix(in srgb, var(--viewer-card-text,#cbd5e1) 30%, transparent)}.diff-card.is-active[data-v-7344a999]{border-color:var(--diff-active-border,#38bdf899);box-shadow:0 0 0 2px color-mix(in srgb, var(--diff-active-border,#38bdf899) 10%, transparent)}.diff-card.is-ignored[data-v-7344a999]{--change-color:var(--ui-text-subtle,#64748b)}.card-heading[data-v-7344a999]{align-items:center;gap:6px;display:flex}.card-select[data-v-7344a999]{text-align:left;cursor:pointer;flex:1;align-items:center;gap:8px;min-width:0;display:flex}.type-icon[data-v-7344a999]{width:24px;height:24px;color:var(--change-color);background:color-mix(in srgb, var(--change-color) 10%, transparent);border-radius:7px;flex-shrink:0;place-items:center;display:grid}.type-icon svg[data-v-7344a999],.card-action svg[data-v-7344a999]{width:14px;height:14px}.card-type[data-v-7344a999]{color:var(--viewer-card-title,#e2e8f0);font-size:12px;font-weight:600}.card-number[data-v-7344a999]{color:var(--ui-text-subtle,#64748b);font-variant-numeric:tabular-nums;font-size:10px}.card-action[data-v-7344a999]{width:28px;height:28px;color:var(--ui-text-subtle,#64748b);cursor:pointer;border-radius:7px;flex-shrink:0;place-items:center;display:grid}.card-action[data-v-7344a999]:hover{color:var(--viewer-card-title,#e2e8f0);background:var(--viewer-card,#ffffff09)}.card-action[data-v-7344a999]:disabled{opacity:.35;cursor:wait}.card-action[data-v-7344a999]:focus-visible,.card-select[data-v-7344a999]:focus-visible{outline:2px solid var(--diff-active-border,#38bdf899);outline-offset:3px;border-radius:6px}.ignored-label[data-v-7344a999]{color:var(--ui-text-subtle,#64748b);white-space:nowrap;font-size:10px}.card-content[data-v-7344a999]{cursor:pointer}.text-row[data-v-7344a999]{background:var(--viewer-card,#ffffff09);border-radius:7px;align-items:flex-start;gap:10px;margin-top:8px;padding:8px 10px;display:flex}.text-row--single[data-v-7344a999]{background:color-mix(in srgb, var(--change-color) 6%, transparent)}.text-label[data-v-7344a999]{color:var(--ui-text-subtle,#64748b);flex-shrink:0;padding-top:1px;font-size:10px;line-height:20px}.card-text[data-v-7344a999]{min-width:0;color:var(--viewer-card-text,#cbd5e1);overflow-wrap:anywhere;white-space:pre-wrap;font-size:13px;line-height:1.65}.change-mark[data-v-7344a999]{background:color-mix(in srgb, var(--change-color) 16%, transparent);border-radius:2px;font-weight:600}.card-location[data-v-7344a999]{color:var(--ui-text-subtle,#64748b);margin:8px 0 0;font-size:10px;line-height:14px}[data-v-c1f84581],[data-v-c1f84581]:before,[data-v-c1f84581]:after{box-sizing:border-box}button[data-v-c1f84581]{font:inherit;color:inherit;background:0 0;border:0;padding:0}h2[data-v-c1f84581],h3[data-v-c1f84581],p[data-v-c1f84581]{margin:0}svg[data-v-c1f84581]{vertical-align:middle;display:inline-block}.ocr-result-view[data-v-c1f84581]{flex-direction:column;height:100%;min-height:0;display:flex}.page-btn svg[data-v-c1f84581]{width:14px;height:14px}.ocr-diff-viewer[data-v-c1f84581]{min-height:0;color:var(--viewer-card-text,#cbd5e1);background:var(--viewer-bg,#0b1220);flex:1;font-family:Segoe UI,Microsoft YaHei,system-ui,sans-serif;display:flex}.viewer-main[data-v-c1f84581]{flex-direction:column;flex:1;min-width:0;display:flex}.compare-row[data-v-c1f84581]{background:var(--viewer-workspace,#080f1c);box-sizing:border-box;flex:1;gap:12px;min-height:0;padding:12px;display:flex;position:relative}.canvas-col[data-v-c1f84581]{border:1px solid var(--viewer-border,#ffffff17);background:var(--viewer-panel,#111827);border-radius:10px;flex-direction:column;flex:1;min-width:0;display:flex;overflow:hidden}.canvas-info-bar[data-v-c1f84581]{height:45px;color:var(--viewer-card-title,#e2e8f0);background:var(--viewer-toolbar,#111a2b);border-bottom:1px solid var(--viewer-border,#ffffff17);white-space:nowrap;text-overflow:ellipsis;flex-shrink:0;align-items:center;padding:6px 10px;font-size:12px;font-weight:600;display:flex;overflow:hidden}.canvas-info-bar-left[data-v-c1f84581]{flex:1;align-items:center;gap:6px;min-width:0;display:flex}.canvas-info-bar-right[data-v-c1f84581]{flex-shrink:0;align-items:center;gap:4px;margin-left:8px;display:flex}.page-num[data-v-c1f84581]{color:var(--ui-text-muted,#94a3b8);text-align:center;-webkit-user-select:none;user-select:none;min-width:50px;font-size:12px}.page-btn[data-v-c1f84581]{border:1px solid var(--viewer-border,#ffffff17);background:var(--viewer-card,#ffffff09);width:24px;height:24px;color:var(--ui-text-muted,#94a3b8);cursor:pointer;border-radius:6px;justify-content:center;align-items:center;padding:0;font-size:10px;line-height:1;transition:background .15s,border-color .15s;display:flex}.page-btn[data-v-c1f84581]:hover:not(:disabled){color:#bfdbfe;background:#3b82f61f;border-color:#60a5fa52}.page-btn[data-v-c1f84581]:disabled{opacity:.35;cursor:default}.canvas-info-bar-left-tag[data-v-c1f84581]{color:#fff;background-color:#10b9812e;border:1px solid #34d39940;border-radius:6px;padding:2px 7px;font-size:12px;line-height:20px}.canvas-info-bar-left-tag.gray[data-v-c1f84581]{color:var(--viewer-card-text,#cbd5e1);background-color:#94a3b824;border-color:#94a3b833}.canvas-info-bar-left-filename[data-v-c1f84581]{white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.canvas-scroll[data-v-c1f84581]{background:var(--viewer-scroll,#1a2230);flex:1;min-height:0;position:relative;overflow-y:scroll}.canvas-scroll--flip[data-v-c1f84581]{direction:rtl}.virtual-spacer[data-v-c1f84581]{direction:ltr;width:100%;position:relative}.viewport-canvas-stack[data-v-c1f84581]{direction:ltr;width:100%;position:sticky;top:0}.compare-canvas[data-v-c1f84581],.annotation-canvas[data-v-c1f84581]{width:100%;display:block;position:absolute;inset:0}.compare-canvas[data-v-c1f84581]{pointer-events:none}.annotation-canvas[data-v-c1f84581]{z-index:1}.line-svg[data-v-c1f84581]{pointer-events:none;position:absolute;top:0;left:0}.side-panel[data-v-c1f84581]{border-left:1px solid var(--viewer-border,#ffffff17);background:var(--viewer-side,#0d1626);flex-direction:column;flex-shrink:0;width:clamp(300px,23vw,360px);min-height:0;display:flex;overflow:hidden}.review-header[data-v-c1f84581]{flex-shrink:0;padding:18px 16px 12px}.review-title-row[data-v-c1f84581]{justify-content:space-between;align-items:center;gap:12px;display:flex}.review-title-row h2[data-v-c1f84581]{color:var(--viewer-card-title,#e2e8f0);align-items:center;gap:8px;font-size:14px;font-weight:650;display:flex}.review-title-row svg[data-v-c1f84581]{width:16px;height:16px;color:var(--ui-text-subtle,#64748b)}.review-total[data-v-c1f84581]{color:var(--ui-text-subtle,#64748b);font-variant-numeric:tabular-nums;font-size:11px}.review-segments[data-v-c1f84581]{background:var(--viewer-card,#ffffff09);border-radius:9px;gap:3px;margin-top:16px;padding:3px;display:flex}.review-segments button[data-v-c1f84581]{min-width:0;color:var(--ui-text-subtle,#64748b);white-space:nowrap;cursor:pointer;border-radius:7px;flex:1;justify-content:center;align-items:center;gap:6px;padding:7px 4px;font-size:12px;transition:background .15s,color .15s;display:flex}.review-segments button[aria-pressed=true][data-v-c1f84581]{background:var(--viewer-side,#0d1626);color:var(--viewer-card-title,#e2e8f0);font-weight:600;box-shadow:0 1px 4px #00000014}.review-segments span[data-v-c1f84581]{font-variant-numeric:tabular-nums;opacity:.65;font-size:10px}.review-types[data-v-c1f84581]{border-bottom:1px solid var(--viewer-border,#ffffff17);flex-shrink:0;align-items:center;gap:4px;padding:0 12px 12px;display:flex}.review-type[data-v-c1f84581]{color:var(--ui-text-subtle,#64748b);white-space:nowrap;cursor:pointer;border-radius:6px;flex:1;justify-content:center;align-items:center;gap:4px;padding:5px 3px;font-size:11px;display:flex}.review-type span[data-v-c1f84581]{opacity:.65;font-variant-numeric:tabular-nums;font-size:10px}.review-type[data-v-c1f84581]:hover,.review-type[aria-pressed=true][data-v-c1f84581]{color:var(--viewer-card-title,#e2e8f0);background:var(--viewer-card,#ffffff09)}.review-type[aria-pressed=true][data-v-c1f84581]{font-weight:600}.side-panel[data-v-c1f84581] .diff-cards{overscroll-behavior:contain;scrollbar-gutter:stable;background:color-mix(in srgb, var(--viewer-card,#ffffff09) 38%, var(--viewer-side,#0d1626));flex:1;min-height:0;padding:14px 12px 16px;overflow-y:auto}.review-footer[data-v-c1f84581]{border-top:1px solid var(--viewer-border,#ffffff17);background:var(--viewer-side,#0d1626);flex-shrink:0;align-items:center;gap:8px;padding:12px;display:flex}.review-footer button[data-v-c1f84581]{cursor:pointer;border-radius:8px;justify-content:center;align-items:center;gap:7px;min-width:0;padding:9px 10px;font-size:12px;transition:background .15s;display:flex}.review-footer svg[data-v-c1f84581]{flex-shrink:0;width:14px;height:14px}.batch-ignore[data-v-c1f84581]{color:var(--viewer-card-title,#e2e8f0);background:var(--viewer-card,#ffffff09);flex:1}.batch-ignore span[data-v-c1f84581]{color:var(--ui-text-subtle,#64748b);font-variant-numeric:tabular-nums;font-size:10px}.batch-restore[data-v-c1f84581]{color:var(--ui-text-subtle,#64748b)}.review-footer button[data-v-c1f84581]:hover:not(:disabled){background:var(--diff-card-hover,#3b82f611);color:var(--viewer-card-title,#e2e8f0)}.review-footer button[data-v-c1f84581]:disabled{opacity:.35;cursor:default}.side-panel button[data-v-c1f84581]:focus-visible{outline:2px solid var(--diff-active-border,#38bdf899);outline-offset:2px}.review-empty[data-v-c1f84581]{text-align:center;min-height:0;color:var(--ui-text-subtle,#64748b);flex:1;padding:42px 20px;overflow-y:auto}.empty-symbol[data-v-c1f84581]{background:var(--viewer-card,#ffffff09);border-radius:14px;place-items:center;width:44px;height:44px;margin:0 auto 14px;display:grid}.empty-symbol svg[data-v-c1f84581]{width:22px;height:22px}.empty-symbol.is-passed[data-v-c1f84581]{color:var(--diff-insert-dot,#00a870);background:var(--diff-insert-bg,#34d3991a)}.review-empty h3[data-v-c1f84581]{color:var(--viewer-card-title,#e2e8f0);font-size:14px;font-weight:600}.review-empty p[data-v-c1f84581]{margin-top:8px;font-size:12px;line-height:1.6}.review-empty button[data-v-c1f84581]{color:var(--viewer-card-text,#cbd5e1);cursor:pointer;text-underline-offset:4px;margin-top:20px;font-size:12px;text-decoration:underline}.page-loading[data-v-c1f84581]{height:200px;color:var(--ui-text-muted,#94a3b8);justify-content:center;align-items:center;font-size:13px;display:flex}
2
2
  /*$vite$:1*/
@@ -97,7 +97,7 @@ function N(e, t) {
97
97
  var se = d({
98
98
  name: "lucide-arrow-left-right",
99
99
  render: N
100
- }), ce = { class: "diff-cards" }, le = { class: "card-heading" }, ue = [
100
+ }), ce = ["data-diff-index"], le = { class: "card-heading" }, ue = [
101
101
  "aria-label",
102
102
  "aria-pressed",
103
103
  "onClick"
@@ -126,8 +126,8 @@ var se = d({
126
126
  activeTab: {}
127
127
  },
128
128
  emits: ["select", "ignore"],
129
- setup(o, { emit: s }) {
130
- let c = o, l = s, u = {
129
+ setup(o, { expose: s, emit: c }) {
130
+ let l = o, u = c, d = {
131
131
  table_insert: "新增表格",
132
132
  table_delete: "删除表格",
133
133
  row_insert: "新增表格行",
@@ -141,15 +141,24 @@ var se = d({
141
141
  cell_split: "拆分单元格",
142
142
  cell_span_modify: "单元格跨度修改"
143
143
  };
144
- function d(e, t) {
145
- return e.domain === "table" && e.tableChange ? u[e.tableChange] : t;
144
+ function f(e, t) {
145
+ return e.domain === "table" && e.tableChange ? d[e.tableChange] : t;
146
146
  }
147
- let f = t(() => ne(c.diffDetail, c.activeTab ?? "all", c.reviewFilter));
148
- function m(e) {
147
+ let m = t(() => ne(l.diffDetail, l.activeTab ?? "all", l.reviewFilter)), h = _(null);
148
+ function ee(e) {
149
+ let t = h.value, n = t?.querySelector(`[data-diff-index="${e}"]`);
150
+ if (!t || !n || t.clientHeight <= 0) return;
151
+ let r = t.getBoundingClientRect(), i = n.getBoundingClientRect(), a = r.top + t.clientTop + 12, o = r.top + t.clientTop + t.clientHeight - 12;
152
+ if (i.top >= a && i.bottom <= o) return;
153
+ let s = i.height > o - a || i.top < a ? i.top - a : i.bottom - o;
154
+ t.scrollTop += s;
155
+ }
156
+ s({ scrollToCard: ee });
157
+ function te(e) {
149
158
  let t = e.type !== "insert", n = (t ? e.srcPage : e.tgtPage) + 1, r = t ? e.sourceLine : e.targetLine;
150
159
  return `第 ${n} 页${e.domain === "table" || r < 0 ? "" : ` · ${t ? "标准" : "比对"}第 ${r + 1} 行`}`;
151
160
  }
152
- function h(e, t) {
161
+ function S(e, t) {
153
162
  let n = [...e];
154
163
  if (t === void 0) return [{
155
164
  text: e,
@@ -174,40 +183,45 @@ var se = d({
174
183
  changed: !1
175
184
  }), i;
176
185
  }
177
- return (t, s) => (g(), i("div", ce, [(g(!0), i(e, null, v(f.value, (u) => (g(), i("article", {
178
- key: u.data.diffId,
179
- class: p(["diff-card", [`diff-card--${u.type}`, {
180
- "is-active": o.activeIndex === u.idx,
181
- "is-ignored": u.data.ignored
186
+ return (t, s) => (g(), i("div", {
187
+ ref_key: "cardsRef",
188
+ ref: h,
189
+ class: "diff-cards"
190
+ }, [(g(!0), i(e, null, v(m.value, (c) => (g(), i("article", {
191
+ key: c.data.diffId,
192
+ "data-diff-index": c.idx,
193
+ class: p(["diff-card", [`diff-card--${c.type}`, {
194
+ "is-active": o.activeIndex === c.idx,
195
+ "is-ignored": c.data.ignored
182
196
  }]])
183
197
  }, [y(t.$slots, "default", {
184
- item: u.data,
185
- index: u.idx,
186
- active: o.activeIndex === u.idx,
187
- select: () => l("select", u.idx),
198
+ item: c.data,
199
+ index: c.idx,
200
+ active: o.activeIndex === c.idx,
201
+ select: () => u("select", c.idx),
188
202
  ignore: (e) => {
189
- !c.readonly && !o.busy && l("ignore", u.data.diffId, e);
203
+ !l.readonly && !o.busy && u("ignore", c.data.diffId, e);
190
204
  }
191
205
  }, () => [a("div", le, [
192
206
  a("button", {
193
207
  class: "card-select",
194
- "aria-label": `定位第 ${u.idx + 1} 处差异,${m(u.data)}`,
195
- "aria-pressed": o.activeIndex === u.idx,
196
- onClick: (e) => l("select", u.idx)
208
+ "aria-label": `定位第 ${c.idx + 1} 处差异,${te(c.data)}`,
209
+ "aria-pressed": o.activeIndex === c.idx,
210
+ onClick: (e) => u("select", c.idx)
197
211
  }, [
198
- a("span", de, [u.type === "insert" ? (g(), n(x(k), { key: 0 })) : u.type === "delete" ? (g(), n(x(oe), { key: 1 })) : (g(), n(x(se), { key: 2 }))]),
199
- a("span", P, b(d(u.data, u.type === "modify" ? "修改" : u.type === "delete" ? "删除" : "新增")), 1),
200
- a("span", F, b(String(u.idx + 1).padStart(2, "0")), 1)
212
+ a("span", de, [c.type === "insert" ? (g(), n(x(k), { key: 0 })) : c.type === "delete" ? (g(), n(x(oe), { key: 1 })) : (g(), n(x(se), { key: 2 }))]),
213
+ a("span", P, b(f(c.data, c.type === "modify" ? "修改" : c.type === "delete" ? "删除" : "新增")), 1),
214
+ a("span", F, b(String(c.idx + 1).padStart(2, "0")), 1)
201
215
  ], 8, ue),
202
- u.data.ignored ? (g(), i("span", fe, "已忽略")) : r("", !0),
203
- c.readonly ? r("", !0) : (g(), i("button", {
216
+ c.data.ignored ? (g(), i("span", fe, "已忽略")) : r("", !0),
217
+ l.readonly ? r("", !0) : (g(), i("button", {
204
218
  key: 1,
205
219
  class: "card-action",
206
220
  disabled: o.busy,
207
- title: u.data.ignored ? "撤销忽略" : "忽略此差异",
208
- "aria-label": `${u.data.ignored ? "撤销忽略" : "忽略"}第 ${u.idx + 1} 处差异`,
209
- onClick: (e) => l("ignore", u.data.diffId, !u.data.ignored)
210
- }, [u.data.ignored ? (g(), n(x(ie), {
221
+ title: c.data.ignored ? "撤销忽略" : "忽略此差异",
222
+ "aria-label": `${c.data.ignored ? "撤销忽略" : "忽略"}第 ${c.idx + 1} 处差异`,
223
+ onClick: (e) => u("ignore", c.data.diffId, !c.data.ignored)
224
+ }, [c.data.ignored ? (g(), n(x(ie), {
211
225
  key: 0,
212
226
  "aria-hidden": "true"
213
227
  })) : (g(), n(x(re), {
@@ -216,20 +230,20 @@ var se = d({
216
230
  }))], 8, I))
217
231
  ]), a("div", {
218
232
  class: "card-content",
219
- onClick: (e) => l("select", u.idx)
220
- }, [u.data.type === "modify" ? (g(), i(e, { key: 0 }, [a("div", pe, [s[0] ||= a("span", { class: "text-label" }, "标准", -1), a("span", me, [(g(!0), i(e, null, v(h(u.data.delChars, u.data.sourceChangeRanges), (e, t) => (g(), i("span", {
233
+ onClick: (e) => u("select", c.idx)
234
+ }, [c.data.type === "modify" ? (g(), i(e, { key: 0 }, [a("div", pe, [s[0] ||= a("span", { class: "text-label" }, "标准", -1), a("span", me, [(g(!0), i(e, null, v(S(c.data.delChars, c.data.sourceChangeRanges), (e, t) => (g(), i("span", {
221
235
  key: t,
222
236
  class: p({ "change-mark": e.changed })
223
- }, b(e.text), 3))), 128))])]), a("div", he, [s[1] ||= a("span", { class: "text-label" }, "比对", -1), a("span", ge, [(g(!0), i(e, null, v(h(u.data.insChars, u.data.targetChangeRanges), (e, t) => (g(), i("span", {
237
+ }, b(e.text), 3))), 128))])]), a("div", he, [s[1] ||= a("span", { class: "text-label" }, "比对", -1), a("span", ge, [(g(!0), i(e, null, v(S(c.data.insChars, c.data.targetChangeRanges), (e, t) => (g(), i("span", {
224
238
  key: t,
225
239
  class: p({ "change-mark": e.changed })
226
- }, b(e.text), 3))), 128))])])], 64)) : (g(), i("div", _e, [a("span", ve, b(u.data.chars || "表格结构变更"), 1)])), a("p", R, b(m(u.data)), 1)], 8, L)], !0)], 2))), 128))]));
240
+ }, b(e.text), 3))), 128))])])], 64)) : (g(), i("div", _e, [a("span", ve, b(c.data.chars || "表格结构变更"), 1)])), a("p", R, b(te(c.data)), 1)], 8, L)], !0)], 10, ce))), 128))], 512));
227
241
  }
228
242
  }), z = (e, t) => {
229
243
  let n = e.__vccOpts || e;
230
244
  for (let [e, r] of t) n[e] = r;
231
245
  return n;
232
- }, be = /*#__PURE__*/ z(ye, [["__scopeId", "data-v-61738111"]]), xe = {
246
+ }, be = /*#__PURE__*/ z(ye, [["__scopeId", "data-v-7344a999"]]), xe = {
233
247
  viewBox: "0 0 24 24",
234
248
  width: "1.2em",
235
249
  height: "1.2em"
@@ -270,7 +284,7 @@ var we = d({
270
284
  width: "1.2em",
271
285
  height: "1.2em"
272
286
  };
273
- function U(e, t) {
287
+ function Te(e, t) {
274
288
  return g(), i("svg", H, [...t[0] ||= [a("path", {
275
289
  fill: "none",
276
290
  stroke: "currentColor",
@@ -280,16 +294,16 @@ function U(e, t) {
280
294
  d: "m11 17l-5-5l5-5m7 10l-5-5l5-5"
281
295
  }, null, -1)]]);
282
296
  }
283
- var Te = d({
297
+ var Ee = d({
284
298
  name: "lucide-chevrons-left",
285
- render: U
286
- }), W = {
299
+ render: Te
300
+ }), U = {
287
301
  viewBox: "0 0 24 24",
288
302
  width: "1.2em",
289
303
  height: "1.2em"
290
304
  };
291
- function G(e, t) {
292
- return g(), i("svg", W, [...t[0] ||= [a("path", {
305
+ function W(e, t) {
306
+ return g(), i("svg", U, [...t[0] ||= [a("path", {
293
307
  fill: "none",
294
308
  stroke: "currentColor",
295
309
  "stroke-linecap": "round",
@@ -298,16 +312,16 @@ function G(e, t) {
298
312
  d: "m15 18l-6-6l6-6"
299
313
  }, null, -1)]]);
300
314
  }
301
- var Ee = d({
315
+ var De = d({
302
316
  name: "lucide-chevron-left",
303
- render: G
304
- }), De = {
317
+ render: W
318
+ }), Oe = {
305
319
  viewBox: "0 0 24 24",
306
320
  width: "1.2em",
307
321
  height: "1.2em"
308
322
  };
309
- function Oe(e, t) {
310
- return g(), i("svg", De, [...t[0] ||= [a("path", {
323
+ function ke(e, t) {
324
+ return g(), i("svg", Oe, [...t[0] ||= [a("path", {
311
325
  fill: "none",
312
326
  stroke: "currentColor",
313
327
  "stroke-linecap": "round",
@@ -316,16 +330,16 @@ function Oe(e, t) {
316
330
  d: "m9 18l6-6l-6-6"
317
331
  }, null, -1)]]);
318
332
  }
319
- var ke = d({
333
+ var Ae = d({
320
334
  name: "lucide-chevron-right",
321
- render: Oe
322
- }), Ae = {
335
+ render: ke
336
+ }), G = {
323
337
  viewBox: "0 0 24 24",
324
338
  width: "1.2em",
325
339
  height: "1.2em"
326
340
  };
327
341
  function K(e, t) {
328
- return g(), i("svg", Ae, [...t[0] ||= [a("path", {
342
+ return g(), i("svg", G, [...t[0] ||= [a("path", {
329
343
  fill: "none",
330
344
  stroke: "currentColor",
331
345
  "stroke-linecap": "round",
@@ -376,7 +390,8 @@ var je = d({
376
390
  type: Boolean,
377
391
  default: !0
378
392
  },
379
- imageCrossOrigin: { default: "anonymous" }
393
+ imageCrossOrigin: { default: "anonymous" },
394
+ imageLoader: {}
380
395
  },
381
396
  emits: [
382
397
  "ignore",
@@ -476,7 +491,7 @@ var je = d({
476
491
  modify: k.value.modifyCount,
477
492
  delete: k.value.deleteCount,
478
493
  insert: k.value.insertCount
479
- })), M = _(0), N = _(0), se = _(), ce = _(), le = _(), ue = _(), de = _(), P = _(), F = _(), fe = _(), I = _([]), L = _([]), pe = _(1), me = _(1), he = _(1), ge = _(1), _e = Math.SQRT2, ve = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map(), ye = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Set(), xe = [], Se = [], B = 0, V = 0, H = 0, U = 0, W = 0, G = null, De = !1, Oe = !1, Ae, K = !1, xt = [];
494
+ })), M = _(0), N = _(0), se = _(), ce = _(), le = _(), ue = _(), de = _(), P = _(), F = _(), fe = _(), I = _([]), L = _([]), pe = _(1), me = _(1), he = _(1), ge = _(1), _e = Math.SQRT2, ve = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map(), ye = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Set(), xe = [], Se = [], B = 0, V = 0, H = 0, Te = 0, U = 0, W = null, Oe = !1, ke = !1, G, K = !1, xt = [];
480
495
  function St(e) {
481
496
  let t = /* @__PURE__ */ new Map();
482
497
  for (let n of e) {
@@ -569,7 +584,14 @@ var je = d({
569
584
  t.name = "AbortError", n(t);
570
585
  return;
571
586
  }
572
- V++;
587
+ if (V++, w.imageLoader) {
588
+ Promise.resolve().then(() => w.imageLoader(e)).then(t, (t) => {
589
+ K || T("image-error", e), n(t);
590
+ }).finally(() => {
591
+ V--, At();
592
+ });
593
+ return;
594
+ }
573
595
  let r = new Image();
574
596
  w.imageCrossOrigin !== null && (r.crossOrigin = w.imageCrossOrigin), r.onload = () => {
575
597
  r.onload = null, r.onerror = null, V--, At(), t(r);
@@ -684,8 +706,8 @@ var je = d({
684
706
  });
685
707
  }
686
708
  }
687
- if (c && G !== null) {
688
- let e = zt(G);
709
+ if (c && W !== null) {
710
+ let e = zt(W);
689
711
  e > 0 && (i.save(), i.globalAlpha = e, i.strokeStyle = Rt[c.color].pulse, i.lineWidth = 1 + e * 4, i.shadowColor = Rt[c.color].pulse, i.shadowBlur = e * 8, i.strokeRect(c.x, c.y, c.w, c.h), i.restore());
690
712
  }
691
713
  e === "src" ? xe = s : Se = s;
@@ -710,15 +732,15 @@ var je = d({
710
732
  Z(e);
711
733
  }
712
734
  function Q(e) {
713
- (!e || e === "src") && (De = !0), (!e || e === "tgt") && (Oe = !0), !H && (H = requestAnimationFrame(() => {
735
+ (!e || e === "src") && (Oe = !0), (!e || e === "tgt") && (ke = !0), !H && (H = requestAnimationFrame(() => {
714
736
  H = 0;
715
- let e = De, t = Oe;
716
- De = !1, Oe = !1, e && Bt("src"), t && Bt("tgt"), Gt(), Ut();
737
+ let e = Oe, t = ke;
738
+ Oe = !1, ke = !1, e && Bt("src"), t && Bt("tgt"), Gt(), Ut();
717
739
  }));
718
740
  }
719
741
  function Vt() {
720
- U ||= requestAnimationFrame(() => {
721
- U = 0, X("src", !0), X("tgt", !0);
742
+ Te ||= requestAnimationFrame(() => {
743
+ Te = 0, X("src", !0), X("tgt", !0);
722
744
  });
723
745
  }
724
746
  function Ht(e) {
@@ -782,23 +804,26 @@ var je = d({
782
804
  t && (Yt("src", e, t.srcPage), Yt("tgt", e, t.tgtPage));
783
805
  }
784
806
  function Zt() {
785
- if (W && cancelAnimationFrame(W), window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
786
- W = 0, G = null, Z("src"), Z("tgt");
807
+ if (U && cancelAnimationFrame(U), window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
808
+ U = 0, W = null, Z("src"), Z("tgt");
787
809
  return;
788
810
  }
789
811
  let e = performance.now(), t = (n) => {
790
- G = Math.min(1, (n - e) / 720), Z("src"), Z("tgt"), G < 1 ? W = requestAnimationFrame(t) : (W = 0, G = null, Z("src"), Z("tgt"));
812
+ W = Math.min(1, (n - e) / 720), Z("src"), Z("tgt"), W < 1 ? U = requestAnimationFrame(t) : (U = 0, W = null, Z("src"), Z("tgt"));
791
813
  };
792
- W = requestAnimationFrame(t);
814
+ U = requestAnimationFrame(t);
793
815
  }
794
816
  async function Qt(e) {
795
817
  let t = w.diffDetail[e];
796
818
  t && (await Promise.all([Ft("src", t.srcPage), Ft("tgt", t.tgtPage)]), !(K || A.value !== e) && (Xt(e), Q(), Zt()));
797
819
  }
798
- function $(e) {
799
- K || (T("select", w.diffDetail[e] ?? null, e), A.value = e, Xt(e), Q(), Qt(e));
820
+ let $t = _(null);
821
+ function $(e, t = !0) {
822
+ K || (T("select", w.diffDetail[e] ?? null, e), A.value = e, t && f(() => {
823
+ !K && A.value === e && $t.value?.scrollToCard(e);
824
+ }), Xt(e), Q(), Qt(e));
800
825
  }
801
- function $t(e, t) {
826
+ function en(e, t) {
802
827
  let n = Et(t), r = Y(t);
803
828
  if (!n || !r) return;
804
829
  let i = n.getBoundingClientRect(), a = (e.clientX - i.left) * r.clientWidth / i.width, o = (e.clientY - i.top) * r.clientHeight / i.height, s = t === "src" ? xe : Se;
@@ -807,63 +832,63 @@ var je = d({
807
832
  if (a >= t.x - 3 && a <= t.x + t.w + 3 && o >= t.y - 3 && o <= t.y + t.h + 3) return t.pairIndex;
808
833
  }
809
834
  }
810
- function en(e, t) {
811
- let n = $t(e, t);
835
+ function tn(e, t) {
836
+ let n = en(e, t);
812
837
  n !== void 0 && $(n);
813
838
  }
814
- function tn(e, t) {
839
+ function nn(e, t) {
815
840
  let n = e.currentTarget;
816
- n.style.cursor = $t(e, t) === void 0 ? "default" : "pointer";
841
+ n.style.cursor = en(e, t) === void 0 ? "default" : "pointer";
817
842
  }
818
- let nn = t(() => O.value[0]?.idx ?? -1);
819
- function rn() {
843
+ let rn = t(() => O.value[0]?.idx ?? -1);
844
+ function an() {
820
845
  I.value = [], L.value = [], pe.value = 1, me.value = 1, xe = [], Se = [], z.clear();
821
846
  }
822
847
  te(async () => {
823
- K = !1, await f(), X("src"), X("tgt"), await f(), $(nn.value), Ae = new ResizeObserver(Vt), P.value && Ae.observe(P.value), F.value && Ae.observe(F.value);
848
+ K = !1, await f(), X("src"), X("tgt"), await f(), $(rn.value), G = new ResizeObserver(Vt), P.value && G.observe(P.value), F.value && G.observe(F.value);
824
849
  }), S(() => [w.sourcePages, w.targetPages], async () => {
825
- rn(), await f(), X("src"), X("tgt"), await f(), $(nn.value);
850
+ an(), await f(), X("src"), X("tgt"), await f(), $(rn.value);
826
851
  }, { deep: !0 }), S([j, D], () => {
827
- T("filter-change", j.value, D.value), $(nn.value);
852
+ T("filter-change", j.value, D.value), $(rn.value);
828
853
  }), S(() => w.diffDetail, () => {
829
854
  let e = A.value;
830
855
  $((O.value.find((t) => t.idx >= e) ?? O.value[O.value.length - 1])?.idx ?? -1);
831
856
  }), ee(() => {
832
- K = !0, Ae?.disconnect(), H && cancelAnimationFrame(H), U && cancelAnimationFrame(U), W && cancelAnimationFrame(W);
857
+ K = !0, G?.disconnect(), H && cancelAnimationFrame(H), Te && cancelAnimationFrame(Te), U && cancelAnimationFrame(U);
833
858
  for (let e of R.values()) e.image && (e.image.src = "");
834
859
  R.clear();
835
860
  });
836
- async function an(e) {
861
+ async function on(e) {
837
862
  let t = typeof e == "string" ? w.diffDetail.findIndex((t) => t.diffId === e) : e;
838
863
  return !Number.isInteger(t) || !w.diffDetail[t] || K ? !1 : (ae.value.has(t) || (j.value = "all", D.value = "all", await f()), $(t), !0);
839
864
  }
840
- function on(e) {
865
+ function sn(e) {
841
866
  let t = O.value.findIndex((e) => e.idx === A.value), n = O.value[t + e];
842
867
  return n ? ($(n.idx), !0) : !1;
843
868
  }
844
- function sn(e, t) {
869
+ function cn(e, t) {
845
870
  let n = e === "source" ? "src" : "tgt";
846
871
  return !Number.isInteger(t) || t < 0 || t >= q(n).length ? !1 : (Kt(n, t), !0);
847
872
  }
848
- function cn(e, t = D.value) {
873
+ function ln(e, t = D.value) {
849
874
  j.value = e, D.value = t;
850
875
  }
851
- function ln() {
876
+ function un() {
852
877
  z.clear(), Q();
853
878
  }
854
879
  return S(M, (e) => T("page-change", "source", e)), S(N, (e) => T("page-change", "target", e)), d({
855
- selectDiff: an,
856
- nextDiff: () => on(1),
857
- previousDiff: () => on(-1),
858
- goToPage: sn,
859
- setFilter: cn,
880
+ selectDiff: on,
881
+ nextDiff: () => sn(1),
882
+ previousDiff: () => sn(-1),
883
+ goToPage: cn,
884
+ setFilter: ln,
860
885
  resize: Vt,
861
- retryImages: ln
886
+ retryImages: un
862
887
  }), (t, d) => (g(), i("div", Me, [
863
888
  y(t.$slots, "toolbar", {
864
889
  activeIndex: A.value,
865
- selectDiff: an,
866
- setFilter: cn
890
+ selectDiff: on,
891
+ setFilter: ln
867
892
  }, void 0, !0),
868
893
  a("div", Ne, [a("div", Pe, [w.sourcePages.length > 0 || w.targetPages.length > 0 ? (g(), i("div", {
869
894
  key: 0,
@@ -871,21 +896,21 @@ var je = d({
871
896
  ref: se,
872
897
  class: "compare-row"
873
898
  }, [
874
- a("div", Fe, [w.sourcePages.length ? (g(), i("div", Ie, [a("div", Le, [d[18] ||= a("div", { class: "canvas-info-bar-left-tag" }, "标准文档", -1), a("div", Re, [y(t.$slots, "source-title", { filename: w.sourceFilename }, () => [s(b(w.sourceFilename || "标准文档"), 1)], !0)])]), a("div", ze, [
899
+ a("div", Fe, [w.sourcePages.length ? (g(), i("div", Ie, [a("div", Le, [d[19] ||= a("div", { class: "canvas-info-bar-left-tag" }, "标准文档", -1), a("div", Re, [y(t.$slots, "source-title", { filename: w.sourceFilename }, () => [s(b(w.sourceFilename || "标准文档"), 1)], !0)])]), a("div", ze, [
875
900
  a("button", {
876
901
  class: "page-btn",
877
902
  disabled: M.value <= 0,
878
903
  title: "第一页",
879
904
  "aria-label": "标准文档第一页",
880
905
  onClick: d[0] ||= (e) => qt(0)
881
- }, [c(x(Te), { "aria-hidden": "true" })], 8, Be),
906
+ }, [c(x(Ee), { "aria-hidden": "true" })], 8, Be),
882
907
  a("button", {
883
908
  class: "page-btn",
884
909
  disabled: M.value <= 0,
885
910
  title: "上一页",
886
911
  "aria-label": "标准文档上一页",
887
912
  onClick: d[1] ||= (e) => qt(M.value - 1)
888
- }, [c(x(Ee), { "aria-hidden": "true" })], 8, Ve),
913
+ }, [c(x(De), { "aria-hidden": "true" })], 8, Ve),
889
914
  a("span", He, b(M.value + 1) + " / " + b(w.sourcePages.length), 1),
890
915
  a("button", {
891
916
  class: "page-btn",
@@ -893,7 +918,7 @@ var je = d({
893
918
  title: "下一页",
894
919
  "aria-label": "标准文档下一页",
895
920
  onClick: d[2] ||= (e) => qt(M.value + 1)
896
- }, [c(x(ke), { "aria-hidden": "true" })], 8, Ue),
921
+ }, [c(x(Ae), { "aria-hidden": "true" })], 8, Ue),
897
922
  a("button", {
898
923
  class: "page-btn",
899
924
  disabled: M.value >= w.sourcePages.length - 1,
@@ -920,24 +945,24 @@ var je = d({
920
945
  ref_key: "srcAnnotationCanvasRef",
921
946
  ref: ue,
922
947
  class: "annotation-canvas",
923
- onClick: d[4] ||= (e) => en(e, "src"),
924
- onMousemove: d[5] ||= (e) => tn(e, "src")
948
+ onClick: d[4] ||= (e) => tn(e, "src"),
949
+ onMousemove: d[5] ||= (e) => nn(e, "src")
925
950
  }, null, 544)], 4)], 4)], 544)]),
926
- a("div", Ge, [w.targetPages.length ? (g(), i("div", Ke, [a("div", qe, [d[19] ||= a("div", { class: "canvas-info-bar-left-tag gray" }, "对比文档", -1), a("div", Je, [y(t.$slots, "target-title", { filename: w.targetFilename }, () => [s(b(w.targetFilename || "对比文档"), 1)], !0)])]), a("div", Ye, [
951
+ a("div", Ge, [w.targetPages.length ? (g(), i("div", Ke, [a("div", qe, [d[20] ||= a("div", { class: "canvas-info-bar-left-tag gray" }, "对比文档", -1), a("div", Je, [y(t.$slots, "target-title", { filename: w.targetFilename }, () => [s(b(w.targetFilename || "对比文档"), 1)], !0)])]), a("div", Ye, [
927
952
  a("button", {
928
953
  class: "page-btn",
929
954
  disabled: N.value <= 0,
930
955
  title: "第一页",
931
956
  "aria-label": "对比文档第一页",
932
957
  onClick: d[7] ||= (e) => Jt(0)
933
- }, [c(x(Te), { "aria-hidden": "true" })], 8, Xe),
958
+ }, [c(x(Ee), { "aria-hidden": "true" })], 8, Xe),
934
959
  a("button", {
935
960
  class: "page-btn",
936
961
  disabled: N.value <= 0,
937
962
  title: "上一页",
938
963
  "aria-label": "对比文档上一页",
939
964
  onClick: d[8] ||= (e) => Jt(N.value - 1)
940
- }, [c(x(Ee), { "aria-hidden": "true" })], 8, Ze),
965
+ }, [c(x(De), { "aria-hidden": "true" })], 8, Ze),
941
966
  a("span", Qe, b(N.value + 1) + " / " + b(w.targetPages.length), 1),
942
967
  a("button", {
943
968
  class: "page-btn",
@@ -945,7 +970,7 @@ var je = d({
945
970
  title: "下一页",
946
971
  "aria-label": "对比文档下一页",
947
972
  onClick: d[9] ||= (e) => Jt(N.value + 1)
948
- }, [c(x(ke), { "aria-hidden": "true" })], 8, $e),
973
+ }, [c(x(Ae), { "aria-hidden": "true" })], 8, $e),
949
974
  a("button", {
950
975
  class: "page-btn",
951
976
  disabled: N.value >= w.targetPages.length - 1,
@@ -972,16 +997,16 @@ var je = d({
972
997
  ref_key: "tgtAnnotationCanvasRef",
973
998
  ref: de,
974
999
  class: "annotation-canvas",
975
- onClick: d[11] ||= (e) => en(e, "tgt"),
976
- onMousemove: d[12] ||= (e) => tn(e, "tgt")
1000
+ onClick: d[11] ||= (e) => tn(e, "tgt"),
1001
+ onMousemove: d[12] ||= (e) => nn(e, "tgt")
977
1002
  }, null, 544)], 4)], 4)], 544)]),
978
1003
  (g(), i("svg", {
979
1004
  ref_key: "svgRef",
980
1005
  ref: fe,
981
1006
  class: "line-svg"
982
1007
  }, null, 512))
983
- ], 512)) : (g(), i("div", tt, [y(t.$slots, "empty", {}, () => [d[20] ||= s("暂无可展示的页面数据", -1)], !0)]))]), a("aside", nt, [
984
- a("header", rt, [a("div", it, [a("h2", null, [c(x(we), { "aria-hidden": "true" }), d[21] ||= s("差异审阅", -1)]), a("span", at, "共 " + b(E.value?.total_difference_count ?? w.diffDetail.length) + " 处", 1)]), a("div", ot, [(g(), i(e, null, v([
1008
+ ], 512)) : (g(), i("div", tt, [y(t.$slots, "empty", {}, () => [d[21] ||= s("暂无可展示的页面数据", -1)], !0)]))]), a("aside", nt, [
1009
+ a("header", rt, [a("div", it, [a("h2", null, [c(x(we), { "aria-hidden": "true" }), d[22] ||= s("差异审阅", -1)]), a("span", at, "共 " + b(E.value?.total_difference_count ?? w.diffDetail.length) + " 处", 1)]), a("div", ot, [(g(), i(e, null, v([
985
1010
  "pending",
986
1011
  "ignored",
987
1012
  "all"
@@ -1003,6 +1028,8 @@ var je = d({
1003
1028
  }, [s(b(e === "all" ? "所有类型" : e === "modify" ? "修改" : e === "delete" ? "删除" : "新增") + " ", 1), a("span", null, b(oe.value[e]), 1)], 8, ut)), 64))]),
1004
1029
  O.value.length ? (g(), n(be, {
1005
1030
  key: 1,
1031
+ ref_key: "diffCardsRef",
1032
+ ref: $t,
1006
1033
  "diff-detail": w.diffDetail,
1007
1034
  "active-index": A.value,
1008
1035
  "active-tab": j.value,
@@ -1010,7 +1037,7 @@ var je = d({
1010
1037
  busy: l.reviewBusy,
1011
1038
  readonly: w.readonly,
1012
1039
  onIgnore: d[15] ||= (e, t) => T("ignore", e, t),
1013
- onSelect: $
1040
+ onSelect: d[16] ||= (e) => $(e, !1)
1014
1041
  }, o({ _: 2 }, [t.$slots["diff-card"] ? {
1015
1042
  name: "default",
1016
1043
  fn: C((e) => [y(t.$slots, "diff-card", m(u(e)), void 0, !0)]),
@@ -1024,7 +1051,7 @@ var je = d({
1024
1051
  "readonly"
1025
1052
  ])) : (g(), i("div", dt, [E.value?.comparison_passed && D.value === "pending" ? (g(), i(e, { key: 0 }, [
1026
1053
  a("span", ft, [c(x(Ce), { "aria-hidden": "true" })]),
1027
- d[22] ||= a("h3", null, "比对通过", -1),
1054
+ d[23] ||= a("h3", null, "比对通过", -1),
1028
1055
  a("p", null, b(E.value.total_difference_count ? "全部差异已标记为忽略" : "两个文档未发现差异"), 1),
1029
1056
  E.value.ignored_difference_count ? (g(), i("button", {
1030
1057
  key: 0,
@@ -1032,8 +1059,8 @@ var je = d({
1032
1059
  }, " 查看已忽略的差异 ")) : r("", !0)
1033
1060
  ], 64)) : (g(), i(e, { key: 1 }, [
1034
1061
  a("span", pt, [c(x(we), { "aria-hidden": "true" })]),
1035
- d[23] ||= a("h3", null, "暂无差异", -1),
1036
- d[24] ||= a("p", null, "当前筛选下没有差异项", -1)
1062
+ d[24] ||= a("h3", null, "暂无差异", -1),
1063
+ d[25] ||= a("p", null, "当前筛选下没有差异项", -1)
1037
1064
  ], 64))])),
1038
1065
  !w.readonly && E.value ? (g(), i("footer", {
1039
1066
  key: 2,
@@ -1044,18 +1071,18 @@ var je = d({
1044
1071
  disabled: l.reviewBusy || !E.value.remaining_difference_count,
1045
1072
  title: "忽略整个任务的所有剩余差异,包含当前筛选之外的差异",
1046
1073
  "aria-label": "忽略整个任务的所有剩余差异,包含筛选外差异",
1047
- onClick: d[16] ||= (e) => T("ignore", null, !0)
1074
+ onClick: d[17] ||= (e) => T("ignore", null, !0)
1048
1075
  }, [
1049
1076
  c(x(re), { "aria-hidden": "true" }),
1050
- d[25] ||= s("忽略全部 ", -1),
1077
+ d[26] ||= s("忽略全部 ", -1),
1051
1078
  E.value.remaining_difference_count ? (g(), i("span", gt, b(E.value.remaining_difference_count), 1)) : r("", !0)
1052
1079
  ], 8, ht), a("button", {
1053
1080
  class: "batch-restore",
1054
1081
  disabled: l.reviewBusy || !E.value.ignored_difference_count,
1055
1082
  title: "撤销整个任务的所有忽略,包含当前筛选之外的差异",
1056
1083
  "aria-label": "撤销整个任务的所有差异忽略",
1057
- onClick: d[17] ||= (e) => T("ignore", null, !1)
1058
- }, [c(x(ie), { "aria-hidden": "true" }), d[26] ||= s("全部撤销 ", -1)], 8, _t)], 8, mt)) : r("", !0)
1084
+ onClick: d[18] ||= (e) => T("ignore", null, !1)
1085
+ }, [c(x(ie), { "aria-hidden": "true" }), d[27] ||= s("全部撤销 ", -1)], 8, _t)], 8, mt)) : r("", !0)
1059
1086
  ])]),
1060
1087
  y(t.$slots, "footer", {
1061
1088
  activeIndex: A.value,
@@ -1063,6 +1090,6 @@ var je = d({
1063
1090
  }, void 0, !0)
1064
1091
  ]));
1065
1092
  }
1066
- }), [["__scopeId", "data-v-c65c6ace"]]);
1093
+ }), [["__scopeId", "data-v-c1f84581"]]);
1067
1094
  //#endregion
1068
1095
  export { xt as OcrResultView };
@@ -9,6 +9,7 @@ type __VLS_Props = {
9
9
  /** 当前激活的 tab */
10
10
  activeTab?: 'all' | 'modify' | 'delete' | 'insert';
11
11
  };
12
+ declare function scrollToCard(index: number): void;
12
13
  declare var __VLS_1: {
13
14
  item: import("..").DeleteItem | import("..").InsertItem | import("..").ModifyItem;
14
15
  index: number;
@@ -19,7 +20,9 @@ declare var __VLS_1: {
19
20
  type __VLS_Slots = {} & {
20
21
  default?: (props: typeof __VLS_1) => any;
21
22
  };
22
- declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
23
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
24
+ scrollToCard: typeof scrollToCard;
25
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
23
26
  select: (index: number) => any;
24
27
  ignore: (diffId: string, ignored: boolean) => any;
25
28
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
@@ -13,13 +13,13 @@ declare var __VLS_1: {
13
13
  filename: string | undefined;
14
14
  }, __VLS_25: {
15
15
  filename: string | undefined;
16
- }, __VLS_47: {}, __VLS_74: {
16
+ }, __VLS_47: {}, __VLS_76: {
17
17
  item: import("../types").DeleteItem | import("../types").InsertItem | import("../types").ModifyItem;
18
18
  index: number;
19
19
  active: boolean;
20
20
  select: () => void;
21
21
  ignore: (ignored: boolean) => void;
22
- }, __VLS_86: {
22
+ }, __VLS_88: {
23
23
  activeIndex: number;
24
24
  review: import("../types").ComparisonReview | undefined;
25
25
  };
@@ -32,9 +32,9 @@ type __VLS_Slots = {} & {
32
32
  } & {
33
33
  empty?: (props: typeof __VLS_47) => any;
34
34
  } & {
35
- 'diff-card'?: (props: typeof __VLS_74) => any;
35
+ 'diff-card'?: (props: typeof __VLS_76) => any;
36
36
  } & {
37
- footer?: (props: typeof __VLS_86) => any;
37
+ footer?: (props: typeof __VLS_88) => any;
38
38
  };
39
39
  declare const __VLS_base: import("vue").DefineComponent<OcrResultViewProps, {
40
40
  selectDiff: typeof selectDiff;
@@ -87,6 +87,8 @@ export interface OcrResultViewProps {
87
87
  /** 默认只读;忽略操作仅发出事件,由宿主保存并回传新数据。 */
88
88
  readonly?: boolean;
89
89
  imageCrossOrigin?: 'anonymous' | 'use-credentials' | null;
90
+ /** Optional host loader for authenticated images. Return a fully decoded image. */
91
+ imageLoader?: (url: string) => Promise<HTMLImageElement>;
90
92
  }
91
93
  export interface OcrResultViewExpose {
92
94
  selectDiff: (indexOrId: number | string) => Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuwenovo/ocr-result-view",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "Vue 3 OCR document comparison result viewer with virtualized Canvas rendering",
5
5
  "repository": {
6
6
  "type": "git",