2026-04-29 a0e785cd62ad6cdd8c0c834401bf224c1b63dc8a
Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_NEW_pro
已添加1个文件
已修改1个文件
280 ■■■■■ 文件已修改
src/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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å¹´MM月DD日") : "-";
  };
</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>
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("正在获取领料数据...");
    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;