# 报表打印系统架构与使用说明 本文档详细介绍了当前报表打印系统的架构设计、核心组件及其使用方法。 ## 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 prepareData(Map 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 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 driverIds, List 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*