Skip to content

八、二次开发接入 ​

本章面向开发人员:如何让一个新的业务单据接入打印中心(获得模板管理 + 打印按钮能力)。

8.1 接入总览 ​

只需三步:

  1. 业务模块实现 PrintDataProvider 接口并注册为 Spring Bean;
  2. (可选)在 BD 基础数据登记单据类型,让模板管理页的树里出现分组;
  3. 前端业务列表页加【打印】按钮调 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 联调自检清单 ​

  1. 启动日志出现你的 billType(注册成功);
  2. GET /admin-api/infra/print/variables?billType=xxx 返回变量三组;
  3. GET /admin-api/infra/print/sample-data?billType=xxx 返回一张真实单据(sampleBillId 生效);
  4. 模板管理页能新建该类型模板,设计器预览有数据;
  5. 业务页打印按钮 → 预览 → 变量全部替换、明细行数正确;
  6. 检查 load() 返回值无 ID/编码裸值(应全部为展示值)。