Files
my-mom-system/.cursor/plans/workorder_print_template_6cc2bcf4.plan.md

572 lines
22 KiB
Markdown
Raw Permalink Normal View History

2026-03-06 02:02:59 +08:00
---
name: Universal Document Print
overview: 设计并实现跨项目的通用单据打印框架,覆盖 erp-frontend-vue (Vue 3) 和 mom-backend-ui (Vue 2) 两个前端项目中所有单据类型的打印需求,采用配置驱动方式,一套设计思路适配全部单据。
todos:
- id: install-deps-vue3
content: "erp-frontend-vue: 安装 qrcode + @types/qrcode"
status: completed
- id: install-deps-vue2
content: "mom-backend-ui: 安装 qrcode已有 vue-plugin-hiprint 用于标签,文档打印需另行处理)"
status: pending
- id: print-types
content: 创建 PrintConfig 类型/接口定义(两项目各一份,结构一致)
status: completed
- id: qrcode-vue3
content: "erp-frontend-vue: 创建 src/components/print/QrCode.vue"
status: completed
- id: print-dialog-vue3
content: "erp-frontend-vue: 创建 src/components/print/PrintDialog.vue@media print 样式)"
status: completed
- id: qrcode-vue2
content: "mom-backend-ui: 创建 src/components/PrintDoc/QrCode.vueVue 2 版)"
status: pending
- id: print-dialog-vue2
content: "mom-backend-ui: 创建 src/components/PrintDoc/PrintDialog.vueVue 2 版,含 @media print 样式)"
status: pending
- id: task-api
content: "erp-frontend-vue: 在 workOrder.ts 中添加 ProTask 类型和 getTaskListByWorkorder API"
status: completed
- id: integrate-workorder-vue3
content: "erp-frontend-vue: 生产工单 form.vue 集成打印"
status: completed
- id: integrate-sales-vue3
content: "erp-frontend-vue: 销售订单 form.vue 集成打印"
status: completed
- id: integrate-purchase-vue3
content: "erp-frontend-vue: 采购订单 form.vue 集成打印"
status: completed
- id: integrate-issue-vue3
content: "erp-frontend-vue: 生产领料单 form.vue 集成打印"
status: completed
- id: integrate-arrival-vue2
content: "mom-backend-ui: 到货通知单 index.vue 集成打印"
status: pending
- id: integrate-itemrecpt-vue2
content: "mom-backend-ui: 物料入库单 index.vue 集成打印"
status: pending
- id: integrate-productsales-vue2
content: "mom-backend-ui: 销售出库单 index.vue 集成打印"
status: pending
- id: integrate-remaining-vue2
content: "mom-backend-ui: 其余仓库单据(退货/转移/杂项等)逐步集成打印"
status: pending
isProject: false
---
# 通用单据打印框架(跨项目)
## 现状分析
### erp-frontend-vueVue 3 + Element Plus
- `handlePrint()` 要么仅调 `window.print()`(生产工单、采购订单),要么是占位符(销售订单等)
-`@media print` 样式、无 QR 码库、无打印组件
- 包含单据:销售订单、采购订单、生产工单、生产领料单、采购到货单(表单未完成)
### mom-backend-uiVue 2 + Element UI
- 已有 `vue-plugin-hiprint` 用于**条码标签**打印(物料/仓库/工位标签),但**无单据格式打印**
- `handleHiPrint` 仅在 detail 页做标签打印,不是单据表单打印
- 包含大量仓库单据模块:到货通知、入库单(4种)、领料单(3种)、出库单(2种)、退货单(3种)、转移单、装箱单、备料通知等
### 两项目共同点
所有单据结构高度一致:**表头字段** + **明细行列表**,适合用统一的配置驱动方案。
## 架构设计
### 核心思路:配置驱动 + 双项目适配
```mermaid
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 用 TypeScriptVue 2 用 JSDoc结构完全一致
```typescript
/** 表头字段 */
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:**
```bash
cd erp-frontend-vue && npm install qrcode && npm install -D @types/qrcode
```
**mom-backend-ui:**
```bash
cd mom-backend-ui && npm install qrcode
```
### 第二步:公共组件开发
#### Vue 3 版erp-frontend-vue
新建目录 `src/components/print/`,包含 3 个文件:
| 文件 | 说明 |
| --------------------------------------------------------------------------------------------- | -------------------------- |
| [src/components/print/types.ts](erp-frontend-vue/src/components/print/types.ts) | PrintConfig 等类型定义 |
| [src/components/print/QrCode.vue](erp-frontend-vue/src/components/print/QrCode.vue) | QR 码组件Props: value, size |
| [src/components/print/PrintDialog.vue](erp-frontend-vue/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](mom-backend-ui/src/components/PrintDoc/QrCode.vue) | QR 码组件Vue 2 语法) |
| [src/components/PrintDoc/PrintDialog.vue](mom-backend-ui/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 文件),核心规则:
```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()` 只需:
1. 构建 `PrintConfig` 对象(映射该单据的字段)
2. 设置 `showPrintDialog = true`
---
## 全部单据配置清单
### A. erp-frontend-vue 项目Vue 3
#### A1. 生产工单
**页面**: [src/views/Production/WorkOrder/form.vue](erp-frontend-vue/src/views/Production/WorkOrder/form.vue)
**需新增 API**: `getTaskListByWorkorder(workorderId)` -> `GET /mes/pro/protask/list` (添加到 [src/api/workOrder.ts](erp-frontend-vue/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](erp-frontend-vue/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](erp-frontend-vue/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](erp-frontend-vue/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](mom-backend-ui/src/views/mes/wm/arrivalnotice/index.vue) + [line.vue](mom-backend-ui/src/views/mes/wm/arrivalnotice/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](mom-backend-ui/src/views/mes/wm/itemrecpt/index.vue) + [line.vue](mom-backend-ui/src/views/mes/wm/itemrecpt/line.vue)
**表头字段:**
- 入库单编号 `recptCode` / 入库单名称 `recptName` / 入库日期 `recptDate` / 单据状态 `status`
- 到货通知单 `noticeCode` / 采购订单号 `poCode` / 供应商 `vendorName` / 备注 `remark`
**明细列(入库行):**
- 序号 / 物料编码 `itemCode` / 物料名称 `itemName` / 规格型号 `specification` / 单位 `unitName` / 入库数量 `quantityRecived` / 批次号 `batchCode`
**页脚**: 制单人 `createBy`
---
#### B3. 产品入库单
**页面**: [src/views/mes/wm/productrecpt/](mom-backend-ui/src/views/mes/wm/productrecpt/)
**表头字段**: 入库单编号、名称、工单编码、入库日期、状态、备注
**明细列**: 产品编码、产品名称、规格、单位、入库数量、批次号
---
#### B4. 外协入库单
**页面**: [src/views/mes/wm/outsourcerecpt/](mom-backend-ui/src/views/mes/wm/outsourcerecpt/)
**表头**: 入库单编号、名称、外协工单号、入库日期、状态、备注
**明细**: 物料编码、物料名称、规格、单位、入库数量、批次号
---
#### B5. 销售出库单
**页面**: [src/views/mes/wm/productsales/index.vue](mom-backend-ui/src/views/mes/wm/productsales/index.vue) + [line.vue](mom-backend-ui/src/views/mes/wm/productsales/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/](mom-backend-ui/src/views/mes/wm/salesnotice/)
**表头**: 通知单编号、销售订单号、客户名称、发货日期、收货人、联系方式、地址、承运商、状态
**明细**: 产品编码、产品名称、规格、单位、发货数量、批次号
---
#### B7. 供应商退货单
**页面**: [src/views/mes/wm/rtvendor/index.vue](mom-backend-ui/src/views/mes/wm/rtvendor/index.vue) + [line.vue](mom-backend-ui/src/views/mes/wm/rtvendor/line.vue)
**表头字段:**
- 退货单编号 `rtCode` / 退货单名称 `rtName` / 采购订单 `poCode` / 退货日期 `rtDate`
- 供应商 `vendorName` / 退货原因 `rtReason` / 运单号 `transportCode` / 单据状态 `status`
- 备注 `remark`(span:3)
**明细列:**
- 序号 / 物料编码 `itemCode` / 物料名称 `itemName` / 规格型号 `specification` / 单位 `unitName` / 退货数量 `quantityRted` / 批次号 `batchCode` / 备注 `remark`
---
#### B8. 销售退货单
**页面**: [src/views/mes/wm/rtsales/](mom-backend-ui/src/views/mes/wm/rtsales/)
**表头**: 退货单编号、销售订单号、客户名称、退货日期、状态
**明细**: 产品编码、产品名称、规格、单位、退货数量、批次号
---
#### B9. 生产退料单
**页面**: [src/views/mes/wm/rtissue/](mom-backend-ui/src/views/mes/wm/rtissue/)
**表头**: 退料单编号、工单编码、退料日期、状态
**明细**: 物料编码、物料名称、规格、单位、退料数量、批次号
---
#### B10. 生产领料单
**页面**: [src/views/mes/wm/issue/index.vue](mom-backend-ui/src/views/mes/wm/issue/index.vue) + [line.vue](mom-backend-ui/src/views/mes/wm/issue/line.vue)
**表头**: 领料单编号、领料单名称、工单编码、工作站、领料日期、状态
**明细**: 物料编码、物料名称、规格、单位、领料数量、备注
---
#### B11. 外协领料单
**页面**: [src/views/mes/wm/outsourceissue/](mom-backend-ui/src/views/mes/wm/outsourceissue/)
**表头**: 领料单编号、外协工单号、领料日期、状态
**明细**: 物料编码、物料名称、规格、单位、领料数量
---
#### B12. 转移单
**页面**: [src/views/mes/wm/transfer/index.vue](mom-backend-ui/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 — 公共组件 + 核心单据(优先)
1. 安装依赖(两个项目)
2. 创建公共打印组件Vue 3 版 + Vue 2 版)
3. erp-frontend-vue: 生产工单、销售订单、采购订单集成打印
4. mom-backend-ui: 到货通知单、物料入库单集成打印
### Phase 2 — 仓库出入库单据
1. erp-frontend-vue: 生产领料单集成打印
2. mom-backend-ui: 销售出库单、发货通知单、生产领料单集成打印
### Phase 3 — 退货/转移/其余单据
1. mom-backend-ui: 供应商退货单、销售退货单、生产退料单
2. 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 类型和 API
- `src/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`
## 扩展性说明
新增任何单据的打印,不论在哪个项目中,只需:
1. 在该单据页面中引入 `PrintDialog` 组件
2. 构建 `PrintConfig` 对象(映射表头字段 + 配置明细列 + 提供行数据)
3. 设置 `showPrintDialog = true`
无需修改任何公共打印组件。