From a0e785cd62ad6cdd8c0c834401bf224c1b63dc8a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 29 四月 2026 10:56:32 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_NEW_pro
---
src/views/productionManagement/productionOrder/index.vue | 55 +++++++++++
src/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue | 225 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 280 insertions(+), 0 deletions(-)
diff --git a/src/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue b/src/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue
new file mode 100644
index 0000000..d1aa267
--- /dev/null
+++ b/src/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue
@@ -0,0 +1,225 @@
+<template>
+ <div class="print-container"
+ id="print-requisition">
+ <div class="print-content">
+ <div class="bill-title">鐢熶骇棰嗘枡鍗�</div>
+ <div class="info-grid">
+ <div class="info-row">
+ <div class="info-item">
+ <span class="label">鍒涘缓鏃ユ湡锛�</span>
+ <span class="value">{{ formatDate(orderRow?.createTime) }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">棰嗘枡鍗曞彿锛�</span>
+ <span class="value">{{ orderRow?.npsNo }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">鐢宠浜猴細</span>
+ <span class="value">{{ userName }}</span>
+ </div>
+ </div>
+ <div class="info-row">
+ <div class="info-item"
+ style="width: 50%;">
+ <span class="label">浜у搧鍚嶇О/鍨嬪彿锛�</span>
+ <span class="value">{{ orderRow?.productName }} / {{ orderRow?.model }}</span>
+ </div>
+ <div class="info-item"
+ style="width: 25%;">
+ <span class="label">鐢熶骇鏁伴噺锛�</span>
+ <span class="value">{{ orderRow?.quantity }}</span>
+ </div>
+ <div class="info-item"
+ style="width: 25%;">
+ <span class="label">闇�姹傛棩鏈燂細</span>
+ <span class="value">{{ formatDate(orderRow?.planCompleteTime) }}</span>
+ </div>
+ </div>
+ </div>
+ <table class="material-table">
+ <thead>
+ <tr>
+ <th width="50">搴忓彿</th>
+ <th>宸ュ簭鍚嶇О</th>
+ <th>瑙勬牸/鍚嶇О</th>
+ <th>鎵瑰彿</th>
+ <th width="80">闇�姹傛暟閲�</th>
+ <th width="80">棰嗘枡鏁伴噺</th>
+ <th width="60">鍗曚綅</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="(item, index) in materialList"
+ :key="index">
+ <td align="center">{{ index + 1 }}</td>
+ <td>{{ item.operationName || '-' }}</td>
+ <td>{{ item.materialName || item.productName }} {{ item.materialModel || item.model }}</td>
+ <td>{{ item.batchNo || '-' }}</td>
+ <td align="right">{{ item.demandedQuantity }}</td>
+ <td align="right">{{ item.pickQuantity || item.pickQty || 0 }}</td>
+ <td align="center">{{ item.unit }}</td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="print-footer">
+ <div class="footer-item">棰嗘枡锛歘_______________</div>
+ <div class="footer-item">鍙戞枡锛歘_______________</div>
+ <div class="footer-item">瀹℃牳锛歘_______________</div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script setup>
+ import dayjs from "dayjs";
+ import useUserStore from "@/store/modules/user";
+ import { computed } from "vue";
+
+ const props = defineProps({
+ orderRow: {
+ type: Object,
+ default: () => ({}),
+ },
+ materialList: {
+ type: Array,
+ default: () => [],
+ },
+ });
+
+ const userStore = useUserStore();
+ const userName = computed(() => userStore.nickName || userStore.name || "-");
+
+ const formatDate = date => {
+ return date ? dayjs(date).format("YYYY骞碝M鏈圖D鏃�") : "-";
+ };
+</script>
+
+<style lang="scss">
+ /* 灞忓箷鏄剧ず鏍峰紡 */
+ .print-requisition-wrapper {
+ display: none;
+ }
+
+ /* 鎵撳嵃涓撶敤鏍峰紡 */
+ @media print {
+ @page {
+ size: landscape;
+ margin: 10mm;
+ }
+
+ /* 鍩虹鎵撳嵃璁剧疆 */
+ html,
+ body {
+ visibility: hidden;
+ height: auto !important;
+ overflow: visible !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ width: 100%;
+ }
+
+ /* 鏄惧紡鏄剧ず鎵撳嵃瀹瑰櫒鍙婂叾鎵�鏈夊瓙鍏冪礌 */
+ .print-requisition-wrapper,
+ .print-requisition-wrapper * {
+ visibility: visible !important;
+ }
+
+ /* 纭繚鎵撳嵃瀹瑰櫒鍗犳嵁鏁翠釜椤甸潰骞剁Щ闄ょ粷瀵瑰畾浣嶅共鎵� */
+ .print-requisition-wrapper {
+ display: block !important;
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: auto;
+ background: white;
+ margin: 0 !important;
+ padding: 0 !important;
+ z-index: 99999;
+ }
+
+ .print-container {
+ width: 100% !important;
+ padding: 0 10mm; /* 浣跨敤瀵圭О鐨勫乏鍙冲唴杈硅窛纭繚灞呬腑 */
+ box-sizing: border-box;
+ height: auto;
+ overflow: visible;
+ color: #000;
+ font-family: "SimSun", "STSong", serif;
+ page-break-inside: avoid;
+ display: block;
+ .print-content {
+ width: 100%;
+ text-align: center;
+ }
+ .bill-title {
+ font-size: 20px;
+ font-weight: bold;
+ text-align: center;
+ margin-bottom: 20px;
+ letter-spacing: 5px;
+ text-decoration: underline;
+ }
+
+ .info-grid {
+ margin-bottom: 10px;
+ font-size: 14px;
+
+ .info-row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-bottom: 8px;
+
+ .info-item {
+ width: 33.33%;
+ display: flex;
+ align-items: flex-end;
+
+ .label {
+ font-weight: bold;
+ white-space: nowrap;
+ }
+ .value {
+ border-bottom: 1px solid #000;
+ padding: 0 5px;
+ flex: 1;
+ min-height: 20px;
+ }
+ }
+ }
+ }
+
+ .material-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 2px solid #000;
+ font-size: 13px;
+
+ th,
+ td {
+ border: 1px solid #000 !important;
+ padding: 6px 4px;
+ height: 25px;
+ -webkit-print-color-adjust: exact;
+ print-color-adjust: exact;
+ }
+
+ th {
+ background-color: #f2f2f2 !important;
+ font-weight: bold;
+ }
+ }
+
+ .print-footer {
+ display: flex;
+ justify-content: space-between;
+ margin-top: 30px;
+ padding: 0 10px;
+
+ .footer-item {
+ font-size: 14px;
+ }
+ }
+ }
+ }
+</style>
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 5f4fa61..28356dd 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -181,6 +181,12 @@
<new-product-order v-if="isShowNewModal"
v-model:visible="isShowNewModal"
@completed="handleQuery" />
+ <!-- 鎵撳嵃棰嗘枡鍗曠粍浠� -->
+ <div class="print-requisition-wrapper">
+ <PrintMaterialRequisition ref="printRef"
+ :order-row="printOrderRow"
+ :material-list="printMaterialList" />
+ </div>
</div>
</template>
@@ -209,8 +215,13 @@
import MaterialLedgerDialog from "@/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue";
import MaterialDetailDialog from "@/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue";
import MaterialSupplementDialog from "@/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue";
+ import PrintMaterialRequisition from "@/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { listPage } from "@/api/productionManagement/processRoute.js";
+ import {
+ listMaterialPickingDetail,
+ listMaterialPickingBom,
+ } from "@/api/productionManagement/productionOrder.js";
const NewProductOrder = defineAsyncComponent(() =>
import("@/views/productionManagement/productionOrder/New.vue")
);
@@ -365,6 +376,14 @@
openMaterialDetailDialog(row);
},
},
+ {
+ name: "鎵撳嵃棰嗘枡鍗�",
+ type: "text",
+ color: "#409eff",
+ clickFun: row => {
+ handlePrint(row);
+ },
+ },
],
},
]);
@@ -440,6 +459,42 @@
const materialSupplementDialogVisible = ref(false);
const currentMaterialSupplementOrder = ref(null);
+ // 鎵撳嵃鐩稿叧
+ const printOrderRow = ref(null);
+ const printMaterialList = ref([]);
+ const handlePrint = async row => {
+ printOrderRow.value = row;
+ proxy.$modal.loading("姝e湪鑾峰彇棰嗘枡鏁版嵁...");
+ try {
+ printMaterialList.value = [];
+ const detailRes = await listMaterialPickingDetail(row.id);
+ const detailList = Array.isArray(detailRes?.data)
+ ? detailRes.data
+ : detailRes?.data?.records || [];
+
+ if (detailList.length > 0) {
+ printMaterialList.value = detailList;
+ }
+
+ if (printMaterialList.value.length === 0) {
+ proxy.$modal.msgWarning("鏆傛棤棰嗘枡鏁版嵁");
+ return;
+ }
+
+ // 绛夊緟 DOM 鏇存柊鍚庢墽琛屾墦鍗�
+ proxy.$nextTick(() => {
+ setTimeout(() => {
+ window.print();
+ }, 800);
+ });
+ } catch (e) {
+ console.error("鑾峰彇棰嗘枡鏁版嵁澶辫触锛�", e);
+ proxy.$modal.msgError("鑾峰彇棰嗘枡鏁版嵁澶辫触");
+ } finally {
+ proxy.$modal.closeLoading();
+ }
+ };
+
const openBindRouteDialog = async (row, type) => {
bindForm.orderId = row.id;
bindForm.routeId = type === "add" ? null : row.processRouteCode;
--
Gitblit v1.9.3