x-print-designer 0.0.2 → 0.0.4
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 +533 -103
- package/dist/{JsBarcode-CaEyZMPG.js → JsBarcode-BCOR_2Tk.js} +1 -1
- package/dist/{browser-Bl9hyQY4.js → browser-54jWk43N.js} +1 -1
- package/dist/{dom-to-image-more.min-CwgZFoL1.js → dom-to-image-more.min-DaRf6ofp.js} +1 -1
- package/dist/{index-C8ZY6iyn.js → index-Cg6-YG7b.js} +1 -1
- package/dist/{index.es-Bd9RXDZp.js → index.es-Dky7JXCp.js} +1 -1
- package/dist/{jspdf.es.min-CXfI1dny.js → jspdf.es.min-CzIpPYrU.js} +1 -1
- package/dist/{jszip.min-DoQFFAlg.js → jszip.min-nApOj_gF.js} +1 -1
- package/dist/print-designer.css +1 -1
- package/dist/print-designer.es.js +1 -1
- package/dist/print-designer.umd.js +38 -38
- package/dist/{web-component-6n-bG7Fh.js → web-component-Bgmv52X1.js} +2814 -1907
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,103 +1,533 @@
|
|
|
1
|
-
# X-Print-Designer
|
|
2
|
-
|
|
3
|
-
基于Vue
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
1
|
+
# X-Print-Designer
|
|
2
|
+
|
|
3
|
+
基于 Vue 3 + TypeScript 开发的打印设计器,支持可视化拖拽设计打印模板,集成 ECharts 图表组件,提供模板模式与报告模式两种工作方式。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 目录
|
|
8
|
+
|
|
9
|
+
- [核心概念:模板模式 vs 报告模式](#核心概念模板模式-vs-报告模式)
|
|
10
|
+
- [快速开始](#快速开始)
|
|
11
|
+
- [传入数据格式](#传入数据格式)
|
|
12
|
+
- [支持的元素类型](#支持的元素类型)
|
|
13
|
+
- [数据绑定方式](#数据绑定方式)
|
|
14
|
+
- [测试数据](#测试数据)
|
|
15
|
+
- [变量语法参考](#变量语法参考)
|
|
16
|
+
- [技术栈](#技术栈)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 核心概念:模板模式 vs 报告模式
|
|
21
|
+
|
|
22
|
+
设计器支持两种工作模式,通过 `mode` 属性/方法进行切换。
|
|
23
|
+
|
|
24
|
+
### 模板模式(template)— 默认模式
|
|
25
|
+
|
|
26
|
+
**适用场景:** 创建可复用的打印模板,模板与数据分离。先在设计器中画好布局,打印时再填入真实数据。
|
|
27
|
+
|
|
28
|
+
**保存行为:**
|
|
29
|
+
- 保存时**只保存页面布局信息**(元素位置、样式、画布大小、参考线等)
|
|
30
|
+
- **不保存**测试数据(`testData`)
|
|
31
|
+
|
|
32
|
+
**典型工作流:**
|
|
33
|
+
1. 在设计器中拖拽元素,设计打印模板的布局
|
|
34
|
+
2. 使用变量语法(如 `{#orderNo}`)标记数据占位符
|
|
35
|
+
3. 保存模板,模板只包含布局结构
|
|
36
|
+
4. 业务系统调用打印/导出时,传入真实数据替换变量
|
|
37
|
+
|
|
38
|
+
**保存的数据结构:**
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"pages": [ /* 页面和元素列表 */ ],
|
|
43
|
+
"canvasSize": { "width": 794, "height": 1123 },
|
|
44
|
+
"guides": [],
|
|
45
|
+
"zoom": 1,
|
|
46
|
+
"showGrid": true,
|
|
47
|
+
"headerHeight": 0,
|
|
48
|
+
"footerHeight": 0,
|
|
49
|
+
"watermark": { "enabled": false, "text": "", "angle": -30, "color": "#000000", "opacity": 0.1, "size": 24, "density": 160 },
|
|
50
|
+
"unit": "mm",
|
|
51
|
+
"pageSpacingX": 0,
|
|
52
|
+
"pageSpacingY": 0,
|
|
53
|
+
"canvasBackground": "#ffffff"
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 报告模式(report)
|
|
58
|
+
|
|
59
|
+
**适用场景:** 创建包含数据的完整报告,布局和数据一起保存。适用于需要将模板和示例数据打包存储的场景。
|
|
60
|
+
|
|
61
|
+
**保存行为:**
|
|
62
|
+
- 保存时**同时保存页面布局信息和测试数据**(`testData`)
|
|
63
|
+
- `testData` 中包含当前设计器中填写/导入的测试数据
|
|
64
|
+
|
|
65
|
+
**典型工作流:**
|
|
66
|
+
1. 在设计器中拖拽元素,设计报告布局
|
|
67
|
+
2. 通过 API 或界面导入测试数据
|
|
68
|
+
3. 保存报告,布局和数据一起持久化
|
|
69
|
+
4. 加载报告时,布局和测试数据一起恢复
|
|
70
|
+
|
|
71
|
+
**保存的数据结构(与模板模式的区别):**
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"pages": [ /* ... */ ],
|
|
76
|
+
"canvasSize": { "width": 794, "height": 1123 },
|
|
77
|
+
"watermark": { /* ... */ },
|
|
78
|
+
"testData": {
|
|
79
|
+
"orderNo": "A001",
|
|
80
|
+
"customerName": "张三",
|
|
81
|
+
"items": [
|
|
82
|
+
{ "name": "产品A", "price": 100, "quantity": 2 }
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 对比总结
|
|
89
|
+
|
|
90
|
+
| 特性 | 模板模式 (template) | 报告模式 (report) |
|
|
91
|
+
|------|-------------------|------------------|
|
|
92
|
+
| 保存布局 | ✅ 是 | ✅ 是 |
|
|
93
|
+
| 保存测试数据 (`testData`) | ❌ 否 | ✅ 是 |
|
|
94
|
+
| 适用场景 | 通用打印模板 | 数据+布局一体的报告 |
|
|
95
|
+
| 数据注入时机 | 打印/导出时传入 | 设计时即绑定 |
|
|
96
|
+
| 典型用途 | 订单打印、标签打印 | 检测报告、统计报表 |
|
|
97
|
+
|
|
98
|
+
### 如何切换模式
|
|
99
|
+
|
|
100
|
+
**Vue 组件方式:**
|
|
101
|
+
|
|
102
|
+
```vue
|
|
103
|
+
<template>
|
|
104
|
+
<!-- 模板模式(默认) -->
|
|
105
|
+
<PrintDesigner mode="template" />
|
|
106
|
+
|
|
107
|
+
<!-- 报告模式 -->
|
|
108
|
+
<PrintDesigner mode="report" />
|
|
109
|
+
</template>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Web Component 方式:**
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
const designer = document.querySelector('print-designer');
|
|
116
|
+
|
|
117
|
+
// 切换为模板模式(默认)
|
|
118
|
+
designer.setMode('template');
|
|
119
|
+
|
|
120
|
+
// 切换为报告模式
|
|
121
|
+
designer.setMode('report');
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 快速开始
|
|
127
|
+
|
|
128
|
+
### 安装
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npm install
|
|
132
|
+
npm run dev
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Vue 组件方式
|
|
136
|
+
|
|
137
|
+
```vue
|
|
138
|
+
<template>
|
|
139
|
+
<PrintDesigner
|
|
140
|
+
mode="template"
|
|
141
|
+
:sample-data="sampleData"
|
|
142
|
+
/>
|
|
143
|
+
</template>
|
|
144
|
+
|
|
145
|
+
<script setup>
|
|
146
|
+
import { ref } from 'vue';
|
|
147
|
+
import PrintDesigner from './components/PrintDesigner.vue';
|
|
148
|
+
|
|
149
|
+
const sampleData = ref({
|
|
150
|
+
id: 1,
|
|
151
|
+
name: '测试报告',
|
|
152
|
+
variables: {
|
|
153
|
+
title: '报告标题',
|
|
154
|
+
customerName: '张三',
|
|
155
|
+
items: [
|
|
156
|
+
{ name: '产品A', price: 100, quantity: 2 },
|
|
157
|
+
{ name: '产品B', price: 200, quantity: 3 }
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
</script>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Web Component 方式
|
|
165
|
+
|
|
166
|
+
```html
|
|
167
|
+
<print-designer id="designer"></print-designer>
|
|
168
|
+
|
|
169
|
+
<script>
|
|
170
|
+
const designer = document.getElementById('designer');
|
|
171
|
+
|
|
172
|
+
// 设置模式
|
|
173
|
+
designer.setMode('template');
|
|
174
|
+
|
|
175
|
+
// 设置测试数据
|
|
176
|
+
designer.setTestData({
|
|
177
|
+
orderNo: 'ORD-001',
|
|
178
|
+
customerName: '张三',
|
|
179
|
+
items: [
|
|
180
|
+
{ name: '产品A', price: 100, quantity: 2 }
|
|
181
|
+
]
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// 设置模板列表
|
|
185
|
+
designer.setTemplates([
|
|
186
|
+
{
|
|
187
|
+
id: 'tpl-1',
|
|
188
|
+
name: 'A4 打印模板',
|
|
189
|
+
data: {
|
|
190
|
+
pages: [],
|
|
191
|
+
canvasSize: { width: 794, height: 1123 },
|
|
192
|
+
unit: 'mm'
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
], { currentTemplateId: 'tpl-1' });
|
|
196
|
+
</script>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 传入数据格式
|
|
202
|
+
|
|
203
|
+
### 1. 通过 `sample-data` 属性传入(Vue 组件方式)
|
|
204
|
+
|
|
205
|
+
使用 `PrintDesigner` 组件时,通过 `sample-data` 属性传入示例数据,用于设计器中的数据绑定预览:
|
|
206
|
+
|
|
207
|
+
```vue
|
|
208
|
+
<template>
|
|
209
|
+
<PrintDesigner :sample-data="sampleData" />
|
|
210
|
+
</template>
|
|
211
|
+
|
|
212
|
+
<script setup>
|
|
213
|
+
const sampleData = ref({
|
|
214
|
+
id: 8,
|
|
215
|
+
name: '测试报告',
|
|
216
|
+
createTime: '2026-05-01',
|
|
217
|
+
variables: {
|
|
218
|
+
dockname: '机场名称',
|
|
219
|
+
dronesn: '无人机序列号',
|
|
220
|
+
totalcount: 100,
|
|
221
|
+
flightRecords: [
|
|
222
|
+
{ time: '2026-04-02 09:30', taskname: '巡检任务A', distance: '12.5 km' },
|
|
223
|
+
{ time: '2026-04-02 14:00', taskname: '巡检任务B', distance: '8.3 km' }
|
|
224
|
+
],
|
|
225
|
+
chartData: [
|
|
226
|
+
{ category: '一月', value: 1200 },
|
|
227
|
+
{ category: '二月', value: 1500 },
|
|
228
|
+
{ category: '三月', value: 1800 }
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
</script>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**`sampleData` 字段说明:**
|
|
236
|
+
|
|
237
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
238
|
+
|-----|------|-----|------|
|
|
239
|
+
| `id` | `number` / `string` | 否 | 数据唯一标识 |
|
|
240
|
+
| `name` | `string` | 否 | 数据名称 |
|
|
241
|
+
| `variables` | `object` | **是** | 变量对象,包含所有可供模板绑定的数据 |
|
|
242
|
+
|
|
243
|
+
`variables` 对象支持任意嵌套结构:
|
|
244
|
+
- **简单值:** `string`、`number`、`boolean`
|
|
245
|
+
- **数组:** 用于表格和图表组件的数据源
|
|
246
|
+
- **嵌套对象:** 支持多级路径访问
|
|
247
|
+
|
|
248
|
+
### 2. 通过 `setTestData()` 方法传入(Web Component 方式)
|
|
249
|
+
|
|
250
|
+
```js
|
|
251
|
+
const designer = document.querySelector('print-designer');
|
|
252
|
+
|
|
253
|
+
designer.setTestData({
|
|
254
|
+
orderNo: 'ORD-2026-001',
|
|
255
|
+
customerName: '张三',
|
|
256
|
+
items: [
|
|
257
|
+
{ name: '产品A', price: 100, quantity: 2 },
|
|
258
|
+
{ name: '产品B', price: 200, quantity: 3 }
|
|
259
|
+
],
|
|
260
|
+
chartData: [
|
|
261
|
+
{ category: '一月', value: 1200 },
|
|
262
|
+
{ category: '二月', value: 1500 }
|
|
263
|
+
]
|
|
264
|
+
});
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 3. 通过 `setVariables()` 方法传入(Web Component 方式)
|
|
268
|
+
|
|
269
|
+
`setVariables` 用于在实际打印/导出时替换模板中的变量占位符:
|
|
270
|
+
|
|
271
|
+
```js
|
|
272
|
+
const designer = document.querySelector('print-designer');
|
|
273
|
+
|
|
274
|
+
// 加载模板
|
|
275
|
+
await designer.loadTemplate('tpl-order');
|
|
276
|
+
|
|
277
|
+
// 设置真实数据
|
|
278
|
+
designer.setVariables({
|
|
279
|
+
orderNo: 'REAL-2026-001',
|
|
280
|
+
customerName: '李四',
|
|
281
|
+
totalAmount: 5999.00
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// 静默打印
|
|
285
|
+
await designer.print({ mode: 'browser', options: { silent: true } });
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### 4. 模板数据结构(完整格式)
|
|
289
|
+
|
|
290
|
+
当你需要直接保存或加载完整的模板数据时,使用以下数据结构:
|
|
291
|
+
|
|
292
|
+
```json
|
|
293
|
+
{
|
|
294
|
+
"id": "tpl_001",
|
|
295
|
+
"name": "A4 订单模板",
|
|
296
|
+
"updatedAt": 1715251200000,
|
|
297
|
+
"data": {
|
|
298
|
+
"pages": [
|
|
299
|
+
{
|
|
300
|
+
"id": "page_1",
|
|
301
|
+
"elements": [
|
|
302
|
+
{
|
|
303
|
+
"id": "el_text_1",
|
|
304
|
+
"type": "text",
|
|
305
|
+
"x": 40,
|
|
306
|
+
"y": 40,
|
|
307
|
+
"width": 200,
|
|
308
|
+
"height": 24,
|
|
309
|
+
"content": "订单号: {#orderNo}",
|
|
310
|
+
"style": {
|
|
311
|
+
"fontSize": 14,
|
|
312
|
+
"fontWeight": "bold",
|
|
313
|
+
"color": "#111827"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"id": "el_table_1",
|
|
318
|
+
"type": "table",
|
|
319
|
+
"x": 40,
|
|
320
|
+
"y": 100,
|
|
321
|
+
"width": 500,
|
|
322
|
+
"height": 200,
|
|
323
|
+
"variable": "@items",
|
|
324
|
+
"columnsVariable": "@tableCols",
|
|
325
|
+
"showFooter": true,
|
|
326
|
+
"footerDataVariable": "@tableFooter",
|
|
327
|
+
"autoPaginate": true,
|
|
328
|
+
"style": {
|
|
329
|
+
"fontSize": 12,
|
|
330
|
+
"color": "#000000",
|
|
331
|
+
"headerBackgroundColor": "#f3f4f6",
|
|
332
|
+
"borderColor": "#d1d5db",
|
|
333
|
+
"borderWidth": 1
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
]
|
|
337
|
+
}
|
|
338
|
+
],
|
|
339
|
+
"canvasSize": { "width": 794, "height": 1123 },
|
|
340
|
+
"guides": [],
|
|
341
|
+
"zoom": 1,
|
|
342
|
+
"showGrid": true,
|
|
343
|
+
"headerHeight": 0,
|
|
344
|
+
"footerHeight": 0,
|
|
345
|
+
"showHeaderLine": false,
|
|
346
|
+
"showFooterLine": false,
|
|
347
|
+
"showMinimap": false,
|
|
348
|
+
"canvasBackground": "#ffffff",
|
|
349
|
+
"pageSpacingX": 0,
|
|
350
|
+
"pageSpacingY": 0,
|
|
351
|
+
"unit": "mm",
|
|
352
|
+
"watermark": {
|
|
353
|
+
"enabled": false,
|
|
354
|
+
"text": "",
|
|
355
|
+
"angle": -30,
|
|
356
|
+
"color": "#000000",
|
|
357
|
+
"opacity": 0.1,
|
|
358
|
+
"size": 24,
|
|
359
|
+
"density": 160
|
|
360
|
+
},
|
|
361
|
+
"testData": {
|
|
362
|
+
"orderNo": "A001",
|
|
363
|
+
"items": [
|
|
364
|
+
{ "name": "产品A", "price": 100, "quantity": 2 }
|
|
365
|
+
]
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
"ext": {
|
|
369
|
+
"availableVariables": [
|
|
370
|
+
{
|
|
371
|
+
"id": "order",
|
|
372
|
+
"label": "订单信息",
|
|
373
|
+
"children": [
|
|
374
|
+
{ "id": "orderNo", "label": "订单号" },
|
|
375
|
+
{ "id": "items", "label": "订单明细", "isArray": true }
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**顶层字段说明:**
|
|
384
|
+
|
|
385
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
386
|
+
|-----|------|-----|------|
|
|
387
|
+
| `id` | `string` | 是 | 模板唯一标识 |
|
|
388
|
+
| `name` | `string` | 是 | 模板名称 |
|
|
389
|
+
| `updatedAt` | `number` | 否 | 更新时间戳(毫秒) |
|
|
390
|
+
| `data` | `object` | 是 | 模板设计数据 |
|
|
391
|
+
| `data.pages` | `Page[]` | 是 | 页面列表,每个页面包含元素数组 |
|
|
392
|
+
| `data.canvasSize` | `Size` | 是 | 画布尺寸 `{ width, height }` |
|
|
393
|
+
| `data.unit` | `string` | 否 | 单位:`mm` / `px` / `pt` / `in` / `cm` |
|
|
394
|
+
| `data.watermark` | `WatermarkSettings` | 否 | 水印配置 |
|
|
395
|
+
| `data.guides` | `Guide[]` | 否 | 参考线列表 |
|
|
396
|
+
| `data.testData` | `object` | 否 | 测试数据(报告模式会保存) |
|
|
397
|
+
| `ext` | `object` | 否 | 扩展字段 |
|
|
398
|
+
| `ext.availableVariables` | `VariableTreeItem[]` | 否 | 模板绑定的变量树 |
|
|
399
|
+
| `permissions` | `object` | 否 | 权限控制 `{ editable, deletable, copyable }` |
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## 支持的元素类型
|
|
404
|
+
|
|
405
|
+
| 元素类型 | 说明 | 数据支持 |
|
|
406
|
+
|---------|------|---------|
|
|
407
|
+
| 文本(Text) | 显示静态文本或变量内容 | 静态内容 / 变量引用 |
|
|
408
|
+
| 长文本(LongText) | 自动扩展的多行文本 | 静态内容 / 变量引用 |
|
|
409
|
+
| 图片(Image) | 显示图片 | 静态URL / 变量引用 |
|
|
410
|
+
| 表格(Table) | 展示数据表格,支持自动分页 | 静态数据 / 数据变量 |
|
|
411
|
+
| 自定义表格(CustomTable) | 自由合并单元格的表格 | 静态数据 / 数据变量 |
|
|
412
|
+
| 条形码(Barcode) | 生成条形码 | 变量引用 |
|
|
413
|
+
| 二维码(QRCode) | 生成二维码 | 变量引用 |
|
|
414
|
+
| 图表(Chart) | ECharts 图表(柱状图/折线图/饼图/环形图/面积图) | 静态数据 / 数据变量 |
|
|
415
|
+
| 线条(Line) | 绘制直线 | — |
|
|
416
|
+
| 矩形(Rect) | 绘制矩形 | — |
|
|
417
|
+
| 圆形(Circle) | 绘制圆形 | — |
|
|
418
|
+
| 页码(PageNumber) | 显示页码信息 | — |
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## 数据绑定方式
|
|
423
|
+
|
|
424
|
+
### 1. 静态数据
|
|
425
|
+
|
|
426
|
+
直接在元素属性面板中输入静态内容,适用于固定不变的文本、图片URL等。
|
|
427
|
+
|
|
428
|
+
### 2. 变量绑定
|
|
429
|
+
|
|
430
|
+
使用特殊语法引用外部传入的数据,数据在打印/导出时动态替换。
|
|
431
|
+
|
|
432
|
+
### 3. 数组数据(表格 & 图表)
|
|
433
|
+
|
|
434
|
+
表格和图表组件可以绑定数组类型的数据变量。
|
|
435
|
+
|
|
436
|
+
**表格数据格式:**
|
|
437
|
+
|
|
438
|
+
```json
|
|
439
|
+
{
|
|
440
|
+
"items": [
|
|
441
|
+
{ "name": "产品A", "price": 100, "quantity": 2 },
|
|
442
|
+
{ "name": "产品B", "price": 200, "quantity": 3 }
|
|
443
|
+
],
|
|
444
|
+
"tableCols": [
|
|
445
|
+
{ "field": "name", "header": "产品名称", "width": 120 },
|
|
446
|
+
{ "field": "price", "header": "单价", "width": 80 },
|
|
447
|
+
{ "field": "quantity", "header": "数量", "width": 80 }
|
|
448
|
+
],
|
|
449
|
+
"tableFooter": [
|
|
450
|
+
{ "name": { "value": "合计" }, "price": { "value": "300" } }
|
|
451
|
+
]
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
在表格元素的属性面板中:
|
|
456
|
+
- **数据变量(variable):** 绑定到 `@items`
|
|
457
|
+
- **列定义变量(columnsVariable):** 绑定到 `@tableCols`
|
|
458
|
+
- **页脚数据变量(footerDataVariable):** 绑定到 `@tableFooter`
|
|
459
|
+
|
|
460
|
+
**图表数据格式:**
|
|
461
|
+
|
|
462
|
+
```json
|
|
463
|
+
{
|
|
464
|
+
"chartData": [
|
|
465
|
+
{ "category": "一月", "value": 1200 },
|
|
466
|
+
{ "category": "二月", "value": 1500 },
|
|
467
|
+
{ "category": "三月", "value": 1800 }
|
|
468
|
+
]
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
图表元素支持的绑定字段:
|
|
473
|
+
- **chartDataVariable:** 数据变量名
|
|
474
|
+
- **chartXField:** X轴/分类字段名
|
|
475
|
+
- **chartYField:** Y轴/数值字段名
|
|
476
|
+
- **chartNameField:** 名称字段(饼图)
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## 测试数据
|
|
481
|
+
|
|
482
|
+
在设计器中编辑时,可以手动编辑测试数据以便预览变量渲染效果。
|
|
483
|
+
|
|
484
|
+
### 设计器内编辑
|
|
485
|
+
|
|
486
|
+
在模板列表中对模板右键 → 选择"测试数据" → 在弹出的 JSON 编辑器中编辑测试数据。
|
|
487
|
+
|
|
488
|
+
### 通过 API 设置
|
|
489
|
+
|
|
490
|
+
```js
|
|
491
|
+
// Web Component 方式
|
|
492
|
+
designer.setTestData({
|
|
493
|
+
orderNo: 'TEST-001',
|
|
494
|
+
customerName: '测试客户'
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// 获取当前测试数据
|
|
498
|
+
const data = designer.getTestData();
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## 变量语法参考
|
|
504
|
+
|
|
505
|
+
| 语法 | 示例 | 说明 |
|
|
506
|
+
|-----|------|------|
|
|
507
|
+
| `@变量名` | `@customerName` | 使用 `@` 符号引用顶层变量 |
|
|
508
|
+
| `{#变量路径}` | `{#order.details[0].name}` | 使用 `{#}` 包裹,支持嵌套路径和数组索引 |
|
|
509
|
+
| `{#变量名}` | `{#orderNo}` | 与 `@` 等价,推荐使用此格式 |
|
|
510
|
+
|
|
511
|
+
在元素属性中绑定变量:
|
|
512
|
+
|
|
513
|
+
| 元素类型 | 可绑定属性的字段 | 示例 |
|
|
514
|
+
|---------|----------------|------|
|
|
515
|
+
| 文本 | `content` | `订单号: {#orderNo}` |
|
|
516
|
+
| 图片 | `variable` | `@logoUrl` |
|
|
517
|
+
| 表格 | `variable`、`columnsVariable`、`footerDataVariable` | `@items` |
|
|
518
|
+
| 条形码 | `variable` | `{#barcode}` |
|
|
519
|
+
| 二维码 | `variable` | `{#url}` |
|
|
520
|
+
| 图表 | `chartDataVariable` | `@chartData` |
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## 技术栈
|
|
525
|
+
|
|
526
|
+
- Vue 3
|
|
527
|
+
- TypeScript
|
|
528
|
+
- Pinia(状态管理)
|
|
529
|
+
- Tailwind CSS
|
|
530
|
+
- ECharts 5
|
|
531
|
+
- Monaco Editor(代码编辑器)
|
|
532
|
+
|
|
533
|
+
---
|
|
@@ -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-Bgmv52X1.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-Bgmv52X1.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-Dky7JXCp.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;
|