--- 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.vue(Vue 2 版)" status: pending - id: print-dialog-vue2 content: "mom-backend-ui: 创建 src/components/PrintDoc/PrintDialog.vue(Vue 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-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种)、转移单、装箱单、备料通知等 ### 两项目共同点 所有单据结构高度一致:**表头字段** + **明细行列表**,适合用统一的配置驱动方案。 ## 架构设计 ### 核心思路:配置驱动 + 双项目适配 ```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 用 TypeScript,Vue 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 图片,渲染 `` 标签。 **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: `