Files
wucaixing-backend/REPORT_SYSTEM_GUIDE.md

140 lines
5.5 KiB
Markdown
Raw Normal View History

2026-05-13 16:14:53 +08:00
# 报表打印系统架构与使用说明
本文档详细介绍了当前报表打印系统的架构设计、核心组件及其使用方法。
## 1. 架构设计概览
本系统采用 **Provider 模式****流式任务构建 (Builder Pattern)** 相结合的设计,旨在实现报表生成的解耦、灵活配置与高扩展性。
### 核心组件
1. **IReportDataProvider (报表数据提供者)**
* **职责**:定义单一报表的元数据(模版、标题、类型)和数据准备逻辑。
* **优势**:将业务逻辑从 Service 层剥离,每个报表对应一个 Provider互不干扰易于维护。
* **关键方法**
* `getReportType()`: 唯一标识(如 `APPLICATION_FORM`)。
* `prepareData(params)`: 准备模版所需的数据。
* `getCoverProviderType()`: 定义关联的封面类型(支持自动封面)。
2. **ReportPrintJob (打印任务构建器)**
* **职责**:负责组装打印任务。它像一条流水线,可以按需添加封面、报表片段、设置公章/水印等。
* **特性**
* **链式调用**`createJob().addCover().addBatch().render()`
* **混合布局**:自动处理横向 (Landscape) 与纵向 (Portrait) 页面的合并。
* **上下文注入**:支持注入 CompanyId 用于公章/水印生成。
3. **ReportRenderService (渲染服务)**
* **职责**:底层的渲染引擎。
* **功能**
* 解析 Velocity 模版。
* 调用 Gotenberg 进行 HTML 转 PDF。
* 处理水印 (Watermark) 和电子公章 (Seal)。
* 合并多个 PDF 片段。
## 2. 现有报表类型
目前系统已实现的 Provider 如下:
| 报表类型 (Type) | Provider 类 | 描述 |
| :--- | :--- | :--- |
| `APPLICATION_FORM` | `DriverApplicationFormProvider` | 驾驶员应聘申请表 |
| `ID_CARD_SCAN` | `IdCardScanProvider` | 身份证扫描件 |
| `DRIVER_LICENSE_COPY` | `DriverLicenseCopyProvider` | 驾驶证复印件 |
| `QUALIFICATION_CERTIFICATE_COPY` | `QualificationCertificateCopyProvider` | 从业资格证复印件 |
| `QUALIFICATION_REVIEW` | `QualificationReviewProvider` | 资格审查及技能考核登记表 |
| `ACCIDENT_RECORD` | `AccidentRecordProvider` | 安全行车事故记录 (横向) |
| `VIOLATION_RECORD` | `ViolationRecordProvider` | 违章记录 (横向) |
| `ANNUAL_ASSESSMENT_RECORD` | `AnnualAssessmentRecordProvider` | 年度考核记录 |
| `MEDICAL_EXAMINATION_REPORT` | `MedicalExaminationReportProvider` | 体检报告 |
| `REWARD_PUNISHMENT_RECORD` | `RewardPunishmentRecordProvider` | 奖惩记录表 |
## 3. 使用方法 (开发指南)
### 3.1 创建新报表
1. **定义 Provider**
新建一个类实现 `IReportDataProvider`,并注册为 Spring Bean (`@Component`)。
```java
@Component
public class MyReportProvider implements IReportDataProvider {
@Override
public String getReportType() { return "MY_REPORT"; }
@Override
public String getTemplateCode() { return "templates/my/report.html.vm"; }
@Override
public Map<String, Object> prepareData(Map<String, Object> params) {
// 准备数据...
return Map.of("data", "value");
}
}
```
2. **创建 Velocity 模版**
`src/main/resources/templates/my/report.html.vm` 中编写 HTML。
### 3.2 调用打印服务
在业务 Service 中注入 `ReportRenderService``providerMap`,然后使用链式调用:
#### 场景 A单个报表打印 (带自动封面)
```java
public byte[] printMyReport(List<String> ids) {
// 1. 获取 Provider
IReportDataProvider provider = providerMap.get("MY_REPORT");
// 2. 构建任务
return reportRenderService.createJob(providerMap::get) // 传入查找器以支持自动封面
.withCompanyId(companyId) // 设置公司ID用于公章
.addCover(provider) // 自动添加关联封面
.addBatch(provider, ids, "id") // 批量添加报表内容
.useSeal(true) // 启用公章
.render(); // 渲染并返回 PDF
}
```
#### 场景 B一键打印 (多报表合并)
```java
public byte[] printAll(List<String> driverIds, List<String> types) {
var job = reportRenderService.createJob(providerMap::get)
.withCompanyId(companyId)
.useSeal(false); // 全局公章开关
for (String id : driverIds) {
// 1. 为每个驾驶员添加一个独立封面
job.addCover("COMMON_COVER", Map.of(
"title", "驾驶员档案",
"subtitle", "张三"
));
// 2. 依次添加选中的报表
for (String type : types) {
job.add(providerMap.get(type), Map.of("driverId", id));
}
}
return job.render();
}
```
### 3.3 进阶配置
* **横向布局**:在 Provider 中重写 `isLandscape()` 返回 `true`,或者在 Job 中调用 `.isLandscape(true)` (通常由 Provider
决定)。
* **自定义封面**Provider 可重写 `getCoverProviderType()` 指定特定封面,或重写 `getCoverData()` 自定义封面参数。
* **水印控制**`job.useWatermark(true).watermarkText("自定义水印")`
## 4. 模版工具支持
模版中内置了 `$tool` 工具类 (`ReportVelocityTool`),提供常用功能:
* `$tool.getDictLabel('type', value)`: 字典翻译
* `$tool.formatDate(date, 'yyyy-MM-dd')`: 日期格式化
* `$tool.getOssUrls(urlStr)`: 解析 OSS 图片链接
* `$tool.numberToChinese(num)`: 数字转中文大写
---
*文档生成日期2026-03-01*