八、二次开发接入
本章面向开发人员:如何让一个新的业务单据接入打印中心(获得模板管理 + 打印按钮能力)。
8.1 接入总览
只需三步:
- 业务模块实现
PrintDataProvider接口并注册为 Spring Bean; - (可选)在 BD 基础数据登记单据类型,让模板管理页的树里出现分组;
- 前端业务列表页加【打印】按钮调
openPrint({ billType, billId })。
不需要写模板渲染代码——渲染、二维码、大写金额全部由打印中心与前端引擎完成。
8.2 SPI 接口定义
接口位于 pointlion-module-infra-api:
java
public interface PrintDataProvider {
String billType(); // 全局唯一,规范:模块_单据,如 fin_voucher
String billName(); // 单据显示名,如 "记账凭证"
String module(); // 所属模块:fin/oa/mes/erp/ams(模板管理分组用)
PrintDataDTO load(String billId); // 加载打印数据(展示模型)
default String sampleBillId() { return null; } // 样例单据ID(设计器预览,建议取最新一张)
List<PrintVariableDTO> variables(); // 变量契约(与 load 返回的 key 一一对应)
}核心约定:load() 返回展示模型——所有字段都是可直接显示的值:状态转中文、字典转标签、用户 ID 转昵称、金额按分转元、日期格式化。前端不做任何转换。
8.3 实现示例(记账凭证)
java
@Component
public class FinVoucherPrintProvider implements PrintDataProvider {
@Override public String billType() { return "fin_voucher"; }
@Override public String billName() { return "记账凭证"; }
@Override public String module() { return "fin"; }
@Override
public PrintDataDTO load(String billId) {
VoucherDO voucher = voucherMapper.selectById(Long.valueOf(billId));
// ... 查分录、科目、期间,状态/凭证字转中文
Map<String, Object> bill = new HashMap<>();
bill.put("voucherNo", voucher.getVoucherNo());
bill.put("statusName", statusToName(voucher.getStatus())); // 展示值
List<Map<String, Object>> items = new ArrayList<>();
// 每行分录 -> Map(lineNo/summary/accountCode/accountName/debit/credit)
return new PrintDataDTO("fin_voucher", billId, "记账凭证",
voucher.getVoucherNo(), bill, items);
}
@Override
public String sampleBillId() {
// 最新一张凭证,供设计器自动预览
return voucherMapper.selectLatestId();
}
@Override
public List<PrintVariableDTO> variables() {
return PrintVariableDTO.list()
.group("bill").add("voucherNo", "凭证号", "string")
.add("voucherDate", "凭证日期", "date")
// ...
.group("items").add("summary", "摘要", "string")
.add("debit", "借方金额", "money")
// ...
.build();
}
}变量 type 取值:string / number / money / date / datetime(供前端格式化参考)。
8.4 注册机制与错误码
- 启动时 Spring 注入全部
PrintDataProvider到注册中心(PrintProviderRegistry),启动日志打印「已注册打印单据类型 N 个」; - billType 重复:启动直接失败,错误码
1_002_029_002(单据类型重复注册)——命名务必带模块前缀; - 取数未注册:运行时报
1_002_029_001(单据类型未注册打印数据提供者); - 模板管理保存时会校验 billType 已注册,未注册报错。
8.5 数据库与菜单(可选)
| 事项 | 说明 |
|---|---|
| 模板表 | infra_print_template 已存在,无需新建(含 paper/mode/content/copies/is_default/status 等字段,逻辑删 + 租户隔离) |
| 单据类型登记 | BD 基础数据 bd_bill_type + bd_bill_type_group(分组),幂等 SQL 参考 sql/fin/fin_p14_g3_g10.sql 的写法 |
| 预置模板 | 建表/初始化 SQL 参考 pointlion-module-infra/sql/print_templates_init.sql(simple 模式 JSON,幂等插入) |
| 权限 | 复用打印中心既有菜单与 infra:print-template:* 按钮,无需新增 |
8.6 前端接入(一行调用)
ts
import { openPrint } from '@/utils/print'
const handlePrint = (id: number) => {
openPrint({ billType: 'your_bill_type', billId: id })
}openPrint 内部自动处理:拉模板列表 → 无模板走兜底 / 单模板直开 / 多模板弹选择 → 新窗口 /print/preview?billType=&billId=。
8.7 联调自检清单
- 启动日志出现你的 billType(注册成功);
GET /admin-api/infra/print/variables?billType=xxx返回变量三组;GET /admin-api/infra/print/sample-data?billType=xxx返回一张真实单据(sampleBillId 生效);- 模板管理页能新建该类型模板,设计器预览有数据;
- 业务页打印按钮 → 预览 → 变量全部替换、明细行数正确;
- 检查 load() 返回值无 ID/编码裸值(应全部为展示值)。
