@jcyao/print-sdk 1.1.2 → 1.1.3

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/CHANGELOG.md CHANGED
@@ -11,6 +11,10 @@
11
11
  | 打印内容偏左 | `@media print` 中 `.print-page` 的 `margin` 未完全覆盖,导致 `auto` margin 在打印时产生偏移 |
12
12
  | 批量打印无边距 | `generateBatchPrintStyles` 未设置 `.print-page` 的 `padding`,导致边距功能失效 |
13
13
 
14
+ ### ✨ 新增功能
15
+
16
+ - **多模板批量打印**:新增 `printMultiTemplate` 方法,支持一次打印操作中组合多个不同模板及各自对应的数据列表(一客一模板场景)
17
+
14
18
  ### 🔧 修复详情
15
19
 
16
20
  #### 1. 打印样式 `@media print` 增强
package/README.md CHANGED
@@ -138,6 +138,50 @@ await sdk.printMultiple(myTemplate, dataList, {
138
138
  });
139
139
  ```
140
140
 
141
+ ### `sdk.printMultiTemplate(groups, options)`
142
+
143
+ 多模板批量打印(多模板 + 各自对应的数据列表)。
144
+
145
+ ```typescript
146
+ await sdk.printMultiTemplate([
147
+ { template: templateA, dataList: [dataA1, dataA2] },
148
+ { template: templateB, dataList: [dataB1] },
149
+ ], {
150
+ preview: true,
151
+ onProgress: (progress) => {
152
+ console.log(
153
+ `组: ${progress.completedGroups}/${progress.totalGroups}, 数据: ${progress.completedDataItems}/${progress.totalDataItems}`
154
+ );
155
+ }
156
+ });
157
+ ```
158
+
159
+ **参数:**
160
+
161
+ ```typescript
162
+ interface PrintTemplateGroup {
163
+ template: PrintTemplate;
164
+ dataList: any[];
165
+ }
166
+
167
+ interface MultiTemplatePrintOptions {
168
+ preview?: boolean;
169
+ onProgress?: (progress: MultiTemplatePrintProgress) => void;
170
+ }
171
+
172
+ interface MultiTemplatePrintProgress {
173
+ totalGroups: number; // 模板组总数
174
+ completedGroups: number; // 已完成组数
175
+ totalDataItems: number; // 总数据条目
176
+ completedDataItems: number; // 已完成数据条目
177
+ failed: number; // 失败条目数
178
+ currentGroupIndex: number; // 当前处理组索引
179
+ currentDataIndex: number; // 当前处理数据索引
180
+ }
181
+ ```
182
+
183
+ > ⚠️ **已知限制**:所有模板必须使用相同的纸张尺寸和边距设置。混合纸张尺寸暂不支持。
184
+
141
185
  ## 🎨 支持的组件
142
186
 
143
187
  - **文本组件** - 显示文本内容,支持标签和数据绑定
@@ -28,6 +28,32 @@ export interface BatchPrintProgress {
28
28
  failed: number;
29
29
  currentIndex: number;
30
30
  }
31
+ /**
32
+ * 模板 + 数据组
33
+ */
34
+ export interface PrintTemplateGroup {
35
+ template: PrintTemplate;
36
+ dataList: any[];
37
+ }
38
+ /**
39
+ * 多模板打印选项
40
+ */
41
+ export interface MultiTemplatePrintOptions {
42
+ preview?: boolean;
43
+ onProgress?: (progress: MultiTemplatePrintProgress) => void;
44
+ }
45
+ /**
46
+ * 多模板打印进度
47
+ */
48
+ export interface MultiTemplatePrintProgress {
49
+ totalGroups: number;
50
+ completedGroups: number;
51
+ totalDataItems: number;
52
+ completedDataItems: number;
53
+ failed: number;
54
+ currentGroupIndex: number;
55
+ currentDataIndex: number;
56
+ }
31
57
  export declare class PrintSDK {
32
58
  /**
33
59
  * 打印
@@ -64,6 +90,15 @@ export declare class PrintSDK {
64
90
  * @param options 批量打印选项
65
91
  */
66
92
  printMultiple(template: PrintTemplate, dataList: any[], options?: BatchPrintOptions): Promise<void>;
93
+ /**
94
+ * 多模板批量打印
95
+ * 支持多个模板各自绑定数据列表,一次打印确认
96
+ *
97
+ * 注意:所有模板需使用相同纸张尺寸,混合尺寸暂不支持
98
+ * @param groups 模板+数据组列表
99
+ * @param options 打印选项
100
+ */
101
+ printMultiTemplate(groups: PrintTemplateGroup[], options?: MultiTemplatePrintOptions): Promise<void>;
67
102
  }
68
103
  /**
69
104
  * 创建 SDK 实例(无需配置)
package/dist/index.esm.js CHANGED
@@ -1993,7 +1993,7 @@ class PrintSDK {
1993
1993
  * @param options 批量打印选项
1994
1994
  */
1995
1995
  async printMultiple(template, dataList, options = {}) {
1996
- var _a, _b;
1996
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1997
1997
  const { preview = false, onProgress, } = options;
1998
1998
  const { page } = template;
1999
1999
  const progress = {
@@ -2036,6 +2036,10 @@ class PrintSDK {
2036
2036
  const styles = generateBatchPrintStyles({
2037
2037
  pageWidthMm,
2038
2038
  pageHeightMm,
2039
+ marginTop: (_b = (_a = page.marginMm) === null || _a === void 0 ? void 0 : _a.top) !== null && _b !== void 0 ? _b : 0,
2040
+ marginRight: (_d = (_c = page.marginMm) === null || _c === void 0 ? void 0 : _c.right) !== null && _d !== void 0 ? _d : 0,
2041
+ marginBottom: (_f = (_e = page.marginMm) === null || _e === void 0 ? void 0 : _e.bottom) !== null && _f !== void 0 ? _f : 0,
2042
+ marginLeft: (_h = (_g = page.marginMm) === null || _g === void 0 ? void 0 : _g.left) !== null && _h !== void 0 ? _h : 0,
2039
2043
  isContinuous: page.size === 'CONTINUOUS',
2040
2044
  minHeightMm: page.minHeightMm,
2041
2045
  });
@@ -2065,7 +2069,7 @@ class PrintSDK {
2065
2069
  iframe.style.top = '-9999px';
2066
2070
  iframe.style.left = '-9999px';
2067
2071
  document.body.appendChild(iframe);
2068
- const iframeDoc = (_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.document;
2072
+ const iframeDoc = (_j = iframe.contentWindow) === null || _j === void 0 ? void 0 : _j.document;
2069
2073
  if (!iframeDoc) {
2070
2074
  throw new Error('Failed to access iframe document');
2071
2075
  }
@@ -2073,13 +2077,129 @@ class PrintSDK {
2073
2077
  iframeDoc.close();
2074
2078
  // 等待所有图片加载完成后再打印
2075
2079
  await waitForImagesLoaded(iframeDoc);
2076
- (_b = iframe.contentWindow) === null || _b === void 0 ? void 0 : _b.print();
2080
+ (_k = iframe.contentWindow) === null || _k === void 0 ? void 0 : _k.print();
2077
2081
  // 打印完成后移除 iframe
2078
2082
  setTimeout(() => {
2079
2083
  document.body.removeChild(iframe);
2080
2084
  }, 1000);
2081
2085
  }
2082
2086
  }
2087
+ /**
2088
+ * 多模板批量打印
2089
+ * 支持多个模板各自绑定数据列表,一次打印确认
2090
+ *
2091
+ * 注意:所有模板需使用相同纸张尺寸,混合尺寸暂不支持
2092
+ * @param groups 模板+数据组列表
2093
+ * @param options 打印选项
2094
+ */
2095
+ async printMultiTemplate(groups, options = {}) {
2096
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
2097
+ const { preview = false, onProgress } = options;
2098
+ if (!groups || groups.length === 0) {
2099
+ console.warn('[PrintSDK] printMultiTemplate: groups 为空,跳过打印');
2100
+ return;
2101
+ }
2102
+ const totalDataItems = groups.reduce((sum, g) => sum + g.dataList.length, 0);
2103
+ const progress = {
2104
+ totalGroups: groups.length,
2105
+ completedGroups: 0,
2106
+ totalDataItems,
2107
+ completedDataItems: 0,
2108
+ failed: 0,
2109
+ currentGroupIndex: 0,
2110
+ currentDataIndex: -1,
2111
+ };
2112
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(progress);
2113
+ const allPagesHTML = [];
2114
+ for (let groupIdx = 0; groupIdx < groups.length; groupIdx++) {
2115
+ const group = groups[groupIdx];
2116
+ progress.currentGroupIndex = groupIdx;
2117
+ progress.currentDataIndex = -1;
2118
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(progress);
2119
+ for (let dataIdx = 0; dataIdx < group.dataList.length; dataIdx++) {
2120
+ const data = group.dataList[dataIdx];
2121
+ progress.currentDataIndex = dataIdx;
2122
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(progress);
2123
+ try {
2124
+ const engine = createPrintEngine(group.template, data);
2125
+ const html = await engine.generatePrintHTML();
2126
+ const bodyContent = extractBodyContent(html);
2127
+ if (bodyContent) {
2128
+ allPagesHTML.push(bodyContent);
2129
+ }
2130
+ progress.completedDataItems++;
2131
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(progress);
2132
+ }
2133
+ catch (error) {
2134
+ progress.failed++;
2135
+ progress.completedDataItems++;
2136
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(progress);
2137
+ console.error(`[PrintSDK] 处理失败: groupIndex=${groupIdx}, dataIndex=${dataIdx}`, error);
2138
+ }
2139
+ }
2140
+ progress.completedGroups++;
2141
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(progress);
2142
+ }
2143
+ progress.currentGroupIndex = -1;
2144
+ progress.currentDataIndex = -1;
2145
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(progress);
2146
+ const { page } = groups[0].template;
2147
+ const { widthMm: pageWidthMm, heightMm: pageHeightMm } = getPageSizeFromConfig(page);
2148
+ const styles = generateBatchPrintStyles({
2149
+ pageWidthMm,
2150
+ pageHeightMm,
2151
+ marginTop: (_b = (_a = page.marginMm) === null || _a === void 0 ? void 0 : _a.top) !== null && _b !== void 0 ? _b : 0,
2152
+ marginRight: (_d = (_c = page.marginMm) === null || _c === void 0 ? void 0 : _c.right) !== null && _d !== void 0 ? _d : 0,
2153
+ marginBottom: (_f = (_e = page.marginMm) === null || _e === void 0 ? void 0 : _e.bottom) !== null && _f !== void 0 ? _f : 0,
2154
+ marginLeft: (_h = (_g = page.marginMm) === null || _g === void 0 ? void 0 : _g.left) !== null && _h !== void 0 ? _h : 0,
2155
+ isContinuous: page.size === 'CONTINUOUS',
2156
+ minHeightMm: page.minHeightMm,
2157
+ });
2158
+ const fullHTML = generatePrintHTML({
2159
+ title: '多模板批量打印',
2160
+ styles,
2161
+ bodyContent: allPagesHTML.join('\n'),
2162
+ });
2163
+ if (preview) {
2164
+ const printWindow = window.open('', '_blank');
2165
+ if (!printWindow) {
2166
+ throw new Error('Failed to open print window');
2167
+ }
2168
+ printWindow.document.write(fullHTML);
2169
+ printWindow.document.close();
2170
+ await waitForImagesLoaded(printWindow.document);
2171
+ printWindow.print();
2172
+ }
2173
+ else {
2174
+ const iframe = document.createElement('iframe');
2175
+ iframe.style.position = 'fixed';
2176
+ iframe.style.top = '-9999px';
2177
+ iframe.style.left = '-9999px';
2178
+ document.body.appendChild(iframe);
2179
+ const iframeDoc = (_j = iframe.contentWindow) === null || _j === void 0 ? void 0 : _j.document;
2180
+ if (!iframeDoc) {
2181
+ throw new Error('Failed to access iframe document');
2182
+ }
2183
+ iframeDoc.write(fullHTML);
2184
+ iframeDoc.close();
2185
+ await waitForImagesLoaded(iframeDoc);
2186
+ const cleanup = () => {
2187
+ if (iframe.parentNode) {
2188
+ document.body.removeChild(iframe);
2189
+ }
2190
+ };
2191
+ if (iframe.contentWindow) {
2192
+ iframe.contentWindow.addEventListener('afterprint', cleanup, { once: true });
2193
+ }
2194
+ (_k = iframe.contentWindow) === null || _k === void 0 ? void 0 : _k.print();
2195
+ setTimeout(() => {
2196
+ if (iframe.parentNode) {
2197
+ console.warn('[PrintSDK] afterprint 事件未触发,执行兜底清理');
2198
+ cleanup();
2199
+ }
2200
+ }, 5000);
2201
+ }
2202
+ }
2083
2203
  }
2084
2204
  /**
2085
2205
  * 创建 SDK 实例(无需配置)