Files

404 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 报告模板开发指南 | 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 | 公司 LogoImages |
| `softwareLogo` | ReportConfig.SoftwareLogo | 软件 LogoImages |
| `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** 编码保存