From 3ea1ff641e1c680a5a1727fb4034797bfe65d93e Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期三, 18 三月 2026 15:29:17 +0800
Subject: [PATCH] fix: 质量、耗材物流

---
 src/pages.json                                                |   21 
 src/pages/inventoryManagement/stockManagement/add.vue         |   16 
 src/pages/qualityManagement/InspectItem/index.vue             |   22 
 src/pages/inventoryManagement/receiptManagement/view.vue      |   13 
 src/pages/consumablesLogistics/dispatchLog/index.vue          |   59 -
 src/pages/consumablesLogistics/receiptManagement/Record.vue   |    9 
 src/pages/qualityManagement/rawMaterial/form.vue              |  418 +++++++++++
 src/pages/qualityManagement/rawMaterial/index.vue             |   50 +
 src/pages/index.vue                                           |   60 -
 src/pages/inventoryManagement/receiptManagement/index.vue     |   70 -
 src/pages/consumablesLogistics/receiptManagement/index.vue    |   59 -
 src/pages/inventoryManagement/dispatchLog/view.vue            |   13 
 src/pages/qualityManagement/nonconformingManagement/index.vue |  457 +++++++----
 src/pages/inventoryManagement/stockManagement/index.vue       |   70 -
 src/pages/consumablesLogistics/dispatchLog/view.vue           |    9 
 src/pages/consumablesLogistics/stockManagement/subtract.vue   |   22 
 src/pages/inventoryManagement/stockManagement/subtract.vue    |   10 
 src/pages/consumablesLogistics/stockManagement/view.vue       |    7 
 /dev/null                                                     |   91 --
 src/pages/consumablesLogistics/stockManagement/add.vue        |   14 
 src/pages/qualityManagement/nonconformingManagement/form.vue  |  458 ++++++++++++
 src/pages/consumablesLogistics/receiptManagement/view.vue     |    9 
 src/pages/consumablesLogistics/stockManagement/index.vue      |   45 -
 src/pages/consumablesLogistics/dispatchLog/Record.vue         |    9 
 src/pages/inventoryManagement/dispatchLog/index.vue           |   59 -
 src/pages/qualityManagement/rawMaterial/files.vue             |  159 ++++
 26 files changed, 1,528 insertions(+), 701 deletions(-)

diff --git a/src/pages.json b/src/pages.json
index 4d5fa2b..5c83101 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -1142,6 +1142,13 @@
       }
     },
     {
+      "path": "pages/qualityManagement/nonconformingManagement/form",
+      "style": {
+        "navigationBarTitleText": "涓嶅悎鏍煎搧绠$悊",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/qualityManagement/rawMaterial/index",
       "style": {
         "navigationBarTitleText": "鍘熸潗鏂�",
@@ -1149,6 +1156,20 @@
       }
     },
     {
+      "path": "pages/qualityManagement/rawMaterial/form",
+      "style": {
+        "navigationBarTitleText": "鍘熸枡妫�",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/qualityManagement/rawMaterial/files",
+      "style": {
+        "navigationBarTitleText": "闄勪欢绠$悊",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/qualityManagement/visualization/qualityDashboard",
       "style": {
         "navigationBarTitleText": "璐ㄩ噺鐪嬫澘",
diff --git a/src/pages/consumablesLogistics/dispatchLog/Record.vue b/src/pages/consumablesLogistics/dispatchLog/Record.vue
index a4afc5e..868f7ed 100644
--- a/src/pages/consumablesLogistics/dispatchLog/Record.vue
+++ b/src/pages/consumablesLogistics/dispatchLog/Record.vue
@@ -86,7 +86,6 @@
 } from "@/api/consumablesLogistics/consumablesOutRecord.js";
 import {
   findAllQualifiedStockOutRecordTypeOptions,
-  findAllUnQualifiedStockOutRecordTypeOptions,
 } from "@/api/basicData/enum.js";
 
 const props = defineProps({
@@ -122,11 +121,7 @@
 };
 
 const fetchStockRecordTypeOptions = () => {
-  const api =
-    props.type === "1"
-      ? findAllUnQualifiedStockOutRecordTypeOptions
-      : findAllQualifiedStockOutRecordTypeOptions;
-  api()
+  findAllQualifiedStockOutRecordTypeOptions()
     .then((res) => {
       stockRecordTypeOptions.value = res.data || [];
     })
@@ -148,7 +143,7 @@
 
 const getList = () => {
   tableLoading.value = true;
-  getConsumablesOutRecordPage({ ...searchForm.value, ...page, type: props.type })
+  getConsumablesOutRecordPage({ ...searchForm.value, ...page, type: "0" })
     .then(res => {
       tableData.value = res?.data?.records || [];
       total.value = res?.data?.total || 0;
diff --git a/src/pages/consumablesLogistics/dispatchLog/index.vue b/src/pages/consumablesLogistics/dispatchLog/index.vue
index 132494f..11d524e 100644
--- a/src/pages/consumablesLogistics/dispatchLog/index.vue
+++ b/src/pages/consumablesLogistics/dispatchLog/index.vue
@@ -1,17 +1,6 @@
 <template>
   <view class="dispatch-page">
     <PageHeader title="鍑哄簱鍙拌处" @back="goBack" />
-    <view class="tabs-wrap">
-      <view
-        v-for="tab in tabs"
-        :key="tab.name"
-        class="tab-item"
-        :class="{ active: activeTab === tab.name }"
-        @click="activeTab = tab.name"
-      >
-        <text>{{ tab.label }}</text>
-      </view>
-    </view>
     <view class="search-section">
       <view class="search-row">
         <view class="search-input-wrap">
@@ -63,26 +52,20 @@
 </template>
 
 <script setup>
-import { reactive, ref, toRefs, watch } from "vue";
+import { reactive, ref, toRefs } from "vue";
 import { onReachBottom, onShow } from "@dcloudio/uni-app";
 import PageHeader from "@/components/PageHeader.vue";
 import { getConsumablesOutRecordPage, delConsumablesOutRecord } from "@/api/consumablesLogistics/consumablesOutRecord.js";
-import { findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions } from "@/api/basicData/enum.js";
+import { findAllQualifiedStockOutRecordTypeOptions } from "@/api/basicData/enum.js";
 
-const activeTab = ref("qualified");
 const stockRecordTypeOptions = ref([]);
-const tabs = [
-  { label: "鍚堟牸鍑哄簱", name: "qualified", type: "0" },
-  { label: "涓嶅悎鏍煎嚭搴�", name: "unqualified", type: "1" },
-];
 const tableData = ref([]);
 const total = ref(0);
 const loadStatus = ref("loadmore");
 const page = reactive({ current: 1, size: 20 });
 const data = reactive({ searchForm: { productName: "" } });
 const { searchForm } = toRefs(data);
-
-const currentType = () => tabs.find((t) => t.name === activeTab.value)?.type || "0";
+const currentType = () => "0";
 
 function getRecordType(recordType) {
   if (recordType == null || recordType === "") return "";
@@ -90,11 +73,7 @@
 }
 
 function fetchRecordTypeOptions() {
-  const api =
-    currentType() === "1"
-      ? findAllUnQualifiedStockOutRecordTypeOptions
-      : findAllQualifiedStockOutRecordTypeOptions;
-  api()
+  findAllQualifiedStockOutRecordTypeOptions()
     .then((res) => {
       const list = res.data != null ? res.data : res;
       stockRecordTypeOptions.value = Array.isArray(list) ? list : [];
@@ -143,13 +122,6 @@
   getList();
 };
 
-watch(activeTab, () => {
-  page.current = 1;
-  loadStatus.value = "loadmore";
-  stockRecordTypeOptions.value = [];
-  getList();
-});
-
 const handleQuery = () => {
   page.current = 1;
   loadStatus.value = "loadmore";
@@ -163,7 +135,7 @@
       "dispatchDetailItem",
       JSON.stringify({
         item,
-        type: currentType(),
+        type: "0",
       })
     );
   } catch (e) {}
@@ -198,9 +170,6 @@
 
 <style lang="scss" scoped>
 .dispatch-page { min-height: 100vh; background: #f5f5f5; padding-bottom: 40rpx; }
-.tabs-wrap { display: flex; background: #fff; padding: 24rpx; gap: 24rpx; }
-.tab-item { flex: 1; text-align: center; padding: 20rpx; border-radius: 12rpx; background: #f0f0f0; font-size: 28rpx; color: #666; }
-.tab-item.active { background: #2979ff; color: #fff; }
 .search-section { background: #fff; margin: 24rpx; padding: 24rpx; border-radius: 16rpx; }
 .search-row { display: flex; align-items: center; }
 .search-input-wrap { flex: 1; margin-right: 20rpx; min-width: 0; }
@@ -216,8 +185,22 @@
 .card-body .l { color: #666; }
 .card-body .r { color: #333; }
 .card-body .r.highlight { color: #2979ff; font-weight: 500; }
-.card-actions { display: flex; justify-content: flex-end; margin-top: 12rpx; }
-.btn-delete { color: #f56c6c; font-size: 28rpx; }
+.card-actions {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin-top: 16rpx;
+  padding-top: 16rpx;
+  border-top: 1rpx solid #eee;
+}
+.btn-delete {
+  color: #f56c6c;
+  font-size: 28rpx;
+  padding: 12rpx 36rpx;
+  border-radius: 999rpx;
+  border: 1rpx solid rgba(245, 108, 108, 0.55);
+  background: rgba(245, 108, 108, 0.08);
+}
 .no-data { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; }
 .load-more-wrap { padding: 24rpx 24rpx 8rpx; }
 </style>
diff --git a/src/pages/consumablesLogistics/dispatchLog/view.vue b/src/pages/consumablesLogistics/dispatchLog/view.vue
index 0008348..546c134 100644
--- a/src/pages/consumablesLogistics/dispatchLog/view.vue
+++ b/src/pages/consumablesLogistics/dispatchLog/view.vue
@@ -92,7 +92,7 @@
 import { ref } from "vue";
 import { onLoad } from "@dcloudio/uni-app";
 import PageHeader from "@/components/PageHeader.vue";
-import { findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions } from "@/api/basicData/enum.js";
+import { findAllQualifiedStockOutRecordTypeOptions } from "@/api/basicData/enum.js";
 
 const detail = ref(null);
 const loading = ref(true);
@@ -126,9 +126,7 @@
 }
 
 function fetchRecordTypeOptions(type) {
-  const api =
-    type === "1" ? findAllUnQualifiedStockOutRecordTypeOptions : findAllQualifiedStockOutRecordTypeOptions;
-  api()
+  findAllQualifiedStockOutRecordTypeOptions()
     .then((res) => {
       const data = res.data != null ? res.data : res;
       stockRecordTypeOptions.value = Array.isArray(data) ? data : [];
@@ -144,9 +142,8 @@
     try {
       const payload = typeof cached === "string" ? JSON.parse(cached) : cached;
       const item = payload && payload.item != null ? payload.item : payload;
-      const type = payload && payload.type != null ? payload.type : "0";
       detail.value = normalizeDetail({ ...item, index: 1 });
-      fetchRecordTypeOptions(type);
+      fetchRecordTypeOptions("0");
       uni.removeStorageSync("dispatchDetailItem");
     } catch (e) {
       uni.removeStorageSync("dispatchDetailItem");
diff --git a/src/pages/consumablesLogistics/receiptManagement/Record.vue b/src/pages/consumablesLogistics/receiptManagement/Record.vue
index 9770be2..29cce52 100644
--- a/src/pages/consumablesLogistics/receiptManagement/Record.vue
+++ b/src/pages/consumablesLogistics/receiptManagement/Record.vue
@@ -86,7 +86,6 @@
 } from "@/api/consumablesLogistics/consumablesInRecord.js";
 import {
   findAllQualifiedStockInRecordTypeOptions,
-  findAllUnQualifiedStockInRecordTypeOptions,
 } from "@/api/basicData/enum.js";
 
 const props = defineProps({
@@ -122,11 +121,7 @@
 };
 
 const fetchStockRecordTypeOptions = () => {
-  const api =
-    props.type === "1"
-      ? findAllUnQualifiedStockInRecordTypeOptions
-      : findAllQualifiedStockInRecordTypeOptions;
-  api()
+  findAllQualifiedStockInRecordTypeOptions()
     .then((res) => {
       stockRecordTypeOptions.value = res.data || [];
     })
@@ -148,7 +143,7 @@
 
 const getList = () => {
   tableLoading.value = true;
-  getConsumablesInRecordListPage({ ...searchForm.value, ...page, type: props.type })
+  getConsumablesInRecordListPage({ ...searchForm.value, ...page, type: "0" })
     .then(res => {
       tableData.value = res?.data?.records || [];
       total.value = res?.data?.total || 0;
diff --git a/src/pages/consumablesLogistics/receiptManagement/index.vue b/src/pages/consumablesLogistics/receiptManagement/index.vue
index db0f94e..9a515e0 100644
--- a/src/pages/consumablesLogistics/receiptManagement/index.vue
+++ b/src/pages/consumablesLogistics/receiptManagement/index.vue
@@ -1,17 +1,6 @@
 <template>
   <view class="receipt-page">
     <PageHeader title="鍏ュ簱绠$悊" @back="goBack" />
-    <view class="tabs-wrap">
-      <view
-        v-for="tab in tabs"
-        :key="tab.name"
-        class="tab-item"
-        :class="{ active: activeTab === tab.name }"
-        @click="activeTab = tab.name"
-      >
-        <text>{{ tab.label }}</text>
-      </view>
-    </view>
     <view class="search-section">
       <view class="search-row">
         <view class="search-input-wrap">
@@ -58,26 +47,20 @@
 </template>
 
 <script setup>
-import { reactive, ref, toRefs, watch } from "vue";
+import { reactive, ref, toRefs } from "vue";
 import { onReachBottom, onShow } from "@dcloudio/uni-app";
 import PageHeader from "@/components/PageHeader.vue";
 import request from "@/utils/request";
-import { findAllQualifiedStockInRecordTypeOptions, findAllUnQualifiedStockInRecordTypeOptions } from "@/api/basicData/enum.js";
+import { findAllQualifiedStockInRecordTypeOptions } from "@/api/basicData/enum.js";
 
-const activeTab = ref("qualified");
 const stockRecordTypeOptions = ref([]);
-const tabs = [
-  { label: "鍚堟牸鍏ュ簱", name: "qualified", type: "0" },
-  { label: "涓嶅悎鏍煎叆搴�", name: "unqualified", type: "1" },
-];
 const tableData = ref([]);
 const total = ref(0);
 const loadStatus = ref("loadmore");
 const page = reactive({ current: 1, size: 4 });
 const data = reactive({ searchForm: { productName: "" } });
 const { searchForm } = toRefs(data);
-
-const currentType = () => tabs.find((t) => t.name === activeTab.value)?.type || "0";
+const currentType = () => "0";
 
 function getRecordType(recordType) {
   if (recordType == null || recordType === "") return "";
@@ -85,11 +68,7 @@
 }
 
 function fetchRecordTypeOptions() {
-  const api =
-    currentType() === "1"
-      ? findAllUnQualifiedStockInRecordTypeOptions
-      : findAllQualifiedStockInRecordTypeOptions;
-  api()
+  findAllQualifiedStockInRecordTypeOptions()
     .then((res) => {
       const data = res.data != null ? res.data : res;
       stockRecordTypeOptions.value = Array.isArray(data) ? data : [];
@@ -142,13 +121,6 @@
   getList();
 };
 
-watch(activeTab, () => {
-  page.current = 1;
-  loadStatus.value = "loadmore";
-  stockRecordTypeOptions.value = [];
-  getList();
-});
-
 const handleQuery = () => {
   page.current = 1;
   loadStatus.value = "loadmore";
@@ -162,7 +134,7 @@
       "receiptDetailItem",
       JSON.stringify({
         item,
-        type: currentType(),
+        type: "0",
       })
     );
   } catch (e) {}
@@ -206,9 +178,6 @@
 
 <style lang="scss" scoped>
 .receipt-page { min-height: 100vh; background: #f5f5f5; padding-bottom: 40rpx; }
-.tabs-wrap { display: flex; background: #fff; padding: 24rpx; gap: 24rpx; }
-.tab-item { flex: 1; text-align: center; padding: 20rpx; border-radius: 12rpx; background: #f0f0f0; font-size: 28rpx; color: #666; }
-.tab-item.active { background: #2979ff; color: #fff; }
 .search-section { background: #fff; margin: 24rpx; padding: 24rpx; border-radius: 16rpx; }
 .search-row { display: flex; align-items: center; }
 .search-input-wrap { flex: 1; margin-right: 20rpx; min-width: 0; }
@@ -224,8 +193,22 @@
 .card-body .l { color: #666; }
 .card-body .r { color: #333; }
 .card-body .r.highlight { color: #2979ff; font-weight: 500; }
-.card-actions { display: flex; justify-content: flex-end; margin-top: 12rpx; }
-.btn-delete { color: #f56c6c; font-size: 28rpx; }
+.card-actions {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin-top: 16rpx;
+  padding-top: 16rpx;
+  border-top: 1rpx solid #eee;
+}
+.btn-delete {
+  color: #f56c6c;
+  font-size: 28rpx;
+  padding: 12rpx 36rpx;
+  border-radius: 999rpx;
+  border: 1rpx solid rgba(245, 108, 108, 0.55);
+  background: rgba(245, 108, 108, 0.08);
+}
 .no-data { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; }
 .load-more-wrap { padding: 24rpx 24rpx 8rpx; }
 </style>
diff --git a/src/pages/consumablesLogistics/receiptManagement/view.vue b/src/pages/consumablesLogistics/receiptManagement/view.vue
index 180eb9a..d603419 100644
--- a/src/pages/consumablesLogistics/receiptManagement/view.vue
+++ b/src/pages/consumablesLogistics/receiptManagement/view.vue
@@ -92,7 +92,7 @@
 import { ref } from "vue";
 import { onLoad } from "@dcloudio/uni-app";
 import PageHeader from "@/components/PageHeader.vue";
-import { findAllQualifiedStockInRecordTypeOptions, findAllUnQualifiedStockInRecordTypeOptions } from "@/api/basicData/enum.js";
+import { findAllQualifiedStockInRecordTypeOptions } from "@/api/basicData/enum.js";
 
 const detail = ref(null);
 const loading = ref(true);
@@ -126,9 +126,7 @@
 }
 
 function fetchRecordTypeOptions(type) {
-  const api =
-    type === "1" ? findAllUnQualifiedStockInRecordTypeOptions : findAllQualifiedStockInRecordTypeOptions;
-  api()
+  findAllQualifiedStockInRecordTypeOptions()
     .then((res) => {
       const data = res.data != null ? res.data : res;
       stockRecordTypeOptions.value = Array.isArray(data) ? data : [];
@@ -144,9 +142,8 @@
     try {
       const payload = typeof cached === "string" ? JSON.parse(cached) : cached;
       const item = payload && payload.item != null ? payload.item : payload;
-      const type = payload && payload.type != null ? payload.type : "0";
       detail.value = normalizeDetail({ ...item, index: 1 });
-      fetchRecordTypeOptions(type);
+      fetchRecordTypeOptions("0");
       uni.removeStorageSync("receiptDetailItem");
     } catch (e) {
       uni.removeStorageSync("receiptDetailItem");
diff --git a/src/pages/consumablesLogistics/stockManagement/Unqualified.vue b/src/pages/consumablesLogistics/stockManagement/Unqualified.vue
deleted file mode 100644
index 76b193e..0000000
--- a/src/pages/consumablesLogistics/stockManagement/Unqualified.vue
+++ /dev/null
@@ -1,91 +0,0 @@
-<template>
-  <div class="app-container">
-    <div class="search_form">
-      <div>
-        <span class="search_title ml10">浜у搧鍚嶇О锛�</span>
-        <el-input
-          v-model="searchForm.productName"
-          style="width: 240px"
-          placeholder="璇疯緭鍏�"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button>
-      </div>
-    </div>
-
-    <div class="table_list">
-      <el-table
-        :data="tableData"
-        border
-        v-loading="tableLoading"
-        style="width: 100%"
-        height="calc(100vh - 18.5em)"
-      >
-        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-        <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="180" show-overflow-tooltip />
-        <el-table-column label="瑙勬牸鍨嬪彿" prop="model" min-width="160" show-overflow-tooltip />
-        <el-table-column label="鍗曚綅" prop="unit" width="100" show-overflow-tooltip />
-        <el-table-column label="搴撳瓨鏁伴噺" prop="qualitity" width="110" show-overflow-tooltip />
-        <el-table-column label="鍐荤粨鏁伴噺" prop="lockedQuantity" width="110" show-overflow-tooltip />
-        <el-table-column label="鏈�杩戞洿鏂版椂闂�" prop="updateTime" width="180" show-overflow-tooltip />
-        <el-table-column label="澶囨敞" prop="remark" min-width="140" show-overflow-tooltip />
-      </el-table>
-
-      <Pagination
-        v-show="total > 0"
-        :total="total"
-        :page="page.current"
-        :limit="page.size"
-        @pagination="paginationChange"
-      />
-    </div>
-  </div>
-</template>
-
-<script setup>
-import { reactive, ref, toRefs } from "vue";
-import Pagination from "@/components/PIMTable/Pagination.vue";
-import { getConsumablesUninventoryListPage } from "@/api/consumablesLogistics/consumablesUninventory.js";
-
-const tableData = ref([]);
-const tableLoading = ref(false);
-
-const page = reactive({
-  current: 1,
-  size: 100,
-});
-const total = ref(0);
-
-const data = reactive({
-  searchForm: {
-    productName: "",
-  },
-});
-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;
-  getConsumablesUninventoryListPage({ ...searchForm.value, ...page })
-    .then(res => {
-      tableData.value = res?.data?.records || [];
-      total.value = res?.data?.total || 0;
-    })
-    .finally(() => {
-      tableLoading.value = false;
-    });
-};
-
-getList();
-</script>
diff --git a/src/pages/consumablesLogistics/stockManagement/add.vue b/src/pages/consumablesLogistics/stockManagement/add.vue
index ed14b7d..38f9711 100644
--- a/src/pages/consumablesLogistics/stockManagement/add.vue
+++ b/src/pages/consumablesLogistics/stockManagement/add.vue
@@ -23,7 +23,7 @@
         </view>
       </view>
 
-      <view v-if="isQualified" class="form-section">
+      <view class="form-section">
         <view class="section-title">杩囩淇℃伅</view>
         <view class="form-row">
           <text class="form-label">杞︾墝鍙�</text>
@@ -114,7 +114,6 @@
 import dayjs from "dayjs";
 import PageHeader from "@/components/PageHeader.vue";
 import { createConsumablesIn } from "@/api/consumablesLogistics/consumablesIn.js";
-import { createConsumablesUnInventory } from "@/api/consumablesLogistics/consumablesUninventory.js";
 import { productModelList } from "@/api/basicData/productModel.js";
 
 const form = reactive({
@@ -133,8 +132,8 @@
   remark: "",
 });
 
-const type = ref("0");
-const isQualified = computed(() => type.value === "0");
+const type = ref("0"); // 鍥哄畾鍚堟牸搴撳瓨
+const isQualified = computed(() => true);
 
 const showProductPopup = ref(false);
 const productQuery = reactive({
@@ -148,9 +147,7 @@
 const weighingDateValue = ref(Date.now());
 
 onLoad((options) => {
-  if (options && options.type != null) {
-    type.value = options.type;
-  }
+  type.value = "0";
 });
 
 const openProductSelector = () => {
@@ -238,8 +235,7 @@
     weighingOperator: form.weighingOperator,
     remark: form.remark,
   };
-  const api = isQualified.value ? createConsumablesIn : createConsumablesUnInventory;
-  api(payload)
+  createConsumablesIn(payload)
     .then(() => {
       uni.showToast({ title: "鏂板鎴愬姛", icon: "success" });
       setTimeout(() => {
diff --git a/src/pages/consumablesLogistics/stockManagement/index.vue b/src/pages/consumablesLogistics/stockManagement/index.vue
index 85021f6..a18ef5f 100644
--- a/src/pages/consumablesLogistics/stockManagement/index.vue
+++ b/src/pages/consumablesLogistics/stockManagement/index.vue
@@ -2,18 +2,6 @@
   <view class="stock-mgmt-page">
     <PageHeader title="搴撳瓨绠$悊" @back="goBack" />
 
-    <view class="tabs-wrap">
-      <view
-        v-for="tab in tabs"
-        :key="tab.name"
-        class="tab-item"
-        :class="{ active: activeTab === tab.name }"
-        @click="activeTab = tab.name"
-      >
-        <text>{{ tab.label }}</text>
-      </view>
-    </view>
-
     <view class="search-section">
       <view class="search-row">
         <view class="search-input-wrap">
@@ -102,17 +90,11 @@
 </template>
 
 <script setup>
-import { computed, reactive, ref, toRefs, watch } from "vue";
+import { computed, reactive, ref, toRefs } from "vue";
 import { onReachBottom, onShow } from "@dcloudio/uni-app";
 import PageHeader from "@/components/PageHeader.vue";
 import { frozenConsumablesIn, getConsumablesInListPage, thawConsumablesIn } from "@/api/consumablesLogistics/consumablesIn.js";
-import { frozenConsumablesUninventory, getConsumablesUninventoryListPage, thawConsumablesUninventory } from "@/api/consumablesLogistics/consumablesUninventory.js";
 
-const activeTab = ref("qualified");
-const tabs = [
-  { label: "鍚堟牸搴撳瓨", name: "qualified" },
-  { label: "涓嶅悎鏍煎簱瀛�", name: "unqualified" },
-];
 const tableData = ref([]);
 const total = ref(0);
 const loadStatus = ref("loadmore");
@@ -126,15 +108,13 @@
 });
 const { searchForm, quantityForm } = toRefs(data);
 
-const isQualified = () => activeTab.value === "qualified";
 const getList = () => {
   const isFirstPage = page.current === 1;
   if (isFirstPage) {
     uni.showLoading({ title: "鍔犺浇涓�...", mask: true });
   }
   const params = { ...page, productName: searchForm.value.productName };
-  const api = isQualified() ? getConsumablesInListPage : getConsumablesUninventoryListPage;
-  api(params)
+  getConsumablesInListPage(params)
     .then((res) => {
       uni.hideLoading();
       const records = res.data?.records || [];
@@ -163,12 +143,6 @@
   getList();
 };
 
-watch(activeTab, () => {
-  page.current = 1;
-  loadStatus.value = "loadmore";
-  getList();
-});
-
 const handleQuery = () => {
   page.current = 1;
   loadStatus.value = "loadmore";
@@ -176,9 +150,8 @@
 };
 
 const goAdd = () => {
-  const type = isQualified() ? "0" : "1";
   uni.navigateTo({
-    url: `/pages/consumablesLogistics/stockManagement/add?type=${type}`,
+    url: `/pages/consumablesLogistics/stockManagement/add?type=0`,
   });
 };
 
@@ -202,13 +175,12 @@
       "stockSubtractRecord",
       JSON.stringify({
         item: row,
-        type: isQualified() ? "0" : "1",
+        type: "0",
       })
     );
   } catch (e) {}
-  const typeParam = isQualified() ? "0" : "1";
   uni.navigateTo({
-    url: `/pages/consumablesLogistics/stockManagement/subtract?type=${typeParam}&id=${row.id}`,
+    url: `/pages/consumablesLogistics/stockManagement/subtract?type=0&id=${row.id}`,
   });
 };
 
@@ -243,9 +215,9 @@
   const base = { id, lockedQuantity: num };
   let promise;
   if (quantityOp.value === "frozen") {
-    promise = isQualified() ? frozenConsumablesIn(base) : frozenConsumablesUninventory(base);
+    promise = frozenConsumablesIn(base);
   } else {
-    promise = isQualified() ? thawConsumablesIn(base) : thawConsumablesUninventory(base);
+    promise = thawConsumablesIn(base);
   }
   promise
     .then(() => {
@@ -283,9 +255,6 @@
 
 <style lang="scss" scoped>
 .stock-mgmt-page { min-height: 100vh; background: #f5f5f5; padding-bottom: 120rpx; }
-.tabs-wrap { display: flex; background: #fff; padding: 24rpx; gap: 24rpx; }
-.tab-item { flex: 1; text-align: center; padding: 20rpx; border-radius: 12rpx; background: #f0f0f0; font-size: 28rpx; color: #666; }
-.tab-item.active { background: #2979ff; color: #fff; }
 .search-section { background: #fff; margin: 24rpx; padding: 24rpx; border-radius: 16rpx; }
 .search-row { display: flex; align-items: center; }
 .search-input-wrap { flex: 1; margin-right: 20rpx; min-width: 0; }
diff --git a/src/pages/consumablesLogistics/stockManagement/subtract.vue b/src/pages/consumablesLogistics/stockManagement/subtract.vue
index 81fea14..f8bd2f3 100644
--- a/src/pages/consumablesLogistics/stockManagement/subtract.vue
+++ b/src/pages/consumablesLogistics/stockManagement/subtract.vue
@@ -25,23 +25,23 @@
           <text class="form-label required">鍑哄簱鏁伴噺</text>
           <up-input v-model="form.stockOutNum" type="number" :placeholder="'鏈�澶�' + stockRecord.unLockedQuantity" />
         </view>
-        <view class="form-row" v-if="isQualified">
+        <view class="form-row">
           <text class="form-label">杞︾墝鍙�</text>
           <up-input v-model="form.licensePlateNo" placeholder="璇疯緭鍏ヨ溅鐗屽彿" />
         </view>
-        <view class="form-row" v-if="isQualified">
+        <view class="form-row">
           <text class="form-label">姣涢噸(鍚�)</text>
           <up-input v-model="form.grossWeight" type="number" placeholder="璇疯緭鍏ユ瘺閲�" />
         </view>
-        <view class="form-row" v-if="isQualified">
+        <view class="form-row">
           <text class="form-label">鐨噸(鍚�)</text>
           <up-input v-model="form.tareWeight" type="number" placeholder="璇疯緭鍏ョ毊閲�" />
         </view>
-        <view class="form-row" v-if="isQualified">
+        <view class="form-row">
           <text class="form-label">鍑�閲�(鍚�)</text>
           <up-input v-model="form.netWeight" type="number" disabled placeholder="鑷姩璁$畻" />
         </view>
-        <view class="form-row" v-if="isQualified">
+        <view class="form-row">
           <text class="form-label">杩囩鏃ユ湡</text>
           <view class="selector-trigger" @click="openWeighingDatePicker">
             <text class="selector-text" :class="{ placeholder: !form.weighingDate }">
@@ -50,7 +50,7 @@
             <up-icon name="calendar" size="16" color="#999"></up-icon>
           </view>
         </view>
-        <view class="form-row" v-if="isQualified">
+        <view class="form-row">
           <text class="form-label">杩囩鍛�</text>
           <up-input v-model="form.weighingOperator" placeholder="璇疯緭鍏ヨ繃纾呭憳" />
         </view>
@@ -83,10 +83,9 @@
 import dayjs from "dayjs";
 import PageHeader from "@/components/PageHeader.vue";
 import { subtractConsumablesIn } from "@/api/consumablesLogistics/consumablesIn.js";
-import { subtractConsumablesUnInventory } from "@/api/consumablesLogistics/consumablesUninventory.js";
 
 const type = ref("0");
-const isQualified = computed(() => type.value === "0");
+const isQualified = computed(() => true);
 
 const stockRecord = reactive({
   id: "",
@@ -110,9 +109,7 @@
 const weighingDateValue = ref(Date.now());
 
 onLoad((options) => {
-  if (options && options.type != null) {
-    type.value = options.type;
-  }
+  type.value = "0";
   const cached = uni.getStorageSync("stockSubtractRecord");
   if (cached) {
     try {
@@ -176,8 +173,7 @@
       return;
     }
   }
-  const api = isQualified.value ? subtractConsumablesIn : subtractConsumablesUnInventory;
-  api({
+  subtractConsumablesIn({
     id: stockRecord.id,
     stockOutNum: outNum,
     licensePlateNo: form.licensePlateNo,
diff --git a/src/pages/consumablesLogistics/stockManagement/view.vue b/src/pages/consumablesLogistics/stockManagement/view.vue
index fd68338..d809a93 100644
--- a/src/pages/consumablesLogistics/stockManagement/view.vue
+++ b/src/pages/consumablesLogistics/stockManagement/view.vue
@@ -64,7 +64,7 @@
 const detail = ref(null);
 const loading = ref(true);
 
-function normalizeDetail(raw, type) {
+function normalizeDetail(raw) {
   if (!raw) return null;
   const d = typeof raw === "object" ? raw : {};
   return {
@@ -76,7 +76,7 @@
     lockedQuantity: d.lockedQuantity,
     unLockedQuantity: d.unLockedQuantity ?? (d.qualitity - (d.lockedQuantity || 0)),
     updateTime: d.updateTime,
-    typeLabel: type === "1" ? "涓嶅悎鏍煎簱瀛�" : "鍚堟牸搴撳瓨",
+    typeLabel: "鍚堟牸搴撳瓨",
   };
 }
 
@@ -86,8 +86,7 @@
     try {
       const payload = typeof cached === "string" ? JSON.parse(cached) : cached;
       const item = payload && payload.item != null ? payload.item : payload;
-      const type = payload && payload.type != null ? payload.type : "0";
-      detail.value = normalizeDetail({ ...item, index: 1 }, type);
+      detail.value = normalizeDetail({ ...item, index: 1 });
       uni.removeStorageSync("stockDetailItem");
     } catch (e) {
       uni.removeStorageSync("stockDetailItem");
diff --git a/src/pages/index.vue b/src/pages/index.vue
index 5e09c1d..c27a0b7 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -426,18 +426,18 @@
 
   // 璐ㄩ噺绠$悊
   const qualityItems = reactive([
-    {
-      icon: "/static/images/icon/caigoutaizhang@2x.png",
-      label: "鍘熸潗鏂欐楠�",
-    },
-    {
-      icon: "/static/images/icon/caigoutaizhang@2x.png",
-      label: "杩囩▼妫�楠�",
-    },
-    {
-      icon: "/static/images/icon/caigoutaizhang@2x.png",
-      label: "鍑哄巶妫�楠�",
-    },
+    // {
+    //   icon: "/static/images/icon/caigoutaizhang@2x.png",
+    //   label: "鍘熸潗鏂欐楠�",
+    // },
+    // {
+    //   icon: "/static/images/icon/caigoutaizhang@2x.png",
+    //   label: "杩囩▼妫�楠�",
+    // },
+    // {
+    //   icon: "/static/images/icon/caigoutaizhang@2x.png",
+    //   label: "鍑哄巶妫�楠�",
+    // },
   ]);
   // 鍗忓悓鍔炲叕鍔熻兘鏁版嵁
   const collaborationItems = reactive([
@@ -949,7 +949,7 @@
           url: "/pages/qualityManagement/nonconformingManagement/index",
         });
         break;
-      case "鍘熸潗鏂�":
+      case "鍘熸枡妫�":
         uni.navigateTo({
           url: "/pages/qualityManagement/rawMaterial/index",
         });
@@ -1206,41 +1206,13 @@
     });
     purchaseItems.splice(0, purchaseItems.length, ...filteredPurchase);
 
-    // 杩囨护璐ㄩ噺绠$悊鑿滃崟
+    // 璐ㄩ噺绠$悊鑿滃崟锛氬浐瀹氬彧灞曠ず 3 涓叆鍙�
     const originalQuality = [
-      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "鍘熸潗鏂欐楠�" },
-      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "杩囩▼妫�楠�" },
-      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "鍑哄巶妫�楠�" },
       { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "妫�娴嬮」缁存姢" },
-      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "鎸囨爣缁存姢" },
-      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "鎸囨爣缁戝畾" },
+      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "鍘熸枡妫�" },
       { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "涓嶅悎鏍煎搧绠$悊" },
-      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "鍘熸潗鏂�" },
-      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "杩戞晥鏈熼��璐�" },
-      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "璐ㄩ噺鐪嬫澘" },
     ];
-    const hasAllowedTitleLike = label => {
-      if (allowedMenuTitles.has(label)) return true;
-      return Array.from(allowedMenuTitles).some(
-        title =>
-          typeof title === "string" &&
-          (title.includes(label) || label.includes(title))
-      );
-    };
-    const filteredQuality = originalQuality.filter(item => {
-      return hasAllowedTitleLike(item.label);
-    });
-    const hasQualityModulePermission = Array.from(allowedMenuTitles).some(
-      title =>
-        typeof title === "string" &&
-        (title.includes("璐ㄩ噺") || title.includes("妫�楠�"))
-    );
-    const finalQualityItems = filteredQuality.length
-      ? filteredQuality
-      : hasQualityModulePermission
-      ? originalQuality
-      : [];
-    qualityItems.splice(0, qualityItems.length, ...finalQualityItems);
+    qualityItems.splice(0, qualityItems.length, ...originalQuality);
 
     // 杩囨护瀹夊叏鐢熶骇鑿滃崟
     const originalSafety = [
diff --git a/src/pages/inventoryManagement/dispatchLog/index.vue b/src/pages/inventoryManagement/dispatchLog/index.vue
index 1ab16fe..702ccf5 100644
--- a/src/pages/inventoryManagement/dispatchLog/index.vue
+++ b/src/pages/inventoryManagement/dispatchLog/index.vue
@@ -2,19 +2,6 @@
   <view class="dispatch-page">
     <PageHeader title="鍑哄簱鍙拌处" @back="goBack" />
 
-    <!-- 鏍囩锛氬悎鏍煎嚭搴� / 涓嶅悎鏍煎嚭搴� -->
-    <view class="tabs-wrap">
-      <view
-        v-for="tab in tabs"
-        :key="tab.name"
-        class="tab-item"
-        :class="{ active: activeTab === tab.name }"
-        @click="activeTab = tab.name"
-      >
-        <text>{{ tab.label }}</text>
-      </view>
-    </view>
-
     <!-- 鎼滅储鍖哄煙 -->
     <view class="search-section">
       <view class="search-row">
@@ -78,21 +65,16 @@
 </template>
 
 <script setup>
-import { ref, reactive, toRefs, watch } from 'vue'
+import { ref, reactive, toRefs } from 'vue'
 import { onShow, onReachBottom } from '@dcloudio/uni-app'
 import PageHeader from '@/components/PageHeader.vue'
 import { getStockOutPage, delStockOut } from '@/api/inventoryManagement/stockOutRecord.js'
 import {
-  findAllQualifiedStockOutRecordTypeOptions,
-  findAllUnQualifiedStockOutRecordTypeOptions
+  findAllQualifiedStockOutRecordTypeOptions
 } from '@/api/basicData/enum.js'
 
-const activeTab = ref('qualified')
 const stockRecordTypeOptions = ref([])
-const tabs = [
-  { label: '鍚堟牸鍑哄簱', name: 'qualified', type: '0' },
-  { label: '涓嶅悎鏍煎嚭搴�', name: 'unqualified', type: '1' }
-]
+const currentType = () => '0'
 const tableData = ref([])
 const total = ref(0)
 const loadStatus = ref('loadmore')
@@ -104,18 +86,13 @@
 })
 const { searchForm } = toRefs(data)
 
-const currentType = () => tabs.find(t => t.name === activeTab.value)?.type || '0'
-
 function getRecordType(recordType) {
   if (recordType == null || recordType === '') return ''
   return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
 }
 
 function fetchRecordTypeOptions() {
-  const api = currentType() === '1'
-    ? findAllUnQualifiedStockOutRecordTypeOptions
-    : findAllQualifiedStockOutRecordTypeOptions
-  api()
+  findAllQualifiedStockOutRecordTypeOptions()
     .then(res => {
       const list = res.data != null ? res.data : res
       stockRecordTypeOptions.value = Array.isArray(list) ? list : []
@@ -168,13 +145,6 @@
   getList()
 }
 
-watch(activeTab, () => {
-  page.current = 1
-  loadStatus.value = 'loadmore'
-  stockRecordTypeOptions.value = []
-  getList()
-})
-
 const handleQuery = () => {
   page.current = 1
   loadStatus.value = 'loadmore'
@@ -186,7 +156,7 @@
   try {
     uni.setStorageSync('dispatchDetailItem', JSON.stringify({
       item,
-      type: currentType()
+      type: '0'
     }))
   } catch (e) {}
   uni.navigateTo({
@@ -224,25 +194,6 @@
   min-height: 100vh;
   background: #f5f5f5;
   padding-bottom: 40rpx;
-}
-.tabs-wrap {
-  display: flex;
-  background: #fff;
-  padding: 24rpx;
-  gap: 24rpx;
-}
-.tab-item {
-  flex: 1;
-  text-align: center;
-  padding: 20rpx;
-  border-radius: 12rpx;
-  background: #f0f0f0;
-  font-size: 28rpx;
-  color: #666;
-}
-.tab-item.active {
-  background: #2979ff;
-  color: #fff;
 }
 .search-section {
   background: #fff;
diff --git a/src/pages/inventoryManagement/dispatchLog/view.vue b/src/pages/inventoryManagement/dispatchLog/view.vue
index ea41965..e764082 100644
--- a/src/pages/inventoryManagement/dispatchLog/view.vue
+++ b/src/pages/inventoryManagement/dispatchLog/view.vue
@@ -95,8 +95,7 @@
 import { onLoad } from '@dcloudio/uni-app'
 import PageHeader from '@/components/PageHeader.vue'
 import {
-  findAllQualifiedStockOutRecordTypeOptions,
-  findAllUnQualifiedStockOutRecordTypeOptions
+  findAllQualifiedStockOutRecordTypeOptions
 } from '@/api/basicData/enum.js'
 
 const detail = ref(null)
@@ -130,11 +129,8 @@
   return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
 }
 
-function fetchRecordTypeOptions(type) {
-  const api = type === '1'
-    ? findAllUnQualifiedStockOutRecordTypeOptions
-    : findAllQualifiedStockOutRecordTypeOptions
-  api()
+function fetchRecordTypeOptions() {
+  findAllQualifiedStockOutRecordTypeOptions()
     .then(res => {
       const data = res.data != null ? res.data : res
       stockRecordTypeOptions.value = Array.isArray(data) ? data : []
@@ -150,9 +146,8 @@
     try {
       const payload = typeof cached === 'string' ? JSON.parse(cached) : cached
       const item = payload && payload.item != null ? payload.item : payload
-      const type = payload && payload.type != null ? payload.type : '0'
       detail.value = normalizeDetail({ ...item, index: 1 })
-      fetchRecordTypeOptions(type)
+      fetchRecordTypeOptions()
       uni.removeStorageSync('dispatchDetailItem')
     } catch (e) {
       uni.removeStorageSync('dispatchDetailItem')
diff --git a/src/pages/inventoryManagement/receiptManagement/index.vue b/src/pages/inventoryManagement/receiptManagement/index.vue
index 60a3ccc..e3625b6 100644
--- a/src/pages/inventoryManagement/receiptManagement/index.vue
+++ b/src/pages/inventoryManagement/receiptManagement/index.vue
@@ -2,19 +2,6 @@
   <view class="receipt-page">
     <PageHeader title="鍏ュ簱绠$悊" @back="goBack" />
 
-    <!-- 鏍囩锛氬悎鏍煎叆搴� / 涓嶅悎鏍煎叆搴� -->
-    <view class="tabs-wrap">
-      <view
-        v-for="tab in tabs"
-        :key="tab.name"
-        class="tab-item"
-        :class="{ active: activeTab === tab.name }"
-        @click="activeTab = tab.name"
-      >
-        <text>{{ tab.label }}</text>
-      </view>
-    </view>
-
     <!-- 鎼滅储鍖哄煙 -->
     <view class="search-section">
       <view class="search-row">
@@ -34,7 +21,7 @@
       </view>
     </view>
 
-    <!-- 鍒楄〃锛堝悎鏍�/涓嶅悎鏍煎叡鐢ㄦ帴鍙� type 鍖哄垎锛� -->
+    <!-- 鍒楄〃 -->
     <view class="list-section" v-if="activeTab !== 'custom'">
       <view v-if="tableData.length > 0">
         <view
@@ -73,7 +60,7 @@
 </template>
 
 <script setup>
-import { ref, reactive, toRefs, watch } from 'vue'
+import { ref, reactive, toRefs } from 'vue'
 import { onShow, onReachBottom } from '@dcloudio/uni-app'
 import PageHeader from '@/components/PageHeader.vue'
 import {
@@ -81,16 +68,11 @@
   batchDeleteStockInRecords
 } from '@/api/inventoryManagement/stockInRecord.js'
 import {
-  findAllQualifiedStockInRecordTypeOptions,
-  findAllUnQualifiedStockInRecordTypeOptions
+  findAllQualifiedStockInRecordTypeOptions
 } from '@/api/basicData/enum.js'
 
-const activeTab = ref('qualified')
 const stockRecordTypeOptions = ref([])
-const tabs = [
-  { label: '鍚堟牸鍏ュ簱', name: 'qualified', type: '0' },
-  { label: '涓嶅悎鏍煎叆搴�', name: 'unqualified', type: '1' }
-]
+const currentType = () => '0'
 
 const tableData = ref([])
 const total = ref(0)
@@ -104,18 +86,13 @@
 })
 const { searchForm } = toRefs(data)
 
-const currentType = () => tabs.find(t => t.name === activeTab.value)?.type || '0'
-
 function getRecordType(recordType) {
   if (recordType == null || recordType === '') return ''
   return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
 }
 
 function fetchRecordTypeOptions() {
-  const api = currentType() === '1'
-    ? findAllUnQualifiedStockInRecordTypeOptions
-    : findAllQualifiedStockInRecordTypeOptions
-  api()
+  findAllQualifiedStockInRecordTypeOptions()
     .then(res => {
       const data = res.data != null ? res.data : res
       stockRecordTypeOptions.value = Array.isArray(data) ? data : []
@@ -126,7 +103,6 @@
 }
 
 const getList = () => {
-  if (activeTab.value === 'custom') return
   const isFirstPage = page.current === 1
   if (isFirstPage) {
     uni.showLoading({ title: '鍔犺浇涓�...', mask: true })
@@ -170,13 +146,6 @@
   getList()
 }
 
-watch(activeTab, () => {
-  page.current = 1
-  loadStatus.value = 'loadmore'
-  stockRecordTypeOptions.value = []
-  getList()
-})
-
 const handleQuery = () => {
   page.current = 1
   loadStatus.value = 'loadmore'
@@ -188,7 +157,7 @@
   try {
     uni.setStorageSync('receiptDetailItem', JSON.stringify({
       item,
-      type: currentType()
+      type: '0'
     }))
   } catch (e) {}
   uni.navigateTo({
@@ -218,7 +187,7 @@
 const goBack = () => uni.navigateBack()
 
 onShow(() => {
-  if (activeTab.value !== 'custom') getList()
+  getList()
 })
 
 onReachBottom(() => {
@@ -231,25 +200,6 @@
   min-height: 100vh;
   background: #f5f5f5;
   padding-bottom: 40rpx;
-}
-.tabs-wrap {
-  display: flex;
-  background: #fff;
-  padding: 24rpx;
-  gap: 24rpx;
-}
-.tab-item {
-  flex: 1;
-  text-align: center;
-  padding: 20rpx;
-  border-radius: 12rpx;
-  background: #f0f0f0;
-  font-size: 28rpx;
-  color: #666;
-}
-.tab-item.active {
-  background: #2979ff;
-  color: #fff;
 }
 .search-section {
   background: #fff;
@@ -340,11 +290,17 @@
   display: flex;
   justify-content: center;
   align-items: center;
+  width: 100%;
+  text-align: center;
 }
 .btn-delete {
   font-size: 28rpx;
   color: #f56c6c;
   padding: 12rpx 32rpx;
+  margin: 0 auto;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
 }
 .no-data {
   text-align: center;
diff --git a/src/pages/inventoryManagement/receiptManagement/view.vue b/src/pages/inventoryManagement/receiptManagement/view.vue
index e5daea9..2833283 100644
--- a/src/pages/inventoryManagement/receiptManagement/view.vue
+++ b/src/pages/inventoryManagement/receiptManagement/view.vue
@@ -95,8 +95,7 @@
 import { onLoad } from '@dcloudio/uni-app'
 import PageHeader from '@/components/PageHeader.vue'
 import {
-  findAllQualifiedStockInRecordTypeOptions,
-  findAllUnQualifiedStockInRecordTypeOptions
+  findAllQualifiedStockInRecordTypeOptions
 } from '@/api/basicData/enum.js'
 
 const detail = ref(null)
@@ -131,11 +130,8 @@
   return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
 }
 
-function fetchRecordTypeOptions(type) {
-  const api = type === '1'
-    ? findAllUnQualifiedStockInRecordTypeOptions
-    : findAllQualifiedStockInRecordTypeOptions
-  api()
+function fetchRecordTypeOptions() {
+  findAllQualifiedStockInRecordTypeOptions()
     .then(res => {
       const data = res.data != null ? res.data : res
       stockRecordTypeOptions.value = Array.isArray(data) ? data : []
@@ -151,9 +147,8 @@
     try {
       const payload = typeof cached === 'string' ? JSON.parse(cached) : cached
       const item = payload && payload.item != null ? payload.item : payload
-      const type = payload && payload.type != null ? payload.type : '0'
       detail.value = normalizeDetail({ ...item, index: 1 })
-      fetchRecordTypeOptions(type)
+      fetchRecordTypeOptions()
       uni.removeStorageSync('receiptDetailItem')
     } catch (e) {
       uni.removeStorageSync('receiptDetailItem')
diff --git a/src/pages/inventoryManagement/stockManagement/add.vue b/src/pages/inventoryManagement/stockManagement/add.vue
index f8c698f..c27d958 100644
--- a/src/pages/inventoryManagement/stockManagement/add.vue
+++ b/src/pages/inventoryManagement/stockManagement/add.vue
@@ -23,8 +23,8 @@
         </view>
       </view>
 
-      <!-- 鍚堟牸搴撳瓨鏃舵樉绀鸿繃纾呯浉鍏冲瓧娈� -->
-      <view v-if="isQualified" class="form-section">
+      <!-- 杩囩鐩稿叧瀛楁 -->
+      <view class="form-section">
         <view class="section-title">杩囩淇℃伅</view>
         <view class="form-row">
           <text class="form-label">杞︾墝鍙�</text>
@@ -145,7 +145,6 @@
 import dayjs from 'dayjs'
 import PageHeader from '@/components/PageHeader.vue'
 import { createStockInventory } from '@/api/inventoryManagement/stockInventory.js'
-import { createStockUnInventory } from '@/api/inventoryManagement/stockUninventory.js'
 import { productModelList } from '@/api/basicData/productModel.js'
 
 const form = reactive({
@@ -165,8 +164,8 @@
   remark: ''
 })
 
-const type = ref('0') // 0 鍚堟牸搴撳瓨锛�1 涓嶅悎鏍煎簱瀛�
-const isQualified = computed(() => type.value === '0')
+const type = ref('0') // 鍥哄畾鍚堟牸搴撳瓨
+const isQualified = computed(() => true)
 
 const showProductPopup = ref(false)
 const productQuery = reactive({
@@ -180,9 +179,7 @@
 const weighingDateValue = ref(Date.now())
 
 onLoad((options) => {
-  if (options && options.type != null) {
-    type.value = options.type
-  }
+  type.value = '0'
 })
 
 const openProductSelector = () => {
@@ -286,8 +283,7 @@
     weighingOperator: form.weighingOperator,
     remark: form.remark
   }
-  const api = isQualified.value ? createStockInventory : createStockUnInventory
-  api(payload)
+  createStockInventory(payload)
     .then(() => {
       uni.showToast({ title: '鏂板鎴愬姛', icon: 'success' })
       setTimeout(() => {
diff --git a/src/pages/inventoryManagement/stockManagement/index.vue b/src/pages/inventoryManagement/stockManagement/index.vue
index e36fac0..3b707a7 100644
--- a/src/pages/inventoryManagement/stockManagement/index.vue
+++ b/src/pages/inventoryManagement/stockManagement/index.vue
@@ -2,19 +2,6 @@
   <view class="stock-mgmt-page">
     <PageHeader title="搴撳瓨绠$悊" @back="goBack" />
 
-    <!-- 鏍囩锛氬悎鏍煎簱瀛� / 涓嶅悎鏍煎簱瀛� -->
-    <view class="tabs-wrap">
-      <view
-        v-for="tab in tabs"
-        :key="tab.name"
-        class="tab-item"
-        :class="{ active: activeTab === tab.name }"
-        @click="activeTab = tab.name"
-      >
-        <text>{{ tab.label }}</text>
-      </view>
-    </view>
-
     <!-- 鎼滅储鍖哄煙 -->
     <view class="search-section">
       <view class="search-row">
@@ -107,7 +94,7 @@
 </template>
 
 <script setup>
-import { ref, reactive, toRefs, watch, computed } from 'vue'
+import { ref, reactive, toRefs, computed } from 'vue'
 import { onShow, onReachBottom } from '@dcloudio/uni-app'
 import PageHeader from '@/components/PageHeader.vue'
 import {
@@ -117,19 +104,7 @@
   frozenStockInventory,
   thawStockInventory
 } from '@/api/inventoryManagement/stockInventory.js'
-import {
-  getStockUninventoryListPage,
-  createStockUnInventory,
-  subtractStockUnInventory,
-  frozenStockUninventory,
-  thawStockUninventory
-} from '@/api/inventoryManagement/stockUninventory.js'
 
-const activeTab = ref('qualified')
-const tabs = [
-  { label: '鍚堟牸搴撳瓨', name: 'qualified' },
-  { label: '涓嶅悎鏍煎簱瀛�', name: 'unqualified' }
-]
 const tableData = ref([])
 const total = ref(0)
 const loadStatus = ref('loadmore') // loadmore | loading | nomore | error
@@ -143,15 +118,13 @@
 })
 const { searchForm, quantityForm } = toRefs(data)
 
-const isQualified = () => activeTab.value === 'qualified'
 const getList = () => {
   const isFirstPage = page.current === 1
   if (isFirstPage) {
     uni.showLoading({ title: '鍔犺浇涓�...', mask: true })
   }
   const params = { ...page, productName: searchForm.value.productName }
-  const api = isQualified() ? getStockInventoryListPage : getStockUninventoryListPage
-  api(params)
+  getStockInventoryListPage(params)
     .then(res => {
       uni.hideLoading()
       const records = res.data?.records || []
@@ -184,12 +157,6 @@
   getList()
 }
 
-watch(activeTab, () => {
-  page.current = 1
-  loadStatus.value = 'loadmore'
-  getList()
-})
-
 const handleQuery = () => {
   page.current = 1
   loadStatus.value = 'loadmore'
@@ -197,9 +164,8 @@
 }
 
 const goAdd = () => {
-  const type = isQualified() ? '0' : '1'
   uni.navigateTo({
-    url: `/pages/inventoryManagement/stockManagement/add?type=${type}`
+    url: `/pages/inventoryManagement/stockManagement/add?type=0`
   })
 }
 
@@ -220,12 +186,11 @@
   try {
     uni.setStorageSync('stockSubtractRecord', JSON.stringify({
       item: row,
-      type: isQualified() ? '0' : '1'
+      type: '0'
     }))
   } catch (e) {}
-  const typeParam = isQualified() ? '0' : '1'
   uni.navigateTo({
-    url: `/pages/inventoryManagement/stockManagement/subtract?type=${typeParam}&id=${row.id}`
+    url: `/pages/inventoryManagement/stockManagement/subtract?type=0&id=${row.id}`
   })
 }
 const openFrozen = (row) => {
@@ -256,9 +221,9 @@
   const base = { id, lockedQuantity: num }
   let promise
   if (quantityOp.value === 'frozen') {
-    promise = isQualified() ? frozenStockInventory(base) : frozenStockUninventory(base)
+    promise = frozenStockInventory(base)
   } else {
-    promise = isQualified() ? thawStockInventory(base) : thawStockUninventory(base)
+    promise = thawStockInventory(base)
   }
   promise.then(() => {
     uni.showToast({ title: '鎿嶄綔鎴愬姛', icon: 'success' })
@@ -272,7 +237,7 @@
   try {
     uni.setStorageSync('stockDetailItem', JSON.stringify({
       item,
-      type: isQualified() ? '0' : '1'
+      type: '0'
     }))
   } catch (e) {}
   if (!item.id) {
@@ -294,25 +259,6 @@
   min-height: 100vh;
   background: #f5f5f5;
   padding-bottom: 120rpx;
-}
-.tabs-wrap {
-  display: flex;
-  background: #fff;
-  padding: 24rpx;
-  gap: 24rpx;
-}
-.tab-item {
-  flex: 1;
-  text-align: center;
-  padding: 20rpx;
-  border-radius: 12rpx;
-  background: #f0f0f0;
-  font-size: 28rpx;
-  color: #666;
-}
-.tab-item.active {
-  background: #2979ff;
-  color: #fff;
 }
 .search-section {
   background: #fff;
diff --git a/src/pages/inventoryManagement/stockManagement/subtract.vue b/src/pages/inventoryManagement/stockManagement/subtract.vue
index 1a7ebf7..2452e04 100644
--- a/src/pages/inventoryManagement/stockManagement/subtract.vue
+++ b/src/pages/inventoryManagement/stockManagement/subtract.vue
@@ -92,7 +92,6 @@
 import dayjs from 'dayjs'
 import PageHeader from '@/components/PageHeader.vue'
 import { subtractStockInventory } from '@/api/inventoryManagement/stockInventory.js'
-import { subtractStockUnInventory } from '@/api/inventoryManagement/stockUninventory.js'
 
 const form = reactive({
   id: undefined,
@@ -124,7 +123,7 @@
   remark: ''
 })
 
-const type = ref('0') // 0 鍚堟牸搴撳瓨锛�1 涓嶅悎鏍煎簱瀛�
+const type = ref('0') // 鍥哄畾鍚堟牸搴撳瓨
 const showWeighingDatePicker = ref(false)
 const weighingDateValue = ref(Date.now())
 
@@ -135,9 +134,7 @@
 })
 
 onLoad((options) => {
-  if (options && options.type != null) {
-    type.value = options.type
-  }
+  type.value = '0'
   const cached = uni.getStorageSync('stockSubtractRecord')
   if (cached) {
     try {
@@ -195,8 +192,7 @@
     return
   }
   const payload = { ...form }
-  const api = type.value === '0' ? subtractStockInventory : subtractStockUnInventory
-  api(payload)
+  subtractStockInventory(payload)
     .then(() => {
       uni.showToast({ title: '鍑哄簱鎴愬姛', icon: 'success' })
       setTimeout(() => {
diff --git a/src/pages/qualityManagement/InspectItem/index.vue b/src/pages/qualityManagement/InspectItem/index.vue
index 92ae99c..822abb6 100644
--- a/src/pages/qualityManagement/InspectItem/index.vue
+++ b/src/pages/qualityManagement/InspectItem/index.vue
@@ -64,7 +64,7 @@
         <view class="dialog-header">
           <text class="dialog-title">{{ operationType === 'add' ? '鏂板妫�娴嬮」鐩�' : '淇敼妫�娴嬮」鐩�' }}</text>
         </view>
-        <up-form :model="form" ref="formRef" label-width="100" label-position="top">
+        <up-form :model="form" :rules="rules" ref="formRef" label-width="100" label-position="top">
           <up-form-item label="妫�娴嬮」鐩�" prop="name" required borderBottom>
             <up-input v-model="form.name" placeholder="璇疯緭鍏ユ娴嬮」鐩悕绉�" border="surround" />
           </up-form-item>
@@ -204,25 +204,27 @@
   dialogVisible.value = false;
 };
 
-const submitForm = () => {
-  formRef.value.validate().then(res => {
-    submitLoading.value = true;
-    qualityInspectItemSave(form).then(() => {
+const submitForm = async () => {
+  if (!formRef.value) return
+  const valid = await formRef.value.validate().catch(() => false)
+  if (!valid) return
+  submitLoading.value = true;
+  qualityInspectItemSave(form)
+    .then(() => {
       toast(operationType.value === 'add' ? '鏂板鎴愬姛' : '淇敼鎴愬姛');
       dialogVisible.value = false;
       handleQuery();
-    }).finally(() => {
+    })
+    .finally(() => {
       submitLoading.value = false;
     });
-  }).catch(errors => {
-    console.log('楠岃瘉澶辫触', errors);
-  });
 };
 
 const handleDelete = (row) => {
   showConfirm('纭鍒犻櫎璇ユ娴嬮」鐩悧锛�').then(res => {
     if (res.confirm) {
-      qualityInspectItemDelete({ id: row.id }).then(() => {
+      // 瀵归綈 PC 绔細鍒犻櫎鎺ュ彛鎺ユ敹 id 鏁扮粍
+      qualityInspectItemDelete([row.id]).then(() => {
         toast('鍒犻櫎鎴愬姛');
         handleQuery();
       });
diff --git a/src/pages/qualityManagement/nonconformingManagement/form.vue b/src/pages/qualityManagement/nonconformingManagement/form.vue
new file mode 100644
index 0000000..7acb67d
--- /dev/null
+++ b/src/pages/qualityManagement/nonconformingManagement/form.vue
@@ -0,0 +1,458 @@
+<template>
+  <view class="nonconforming-form-page">
+    <PageHeader :title="pageTitle" @back="goBack" />
+
+    <scroll-view scroll-y class="content-scroll">
+      <view class="form-section">
+        <view class="form-row">
+          <text class="form-label required">浜у搧鍚嶇О</text>
+          <view class="selector-trigger" @click="openProductSelector" :class="{ disabled: isEdit }">
+            <text class="selector-text" :class="{ placeholder: !form.productName }">
+              {{ form.productName || '璇烽�夋嫨' }}
+            </text>
+            <up-icon name="arrow-right" size="16" color="#999"></up-icon>
+          </view>
+        </view>
+        <view class="form-row">
+          <text class="form-label required">瑙勬牸鍨嬪彿</text>
+          <view class="selector-trigger" @click="openModelSelector" :class="{ disabled: !form.productId || isEdit }">
+            <text class="selector-text" :class="{ placeholder: !form.model }">
+              {{ form.model || '璇烽�夋嫨' }}
+            </text>
+            <up-icon name="arrow-right" size="16" color="#999"></up-icon>
+          </view>
+        </view>
+        <view class="form-row">
+          <text class="form-label">鍗曚綅</text>
+          <up-input v-model="form.unit" disabled placeholder="鑷姩甯﹀嚭" />
+        </view>
+        <view class="form-row">
+          <text class="form-label required">鎵瑰彿</text>
+          <up-input v-model="form.batchNo" placeholder="璇疯緭鍏�" />
+        </view>
+        <view class="form-row">
+          <text class="form-label required">妫�楠岀被鍨�</text>
+          <view class="selector-trigger" @click="showTypeSelect = true">
+            <text class="selector-text" :class="{ placeholder: form.checkType === undefined || form.checkType === '' }">
+              {{ checkTypeLabel || '璇烽�夋嫨' }}
+            </text>
+            <up-icon name="arrow-down" size="14" color="#999"></up-icon>
+          </view>
+        </view>
+        <view class="form-row">
+          <text class="form-label required">妫�楠屽憳</text>
+          <view class="selector-trigger" @click="showUserSelect = true">
+            <text class="selector-text" :class="{ placeholder: !form.checkName }">
+              {{ form.checkName || '璇烽�夋嫨' }}
+            </text>
+            <up-icon name="arrow-down" size="14" color="#999"></up-icon>
+          </view>
+        </view>
+        <view class="form-row">
+          <text class="form-label required">妫�娴嬫棩鏈�</text>
+          <view class="selector-trigger" @click="openCheckTimePicker">
+            <text class="selector-text" :class="{ placeholder: !form.checkTime }">
+              {{ form.checkTime || '璇烽�夋嫨' }}
+            </text>
+            <up-icon name="calendar" size="16" color="#999"></up-icon>
+          </view>
+        </view>
+        <view class="form-row">
+          <text class="form-label required">涓嶅悎鏍肩幇璞�</text>
+          <up-textarea v-model="form.defectivePhenomena" placeholder="璇疯緭鍏�" count border="surround" />
+        </view>
+      </view>
+
+      <view class="form-section">
+        <view class="section-title">榛樿澶勭悊淇℃伅</view>
+        <view class="form-row">
+          <text class="form-label required">澶勭悊缁撴灉</text>
+          <up-input :modelValue="dealResultLabel || '鎶ュ簾'" disabled />
+        </view>
+        <view class="form-row">
+          <text class="form-label">澶勭悊浜�</text>
+          <up-input v-model="form.dealName" placeholder="閫夊~" />
+        </view>
+        <view class="form-row">
+          <text class="form-label">澶勭悊鏃ユ湡</text>
+          <view class="selector-trigger" @click="openDealTimePicker">
+            <text class="selector-text" :class="{ placeholder: !form.dealTime }">
+              {{ form.dealTime || '璇烽�夋嫨' }}
+            </text>
+            <up-icon name="calendar" size="16" color="#999"></up-icon>
+          </view>
+        </view>
+      </view>
+    </scroll-view>
+
+    <view class="bottom-bar">
+      <view class="btn-submit" @click="handleSubmit" :class="{ disabled: submitting }">
+        {{ submitting ? '鎻愪氦涓�...' : '鎻愪氦' }}
+      </view>
+    </view>
+
+    <!-- 浜у搧閫夋嫨 -->
+    <up-popup :show="showProductPopup" mode="bottom" @close="showProductPopup = false">
+      <view class="popup">
+        <view class="popup-header">
+          <text class="popup-title">閫夋嫨浜у搧</text>
+        </view>
+        <scroll-view scroll-y class="popup-list">
+          <view
+            v-for="(item, idx) in productOptions"
+            :key="item.value || idx"
+            class="popup-item"
+            @click="selectProduct(item)"
+          >
+            <text class="popup-item-title">{{ item.label }}</text>
+          </view>
+          <view v-if="!productLoading && productOptions.length === 0" class="no-data">鏆傛棤鏁版嵁</view>
+        </scroll-view>
+      </view>
+    </up-popup>
+
+    <!-- 鍨嬪彿閫夋嫨 -->
+    <up-popup :show="showModelPopup" mode="bottom" @close="showModelPopup = false">
+      <view class="popup">
+        <view class="popup-header">
+          <text class="popup-title">閫夋嫨瑙勬牸鍨嬪彿</text>
+        </view>
+        <scroll-view scroll-y class="popup-list">
+          <view
+            v-for="(item, idx) in modelOptions"
+            :key="item.id || idx"
+            class="popup-item"
+            @click="selectModel(item)"
+          >
+            <view class="popup-item-row">
+              <text class="popup-item-title">{{ item.model }}</text>
+              <text class="popup-item-sub">{{ item.unit }}</text>
+            </view>
+          </view>
+          <view v-if="!modelLoading && modelOptions.length === 0" class="no-data">鏆傛棤鏁版嵁</view>
+        </scroll-view>
+      </view>
+    </up-popup>
+
+    <!-- 妫�楠岀被鍨� -->
+    <up-action-sheet
+      :actions="checkTypeActions"
+      :show="showTypeSelect"
+      @close="showTypeSelect = false"
+      @select="selectCheckType"
+      title="璇烽�夋嫨妫�楠岀被鍨�"
+    />
+
+    <!-- 妫�楠屽憳 -->
+    <up-action-sheet
+      :actions="userActions"
+      :show="showUserSelect"
+      @close="showUserSelect = false"
+      @select="selectUser"
+      title="璇烽�夋嫨妫�楠屽憳"
+    />
+
+    <!-- 鏃ユ湡閫夋嫨鍣細妫�娴嬫棩鏈� -->
+    <up-datetime-picker
+      :show="showCheckTimePicker"
+      v-model="checkTimeValue"
+      mode="date"
+      @confirm="confirmCheckTime"
+      @cancel="showCheckTimePicker = false"
+    />
+    <!-- 鏃ユ湡閫夋嫨鍣細澶勭悊鏃ユ湡 -->
+    <up-datetime-picker
+      :show="showDealTimePicker"
+      v-model="dealTimeValue"
+      mode="date"
+      @confirm="confirmDealTime"
+      @cancel="showDealTimePicker = false"
+    />
+  </view>
+</template>
+
+<script setup>
+import { computed, reactive, ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import dayjs from 'dayjs'
+import PageHeader from '@/components/PageHeader.vue'
+import { useDict } from '@/utils/dict'
+import { toast } from '@/utils/common'
+import { productTreeList, modelList } from '@/api/basicData/product.js'
+import { userListNoPage } from '@/api/system/user.js'
+import {
+  getQualityUnqualifiedInfo,
+  qualityUnqualifiedAdd,
+  qualityUnqualifiedUpdate
+} from '@/api/qualityManagement/nonconformingManagement.js'
+
+const pageType = ref('add') // add | edit
+const id = ref('')
+const submitting = ref(false)
+
+const isEdit = computed(() => pageType.value === 'edit')
+const pageTitle = computed(() => (isEdit.value ? '缂栬緫涓嶅悎鏍肩鐞�' : '鏂板涓嶅悎鏍肩鐞�'))
+
+const { rejection_handling } = useDict('rejection_handling')
+const dealResultLabel = computed(() => {
+  const list = rejection_handling?.value || []
+  const v = form.dealResult
+  return (list || []).find(it => String(it.value) === String(v))?.label || ''
+})
+const getScrapDealResultValue = () => {
+  const list = rejection_handling?.value || []
+  const scrap = (list || []).find(it => String(it?.label ?? '') === '鎶ュ簾')
+  return scrap?.value ?? ''
+}
+
+const form = reactive({
+  id: undefined,
+  productId: '',
+  productName: '',
+  productModelId: '',
+  model: '',
+  unit: '',
+  batchNo: '',
+  checkType: undefined,
+  checkName: '',
+  checkTime: '',
+  defectivePhenomena: '',
+  dealResult: '',
+  dealName: '',
+  dealTime: ''
+})
+
+// 閫夋嫨鍣ㄦ暟鎹�
+const showProductPopup = ref(false)
+const productLoading = ref(false)
+const productOptions = ref([])
+
+const showModelPopup = ref(false)
+const modelLoading = ref(false)
+const modelOptions = ref([])
+
+const showTypeSelect = ref(false)
+const checkTypeActions = [
+  { name: '鍏ュ巶妫�', value: 0 },
+  { name: '杞﹂棿妫�', value: 1 },
+  { name: '鍑哄巶妫�', value: 2 }
+]
+const checkTypeLabel = computed(() => {
+  const v = form.checkType
+  return checkTypeActions.find(it => String(it.value) === String(v))?.name || ''
+})
+
+const showUserSelect = ref(false)
+const userActions = ref([])
+
+const showCheckTimePicker = ref(false)
+const checkTimeValue = ref(Date.now())
+const showDealTimePicker = ref(false)
+const dealTimeValue = ref(Date.now())
+
+const loadProducts = async () => {
+  productLoading.value = true
+  try {
+    const res = await productTreeList()
+    const list =
+      (Array.isArray(res) ? res : null) ||
+      (Array.isArray(res?.data) ? res.data : null) ||
+      (Array.isArray(res?.records) ? res.records : null) ||
+      (Array.isArray(res?.data?.records) ? res.data.records : null) ||
+      []
+    // 浠呭彇鍙跺瓙鑺傜偣锛堝彲閫変骇鍝侊級锛涘苟杞负 action 鍒楄〃
+    const flat = []
+    const walk = (nodes) => {
+      ;(nodes || []).forEach(n => {
+        const children = Array.isArray(n?.children) ? n.children : []
+        if (children.length > 0) walk(children)
+        else {
+          const value = n?.value ?? n?.id
+          const label = n?.label || n?.productName || n?.name || ''
+          flat.push({ label, value })
+        }
+      })
+    }
+    walk(list)
+    productOptions.value = flat.filter(it => it.value)
+  } finally {
+    productLoading.value = false
+  }
+}
+
+const openProductSelector = async () => {
+  if (isEdit.value) return
+  showProductPopup.value = true
+  if (productOptions.value.length === 0) {
+    await loadProducts()
+  }
+}
+const selectProduct = (item) => {
+  if (isEdit.value) return
+  form.productId = item.value
+  form.productName = item.label
+  form.productModelId = ''
+  form.model = ''
+  form.unit = ''
+  modelOptions.value = []
+  showProductPopup.value = false
+}
+
+const loadModels = async () => {
+  if (!form.productId) return
+  modelLoading.value = true
+  try {
+    const res = await modelList({ id: form.productId })
+    modelOptions.value = Array.isArray(res) ? res : (res?.data || [])
+  } finally {
+    modelLoading.value = false
+  }
+}
+const openModelSelector = async () => {
+  if (isEdit.value) return
+  if (!form.productId) {
+    toast('璇峰厛閫夋嫨浜у搧鍚嶇О')
+    return
+  }
+  showModelPopup.value = true
+  if (modelOptions.value.length === 0) {
+    await loadModels()
+  }
+}
+const selectModel = (item) => {
+  if (isEdit.value) return
+  form.productModelId = item?.id
+  form.model = item?.model || ''
+  form.unit = item?.unit || ''
+  showModelPopup.value = false
+}
+
+const selectCheckType = (e) => {
+  form.checkType = e.value
+  showTypeSelect.value = false
+}
+
+const loadUsers = async () => {
+  const res = await userListNoPage()
+  const list = res?.data || []
+  userActions.value = (list || []).map(u => ({ name: u.nickName, value: u.nickName })).filter(it => it.value)
+}
+const selectUser = (e) => {
+  form.checkName = e.value
+  showUserSelect.value = false
+}
+
+const openCheckTimePicker = () => {
+  checkTimeValue.value = form.checkTime ? dayjs(form.checkTime, 'YYYY-MM-DD').valueOf() : Date.now()
+  showCheckTimePicker.value = true
+}
+const confirmCheckTime = (e) => {
+  const ts = e?.value ?? checkTimeValue.value
+  form.checkTime = dayjs(ts).format('YYYY-MM-DD')
+  showCheckTimePicker.value = false
+}
+
+const openDealTimePicker = () => {
+  dealTimeValue.value = form.dealTime ? dayjs(form.dealTime, 'YYYY-MM-DD').valueOf() : Date.now()
+  showDealTimePicker.value = true
+}
+const confirmDealTime = (e) => {
+  const ts = e?.value ?? dealTimeValue.value
+  form.dealTime = dayjs(ts).format('YYYY-MM-DD')
+  showDealTimePicker.value = false
+}
+
+const loadDetail = async () => {
+  if (!id.value) return
+  const res = await getQualityUnqualifiedInfo(id.value)
+  const d = res?.data || {}
+  Object.assign(form, {
+    id: d.id,
+    productId: d.productId,
+    productName: d.productName,
+    productModelId: d.productModelId,
+    model: d.model,
+    unit: d.unit,
+    batchNo: d.batchNo,
+    // 鍏煎鍚庣杩斿洖瀛楁锛氫紭鍏� checkType锛屽叾娆� inspectType
+    checkType: d.checkType ?? d.inspectType,
+    checkName: d.checkName,
+    checkTime: d.checkTime,
+    defectivePhenomena: d.defectivePhenomena,
+    dealResult: d.dealResult,
+    dealName: d.dealName,
+    dealTime: d.dealTime
+  })
+}
+
+const validate = () => {
+  if (!form.productId) return toast('璇烽�夋嫨浜у搧鍚嶇О'), false
+  if (!form.productModelId) return toast('璇烽�夋嫨瑙勬牸鍨嬪彿'), false
+  if (!form.batchNo) return toast('璇疯緭鍏ユ壒鍙�'), false
+  if (form.checkType === undefined || form.checkType === '') return toast('璇烽�夋嫨妫�楠岀被鍨�'), false
+  if (!form.checkName) return toast('璇烽�夋嫨妫�楠屽憳'), false
+  if (!form.checkTime) return toast('璇烽�夋嫨妫�娴嬫棩鏈�'), false
+  if (!form.defectivePhenomena) return toast('璇疯緭鍏ヤ笉鍚堟牸鐜拌薄'), false
+  return true
+}
+
+const handleSubmit = async () => {
+  if (submitting.value) return
+  if (!validate()) return
+  submitting.value = true
+  try {
+    // 澶勭悊缁撴灉榛樿鎶ュ簾
+    if (!form.dealResult) form.dealResult = getScrapDealResultValue()
+    const payload = { ...form }
+    delete payload.inspectState
+    const api = isEdit.value ? qualityUnqualifiedUpdate : qualityUnqualifiedAdd
+    await api(payload)
+    toast('鎻愪氦鎴愬姛')
+    setTimeout(() => uni.navigateBack(), 400)
+  } catch (e) {
+    toast('鎻愪氦澶辫触')
+  } finally {
+    submitting.value = false
+  }
+}
+
+const goBack = () => uni.navigateBack()
+
+onLoad(async (options) => {
+  pageType.value = options?.type || 'add'
+  id.value = options?.id || ''
+  form.dealResult = getScrapDealResultValue()
+  await loadUsers()
+  if (isEdit.value) {
+    await loadDetail()
+  }
+})
+</script>
+
+<style lang="scss" scoped>
+.nonconforming-form-page { min-height: 100vh; background: #f5f5f5; padding-bottom: 120rpx; }
+.content-scroll { height: calc(100vh - 100rpx); }
+.form-section { background: #fff; margin: 24rpx; padding: 24rpx; border-radius: 16rpx; }
+.section-title { font-size: 28rpx; font-weight: 500; color: #333; margin-bottom: 12rpx; }
+.form-row { margin-bottom: 24rpx; }
+.form-label { display: block; font-size: 26rpx; color: #666; margin-bottom: 12rpx; }
+.form-label.required:before { content: "*"; color: #f56c6c; margin-right: 6rpx; }
+.selector-trigger { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; background: #f5f5f5; border-radius: 12rpx; }
+.selector-trigger.disabled { opacity: 0.6; }
+.selector-text { font-size: 28rpx; color: #333; }
+.selector-text.placeholder { color: #999; }
+.bottom-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -4rpx 16rpx rgba(0,0,0,0.04); }
+.btn-submit { height: 88rpx; border-radius: 999rpx; background: #2979ff; color: #fff; font-size: 30rpx; display: flex; align-items: center; justify-content: center; }
+.btn-submit.disabled { opacity: 0.6; }
+
+.popup { background: #fff; border-top-left-radius: 16rpx; border-top-right-radius: 16rpx; overflow: hidden; }
+.popup-header { padding: 24rpx; border-bottom: 1rpx solid #eee; }
+.popup-title { font-size: 30rpx; font-weight: 500; color: #333; }
+.popup-list { max-height: 60vh; padding: 12rpx 0; }
+.popup-item { padding: 22rpx 24rpx; border-bottom: 1rpx solid #f0f0f0; }
+.popup-item-title { font-size: 28rpx; color: #333; }
+.popup-item-row { display: flex; justify-content: space-between; gap: 16rpx; }
+.popup-item-sub { font-size: 24rpx; color: #999; }
+.no-data { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; }
+</style>
+
diff --git a/src/pages/qualityManagement/nonconformingManagement/index.vue b/src/pages/qualityManagement/nonconformingManagement/index.vue
index 5efa7ae..f3cc42e 100644
--- a/src/pages/qualityManagement/nonconformingManagement/index.vue
+++ b/src/pages/qualityManagement/nonconformingManagement/index.vue
@@ -2,74 +2,69 @@
   <view class="nonconforming-management-page">
     <PageHeader title="涓嶅悎鏍煎搧绠$悊" @back="goBack" />
     
-    <!-- 鎼滅储涓庣瓫閫� -->
+    <!-- 鎼滅储涓庣瓫閫夛紙鏍峰紡鍙傜収浠撳偍鐗╂祦妯″潡锛� -->
     <view class="search-section">
-      <up-search
-        placeholder="璇疯緭鍏ヤ骇鍝佸悕绉版悳绱�"
-        v-model="searchForm.productName"
-        @search="handleQuery"
-        @custom="handleQuery"
-        @clear="handleQuery"
-        :show-action="true"
-        action-text="鎼滅储"
-        :animation="true"
-        customStyle="margin-bottom: 20rpx"
-      ></up-search>
+      <view class="search-row">
+        <view class="search-input-wrap">
+          <up-input v-model="searchForm.productName" placeholder="浜у搧鍚嶇О" clearable />
+        </view>
+        <view class="btn-search" @click="handleQuery">
+          <view class="btn-search-inner">
+            <up-icon name="search" size="22" color="#fff"></up-icon>
+            <text>鎼滅储</text>
+          </view>
+        </view>
+      </view>
       <view class="filter-row">
         <view class="filter-item" @click="showTypeSelect = true">
           <text>{{ typeLabel }}</text>
           <up-icon name="arrow-down" size="14" color="#999"></up-icon>
         </view>
-        <view class="filter-item" @click="showStatusSelect = true">
-          <text>{{ statusLabel }}</text>
-          <up-icon name="arrow-down" size="14" color="#999"></up-icon>
+        <view class="filter-item" @click="openDateRange">
+          <text>{{ dateRangeLabel }}</text>
+          <up-icon name="calendar" size="14" color="#999"></up-icon>
         </view>
       </view>
     </view>
 
     <!-- 鍒楄〃鍖哄煙 -->
-    <view class="list-container" v-if="tableData.length > 0">
-      <view v-for="(item, index) in tableData" :key="index" class="list-item">
-        <view class="item-header">
-          <text class="product-name">{{ item.productName }}</text>
-          <up-tag :text="getStatusText(item.inspectState)" :type="getStatusType(item.inspectState)" size="mini"></up-tag>
-        </view>
-        <view class="item-content">
-          <view class="item-row">
-            <text class="item-label">绫诲埆锛�</text>
-            <text class="item-value">{{ getInspectTypeText(item.inspectType) }}</text>
+    <view class="list-section">
+      <view v-if="tableData.length > 0">
+        <view v-for="(item, index) in tableData" :key="item.id || index" class="card-item">
+          <view class="card-click" @click="openForm('edit', item)">
+            <view class="card-header">
+              <view class="header-main">
+                <text class="product-name">{{ item.productName }}</text>
+              </view>
+              <view class="header-sub">
+                <text class="sub-title">{{ item.model || '-' }}</text>
+                <up-tag :text="getInspectTypeText(item.checkType ?? item.inspectType)" type="primary" size="mini" />
+              </view>
+            </view>
+            <up-divider />
+            <view class="card-body">
+              <view class="row"><text class="l">妫�娴嬫棩鏈�</text><text class="r">{{ item.checkTime || '-' }}</text></view>
+              <view class="row"><text class="l">鎵瑰彿</text><text class="r">{{ item.batchNo || '-' }}</text></view>
+              <view class="row"><text class="l">妫�楠屽憳</text><text class="r">{{ item.checkName || '-' }}</text></view>
+              <view class="row"><text class="l">涓嶅悎鏍肩幇璞�</text><text class="r text-error">{{ item.defectivePhenomena || '-' }}</text></view>
+              <view class="row" v-if="item.inspectState == 1"><text class="l">澶勭悊缁撴灉</text><text class="r text-success">{{ getDealResultLabel(item.dealResult) || item.dealResult || '-' }}</text></view>
+              <view class="row" v-if="item.inspectState == 1"><text class="l">澶勭悊浜�</text><text class="r">{{ item.dealName || '-' }}</text></view>
+              <view class="row" v-if="item.inspectState == 1"><text class="l">澶勭悊鏃ユ湡</text><text class="r">{{ item.dealTime || '-' }}</text></view>
+            </view>
           </view>
-          <view class="item-row">
-            <text class="item-label">妫�娴嬫棩鏈燂細</text>
-            <text class="item-value">{{ item.checkTime || '-' }}</text>
-          </view>
-          <view class="item-row">
-            <text class="item-label">瑙勬牸鍨嬪彿锛�</text>
-            <text class="item-value">{{ item.model || '-' }}</text>
-          </view>
-          <view class="item-row">
-            <text class="item-label">涓嶅悎鏍肩幇璞★細</text>
-            <text class="item-value text-error">{{ item.defectivePhenomena || '-' }}</text>
-          </view>
-          <view class="item-row" v-if="item.inspectState === 1">
-            <text class="item-label">澶勭悊缁撴灉锛�</text>
-            <text class="item-value text-success">{{ item.dealResult || '-' }}</text>
+          <view class="card-actions">
+            <view class="btn-link btn-link-primary" v-if="item.inspectState == 0" @click.stop="openDealDialog(item)">澶勭悊</view>
+            <view class="btn-link btn-link-plain" v-if="item.inspectState == 0" @click.stop="openForm('edit', item)">缂栬緫</view>
+            <view class="btn-link btn-link-warn" @click.stop="handleDelete(item)">鍒犻櫎</view>
           </view>
         </view>
-        <view class="item-actions">
-          <up-button v-if="item.inspectState === 0" type="primary" size="mini" @click.stop="openDealDialog(item)">澶勭悊</up-button>
-          <up-button type="error" size="mini" @click.stop="handleDelete(item)">鍒犻櫎</up-button>
+        <view class="load-more-wrap">
+          <u-loadmore :status="loadStatus" @loadmore="loadMore" />
         </view>
       </view>
-      <view class="pagination-container">
-        <up-loadmore :status="loadStatus" @loadmore="getList" />
-      </view>
+      <view v-else class="no-data">鏆傛棤鏁版嵁</view>
     </view>
     
-    <view v-else class="no-data">
-      <up-empty mode="data" text="鏆傛棤鏁版嵁"></up-empty>
-    </view>
-
     <!-- 绫诲瀷閫夋嫨鍣� -->
     <up-action-sheet
       :actions="typeActions"
@@ -77,15 +72,6 @@
       @close="showTypeSelect = false"
       @select="selectType"
       title="璇烽�夋嫨绫诲埆"
-    ></up-action-sheet>
-
-    <!-- 鐘舵�侀�夋嫨鍣� -->
-    <up-action-sheet
-      :actions="statusActions"
-      :show="showStatusSelect"
-      @close="showStatusSelect = false"
-      @select="selectStatus"
-      title="璇烽�夋嫨鐘舵��"
     ></up-action-sheet>
 
     <!-- 澶勭悊寮圭獥 -->
@@ -97,10 +83,19 @@
         <up-form :model="dealForm" ref="dealFormRef" label-width="100" label-position="top">
           <view class="info-summary">
             <text class="summary-text">浜у搧锛歿{ currentItem?.productName }}</text>
-            <text class="summary-text">涓嶅悎鏍肩幇璞★細{{ currentItem?.defectivePhenomena }}</text>
+            <text class="summary-text">妫�娴嬫棩鏈燂細{{ currentItem?.checkTime || '-' }}</text>
           </view>
+          <up-form-item label="涓嶅悎鏍肩幇璞�" prop="defectivePhenomena" required borderBottom>
+            <up-textarea v-model="dealForm.defectivePhenomena" placeholder="璇疯緭鍏ヤ笉鍚堟牸鐜拌薄" count border="surround" />
+          </up-form-item>
           <up-form-item label="澶勭悊缁撴灉" prop="dealResult" required borderBottom>
-            <up-textarea v-model="dealForm.dealResult" placeholder="璇疯緭鍏ュ鐞嗙粨鏋�" count border="surround" />
+            <view class="selector-trigger" @click="showDealResultSelect = true">
+              <text class="selector-text" :class="{ placeholder: !dealResultLabel }">{{ dealResultLabel || '璇烽�夋嫨澶勭悊缁撴灉' }}</text>
+              <up-icon name="arrow-down" size="14" color="#999"></up-icon>
+            </view>
+          </up-form-item>
+          <up-form-item label="澶勭悊浜�" prop="dealName" required borderBottom>
+            <up-input v-model="dealForm.dealName" placeholder="璇疯緭鍏ュ鐞嗕汉" border="surround" />
           </up-form-item>
           <up-form-item label="澶勭悊鏃ユ湡" prop="dealTime" required borderBottom>
             <up-input
@@ -119,6 +114,15 @@
       </view>
     </up-popup>
 
+    <!-- 澶勭悊缁撴灉閫夋嫨鍣� -->
+    <up-action-sheet
+      :actions="dealResultActions"
+      :show="showDealResultSelect"
+      @close="showDealResultSelect = false"
+      @select="selectDealResult"
+      title="璇烽�夋嫨澶勭悊缁撴灉"
+    />
+
     <!-- 鏃ユ湡閫夋嫨鍣� -->
     <up-datetime-picker
       :show="showDatePicker"
@@ -127,23 +131,49 @@
       @confirm="confirmDate"
       @cancel="showDatePicker = false"
     ></up-datetime-picker>
+
+    <!-- 褰曞叆鏃ユ湡鑼冨洿閫夋嫨锛氬紑濮� -->
+    <up-datetime-picker
+      :show="showEntryStartPicker"
+      v-model="entryStartValue"
+      mode="date"
+      @confirm="confirmEntryStart"
+      @cancel="showEntryStartPicker = false"
+    />
+    <!-- 褰曞叆鏃ユ湡鑼冨洿閫夋嫨锛氱粨鏉� -->
+    <up-datetime-picker
+      :show="showEntryEndPicker"
+      v-model="entryEndValue"
+      mode="date"
+      @confirm="confirmEntryEnd"
+      @cancel="showEntryEndPicker = false"
+    />
+
+    <!-- 鍙充笅瑙掓柊澧炴寜閽� -->
+    <view class="fab-button" @click="openForm('add')">
+      <up-icon name="plus" size="24" color="#ffffff"></up-icon>
+    </view>
   </view>
 </template>
 
 <script setup>
-import { ref, reactive, onMounted, computed } from 'vue';
+import { ref, reactive, computed } from 'vue';
 import {
   qualityUnqualifiedListPage,
   qualityUnqualifiedDeal,
   qualityUnqualifiedDel
 } from '@/api/qualityManagement/nonconformingManagement.js';
 import { toast, showConfirm } from '@/utils/common';
+import { useDict } from '@/utils/dict'
 import dayjs from 'dayjs';
+import PageHeader from '@/components/PageHeader.vue'
+import { onReachBottom, onShow } from '@dcloudio/uni-app'
 
 const searchForm = reactive({
   productName: '',
-  inspectType: '',
-  inspectState: ''
+  checkType: '',
+  entryDateStart: undefined,
+  entryDateEnd: undefined
 });
 
 const tableData = ref([]);
@@ -162,54 +192,67 @@
   { name: '鍑哄巶妫�', value: '2' }
 ];
 const typeLabel = computed(() => {
-  const action = typeActions.find(a => a.value === searchForm.inspectType);
+  const action = typeActions.find(a => a.value === String(searchForm.checkType ?? ''));
   return action ? action.name : '鍏ㄩ儴绫诲埆';
 });
 
-const showStatusSelect = ref(false);
-const statusActions = [
-  { name: '鍏ㄩ儴', value: '' },
-  { name: '寰呭鐞�', value: '0' },
-  { name: '宸插鐞�', value: '1' }
-];
-const statusLabel = computed(() => {
-  const action = statusActions.find(a => a.value === searchForm.inspectState);
-  return action ? action.name : '鍏ㄩ儴鐘舵��';
-});
+const dateRangeLabel = computed(() => {
+  if (searchForm.entryDateStart && searchForm.entryDateEnd) return `${searchForm.entryDateStart}~${searchForm.entryDateEnd}`
+  if (searchForm.entryDateStart) return `${searchForm.entryDateStart}~`
+  if (searchForm.entryDateEnd) return `~${searchForm.entryDateEnd}`
+  return '妫�娴嬫棩鏈�'
+})
 
 const dealDialogVisible = ref(false);
 const submitLoading = ref(false);
 const currentItem = ref(null);
 const dealForm = reactive({
   id: null,
+  defectivePhenomena: '',
   dealResult: '',
+  dealName: '',
   dealTime: dayjs().format('YYYY-MM-DD')
 });
+
+const { rejection_handling } = useDict('rejection_handling')
+const showDealResultSelect = ref(false)
+const dealResultActions = computed(() => {
+  const list = rejection_handling?.value || []
+  return (list || []).map(it => ({ name: it.label, value: it.value }))
+})
+const dealResultLabel = computed(() => {
+  const list = rejection_handling?.value || []
+  const v = dealForm.dealResult
+  return (list || []).find(it => String(it.value) === String(v))?.label || ''
+})
+function getDealResultLabel(value) {
+  const list = rejection_handling?.value || []
+  return (list || []).find(it => String(it.value) === String(value))?.label || ''
+}
 
 const showDatePicker = ref(false);
 const dateValue = ref(Number(new Date()));
 
+const showEntryStartPicker = ref(false)
+const showEntryEndPicker = ref(false)
+const entryStartValue = ref(Date.now())
+const entryEndValue = ref(Date.now())
+
 const getInspectTypeText = (type) => {
   const types = { '0': '鍏ュ巶妫�', '1': '杞﹂棿妫�', '2': '鍑哄巶妫�' };
-  return types[type] || '-';
-};
-
-const getStatusText = (state) => {
-  return state === 1 ? '宸插鐞�' : '寰呭鐞�';
-};
-
-const getStatusType = (state) => {
-  return state === 1 ? 'success' : 'warning';
+  return types[String(type ?? '')] || '-';
 };
 
 const getList = () => {
-  if (loadStatus.value === 'loading' || (page.total > 0 && tableData.value.length >= page.total)) return;
-  
-  loadStatus.value = 'loading';
+  const isFirstPage = page.current === 1
+  if (loadStatus.value === 'loading' || (!isFirstPage && page.total > 0 && tableData.value.length >= page.total)) return
+
+  loadStatus.value = 'loading'
   const params = {
     productName: searchForm.productName || null,
-    inspectType: searchForm.inspectType || null,
-    inspectState: searchForm.inspectState || null,
+    checkType: searchForm.checkType === '' ? null : searchForm.checkType,
+    entryDateStart: searchForm.entryDateStart,
+    entryDateEnd: searchForm.entryDateEnd,
     current: page.current,
     size: page.size
   };
@@ -227,12 +270,18 @@
       loadStatus.value = 'nomore';
     } else {
       loadStatus.value = 'loadmore';
-      page.current++;
     }
   }).catch(() => {
-    loadStatus.value = 'loadmore';
+    loadStatus.value = 'error';
   });
 };
+
+const loadMore = () => {
+  if (loadStatus.value === 'nomore' || loadStatus.value === 'loading') return
+  loadStatus.value = 'loading'
+  page.current++
+  getList()
+}
 
 const handleQuery = () => {
   page.current = 1;
@@ -243,27 +292,55 @@
 };
 
 const selectType = (e) => {
-  searchForm.inspectType = e.value;
+  searchForm.checkType = e.value;
   handleQuery();
 };
 
-const selectStatus = (e) => {
-  searchForm.inspectState = e.value;
-  handleQuery();
-};
+const openDateRange = () => {
+  entryStartValue.value = searchForm.entryDateStart ? dayjs(searchForm.entryDateStart, 'YYYY-MM-DD').valueOf() : Date.now()
+  showEntryStartPicker.value = true
+}
+const confirmEntryStart = (e) => {
+  const ts = e?.value ?? entryStartValue.value
+  searchForm.entryDateStart = dayjs(ts).format('YYYY-MM-DD')
+  showEntryStartPicker.value = false
+  entryEndValue.value = searchForm.entryDateEnd ? dayjs(searchForm.entryDateEnd, 'YYYY-MM-DD').valueOf() : Date.now()
+  showEntryEndPicker.value = true
+}
+const confirmEntryEnd = (e) => {
+  const ts = e?.value ?? entryEndValue.value
+  searchForm.entryDateEnd = dayjs(ts).format('YYYY-MM-DD')
+  showEntryEndPicker.value = false
+  handleQuery()
+}
 
 const openDealDialog = (item) => {
   currentItem.value = item;
   dealForm.id = item.id;
-  dealForm.dealResult = '';
+  dealForm.defectivePhenomena = item.defectivePhenomena || ''
+  dealForm.dealResult = item.dealResult || '';
+  dealForm.dealName = item.dealName || ''
   dealForm.dealTime = dayjs().format('YYYY-MM-DD');
   dealDialogVisible.value = true;
 };
 
+const selectDealResult = (e) => {
+  dealForm.dealResult = e.value
+  showDealResultSelect.value = false
+}
+
 const submitDeal = () => {
-  if (!dealForm.dealResult) {
-    toast('璇疯緭鍏ュ鐞嗙粨鏋�');
+  if (!dealForm.defectivePhenomena) {
+    toast('璇疯緭鍏ヤ笉鍚堟牸鐜拌薄')
     return;
+  }
+  if (!dealForm.dealResult) {
+    toast('璇烽�夋嫨澶勭悊缁撴灉')
+    return
+  }
+  if (!dealForm.dealName) {
+    toast('璇疯緭鍏ュ鐞嗕汉')
+    return
   }
   submitLoading.value = true;
   qualityUnqualifiedDeal(dealForm).then(() => {
@@ -291,89 +368,115 @@
   showDatePicker.value = false;
 };
 
+const openForm = (type, row) => {
+  if (type !== 'add' && row?.inspectState == 1) {
+    toast('宸插鐞嗙殑鏁版嵁涓嶈兘鍐嶇紪杈�')
+    return
+  }
+  const id = row?.id
+  uni.navigateTo({
+    url: `/pages/qualityManagement/nonconformingManagement/form?type=${type}${id ? `&id=${id}` : ''}`
+  })
+}
+
 const goBack = () => {
   uni.navigateBack();
 };
 
-onMounted(() => {
-  handleQuery();
-});
+onShow(() => {
+  handleQuery()
+})
+
+onReachBottom(() => {
+  loadMore()
+})
 </script>
 
 <style lang="scss" scoped>
 .nonconforming-management-page {
-  padding-bottom: 20rpx;
-  background-color: #f5f7fa;
   min-height: 100vh;
+  background: #f5f5f5;
+  padding-bottom: 120rpx;
 }
 
 .search-section {
-  padding: 20rpx 30rpx;
-  background-color: #ffffff;
-  position: sticky;
-  top: 0;
-  z-index: 10;
+  background: #fff;
+  margin: 24rpx;
+  padding: 24rpx;
+  border-radius: 16rpx;
 }
+
+.search-row { display: flex; align-items: center; margin-bottom: 20rpx; }
+.search-input-wrap { flex: 1; margin-right: 20rpx; min-width: 0; }
+.btn-search {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 180rpx;
+  min-height: 72rpx;
+  flex-shrink: 0;
+  padding: 20rpx 24rpx;
+  background: #2979ff;
+  color: #fff;
+  border-radius: 12rpx;
+  font-size: 28rpx;
+  box-sizing: border-box;
+  text-align: center;
+}
+.btn-search-inner { display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 8rpx; }
 
 .filter-row {
   display: flex;
-  justify-content: space-around;
-  padding: 10rpx 0;
+  gap: 20rpx;
 }
 
 .filter-item {
-  display: flex;
-  align-items: center;
-  gap: 10rpx;
-  font-size: 28rpx;
-  color: #606266;
-}
-
-.list-container {
-  padding: 20rpx;
-}
-
-.list-item {
-  background-color: #ffffff;
-  border-radius: 16rpx;
-  padding: 30rpx;
-  margin-bottom: 20rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
-}
-
-.item-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20rpx;
-}
-
-.product-name {
-  font-size: 30rpx;
-  font-weight: bold;
-  color: #303133;
-}
-
-.item-content {
-  margin-bottom: 20rpx;
-}
-
-.item-row {
-  display: flex;
-  margin-bottom: 10rpx;
-}
-
-.item-label {
-  color: #909399;
-  width: 180rpx;
-  font-size: 28rpx;
-}
-
-.item-value {
   flex: 1;
-  color: #303133;
-  font-size: 28rpx;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 18rpx 20rpx;
+  background: #f5f5f5;
+  border-radius: 12rpx;
+  font-size: 26rpx;
+  color: #666;
 }
+
+.list-section { padding: 0 24rpx; }
+.card-item {
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 16rpx 20rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
+}
+.card-header { padding: 2rpx 0 6rpx; }
+.header-main { display: flex; justify-content: space-between; align-items: center; gap: 16rpx; }
+.product-name { font-size: 30rpx; font-weight: 500; color: #333; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.header-sub { display: flex; justify-content: space-between; gap: 16rpx; margin-top: 6rpx; }
+.sub-title { font-size: 24rpx; color: #999; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.sub-right { font-size: 24rpx; color: #999; flex-shrink: 0; }
+.card-body .row { display: flex; justify-content: space-between; padding: 6rpx 0; font-size: 26rpx; }
+.card-body .l { color: #666; width: 180rpx; flex-shrink: 0; }
+.card-body .r { color: #333; flex: 1; text-align: right; word-break: break-all; }
+.card-actions {
+  display: flex;
+  gap: 16rpx;
+  justify-content: flex-end;
+  align-items: center;
+  margin-top: 12rpx;
+  padding-top: 14rpx;
+  border-top: 1rpx solid #eee;
+}
+.btn-link {
+  font-size: 28rpx;
+  padding: 10rpx 22rpx;
+  border-radius: 999rpx;
+  border: 1rpx solid transparent;
+}
+.btn-link-primary { color: #2979ff; border-color: rgba(41, 121, 255, 0.4); background: rgba(41, 121, 255, 0.08); }
+.btn-link-plain { color: #606266; border-color: rgba(96, 98, 102, 0.35); background: rgba(96, 98, 102, 0.06); }
+.btn-link-warn { color: #f56c6c; border-color: rgba(245, 108, 108, 0.55); background: rgba(245, 108, 108, 0.08); }
 
 .text-error {
   color: #f56c6c;
@@ -383,17 +486,8 @@
   color: #67c23a;
 }
 
-.item-actions {
-  display: flex;
-  justify-content: flex-end;
-  gap: 20rpx;
-  border-top: 1rpx solid #ebeef5;
-  padding-top: 20rpx;
-}
-
-.no-data {
-  padding-top: 200rpx;
-}
+.no-data { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; }
+.load-more-wrap { padding: 24rpx 24rpx 8rpx; }
 
 .dialog-content {
   width: 650rpx;
@@ -431,4 +525,23 @@
 .dialog-footer {
   margin-top: 40rpx;
 }
+
+.selector-trigger { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; background: #f5f5f5; border-radius: 12rpx; }
+.selector-text { font-size: 28rpx; color: #333; }
+.selector-text.placeholder { color: #999; }
+
+.fab-button {
+  position: fixed;
+  right: 36rpx;
+  bottom: 72rpx;
+  width: 104rpx;
+  height: 104rpx;
+  border-radius: 52rpx;
+  background: #2979ff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  box-shadow: 0 10rpx 26rpx rgba(41, 121, 255, 0.35);
+  z-index: 20;
+}
 </style>
diff --git a/src/pages/qualityManagement/rawMaterial/files.vue b/src/pages/qualityManagement/rawMaterial/files.vue
new file mode 100644
index 0000000..32842f4
--- /dev/null
+++ b/src/pages/qualityManagement/rawMaterial/files.vue
@@ -0,0 +1,159 @@
+<template>
+  <view class="file-page">
+    <PageHeader title="闄勪欢绠$悊" @back="goBack" />
+
+    <view class="file-list">
+      <view v-if="files.length > 0">
+        <view v-for="(f, idx) in files" :key="f.id || idx" class="file-item">
+          <view class="file-info">
+            <text class="file-name">{{ f.name }}</text>
+          </view>
+          <view class="file-actions">
+            <view class="btn-link" @click="previewFile(f)">棰勮</view>
+            <view class="btn-link danger" @click="confirmDelete(f)">鍒犻櫎</view>
+          </view>
+        </view>
+      </view>
+      <view v-else class="empty">鏆傛棤闄勪欢</view>
+    </view>
+
+    <view class="upload-bar">
+      <view class="btn-upload" @click="chooseFile">涓婁紶闄勪欢</view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { onLoad, onShow } from '@dcloudio/uni-app'
+import PageHeader from '@/components/PageHeader.vue'
+import config from '@/config'
+import { getToken } from '@/utils/auth'
+import { qualityInspectFileAdd, qualityInspectFileDel, qualityInspectFileListPage } from '@/api/qualityManagement/qualityInspectFile.js'
+
+const inspectId = ref('')
+const files = ref([])
+
+const getList = () => {
+  if (!inspectId.value) return
+  qualityInspectFileListPage({ inspectId: inspectId.value, current: 1, size: 200 })
+    .then(res => {
+      files.value = res?.data?.records || []
+    })
+    .catch(() => { files.value = [] })
+}
+
+const chooseFile = () => {
+  if (!inspectId.value) {
+    uni.showToast({ title: '缂哄皯妫�楠岃褰旾D', icon: 'none' })
+    return
+  }
+  uni.chooseFile({
+    count: 1,
+    success: (res) => {
+      const path = res?.tempFiles?.[0]?.path
+      const name = res?.tempFiles?.[0]?.name
+      if (!path) return
+      uploadOne(path, name)
+    }
+  })
+}
+
+const uploadOne = (filePath, originalName) => {
+  const token = getToken()
+  if (!token) {
+    uni.showToast({ title: '鏈櫥褰�', icon: 'none' })
+    return
+  }
+  uni.showLoading({ title: '涓婁紶涓�...', mask: true })
+  uni.uploadFile({
+    url: config.baseUrl + '/file/upload',
+    filePath,
+    name: 'file',
+    header: { Authorization: 'Bearer ' + token },
+    success: (res) => {
+      uni.hideLoading()
+      try {
+        const resp = JSON.parse(res.data || '{}')
+        if (resp.code !== 200) throw new Error('upload fail')
+        const fileRow = {
+          inspectId: inspectId.value,
+          name: resp.data?.originalName || originalName || '闄勪欢',
+          url: resp.data?.tempPath
+        }
+        qualityInspectFileAdd(fileRow).then(() => {
+          uni.showToast({ title: '涓婁紶鎴愬姛', icon: 'success' })
+          getList()
+        })
+      } catch (e) {
+        uni.showToast({ title: '涓婁紶澶辫触', icon: 'none' })
+      }
+    },
+    fail: () => {
+      uni.hideLoading()
+      uni.showToast({ title: '涓婁紶澶辫触', icon: 'none' })
+    }
+  })
+}
+
+const previewFile = (f) => {
+  const url = f?.url
+  if (!url) return
+  // H5/APP 缁熶竴鐢ㄥ閮ㄦ墦寮�
+  uni.navigateTo({
+    url: `/pages/inspectionUpload/filePreview?url=${encodeURIComponent(url)}`
+  })
+}
+
+const confirmDelete = (f) => {
+  if (!f?.id) return
+  uni.showModal({
+    title: '鍒犻櫎',
+    content: '纭鍒犻櫎璇ラ檮浠讹紵',
+    success: (r) => {
+      if (!r.confirm) return
+      qualityInspectFileDel([f.id]).then(() => {
+        uni.showToast({ title: '鍒犻櫎鎴愬姛', icon: 'success' })
+        getList()
+      })
+    }
+  })
+}
+
+onLoad((options) => {
+  inspectId.value = options?.id || ''
+  if (!inspectId.value) {
+    const cached = uni.getStorageSync('rawMaterialFilesCtx')
+    if (cached) {
+      try {
+        const payload = typeof cached === 'string' ? JSON.parse(cached) : cached
+        inspectId.value = payload?.id || ''
+        uni.removeStorageSync('rawMaterialFilesCtx')
+      } catch (e) {
+        uni.removeStorageSync('rawMaterialFilesCtx')
+      }
+    }
+  }
+})
+
+onShow(() => {
+  getList()
+})
+
+const goBack = () => uni.navigateBack()
+</script>
+
+<style lang="scss" scoped>
+.file-page { min-height: 100vh; background: #f5f5f5; padding-bottom: 120rpx; }
+.file-list { margin: 24rpx; background: #fff; border-radius: 16rpx; padding: 12rpx 24rpx; }
+.file-item { padding: 20rpx 0; border-bottom: 1rpx solid #eee; display: flex; justify-content: space-between; align-items: center; gap: 16rpx; }
+.file-item:last-child { border-bottom: 0; }
+.file-name { font-size: 28rpx; color: #333; }
+.file-actions { display: flex; gap: 20rpx; }
+.btn-link { color: #2979ff; font-size: 26rpx; }
+.btn-link.danger { color: #f56c6c; }
+.empty { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; }
+.upload-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -4rpx 16rpx rgba(0,0,0,0.04); }
+.btn-upload { height: 88rpx; border-radius: 999rpx; background: #2979ff; color: #fff; font-size: 30rpx; display: flex; align-items: center; justify-content: center; }
+</style>
+
diff --git a/src/pages/qualityManagement/rawMaterial/form.vue b/src/pages/qualityManagement/rawMaterial/form.vue
new file mode 100644
index 0000000..148dcd6
--- /dev/null
+++ b/src/pages/qualityManagement/rawMaterial/form.vue
@@ -0,0 +1,418 @@
+<template>
+  <view class="rm-form-page">
+    <PageHeader :title="operationType === 'add' ? '鏂板鍘熸枡妫�' : '缂栬緫鍘熸枡妫�'" @back="goBack" />
+
+    <scroll-view scroll-y class="content-scroll">
+      <view class="section-card">
+        <view class="section-title">鍩虹淇℃伅</view>
+
+        <view class="form-row">
+          <text class="form-label required">浜у搧鍚嶇О</text>
+          <view class="selector-trigger" @click="openProductSelector" :class="{ disabled: operationType === 'edit' }">
+            <text class="selector-text" :class="{ placeholder: !form.productName }">
+              {{ form.productName || '璇烽�夋嫨浜у搧' }}
+            </text>
+            <up-icon name="arrow-right" size="16" color="#999"></up-icon>
+          </view>
+        </view>
+
+        <view class="form-row">
+          <text class="form-label required">瑙勬牸鍨嬪彿</text>
+          <up-input v-model="form.model" disabled placeholder="璇烽�夋嫨浜у搧鍚庤嚜鍔ㄥ甫鍑�" />
+        </view>
+
+        <view class="form-row">
+          <text class="form-label">鍗曚綅</text>
+          <up-input v-model="form.unit" disabled placeholder="鑷姩甯﹀嚭" />
+        </view>
+
+        <view class="form-row">
+          <text class="form-label required">鎵瑰彿</text>
+          <up-input v-model="form.batchNo" placeholder="璇疯緭鍏ユ壒鍙�" />
+        </view>
+
+        <view class="form-row">
+          <text class="form-label required">妫�楠岀被鍨�</text>
+          <view class="selector-trigger" @click="showCheckTypeSheet = true">
+            <text class="selector-text" :class="{ placeholder: form.checkType === '' || form.checkType == null }">
+              {{ checkTypeLabel }}
+            </text>
+            <up-icon name="arrow-down" size="14" color="#999"></up-icon>
+          </view>
+        </view>
+
+        <view class="form-row">
+          <text class="form-label required">妫�娴嬬粨鏋�</text>
+          <view class="selector-trigger" @click="showCheckResultSheet = true">
+            <text class="selector-text" :class="{ placeholder: form.checkResult === '' || form.checkResult == null }">
+              {{ checkResultLabel }}
+            </text>
+            <up-icon name="arrow-down" size="14" color="#999"></up-icon>
+          </view>
+        </view>
+
+        <view class="form-row">
+          <text class="form-label required">妫�楠屽憳</text>
+          <up-input v-model="form.checkUserName" placeholder="璇疯緭鍏ユ楠屽憳" />
+        </view>
+
+        <view class="form-row">
+          <text class="form-label required">妫�娴嬫棩鏈�</text>
+          <view class="selector-trigger" @click="openCheckDatePicker">
+            <text class="selector-text" :class="{ placeholder: !form.checkTime }">
+              {{ form.checkTime || '璇烽�夋嫨妫�娴嬫棩鏈�' }}
+            </text>
+            <up-icon name="calendar" size="16" color="#999"></up-icon>
+          </view>
+        </view>
+      </view>
+
+      <view class="section-card">
+        <view class="section-title row-between">
+          <text>妫�娴嬮」鐩�</text>
+          <view class="btn-inline" @click="openItemSelector">娣诲姞妫�娴嬮」鐩�</view>
+        </view>
+
+        <view v-if="inspectItems.length > 0">
+          <view v-for="(it, idx) in inspectItems" :key="it.id || idx" class="item-card">
+            <view class="item-head">
+              <text class="item-name">{{ it.name }}</text>
+              <view class="item-del" @click="removeItem(it.id)">鍒犻櫎</view>
+            </view>
+            <view class="item-row"><text class="l">鍗曚綅</text><text class="r">{{ it.unit || '-' }}</text></view>
+            <view class="item-row"><text class="l">鏍囧噯鍊�</text><text class="r">{{ it.standardValue || '-' }}</text></view>
+            <view class="item-row"><text class="l">鍐呮帶鍊�</text><text class="r">{{ it.internalControl || '-' }}</text></view>
+            <view class="item-row input-row">
+              <text class="l">鍖栭獙鍊�</text>
+              <up-input v-model="it.testValue" placeholder="璇疯緭鍏�" class="test-value-input" />
+            </view>
+          </view>
+        </view>
+        <view v-else class="no-data">璇锋坊鍔犳娴嬮」鐩�</view>
+      </view>
+    </scroll-view>
+
+    <view class="bottom-bar">
+      <view class="btn-submit" :class="{ disabled: submitLoading }" @click="handleSubmit">
+        {{ submitLoading ? '鎻愪氦涓�...' : '淇濆瓨' }}
+      </view>
+    </view>
+
+    <!-- 浜у搧閫夋嫨寮圭獥锛堝鐢� pageModel 鎺ュ彛锛� -->
+    <up-popup :show="showProductPopup" mode="bottom" @close="showProductPopup = false">
+      <view class="popup-wrap">
+        <view class="popup-header">
+          <text class="popup-title">閫夋嫨浜у搧</text>
+        </view>
+        <view class="popup-search">
+          <up-input v-model="productQuery.productName" placeholder="浜у搧澶х被" clearable />
+          <up-input v-model="productQuery.model" placeholder="鍨嬪彿鍚嶇О" clearable />
+          <view class="popup-search-btn" @click="loadProductList">鎼滅储</view>
+        </view>
+        <scroll-view scroll-y class="popup-list">
+          <view v-for="row in productList" :key="row.id" class="popup-item" @click="selectProduct(row)">
+            <view class="popup-item-top">
+              <text class="popup-item-name">{{ row.productName }}</text>
+              <text class="popup-item-unit">{{ row.unit }}</text>
+            </view>
+            <view class="popup-item-sub">鍨嬪彿锛歿{ row.model }}</view>
+          </view>
+          <view v-if="!productLoading && productList.length === 0" class="no-data">鏆傛棤鏁版嵁</view>
+        </scroll-view>
+      </view>
+    </up-popup>
+
+    <!-- 妫�娴嬮」鐩�夋嫨寮圭獥锛堢畝鍖栵細浠庢娴嬮」缁存姢琛ㄩ噷閫夛級 -->
+    <up-popup :show="showItemPopup" mode="bottom" @close="showItemPopup = false">
+      <view class="popup-wrap">
+        <view class="popup-header">
+          <text class="popup-title">閫夋嫨妫�娴嬮」鐩�</text>
+        </view>
+        <view class="popup-search">
+          <up-input v-model="itemQuery.name" placeholder="妫�娴嬮」鐩悕绉�" clearable />
+          <view class="popup-search-btn" @click="loadItemList">鎼滅储</view>
+        </view>
+        <scroll-view scroll-y class="popup-list">
+          <view
+            v-for="row in itemList"
+            :key="row.id"
+            class="popup-item"
+            :class="{ selected: isItemSelected(row.id) }"
+            @click="toggleItem(row)"
+          >
+            <view class="popup-item-top">
+              <text class="popup-item-name">{{ row.name }}</text>
+              <view class="right-wrap">
+                <text class="popup-item-unit">{{ row.unit }}</text>
+                <up-icon
+                  v-if="isItemSelected(row.id)"
+                  name="checkbox-mark"
+                  size="18"
+                  color="#2979ff"
+                ></up-icon>
+              </view>
+            </view>
+            <view class="popup-item-sub">鏍囧噯鍊硷細{{ row.standardValue || '-' }}锝滃唴鎺у�硷細{{ row.internalControl || '-' }}</view>
+          </view>
+          <view v-if="!itemLoading && itemList.length === 0" class="no-data">鏆傛棤鏁版嵁</view>
+        </scroll-view>
+        <view class="popup-footer">
+          <view class="btn-cancel" @click="showItemPopup = false">鍙栨秷</view>
+          <view class="btn-ok" @click="confirmItems">纭畾</view>
+        </view>
+      </view>
+    </up-popup>
+
+    <!-- 閫夋嫨鍣細妫�楠岀被鍨�/缁撴灉 -->
+    <up-action-sheet :actions="checkTypeActions" :show="showCheckTypeSheet" @close="showCheckTypeSheet = false" @select="onSelectCheckType" title="妫�楠岀被鍨�" />
+    <up-action-sheet :actions="checkResultActions" :show="showCheckResultSheet" @close="showCheckResultSheet = false" @select="onSelectCheckResult" title="妫�娴嬬粨鏋�" />
+
+    <!-- 鏃ユ湡閫夋嫨 -->
+    <up-popup :show="showCheckDatePicker" mode="bottom" @close="showCheckDatePicker = false">
+      <up-datetime-picker :show="true" v-model="checkDateValue" mode="date" @confirm="onCheckDateConfirm" @cancel="showCheckDatePicker = false" />
+    </up-popup>
+  </view>
+</template>
+
+<script setup>
+import { computed, reactive, ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import dayjs from 'dayjs'
+import PageHeader from '@/components/PageHeader.vue'
+import useUserStore from '@/store/modules/user'
+import { productModelList } from '@/api/basicData/productModel.js'
+import { qualityInspectItemListPage } from '@/api/qualityManagement/inspectItem.js'
+import { createRawMaterial, findRawMaterialDetail, updateRawMaterial } from '@/api/qualityManagement/rawMaterial.js'
+
+const userStore = useUserStore()
+
+const operationType = ref('add')
+const submitLoading = ref(false)
+
+const form = reactive({
+  id: null,
+  productId: '',
+  productModelId: '',
+  productName: '',
+  model: '',
+  unit: '',
+  batchNo: '',
+  checkType: '',
+  checkResult: '',
+  checkUserName: userStore?.nickName || '',
+  checkTime: ''
+})
+
+const inspectItems = ref([]) // qualityInspectItem
+
+// 妫�楠岀被鍨�/缁撴灉
+const checkTypeActions = [
+  { name: '鍏ュ巶妫�', value: 0 },
+  { name: '杞﹂棿妫�', value: 1 },
+  { name: '鍑哄巶妫�', value: 2 }
+]
+const checkResultActions = [
+  { name: '鍚堟牸', value: 1 },
+  { name: '涓嶅悎鏍�', value: 0 }
+]
+const showCheckTypeSheet = ref(false)
+const showCheckResultSheet = ref(false)
+const checkTypeLabel = computed(() => checkTypeActions.find(a => a.value === form.checkType)?.name || '璇烽�夋嫨')
+const checkResultLabel = computed(() => checkResultActions.find(a => a.value === form.checkResult)?.name || '璇烽�夋嫨')
+const onSelectCheckType = (e) => { form.checkType = e.value; showCheckTypeSheet.value = false }
+const onSelectCheckResult = (e) => { form.checkResult = e.value; showCheckResultSheet.value = false }
+
+// 鏃ユ湡閫夋嫨
+const showCheckDatePicker = ref(false)
+const checkDateValue = ref(Date.now())
+const openCheckDatePicker = () => {
+  checkDateValue.value = form.checkTime ? dayjs(form.checkTime, 'YYYY-MM-DD').valueOf() : Date.now()
+  showCheckDatePicker.value = true
+}
+const onCheckDateConfirm = (e) => {
+  form.checkTime = dayjs(e.value).format('YYYY-MM-DD')
+  showCheckDatePicker.value = false
+}
+
+// 浜у搧閫夋嫨
+const showProductPopup = ref(false)
+const productQuery = reactive({ productName: '', model: '' })
+const productList = ref([])
+const productLoading = ref(false)
+const openProductSelector = () => {
+  if (operationType.value === 'edit') return
+  showProductPopup.value = true
+  if (productList.value.length === 0) loadProductList()
+}
+const loadProductList = () => {
+  productLoading.value = true
+  productModelList({ productName: productQuery.productName || '', model: productQuery.model || '', current: 1, size: 20 })
+    .then(res => {
+      const data = res?.records || res?.data?.records || []
+      productList.value = Array.isArray(data) ? data : []
+    })
+    .finally(() => { productLoading.value = false })
+}
+const selectProduct = (row) => {
+  form.productId = row.productId
+  form.productModelId = row.id
+  form.productName = row.productName
+  form.model = row.model
+  form.unit = row.unit
+  showProductPopup.value = false
+}
+
+// 妫�娴嬮」鐩�夋嫨
+const showItemPopup = ref(false)
+const itemQuery = reactive({ name: '' })
+const itemList = ref([])
+const itemLoading = ref(false)
+const selectedItemIds = ref(new Set())
+const isItemSelected = (id) => selectedItemIds.value.has(id)
+const openItemSelector = () => {
+  showItemPopup.value = true
+  selectedItemIds.value = new Set(inspectItems.value.map(i => i.id))
+  if (itemList.value.length === 0) loadItemList()
+}
+const loadItemList = () => {
+  itemLoading.value = true
+  qualityInspectItemListPage({ name: itemQuery.name || null, current: 1, size: 50 })
+    .then(res => {
+      const records = res?.data?.records || []
+      itemList.value = Array.isArray(records) ? records : []
+    })
+    .finally(() => { itemLoading.value = false })
+}
+const toggleItem = (row) => {
+  const set = selectedItemIds.value
+  if (set.has(row.id)) set.delete(row.id)
+  else set.add(row.id)
+  // 绠�鍗曟彁绀洪�変腑鐘舵�侊紙鍙寜闇�鍋� icon锛�
+}
+const confirmItems = () => {
+  const set = selectedItemIds.value
+  const existingMap = new Map(inspectItems.value.map(i => [i.id, i]))
+  const next = []
+  for (const id of set) {
+    const exist = existingMap.get(id)
+    if (exist) next.push(exist)
+    else {
+      const row = itemList.value.find(r => r.id === id)
+      if (row) next.push({ ...row, testValue: '' })
+    }
+  }
+  inspectItems.value = next
+  showItemPopup.value = false
+}
+const removeItem = (id) => {
+  inspectItems.value = inspectItems.value.filter(i => i.id !== id)
+}
+
+const validate = () => {
+  if (!form.productModelId) return '璇烽�夋嫨浜у搧'
+  if (!form.batchNo) return '璇疯緭鍏ユ壒鍙�'
+  if (form.checkType === '' || form.checkType == null) return '璇烽�夋嫨妫�楠岀被鍨�'
+  if (form.checkResult === '' || form.checkResult == null) return '璇烽�夋嫨妫�娴嬬粨鏋�'
+  if (!form.checkUserName) return '璇疯緭鍏ユ楠屽憳'
+  if (!form.checkTime) return '璇烽�夋嫨妫�娴嬫棩鏈�'
+  if (!inspectItems.value.length) return '璇锋坊鍔犳娴嬮」鐩�'
+  return ''
+}
+
+const handleSubmit = () => {
+  if (submitLoading.value) return
+  const msg = validate()
+  if (msg) {
+    uni.showToast({ title: msg, icon: 'none' })
+    return
+  }
+  submitLoading.value = true
+  const payload = { ...form, qualityInspectItem: inspectItems.value }
+  const api = operationType.value === 'add' ? createRawMaterial : updateRawMaterial
+  api(payload)
+    .then(() => {
+      uni.showToast({ title: '淇濆瓨鎴愬姛', icon: 'success' })
+      setTimeout(() => uni.navigateBack(), 400)
+    })
+    .catch(() => {
+      uni.showToast({ title: '淇濆瓨澶辫触', icon: 'none' })
+    })
+    .finally(() => { submitLoading.value = false })
+}
+
+onLoad((options) => {
+  operationType.value = options?.type || 'add'
+  const id = options?.id
+  if (operationType.value === 'edit' && id) {
+    findRawMaterialDetail(id).then(res => {
+      const d = res?.data || {}
+      form.id = d.id
+      form.productId = d.productId
+      form.productModelId = d.productModelId
+      form.productName = d.productName
+      form.model = d.model
+      form.unit = d.unit
+      form.batchNo = d.batchNo
+      form.checkType = d.checkType
+      form.checkResult = d.checkResult
+      form.checkUserName = d.checkUserName || form.checkUserName
+      form.checkTime = d.checkTime
+      inspectItems.value = Array.isArray(d.qualityInspectItem) ? d.qualityInspectItem : []
+    })
+  }
+})
+
+const goBack = () => uni.navigateBack()
+</script>
+
+<style lang="scss" scoped>
+.rm-form-page { min-height: 100vh; background: #f5f5f5; padding-bottom: 110rpx; }
+.content-scroll { height: calc(100vh - 110rpx); }
+.section-card { background: #fff; margin: 24rpx; padding: 24rpx; border-radius: 16rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
+.section-title { font-size: 28rpx; font-weight: 500; color: #333; margin-bottom: 12rpx; display: flex; align-items: center; }
+.row-between { justify-content: space-between; }
+.btn-inline { font-size: 26rpx; color: #2979ff; }
+.form-row { margin-bottom: 22rpx; }
+.form-label { display: block; font-size: 26rpx; color: #666; margin-bottom: 12rpx; }
+.form-label.required:before { content: "*"; color: #f56c6c; margin-right: 6rpx; }
+.selector-trigger { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; background: #f5f5f5; border-radius: 12rpx; }
+.selector-trigger.disabled { opacity: 0.6; }
+.selector-text { font-size: 28rpx; color: #333; }
+.selector-text.placeholder { color: #999; }
+.no-data { text-align: center; padding: 40rpx 0; color: #999; font-size: 26rpx; }
+.item-card { padding: 18rpx 0; border-top: 1rpx solid #eee; }
+.item-head { display: flex; justify-content: space-between; align-items: center; padding: 6rpx 0 10rpx; }
+.item-name { font-size: 28rpx; font-weight: 500; color: #333; }
+.item-del { font-size: 26rpx; color: #f56c6c; }
+.item-row { display: flex; justify-content: space-between; align-items: center; padding: 6rpx 0; font-size: 26rpx; }
+.item-row .l { color: #666; }
+.item-row .r { color: #333; }
+.input-row { align-items: center; }
+.test-value-input {
+  flex: 0 0 220rpx;
+}
+:deep(.test-value-input .u-input),
+:deep(.test-value-input .up-input) {
+  width: 100%;
+}
+.bottom-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -4rpx 16rpx rgba(0,0,0,0.04); }
+.btn-submit { height: 88rpx; border-radius: 999rpx; background: #2979ff; color: #fff; font-size: 30rpx; display: flex; align-items: center; justify-content: center; }
+.btn-submit.disabled { opacity: 0.6; }
+.popup-wrap { background: #fff; border-radius: 24rpx 24rpx 0 0; padding-bottom: env(safe-area-inset-bottom); }
+.popup-header { padding: 24rpx; border-bottom: 1rpx solid #eee; text-align: center; }
+.popup-title { font-size: 30rpx; font-weight: 500; color: #333; }
+.popup-search { padding: 16rpx 24rpx; display: grid; grid-template-columns: 1fr 1fr 140rpx; gap: 16rpx; align-items: center; }
+.popup-search-btn { height: 72rpx; border-radius: 12rpx; background: #2979ff; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 28rpx; }
+.popup-list { max-height: 60vh; padding: 0 24rpx 24rpx; }
+.popup-item { padding: 18rpx 0; border-bottom: 1rpx solid #f0f0f0; }
+.popup-item.selected { background: rgba(41, 121, 255, 0.06); }
+.popup-item-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6rpx; }
+.right-wrap { display: inline-flex; align-items: center; gap: 12rpx; }
+.popup-item-name { font-size: 28rpx; color: #333; }
+.popup-item-unit { font-size: 24rpx; color: #999; }
+.popup-item-sub { font-size: 24rpx; color: #666; }
+.popup-footer { display: flex; gap: 24rpx; padding: 16rpx 24rpx 24rpx; }
+.btn-cancel { flex: 1; text-align: center; padding: 24rpx; background: #f0f0f0; border-radius: 12rpx; }
+.btn-ok { flex: 1; text-align: center; padding: 24rpx; background: #2979ff; color: #fff; border-radius: 12rpx; }
+</style>
+
diff --git a/src/pages/qualityManagement/rawMaterial/index.vue b/src/pages/qualityManagement/rawMaterial/index.vue
index 8f2d009..99abfeb 100644
--- a/src/pages/qualityManagement/rawMaterial/index.vue
+++ b/src/pages/qualityManagement/rawMaterial/index.vue
@@ -31,7 +31,11 @@
       <view v-for="(item, index) in tableData" :key="index" class="list-item">
         <view class="item-header">
           <text class="product-name">{{ item.productName }}</text>
-          <up-tag :text="item.inspectState ? '宸叉彁浜�' : '鏈彁浜�'" :type="item.inspectState ? 'success' : 'warning'" size="mini"></up-tag>
+          <up-tag
+            :text="item.inspectState == 1 ? '宸叉彁浜�' : '鏈彁浜�'"
+            :type="item.inspectState == 1 ? 'success' : 'warning'"
+            size="mini"
+          ></up-tag>
         </view>
         <view class="item-content">
           <view class="item-row">
@@ -56,8 +60,9 @@
           </view>
         </view>
         <view class="item-actions">
-          <up-button v-if="!item.inspectState" type="primary" size="mini" @click.stop="openForm('edit', item)">缂栬緫</up-button>
-          <up-button v-if="!item.inspectState" type="success" size="mini" @click.stop="handleConfirmSubmit(item)">鎻愪氦</up-button>
+          <up-button v-if="item.inspectState != 1" type="primary" size="mini" @click.stop="openForm('edit', item)">缂栬緫</up-button>
+          <up-button type="info" size="mini" @click.stop="openFiles(item)">闄勪欢</up-button>
+          <up-button v-if="item.inspectState != 1" type="success" size="mini" @click.stop="handleConfirmSubmit(item)">鎻愪氦</up-button>
           <up-button type="error" size="mini" @click.stop="handleDelete(item)">鍒犻櫎</up-button>
         </view>
       </view>
@@ -96,7 +101,8 @@
 </template>
 
 <script setup>
-import { ref, reactive, onMounted, computed } from 'vue';
+import { ref, reactive, computed } from 'vue';
+import { onShow } from '@dcloudio/uni-app';
 import {
   findRawMaterialListPage,
   submitRawMaterial,
@@ -195,9 +201,10 @@
 };
 
 const openForm = (type, item) => {
-  // Mobile usually navigates to a new page for add/edit if complex
-  // Here we'll just show a toast for now as the actual form components are many
-  toast('鍔熻兘寮�鍙戜腑锛岃鍦≒C绔搷浣�');
+  const id = item?.id
+  uni.navigateTo({
+    url: `/pages/qualityManagement/rawMaterial/form?type=${type}${id ? `&id=${id}` : ''}`
+  })
 };
 
 const handleConfirmSubmit = (row) => {
@@ -214,7 +221,8 @@
 const handleDelete = (row) => {
   showConfirm('纭鍒犻櫎璇ヨ褰曞悧锛�').then(res => {
     if (res.confirm) {
-      deleteRawMaterial({ id: row.id }).then(() => {
+      // 瀵归綈 PC 绔細鍒犻櫎鎺ュ彛鎺ユ敹 id 鏁扮粍
+      deleteRawMaterial([row.id]).then(() => {
         toast('鍒犻櫎鎴愬姛');
         handleQuery();
       });
@@ -222,11 +230,24 @@
   });
 };
 
+const openFiles = (row) => {
+  if (!row?.id) {
+    toast('璇峰厛淇濆瓨鍚庡啀涓婁紶闄勪欢')
+    return
+  }
+  try {
+    uni.setStorageSync('rawMaterialFilesCtx', JSON.stringify({ id: row.id }))
+  } catch (e) {}
+  uni.navigateTo({
+    url: `/pages/qualityManagement/rawMaterial/files?id=${row.id}`
+  })
+}
+
 const goBack = () => {
   uni.navigateBack();
 };
 
-onMounted(() => {
+onShow(() => {
   handleQuery();
 });
 </script>
@@ -309,10 +330,19 @@
 .item-actions {
   display: flex;
   justify-content: flex-end;
-  gap: 20rpx;
+  gap: 16rpx;
   border-top: 1rpx solid #ebeef5;
   padding-top: 20rpx;
 }
+.item-actions :deep(.u-button),
+.item-actions :deep(.up-button) {
+  min-width: 140rpx;
+  height: 64rpx;
+  line-height: 64rpx;
+  font-size: 26rpx;
+  border-radius: 999rpx;
+  padding: 0 24rpx;
+}
 
 .no-data {
   padding-top: 200rpx;

--
Gitblit v1.9.3