@worm-vue3-print/canvas 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 +54 -0
- package/dist/canvas.css +1 -0
- package/dist/components/CanvasArea.vue.d.ts +102 -0
- package/dist/components/CanvasPaper.vue.d.ts +50 -0
- package/dist/components/DesignerToolbar.vue.d.ts +59 -0
- package/dist/components/ExpressionEditor.vue.d.ts +16 -0
- package/dist/components/FieldTreePanel.vue.d.ts +11 -0
- package/dist/components/LayerPanel.vue.d.ts +14 -0
- package/dist/components/LeftPanel.vue.d.ts +24 -0
- package/dist/components/PresetColorPicker.vue.d.ts +10 -0
- package/dist/components/PrintDesigner.vue.d.ts +27 -0
- package/dist/components/PrintHtmlPreview.vue.d.ts +23 -0
- package/dist/components/PropertyPanel.vue.d.ts +23 -0
- package/dist/components/Ruler.vue.d.ts +12 -0
- package/dist/components/StatusBar.vue.d.ts +14 -0
- package/dist/components/WatermarkConfig.vue.d.ts +12 -0
- package/dist/components/elements/BarcodeElement.vue.d.ts +9 -0
- package/dist/components/elements/BaseElement.vue.d.ts +45 -0
- package/dist/components/elements/CellBarcode.vue.d.ts +10 -0
- package/dist/components/elements/HtmlElement.vue.d.ts +9 -0
- package/dist/components/elements/ImageElement.vue.d.ts +9 -0
- package/dist/components/elements/LineElement.vue.d.ts +7 -0
- package/dist/components/elements/LongTextElement.vue.d.ts +9 -0
- package/dist/components/elements/PageNumberElement.vue.d.ts +9 -0
- package/dist/components/elements/QrcodeElement.vue.d.ts +9 -0
- package/dist/components/elements/ShapeElement.vue.d.ts +7 -0
- package/dist/components/elements/TableContextMenu.vue.d.ts +19 -0
- package/dist/components/elements/TableElement.vue.d.ts +17 -0
- package/dist/components/elements/TextElement.vue.d.ts +9 -0
- package/dist/components/property/AdvancedGroup.vue.d.ts +13 -0
- package/dist/components/property/AppearanceGroup.vue.d.ts +10 -0
- package/dist/components/property/BindingControl.vue.d.ts +13 -0
- package/dist/components/property/BorderBgGroup.vue.d.ts +9 -0
- package/dist/components/property/CodeGroup.vue.d.ts +13 -0
- package/dist/components/property/ImageContentUpload.vue.d.ts +10 -0
- package/dist/components/property/PaginationGroup.vue.d.ts +9 -0
- package/dist/components/property/PositionSizeGroup.vue.d.ts +9 -0
- package/dist/components/property/PropertyGroup.vue.d.ts +19 -0
- package/dist/components/property/PropertySearch.vue.d.ts +7 -0
- package/dist/components/property/TableCellGroup.vue.d.ts +12 -0
- package/dist/components/property/TableRowGroup.vue.d.ts +8 -0
- package/dist/components/property/TableSettingsGroup.vue.d.ts +8 -0
- package/dist/composables/useAdsorb.d.ts +26 -0
- package/dist/composables/useAdsorbManager.d.ts +31 -0
- package/dist/composables/useAlign.d.ts +5 -0
- package/dist/composables/useBindingDisplay.d.ts +11 -0
- package/dist/composables/useClipboard.d.ts +251 -0
- package/dist/composables/useDesignerState.d.ts +1149 -0
- package/dist/composables/useDrag.d.ts +51 -0
- package/dist/composables/useGroup.d.ts +7 -0
- package/dist/composables/useGuides.d.ts +12 -0
- package/dist/composables/useHistory.d.ts +31 -0
- package/dist/composables/useHostAdapter.d.ts +4 -0
- package/dist/composables/useKeyboard.d.ts +22 -0
- package/dist/composables/useResize.d.ts +26 -0
- package/dist/composables/useSelection.d.ts +26 -0
- package/dist/composables/useStudioChrome.d.ts +8 -0
- package/dist/composables/useTableSelection.d.ts +10 -0
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +6444 -0
- package/dist/index.js.map +1 -0
- package/dist/render/browser-code-renderer.d.ts +3 -0
- package/dist/render/browser-pagination.d.ts +17 -0
- package/dist/types.d.ts +282 -0
- package/dist/utils/binding-registry.d.ts +8 -0
- package/dist/utils/binding.d.ts +16 -0
- package/dist/utils/default-config.d.ts +13 -0
- package/dist/utils/demo-data.d.ts +2 -0
- package/dist/utils/element-factory.d.ts +4 -0
- package/dist/utils/engine.d.ts +2 -0
- package/dist/utils/expression-eval.d.ts +30 -0
- package/dist/utils/field-groups.d.ts +21 -0
- package/dist/utils/migrate.d.ts +2 -0
- package/dist/utils/preset-colors.d.ts +2 -0
- package/dist/utils/property-search.d.ts +18 -0
- package/dist/utils/ruler.d.ts +7 -0
- package/dist/utils/scale.d.ts +2 -0
- package/dist/utils/table-matrix.d.ts +61 -0
- package/dist/utils/units.d.ts +4 -0
- package/dist/utils/zone-layout.d.ts +27 -0
- package/package.json +55 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PrintTemplateData, PageLayout, CodeRenderer } from '@worm-vue3-print/core';
|
|
2
|
+
export interface BrowserRenderResult {
|
|
3
|
+
/** 最终多页 HTML 字符串 */
|
|
4
|
+
html: string;
|
|
5
|
+
/** 总页数 */
|
|
6
|
+
pageCount: number;
|
|
7
|
+
/** 分页布局(调试/高级用途) */
|
|
8
|
+
pageLayouts: PageLayout[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 浏览器内完成「数据绑定 → 测量 → 分页 → 最终 HTML」全流程。
|
|
12
|
+
* @param template 模板 JSON(设计器 TemplateData 结构兼容)
|
|
13
|
+
* @param printData 业务数据
|
|
14
|
+
* @param baseUrl 图片相对路径拼接前缀
|
|
15
|
+
* @param codeRenderer 条码渲染器(browserCodeRenderer)
|
|
16
|
+
*/
|
|
17
|
+
export declare function renderHtmlPages(template: PrintTemplateData, printData?: Record<string, any> | Record<string, any>[], baseUrl?: string, codeRenderer?: CodeRenderer): Promise<BrowserRenderResult>;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/** 纸张尺寸 */
|
|
2
|
+
export type PaperSize = 'A4' | 'A3' | 'A5' | 'Letter' | 'Legal' | 'CUSTOM';
|
|
3
|
+
/** 元素所属区域(运行时标记,序列化时剥离;区域元素 left/top 相对所在区域左上角,单位 pt) */
|
|
4
|
+
export type ElementZone = 'content' | 'header' | 'footer';
|
|
5
|
+
/** 元素分页属性(非表格元素) */
|
|
6
|
+
export interface PaginationConfig {
|
|
7
|
+
pageable: boolean;
|
|
8
|
+
keepWithNext: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** 表格分页配置 */
|
|
11
|
+
export interface TablePaginationConfig {
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** 新模板数据模型(替代旧 PrintPanel / PrintTemplateJson) */
|
|
15
|
+
export interface TemplateData {
|
|
16
|
+
paperSize: PaperSize;
|
|
17
|
+
orientation: 'portrait' | 'landscape';
|
|
18
|
+
margins: {
|
|
19
|
+
top: number;
|
|
20
|
+
right: number;
|
|
21
|
+
bottom: number;
|
|
22
|
+
left: number;
|
|
23
|
+
};
|
|
24
|
+
header: {
|
|
25
|
+
height: number;
|
|
26
|
+
elements: TemplateElement[];
|
|
27
|
+
};
|
|
28
|
+
footer: {
|
|
29
|
+
height: number;
|
|
30
|
+
elements: TemplateElement[];
|
|
31
|
+
};
|
|
32
|
+
firstPageOverlay: {
|
|
33
|
+
height: number;
|
|
34
|
+
elements: TemplateElement[];
|
|
35
|
+
};
|
|
36
|
+
elements: TemplateElement[];
|
|
37
|
+
/** 元素坐标单位(新保存模板固定 'mm';旧数据无此字段按 pt 迁移) */
|
|
38
|
+
unit?: 'pt' | 'mm';
|
|
39
|
+
/** 自定义纸张宽度(mm),仅 paperSize='CUSTOM' 时有效 */
|
|
40
|
+
customWidth?: number;
|
|
41
|
+
/** 自定义纸张高度(mm),仅 paperSize='CUSTOM' 时有效 */
|
|
42
|
+
customHeight?: number;
|
|
43
|
+
/** 水印配置 */
|
|
44
|
+
watermark?: WatermarkOptions;
|
|
45
|
+
/** 手动参考线(设计态辅助,序列化保留,渲染端忽略) */
|
|
46
|
+
guides?: AlignLine[];
|
|
47
|
+
}
|
|
48
|
+
/** 模板元素引用(用于 TemplateData 各区域) */
|
|
49
|
+
export type TemplateElement = PrintElementData;
|
|
50
|
+
/** 元素类型 */
|
|
51
|
+
export type ElementType = 'text' | 'image' | 'longText' | 'table' | 'hline' | 'vline' | 'rect' | 'oval' | 'barcode' | 'qrcode' | 'html' | 'pageNumber';
|
|
52
|
+
/** 对齐方式 */
|
|
53
|
+
export type TextAlign = 'left' | 'center' | 'right';
|
|
54
|
+
/** 垂直对齐方式(文本类元素,未设置时按顶部处理,与打印端一致) */
|
|
55
|
+
export type VerticalAlign = 'top' | 'middle' | 'bottom';
|
|
56
|
+
/** 缩放手柄方向 */
|
|
57
|
+
export type ResizePoint = 'nw' | 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w';
|
|
58
|
+
/** 引导线 */
|
|
59
|
+
export interface AlignLine {
|
|
60
|
+
type: 'vertical' | 'horizontal';
|
|
61
|
+
position: number;
|
|
62
|
+
id?: string;
|
|
63
|
+
/** 引导线颜色(区分左/中/右对齐类型) */
|
|
64
|
+
color?: string;
|
|
65
|
+
}
|
|
66
|
+
/** 吸附结果 */
|
|
67
|
+
export interface AdsorbResult {
|
|
68
|
+
left: number;
|
|
69
|
+
top: number;
|
|
70
|
+
lines: AlignLine[];
|
|
71
|
+
}
|
|
72
|
+
/** 元素矩形(用于吸附检测) */
|
|
73
|
+
export interface ElementRect {
|
|
74
|
+
id: string;
|
|
75
|
+
left: number;
|
|
76
|
+
top: number;
|
|
77
|
+
width: number;
|
|
78
|
+
height: number;
|
|
79
|
+
}
|
|
80
|
+
/** 表格行类型:header 标题 / data 数据(全表唯一) / subtotal 当前页小计(每页末尾) / summary 整表汇总 */
|
|
81
|
+
export type TableRowType = 'header' | 'data' | 'subtotal' | 'summary';
|
|
82
|
+
/** 单边边框样式 */
|
|
83
|
+
export interface TableCellBorder {
|
|
84
|
+
width: number;
|
|
85
|
+
style: 'solid' | 'dashed' | 'dotted' | 'double' | 'none';
|
|
86
|
+
color: string;
|
|
87
|
+
}
|
|
88
|
+
/** 四边边框 */
|
|
89
|
+
export interface TableCellBorders {
|
|
90
|
+
top?: TableCellBorder;
|
|
91
|
+
right?: TableCellBorder;
|
|
92
|
+
bottom?: TableCellBorder;
|
|
93
|
+
left?: TableCellBorder;
|
|
94
|
+
}
|
|
95
|
+
/** 单元格内容类型 */
|
|
96
|
+
export type TableCellType = 'text' | 'barcode' | 'qrcode';
|
|
97
|
+
/** 单元格 */
|
|
98
|
+
export interface TableCell {
|
|
99
|
+
id: string;
|
|
100
|
+
formatter?: string;
|
|
101
|
+
cellType?: TableCellType;
|
|
102
|
+
barcodeType?: string;
|
|
103
|
+
qrCodeLevel?: string;
|
|
104
|
+
showBarcodeText?: boolean;
|
|
105
|
+
rowspan?: number;
|
|
106
|
+
colspan?: number;
|
|
107
|
+
merged?: boolean;
|
|
108
|
+
align?: TextAlign;
|
|
109
|
+
valign?: 'top' | 'middle' | 'bottom';
|
|
110
|
+
fontFamily?: string;
|
|
111
|
+
fontSize?: number;
|
|
112
|
+
fontWeight?: string;
|
|
113
|
+
color?: string;
|
|
114
|
+
backgroundColor?: string;
|
|
115
|
+
borders?: TableCellBorders;
|
|
116
|
+
padding?: number;
|
|
117
|
+
wordWrap?: boolean;
|
|
118
|
+
}
|
|
119
|
+
/** 表格行 */
|
|
120
|
+
export interface TableRow {
|
|
121
|
+
id: string;
|
|
122
|
+
type: TableRowType;
|
|
123
|
+
height: number;
|
|
124
|
+
repeatOnPage?: boolean;
|
|
125
|
+
cells: TableCell[];
|
|
126
|
+
}
|
|
127
|
+
/** 单元格选区(r/c 均为 0 基,闭区间) */
|
|
128
|
+
export interface TableSelection {
|
|
129
|
+
elementId: string;
|
|
130
|
+
r1: number;
|
|
131
|
+
c1: number;
|
|
132
|
+
r2: number;
|
|
133
|
+
c2: number;
|
|
134
|
+
}
|
|
135
|
+
/** 表格历史字段绑定(兼容存量模板,实际取 fields[0].dataSource) */
|
|
136
|
+
export interface ElementFieldBinding {
|
|
137
|
+
text?: string;
|
|
138
|
+
dataSource?: string;
|
|
139
|
+
}
|
|
140
|
+
/** 元素选项(序列化到 JSON) */
|
|
141
|
+
export interface ElementOptions {
|
|
142
|
+
left: number;
|
|
143
|
+
top: number;
|
|
144
|
+
width: number;
|
|
145
|
+
height: number;
|
|
146
|
+
/** @deprecated 统一使用 formatter */
|
|
147
|
+
title?: string;
|
|
148
|
+
testData?: string;
|
|
149
|
+
fontSize?: number;
|
|
150
|
+
fontWeight?: string;
|
|
151
|
+
fontFamily?: string;
|
|
152
|
+
color?: string;
|
|
153
|
+
backgroundColor?: string;
|
|
154
|
+
textAlign?: TextAlign;
|
|
155
|
+
verticalAlign?: VerticalAlign;
|
|
156
|
+
lineHeight?: number;
|
|
157
|
+
letterSpacing?: number;
|
|
158
|
+
fixed?: boolean;
|
|
159
|
+
locked?: boolean;
|
|
160
|
+
/** 元素可见性(图层面板切换) */
|
|
161
|
+
visible?: boolean;
|
|
162
|
+
borderWidth?: number;
|
|
163
|
+
borderStyle?: string;
|
|
164
|
+
borderColor?: string;
|
|
165
|
+
contentPaddingLeft?: number;
|
|
166
|
+
contentPaddingTop?: number;
|
|
167
|
+
contentPaddingRight?: number;
|
|
168
|
+
contentPaddingBottom?: number;
|
|
169
|
+
textDecoration?: string;
|
|
170
|
+
textType?: 'barcode' | 'qrcode';
|
|
171
|
+
barcodeType?: string;
|
|
172
|
+
barWidth?: number;
|
|
173
|
+
barAutoWidth?: string;
|
|
174
|
+
qrCodeLevel?: string;
|
|
175
|
+
src?: string;
|
|
176
|
+
fit?: string;
|
|
177
|
+
hideTitle?: boolean;
|
|
178
|
+
draggable?: boolean;
|
|
179
|
+
axis?: string;
|
|
180
|
+
transform?: number;
|
|
181
|
+
zIndex?: number;
|
|
182
|
+
groupId?: string;
|
|
183
|
+
pagination?: PaginationConfig;
|
|
184
|
+
tablePagination?: TablePaginationConfig;
|
|
185
|
+
/** @deprecated 静态布局模式已移除,所有表格统一使用动态模式 */
|
|
186
|
+
tableMode?: 'dynamic' | 'static';
|
|
187
|
+
tableRows?: TableRow[];
|
|
188
|
+
tableColWidths?: number[];
|
|
189
|
+
tableDefaultFontSize?: number;
|
|
190
|
+
tableDefaultColor?: string;
|
|
191
|
+
tableDefaultPadding?: number;
|
|
192
|
+
/** 列表数据源路径(data 行迭代的数据数组) */
|
|
193
|
+
dataSource?: string;
|
|
194
|
+
/** @deprecated 兼容存量表格模型;列表数据源优先使用 dataSource */
|
|
195
|
+
fields?: ElementFieldBinding[];
|
|
196
|
+
formatter?: string;
|
|
197
|
+
styler?: string;
|
|
198
|
+
rowStyler?: string;
|
|
199
|
+
longTextIndent?: number;
|
|
200
|
+
leftSpaceRemoved?: boolean;
|
|
201
|
+
lHeight?: number;
|
|
202
|
+
}
|
|
203
|
+
/** 元素类型元数据 */
|
|
204
|
+
export interface PrintElementTypeMeta {
|
|
205
|
+
title?: string;
|
|
206
|
+
type: ElementType;
|
|
207
|
+
editable?: boolean;
|
|
208
|
+
formatter?: string;
|
|
209
|
+
styler?: string;
|
|
210
|
+
}
|
|
211
|
+
/** 序列化元素数据 */
|
|
212
|
+
export interface PrintElementData {
|
|
213
|
+
id?: string;
|
|
214
|
+
type?: ElementType;
|
|
215
|
+
options: ElementOptions;
|
|
216
|
+
printElementType: PrintElementTypeMeta;
|
|
217
|
+
}
|
|
218
|
+
/** 水印配置 */
|
|
219
|
+
export interface WatermarkOptions {
|
|
220
|
+
/** 水印模式:fixed=固定文本,binding=绑定字段 */
|
|
221
|
+
mode?: 'fixed' | 'binding';
|
|
222
|
+
/** 固定文本(mode=fixed 时使用) */
|
|
223
|
+
content?: string;
|
|
224
|
+
/** 绑定字段(mode=binding 时使用) */
|
|
225
|
+
binding?: string;
|
|
226
|
+
/** 测试值(设计态预览使用) */
|
|
227
|
+
testData?: string;
|
|
228
|
+
/** 旋转角度 */
|
|
229
|
+
rotate?: number;
|
|
230
|
+
/** 颜色 */
|
|
231
|
+
color?: string;
|
|
232
|
+
/** 透明度 */
|
|
233
|
+
opacity?: number;
|
|
234
|
+
/** 显示时间戳 */
|
|
235
|
+
timestamp?: boolean;
|
|
236
|
+
/** 时间格式 */
|
|
237
|
+
format?: string;
|
|
238
|
+
}
|
|
239
|
+
/** 运行时元素(设计器中带状态) */
|
|
240
|
+
export interface RuntimeElement {
|
|
241
|
+
id: string;
|
|
242
|
+
options: ElementOptions;
|
|
243
|
+
printElementType: PrintElementTypeMeta;
|
|
244
|
+
selected?: boolean;
|
|
245
|
+
/** 运行时所属区域,序列化时剥离,缺省视为 content */
|
|
246
|
+
zone?: ElementZone;
|
|
247
|
+
}
|
|
248
|
+
/** 业务字段(宿主查询后传入,核心不内置字段字典) */
|
|
249
|
+
export interface PrintBusinessField {
|
|
250
|
+
id?: string;
|
|
251
|
+
fieldKey: string;
|
|
252
|
+
fieldLabel: string;
|
|
253
|
+
/** 字段类型;'list' 表示明细列表字段(用于表格数据源选择) */
|
|
254
|
+
fieldType: string;
|
|
255
|
+
sortOrder: number;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* 绑定位置描述(用于属性面板自动渲染绑定控件)
|
|
259
|
+
*/
|
|
260
|
+
export interface BindingDescriptor {
|
|
261
|
+
/** 绑定的属性路径(如 'options.formatter'、'options.tableRows[0].cells[0].formatter') */
|
|
262
|
+
targetPath: string;
|
|
263
|
+
/** 显示名称 */
|
|
264
|
+
label: string;
|
|
265
|
+
/** 数据源上下文 */
|
|
266
|
+
dataSource: 'main' | 'list' | 'subtotal' | 'summary';
|
|
267
|
+
/** 绑定的列表字段(仅表格行需要) */
|
|
268
|
+
listField?: string;
|
|
269
|
+
/** 提示文本 */
|
|
270
|
+
placeholder?: string;
|
|
271
|
+
/** 是否允许清空 */
|
|
272
|
+
clearable?: boolean;
|
|
273
|
+
}
|
|
274
|
+
/** 截图请求载荷(设计器叠层对比用) */
|
|
275
|
+
export interface ScreenshotRequest {
|
|
276
|
+
templateJson: TemplateData;
|
|
277
|
+
printData: Record<string, any>;
|
|
278
|
+
}
|
|
279
|
+
/** 截图适配器:宿主依据模板 + 数据返回 PNG Blob */
|
|
280
|
+
export type RequestScreenshotFn = (req: ScreenshotRequest) => Promise<Blob>;
|
|
281
|
+
/** 图片上传适配器:宿主上传文件并返回可访问的图片 URL */
|
|
282
|
+
export type UploadImageFn = (file: File) => Promise<string>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BindingDescriptor } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* 元素绑定声明注册表
|
|
4
|
+
* 每个元素类型声明其支持的 formatter 绑定位置
|
|
5
|
+
*/
|
|
6
|
+
export declare const ELEMENT_BINDING_REGISTRY: Record<string, BindingDescriptor[]>;
|
|
7
|
+
export declare function getTableCellBindings(rowType: string, rowIndex: number, cellIndex: number, listField?: string): BindingDescriptor[];
|
|
8
|
+
export declare function getElementBindings(element: any): BindingDescriptor[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RuntimeElement } from '../types';
|
|
2
|
+
import './expression-eval';
|
|
3
|
+
/** 从业务字段创建带 formatter 绑定的文本元素 */
|
|
4
|
+
export declare function createFieldElement(field: {
|
|
5
|
+
fieldKey: string;
|
|
6
|
+
fieldLabel: string;
|
|
7
|
+
}): RuntimeElement;
|
|
8
|
+
/** 非设计态文本内容解析:用共享引擎渲染 formatter */
|
|
9
|
+
export declare function resolveTextBinding(options: {
|
|
10
|
+
formatter?: string;
|
|
11
|
+
}, data?: Record<string, any>[]): string;
|
|
12
|
+
/**
|
|
13
|
+
* 设计态条码/二维码单元格取值:{field} 占位符替换为 demo 数据
|
|
14
|
+
* (列表字段取数据源首项,全局字段按路径取),无匹配回退通用示例码值
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveBarcodeDesignValue(formatter: string | undefined, listSource?: Record<string, any>[]): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TemplateData } from '../types';
|
|
2
|
+
export declare const PAPER_PRESETS: Record<string, {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* 获取纸张原始宽高(mm,未应用方向)
|
|
8
|
+
* CUSTOM 时读取 customWidth/customHeight,缺省回退 A4
|
|
9
|
+
*/
|
|
10
|
+
export declare function getPaperDimensions(t: Pick<TemplateData, 'paperSize' | 'orientation' | 'customWidth' | 'customHeight'>): {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RuntimeElement, ElementType, ElementOptions } from '../types';
|
|
2
|
+
export declare function generateId(): string;
|
|
3
|
+
export declare function createDefaultOptions(type: ElementType): ElementOptions;
|
|
4
|
+
export declare function createRuntimeElement(type: ElementType, options?: Partial<ElementOptions>): RuntimeElement;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { formatMoney, formatDate, toUpperCaseAmount, ifFn } from '@worm-vue3-print/core';
|
|
2
|
+
export declare const EXTENDED_FUNCTIONS: {
|
|
3
|
+
MONEY: typeof formatMoney;
|
|
4
|
+
CONCAT: (...args: any[]) => string;
|
|
5
|
+
IF: typeof ifFn;
|
|
6
|
+
FORMAT: (value: any) => string;
|
|
7
|
+
SUBSTR: (str: string, start: number, len?: number) => string;
|
|
8
|
+
LEN: (str: string) => number;
|
|
9
|
+
ROUND: (num: number, decimals: number) => number;
|
|
10
|
+
NOW: () => string;
|
|
11
|
+
IFEMPTY: (value: any, defaultVal: string) => string;
|
|
12
|
+
PAD: (value: any, len: number, char: string) => string;
|
|
13
|
+
REPLACE: (str: string, from: string, to: string) => string;
|
|
14
|
+
JSON: (value: any) => string;
|
|
15
|
+
DATE: typeof formatDate;
|
|
16
|
+
UPPER: typeof toUpperCaseAmount;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* 在受限沙箱内求值表达式
|
|
20
|
+
* @param expr 表达式字符串
|
|
21
|
+
* @param context 上下文变量
|
|
22
|
+
* @param _callableNames 保留参数,实际使用共享引擎
|
|
23
|
+
*/
|
|
24
|
+
export declare function safeEval(expr: string, context: Record<string, any>, _callableNames?: string[]): any;
|
|
25
|
+
/**
|
|
26
|
+
* 模板字符串求值:{表达式} 内 safeEval 求值,外为字面文本。
|
|
27
|
+
* 聚合函数 SUM/AVG/COUNT/MIN/MAX(field) 预处理(需 ctx.rows)。
|
|
28
|
+
* 单个 {expr} 求值失败时保留原 {expr} 文本。
|
|
29
|
+
*/
|
|
30
|
+
export declare function evaluateTemplate(text: string, ctx: Record<string, any>): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PrintBusinessField } from '../types';
|
|
2
|
+
export interface FieldGroup {
|
|
3
|
+
/** 分组键(fieldKey 首段);空串表示无分组的顶层字段 */
|
|
4
|
+
key: string;
|
|
5
|
+
/** 分组显示名:取容器字段的 fieldLabel,缺省回退为 key */
|
|
6
|
+
label: string;
|
|
7
|
+
/** 是否明细列表分组(容器字段 fieldType === 'list') */
|
|
8
|
+
isList: boolean;
|
|
9
|
+
/** 分组下的叶子字段 */
|
|
10
|
+
fields: PrintBusinessField[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 将宿主扁平字段按 fieldKey 首段分组:
|
|
14
|
+
* - 带点路径(supplier.name、goods.spec)归入首段分组;
|
|
15
|
+
* - 无点且作为其它字段前缀的记录视为分组容器(如 supplier/goods),
|
|
16
|
+
* 容器提供分组名称,fieldType='list' 标识明细列表(表格数据源);
|
|
17
|
+
* - 无点且无子字段的记录作为独立顶层字段。
|
|
18
|
+
*/
|
|
19
|
+
export declare function groupFields(fields: PrintBusinessField[]): FieldGroup[];
|
|
20
|
+
/** 按关键字过滤分组(匹配字段名/字段 key),无叶子的分组剔除 */
|
|
21
|
+
export declare function filterGroups(groups: FieldGroup[], keyword: string): FieldGroup[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** 属性面板搜索注册表:分组 → 表单项 → 关键词 */
|
|
2
|
+
export interface PropertyItem {
|
|
3
|
+
key: string;
|
|
4
|
+
keywords: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface PropertyGroupDef {
|
|
7
|
+
group: string;
|
|
8
|
+
groupLabel: string;
|
|
9
|
+
items: PropertyItem[];
|
|
10
|
+
}
|
|
11
|
+
export declare const PROPERTY_REGISTRY: PropertyGroupDef[];
|
|
12
|
+
/** 正向包含匹配:任一关键词包含搜索词即命中;空搜索恒命中 */
|
|
13
|
+
export declare function matchKeywords(search: string, keywords: string[]): boolean;
|
|
14
|
+
/** 计算命中的分组与表单项 key 集合 */
|
|
15
|
+
export declare function searchProperties(search: string): {
|
|
16
|
+
groups: string[];
|
|
17
|
+
itemKeys: Set<string>;
|
|
18
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { TableRow, TableRowType, TableCell, TableCellBorder, ElementOptions } from '../types';
|
|
2
|
+
export interface CellRect {
|
|
3
|
+
r1: number;
|
|
4
|
+
c1: number;
|
|
5
|
+
r2: number;
|
|
6
|
+
c2: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function createCell(partial?: Partial<TableCell>): TableCell;
|
|
9
|
+
/** 默认新建表格:3 列 × 4 行(标题/数据/小计/汇总),列宽均分 50mm,表格组件默认显示当前页小计行 */
|
|
10
|
+
export declare function createDefaultTable(): {
|
|
11
|
+
rows: TableRow[];
|
|
12
|
+
colWidths: number[];
|
|
13
|
+
};
|
|
14
|
+
/** 定位覆盖 (r,c) 的主格坐标(自身非 merged 即为主格) */
|
|
15
|
+
export declare function findMainCell(rows: TableRow[], r: number, c: number): {
|
|
16
|
+
r: number;
|
|
17
|
+
c: number;
|
|
18
|
+
};
|
|
19
|
+
/** 主格覆盖矩形 */
|
|
20
|
+
export declare function getSpanRect(rows: TableRow[], r: number, c: number): CellRect;
|
|
21
|
+
/** 由锚点/焦点推导矩形选区,并迭代扩展至完整包含所有跨越的合并格 */
|
|
22
|
+
export declare function normalizeSelection(rows: TableRow[], a: {
|
|
23
|
+
r: number;
|
|
24
|
+
c: number;
|
|
25
|
+
}, b: {
|
|
26
|
+
r: number;
|
|
27
|
+
c: number;
|
|
28
|
+
}): CellRect;
|
|
29
|
+
/** 合并合法性校验,返回拒绝原因或 null */
|
|
30
|
+
export declare function canMergeReason(rows: TableRow[], rect: CellRect): string | null;
|
|
31
|
+
/** 合并:左上为主格,非空内容空格拼接并入主格 */
|
|
32
|
+
export declare function mergeCells(rows: TableRow[], rect: CellRect): void;
|
|
33
|
+
/** 拆分选区内所有合并格:占位格恢复并复制主格样式 */
|
|
34
|
+
export declare function splitCells(rows: TableRow[], rect: CellRect): void;
|
|
35
|
+
/** 插入行。index 为参照行,position 决定插在其上方或下方 */
|
|
36
|
+
export declare function insertRow(rows: TableRow[], index: number, position: 'above' | 'below'): void;
|
|
37
|
+
/** 删除行;主格在被删行时移交下一行 */
|
|
38
|
+
export declare function deleteRow(rows: TableRow[], index: number): string | null;
|
|
39
|
+
/** 插入列 */
|
|
40
|
+
export declare function insertCol(rows: TableRow[], colWidths: number[], index: number, position: 'left' | 'right'): void;
|
|
41
|
+
/** 删除列;主格在被删列时移交右侧列 */
|
|
42
|
+
export declare function deleteCol(rows: TableRow[], colWidths: number[], index: number): string | null;
|
|
43
|
+
/** 行类型变更校验 + 写入。约束:header 顶部连续;data 唯一;subtotal/summary 在 data 之后;subtotal 在 summary 之前 */
|
|
44
|
+
export declare function setRowType(rows: TableRow[], index: number, type: TableRowType): string | null;
|
|
45
|
+
export type BorderPreset = 'all' | 'outer' | 'inner' | 'none';
|
|
46
|
+
/** 按预设批量写边框;none 时清空选区内所有格的 borders */
|
|
47
|
+
export declare function applyBorderPreset(rows: TableRow[], rect: CellRect, preset: BorderPreset, border: TableCellBorder): void;
|
|
48
|
+
/** 设计态下无边框单元格的辅助虚线:与背景网格线同风格(浅灰虚线),略深保证可读 */
|
|
49
|
+
export declare const GHOST_BORDER_CSS = "1px dashed rgba(0,0,0,0.18)";
|
|
50
|
+
/**
|
|
51
|
+
* 解析单元格某条边的最终 CSS border 值。
|
|
52
|
+
* - 有真实边框(style 非 none)→ 返回 `${width}pt ${style} ${color}`
|
|
53
|
+
* - 设计态且开关开启、且该边无边框 → 返回虚拟虚线(仅设计稿展示,不影响预览/打印)
|
|
54
|
+
* - 其余情况(预览态 / 开关关闭)→ 'none'
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveCellBorderCss(b: TableCellBorder | undefined, opts?: {
|
|
57
|
+
designMode?: boolean;
|
|
58
|
+
showGhostBorder?: boolean;
|
|
59
|
+
}): string;
|
|
60
|
+
/** 表格元素尺寸派生:options.width/height 恒等于列宽和/行高和(mm),与渲染端一致 */
|
|
61
|
+
export declare function syncTableElementSize(options: ElementOptions): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { RuntimeElement, TemplateData, ElementZone } from '../types';
|
|
2
|
+
/** 允许放入页眉/页脚的元素类型 */
|
|
3
|
+
export declare const ZONE_ALLOWED_TYPES: string[];
|
|
4
|
+
export interface ZoneRectPt {
|
|
5
|
+
left: number;
|
|
6
|
+
top: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
/** 纸张宽高(mm,含方向;CUSTOM 读取 customWidth/customHeight,缺省回退 A4) */
|
|
11
|
+
export declare function getPaperSizeMM(t: TemplateData): {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
/** 三区在纸面坐标系中的矩形(mm),布局:上边距→页眉→内容→页脚→下边距 */
|
|
16
|
+
export declare function getZoneRects(t: TemplateData): Record<ElementZone, ZoneRectPt>;
|
|
17
|
+
/** 纸面 mm 坐标 → 命中区域(高度为 0 的区域不参与命中) */
|
|
18
|
+
export declare function zoneFromPaperPoint(t: TemplateData, _x: number, y: number): ElementZone;
|
|
19
|
+
/** 将元素局部坐标 clamp 到区域矩形内(原地修改) */
|
|
20
|
+
export declare function clampToZone(el: RuntimeElement, zone: ZoneRectPt): void;
|
|
21
|
+
/**
|
|
22
|
+
* 拖拽/缩放结束后按元素中心点归区:
|
|
23
|
+
* 跨区时换算坐标并改写 zone;页眉/页脚内 clamp;类型不允许时拒绝跨入并 clamp 回内容区。
|
|
24
|
+
*/
|
|
25
|
+
export declare function finalizeElementZone(el: RuntimeElement, t: TemplateData): {
|
|
26
|
+
rejected: boolean;
|
|
27
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@worm-vue3-print/canvas",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Vue 3 可视化打印模板设计器画布(开源核心,无 Element Plus、无宿主业务依赖)",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./style.css": "./dist/canvas.css"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"keywords": [
|
|
22
|
+
"vue3",
|
|
23
|
+
"print",
|
|
24
|
+
"template",
|
|
25
|
+
"designer",
|
|
26
|
+
"canvas"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"test": "vitest run",
|
|
30
|
+
"test:watch": "vitest",
|
|
31
|
+
"build": "vite build && vue-tsc -p tsconfig.build.json"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"vue": "^3.5.0"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@worm-vue3-print/core": "^1.0.0",
|
|
38
|
+
"dompurify": "^3.4.12",
|
|
39
|
+
"jsbarcode": "^3.12.3",
|
|
40
|
+
"qrcode": "^1.5.4",
|
|
41
|
+
"sortablejs": "^1.15.7"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/qrcode": "^1.5.6",
|
|
45
|
+
"@types/sortablejs": "^1.15.9",
|
|
46
|
+
"@vitejs/plugin-vue": "^6.0.1",
|
|
47
|
+
"@vue/test-utils": "^2.4.11",
|
|
48
|
+
"happy-dom": "^20.10.6",
|
|
49
|
+
"typescript": "~5.9.3",
|
|
50
|
+
"vite": "^7.3.6",
|
|
51
|
+
"vitest": "^4.1.9",
|
|
52
|
+
"vue": "^3.5.24",
|
|
53
|
+
"vue-tsc": "^3.3.11"
|
|
54
|
+
}
|
|
55
|
+
}
|