@koi-br/ocr-web-sdk 1.0.17 → 1.0.19

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.
@@ -1,4 +1,4 @@
1
- import { g as getAugmentedNamespace, a as getDefaultExportFromCjs } from "./index-CTfcg7Et.mjs";
1
+ import { g as getAugmentedNamespace, a as getDefaultExportFromCjs } from "./index-DYIW_Uab.mjs";
2
2
  function _mergeNamespaces(U, W) {
3
3
  for (var Z = 0; Z < W.length; Z++) {
4
4
  const s0 = W[Z];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koi-br/ocr-web-sdk",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "一个支持多种Office文件格式预览的Vue3组件SDK,包括PDF、Word、Excel、图片、OFD、TIF等格式",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -18,7 +18,8 @@
18
18
  "private": false,
19
19
  "author": "chunyu.ma",
20
20
  "publishConfig": {
21
- "access": "public"
21
+ "access": "public",
22
+ "registry": "https://registry.npmjs.org/"
22
23
  },
23
24
  "files": [
24
25
  "dist",
@@ -59,4 +60,4 @@
59
60
  "peerDependencies": {
60
61
  "vue": "^3.0.0"
61
62
  }
62
- }
63
+ }
@@ -151,7 +151,7 @@ const props = defineProps({
151
151
  }
152
152
  });
153
153
 
154
- const emit = defineEmits(['original', 'download']);
154
+ const emit = defineEmits(['original', 'download', 'load']);
155
155
 
156
156
  const rotation = ref(0);
157
157
  const scale = ref(1);
@@ -219,6 +219,15 @@ const original = () => {
219
219
  emit('original');
220
220
  };
221
221
 
222
+ // 图片加载完成处理
223
+ const onImageLoad = (event) => {
224
+ const img = event.target;
225
+ emit('load', {
226
+ width: img.naturalWidth,
227
+ height: img.naturalHeight
228
+ });
229
+ };
230
+
222
231
  defineExpose({
223
232
  reset
224
233
  });
@@ -361,12 +361,14 @@ interface Props {
361
361
  blocksData?: BlockInfo[]; // PDF分块数据(从后端layout-parsing接口获取)
362
362
  showTocSidebar?: boolean; // 是否显示目录侧边栏(包括工具栏中的切换按钮),默认为 true
363
363
  isDownload?: boolean; // 是否显示下载按钮,默认为 false
364
+ enableMargin?: boolean; // 是否启用留白(自动缩放和适合页宽模式下),true=留白(左右各20px,共40px),false=不留白(只有左右5px padding),默认为 true
364
365
  }
365
366
 
366
367
  // 使用 withDefaults 显式设置默认值,确保未传递 prop 时使用默认值
367
368
  const props = withDefaults(defineProps<Props>(), {
368
369
  showTocSidebar: true, // 默认显示目录侧边栏
369
370
  isDownload: false, // 默认不显示下载按钮
371
+ enableMargin: true, // 默认启用留白
370
372
  });
371
373
 
372
374
  /**
@@ -1293,9 +1295,11 @@ const calculateScaleWithDimensions = (
1293
1295
  const canvasWidth = firstCanvas.width / pixelRatio;
1294
1296
  const canvasHeight = firstCanvas.height / pixelRatio;
1295
1297
 
1296
- // 预留较小的边距,让PDF占用更多宽度
1298
+ // 根据配置决定是否留白
1299
+ // enableMargin = true: 留白模式,左右总共预留 40px 边距(维持现状)
1300
+ // enableMargin = false: 不留白模式,只有左右5px padding(.pdf-viewer 的 padding)
1297
1301
  // 注意:containerWidth 已经是 .pdf-viewer 的 clientWidth(已减去 padding)
1298
- const horizontalMargin = 40; // 左右总共预留 40px 边距
1302
+ const horizontalMargin = props.enableMargin ? 40 : 10; // 留白模式:40px,不留白模式:10px
1299
1303
 
1300
1304
  // 计算可用宽度:直接使用容器宽度减去额外边距
1301
1305
  const availableWidth = containerWidth - horizontalMargin;
@@ -82,7 +82,7 @@ const props = defineProps({
82
82
  }
83
83
  });
84
84
 
85
- const emit = defineEmits(['download']);
85
+ const emit = defineEmits(['download', 'load']);
86
86
 
87
87
  const containerRef = ref(null);
88
88
  const isLoading = ref(false);
@@ -180,6 +180,8 @@ const loadDocument = async () => {
180
180
  await nextTick();
181
181
  // 渲染文档
182
182
  await renderDocument(documentData);
183
+ // 文档加载完成,触发 load 事件
184
+ emit('load');
183
185
  } catch (err) {
184
186
  console.error('文档加载失败:', err);
185
187
  error.value = `加载文档失败: ${err.message}`;
package/preview/index.vue CHANGED
@@ -30,6 +30,7 @@
30
30
  :is-download="props.isDownload"
31
31
  v-bind="props.pdfProps || {}"
32
32
  @download="handleDownload"
33
+ @pdf-loaded="handleFileLoaded"
33
34
  >
34
35
  <!-- 透传 left-top 插槽给 PdfPreview -->
35
36
  <template #left-top>
@@ -47,6 +48,7 @@
47
48
  v-bind="props.imageProps || {}"
48
49
  @original="handleOriginal"
49
50
  @download="handleDownload"
51
+ @load="handleFileLoaded"
50
52
  >
51
53
  <template #left-top>
52
54
  <slot name="left-top"></slot>
@@ -61,6 +63,7 @@
61
63
  :is-download="props.isDownload"
62
64
  v-bind="props.tifProps || {}"
63
65
  @download="handleDownload"
66
+ @load="handleFileLoaded"
64
67
  >
65
68
  <template #left-top>
66
69
  <slot name="left-top"></slot>
@@ -75,6 +78,7 @@
75
78
  :is-download="props.isDownload"
76
79
  v-bind="props.docxProps || {}"
77
80
  @download="handleDownload"
81
+ @load="handleFileLoaded"
78
82
  >
79
83
  <template #left-top>
80
84
  <slot name="left-top"></slot>
@@ -89,6 +93,7 @@
89
93
  :is-download="props.isDownload"
90
94
  v-bind="props.ofdProps || {}"
91
95
  @download="handleDownload"
96
+ @load="handleFileLoaded"
92
97
  >
93
98
  </OfdPreview>
94
99
 
@@ -100,6 +105,7 @@
100
105
  :is-download="props.isDownload"
101
106
  v-bind="props.xlsxProps || {}"
102
107
  @download="handleDownload"
108
+ @load="handleFileLoaded"
103
109
  >
104
110
  <template #left-top>
105
111
  <slot name="left-top"></slot>
@@ -130,6 +136,9 @@ import OfdPreview from './ofdPreview.vue';
130
136
  import DocxPreview from './docxPreview.vue';
131
137
  import XLSXPreview from './xlsxPreview.vue';
132
138
 
139
+ // 定义 emits
140
+ const emit = defineEmits(['load']);
141
+
133
142
  // 定义 props
134
143
  const props = defineProps({
135
144
  isDownload: {
@@ -187,11 +196,14 @@ const originalId = ref('');
187
196
  // 添加 AbortController 的引用
188
197
  const abortController = ref(null);
189
198
 
199
+ // 文件加载完成的回调函数
200
+ const onLoadCallback = ref(null);
201
+
190
202
  // 通过文件名判断类型
191
203
  const getFileType = (fileName = '') => {
192
204
  const ext = fileName.split('.').pop()?.toLowerCase();
193
205
  if (ext === 'pdf') return 'pdf';
194
- if (['tif'].includes(ext)) return 'tif';
206
+ if (['tif', 'tiff'].includes(ext)) return 'tif';
195
207
  if (['ofd'].includes(ext)) return 'ofd';
196
208
  if (['docx'].includes(ext)) return 'docx';
197
209
  if (['xlsx'].includes(ext)) return 'xlsx';
@@ -217,7 +229,8 @@ const getMimeType = (fileName = '') => {
217
229
  const ext = fileName.split('.').pop()?.toLowerCase();
218
230
  const mimeTypes = {
219
231
  pdf: 'application/pdf',
220
- tif: 'image/tif',
232
+ tif: 'image/tiff',
233
+ tiff: 'image/tiff',
221
234
  docx: 'application/docx',
222
235
  jpg: 'image/jpeg',
223
236
  jpeg: 'image/jpeg',
@@ -299,6 +312,7 @@ const handleDownload = () => {
299
312
  * @param {string} fileName - 文件名(可选,用于判断文件类型)
300
313
  * @param {object} options - 可选配置
301
314
  * @param {Function} options.onProgress - 下载进度回调函数 (progress) => void
315
+ * @param {Function} options.onLoad - 文件加载完成回调函数 (fileInfo) => void
302
316
  * @param {string} options.originalId - 原图ID(用于图片预览)
303
317
  */
304
318
  const preview = async (file, fileName, options = {}) => {
@@ -307,7 +321,10 @@ const preview = async (file, fileName, options = {}) => {
307
321
  return;
308
322
  }
309
323
 
310
- const { onProgress, originalId: originalFileId } = options;
324
+ const { onProgress, onLoad, originalId: originalFileId } = options;
325
+
326
+ // 保存加载完成回调函数
327
+ onLoadCallback.value = onLoad || null;
311
328
 
312
329
  // 清除旧的预览
313
330
  clearPreview();
@@ -359,6 +376,24 @@ const handleOriginal = () => {
359
376
  }
360
377
  };
361
378
 
379
+ // 处理文件加载完成事件
380
+ const handleFileLoaded = (data) => {
381
+ const fileInfo = {
382
+ fileType: fileType.value,
383
+ fileName: currentFileName.value,
384
+ fileUrl: fileUrl.value,
385
+ ...(data || {})
386
+ };
387
+
388
+ // 调用用户提供的加载完成回调函数(通过 options.onLoad)
389
+ if (onLoadCallback.value && typeof onLoadCallback.value === 'function') {
390
+ onLoadCallback.value(fileInfo);
391
+ }
392
+
393
+ // 向外 emit load 事件(供父组件通过 @load 监听)
394
+ emit('load', fileInfo);
395
+ };
396
+
362
397
  // 获取当前活动的预览组件引用
363
398
  const getCurrentPreviewRef = () => {
364
399
  switch (fileType.value) {
@@ -327,6 +327,40 @@ const loadTiff = async () => {
327
327
  throw new Error(`HTTP error! status: ${response.status}`);
328
328
  }
329
329
  const arrayBuffer = await response.arrayBuffer();
330
+ // 验证文件大小
331
+ if (arrayBuffer.byteLength === 0) {
332
+ throw new Error('文件为空或无法读取');
333
+ }
334
+
335
+ // 验证文件实际格式
336
+ const uint8Array = new Uint8Array(arrayBuffer);
337
+ const isValidTiff =
338
+ (uint8Array[0] === 0x49 && uint8Array[1] === 0x49) || // Little-endian TIFF
339
+ (uint8Array[0] === 0x4d && uint8Array[1] === 0x4d); // Big-endian TIFF
340
+
341
+ // 检测是否为 JPEG 格式 (0xFF 0xD8)
342
+ const isJpeg = uint8Array[0] === 0xff && uint8Array[1] === 0xd8;
343
+ // 检测是否为 PNG 格式 (0x89 0x50 0x4E 0x47)
344
+ const isPng =
345
+ uint8Array[0] === 0x89 &&
346
+ uint8Array[1] === 0x50 &&
347
+ uint8Array[2] === 0x4e &&
348
+ uint8Array[3] === 0x47;
349
+
350
+ // 如果不是 TIFF 格式,但是常见的图片格式,直接使用图片预览
351
+ if (!isValidTiff && (isJpeg || isPng)) {
352
+ const blob = new Blob([arrayBuffer], {
353
+ type: isJpeg ? 'image/jpeg' : 'image/png'
354
+ });
355
+ imgDataUrl.value = URL.createObjectURL(blob);
356
+ error.value = '';
357
+ emit('load', {
358
+ width: 0,
359
+ height: 0
360
+ });
361
+ isLoading.value = false;
362
+ return;
363
+ }
330
364
 
331
365
  // 创建TIFF实例
332
366
  // tiff.js 的 Tiff 是一个构造函数,需要使用 new 关键字
@@ -382,7 +416,7 @@ const loadTiff = async () => {
382
416
 
383
417
  // 图片加载成功回调
384
418
  const onImageLoad = () => {
385
- console.log('TIFF图片渲染成功');
419
+ // 图片加载成功
386
420
  };
387
421
 
388
422
  // 图片加载失败回调
@@ -88,7 +88,7 @@ const props = defineProps({
88
88
  }
89
89
  });
90
90
 
91
- const emit = defineEmits(['download']);
91
+ const emit = defineEmits(['download', 'load']);
92
92
 
93
93
  const excel = ref('');
94
94
  const loading = ref(false);
@@ -125,6 +125,7 @@ const resetZoom = () => {
125
125
  // 文件加载成功
126
126
  const onRendered = () => {
127
127
  loading.value = false;
128
+ emit('load');
128
129
  };
129
130
 
130
131
  // 文件加载失败