22 KiB
name, overview, todos, isProject
| name | overview | todos | isProject | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Universal Document Print | 设计并实现跨项目的通用单据打印框架,覆盖 erp-frontend-vue (Vue 3) 和 mom-backend-ui (Vue 2) 两个前端项目中所有单据类型的打印需求,采用配置驱动方式,一套设计思路适配全部单据。 |
|
false |
通用单据打印框架(跨项目)
现状分析
erp-frontend-vue(Vue 3 + Element Plus)
handlePrint()要么仅调window.print()(生产工单、采购订单),要么是占位符(销售订单等)- 无
@media print样式、无 QR 码库、无打印组件 - 包含单据:销售订单、采购订单、生产工单、生产领料单、采购到货单(表单未完成)
mom-backend-ui(Vue 2 + Element UI)
- 已有
vue-plugin-hiprint用于条码标签打印(物料/仓库/工位标签),但无单据格式打印 handleHiPrint仅在 detail 页做标签打印,不是单据表单打印- 包含大量仓库单据模块:到货通知、入库单(4种)、领料单(3种)、出库单(2种)、退货单(3种)、转移单、装箱单、备料通知等
两项目共同点
所有单据结构高度一致:表头字段 + 明细行列表,适合用统一的配置驱动方案。
架构设计
核心思路:配置驱动 + 双项目适配
graph TB
subgraph config ["PrintConfig 配置接口(结构一致)"]
fields["headerFields: 表头字段数组"]
cols["columns: 明细列定义"]
data["data: 明细行数据"]
meta["title / qrCode / footer"]
end
subgraph vue3 ["erp-frontend-vue (Vue 3)"]
pd3["PrintDialog.vue"]
qr3["QrCode.vue"]
pages3["各单据 form.vue"]
end
subgraph vue2 ["mom-backend-ui (Vue 2)"]
pd2["PrintDialog.vue"]
qr2["QrCode.vue"]
pages2["各单据 index.vue"]
end
pages3 -->|"构建 config"| pd3
pages2 -->|"构建 config"| pd2
pd3 --> qr3
pd2 --> qr2
config -.->|"同一结构"| pd3
config -.->|"同一结构"| pd2
PrintConfig 接口定义
两个项目各自维护一份(Vue 3 用 TypeScript,Vue 2 用 JSDoc),结构完全一致:
/** 表头字段 */
interface PrintHeaderField {
label: string // "单据编码"
value: string | number // "SCDD000001"
span?: number // 占列数,默认 1(共 4 列一行)
}
/** 明细表列 */
interface PrintColumn {
prop: string // 数据字段名
label: string // 列标题
width?: string // 列宽
align?: 'left' | 'center' | 'right'
type?: 'text' | 'index' | 'qrcode' | 'amount'
qrCodeProp?: string // type=qrcode 时的编码内容字段
formatter?: (row: any, index: number) => string
}
/** 合计行 */
interface PrintSummary {
label: string
value: string | number
}
/** 完整打印配置 */
interface PrintConfig {
systemName?: string // 默认 "升阳云ERP"
title: string // "销售订单" | "到货通知单" | ...
subtitle?: string // "加工车间" 等
qrCodeValue?: string // 右上角二维码内容
headerFields: PrintHeaderField[] // 4 列网格,自动换行
columns: PrintColumn[] // 明细表列
data: any[] // 明细表数据
summaries?: PrintSummary[] // 合计行(可选)
footer: {
creator?: string // 制单人
approver?: string // 审核人
}
}
打印页面统一布局
+------------------------------------------------------------------+
| 升阳云ERP [QR 码] |
| {title} - {subtitle} |
| |
| {label}: {value} {label}: {value} {label}: {value} {label}:|
| {label}: {value} {label}: {value} {label}: {value} {label}:|
| |
| +----+----------+----------+------+------+----------+------+ |
| | 序号| 列1 | 列2 | 列3 | 列4 | 列5 | 列6 | |
| +----+----------+----------+------+------+----------+------+ |
| | 1 | ... | ... | ... | ... | [QR码] | ... | |
| +----+----------+----------+------+------+----------+------+ |
| |
| 制单人: xxx 审核人: xxx 打印日期: 2025-xx-xx |
+------------------------------------------------------------------+
实现步骤
第一步:依赖安装
erp-frontend-vue:
cd erp-frontend-vue && npm install qrcode && npm install -D @types/qrcode
mom-backend-ui:
cd mom-backend-ui && npm install qrcode
第二步:公共组件开发
Vue 3 版(erp-frontend-vue)
新建目录 src/components/print/,包含 3 个文件:
| 文件 | 说明 |
|---|---|
| src/components/print/types.ts | PrintConfig 等类型定义 |
| src/components/print/QrCode.vue | QR 码组件(Props: value, size) |
| src/components/print/PrintDialog.vue | 通用打印对话框 |
QrCode.vue — 使用 qrcode.toDataURL() 生成 base64 图片,渲染 <img> 标签。
PrintDialog.vue — 核心组件:
- Props:
v-model:visible、config: PrintConfig el-dialog(fullscreen)包裹打印预览- 对话框 header 有「打印」「关闭」按钮
- 打印内容区使用纯 HTML table + CSS Grid(不依赖 Element Plus),确保打印输出干净
- 组件内嵌
@media print样式,隐藏对话框 header/footer,仅保留.print-content
Vue 2 版(mom-backend-ui)
新建目录 src/components/PrintDoc/,包含 2 个文件:
| 文件 | 说明 |
|---|---|
| src/components/PrintDoc/QrCode.vue | QR 码组件(Vue 2 语法) |
| src/components/PrintDoc/PrintDialog.vue | 通用打印对话框(Vue 2 + Element UI el-dialog) |
两个版本的布局 HTML 和 CSS 完全一致,仅框架语法不同:
- Vue 3:
<script setup>+defineProps+v-model:visible - Vue 2:
export default+props+.sync修饰符
第三步:打印专用 CSS(两项目通用)
嵌入在 PrintDialog 组件内(或独立 CSS 文件),核心规则:
@media print {
body > *:not(.el-overlay):not(.v-modal) { display: none !important; }
.el-overlay, .v-modal { position: static !important; overflow: visible !important; }
.el-dialog__wrapper { position: static !important; overflow: visible !important; }
.el-dialog { box-shadow: none !important; border: none !important;
margin: 0 !important; width: 100% !important; }
.el-dialog__header, .el-dialog__footer,
.print-dialog-actions { display: none !important; }
.print-content { padding: 8mm 10mm; margin: 0; }
.print-content table { page-break-inside: auto; }
.print-content tr { page-break-inside: avoid; }
}
第四步:各单据集成
每个单据页面的 handlePrint() 只需:
- 构建
PrintConfig对象(映射该单据的字段) - 设置
showPrintDialog = true
全部单据配置清单
A. erp-frontend-vue 项目(Vue 3)
A1. 生产工单
页面: src/views/Production/WorkOrder/form.vue
需新增 API: getTaskListByWorkorder(workorderId) -> GET /mes/pro/protask/list (添加到 src/api/workOrder.ts)
表头字段(headerFields):
- 单据编码
workorderCode/ 跟单号salesOrderCode/ 物料编码productCode/ 工艺路线routeName - 单据日期
orderDate/ 操作员operatorName/ 物料名称productName + productSpc/ 生产线productionLine - 单据状态
status/ 订单交期deliveryDate/ 计量单位unitName/ 生产日期productionDate - 业务状态
businessStatus/ 需求日期requestDate/ 生产数量quantity/ 备注remark
明细列(工序,来自 ProTask):
- 序号(index) / 工序编码
processCode/ 工序名称processName/ 应报数量quantity/ 计件方式(固定"个人") / 扫码报工(qrcode) / 备注
页脚: 制单人 createBy / 审核人 approverName
A2. 销售订单
页面: src/views/Sales/Order/form.vue
表头字段:
- 单据编码
orderCode/ 单据日期orderDate/ 单据状态orderStatus/ 业务类型bizType - 客户名称
clientName/ 销售人员salesmanName/ 销售部门deptName/ 合同号contractNo - 交付日期
deliveryDate/ 付款条件paymentTerms/ 收货人receiver/ 收货电话receiverPhone - 收货地址
receiverAddress(span:2) / 备注remark(span:2)
明细列(物料行,来自 lines):
- 序号 / 物料编码
itemCode/ 物料名称itemName/ 型号规格specification/ 主计量unitOfMeasure/ 数量quantity/ 单价unitPrice/ 金额amount/ 质量要求qualityReq/ 备注remark
合计: 总金额 totalAmount
页脚: 制单人 createBy / 审核人 auditorName
A3. 采购订单
页面: src/views/Purchasing/Order/form.vue
表头字段:
- 单据编码
orderCode/ 单据日期orderDate/ 单据状态status/ 业务类型businessType - 业务状态
businessStatus/ 供方supplierName/ 采购部门deptName/ 采购人员userName - 到货日期
deliveryDate/ 合同号contractNo/ 用料需求materialNeed/ 备注remark
明细列(采购行,来自 lines):
- 序号 / 跟单编号
trackCode/ 计划单号planCode/ 物料编码itemCode/ 物料名称itemName/ 型号规格specification/ 主计量unitName/ 数量quantity/ 单价unitPrice/ 金额amount/ 采购说明remark
合计: 总数量 totalQuantity / 总金额 totalAmount
页脚: 制单人 operatorName / 审核人 approverName
A4. 生产领料单
页面: src/views/Warehouse/Issue/form.vue(需新增打印按钮)
表头字段:
- 单据编码
issueCode/ 领料日期issueDate/ 单据状态status/ 工单编码workorderCode - 工作站
workstationName/ 客户名称clientName/ 需求时间requiredTime/ 备注remark
明细列(领料行):
- 序号 / 物料编码
itemCode/ 物料名称itemName/ 规格型号specification/ 计量单位unitName/ 领料数量quantityIssued/ 批次号batchCode/ 备注remark
页脚: 制单人 createBy
B. mom-backend-ui 项目(Vue 2)
以下单据在老项目中,均无单据打印功能(仅部分有标签打印)。统一使用 PrintDialog 组件集成。
B1. 到货通知单
页面: src/views/mes/wm/arrivalnotice/index.vue + line.vue
表头字段:
- 通知单编号
noticeCode/ 通知单名称noticeName/ 采购订单号poCode/ 到货日期arrivalDate - 供应商
vendorName/ 联系人contact/ 联系方式tel/ 单据状态status - 备注
remark(span:3)
明细列(到货行):
- 序号 / 物料编码
itemCode/ 物料名称itemName/ 规格型号specification/ 单位unitName/ 到货数量quantityArrival/ 是否检验iqcCheck/ 合格数量quantityQuanlified/ 检验单号iqcCode/ 备注remark
页脚: 制单人 createBy
B2. 物料入库单(采购入库)
页面: src/views/mes/wm/itemrecpt/index.vue + line.vue
表头字段:
- 入库单编号
recptCode/ 入库单名称recptName/ 入库日期recptDate/ 单据状态status - 到货通知单
noticeCode/ 采购订单号poCode/ 供应商vendorName/ 备注remark
明细列(入库行):
- 序号 / 物料编码
itemCode/ 物料名称itemName/ 规格型号specification/ 单位unitName/ 入库数量quantityRecived/ 批次号batchCode
页脚: 制单人 createBy
B3. 产品入库单
页面: src/views/mes/wm/productrecpt/
表头字段: 入库单编号、名称、工单编码、入库日期、状态、备注 明细列: 产品编码、产品名称、规格、单位、入库数量、批次号
B4. 外协入库单
页面: src/views/mes/wm/outsourcerecpt/
表头: 入库单编号、名称、外协工单号、入库日期、状态、备注 明细: 物料编码、物料名称、规格、单位、入库数量、批次号
B5. 销售出库单
页面: src/views/mes/wm/productsales/index.vue + line.vue
表头字段:
- 出库单编号
salesCode/ 出库单名称salesName/ 发货通知单noticeCode/ 销售订单soCode - 客户编码
clientCode/ 客户名称clientName/ 出库日期salesDate/ 单据状态status - 收货人
recipient/ 联系方式tel/ 承运商carrier/ 运输单号shippingNumber - 收货地址
address(span:2) / 备注remark(span:2)
明细列(出库行):
- 序号 / 产品编码
itemCode/ 产品名称itemName/ 规格型号specification/ 单位unitName/ 出库数量quantitySales/ 批次号batchCode/ 是否检验oqcCheck/ 备注remark
页脚: 制单人 createBy
B6. 发货通知单
页面: src/views/mes/wm/salesnotice/
表头: 通知单编号、销售订单号、客户名称、发货日期、收货人、联系方式、地址、承运商、状态 明细: 产品编码、产品名称、规格、单位、发货数量、批次号
B7. 供应商退货单
页面: src/views/mes/wm/rtvendor/index.vue + line.vue
表头字段:
- 退货单编号
rtCode/ 退货单名称rtName/ 采购订单poCode/ 退货日期rtDate - 供应商
vendorName/ 退货原因rtReason/ 运单号transportCode/ 单据状态status - 备注
remark(span:3)
明细列:
- 序号 / 物料编码
itemCode/ 物料名称itemName/ 规格型号specification/ 单位unitName/ 退货数量quantityRted/ 批次号batchCode/ 备注remark
B8. 销售退货单
表头: 退货单编号、销售订单号、客户名称、退货日期、状态 明细: 产品编码、产品名称、规格、单位、退货数量、批次号
B9. 生产退料单
表头: 退料单编号、工单编码、退料日期、状态 明细: 物料编码、物料名称、规格、单位、退料数量、批次号
B10. 生产领料单
页面: src/views/mes/wm/issue/index.vue + line.vue
表头: 领料单编号、领料单名称、工单编码、工作站、领料日期、状态 明细: 物料编码、物料名称、规格、单位、领料数量、备注
B11. 外协领料单
页面: src/views/mes/wm/outsourceissue/
表头: 领料单编号、外协工单号、领料日期、状态 明细: 物料编码、物料名称、规格、单位、领料数量
B12. 转移单
页面: src/views/mes/wm/transfer/index.vue
表头字段:
- 转移单编号
transferCode/ 转移单名称transferName/ 转移类型transferType/ 转移日期transferDate - 是否配送
deliveryFlag/ 收货人recipient/ 联系方式tel/ 单据状态status - 承运商
carrier/ 运输单号shippingNumber/ 目的地destination/ 备注remark
明细: 物料编码、物料名称、规格、单位、转移数量、批次号
B13. 杂项入库单 / 杂项出库单 / 备料通知单 / 装箱单
页面: 分别位于 mes/wm/miscrecpt/、mes/wm/miscissue/、mes/wm/mrnotice/、mes/wm/package/
结构与上述单据一致,表头字段略有不同,明细均为物料行。集成方式相同:构建 PrintConfig 即可。
实施优先级
Phase 1 — 公共组件 + 核心单据(优先)
- 安装依赖(两个项目)
- 创建公共打印组件(Vue 3 版 + Vue 2 版)
- erp-frontend-vue: 生产工单、销售订单、采购订单集成打印
- mom-backend-ui: 到货通知单、物料入库单集成打印
Phase 2 — 仓库出入库单据
- erp-frontend-vue: 生产领料单集成打印
- mom-backend-ui: 销售出库单、发货通知单、生产领料单集成打印
Phase 3 — 退货/转移/其余单据
- mom-backend-ui: 供应商退货单、销售退货单、生产退料单
- mom-backend-ui: 转移单、外协入库/领料、杂项入库/出库、备料通知、装箱单
文件变更总览
erp-frontend-vue(新增 3 文件 + 修改 5 文件)
新增:
src/components/print/types.ts— PrintConfig 类型定义src/components/print/QrCode.vue— QR 码组件src/components/print/PrintDialog.vue— 通用打印对话框
修改:
src/api/workOrder.ts— 添加 ProTask 类型和 APIsrc/views/Production/WorkOrder/form.vue— 集成打印src/views/Sales/Order/form.vue— 集成打印src/views/Purchasing/Order/form.vue— 集成打印src/views/Warehouse/Issue/form.vue— 添加打印按钮 + 集成打印
mom-backend-ui(新增 2 文件 + 修改 N 个单据页面)
新增:
src/components/PrintDoc/QrCode.vue— QR 码组件(Vue 2)src/components/PrintDoc/PrintDialog.vue— 通用打印对话框(Vue 2)
修改(Phase 1-3 逐步):
src/views/mes/wm/arrivalnotice/index.vue— 到货通知单src/views/mes/wm/itemrecpt/index.vue— 物料入库单src/views/mes/wm/productsales/index.vue— 销售出库单src/views/mes/wm/salesnotice/index.vue— 发货通知单src/views/mes/wm/issue/index.vue— 生产领料单src/views/mes/wm/rtvendor/index.vue— 供应商退货单src/views/mes/wm/rtsales/index.vue— 销售退货单src/views/mes/wm/rtissue/index.vue— 生产退料单src/views/mes/wm/transfer/index.vue— 转移单- 其余仓库单据页面...
安装依赖:
- erp-frontend-vue:
qrcode+@types/qrcode - mom-backend-ui:
qrcode
扩展性说明
新增任何单据的打印,不论在哪个项目中,只需:
- 在该单据页面中引入
PrintDialog组件 - 构建
PrintConfig对象(映射表头字段 + 配置明细列 + 提供行数据) - 设置
showPrintDialog = true
无需修改任何公共打印组件。