x-print-designer 0.0.6 → 0.0.8
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 +273 -43
- package/dist/{JsBarcode-CUiJ4kMt.js → JsBarcode-Dgi3IOT3.js} +1 -1
- package/dist/{browser-DIU9kPWX.js → browser-DlaXrxTz.js} +1 -1
- package/dist/{dom-to-image-more.min-vPlSBgID.js → dom-to-image-more.min-c7u3eC0x.js} +1 -1
- package/dist/{index-DdtP0Fsw.js → index-BruhTdzE.js} +1 -1
- package/dist/{index.es-CJ4AuCoP.js → index.es-CT9Fe2Z9.js} +1 -1
- package/dist/{jspdf.es.min-Dv-nNebO.js → jspdf.es.min-DrqPbpn5.js} +1 -1
- package/dist/{jszip.min-BYYbhBEw.js → jszip.min-qOn_nG5R.js} +1 -1
- package/dist/print-designer.css +1 -1
- package/dist/print-designer.es.js +1 -1
- package/dist/print-designer.umd.js +37 -37
- package/dist/{web-component-Bgs-OHJ9.js → web-component-DcKncTzs.js} +253 -200
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,35 +25,112 @@
|
|
|
25
25
|
|
|
26
26
|
设计器支持两种工作模式,通过 `mode` 属性/方法进行切换。
|
|
27
27
|
|
|
28
|
+
### 概念说明
|
|
29
|
+
|
|
30
|
+
| 概念 | 说明 |
|
|
31
|
+
|------|------|
|
|
32
|
+
| **模板 (Template)** | 页面布局设计,包含元素位置、样式、画布大小等,不包含具体数据 |
|
|
33
|
+
| **数据 (Data)** | 业务数据,如订单信息、报告内容、用户信息等 |
|
|
34
|
+
| **模板 ID** | 模板的唯一标识,用于关联和加载模板 |
|
|
35
|
+
| **数据 ID** | 业务数据的唯一标识,如订单 ID、报告 ID |
|
|
36
|
+
|
|
28
37
|
### 模板模式(`template`)— 默认模式
|
|
29
38
|
|
|
30
|
-
|
|
39
|
+
**设计理念:** 模板与数据分离,一个模板可绑定多个不同的数据。
|
|
31
40
|
|
|
41
|
+
**适用场景:**
|
|
42
|
+
- 订单打印(同一订单模板,打印不同订单)
|
|
43
|
+
- 标签打印(同一标签模板,打印不同商品)
|
|
44
|
+
- 快递单据(同一单据模板,打印不同收件人)
|
|
45
|
+
|
|
46
|
+
**数据流向:**
|
|
47
|
+
```
|
|
48
|
+
模板(保存布局) + 数据(打印时注入) = 最终打印结果
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**保存行为:**
|
|
32
52
|
- 保存时**只保存页面布局**(元素位置、样式、画布大小等)
|
|
33
|
-
- **不保存** `testData
|
|
53
|
+
- **不保存** `testData`
|
|
34
54
|
|
|
35
55
|
### 报告模式(`report`)
|
|
36
56
|
|
|
37
|
-
|
|
57
|
+
**设计理念:** 数据与布局绑定,保存的是完整的报告快照。
|
|
58
|
+
|
|
59
|
+
**适用场景:**
|
|
60
|
+
- 检测报告(每次检测结果 + 固定格式的报告模板)
|
|
61
|
+
- 数据报表(当前统计数据的可视化呈现)
|
|
62
|
+
- 档案文件(包含具体数据的完整文档)
|
|
63
|
+
|
|
64
|
+
**数据流向:**
|
|
65
|
+
```
|
|
66
|
+
报告(模板 + 数据 一起保存) = 完整的报告文件
|
|
67
|
+
```
|
|
38
68
|
|
|
39
|
-
|
|
69
|
+
**保存行为:**
|
|
70
|
+
- 保存时**同时保存页面布局 + 测试数据**
|
|
71
|
+
- `testData` 会被完整保存到模板数据中
|
|
40
72
|
|
|
41
|
-
###
|
|
73
|
+
### 两种模式对比
|
|
42
74
|
|
|
43
|
-
| 特性 | `template` | `report` |
|
|
44
|
-
|
|
75
|
+
| 特性 | `template` 模板模式 | `report` 报告模式 |
|
|
76
|
+
|------|-------------------|------------------|
|
|
45
77
|
| 保存布局 | ✅ | ✅ |
|
|
46
78
|
| 保存 testData | ❌ | ✅ |
|
|
47
|
-
|
|
|
79
|
+
| 数据与模板关系 | 分离,运行时注入 | 绑定,一起保存 |
|
|
80
|
+
| 模板复用性 | 高,可用于多个数据 | 低,针对当前数据 |
|
|
81
|
+
| 典型用途 | 订单打印、标签 | 检测报告、数据报表 |
|
|
82
|
+
| 数据持久化 | 数据需单独存储 | 数据与模板一起存储 |
|
|
83
|
+
|
|
84
|
+
### 使用示例
|
|
85
|
+
|
|
86
|
+
**模板模式(推荐用于可复用模板):**
|
|
87
|
+
```javascript
|
|
88
|
+
// 1. 创建/编辑模板
|
|
89
|
+
const sampleData = {
|
|
90
|
+
id: null, // 无需数据 ID,只是用于预览
|
|
91
|
+
title: "@orderNo", // 绑定变量
|
|
92
|
+
customerName: "@customerName"
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// 2. 保存模板(只保存布局)
|
|
96
|
+
// payload.data 不包含 testData
|
|
97
|
+
|
|
98
|
+
// 3. 打印时动态注入数据
|
|
99
|
+
designer.setVariables({
|
|
100
|
+
orderNo: "ORD-2024-001",
|
|
101
|
+
customerName: "张三"
|
|
102
|
+
});
|
|
103
|
+
designer.print();
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**报告模式(推荐用于完整报告):**
|
|
107
|
+
```javascript
|
|
108
|
+
// 1. 创建/编辑报告
|
|
109
|
+
const sampleData = {
|
|
110
|
+
id: 8, // 报告 ID
|
|
111
|
+
title: "2024年第一季度销售报告",
|
|
112
|
+
totalAmount: 50000,
|
|
113
|
+
items: [...] // 报告数据
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// 2. 保存报告(布局 + 数据一起保存)
|
|
117
|
+
// payload.data 包含完整的 testData
|
|
118
|
+
|
|
119
|
+
// 3. 加载后直接打印,无需再次注入数据
|
|
120
|
+
designer.loadTemplate(8);
|
|
121
|
+
designer.print();
|
|
122
|
+
```
|
|
48
123
|
|
|
49
124
|
### 切换模式
|
|
50
125
|
|
|
51
126
|
```vue
|
|
52
|
-
|
|
53
|
-
<PrintDesigner mode="
|
|
127
|
+
<!-- Vue 组件 -->
|
|
128
|
+
<PrintDesigner mode="template" /> <!-- 模板模式(默认) -->
|
|
129
|
+
<PrintDesigner mode="report" /> <!-- 报告模式 -->
|
|
54
130
|
```
|
|
55
131
|
|
|
56
|
-
```
|
|
132
|
+
```javascript
|
|
133
|
+
// Web Component
|
|
57
134
|
designer.setMode('template');
|
|
58
135
|
designer.setMode('report');
|
|
59
136
|
```
|
|
@@ -206,32 +283,84 @@ await designer.print({ mode: 'browser', options: { silent: true } });
|
|
|
206
283
|
|
|
207
284
|
## 传入数据格式
|
|
208
285
|
|
|
209
|
-
|
|
286
|
+
### 基本要求
|
|
210
287
|
|
|
211
|
-
|
|
288
|
+
`sample-data` 接收一个普通的 JSON 对象,**唯一必填字段是 `id`**,用于标识业务数据的唯一性。其他字段完全自由,可以根据业务需求灵活组织数据结构。
|
|
212
289
|
|
|
213
290
|
| 字段 | 类型 | 必填 | 说明 |
|
|
214
291
|
|------|------|------|------|
|
|
215
|
-
| `id` | `number` / `string` | 是 |
|
|
292
|
+
| `id` | `number` / `string` | ✅ 是 | **业务数据的唯一标识**,如报告 ID、订单 ID |
|
|
216
293
|
| `templateId` | `string` | 否 | 加载的打印模板 ID,不传则用当前已选模板 |
|
|
217
294
|
| `name` | `string` | 否 | 数据名称,如报告标题、订单名称 |
|
|
218
|
-
| `variables` | `object` | 否 |
|
|
219
|
-
| 任意自定义字段 | `any` | 否 | 如 `createTime`、`
|
|
295
|
+
| `variables` | `object` | 否 | 业务变量对象(可选,用作组织数据的约定) |
|
|
296
|
+
| 任意自定义字段 | `any` | 否 | 如 `createTime`、`customerName`,也可在模板中直接引用 |
|
|
297
|
+
|
|
298
|
+
### 两种数据传入方式
|
|
299
|
+
|
|
300
|
+
组件支持两种数据组织方式,**可以任选其一**,组件会自动兼容处理:
|
|
301
|
+
|
|
302
|
+
#### 方式一:带 `variables` 包装(推荐)
|
|
303
|
+
|
|
304
|
+
将所有业务变量放在 `variables` 对象中,结构清晰,适合复杂业务场景:
|
|
305
|
+
|
|
306
|
+
```json
|
|
307
|
+
{
|
|
308
|
+
"id": 8,
|
|
309
|
+
"name": "测试报告",
|
|
310
|
+
"templateId": "tpl_report",
|
|
311
|
+
"variables": {
|
|
312
|
+
"title": "报告标题",
|
|
313
|
+
"customerName": "张三",
|
|
314
|
+
"items": [
|
|
315
|
+
{ "name": "产品A", "price": 100, "quantity": 2 }
|
|
316
|
+
],
|
|
317
|
+
"chartData": [
|
|
318
|
+
{ "category": "一月", "value": 1200 },
|
|
319
|
+
{ "category": "二月", "value": 1500 }
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
模板绑定写法:`@title`、`@customerName`、`@items`、`@chartData`
|
|
220
326
|
|
|
221
|
-
|
|
327
|
+
#### 方式二:直接扁平数据(简洁)
|
|
222
328
|
|
|
223
|
-
|
|
329
|
+
将所有字段直接放在根级别,无需 `variables` 包装,适合简单场景:
|
|
224
330
|
|
|
225
|
-
|
|
331
|
+
```json
|
|
332
|
+
{
|
|
333
|
+
"id": 8,
|
|
334
|
+
"name": "测试报告",
|
|
335
|
+
"title": "报告标题",
|
|
336
|
+
"customerName": "张三",
|
|
337
|
+
"items": [
|
|
338
|
+
{ "name": "产品A", "price": 100, "quantity": 2 }
|
|
339
|
+
],
|
|
340
|
+
"chartData": [
|
|
341
|
+
{ "category": "一月", "value": 1200 },
|
|
342
|
+
{ "category": "二月", "value": 1500 }
|
|
343
|
+
]
|
|
344
|
+
}
|
|
345
|
+
```
|
|
226
346
|
|
|
227
|
-
|
|
228
|
-
- **字符串** `string` — 文本元素绑定
|
|
229
|
-
- **数字** `number` — 文本、图表数据
|
|
230
|
-
- **布尔值** `boolean`
|
|
231
|
-
- **数组** `array` — 表格数据源、图表数据源
|
|
232
|
-
- **嵌套对象** `object` — 多级路径访问
|
|
347
|
+
模板绑定写法:`@title`、`@customerName`、`@items`、`@chartData`
|
|
233
348
|
|
|
234
|
-
|
|
349
|
+
> 两种方式完全等效,组件内部会自动解析变量路径,无需担心格式不匹配。
|
|
350
|
+
|
|
351
|
+
### 支持的数据类型
|
|
352
|
+
|
|
353
|
+
所有字段都可在模板元素中通过变量语法绑定,支持:
|
|
354
|
+
|
|
355
|
+
| 类型 | 示例 | 在模板中绑定 |
|
|
356
|
+
|------|------|-------------|
|
|
357
|
+
| 字符串 | `"张三"` | `@customerName` |
|
|
358
|
+
| 数字 | `100` | `@totalAmount` |
|
|
359
|
+
| 布尔值 | `true` | `@isPaid` |
|
|
360
|
+
| 数组 | `[{...}, {...}]` | `@items` |
|
|
361
|
+
| 嵌套对象 | `{user: {name: "李四"}}` | `@user.name` |
|
|
362
|
+
|
|
363
|
+
### 完整示例数据格式
|
|
235
364
|
|
|
236
365
|
```json
|
|
237
366
|
{
|
|
@@ -289,15 +418,16 @@ await designer.print({ mode: 'browser', options: { silent: true } });
|
|
|
289
418
|
|
|
290
419
|
### 在模板中绑定变量
|
|
291
420
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
|
295
|
-
|
|
296
|
-
| `variables.
|
|
297
|
-
| `variables.
|
|
298
|
-
| `variables.flightRecords` | `@flightRecords` | 表格、自定义表格 |
|
|
299
|
-
| `variables.
|
|
300
|
-
|
|
421
|
+
变量绑定使用 `@变量名` 或 `{#变量名}` 语法。绑定时只需使用变量名,无需关心数据是否在 `variables` 包装下:
|
|
422
|
+
|
|
423
|
+
| 变量路径 | 绑定写法 | 应用元素 |
|
|
424
|
+
|---------|---------|---------|
|
|
425
|
+
| `variables.dockname` / `dockname` | `@dockname` | 文本 |
|
|
426
|
+
| `variables.reportname` / `reportname` | `@reportname` | 文本 |
|
|
427
|
+
| `variables.flightRecords` / `flightRecords` | `@flightRecords` | 表格、自定义表格 |
|
|
428
|
+
| `variables.chartData` / `chartData` | `@chartData` | 图表 |
|
|
429
|
+
|
|
430
|
+
> 组件会自动解析变量路径,无论数据在 `variables.xxx` 还是直接在根级别,都能正确绑定。
|
|
301
431
|
|
|
302
432
|
### 表格数据
|
|
303
433
|
|
|
@@ -343,6 +473,34 @@ await designer.print({ mode: 'browser', options: { silent: true } });
|
|
|
343
473
|
- **chartYField:** `value`(Y 轴字段名)
|
|
344
474
|
- **chartNameField:** `category`(饼图名称字段)
|
|
345
475
|
|
|
476
|
+
### 使用注意事项
|
|
477
|
+
|
|
478
|
+
1. **`id` 字段的重要性**
|
|
479
|
+
- `id` 是业务数据的唯一标识,用于在保存回调中识别当前编辑的数据
|
|
480
|
+
- 如果不传 `id`,保存时 `payload.id` 将为 `null`,表示新建数据
|
|
481
|
+
|
|
482
|
+
2. **`id` 与 `templateId` 的区别**
|
|
483
|
+
- `id`:业务数据(如订单、报告)的标识
|
|
484
|
+
- `templateId`:打印模板的标识,两者是完全不同的概念
|
|
485
|
+
|
|
486
|
+
3. **变量命名建议**
|
|
487
|
+
- 使用有意义的变量名,如 `customerName` 而非 `c`
|
|
488
|
+
- 避免使用特殊字符和空格
|
|
489
|
+
- 嵌套路径使用点号分隔,如 `@user.profile.name`
|
|
490
|
+
|
|
491
|
+
4. **数组数据的注意事项**
|
|
492
|
+
- 表格和图表需要数组类型的数据
|
|
493
|
+
- 数组元素应包含一致的字段结构
|
|
494
|
+
- 示例:`items: [{name: "A", price: 100}, {name: "B", price: 200}]`
|
|
495
|
+
|
|
496
|
+
5. **动态更新数据**
|
|
497
|
+
- 可以通过 Web Component 的 `setSampleData()` 方法动态更新数据
|
|
498
|
+
- 数据更新后,模板中的变量绑定会自动重新解析
|
|
499
|
+
|
|
500
|
+
6. **数据验证建议**
|
|
501
|
+
- 确保传入的数据字段与模板中绑定的变量名一致
|
|
502
|
+
- 如果变量找不到对应的数据,模板中会显示为空
|
|
503
|
+
|
|
346
504
|
---
|
|
347
505
|
|
|
348
506
|
## 保存回调 `onSave`
|
|
@@ -355,27 +513,99 @@ await designer.print({ mode: 'browser', options: { silent: true } });
|
|
|
355
513
|
interface SavePayload {
|
|
356
514
|
id: string | null; // 模板 ID,null 表示新建
|
|
357
515
|
name: string; // 模板名称
|
|
358
|
-
data: Record<string, any>; //
|
|
516
|
+
data: Record<string, any>; // 模板数据(见下方详细说明)
|
|
359
517
|
isNew: boolean; // 是否新建模板
|
|
360
518
|
}
|
|
361
519
|
```
|
|
362
520
|
|
|
521
|
+
### 不同模式下的保存数据差异
|
|
522
|
+
|
|
523
|
+
| 数据字段 | 模板模式 | 报告模式 | 说明 |
|
|
524
|
+
|---------|---------|---------|------|
|
|
525
|
+
| `pages` | ✅ | ✅ | 页面元素布局 |
|
|
526
|
+
| `canvasSize` | ✅ | ✅ | 画布尺寸 |
|
|
527
|
+
| `watermark` | ✅ | ✅ | 水印设置 |
|
|
528
|
+
| `guides` | ✅ | ✅ | 辅助线 |
|
|
529
|
+
| `testData` | ❌ | ✅ | 传入的示例数据 |
|
|
530
|
+
| `unit` | ✅ | ✅ | 单位设置 |
|
|
531
|
+
| `showGrid` | ✅ | ✅ | 网格显示 |
|
|
532
|
+
| ... | ... | ... | 其他配置 |
|
|
533
|
+
|
|
534
|
+
### 保存数据示例
|
|
535
|
+
|
|
536
|
+
**模板模式保存的数据:**
|
|
537
|
+
```javascript
|
|
538
|
+
{
|
|
539
|
+
id: "tpl_001", // 模板 ID
|
|
540
|
+
name: "订单打印模板",
|
|
541
|
+
data: {
|
|
542
|
+
pages: [...], // 页面布局
|
|
543
|
+
canvasSize: {...}, // 画布尺寸
|
|
544
|
+
watermark: {...}, // 水印设置
|
|
545
|
+
unit: "mm",
|
|
546
|
+
showGrid: true,
|
|
547
|
+
// ❌ 没有 testData 字段
|
|
548
|
+
},
|
|
549
|
+
isNew: false
|
|
550
|
+
}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
**报告模式保存的数据:**
|
|
554
|
+
```javascript
|
|
555
|
+
{
|
|
556
|
+
id: "rpt_001", // 报告 ID
|
|
557
|
+
name: "第一季度销售报告",
|
|
558
|
+
data: {
|
|
559
|
+
pages: [...], // 页面布局
|
|
560
|
+
canvasSize: {...}, // 画布尺寸
|
|
561
|
+
watermark: {...}, // 水印设置
|
|
562
|
+
unit: "mm",
|
|
563
|
+
showGrid: true,
|
|
564
|
+
// ✅ 包含完整的 testData
|
|
565
|
+
testData: {
|
|
566
|
+
id: 8,
|
|
567
|
+
name: "第一季度销售报告",
|
|
568
|
+
totalAmount: 50000,
|
|
569
|
+
items: [
|
|
570
|
+
{ name: "产品A", price: 100, quantity: 200 },
|
|
571
|
+
{ name: "产品B", price: 200, quantity: 150 }
|
|
572
|
+
],
|
|
573
|
+
chartData: [
|
|
574
|
+
{ category: "一月", value: 1200 },
|
|
575
|
+
{ category: "二月", value: 1500 },
|
|
576
|
+
{ category: "三月", value: 1800 }
|
|
577
|
+
]
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
isNew: false
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
363
584
|
### 使用示例
|
|
364
585
|
|
|
365
586
|
```vue
|
|
366
587
|
<PrintDesigner
|
|
588
|
+
:mode="mode"
|
|
367
589
|
:on-save="handleSave"
|
|
368
590
|
/>
|
|
369
591
|
|
|
370
592
|
<script setup>
|
|
593
|
+
import { ref } from 'vue';
|
|
594
|
+
|
|
595
|
+
const mode = ref('template'); // 或 'report'
|
|
596
|
+
|
|
371
597
|
const handleSave = async (payload) => {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
598
|
+
console.log('保存模式:', mode.value);
|
|
599
|
+
console.log('保存的数据:', payload);
|
|
600
|
+
|
|
601
|
+
// 根据模式决定如何处理
|
|
602
|
+
if (mode.value === 'template') {
|
|
603
|
+
// 模板模式:保存布局,数据单独处理
|
|
604
|
+
await saveTemplate(payload.id, payload.name, payload.data);
|
|
605
|
+
} else {
|
|
606
|
+
// 报告模式:布局和数据一起保存
|
|
607
|
+
await saveReport(payload.id, payload.name, payload.data);
|
|
608
|
+
}
|
|
379
609
|
};
|
|
380
610
|
</script>
|
|
381
611
|
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent, h, computed, onUnmounted, watch, shallowRef, loader, onMounted, nextTick, ref } from "./web-component-
|
|
1
|
+
import { defineComponent, h, computed, onUnmounted, watch, shallowRef, loader, onMounted, nextTick, ref } from "./web-component-DcKncTzs.js";
|
|
2
2
|
var __defProp$2 = Object.defineProperty;
|
|
3
3
|
var __defProps = Object.defineProperties;
|
|
4
4
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { commonjsGlobal, getDefaultExportFromCjs } from "./web-component-
|
|
1
|
+
import { commonjsGlobal, getDefaultExportFromCjs } from "./web-component-DcKncTzs.js";
|
|
2
2
|
import { _typeof as _typeof$1 } from "./typeof-DxTVrAEz.js";
|
|
3
3
|
var es_promise = {};
|
|
4
4
|
var es_promise_constructor = {};
|
|
@@ -10832,7 +10832,7 @@ function le() {
|
|
|
10832
10832
|
var h2 = l2.getContext("2d");
|
|
10833
10833
|
h2.fillStyle = "#fff", h2.fillRect(0, 0, l2.width, l2.height);
|
|
10834
10834
|
var f2 = { ignoreMouse: true, ignoreAnimation: true, ignoreDimensions: true }, d2 = this;
|
|
10835
|
-
return (i.canvg ? Promise.resolve(i.canvg) : import("./index.es-
|
|
10835
|
+
return (i.canvg ? Promise.resolve(i.canvg) : import("./index.es-CT9Fe2Z9.js")).catch(function(t3) {
|
|
10836
10836
|
return Promise.reject(new Error("Could not load canvg: " + t3));
|
|
10837
10837
|
}).then(function(t3) {
|
|
10838
10838
|
return t3.default ? t3.default : t3;
|
package/dist/print-designer.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.custom-scrollbar[data-v-
|
|
1
|
+
.custom-scrollbar[data-v-74e0e91a]::-webkit-scrollbar{width:4px}.custom-scrollbar[data-v-74e0e91a]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-74e0e91a]::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:2px}.custom-scrollbar[data-v-74e0e91a]::-webkit-scrollbar-thumb:hover{background-color:#d1d5db}.dark .custom-scrollbar[data-v-74e0e91a]::-webkit-scrollbar-thumb{background-color:#374151}.dark .custom-scrollbar[data-v-74e0e91a]::-webkit-scrollbar-thumb:hover{background-color:#4b5563}.print-renderer[data-v-d181d33d]{padding:0}.animate-fade-in[data-v-4c59b77a]{animation:fadeIn-4c59b77a .2s ease-out}@keyframes fadeIn-4c59b77a{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}[data-v-3e59cbc1] .print-page{margin-bottom:20px;background:#fff;box-shadow:none!important;position:relative!important;left:auto!important;top:auto!important}[data-v-3e59cbc1] .print-page:last-child{margin-bottom:0}.preview-content[data-v-3e59cbc1] *{cursor:default!important}.resize-y[data-v-e19d1803]{resize:vertical}.custom-scrollbar[data-v-1e890fd6]::-webkit-scrollbar{width:4px}.custom-scrollbar[data-v-1e890fd6]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-1e890fd6]::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:2px}.custom-scrollbar[data-v-1e890fd6]::-webkit-scrollbar-thumb:hover{background-color:#d1d5db}.dark .custom-scrollbar[data-v-1e890fd6]::-webkit-scrollbar-thumb{background-color:#374151}.dark .custom-scrollbar[data-v-1e890fd6]::-webkit-scrollbar-thumb:hover{background-color:#4b5563}.custom-scrollbar[data-v-2ce9799f]::-webkit-scrollbar{width:4px}.custom-scrollbar[data-v-2ce9799f]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-2ce9799f]::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:2px}.custom-scrollbar[data-v-2ce9799f]::-webkit-scrollbar-thumb:hover{background-color:#d1d5db}.dark .custom-scrollbar[data-v-2ce9799f]::-webkit-scrollbar-thumb{background-color:#374151}.dark .custom-scrollbar[data-v-2ce9799f]::-webkit-scrollbar-thumb:hover{background-color:#4b5563}.custom-scrollbar[data-v-9d2cf375]::-webkit-scrollbar{width:4px}.custom-scrollbar[data-v-9d2cf375]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-9d2cf375]::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:2px}.custom-scrollbar[data-v-9d2cf375]::-webkit-scrollbar-thumb:hover{background-color:#d1d5db}.dark .custom-scrollbar[data-v-9d2cf375]::-webkit-scrollbar-thumb{background-color:#374151}.dark .custom-scrollbar[data-v-9d2cf375]::-webkit-scrollbar-thumb:hover{background-color:#4b5563}.custom-scrollbar[data-v-89c1feca]::-webkit-scrollbar{width:4px}.custom-scrollbar[data-v-89c1feca]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-89c1feca]::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:2px}.custom-scrollbar[data-v-89c1feca]::-webkit-scrollbar-thumb:hover{background-color:#d1d5db}.dark .custom-scrollbar[data-v-89c1feca]::-webkit-scrollbar-thumb{background-color:#374151}.dark .custom-scrollbar[data-v-89c1feca]::-webkit-scrollbar-thumb:hover{background-color:#4b5563}.custom-scrollbar[data-v-611b266a]::-webkit-scrollbar{width:6px}.custom-scrollbar[data-v-611b266a]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-611b266a]::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:3px}.custom-scrollbar[data-v-611b266a]::-webkit-scrollbar-thumb:hover{background-color:#d1d5db}.no-scrollbar[data-v-9e6ec8c1]{-ms-overflow-style:none;scrollbar-width:none}.no-scrollbar[data-v-9e6ec8c1]::-webkit-scrollbar{display:none}.custom-scrollbar[data-v-f18f44fe]::-webkit-scrollbar{width:6px}.custom-scrollbar[data-v-f18f44fe]::-webkit-scrollbar-track{background:transparent}.custom-scrollbar[data-v-f18f44fe]::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:3px}.custom-scrollbar[data-v-f18f44fe]::-webkit-scrollbar-thumb:hover{background-color:#d1d5db}.dark .custom-scrollbar[data-v-f18f44fe]::-webkit-scrollbar-thumb{background-color:#374151}.dark .custom-scrollbar[data-v-f18f44fe]::-webkit-scrollbar-thumb:hover{background-color:#4b5563}
|