404 lines
12 KiB
Markdown
404 lines
12 KiB
Markdown
# 报告模板开发指南 | Template Development Guide
|
||
|
||
## 1. 概述
|
||
|
||
XP.ReportEngine 使用 JSON 格式定义报告模板。模板描述了 PDF 报告的页面结构、元素布局、数据绑定和样式定义。
|
||
|
||
模板文件存放在 `XP.ReportEngine/Templates/` 目录下,通过 `App.config` 中的 `Report:TemplatePath` 配置项指定使用哪个模板。
|
||
|
||
## 2. 新增模板步骤
|
||
|
||
### 2.1 创建模板文件
|
||
|
||
1. 在 `Templates/` 目录下创建新的 JSON 文件,如 `CustomReportTemplate.json`
|
||
2. 在 `.csproj` 中确认模板文件会被复制到输出目录(已有通配规则):
|
||
```xml
|
||
<Content Include="Templates\*.json">
|
||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||
</Content>
|
||
```
|
||
3. 修改 `App.config` 中的 `Report:TemplatePath` 指向新模板:
|
||
```xml
|
||
<add key="Report:TemplatePath" value="Templates\CustomReportTemplate.json" />
|
||
```
|
||
|
||
### 2.2 模板验证规则
|
||
|
||
模板加载后会自动验证,必须满足以下条件:
|
||
- 包含 `document` 顶层字段(页面设置)
|
||
- 包含 `pages` 顶层字段(至少一个页面定义)
|
||
- 包含 `styles` 顶层字段(样式字典)
|
||
|
||
验证失败时报告生成会返回错误,不会生成 PDF。
|
||
|
||
## 3. 模板 JSON 结构
|
||
|
||
```json
|
||
{
|
||
"document": { ... }, // 必需:文档级设置(页面尺寸、边距、页眉页脚)
|
||
"pages": [ ... ], // 必需:页面定义数组
|
||
"styles": { ... } // 必需:样式定义字典
|
||
}
|
||
```
|
||
|
||
## 4. document 配置
|
||
|
||
```json
|
||
{
|
||
"document": {
|
||
"pageSize": "A4",
|
||
"orientation": "Portrait",
|
||
"margins": { "top": 40, "bottom": 20, "left": 20, "right": 20 },
|
||
"header": {
|
||
"enabled": true,
|
||
"left": ["标题文本", "第二行文本"],
|
||
"right": ["右侧文本"],
|
||
"rightImageKey": "companyLogo",
|
||
"leftImageKey": "softwareLogo",
|
||
"fontSize": 7,
|
||
"color": "#666666",
|
||
"showLine": true
|
||
},
|
||
"footer": {
|
||
"enabled": true,
|
||
"left": ["公司名称"],
|
||
"right": ["{currentPage} / {totalPages}"],
|
||
"fontSize": 8,
|
||
"color": "#666666",
|
||
"showLine": true
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `pageSize` | string | `"A4"` | 页面尺寸 |
|
||
| `orientation` | string | `"Portrait"` | 方向:Portrait / Landscape |
|
||
| `margins` | object | `{top:20, bottom:20, left:20, right:20}` | 边距(mm) |
|
||
| `header` | object | null | 页眉配置(首页不显示) |
|
||
| `footer` | object | null | 页脚配置(首页不显示) |
|
||
|
||
### 页眉/页脚字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `enabled` | bool | 是否启用 |
|
||
| `left` | string[] | 左侧文本行(支持 `${}` 绑定) |
|
||
| `right` | string[] | 右侧文本行(支持 `${}` 绑定) |
|
||
| `leftImageKey` | string | 左侧图像的 dataKey |
|
||
| `rightImageKey` | string | 右侧图像的 dataKey |
|
||
| `fontSize` | float | 字体大小 |
|
||
| `color` | string | 字体颜色(十六进制) |
|
||
| `showLine` | bool | 是否显示分隔线 |
|
||
|
||
页脚特殊占位符:
|
||
- `{currentPage}` — 当前页码
|
||
- `{totalPages}` — 总页数
|
||
|
||
## 5. pages 页面定义
|
||
|
||
```json
|
||
{
|
||
"pages": [
|
||
{
|
||
"type": "homepage",
|
||
"elements": [ ... ]
|
||
},
|
||
{
|
||
"type": "customPage",
|
||
"elements": [ ... ]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `type` | string | 页面类型标识(`homepage` 类型不显示页眉页脚) |
|
||
| `elements` | array | 页面内的元素列表 |
|
||
|
||
### 内置页面类型
|
||
|
||
| 类型 | 说明 | 特殊行为 |
|
||
|------|------|---------|
|
||
| `homepage` | 首页 | 不显示页眉页脚 |
|
||
| `summary` | 汇总页 | 无 |
|
||
| `metricData` | 距离测量页 | 无 |
|
||
| `bgaInspection` | BGA 检测页 | 无 |
|
||
| `voidInspection` | 空隙检测页 | 无 |
|
||
| `viaFillInspection` | 通孔填锡页 | 无 |
|
||
|
||
你可以自定义任意 `type` 名称,只有 `homepage` 有特殊行为(不显示页眉页脚)。
|
||
|
||
## 6. 元素类型
|
||
|
||
### 6.1 text — 文本元素
|
||
|
||
```json
|
||
{
|
||
"type": "text",
|
||
"content": "${loc:Report_Title}",
|
||
"style": "heading",
|
||
"positioning": "flow",
|
||
"align": "center",
|
||
"colorRules": { "Pass": "#008000", "Fail": "#FF0000" }
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `content` | string | 文本内容,支持 `${}` 绑定表达式 |
|
||
| `style` | string | 引用 `styles` 中定义的样式名 |
|
||
| `align` | string | 对齐:left / center / right |
|
||
| `colorRules` | object | 条件颜色规则(内容包含关键词时变色) |
|
||
|
||
### 6.2 image — 图像元素
|
||
|
||
```json
|
||
{
|
||
"type": "image",
|
||
"dataKey": "workpieceImage",
|
||
"size": [160, 110],
|
||
"border": true,
|
||
"align": "center",
|
||
"style": "imageDefault",
|
||
"positioning": "flow"
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `dataKey` | string | 图像数据键(对应 `ReportContext.Images` 中的键) |
|
||
| `size` | float[2] | [宽, 高](mm),图像会等比缩放适应 |
|
||
| `border` | bool | 是否显示边框 |
|
||
| `align` | string | 对齐:left / center / right |
|
||
|
||
图像缺失时会渲染灰色占位矩形,不会中断报告生成。
|
||
|
||
### 6.3 table — 表格元素
|
||
|
||
```json
|
||
{
|
||
"type": "table",
|
||
"dataKey": "bgaBallsTable",
|
||
"positioning": "flow",
|
||
"size": [170, 0],
|
||
"style": "tableDefault",
|
||
"columns": [
|
||
{ "header": "序号", "field": "index", "width": 25, "align": "center" },
|
||
{ "header": "气泡率", "field": "voidRate", "width": 40, "align": "center" },
|
||
{ "header": "面积", "field": "area", "width": 40, "align": "center" },
|
||
{
|
||
"header": "分类",
|
||
"field": "classification",
|
||
"width": 35,
|
||
"align": "center",
|
||
"colorRules": { "Pass": "#008000", "Fail": "#FF0000" }
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `dataKey` | string | 表格数据键(对应 `ReportContext.Properties` 中的 `List<Dictionary<string, object>>` 数据) |
|
||
| `size` | float[2] | [宽, 高](mm),高度为 0 表示自动 |
|
||
| `columns` | array | 列定义数组 |
|
||
|
||
#### 列定义(ColumnDefinition)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `header` | string | 表头文本(支持 `${}` 绑定) |
|
||
| `field` | string | 数据字段名(对应行数据字典中的键) |
|
||
| `width` | float | 列宽(mm) |
|
||
| `align` | string | 对齐:left / center / right |
|
||
| `colorRules` | object | 条件颜色规则(单元格值匹配时变色) |
|
||
|
||
### 6.4 row — 水平布局容器
|
||
|
||
```json
|
||
{
|
||
"type": "row",
|
||
"size": [170, 100],
|
||
"widths": [6, 4],
|
||
"positioning": "flow",
|
||
"children": [
|
||
{
|
||
"type": "column", "align": "left",
|
||
"children": [
|
||
{ "type": "image", "dataKey": "myImage", "size": [110, 90] }
|
||
]
|
||
},
|
||
{
|
||
"type": "column", "align": "left",
|
||
"children": [
|
||
{ "type": "text", "content": "文本内容", "style": "body" }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `size` | float[2] | [总宽, 总高](mm) |
|
||
| `widths` | float[] | 列宽比例数组(如 `[6, 4]` 表示 60%:40%) |
|
||
| `children` | array | 子列元素(`type: "column"`) |
|
||
|
||
### 6.5 spacer — 间距元素
|
||
|
||
```json
|
||
{ "type": "spacer", "size": [170, 10], "positioning": "flow" }
|
||
```
|
||
|
||
用于在元素之间添加垂直间距。`size[1]` 为间距高度(mm)。
|
||
|
||
### 6.6 divider — 分隔线
|
||
|
||
```json
|
||
{ "type": "divider", "positioning": "flow" }
|
||
```
|
||
|
||
渲染一条水平分隔线。
|
||
|
||
### 6.7 pagebreak — 强制分页
|
||
|
||
```json
|
||
{ "type": "pagebreak" }
|
||
```
|
||
|
||
在当前位置强制插入分页符。
|
||
|
||
## 7. 样式定义
|
||
|
||
```json
|
||
{
|
||
"styles": {
|
||
"heading": {
|
||
"font": "auto",
|
||
"size": 16,
|
||
"bold": true,
|
||
"italic": false,
|
||
"color": "#333333",
|
||
"align": "left",
|
||
"marginTop": 0,
|
||
"marginBottom": 3,
|
||
"paddingLeft": 0,
|
||
"lineHeight": 0,
|
||
"backgroundColor": ""
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `font` | string | `"auto"` | 字体(`auto` 根据语言自动选择) |
|
||
| `size` | float | 12 | 字体大小(pt) |
|
||
| `bold` | bool | false | 粗体 |
|
||
| `italic` | bool | false | 斜体 |
|
||
| `color` | string | `"#000000"` | 字体颜色(十六进制) |
|
||
| `align` | string | `"left"` | 对齐:left / center / right |
|
||
| `backgroundColor` | string | — | 背景色(十六进制) |
|
||
| `marginTop` | float | 0 | 上边距(mm) |
|
||
| `marginBottom` | float | 0 | 下边距(mm) |
|
||
| `paddingLeft` | float | 0 | 左缩进(mm) |
|
||
| `lineHeight` | float | 0 | 行高倍数(0 = 默认) |
|
||
|
||
元素引用未定义的样式名时,会使用默认样式(12pt、黑色、左对齐),不会报错。
|
||
|
||
## 8. 数据绑定表达式
|
||
|
||
模板中的 `content`、`header` 等文本字段支持 `${}` 绑定表达式:
|
||
|
||
| 语法 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| `${key}` | 从 Properties 中取值 | `${sampleName}` |
|
||
| `${metadata.field}` | 从 Metadata 中取值 | `${metadata.reportId}` |
|
||
| `${loc:Key}` | 多语言资源键 | `${loc:Report_Title}` |
|
||
| `${formatDate(value)}` | 格式化日期 | `${formatDate(metadata.inspectionDate)}` |
|
||
| `${formatNumber(value, decimals)}` | 格式化数字 | `${formatNumber(totalArea, 2)}` |
|
||
| `${formatPercent(value)}` | 格式化百分比 | `${formatPercent(voidRate)}` |
|
||
|
||
### 数据来源
|
||
|
||
绑定表达式从 `ReportContext` 中查找数据:
|
||
- `Properties` 字典 — 扁平化的键值对(由 `ProcessorDataAdapter` 从处理器输出转换而来)
|
||
- `Metadata` — 报告元数据对象
|
||
- `Images` 字典 — 图像数据(通过 `dataKey` 引用)
|
||
|
||
### ProcessorDataAdapter 输出的键名
|
||
|
||
| 处理器类型 | Properties 中的键 | Images 中的键 | 表格 dataKey |
|
||
|-----------|------------------|--------------|-------------|
|
||
| LineMeasurementProcessor | measurementType, point1, point2, pixelDistance, actualDistance, unit, angle | lineMeasurementImage | — |
|
||
| BgaVoidRateProcessor | bgaCount, voidRate, fillRate, totalBgaArea, totalVoidArea, voidLimit, classification | bgaInspectionImage | bgaBallsTable |
|
||
| VoidMeasurementProcessor | roiArea, totalVoidArea, voidRate, voidLimit, voidCount, maxVoidArea, classification | voidInspectionImage | voidsTable |
|
||
| FillRateProcessor | fillRate, voidRate, fullDistance, fillDistance, thtLimit, classification, e1-e4 | viaFillImage | — |
|
||
|
||
### ReportService 自动注入的键
|
||
|
||
| 键 | 来源 | 说明 |
|
||
|----|------|------|
|
||
| `CompanyName` | ReportConfig | 公司名称 |
|
||
| `SoftwareName` | ReportConfig | 软件名称 |
|
||
| `companyLogo` | ReportConfig.CompanyLogo | 公司 Logo(Images) |
|
||
| `softwareLogo` | ReportConfig.SoftwareLogo | 软件 Logo(Images) |
|
||
| `summaryTable` | 自动生成 | 首页汇总表数据 |
|
||
|
||
## 9. 定位方式
|
||
|
||
| 值 | 说明 |
|
||
|----|------|
|
||
| `"flow"` | 流式布局,元素按顺序从上到下排列(推荐) |
|
||
| `"absolute"` | 绝对定位,使用 `position` 坐标(不推荐,兼容性差) |
|
||
|
||
建议所有元素使用 `"positioning": "flow"`。
|
||
|
||
## 10. 完整模板示例(最小化)
|
||
|
||
```json
|
||
{
|
||
"document": {
|
||
"pageSize": "A4",
|
||
"orientation": "Portrait",
|
||
"margins": { "top": 20, "bottom": 20, "left": 20, "right": 20 }
|
||
},
|
||
"pages": [
|
||
{
|
||
"type": "homepage",
|
||
"elements": [
|
||
{ "type": "text", "content": "检测报告", "style": "title", "positioning": "flow" },
|
||
{ "type": "text", "content": "报告编号:${metadata.reportId}", "style": "body", "positioning": "flow" },
|
||
{ "type": "text", "content": "检测日期:${formatDate(metadata.inspectionDate)}", "style": "body", "positioning": "flow" }
|
||
]
|
||
},
|
||
{
|
||
"type": "dataPage",
|
||
"elements": [
|
||
{ "type": "text", "content": "检测数据", "style": "heading", "positioning": "flow" },
|
||
{ "type": "image", "dataKey": "inspectionImage", "size": [150, 100], "positioning": "flow" }
|
||
]
|
||
}
|
||
],
|
||
"styles": {
|
||
"title": { "size": 24, "bold": true, "align": "center" },
|
||
"heading": { "size": 16, "bold": true },
|
||
"body": { "size": 12 }
|
||
}
|
||
}
|
||
```
|
||
|
||
## 11. 注意事项
|
||
|
||
1. **尺寸单位**:所有尺寸(size、margins、width)单位为 **mm**(毫米)
|
||
2. **颜色格式**:使用十六进制格式 `#RRGGBB`(如 `#FF0000` 为红色)
|
||
3. **表格自动跨页**:当表格数据行超出当前页面剩余空间时,排版引擎会自动分页
|
||
4. **图像缺失容错**:图像 dataKey 对应的数据不存在时,渲染占位矩形,不中断生成
|
||
5. **样式缺失容错**:引用未定义的样式名时使用默认样式,不中断生成
|
||
6. **绑定表达式缺失**:`${}` 表达式对应的数据不存在时,替换为空字符串
|
||
7. **首页特殊处理**:`type: "homepage"` 的页面不显示页眉页脚
|
||
8. **JSON 编码**:模板文件必须使用 **UTF-8** 编码保存
|