From c85acf29485748eb97fbca1ace79ee4d3635002d Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期六, 16 五月 2026 11:32:18 +0800
Subject: [PATCH] 阳光印刷 1.仓储物流分类修改

---
 src/views/inventoryManagement/dispatchLog/RawMaterial.vue       |  692 ++++++++++++++
 src/views/inventoryManagement/receiptManagement/index.vue       |   41 
 src/views/inventoryManagement/dispatchLog/Qualified.vue         |  692 ++++++++++++++
 src/views/inventoryManagement/receiptManagement/Unqualified.vue |  234 ++++
 src/views/inventoryManagement/dispatchLog/Unqualified.vue       |  692 ++++++++++++++
 src/views/inventoryManagement/receiptManagement/Qualified.vue   |  234 ++++
 src/views/inventoryManagement/receiptManagement/RawMaterial.vue |  234 ++++
 src/views/inventoryManagement/dispatchLog/index.vue             |   57 
 8 files changed, 2,839 insertions(+), 37 deletions(-)

diff --git a/src/views/inventoryManagement/dispatchLog/Qualified.vue b/src/views/inventoryManagement/dispatchLog/Qualified.vue
new file mode 100644
index 0000000..75f435e
--- /dev/null
+++ b/src/views/inventoryManagement/dispatchLog/Qualified.vue
@@ -0,0 +1,692 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title ml10">鍑哄簱鏃ユ湡锛�</span>
+        <el-date-picker
+          v-model="searchForm.timeStr"
+          type="date"
+          placeholder="璇烽�夋嫨鏃ユ湡"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          clearable
+          @change="handleQuery"
+        />
+        <span class="search_title ml10">鏉ユ簮锛�</span>
+        <el-select v-model="searchForm.recordType"
+                   style="width: 240px"
+                   placeholder="璇烽�夋嫨"
+                   clearable>
+          <el-option v-for="item in stockRecordTypeOptions"
+                     :key="item.value"
+                     :label="item.label"
+                     :value="item.value"/>
+        </el-select>
+        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+        >鎼滅储</el-button
+        >
+      </div>
+      <div>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+        <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
+      </div>
+    </div>
+    <div class="table_list">
+      <el-table
+        :data="tableData"
+        border
+        v-loading="tableLoading"
+        @selection-change="handleSelectionChange"
+        :expand-row-keys="expandedRowKeys"
+        :row-key="(row) => row.id"
+        style="width: 100%"
+        height="calc(100vh - 18.5em)"
+      >
+        <el-table-column align="center" type="selection" width="55" />
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column
+            label="鍑哄簱鎵规"
+            prop="outboundBatches"
+            min-width="100"
+            show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱鏃ユ湡"
+          prop="createTime"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="浜у搧澶х被"
+          prop="productName"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="瑙勬牸鍨嬪彿"
+          prop="model"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍗曚綅"
+          prop="unit"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱鏁伴噺"
+          prop="stockOutNum"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱浜�"
+          prop="createBy"
+          show-overflow-tooltip
+        />
+        <el-table-column label="鏉ユ簮"
+                         prop="recordType"
+                         show-overflow-tooltip>
+          <template #default="scope">
+            {{ getRecordType(scope.row.recordType) }}
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        layout="total, sizes, prev, pager, next, jumper"
+        :page="page.current"
+        :limit="page.size"
+        @pagination="paginationChange"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { ref, reactive, toRefs, getCurrentInstance } from "vue";
+import { ElMessageBox } from "element-plus";
+import useUserStore from "@/store/modules/user";
+import { getCurrentDate } from "@/utils/index.js";
+import {
+  getStockOutPage,
+  delStockOut,
+} from "@/api/inventoryManagement/stockOut.js";
+import {
+  findAllQualifiedStockOutRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+
+const userStore = useUserStore();
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([]);
+const page = reactive({
+  current: 1,
+  size: 100,
+});
+const total = ref(0);
+
+// 鎵撳嵃鐩稿叧
+const printPreviewVisible = ref(false);
+const printData = ref([]);
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const data = reactive({
+  searchForm: {
+    timeStr: "",
+    recordType: "",
+    rootName: "鎴愬搧"
+  }
+});
+const { searchForm } = toRefs(data);
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+const paginationChange = (obj) => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+const getList = () => {
+  tableLoading.value = true;
+  getStockOutPage({ ...searchForm.value, ...page })
+    .then((res) => {
+      tableLoading.value = false;
+      tableData.value = res.data.records;
+      tableData.value.map((item) => {
+        item.children = [];
+      });
+      total.value = res.data.total;
+    })
+    .catch(() => {
+      tableLoading.value = false;
+    });
+};
+
+const getRecordType = (recordType) => {
+  return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
+}
+
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+  findAllQualifiedStockOutRecordTypeOptions()
+    .then(res => {
+      stockRecordTypeOptions.value = res.data;
+    })
+}
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+  // 杩囨护鎺夊瓙鏁版嵁
+  selectedRows.value = selection.filter((item) => item.id);
+  console.log("selection", selectedRows.value);
+};
+const expandedRowKeys = ref([]);
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download("/stockOutRecord/exportStockOutRecord", {rootName: searchForm.value.rootName}, "鎴愬搧鍑哄簱鍙拌处.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+  let ids = [];
+  if (selectedRows.value.length > 0) {
+    ids = selectedRows.value.map((item) => item.id);
+  } else {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      delStockOut(ids).then((res) => {
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        getList();
+      });
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+// 鎵撳嵃鍔熻兘
+const handlePrint = () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+    return;
+  }
+  printData.value = [...selectedRows.value];
+  console.log('鎵撳嵃鏁版嵁:', printData.value);
+  printPreviewVisible.value = true;
+};
+
+// 鎵ц鎵撳嵃
+const executePrint = () => {
+  console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length);
+  console.log('鎵撳嵃鏁版嵁:', printData.value);
+  
+  // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+  const printWindow = window.open('', '_blank', 'width=800,height=600');
+  
+  // 鏋勫缓鎵撳嵃鍐呭
+  let printContent = `
+    <!DOCTYPE html>
+    <html>
+    <head>
+      <meta charset="UTF-8">
+      <title>鎵撳嵃棰勮</title>
+      <style>
+        body {
+          margin: 0;
+          padding: 0;
+          font-family: "SimSun", serif;
+          background: white;
+        }
+        .print-page {
+          width: 200mm;
+          height: 75mm;
+          padding: 10mm;
+          padding-left: 20mm;
+          background: white;
+          box-sizing: border-box;
+          page-break-after: always;
+          page-break-inside: avoid;
+        }
+        .print-page:last-child {
+          page-break-after: avoid;
+        }
+        .delivery-note {
+          width: 100%;
+          height: 100%;
+          font-size: 12px;
+          line-height: 1.2;
+          display: flex;
+          flex-direction: column;
+          color: #000;
+        }
+        .header {
+          text-align: center;
+          margin-bottom: 8px;
+        }
+        .company-name {
+          font-size: 18px;
+          font-weight: bold;
+          margin-bottom: 4px;
+        }
+        .document-title {
+          font-size: 16px;
+          font-weight: bold;
+        }
+        .info-section {
+          margin-bottom: 8px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        }
+        .info-row {
+          line-height: 20px;
+        }
+        .label {
+          font-weight: bold;
+          width: 60px;
+          font-size: 12px;
+        }
+        .value {
+          margin-right: 20px;
+          min-width: 80px;
+          font-size: 12px;
+        }
+        .table-section {
+          margin-bottom: 40px;
+        }
+        .product-table {
+          width: 100%;
+          border-collapse: collapse;
+          border: 1px solid #000;
+        }
+        .product-table th, .product-table td {
+          border: 1px solid #000;
+          padding: 6px;
+          text-align: center;
+          font-size: 12px;
+          line-height: 1.4;
+        }
+        .product-table th {
+          font-weight: bold;
+        }
+        .total-value {
+          font-weight: bold;
+        }
+        .footer-section {
+          margin-top: auto;
+        }
+        .footer-row {
+          display: flex;
+          margin-bottom: 3px;
+          line-height: 22px;
+          justify-content: space-between;
+        }
+        .footer-item {
+          display: flex;
+          margin-right: 20px;
+        }
+        .footer-item .label {
+          font-weight: bold;
+          width: 80px;
+          font-size: 12px;
+        }
+        .footer-item .value {
+          min-width: 80px;
+          font-size: 12px;
+        }
+        .address-item .address-value {
+          min-width: 200px;
+        }
+        @media print {
+          body {
+            margin: 0;
+            padding: 0;
+          }
+          .print-page {
+            margin: 0;
+            padding: 10mm;
+            page-break-inside: avoid;
+            page-break-after: always;
+          }
+          .print-page:last-child {
+            page-break-after: avoid;
+          }
+        }
+      </style>
+    </head>
+    <body>
+  `;
+  
+  // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+  printData.value.forEach((item, index) => {
+    printContent += `
+      <div class="print-page">
+        <div class="delivery-note">
+          <div class="header">
+            <div class="company-name">闃冲厜鍗板埛鏈夐檺璐d换鍏徃</div>
+            <div class="document-title">闆跺敭鍙戣揣鍗�</div>
+          </div>
+          
+          <div class="info-section">
+            <div class="info-row">
+              <div>
+                <span class="label">鍙戣揣鏃ユ湡锛�</span>
+                <span class="value">${formatDate(item.createTime)}</span>
+              </div>
+              <div>
+                <span class="label">瀹㈡埛鍚嶇О锛�</span>
+                <span class="value">${item.supplierName || '寮犵埍鏈�'}</span>
+              </div>
+            </div>
+            <div class="info-row">
+              <span class="label">鍗曞彿锛�</span>
+              <span class="value">${item.code || ''}</span>
+            </div>
+          </div>
+
+          <div class="table-section">
+            <table class="product-table">
+              <thead>
+                <tr>
+                  <th>浜у搧鍚嶇О</th>
+                  <th>瑙勬牸鍨嬪彿</th>
+                  <th>鍗曚綅</th>
+                  <th>鍗曚环</th>
+                  <th>闆跺敭鏁伴噺</th>
+                  <th>闆跺敭閲戦</th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td>${item.productName || '鐮傜伆鐮�'}</td>
+                  <td>${item.model || '鏍囧噯'}</td>
+                  <td>${item.unit || '鍧�'}</td>
+                  <td>${item.taxInclusiveUnitPrice || '0'}</td>
+                  <td>${item.inboundNum || '2000'}</td>
+                  <td>${item.taxInclusiveTotalPrice || '0'}</td>
+                </tr>
+              </tbody>
+              <tfoot>
+                <tr>
+                  <td class="label">鍚堣</td>
+                  <td class="total-value"></td>
+                  <td class="total-value"></td>
+                  <td class="total-value"></td>
+                  <td class="total-value">${item.inboundNum || '2000'}</td>
+                  <td class="total-value">${item.taxInclusiveTotalPrice || '0'}</td>
+                </tr>
+              </tfoot>
+            </table>
+          </div>
+
+          <div class="footer-section">
+            <div class="footer-row">
+              <div class="footer-item">
+                <span class="label">鏀惰揣鐢佃瘽锛�</span>
+                <span class="value"></span>
+              </div>
+              <div class="footer-item">
+                <span class="label">鏀惰揣浜猴細</span>
+                <span class="value"></span>
+              </div>
+              <div class="footer-item address-item">
+                <span class="label">鏀惰揣鍦板潃锛�</span>
+                <span class="value address-value"></span>
+              </div>
+            </div>
+            <div class="footer-row">
+              <div class="footer-item">
+                <span class="label">鎿嶄綔鍛橈細</span>
+                <span class="value">${userStore.nickName || '鎾曞紑鍓�'}</span>
+              </div>
+              <div class="footer-item">
+                <span class="label">鎵撳嵃鏃ユ湡锛�</span>
+                <span class="value">${formatDateTime(new Date())}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    `;
+  });
+  
+  printContent += `
+    </body>
+    </html>
+  `;
+  
+  // 鍐欏叆鍐呭鍒版柊绐楀彛
+  printWindow.document.write(printContent);
+  printWindow.document.close();
+  
+  // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+  printWindow.onload = () => {
+    setTimeout(() => {
+      printWindow.print();
+      printWindow.close();
+      printPreviewVisible.value = false;
+    }, 500);
+  };
+};
+
+
+
+// 鏍煎紡鍖栨棩鏈�
+const formatDate = (dateString) => {
+  if (!dateString) return getCurrentDate();
+  const date = new Date(dateString);
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  const day = String(date.getDate()).padStart(2, "0");
+  return `${year}/${month}/${day}`;
+};
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (date) => {
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  const day = String(date.getDate()).padStart(2, "0");
+  const hours = String(date.getHours()).padStart(2, "0");
+  const minutes = String(date.getMinutes()).padStart(2, "0");
+  const seconds = String(date.getSeconds()).padStart(2, "0");
+  return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+};
+onMounted(() => {
+  getList();
+  fetchStockRecordTypeOptions();
+});
+</script>
+
+<style scoped lang="scss">
+.print-preview-dialog {
+  .el-dialog__body {
+    padding: 0;
+    max-height: 80vh;
+    overflow-y: auto;
+  }
+}
+
+.print-preview-container {
+  .print-preview-header {
+    padding: 15px;
+    border-bottom: 1px solid #e4e7ed;
+    text-align: center;
+    
+    .el-button {
+      margin: 0 10px;
+    }
+  }
+  
+  .print-preview-content {
+    padding: 20px;
+    background-color: #f5f5f5;
+    min-height: 400px;
+  }
+}
+
+.print-page {
+  width: 220mm;
+  height: 90mm;
+  padding: 10mm;
+  margin: 0 auto;
+  background: white;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+  box-sizing: border-box;
+}
+
+.delivery-note {
+  width: 100%;
+  height: 100%;
+  font-family: "SimSun", serif;
+  font-size: 10px;
+  line-height: 1.2;
+  display: flex;
+  flex-direction: column;
+}
+
+.header {
+  text-align: center;
+  margin-bottom: 8px;
+  
+  .company-name {
+    font-size: 18px;
+    font-weight: bold;
+    margin-bottom: 4px;
+  }
+  
+  .document-title {
+    font-size: 16px;
+    font-weight: bold;
+  }
+}
+
+.info-section {
+  margin-bottom: 8px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  
+  .info-row {
+    line-height: 20px;
+    
+    .label {
+      font-weight: bold;
+      width: 60px;
+      font-size: 14px;
+    }
+    
+    .value {
+      margin-right: 20px;
+      min-width: 80px;
+      font-size: 14px;
+    }
+  }
+}
+
+.table-section {
+  margin-bottom: 4px;
+  flex: 1;
+  
+  .product-table {
+    width: 100%;
+    border-collapse: collapse;
+    border: 1px solid #000;
+    
+    th, td {
+      border: 1px solid #000;
+      padding: 6px;
+      text-align: center;
+      font-size: 14px;
+      line-height: 1.4;
+    }
+    
+    th {
+      font-weight: bold;
+    }
+    
+    .total-label {
+      text-align: right;
+      font-weight: bold;
+    }
+    
+    .total-value {
+      font-weight: bold;
+    }
+  }
+}
+
+.footer-section {
+  .footer-row {
+    display: flex;
+    margin-bottom: 3px;
+    line-height: 20px;
+    justify-content: space-between;
+    
+    .footer-item {
+      display: flex;
+      margin-right: 20px;
+      
+      .label {
+        font-weight: bold;
+        width: 80px;
+        font-size: 14px;
+      }
+      
+      .value {
+        min-width: 80px;
+        font-size: 14px;
+      }
+      
+      &.address-item {
+        .address-value {
+          min-width: 200px;
+        }
+      }
+    }
+  }
+}
+
+@media print {
+  .app-container {
+    display: none;
+  }
+  
+  .print-page {
+    box-shadow: none;
+    margin: 0;
+    padding: 10mm;
+    padding-left: 20mm;
+    page-break-inside: avoid;
+    page-break-after: always;
+  }
+  .print-page:last-child {
+    page-break-after: avoid;
+  }
+}
+</style>
diff --git a/src/views/inventoryManagement/dispatchLog/RawMaterial.vue b/src/views/inventoryManagement/dispatchLog/RawMaterial.vue
new file mode 100644
index 0000000..7d03e0b
--- /dev/null
+++ b/src/views/inventoryManagement/dispatchLog/RawMaterial.vue
@@ -0,0 +1,692 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title ml10">鍑哄簱鏃ユ湡锛�</span>
+        <el-date-picker
+          v-model="searchForm.timeStr"
+          type="date"
+          placeholder="璇烽�夋嫨鏃ユ湡"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          clearable
+          @change="handleQuery"
+        />
+        <span class="search_title ml10">鏉ユ簮锛�</span>
+        <el-select v-model="searchForm.recordType"
+                   style="width: 240px"
+                   placeholder="璇烽�夋嫨"
+                   clearable>
+          <el-option v-for="item in stockRecordTypeOptions"
+                     :key="item.value"
+                     :label="item.label"
+                     :value="item.value"/>
+        </el-select>
+        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+        >鎼滅储</el-button
+        >
+      </div>
+      <div>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+        <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
+      </div>
+    </div>
+    <div class="table_list">
+      <el-table
+        :data="tableData"
+        border
+        v-loading="tableLoading"
+        @selection-change="handleSelectionChange"
+        :expand-row-keys="expandedRowKeys"
+        :row-key="(row) => row.id"
+        style="width: 100%"
+        height="calc(100vh - 18.5em)"
+      >
+        <el-table-column align="center" type="selection" width="55" />
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column
+            label="鍑哄簱鎵规"
+            prop="outboundBatches"
+            min-width="100"
+            show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱鏃ユ湡"
+          prop="createTime"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="浜у搧澶х被"
+          prop="productName"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="瑙勬牸鍨嬪彿"
+          prop="model"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍗曚綅"
+          prop="unit"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱鏁伴噺"
+          prop="stockOutNum"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱浜�"
+          prop="createBy"
+          show-overflow-tooltip
+        />
+        <el-table-column label="鏉ユ簮"
+                         prop="recordType"
+                         show-overflow-tooltip>
+          <template #default="scope">
+            {{ getRecordType(scope.row.recordType) }}
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        layout="total, sizes, prev, pager, next, jumper"
+        :page="page.current"
+        :limit="page.size"
+        @pagination="paginationChange"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { ref, reactive, toRefs, getCurrentInstance } from "vue";
+import { ElMessageBox } from "element-plus";
+import useUserStore from "@/store/modules/user";
+import { getCurrentDate } from "@/utils/index.js";
+import {
+  getStockOutPage,
+  delStockOut,
+} from "@/api/inventoryManagement/stockOut.js";
+import {
+  findAllQualifiedStockOutRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+
+const userStore = useUserStore();
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([]);
+const page = reactive({
+  current: 1,
+  size: 100,
+});
+const total = ref(0);
+
+// 鎵撳嵃鐩稿叧
+const printPreviewVisible = ref(false);
+const printData = ref([]);
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const data = reactive({
+  searchForm: {
+    timeStr: "",
+    recordType: "",
+    rootName: "鍘熸潗鏂�"
+  }
+});
+const { searchForm } = toRefs(data);
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+const paginationChange = (obj) => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+const getList = () => {
+  tableLoading.value = true;
+  getStockOutPage({ ...searchForm.value, ...page })
+    .then((res) => {
+      tableLoading.value = false;
+      tableData.value = res.data.records;
+      tableData.value.map((item) => {
+        item.children = [];
+      });
+      total.value = res.data.total;
+    })
+    .catch(() => {
+      tableLoading.value = false;
+    });
+};
+
+const getRecordType = (recordType) => {
+  return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
+}
+
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+  findAllQualifiedStockOutRecordTypeOptions()
+    .then(res => {
+      stockRecordTypeOptions.value = res.data;
+    })
+}
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+  // 杩囨护鎺夊瓙鏁版嵁
+  selectedRows.value = selection.filter((item) => item.id);
+  console.log("selection", selectedRows.value);
+};
+const expandedRowKeys = ref([]);
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download("/stockOutRecord/exportStockOutRecord", {rootName: searchForm.value.rootName}, "鍘熸潗鏂欏嚭搴撳彴璐�.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+  let ids = [];
+  if (selectedRows.value.length > 0) {
+    ids = selectedRows.value.map((item) => item.id);
+  } else {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      delStockOut(ids).then((res) => {
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        getList();
+      });
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+// 鎵撳嵃鍔熻兘
+const handlePrint = () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+    return;
+  }
+  printData.value = [...selectedRows.value];
+  console.log('鎵撳嵃鏁版嵁:', printData.value);
+  printPreviewVisible.value = true;
+};
+
+// 鎵ц鎵撳嵃
+const executePrint = () => {
+  console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length);
+  console.log('鎵撳嵃鏁版嵁:', printData.value);
+  
+  // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+  const printWindow = window.open('', '_blank', 'width=800,height=600');
+  
+  // 鏋勫缓鎵撳嵃鍐呭
+  let printContent = `
+    <!DOCTYPE html>
+    <html>
+    <head>
+      <meta charset="UTF-8">
+      <title>鎵撳嵃棰勮</title>
+      <style>
+        body {
+          margin: 0;
+          padding: 0;
+          font-family: "SimSun", serif;
+          background: white;
+        }
+        .print-page {
+          width: 200mm;
+          height: 75mm;
+          padding: 10mm;
+          padding-left: 20mm;
+          background: white;
+          box-sizing: border-box;
+          page-break-after: always;
+          page-break-inside: avoid;
+        }
+        .print-page:last-child {
+          page-break-after: avoid;
+        }
+        .delivery-note {
+          width: 100%;
+          height: 100%;
+          font-size: 12px;
+          line-height: 1.2;
+          display: flex;
+          flex-direction: column;
+          color: #000;
+        }
+        .header {
+          text-align: center;
+          margin-bottom: 8px;
+        }
+        .company-name {
+          font-size: 18px;
+          font-weight: bold;
+          margin-bottom: 4px;
+        }
+        .document-title {
+          font-size: 16px;
+          font-weight: bold;
+        }
+        .info-section {
+          margin-bottom: 8px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        }
+        .info-row {
+          line-height: 20px;
+        }
+        .label {
+          font-weight: bold;
+          width: 60px;
+          font-size: 12px;
+        }
+        .value {
+          margin-right: 20px;
+          min-width: 80px;
+          font-size: 12px;
+        }
+        .table-section {
+          margin-bottom: 40px;
+        }
+        .product-table {
+          width: 100%;
+          border-collapse: collapse;
+          border: 1px solid #000;
+        }
+        .product-table th, .product-table td {
+          border: 1px solid #000;
+          padding: 6px;
+          text-align: center;
+          font-size: 12px;
+          line-height: 1.4;
+        }
+        .product-table th {
+          font-weight: bold;
+        }
+        .total-value {
+          font-weight: bold;
+        }
+        .footer-section {
+          margin-top: auto;
+        }
+        .footer-row {
+          display: flex;
+          margin-bottom: 3px;
+          line-height: 22px;
+          justify-content: space-between;
+        }
+        .footer-item {
+          display: flex;
+          margin-right: 20px;
+        }
+        .footer-item .label {
+          font-weight: bold;
+          width: 80px;
+          font-size: 12px;
+        }
+        .footer-item .value {
+          min-width: 80px;
+          font-size: 12px;
+        }
+        .address-item .address-value {
+          min-width: 200px;
+        }
+        @media print {
+          body {
+            margin: 0;
+            padding: 0;
+          }
+          .print-page {
+            margin: 0;
+            padding: 10mm;
+            page-break-inside: avoid;
+            page-break-after: always;
+          }
+          .print-page:last-child {
+            page-break-after: avoid;
+          }
+        }
+      </style>
+    </head>
+    <body>
+  `;
+  
+  // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+  printData.value.forEach((item, index) => {
+    printContent += `
+      <div class="print-page">
+        <div class="delivery-note">
+          <div class="header">
+            <div class="company-name">闃冲厜鍗板埛鏈夐檺璐d换鍏徃</div>
+            <div class="document-title">闆跺敭鍙戣揣鍗�</div>
+          </div>
+          
+          <div class="info-section">
+            <div class="info-row">
+              <div>
+                <span class="label">鍙戣揣鏃ユ湡锛�</span>
+                <span class="value">${formatDate(item.createTime)}</span>
+              </div>
+              <div>
+                <span class="label">瀹㈡埛鍚嶇О锛�</span>
+                <span class="value">${item.supplierName || '寮犵埍鏈�'}</span>
+              </div>
+            </div>
+            <div class="info-row">
+              <span class="label">鍗曞彿锛�</span>
+              <span class="value">${item.code || ''}</span>
+            </div>
+          </div>
+
+          <div class="table-section">
+            <table class="product-table">
+              <thead>
+                <tr>
+                  <th>浜у搧鍚嶇О</th>
+                  <th>瑙勬牸鍨嬪彿</th>
+                  <th>鍗曚綅</th>
+                  <th>鍗曚环</th>
+                  <th>闆跺敭鏁伴噺</th>
+                  <th>闆跺敭閲戦</th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td>${item.productName || '鐮傜伆鐮�'}</td>
+                  <td>${item.model || '鏍囧噯'}</td>
+                  <td>${item.unit || '鍧�'}</td>
+                  <td>${item.taxInclusiveUnitPrice || '0'}</td>
+                  <td>${item.inboundNum || '2000'}</td>
+                  <td>${item.taxInclusiveTotalPrice || '0'}</td>
+                </tr>
+              </tbody>
+              <tfoot>
+                <tr>
+                  <td class="label">鍚堣</td>
+                  <td class="total-value"></td>
+                  <td class="total-value"></td>
+                  <td class="total-value"></td>
+                  <td class="total-value">${item.inboundNum || '2000'}</td>
+                  <td class="total-value">${item.taxInclusiveTotalPrice || '0'}</td>
+                </tr>
+              </tfoot>
+            </table>
+          </div>
+
+          <div class="footer-section">
+            <div class="footer-row">
+              <div class="footer-item">
+                <span class="label">鏀惰揣鐢佃瘽锛�</span>
+                <span class="value"></span>
+              </div>
+              <div class="footer-item">
+                <span class="label">鏀惰揣浜猴細</span>
+                <span class="value"></span>
+              </div>
+              <div class="footer-item address-item">
+                <span class="label">鏀惰揣鍦板潃锛�</span>
+                <span class="value address-value"></span>
+              </div>
+            </div>
+            <div class="footer-row">
+              <div class="footer-item">
+                <span class="label">鎿嶄綔鍛橈細</span>
+                <span class="value">${userStore.nickName || '鎾曞紑鍓�'}</span>
+              </div>
+              <div class="footer-item">
+                <span class="label">鎵撳嵃鏃ユ湡锛�</span>
+                <span class="value">${formatDateTime(new Date())}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    `;
+  });
+  
+  printContent += `
+    </body>
+    </html>
+  `;
+  
+  // 鍐欏叆鍐呭鍒版柊绐楀彛
+  printWindow.document.write(printContent);
+  printWindow.document.close();
+  
+  // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+  printWindow.onload = () => {
+    setTimeout(() => {
+      printWindow.print();
+      printWindow.close();
+      printPreviewVisible.value = false;
+    }, 500);
+  };
+};
+
+
+
+// 鏍煎紡鍖栨棩鏈�
+const formatDate = (dateString) => {
+  if (!dateString) return getCurrentDate();
+  const date = new Date(dateString);
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  const day = String(date.getDate()).padStart(2, "0");
+  return `${year}/${month}/${day}`;
+};
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (date) => {
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  const day = String(date.getDate()).padStart(2, "0");
+  const hours = String(date.getHours()).padStart(2, "0");
+  const minutes = String(date.getMinutes()).padStart(2, "0");
+  const seconds = String(date.getSeconds()).padStart(2, "0");
+  return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+};
+onMounted(() => {
+  getList();
+  fetchStockRecordTypeOptions();
+});
+</script>
+
+<style scoped lang="scss">
+.print-preview-dialog {
+  .el-dialog__body {
+    padding: 0;
+    max-height: 80vh;
+    overflow-y: auto;
+  }
+}
+
+.print-preview-container {
+  .print-preview-header {
+    padding: 15px;
+    border-bottom: 1px solid #e4e7ed;
+    text-align: center;
+    
+    .el-button {
+      margin: 0 10px;
+    }
+  }
+  
+  .print-preview-content {
+    padding: 20px;
+    background-color: #f5f5f5;
+    min-height: 400px;
+  }
+}
+
+.print-page {
+  width: 220mm;
+  height: 90mm;
+  padding: 10mm;
+  margin: 0 auto;
+  background: white;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+  box-sizing: border-box;
+}
+
+.delivery-note {
+  width: 100%;
+  height: 100%;
+  font-family: "SimSun", serif;
+  font-size: 10px;
+  line-height: 1.2;
+  display: flex;
+  flex-direction: column;
+}
+
+.header {
+  text-align: center;
+  margin-bottom: 8px;
+  
+  .company-name {
+    font-size: 18px;
+    font-weight: bold;
+    margin-bottom: 4px;
+  }
+  
+  .document-title {
+    font-size: 16px;
+    font-weight: bold;
+  }
+}
+
+.info-section {
+  margin-bottom: 8px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  
+  .info-row {
+    line-height: 20px;
+    
+    .label {
+      font-weight: bold;
+      width: 60px;
+      font-size: 14px;
+    }
+    
+    .value {
+      margin-right: 20px;
+      min-width: 80px;
+      font-size: 14px;
+    }
+  }
+}
+
+.table-section {
+  margin-bottom: 4px;
+  flex: 1;
+  
+  .product-table {
+    width: 100%;
+    border-collapse: collapse;
+    border: 1px solid #000;
+    
+    th, td {
+      border: 1px solid #000;
+      padding: 6px;
+      text-align: center;
+      font-size: 14px;
+      line-height: 1.4;
+    }
+    
+    th {
+      font-weight: bold;
+    }
+    
+    .total-label {
+      text-align: right;
+      font-weight: bold;
+    }
+    
+    .total-value {
+      font-weight: bold;
+    }
+  }
+}
+
+.footer-section {
+  .footer-row {
+    display: flex;
+    margin-bottom: 3px;
+    line-height: 20px;
+    justify-content: space-between;
+    
+    .footer-item {
+      display: flex;
+      margin-right: 20px;
+      
+      .label {
+        font-weight: bold;
+        width: 80px;
+        font-size: 14px;
+      }
+      
+      .value {
+        min-width: 80px;
+        font-size: 14px;
+      }
+      
+      &.address-item {
+        .address-value {
+          min-width: 200px;
+        }
+      }
+    }
+  }
+}
+
+@media print {
+  .app-container {
+    display: none;
+  }
+  
+  .print-page {
+    box-shadow: none;
+    margin: 0;
+    padding: 10mm;
+    padding-left: 20mm;
+    page-break-inside: avoid;
+    page-break-after: always;
+  }
+  .print-page:last-child {
+    page-break-after: avoid;
+  }
+}
+</style>
diff --git a/src/views/inventoryManagement/dispatchLog/Unqualified.vue b/src/views/inventoryManagement/dispatchLog/Unqualified.vue
new file mode 100644
index 0000000..f5f17a6
--- /dev/null
+++ b/src/views/inventoryManagement/dispatchLog/Unqualified.vue
@@ -0,0 +1,692 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title ml10">鍑哄簱鏃ユ湡锛�</span>
+        <el-date-picker
+          v-model="searchForm.timeStr"
+          type="date"
+          placeholder="璇烽�夋嫨鏃ユ湡"
+          value-format="YYYY-MM-DD"
+          format="YYYY-MM-DD"
+          clearable
+          @change="handleQuery"
+        />
+        <span class="search_title ml10">鏉ユ簮锛�</span>
+        <el-select v-model="searchForm.recordType"
+                   style="width: 240px"
+                   placeholder="璇烽�夋嫨"
+                   clearable>
+          <el-option v-for="item in stockRecordTypeOptions"
+                     :key="item.value"
+                     :label="item.label"
+                     :value="item.value"/>
+        </el-select>
+        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+        >鎼滅储</el-button
+        >
+      </div>
+      <div>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+        <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
+      </div>
+    </div>
+    <div class="table_list">
+      <el-table
+        :data="tableData"
+        border
+        v-loading="tableLoading"
+        @selection-change="handleSelectionChange"
+        :expand-row-keys="expandedRowKeys"
+        :row-key="(row) => row.id"
+        style="width: 100%"
+        height="calc(100vh - 18.5em)"
+      >
+        <el-table-column align="center" type="selection" width="55" />
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column
+            label="鍑哄簱鎵规"
+            prop="outboundBatches"
+            min-width="100"
+            show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱鏃ユ湡"
+          prop="createTime"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="浜у搧澶х被"
+          prop="productName"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="瑙勬牸鍨嬪彿"
+          prop="model"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍗曚綅"
+          prop="unit"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱鏁伴噺"
+          prop="stockOutNum"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍑哄簱浜�"
+          prop="createBy"
+          show-overflow-tooltip
+        />
+        <el-table-column label="鏉ユ簮"
+                         prop="recordType"
+                         show-overflow-tooltip>
+          <template #default="scope">
+            {{ getRecordType(scope.row.recordType) }}
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        layout="total, sizes, prev, pager, next, jumper"
+        :page="page.current"
+        :limit="page.size"
+        @pagination="paginationChange"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { ref, reactive, toRefs, getCurrentInstance } from "vue";
+import { ElMessageBox } from "element-plus";
+import useUserStore from "@/store/modules/user";
+import { getCurrentDate } from "@/utils/index.js";
+import {
+  getStockOutPage,
+  delStockOut,
+} from "@/api/inventoryManagement/stockOut.js";
+import {
+  findAllUnQualifiedStockOutRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+
+const userStore = useUserStore();
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([]);
+const page = reactive({
+  current: 1,
+  size: 100,
+});
+const total = ref(0);
+
+// 鎵撳嵃鐩稿叧
+const printPreviewVisible = ref(false);
+const printData = ref([]);
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const data = reactive({
+  searchForm: {
+    timeStr: "",
+    recordType: "",
+    rootName: "杈呮潗"
+  }
+});
+const { searchForm } = toRefs(data);
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+const paginationChange = (obj) => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+const getList = () => {
+  tableLoading.value = true;
+  getStockOutPage({ ...searchForm.value, ...page })
+    .then((res) => {
+      tableLoading.value = false;
+      tableData.value = res.data.records;
+      tableData.value.map((item) => {
+        item.children = [];
+      });
+      total.value = res.data.total;
+    })
+    .catch(() => {
+      tableLoading.value = false;
+    });
+};
+
+const getRecordType = (recordType) => {
+  return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
+}
+
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+  findAllUnQualifiedStockOutRecordTypeOptions()
+    .then(res => {
+      stockRecordTypeOptions.value = res.data;
+    })
+}
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+  // 杩囨护鎺夊瓙鏁版嵁
+  selectedRows.value = selection.filter((item) => item.id);
+  console.log("selection", selectedRows.value);
+};
+const expandedRowKeys = ref([]);
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download("/stockOutRecord/exportStockOutRecord", {rootName: searchForm.value.rootName}, "杈呮潗鍑哄簱鍙拌处.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+  let ids = [];
+  if (selectedRows.value.length > 0) {
+    ids = selectedRows.value.map((item) => item.id);
+  } else {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      delStockOut(ids).then((res) => {
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        getList();
+      });
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+// 鎵撳嵃鍔熻兘
+const handlePrint = () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+    return;
+  }
+  printData.value = [...selectedRows.value];
+  console.log('鎵撳嵃鏁版嵁:', printData.value);
+  printPreviewVisible.value = true;
+};
+
+// 鎵ц鎵撳嵃
+const executePrint = () => {
+  console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length);
+  console.log('鎵撳嵃鏁版嵁:', printData.value);
+  
+  // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+  const printWindow = window.open('', '_blank', 'width=800,height=600');
+  
+  // 鏋勫缓鎵撳嵃鍐呭
+  let printContent = `
+    <!DOCTYPE html>
+    <html>
+    <head>
+      <meta charset="UTF-8">
+      <title>鎵撳嵃棰勮</title>
+      <style>
+        body {
+          margin: 0;
+          padding: 0;
+          font-family: "SimSun", serif;
+          background: white;
+        }
+        .print-page {
+          width: 200mm;
+          height: 75mm;
+          padding: 10mm;
+          padding-left: 20mm;
+          background: white;
+          box-sizing: border-box;
+          page-break-after: always;
+          page-break-inside: avoid;
+        }
+        .print-page:last-child {
+          page-break-after: avoid;
+        }
+        .delivery-note {
+          width: 100%;
+          height: 100%;
+          font-size: 12px;
+          line-height: 1.2;
+          display: flex;
+          flex-direction: column;
+          color: #000;
+        }
+        .header {
+          text-align: center;
+          margin-bottom: 8px;
+        }
+        .company-name {
+          font-size: 18px;
+          font-weight: bold;
+          margin-bottom: 4px;
+        }
+        .document-title {
+          font-size: 16px;
+          font-weight: bold;
+        }
+        .info-section {
+          margin-bottom: 8px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        }
+        .info-row {
+          line-height: 20px;
+        }
+        .label {
+          font-weight: bold;
+          width: 60px;
+          font-size: 12px;
+        }
+        .value {
+          margin-right: 20px;
+          min-width: 80px;
+          font-size: 12px;
+        }
+        .table-section {
+          margin-bottom: 40px;
+        }
+        .product-table {
+          width: 100%;
+          border-collapse: collapse;
+          border: 1px solid #000;
+        }
+        .product-table th, .product-table td {
+          border: 1px solid #000;
+          padding: 6px;
+          text-align: center;
+          font-size: 12px;
+          line-height: 1.4;
+        }
+        .product-table th {
+          font-weight: bold;
+        }
+        .total-value {
+          font-weight: bold;
+        }
+        .footer-section {
+          margin-top: auto;
+        }
+        .footer-row {
+          display: flex;
+          margin-bottom: 3px;
+          line-height: 22px;
+          justify-content: space-between;
+        }
+        .footer-item {
+          display: flex;
+          margin-right: 20px;
+        }
+        .footer-item .label {
+          font-weight: bold;
+          width: 80px;
+          font-size: 12px;
+        }
+        .footer-item .value {
+          min-width: 80px;
+          font-size: 12px;
+        }
+        .address-item .address-value {
+          min-width: 200px;
+        }
+        @media print {
+          body {
+            margin: 0;
+            padding: 0;
+          }
+          .print-page {
+            margin: 0;
+            padding: 10mm;
+            page-break-inside: avoid;
+            page-break-after: always;
+          }
+          .print-page:last-child {
+            page-break-after: avoid;
+          }
+        }
+      </style>
+    </head>
+    <body>
+  `;
+  
+  // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+  printData.value.forEach((item, index) => {
+    printContent += `
+      <div class="print-page">
+        <div class="delivery-note">
+          <div class="header">
+            <div class="company-name">闃冲厜鍗板埛鏈夐檺璐d换鍏徃</div>
+            <div class="document-title">闆跺敭鍙戣揣鍗�</div>
+          </div>
+          
+          <div class="info-section">
+            <div class="info-row">
+              <div>
+                <span class="label">鍙戣揣鏃ユ湡锛�</span>
+                <span class="value">${formatDate(item.createTime)}</span>
+              </div>
+              <div>
+                <span class="label">瀹㈡埛鍚嶇О锛�</span>
+                <span class="value">${item.supplierName || '寮犵埍鏈�'}</span>
+              </div>
+            </div>
+            <div class="info-row">
+              <span class="label">鍗曞彿锛�</span>
+              <span class="value">${item.code || ''}</span>
+            </div>
+          </div>
+
+          <div class="table-section">
+            <table class="product-table">
+              <thead>
+                <tr>
+                  <th>浜у搧鍚嶇О</th>
+                  <th>瑙勬牸鍨嬪彿</th>
+                  <th>鍗曚綅</th>
+                  <th>鍗曚环</th>
+                  <th>闆跺敭鏁伴噺</th>
+                  <th>闆跺敭閲戦</th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td>${item.productName || '鐮傜伆鐮�'}</td>
+                  <td>${item.model || '鏍囧噯'}</td>
+                  <td>${item.unit || '鍧�'}</td>
+                  <td>${item.taxInclusiveUnitPrice || '0'}</td>
+                  <td>${item.inboundNum || '2000'}</td>
+                  <td>${item.taxInclusiveTotalPrice || '0'}</td>
+                </tr>
+              </tbody>
+              <tfoot>
+                <tr>
+                  <td class="label">鍚堣</td>
+                  <td class="total-value"></td>
+                  <td class="total-value"></td>
+                  <td class="total-value"></td>
+                  <td class="total-value">${item.inboundNum || '2000'}</td>
+                  <td class="total-value">${item.taxInclusiveTotalPrice || '0'}</td>
+                </tr>
+              </tfoot>
+            </table>
+          </div>
+
+          <div class="footer-section">
+            <div class="footer-row">
+              <div class="footer-item">
+                <span class="label">鏀惰揣鐢佃瘽锛�</span>
+                <span class="value"></span>
+              </div>
+              <div class="footer-item">
+                <span class="label">鏀惰揣浜猴細</span>
+                <span class="value"></span>
+              </div>
+              <div class="footer-item address-item">
+                <span class="label">鏀惰揣鍦板潃锛�</span>
+                <span class="value address-value"></span>
+              </div>
+            </div>
+            <div class="footer-row">
+              <div class="footer-item">
+                <span class="label">鎿嶄綔鍛橈細</span>
+                <span class="value">${userStore.nickName || '鎾曞紑鍓�'}</span>
+              </div>
+              <div class="footer-item">
+                <span class="label">鎵撳嵃鏃ユ湡锛�</span>
+                <span class="value">${formatDateTime(new Date())}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    `;
+  });
+  
+  printContent += `
+    </body>
+    </html>
+  `;
+  
+  // 鍐欏叆鍐呭鍒版柊绐楀彛
+  printWindow.document.write(printContent);
+  printWindow.document.close();
+  
+  // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+  printWindow.onload = () => {
+    setTimeout(() => {
+      printWindow.print();
+      printWindow.close();
+      printPreviewVisible.value = false;
+    }, 500);
+  };
+};
+
+
+
+// 鏍煎紡鍖栨棩鏈�
+const formatDate = (dateString) => {
+  if (!dateString) return getCurrentDate();
+  const date = new Date(dateString);
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  const day = String(date.getDate()).padStart(2, "0");
+  return `${year}/${month}/${day}`;
+};
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (date) => {
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  const day = String(date.getDate()).padStart(2, "0");
+  const hours = String(date.getHours()).padStart(2, "0");
+  const minutes = String(date.getMinutes()).padStart(2, "0");
+  const seconds = String(date.getSeconds()).padStart(2, "0");
+  return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+};
+onMounted(() => {
+  getList();
+  fetchStockRecordTypeOptions();
+});
+</script>
+
+<style scoped lang="scss">
+.print-preview-dialog {
+  .el-dialog__body {
+    padding: 0;
+    max-height: 80vh;
+    overflow-y: auto;
+  }
+}
+
+.print-preview-container {
+  .print-preview-header {
+    padding: 15px;
+    border-bottom: 1px solid #e4e7ed;
+    text-align: center;
+    
+    .el-button {
+      margin: 0 10px;
+    }
+  }
+  
+  .print-preview-content {
+    padding: 20px;
+    background-color: #f5f5f5;
+    min-height: 400px;
+  }
+}
+
+.print-page {
+  width: 220mm;
+  height: 90mm;
+  padding: 10mm;
+  margin: 0 auto;
+  background: white;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+  box-sizing: border-box;
+}
+
+.delivery-note {
+  width: 100%;
+  height: 100%;
+  font-family: "SimSun", serif;
+  font-size: 10px;
+  line-height: 1.2;
+  display: flex;
+  flex-direction: column;
+}
+
+.header {
+  text-align: center;
+  margin-bottom: 8px;
+  
+  .company-name {
+    font-size: 18px;
+    font-weight: bold;
+    margin-bottom: 4px;
+  }
+  
+  .document-title {
+    font-size: 16px;
+    font-weight: bold;
+  }
+}
+
+.info-section {
+  margin-bottom: 8px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  
+  .info-row {
+    line-height: 20px;
+    
+    .label {
+      font-weight: bold;
+      width: 60px;
+      font-size: 14px;
+    }
+    
+    .value {
+      margin-right: 20px;
+      min-width: 80px;
+      font-size: 14px;
+    }
+  }
+}
+
+.table-section {
+  margin-bottom: 4px;
+  flex: 1;
+  
+  .product-table {
+    width: 100%;
+    border-collapse: collapse;
+    border: 1px solid #000;
+    
+    th, td {
+      border: 1px solid #000;
+      padding: 6px;
+      text-align: center;
+      font-size: 14px;
+      line-height: 1.4;
+    }
+    
+    th {
+      font-weight: bold;
+    }
+    
+    .total-label {
+      text-align: right;
+      font-weight: bold;
+    }
+    
+    .total-value {
+      font-weight: bold;
+    }
+  }
+}
+
+.footer-section {
+  .footer-row {
+    display: flex;
+    margin-bottom: 3px;
+    line-height: 20px;
+    justify-content: space-between;
+    
+    .footer-item {
+      display: flex;
+      margin-right: 20px;
+      
+      .label {
+        font-weight: bold;
+        width: 80px;
+        font-size: 14px;
+      }
+      
+      .value {
+        min-width: 80px;
+        font-size: 14px;
+      }
+      
+      &.address-item {
+        .address-value {
+          min-width: 200px;
+        }
+      }
+    }
+  }
+}
+
+@media print {
+  .app-container {
+    display: none;
+  }
+  
+  .print-page {
+    box-shadow: none;
+    margin: 0;
+    padding: 10mm;
+    padding-left: 20mm;
+    page-break-inside: avoid;
+    page-break-after: always;
+  }
+  .print-page:last-child {
+    page-break-after: avoid;
+  }
+}
+</style>
diff --git a/src/views/inventoryManagement/dispatchLog/index.vue b/src/views/inventoryManagement/dispatchLog/index.vue
index 88d9984..2c2d236 100644
--- a/src/views/inventoryManagement/dispatchLog/index.vue
+++ b/src/views/inventoryManagement/dispatchLog/index.vue
@@ -1,38 +1,49 @@
-<!-- 鍦ㄤ綘鐨勪富椤甸潰涓� -->
 <template>
   <div class="app-container">
     <el-tabs v-model="activeTab" @tab-change="handleTabChange">
-      <el-tab-pane v-for="tab in tabs"
-                   :label="tab.label"
-                   :name="tab.name"
-                   :key="tab.name">
-        <record :type="tab.type" v-if="activeTab === tab.name" />
+      <el-tab-pane
+          v-for="tab in tabs"
+          :label="tab.label"
+          :name="tab.name"
+          :key="tab.name"
+      >
+        <component
+            :is="tab.component"
+            v-if="activeTab === tab.name"
+            :stock-type="tab.name"
+        />
       </el-tab-pane>
     </el-tabs>
   </div>
 </template>
 
 <script setup>
-import Record from "@/views/inventoryManagement/dispatchLog/Record.vue";
+import { ref, shallowRef } from 'vue'
+import QualifiedRecord from "@/views/inventoryManagement/dispatchLog/Qualified.vue";
+import UnqualifiedRecord from "@/views/inventoryManagement/dispatchLog/Unqualified.vue";
+import RawMaterialRecord from "@/views/inventoryManagement/dispatchLog/RawMaterial.vue"
+
 const activeTab = ref('qualified')
-const type = ref(0)
-const tabs = computed(() => {
-  return [
-    {
-      label: '鍚堟牸鍑哄簱',
-      name: 'qualified',
-      type: '0'
-    },
-    {
-      label: '涓嶅悎鏍煎嚭搴�',
-      name: 'unqualified',
-      type: '1'
-    }
-  ]
-})
+
+const tabs = shallowRef([
+  {
+    label: '鎴愬搧鍑哄簱',
+    name: 'qualified',
+    component: QualifiedRecord
+  },
+  {
+    label: '杈呮潗鍑哄簱',
+    name: 'assistant',
+    component: UnqualifiedRecord
+  },
+  {
+    label: '鍘熸潗鏂欏嚭搴�',
+    name: 'rawMaterial',
+    component: RawMaterialRecord
+  }
+])
 
 const handleTabChange = (tabName) => {
   activeTab.value = tabName;
-  type.value = tabName === 'qualified' ? 0 : 1
 }
 </script>
diff --git a/src/views/inventoryManagement/receiptManagement/Qualified.vue b/src/views/inventoryManagement/receiptManagement/Qualified.vue
new file mode 100644
index 0000000..4035255
--- /dev/null
+++ b/src/views/inventoryManagement/receiptManagement/Qualified.vue
@@ -0,0 +1,234 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title ml10">鍏ュ簱鏃ユ湡锛�</span>
+        <el-date-picker v-model="searchForm.timeStr"
+                        type="date"
+                        placeholder="璇烽�夋嫨鏃ユ湡"
+                        value-format="YYYY-MM-DD"
+                        format="YYYY-MM-DD"
+                        clearable
+                        @change="handleQuery"/>
+        <span class="search_title ml10">浜у搧澶х被锛�</span>
+        <el-input v-model="searchForm.productName"
+                  style="width: 240px"
+                  placeholder="璇疯緭鍏�"
+                  clearable/>
+        <span class="search_title ml10">鏉ユ簮锛�</span>
+        <el-select v-model="searchForm.recordType"
+                  style="width: 240px"
+                  placeholder="璇烽�夋嫨"
+                  clearable>
+          <el-option v-for="item in stockRecordTypeOptions"
+                     :key="item.value"
+                     :label="item.label"
+                     :value="item.value"/>
+        </el-select>
+        <el-button type="primary"
+                   @click="handleQuery"
+                   style="margin-left: 10px">鎼滅储
+        </el-button>
+      </div>
+      <div>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="danger"
+                   plain
+                   @click="handleDelete">鍒犻櫎
+        </el-button>
+      </div>
+    </div>
+    <div class="table_list">
+      <el-table :data="tableData"
+                border
+                v-loading="tableLoading"
+                @selection-change="handleSelectionChange"
+                :expand-row-keys="expandedRowKeys"
+                :row-key="row => row.id"
+                style="width: 100%"
+                height="calc(100vh - 18.5em)">
+        <el-table-column align="center"
+                         type="selection"
+                         width="55"/>
+        <el-table-column align="center"
+                         label="搴忓彿"
+                         type="index"
+                         width="60"/>
+        <el-table-column label="鍏ュ簱鎵规"
+                         prop="inboundBatches"
+                         width="280"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱鏃堕棿"
+                         prop="createTime"
+                         show-overflow-tooltip/>
+        <el-table-column label="浜у搧澶х被"
+                         prop="productName"
+                         show-overflow-tooltip/>
+        <el-table-column label="瑙勬牸鍨嬪彿"
+                         prop="model"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍗曚綅"
+                         prop="unit"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱鏁伴噺"
+                         prop="stockInNum"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱浜�"
+                         prop="createBy"
+                         show-overflow-tooltip/>
+        <el-table-column label="鏉ユ簮"
+                         prop="recordType"
+                         show-overflow-tooltip>
+          <template #default="scope">
+            {{ getRecordType(scope.row.recordType) }}
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination v-show="total > 0"
+                  :total="total"
+                  layout="total, sizes, prev, pager, next, jumper"
+                  :page="page.current"
+                  :limit="page.size"
+                  @pagination="pageProductChange"/>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import pagination from "@/components/PIMTable/Pagination.vue";
+import {
+  ref,
+  reactive,
+  toRefs,
+  onMounted,
+  getCurrentInstance,
+} from "vue";
+import {ElMessageBox} from "element-plus";
+import {
+  getStockInRecordListPage,
+  batchDeleteStockInRecords,
+} from "@/api/inventoryManagement/stockInRecord.js";
+import {
+  findAllQualifiedStockInRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+
+const {proxy} = getCurrentInstance();
+
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([]);
+const page = reactive({
+  current: 1,
+  size: 10,
+});
+const total = ref(0);
+
+const data = reactive({
+  searchForm: {
+    productName: "",
+    timeStr: "",
+    recordType: "",
+    rootName: "鎴愬搧"
+  },
+});
+const {searchForm} = toRefs(data);
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+
+const getRecordType = (recordType) => {
+  return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
+}
+
+const pageProductChange = obj => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+
+const getList = () => {
+  tableLoading.value = true;
+  const params = {...page};
+  params.timeStr = searchForm.value.timeStr;
+  params.productName = searchForm.value.productName;
+  params.recordType = searchForm.value.recordType;
+  params.rootName = searchForm.value.rootName;
+  getStockInRecordListPage(params)
+      .then(res => {
+        tableData.value = res.data.records;
+        total.value = res.data.total || 0;
+      }).finally(() => {
+    tableLoading.value = false;
+  })
+};
+
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+  findAllQualifiedStockInRecordTypeOptions()
+      .then(res => {
+        stockRecordTypeOptions.value = res.data;
+      })
+}
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = selection => {
+  selectedRows.value = selection.filter(item => item.id);
+};
+
+const expandedRowKeys = ref([]);
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        proxy.download("/stockInRecord/exportStockInRecord", {rootName: searchForm.value.rootName}, "鎴愬搧鍏ュ簱.xlsx");
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  const ids = selectedRows.value.map(item => item.id);
+
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        batchDeleteStockInRecords(ids)
+            .then(() => {
+              proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+              getList();
+            })
+            .catch(() => {
+              proxy.$modal.msgError("鍒犻櫎澶辫触");
+            });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+
+onMounted(() => {
+  getList();
+  fetchStockRecordTypeOptions();
+});
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/inventoryManagement/receiptManagement/RawMaterial.vue b/src/views/inventoryManagement/receiptManagement/RawMaterial.vue
new file mode 100644
index 0000000..89d5296
--- /dev/null
+++ b/src/views/inventoryManagement/receiptManagement/RawMaterial.vue
@@ -0,0 +1,234 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title ml10">鍏ュ簱鏃ユ湡锛�</span>
+        <el-date-picker v-model="searchForm.timeStr"
+                        type="date"
+                        placeholder="璇烽�夋嫨鏃ユ湡"
+                        value-format="YYYY-MM-DD"
+                        format="YYYY-MM-DD"
+                        clearable
+                        @change="handleQuery"/>
+        <span class="search_title ml10">浜у搧澶х被锛�</span>
+        <el-input v-model="searchForm.productName"
+                  style="width: 240px"
+                  placeholder="璇疯緭鍏�"
+                  clearable/>
+        <span class="search_title ml10">鏉ユ簮锛�</span>
+        <el-select v-model="searchForm.recordType"
+                  style="width: 240px"
+                  placeholder="璇烽�夋嫨"
+                  clearable>
+          <el-option v-for="item in stockRecordTypeOptions"
+                     :key="item.value"
+                     :label="item.label"
+                     :value="item.value"/>
+        </el-select>
+        <el-button type="primary"
+                   @click="handleQuery"
+                   style="margin-left: 10px">鎼滅储
+        </el-button>
+      </div>
+      <div>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="danger"
+                   plain
+                   @click="handleDelete">鍒犻櫎
+        </el-button>
+      </div>
+    </div>
+    <div class="table_list">
+      <el-table :data="tableData"
+                border
+                v-loading="tableLoading"
+                @selection-change="handleSelectionChange"
+                :expand-row-keys="expandedRowKeys"
+                :row-key="row => row.id"
+                style="width: 100%"
+                height="calc(100vh - 18.5em)">
+        <el-table-column align="center"
+                         type="selection"
+                         width="55"/>
+        <el-table-column align="center"
+                         label="搴忓彿"
+                         type="index"
+                         width="60"/>
+        <el-table-column label="鍏ュ簱鎵规"
+                         prop="inboundBatches"
+                         width="280"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱鏃堕棿"
+                         prop="createTime"
+                         show-overflow-tooltip/>
+        <el-table-column label="浜у搧澶х被"
+                         prop="productName"
+                         show-overflow-tooltip/>
+        <el-table-column label="瑙勬牸鍨嬪彿"
+                         prop="model"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍗曚綅"
+                         prop="unit"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱鏁伴噺"
+                         prop="stockInNum"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱浜�"
+                         prop="createBy"
+                         show-overflow-tooltip/>
+        <el-table-column label="鏉ユ簮"
+                         prop="recordType"
+                         show-overflow-tooltip>
+          <template #default="scope">
+            {{ getRecordType(scope.row.recordType) }}
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination v-show="total > 0"
+                  :total="total"
+                  layout="total, sizes, prev, pager, next, jumper"
+                  :page="page.current"
+                  :limit="page.size"
+                  @pagination="pageProductChange"/>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import pagination from "@/components/PIMTable/Pagination.vue";
+import {
+  ref,
+  reactive,
+  toRefs,
+  onMounted,
+  getCurrentInstance,
+} from "vue";
+import {ElMessageBox} from "element-plus";
+import {
+  getStockInRecordListPage,
+  batchDeleteStockInRecords,
+} from "@/api/inventoryManagement/stockInRecord.js";
+import {
+  findAllQualifiedStockInRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+
+const {proxy} = getCurrentInstance();
+
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([]);
+const page = reactive({
+  current: 1,
+  size: 10,
+});
+const total = ref(0);
+
+const data = reactive({
+  searchForm: {
+    productName: "",
+    timeStr: "",
+    recordType: "",
+    rootName: "鍘熸潗鏂�"
+  },
+});
+const {searchForm} = toRefs(data);
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+
+const getRecordType = (recordType) => {
+  return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
+}
+
+const pageProductChange = obj => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+
+const getList = () => {
+  tableLoading.value = true;
+  const params = {...page};
+  params.timeStr = searchForm.value.timeStr;
+  params.productName = searchForm.value.productName;
+  params.recordType = searchForm.value.recordType;
+  params.rootName = searchForm.value.rootName;
+  getStockInRecordListPage(params)
+      .then(res => {
+        tableData.value = res.data.records;
+        total.value = res.data.total || 0;
+      }).finally(() => {
+    tableLoading.value = false;
+  })
+};
+
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+  findAllQualifiedStockInRecordTypeOptions()
+      .then(res => {
+        stockRecordTypeOptions.value = res.data;
+      })
+}
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = selection => {
+  selectedRows.value = selection.filter(item => item.id);
+};
+
+const expandedRowKeys = ref([]);
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        proxy.download("/stockInRecord/exportStockInRecord", {rootName: searchForm.value.rootName}, "鍘熸潗鏂欏叆搴�.xlsx");
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  const ids = selectedRows.value.map(item => item.id);
+
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        batchDeleteStockInRecords(ids)
+            .then(() => {
+              proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+              getList();
+            })
+            .catch(() => {
+              proxy.$modal.msgError("鍒犻櫎澶辫触");
+            });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+
+onMounted(() => {
+  getList();
+  fetchStockRecordTypeOptions();
+});
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/inventoryManagement/receiptManagement/Unqualified.vue b/src/views/inventoryManagement/receiptManagement/Unqualified.vue
new file mode 100644
index 0000000..4e4b9db
--- /dev/null
+++ b/src/views/inventoryManagement/receiptManagement/Unqualified.vue
@@ -0,0 +1,234 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title ml10">鍏ュ簱鏃ユ湡锛�</span>
+        <el-date-picker v-model="searchForm.timeStr"
+                        type="date"
+                        placeholder="璇烽�夋嫨鏃ユ湡"
+                        value-format="YYYY-MM-DD"
+                        format="YYYY-MM-DD"
+                        clearable
+                        @change="handleQuery"/>
+        <span class="search_title ml10">浜у搧澶х被锛�</span>
+        <el-input v-model="searchForm.productName"
+                  style="width: 240px"
+                  placeholder="璇疯緭鍏�"
+                  clearable/>
+        <span class="search_title ml10">鏉ユ簮锛�</span>
+        <el-select v-model="searchForm.recordType"
+                  style="width: 240px"
+                  placeholder="璇烽�夋嫨"
+                  clearable>
+          <el-option v-for="item in stockRecordTypeOptions"
+                     :key="item.value"
+                     :label="item.label"
+                     :value="item.value"/>
+        </el-select>
+        <el-button type="primary"
+                   @click="handleQuery"
+                   style="margin-left: 10px">鎼滅储
+        </el-button>
+      </div>
+      <div>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="danger"
+                   plain
+                   @click="handleDelete">鍒犻櫎
+        </el-button>
+      </div>
+    </div>
+    <div class="table_list">
+      <el-table :data="tableData"
+                border
+                v-loading="tableLoading"
+                @selection-change="handleSelectionChange"
+                :expand-row-keys="expandedRowKeys"
+                :row-key="row => row.id"
+                style="width: 100%"
+                height="calc(100vh - 18.5em)">
+        <el-table-column align="center"
+                         type="selection"
+                         width="55"/>
+        <el-table-column align="center"
+                         label="搴忓彿"
+                         type="index"
+                         width="60"/>
+        <el-table-column label="鍏ュ簱鎵规"
+                         prop="inboundBatches"
+                         width="280"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱鏃堕棿"
+                         prop="createTime"
+                         show-overflow-tooltip/>
+        <el-table-column label="浜у搧澶х被"
+                         prop="productName"
+                         show-overflow-tooltip/>
+        <el-table-column label="瑙勬牸鍨嬪彿"
+                         prop="model"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍗曚綅"
+                         prop="unit"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱鏁伴噺"
+                         prop="stockInNum"
+                         show-overflow-tooltip/>
+        <el-table-column label="鍏ュ簱浜�"
+                         prop="createBy"
+                         show-overflow-tooltip/>
+        <el-table-column label="鏉ユ簮"
+                         prop="recordType"
+                         show-overflow-tooltip>
+          <template #default="scope">
+            {{ getRecordType(scope.row.recordType) }}
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination v-show="total > 0"
+                  :total="total"
+                  layout="total, sizes, prev, pager, next, jumper"
+                  :page="page.current"
+                  :limit="page.size"
+                  @pagination="pageProductChange"/>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import pagination from "@/components/PIMTable/Pagination.vue";
+import {
+  ref,
+  reactive,
+  toRefs,
+  onMounted,
+  getCurrentInstance,
+} from "vue";
+import {ElMessageBox} from "element-plus";
+import {
+  getStockInRecordListPage,
+  batchDeleteStockInRecords,
+} from "@/api/inventoryManagement/stockInRecord.js";
+import {
+  findAllUnQualifiedStockInRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+
+const {proxy} = getCurrentInstance();
+
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+// 鏉ユ簮绫诲瀷閫夐」
+const stockRecordTypeOptions = ref([]);
+const page = reactive({
+  current: 1,
+  size: 10,
+});
+const total = ref(0);
+
+const data = reactive({
+  searchForm: {
+    productName: "",
+    timeStr: "",
+    recordType: "",
+    rootName: "杈呮潗"
+  },
+});
+const {searchForm} = toRefs(data);
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+
+const getRecordType = (recordType) => {
+  return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
+}
+
+const pageProductChange = obj => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+
+const getList = () => {
+  tableLoading.value = true;
+  const params = {...page};
+  params.timeStr = searchForm.value.timeStr;
+  params.productName = searchForm.value.productName;
+  params.recordType = searchForm.value.recordType;
+  params.rootName = searchForm.value.rootName;
+  getStockInRecordListPage(params)
+      .then(res => {
+        tableData.value = res.data.records;
+        total.value = res.data.total || 0;
+      }).finally(() => {
+    tableLoading.value = false;
+  })
+};
+
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+  findAllUnQualifiedStockInRecordTypeOptions()
+      .then(res => {
+        stockRecordTypeOptions.value = res.data;
+      })
+}
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = selection => {
+  selectedRows.value = selection.filter(item => item.id);
+};
+
+const expandedRowKeys = ref([]);
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        proxy.download("/stockInRecord/exportStockInRecord", {rootName: searchForm.value.rootName}, "杈呮潗鍏ュ簱.xlsx");
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  const ids = selectedRows.value.map(item => item.id);
+
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        batchDeleteStockInRecords(ids)
+            .then(() => {
+              proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+              getList();
+            })
+            .catch(() => {
+              proxy.$modal.msgError("鍒犻櫎澶辫触");
+            });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+
+onMounted(() => {
+  getList();
+  fetchStockRecordTypeOptions();
+});
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/inventoryManagement/receiptManagement/index.vue b/src/views/inventoryManagement/receiptManagement/index.vue
index 8ca110f..38af0ba 100644
--- a/src/views/inventoryManagement/receiptManagement/index.vue
+++ b/src/views/inventoryManagement/receiptManagement/index.vue
@@ -1,36 +1,49 @@
 <template>
   <div class="app-container">
     <el-tabs v-model="activeTab" @tab-change="handleTabChange">
-      <el-tab-pane v-for="tab in tabs"
-                   :label="tab.label"
-                   :name="tab.name"
-                   :key="tab.name">
-        <record :type="tab.type" v-if="activeTab === tab.name" />
+      <el-tab-pane
+          v-for="tab in tabs"
+          :label="tab.label"
+          :name="tab.name"
+          :key="tab.name"
+      >
+        <component
+            :is="tab.component"
+            v-if="activeTab === tab.name"
+            :stock-type="tab.name"
+        />
       </el-tab-pane>
     </el-tabs>
   </div>
 </template>
 
 <script setup>
-import Record from "@/views/inventoryManagement/receiptManagement/Record.vue";
+import { ref, shallowRef } from 'vue'
+import QualifiedRecord from "@/views/inventoryManagement/receiptManagement/Qualified.vue";
+import UnqualifiedRecord from "@/views/inventoryManagement/receiptManagement/Unqualified.vue";
+import RawMaterialRecord from "@/views/inventoryManagement/receiptManagement/RawMaterial.vue"
 
 const activeTab = ref('qualified')
-const type = ref(0)
-const tabs = ref([
+
+const tabs = shallowRef([
   {
-    label: '鍚堟牸鍏ュ簱',
+    label: '鎴愬搧鍏ュ簱',
     name: 'qualified',
-    type: '0'
+    component: QualifiedRecord
   },
   {
-    label: '涓嶅悎鏍煎叆搴�',
-    name: 'unqualified',
-    type: '1'
+    label: '杈呮潗鍏ュ簱',
+    name: 'assistant',
+    component: UnqualifiedRecord
+  },
+  {
+    label: '鍘熸潗鏂欏叆搴�',
+    name: 'rawMaterial',
+    component: RawMaterialRecord
   }
 ])
 
 const handleTabChange = (tabName) => {
   activeTab.value = tabName;
-  type.value = tabName === 'qualified' ? 0 : 1
 }
 </script>

--
Gitblit v1.9.3