@worm-vue3-print/core 1.0.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 +37 -0
- package/dist/index.cjs +1816 -0
- package/dist/index.d.cts +376 -0
- package/dist/index.d.ts +376 -0
- package/dist/index.js +1758 -0
- package/package.json +37 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
type TokenType = 'num' | 'str' | 'bool' | 'ident' | 'punc';
|
|
2
|
+
interface Token {
|
|
3
|
+
type: TokenType;
|
|
4
|
+
value: string;
|
|
5
|
+
position: number;
|
|
6
|
+
}
|
|
7
|
+
type ASTNode = {
|
|
8
|
+
type: 'num';
|
|
9
|
+
value: number;
|
|
10
|
+
} | {
|
|
11
|
+
type: 'str';
|
|
12
|
+
value: string;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'bool';
|
|
15
|
+
value: boolean;
|
|
16
|
+
} | {
|
|
17
|
+
type: 'ident';
|
|
18
|
+
name: string;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'binary';
|
|
21
|
+
op: string;
|
|
22
|
+
left: ASTNode;
|
|
23
|
+
right: ASTNode;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'unary';
|
|
26
|
+
op: string;
|
|
27
|
+
arg: ASTNode;
|
|
28
|
+
prefix: boolean;
|
|
29
|
+
} | {
|
|
30
|
+
type: 'ternary';
|
|
31
|
+
cond: ASTNode;
|
|
32
|
+
consequent: ASTNode;
|
|
33
|
+
alternate: ASTNode;
|
|
34
|
+
} | {
|
|
35
|
+
type: 'member';
|
|
36
|
+
object: ASTNode;
|
|
37
|
+
property: string;
|
|
38
|
+
computed: boolean;
|
|
39
|
+
} | {
|
|
40
|
+
type: 'call';
|
|
41
|
+
callee: ASTNode;
|
|
42
|
+
args: ASTNode[];
|
|
43
|
+
} | {
|
|
44
|
+
type: 'array';
|
|
45
|
+
elements: ASTNode[];
|
|
46
|
+
} | {
|
|
47
|
+
type: 'object';
|
|
48
|
+
properties: Array<{
|
|
49
|
+
key: string;
|
|
50
|
+
value: ASTNode;
|
|
51
|
+
}>;
|
|
52
|
+
};
|
|
53
|
+
type TemplatePart = {
|
|
54
|
+
type: 'text';
|
|
55
|
+
value: string;
|
|
56
|
+
} | {
|
|
57
|
+
type: 'expr';
|
|
58
|
+
expression: ASTNode;
|
|
59
|
+
};
|
|
60
|
+
interface TemplateAST {
|
|
61
|
+
type: 'template';
|
|
62
|
+
parts: TemplatePart[];
|
|
63
|
+
}
|
|
64
|
+
type ExprFunction = (...args: any[]) => any;
|
|
65
|
+
interface EngineOptions {
|
|
66
|
+
/** 自定义函数注册表 */
|
|
67
|
+
functions?: Record<string, ExprFunction>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
declare function tokenize(input: string): Token[];
|
|
71
|
+
|
|
72
|
+
declare function parse(tokens: Token[]): ASTNode;
|
|
73
|
+
|
|
74
|
+
declare function evaluate(node: ASTNode, context: Record<string, any>, functions?: Record<string, ExprFunction>): any;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 解析模板字符串为 TemplateAST
|
|
78
|
+
* 语法: {expr} 内为表达式,外部为字面文本
|
|
79
|
+
* 转义: \{ \} 不解析为表达式
|
|
80
|
+
*/
|
|
81
|
+
declare function parseTemplate(template: string): TemplateAST;
|
|
82
|
+
/**
|
|
83
|
+
* 将 TemplateAST 渲染为最终字符串
|
|
84
|
+
*/
|
|
85
|
+
declare function renderTemplate(ast: TemplateAST, context: Record<string, any>, functions?: Record<string, ExprFunction>): string;
|
|
86
|
+
/**
|
|
87
|
+
* 编译模板,返回渲染函数(性能优化:AST 只解析一次)
|
|
88
|
+
*/
|
|
89
|
+
declare function compileTemplate(template: string, functions?: Record<string, ExprFunction>): (context: Record<string, any>) => string;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 按点分路径取值;优先扁平 key(含点),其次嵌套路径。取不到返回 undefined。
|
|
93
|
+
*/
|
|
94
|
+
declare function getByPath(obj: any, path: string): any;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 金额格式化:千分位 + 两位小数
|
|
98
|
+
*/
|
|
99
|
+
declare function formatMoney(value: any): string;
|
|
100
|
+
/**
|
|
101
|
+
* 日期格式化
|
|
102
|
+
* 支持: YYYY, MM, DD, HH, mm, ss
|
|
103
|
+
*/
|
|
104
|
+
declare function formatDate(value: any, fmt: string): string;
|
|
105
|
+
/**
|
|
106
|
+
* 数字转大写金额
|
|
107
|
+
*/
|
|
108
|
+
declare function toUpperCaseAmount(value: any): string;
|
|
109
|
+
/**
|
|
110
|
+
* 条件判断函数
|
|
111
|
+
*/
|
|
112
|
+
declare function ifFn(condition: any, trueVal: any, falseVal: any): any;
|
|
113
|
+
|
|
114
|
+
declare function sum(rows: any[], field: string): number;
|
|
115
|
+
declare function avg(rows: any[], field: string): number;
|
|
116
|
+
declare function count(rows: any[], field: string): number;
|
|
117
|
+
declare function min(rows: any[], field: string): number;
|
|
118
|
+
declare function max(rows: any[], field: string): number;
|
|
119
|
+
|
|
120
|
+
declare function setPageIndex(v: number): void;
|
|
121
|
+
declare function setTotalPages(v: number): void;
|
|
122
|
+
declare const systemVars: {
|
|
123
|
+
pageIndex: () => number;
|
|
124
|
+
totalPages: () => number;
|
|
125
|
+
printDate: () => string;
|
|
126
|
+
printTime: () => number;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
type PaperSize = 'A4' | 'A3' | 'A5' | 'Letter' | 'Legal' | 'CUSTOM';
|
|
130
|
+
/** 纸张尺寸映射(mm) */
|
|
131
|
+
declare const PAPER_DIMENSIONS: Record<PaperSize, {
|
|
132
|
+
width: number;
|
|
133
|
+
height: number;
|
|
134
|
+
}>;
|
|
135
|
+
interface TemplateData {
|
|
136
|
+
paperSize: PaperSize;
|
|
137
|
+
orientation: 'portrait' | 'landscape';
|
|
138
|
+
/** 自定义纸张宽度(mm),仅 paperSize='CUSTOM' 时生效 */
|
|
139
|
+
customWidth?: number;
|
|
140
|
+
/** 自定义纸张高度(mm),仅 paperSize='CUSTOM' 时生效 */
|
|
141
|
+
customHeight?: number;
|
|
142
|
+
margins: {
|
|
143
|
+
top: number;
|
|
144
|
+
right: number;
|
|
145
|
+
bottom: number;
|
|
146
|
+
left: number;
|
|
147
|
+
};
|
|
148
|
+
header: {
|
|
149
|
+
height: number;
|
|
150
|
+
elements: TemplateElement[];
|
|
151
|
+
};
|
|
152
|
+
footer: {
|
|
153
|
+
height: number;
|
|
154
|
+
elements: TemplateElement[];
|
|
155
|
+
};
|
|
156
|
+
firstPageOverlay: {
|
|
157
|
+
height: number;
|
|
158
|
+
elements: TemplateElement[];
|
|
159
|
+
};
|
|
160
|
+
elements: TemplateElement[];
|
|
161
|
+
}
|
|
162
|
+
/** 元素分页属性(非表格元素) */
|
|
163
|
+
interface PaginationConfig {
|
|
164
|
+
pageable: boolean;
|
|
165
|
+
keepWithNext: boolean;
|
|
166
|
+
}
|
|
167
|
+
/** 表格分页配置 */
|
|
168
|
+
interface TablePaginationConfig {
|
|
169
|
+
enabled: boolean;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 模板元素 — print-render 侧的简化视图。
|
|
173
|
+
* 兼容前端 PrintElementData 的 options 嵌套结构,
|
|
174
|
+
* 同时提供扁平访问器方便分页引擎使用。
|
|
175
|
+
*/
|
|
176
|
+
interface TemplateElement {
|
|
177
|
+
id: string;
|
|
178
|
+
type: string;
|
|
179
|
+
/** 元素选项(与前端 ElementOptions 对齐) */
|
|
180
|
+
options: Record<string, any>;
|
|
181
|
+
/** 元素类型元数据(与前端 PrintElementTypeMeta 对齐) */
|
|
182
|
+
printElementType?: {
|
|
183
|
+
type: string;
|
|
184
|
+
title?: string;
|
|
185
|
+
[key: string]: any;
|
|
186
|
+
};
|
|
187
|
+
/** 分页属性(非表格元素) */
|
|
188
|
+
pagination?: PaginationConfig;
|
|
189
|
+
/** 表格分页配置(表格元素) */
|
|
190
|
+
tablePagination?: TablePaginationConfig;
|
|
191
|
+
}
|
|
192
|
+
type RenderRowType = 'header' | 'data' | 'summary' | 'subtotal' | 'static';
|
|
193
|
+
interface RenderCellBorder {
|
|
194
|
+
width: number;
|
|
195
|
+
style: string;
|
|
196
|
+
color: string;
|
|
197
|
+
}
|
|
198
|
+
interface RenderCellBorders {
|
|
199
|
+
top?: RenderCellBorder;
|
|
200
|
+
right?: RenderCellBorder;
|
|
201
|
+
bottom?: RenderCellBorder;
|
|
202
|
+
left?: RenderCellBorder;
|
|
203
|
+
}
|
|
204
|
+
/** 绑定后的单元格:content 已是最终文本(小计行 content 为占位值,真实值按每页数据渲染时求值) */
|
|
205
|
+
interface RenderCell {
|
|
206
|
+
content: string;
|
|
207
|
+
/** 小计行专用:单元格原始 formatter 表达式,渲染阶段以当前页数据行上下文求值 */
|
|
208
|
+
rawFormatter?: string;
|
|
209
|
+
/** 内容类型:text(默认)/ barcode / qrcode,非 text 时 content 为码值 */
|
|
210
|
+
cellType?: string;
|
|
211
|
+
/** 条形码码制(jsbarcode 格式名),仅 cellType='barcode' 时生效 */
|
|
212
|
+
barcodeType?: string;
|
|
213
|
+
/** 二维码纠错级别 L/M/Q/H,仅 cellType='qrcode' 时生效 */
|
|
214
|
+
qrCodeLevel?: string;
|
|
215
|
+
/** 条形码下方是否显示文本,仅 cellType='barcode' 时生效 */
|
|
216
|
+
showBarcodeText?: boolean;
|
|
217
|
+
rowspan: number;
|
|
218
|
+
colspan: number;
|
|
219
|
+
merged: boolean;
|
|
220
|
+
align?: string;
|
|
221
|
+
valign?: string;
|
|
222
|
+
fontSize?: number;
|
|
223
|
+
fontWeight?: string;
|
|
224
|
+
color?: string;
|
|
225
|
+
backgroundColor?: string;
|
|
226
|
+
borders?: RenderCellBorders;
|
|
227
|
+
padding?: number;
|
|
228
|
+
wordWrap?: boolean;
|
|
229
|
+
}
|
|
230
|
+
/** 绑定后的渲染行,存入 options._renderRows */
|
|
231
|
+
interface RenderRow {
|
|
232
|
+
type: RenderRowType;
|
|
233
|
+
height: number;
|
|
234
|
+
cells: RenderCell[];
|
|
235
|
+
}
|
|
236
|
+
interface CodeRenderOptions {
|
|
237
|
+
/** 条形码码制(jsbarcode 格式名),仅 barcode 类型使用 */
|
|
238
|
+
barcodeType?: string;
|
|
239
|
+
/** 二维码纠错级别 L/M/Q/H,仅 qrcode 类型使用 */
|
|
240
|
+
qrCodeLevel?: string;
|
|
241
|
+
/** 条形码下方是否显示文本 */
|
|
242
|
+
showText?: boolean;
|
|
243
|
+
/** 条码模块宽度倍率 */
|
|
244
|
+
barWidth?: number;
|
|
245
|
+
/** 条码下方文本字号(pt) */
|
|
246
|
+
fontSize?: number;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* 码值 → SVG 字符串渲染器。
|
|
250
|
+
* 服务端由 print-render 用 bwip-js 实现;浏览器由 print-canvas 用 jsbarcode/qrcode 实现。
|
|
251
|
+
* 码值非法时抛出异常,由调用方降级为文本占位。
|
|
252
|
+
*/
|
|
253
|
+
interface CodeRenderer {
|
|
254
|
+
render(value: string, cellType: 'barcode' | 'qrcode', opts?: CodeRenderOptions): string;
|
|
255
|
+
}
|
|
256
|
+
interface RenderRequest {
|
|
257
|
+
templateJson: TemplateData;
|
|
258
|
+
printData?: Record<string, any>;
|
|
259
|
+
/** 服务端对外访问 base URL,用于把 /docfiles/... 等相对路径图片拼接为完整地址 */
|
|
260
|
+
baseUrl?: string;
|
|
261
|
+
}
|
|
262
|
+
interface MeasuredElement {
|
|
263
|
+
id: string;
|
|
264
|
+
measuredHeight: number;
|
|
265
|
+
/** 表格每行实际高度(mm),仅表格元素有值 */
|
|
266
|
+
measuredRowHeights?: number[];
|
|
267
|
+
/** 重复表头段实际高度(mm)= 前 _repeatHeaderCount 个渲染行高之和,仅表格元素有值 */
|
|
268
|
+
repeatHeaderHeight?: number;
|
|
269
|
+
}
|
|
270
|
+
interface PageLayout {
|
|
271
|
+
pageIndex: number;
|
|
272
|
+
sections: PageSection[];
|
|
273
|
+
}
|
|
274
|
+
interface PageSection {
|
|
275
|
+
elementId: string;
|
|
276
|
+
type: 'element' | 'table-slice' | 'flow-group';
|
|
277
|
+
/** table-slice 专用:渲染行起始索引(含表头行) */
|
|
278
|
+
startRow?: number;
|
|
279
|
+
/** table-slice 专用:渲染行结束索引(不含) */
|
|
280
|
+
endRow?: number;
|
|
281
|
+
/** table-slice 专用:非首片时在切片前重复表头段 */
|
|
282
|
+
repeatHeader?: boolean;
|
|
283
|
+
/** table-slice 专用:本片末尾是否渲染小计行(当前页数据小计,每页重复) */
|
|
284
|
+
subtotal?: boolean;
|
|
285
|
+
/** table-slice 专用:本片末尾是否渲染整表汇总行(总计,仅最后一页) */
|
|
286
|
+
summary?: boolean;
|
|
287
|
+
/** 本节在本页内容区内的实际 top(mm)。发生换页后的内容为 0;缺省回退元素设计 top */
|
|
288
|
+
renderTop?: number;
|
|
289
|
+
/**
|
|
290
|
+
* flow-group 专用:相对容器在本页的实际 top(mm),覆盖元素设计 top。
|
|
291
|
+
* 同页时 = 表格设计 top(容器顶部对齐表格 slice 顶部);
|
|
292
|
+
* 跟随区整体移页时 = 新页内容区顶部(0)。
|
|
293
|
+
*/
|
|
294
|
+
groupTop?: number;
|
|
295
|
+
/** flow-group 专用:跟随区成员元素 id(容器内按文档流渲染) */
|
|
296
|
+
followElementIds?: string[];
|
|
297
|
+
}
|
|
298
|
+
/** 获取纸张物理尺寸(考虑方向) */
|
|
299
|
+
declare function getPaperDimensions(template: TemplateData): {
|
|
300
|
+
width: number;
|
|
301
|
+
height: number;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* 将模板中元素的 formatter 表达式求值为实际值。
|
|
306
|
+
* 返回新的模板对象(深拷贝),不修改原始模板。
|
|
307
|
+
*/
|
|
308
|
+
declare function bindData(template: TemplateData, printData?: Record<string, any> | Record<string, any>[], baseUrl?: string): TemplateData;
|
|
309
|
+
declare function injectSystemVariables(html: string): string;
|
|
310
|
+
|
|
311
|
+
interface GenerateOptions {
|
|
312
|
+
/** 第一遍测量模式:所有元素在一个连续区域,不分页 */
|
|
313
|
+
isMeasurementPass?: boolean;
|
|
314
|
+
/** 条码/二维码 SVG 渲染器;缺省或渲染抛错时降级为文本占位 */
|
|
315
|
+
codeRenderer?: CodeRenderer;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* 生成完整 HTML 字符串。
|
|
319
|
+
*
|
|
320
|
+
* - 第一遍(isMeasurementPass=true):单页连续区域,每个元素带 data-measure-id
|
|
321
|
+
* - 第二遍:按分页结果生成多页 HTML,填充 {pageIndex}/{totalPages}
|
|
322
|
+
*/
|
|
323
|
+
declare function generateHtml(template: TemplateData, pageLayouts: PageLayout[], printData?: Record<string, any>, options?: GenerateOptions): string;
|
|
324
|
+
|
|
325
|
+
/** mm 值转 CSS 字符串 */
|
|
326
|
+
declare function mm(value: number): string;
|
|
327
|
+
/**
|
|
328
|
+
* 生成完整的打印页面 CSS。
|
|
329
|
+
* 包含纸张尺寸、边距、页眉页脚、内容区、首页叠加区域等样式。
|
|
330
|
+
*/
|
|
331
|
+
declare function buildPageCss(template: TemplateData): string;
|
|
332
|
+
/**
|
|
333
|
+
* 生成内联样式:元素绝对定位(mm 单位)
|
|
334
|
+
*/
|
|
335
|
+
declare function elementPositionStyle(left: number, top: number, width: number, height?: number): string;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* 表格设计底部(mm)= 设计 top + 设计高度。
|
|
339
|
+
* 设计高度优先取 tableRows 设计行高之和(设计意图,不受渲染数据量影响),
|
|
340
|
+
* 缺失时回退 options.height。
|
|
341
|
+
*/
|
|
342
|
+
declare function tableDesignBottom(el: TemplateElement): number;
|
|
343
|
+
/**
|
|
344
|
+
* 基于测量结果执行分页计算,返回每页的布局方案。
|
|
345
|
+
*
|
|
346
|
+
* 算法流程:
|
|
347
|
+
* 1. 计算页面可用高度(contentHeight / availableHeight)
|
|
348
|
+
* 2. 按 Y 坐标顺序遍历内容区元素
|
|
349
|
+
* 3. 表格:逐行切片;非表格:元素级不拆分
|
|
350
|
+
* 4. 处理 keepWithNext、单行超高、首页叠加等边界
|
|
351
|
+
* 5. 表格下方跟随区:与最后一片同页时包成 flow-group;放不下整体移下一页
|
|
352
|
+
*/
|
|
353
|
+
declare function paginate(template: TemplateData, measuredElements: Map<string, MeasuredElement>): PageLayout[];
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* 在受限沙箱内求值表达式
|
|
357
|
+
* @param expr 表达式字符串
|
|
358
|
+
* @param context 上下文变量
|
|
359
|
+
*/
|
|
360
|
+
declare function safeEval(expr: string, context: Record<string, any>): any;
|
|
361
|
+
/**
|
|
362
|
+
* 模板字符串求值:{表达式} 内求值,外为字面文本。
|
|
363
|
+
* 聚合函数 SUM/AVG/COUNT/MIN/MAX(field) 预处理(需 ctx.rows)。
|
|
364
|
+
* 单个 {expr} 求值失败时保留原 {expr} 文本。
|
|
365
|
+
*/
|
|
366
|
+
declare function evaluateTemplate(text: string, ctx: Record<string, any>): string;
|
|
367
|
+
|
|
368
|
+
declare class TemplateEngine {
|
|
369
|
+
private functions;
|
|
370
|
+
constructor(options?: EngineOptions);
|
|
371
|
+
registerFunction(name: string, fn: ExprFunction): void;
|
|
372
|
+
evaluate(expression: string, context: Record<string, any>): any;
|
|
373
|
+
render(template: string, context: Record<string, any>): string;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export { type ASTNode, type CodeRenderOptions, type CodeRenderer, type EngineOptions, type ExprFunction, type GenerateOptions, type MeasuredElement, PAPER_DIMENSIONS, type PageLayout, type PageSection, type PaperSize, type TemplateData as PrintTemplateData, type TemplateElement as PrintTemplateElement, type RenderCell, type RenderRequest, type RenderRow, type TemplateAST, TemplateEngine, avg, bindData, buildPageCss, compileTemplate, count, elementPositionStyle, evaluate, evaluateTemplate, formatDate, formatMoney, generateHtml, getByPath, getPaperDimensions, ifFn, injectSystemVariables, max, min, mm, paginate, parse, parseTemplate, renderTemplate, safeEval, setPageIndex, setTotalPages, sum, systemVars, tableDesignBottom, toUpperCaseAmount, tokenize };
|