53 lines
3.5 KiB
Markdown
53 lines
3.5 KiB
Markdown
# dealerhub · 打印功能实施报告(P3 #17 打印模板引擎,提前落地)
|
||
|
||
> **需求来源**:用户提出"需要打印的功能"。对应《差距分析与改造清单》P3 第 17 项(打印模板引擎),
|
||
> 竞品对标:智慧记"多种单据都能打"(小票/A4/三联/标签)、管家婆打印模板。
|
||
> **结果**:后端打印中心 + 前端打印按钮全部落地,新增 16 个测试,全量回归 **157 passed**;
|
||
> 顺带修复一个**全项目潜在 bug**(detail 路由 404,见下文)。
|
||
|
||
## ✅ 功能清单
|
||
|
||
1. **打印模板引擎(注入安全)**
|
||
- 自研占位符语法:`{{path.to.value}}` 点路径取值 + `{{#each lines}}…{{/each}}` 行循环
|
||
- 所有取值经 html.escape——商品名含 `<script>`/`<img onerror>` 均被转义(有专项测试)
|
||
- Django/Jinja 模板标签原样输出不执行——租户编辑模板无法注入逻辑(防模板注入)
|
||
2. **两种单据默认模板**(A4 版式、含抬头/明细表/抹零/签收栏/页脚)
|
||
- 销售单 `sales_bill`(XS 单号、客户、仓库、合计行数数量、应收合计)
|
||
- 进货单 `purchase_bill`(供应商视角)
|
||
- 首次渲染自动落库为租户模板(`is_default=True`),可在管理界面改
|
||
3. **打印抬头设置**(租户单例):公司名/电话/地址/开户行/页脚备注,渲染时自动注入 `{{company.*}}`
|
||
4. **API**
|
||
- `GET /api/v1/printing/render/<doc_type>/<id>/?template=code&autoprint=0|1` → 整页 HTML(带自动打印脚本,可关)
|
||
- `GET|POST|PATCH /api/v1/printing/templates/`(模板 CRUD)
|
||
- `GET|PUT|PATCH /api/v1/printing/settings/default/`(抬头单例)
|
||
5. **前端**:销售单/采购单列表加"打印"按钮(仅已过账单可用)——axios 取回 HTML → 新窗口写入 → 浏览器打印对话框自动弹出;`npm run build` 通过
|
||
6. **样张**:`docs/print_sample.html`(含中文抬头、明细、抹零 0.5 元、签收栏的完整样例,浏览器打开即可打印预览)
|
||
|
||
## 🐛 顺带修复:全项目 detail 路由 404(潜在 bug)
|
||
|
||
打印模板的 PUT/PATCH 测试暴露:`BaseTenantViewSet.get_queryset` 是 `async def`,
|
||
而 adrf 的 `aget_object()` **同步**调用它拿到 coroutine,在 `aget_object_or_404` 里抛
|
||
`ValueError` 被吞成 Http404——**全项目所有 detail 路由(retrieve/PUT/PATCH/DELETE)一直都会 404**。
|
||
此前未暴露是因为旧测试只覆盖 list 接口。
|
||
**修复**:`apps/core/viewset.py` 增加覆盖版 `aget_object`(先 await get_queryset 再过滤/查对象/校验权限),
|
||
对全部业务 ViewSet 生效。
|
||
|
||
## 📁 变更文件
|
||
|
||
```
|
||
backend/apps/printing/ [新] models / renderer / services / views / serializers / urls / migrations
|
||
backend/config/settings/base.py 注册 apps.printing
|
||
backend/apps/core/urls.py 挂载 printing 路由
|
||
backend/apps/core/viewset.py [修] aget_object 支持 async get_queryset(全局 detail 路由修复)
|
||
backend/tests/test_printing.py [新] 16 例(渲染器安全/语法、上下文、API、租户隔离、转义)
|
||
frontend/src/pages/SalesBills.vue · PurchaseBills.vue [新] 打印按钮
|
||
frontend/dist/ [重建]
|
||
docs/print_sample.html [新] 打印样张
|
||
```
|
||
|
||
## 🔜 打印后续可扩展(未做)
|
||
|
||
- 三联送货单/小票(58mm)版式模板、`{{#if}}` 条件块、批次号列(批次商品)
|
||
- 二维码(对账单分享链接直接印在单据上,客户扫码对账)
|
||
- PDA/标签打印(蓝牙热敏)
|