From a342672f32352c1337b8977c25c101725fccedd5 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 24 九月 2026 10:48:27 +0800
Subject: [PATCH] fix: MOM 1.产品选择组件修改

---
 src/views/erp/purchase/in/data.ts                   |   18 -
 src/views/erp/stock/out/modules/item-form.vue       |   38 +--
 src/views/erp/stock/in/modules/item-form.vue        |   38 +--
 src/views/erp/stock/move/modules/item-form.vue      |   38 +--
 src/views/srm/tender/detail.vue                     |   40 +--
 src/views/wls/arrivalnotice/data.ts                 |   16 -
 src/views/erp/purchase/order/modules/item-form.vue  |   35 +--
 src/views/erp/sale/return/modules/item-form.vue     |   41 ++-
 src/views/erp/sale/return/data.ts                   |   24 --
 src/views/erp/purchase/statistics/price.vue         |   11 
 src/views/erp/purchase/in/modules/item-form.vue     |   13 -
 src/views/erp/stock/move/data.ts                    |   11 
 src/views/erp/sale/out/modules/item-form.vue        |   15 -
 src/views/mes/qc/template/data.ts                   |   13 -
 src/views/erp/purchase/return/data.ts               |   18 -
 src/views/erp/stock/record/data.ts                  |   11 
 src/views/erp/sale/order/data.ts                    |   12 -
 src/views/erp/stock/check/data.ts                   |   11 
 src/views/erp/stock/out/data.ts                     |   13 -
 src/views/crm/saleQuotation/data.ts                 |    1 
 src/views/erp/stock/check/modules/item-form.vue     |   38 +--
 src/views/erp/stock/stock/data.ts                   |   11 
 src/views/erp/purchase/return/modules/item-form.vue |   13 -
 src/views/erp/sale/out/data.ts                      |   24 --
 src/views/erp/stock/in/data.ts                      |   11 
 25 files changed, 176 insertions(+), 338 deletions(-)

diff --git a/src/views/crm/saleQuotation/data.ts b/src/views/crm/saleQuotation/data.ts
index ab372f0..f9b8a8c 100644
--- a/src/views/crm/saleQuotation/data.ts
+++ b/src/views/crm/saleQuotation/data.ts
@@ -6,7 +6,6 @@
 import { z } from '#/adapter/form';
 import { getSimpleBusinessList } from '#/api/crm/business';
 import { getSimpleContactList } from '#/api/crm/contact';
-import { getItemPage } from '#/api/mdm/item';
 import { getSimpleUserList } from '#/api/system/user';
 import { useUserStore } from '#/packages/stores/src';
 import CrmCustomerSelect from '#/components/crm-customer-select.vue';
diff --git a/src/views/erp/purchase/in/data.ts b/src/views/erp/purchase/in/data.ts
index ef9d96b..d7ee380 100644
--- a/src/views/erp/purchase/in/data.ts
+++ b/src/views/erp/purchase/in/data.ts
@@ -1,17 +1,19 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
+import { markRaw } from 'vue';
+
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils';
 
 import { z } from '#/adapter/form';
 import { getAccountSimpleList } from '#/api/erp/finance/account';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getSupplierSimpleList } from '#/api/srm/supplier';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
@@ -314,14 +316,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
@@ -531,14 +528,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/purchase/in/modules/item-form.vue b/src/views/erp/purchase/in/modules/item-form.vue
index d53b4fe..fd7a153 100644
--- a/src/views/erp/purchase/in/modules/item-form.vue
+++ b/src/views/erp/purchase/in/modules/item-form.vue
@@ -12,7 +12,6 @@
 import { Input, InputNumber, Select } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getWarehouseStockCount } from '#/api/erp/stock/stock';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 
@@ -40,7 +39,6 @@
 ]);
 
 const tableData = ref<ErpPurchaseInApi.PurchaseInItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<any[]>([]); // 浜у搧涓嬫媺閫夐」
 const warehouseOptions = ref<any[]>([]); // 浠撳簱涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
@@ -192,7 +190,6 @@
 
 /** 鍒濆鍖� */
 onMounted(async () => {
-  productOptions.value = await getProductSimpleList();
   warehouseOptions.value = await getWarehouseSimpleList();
 });
 </script>
@@ -212,15 +209,7 @@
       />
     </template>
     <template #productId="{ row }">
-      <Select
-        disabled
-        v-model:value="row.productId"
-        :options="productOptions"
-        :field-names="{ label: 'name', value: 'id' }"
-        class="w-full"
-        placeholder="璇烽�夋嫨浜у搧"
-        show-search
-      />
+      <span>{{ row.productName || '-' }}</span>
     </template>
     <template #count="{ row }">
       <InputNumber
diff --git a/src/views/erp/purchase/order/modules/item-form.vue b/src/views/erp/purchase/order/modules/item-form.vue
index 009246a..7ba1dc1 100644
--- a/src/views/erp/purchase/order/modules/item-form.vue
+++ b/src/views/erp/purchase/order/modules/item-form.vue
@@ -10,10 +10,10 @@
   erpPriceMultiply,
 } from '@vben/utils';
 
-import { Input, InputNumber, Select, Switch } from 'ant-design-vue';
+import { Input, InputNumber, Switch } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getItemPage } from '#/api/mdm/item';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 import { useFormItemColumns } from '../data';
 
@@ -36,7 +36,6 @@
 ]);
 
 const tableData = ref<ErpPurchaseOrderApi.PurchaseOrderItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<MdmItemApi.Item[]>([]); // 浜у搧涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
 const summaries = computed(() => {
@@ -150,16 +149,15 @@
 }
 
 /** 澶勭悊浜у搧鍙樻洿 */
-async function handleProductChange(productId: any, row: any) {
-  const product = productOptions.value.find((p) => p.id === productId);
-  if (!product) {
+function handleProductChange(item: MdmItemApi.Item | undefined, row: any) {
+  if (!item?.id) {
     return;
   }
-  row.productId = productId;
-  row.productUnitId = product.unitMeasureId;
-  row.productUnitName = product.unitMeasureName;
-  row.productName = product.name;
-  row.productPrice = product.purchasePrice || 0;
+  row.productId = item.id;
+  row.productUnitId = item.unitMeasureId;
+  row.productUnitName = item.unitMeasureName;
+  row.productName = item.name;
+  row.productPrice = item.purchasePrice || 0;
   row.count = row.count || 1;
   handleRowChange(row);
 }
@@ -208,9 +206,7 @@
 });
 
 /** 鍒濆鍖� */
-onMounted(async () => {
-  const res = await getItemPage({ pageNo: 1, pageSize: 100, status: 0 });
-  productOptions.value = res.list || [];
+onMounted(() => {
   // 鐩殑锛氭柊澧炴椂锛岄粯璁ゆ坊鍔犱竴琛�
   if (tableData.value.length === 0) {
     handleAdd();
@@ -221,15 +217,12 @@
 <template>
   <Grid class="w-full">
     <template #productId="{ row }">
-      <Select
+      <MdmItemSelect
         v-if="!disabled"
-        v-model:value="row.productId"
-        :options="productOptions"
-        :field-names="{ label: 'name', value: 'id' }"
-        class="w-full"
+        v-model:model-value="row.productId"
+        :label="row.productName"
         placeholder="璇烽�夋嫨浜у搧"
-        show-search
-        @change="handleProductChange($event, row)"
+        @change="(item) => handleProductChange(item, row)"
       />
       <span v-else>{{ row.productName || '-' }}</span>
     </template>
diff --git a/src/views/erp/purchase/return/data.ts b/src/views/erp/purchase/return/data.ts
index 5bb8b24..d640187 100644
--- a/src/views/erp/purchase/return/data.ts
+++ b/src/views/erp/purchase/return/data.ts
@@ -1,17 +1,19 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
+import { markRaw } from 'vue';
+
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils';
 
 import { z } from '#/adapter/form';
 import { getAccountSimpleList } from '#/api/erp/finance/account';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getSupplierSimpleList } from '#/api/srm/supplier';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
@@ -314,14 +316,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
@@ -512,14 +509,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/purchase/return/modules/item-form.vue b/src/views/erp/purchase/return/modules/item-form.vue
index 93413df..a63e606 100644
--- a/src/views/erp/purchase/return/modules/item-form.vue
+++ b/src/views/erp/purchase/return/modules/item-form.vue
@@ -12,7 +12,6 @@
 import { Input, InputNumber, Select } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getWarehouseStockCount } from '#/api/erp/stock/stock';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 
@@ -40,7 +39,6 @@
 ]);
 
 const tableData = ref<ErpPurchaseReturnApi.PurchaseReturnItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<any[]>([]); // 浜у搧涓嬫媺閫夐」
 const warehouseOptions = ref<any[]>([]); // 浠撳簱涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
@@ -195,7 +193,6 @@
 
 /** 鍒濆鍖� */
 onMounted(async () => {
-  productOptions.value = await getProductSimpleList();
   warehouseOptions.value = await getWarehouseSimpleList();
 });
 </script>
@@ -215,15 +212,7 @@
       />
     </template>
     <template #productId="{ row }">
-      <Select
-        disabled
-        v-model:value="row.productId"
-        :options="productOptions"
-        :field-names="{ label: 'name', value: 'id' }"
-        class="w-full"
-        placeholder="璇烽�夋嫨浜у搧"
-        show-search
-      />
+      <span>{{ row.productName || '-' }}</span>
     </template>
     <template #count="{ row }">
       <InputNumber
diff --git a/src/views/erp/purchase/statistics/price.vue b/src/views/erp/purchase/statistics/price.vue
index 2ab13e1..7f9ac25 100644
--- a/src/views/erp/purchase/statistics/price.vue
+++ b/src/views/erp/purchase/statistics/price.vue
@@ -2,14 +2,16 @@
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 import type { ErpPurchaseStatisticsApi } from '#/api/erp/purchase/statistics';
 
+import { markRaw } from 'vue';
+
 import { Page } from '@vben/common-ui';
 
 import { Tag } from 'ant-design-vue';
 
 import { useVbenVxeGrid } from '#/adapter/vxe-table';
 import { getPriceAnalysis } from '#/api/erp/purchase/statistics';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 import type { VbenFormSchema } from '#/adapter/form';
 
@@ -20,14 +22,9 @@
   {
     fieldName: 'productId',
     label: '浜у搧',
-    component: 'ApiSelect',
+    component: markRaw(MdmItemSelect),
     componentProps: {
       placeholder: '璇烽�夋嫨浜у搧',
-      allowClear: true,
-      showSearch: true,
-      api: getProductSimpleList,
-      labelField: 'name',
-      valueField: 'id',
     },
   },
   {
diff --git a/src/views/erp/sale/order/data.ts b/src/views/erp/sale/order/data.ts
index fc572c7..d5c8233 100644
--- a/src/views/erp/sale/order/data.ts
+++ b/src/views/erp/sale/order/data.ts
@@ -5,10 +5,10 @@
 
 import { z } from '#/adapter/form';
 import { getAccountSimpleList } from '#/api/erp/finance/account';
-import { getItemPage } from '#/api/mdm/item';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps, withoutFixedColumns } from '#/utils';
 import CrmCustomerSelect from '#/components/crm-customer-select.vue';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 import { markRaw } from 'vue';
 
@@ -330,17 +330,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: async () => {
-          const res = await getItemPage({ pageNo: 1, pageSize: 100, status: 0 });
-          return res.list || [];
-        },
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/sale/out/data.ts b/src/views/erp/sale/out/data.ts
index 298eed3..f79df7d 100644
--- a/src/views/erp/sale/out/data.ts
+++ b/src/views/erp/sale/out/data.ts
@@ -1,17 +1,19 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
+import { markRaw } from 'vue';
+
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils';
 
 import { z } from '#/adapter/form';
 import { getAccountSimpleList } from '#/api/erp/finance/account';
-import { getItemPage } from '#/api/mdm/item';
 import { getCustomerSimpleList as getCrmCustomerSimpleList } from '#/api/crm/customer';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
@@ -335,17 +337,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: async () => {
-          const res = await getItemPage({ pageNo: 1, pageSize: 100, status: 0 });
-          return res.list || [];
-        },
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
@@ -540,17 +534,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: async () => {
-          const res = await getItemPage({ pageNo: 1, pageSize: 100, status: 0 });
-          return res.list || [];
-        },
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/sale/out/modules/item-form.vue b/src/views/erp/sale/out/modules/item-form.vue
index 29d57b1..0067dad 100644
--- a/src/views/erp/sale/out/modules/item-form.vue
+++ b/src/views/erp/sale/out/modules/item-form.vue
@@ -1,5 +1,4 @@
 <script lang="ts" setup>
-import type { MdmItemApi } from '#/api/mdm/item';
 import type { ErpSaleOutApi } from '#/api/erp/sale/out';
 
 import { computed, nextTick, onMounted, ref, watch } from 'vue';
@@ -13,7 +12,6 @@
 import { Input, InputNumber, Select } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getItemPage } from '#/api/mdm/item';
 import { getWarehouseStockCount } from '#/api/erp/stock/stock';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 
@@ -41,7 +39,6 @@
 ]);
 
 const tableData = ref<ErpSaleOutApi.SaleOutItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<MdmItemApi.Item[]>([]); // 鐗╂枡涓嬫媺閫夐」
 const warehouseOptions = ref<any[]>([]); // 浠撳簱涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
@@ -193,8 +190,6 @@
 
 /** 鍒濆鍖� */
 onMounted(async () => {
-  const res = await getItemPage({ pageNo: 1, pageSize: 100, status: 0 });
-  productOptions.value = res.list || [];
   warehouseOptions.value = await getWarehouseSimpleList();
 });
 </script>
@@ -214,15 +209,7 @@
       />
     </template>
     <template #productId="{ row }">
-      <Select
-        disabled
-        v-model:value="row.productId"
-        :options="productOptions"
-        :field-names="{ label: 'name', value: 'id' }"
-        class="w-full"
-        placeholder="璇烽�夋嫨浜у搧"
-        show-search
-      />
+      <span>{{ row.productName || '-' }}</span>
     </template>
     <template #count="{ row }">
       <InputNumber
diff --git a/src/views/erp/sale/return/data.ts b/src/views/erp/sale/return/data.ts
index 68e9e22..402c46a 100644
--- a/src/views/erp/sale/return/data.ts
+++ b/src/views/erp/sale/return/data.ts
@@ -1,17 +1,19 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
+import { markRaw } from 'vue';
+
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils';
 
 import { z } from '#/adapter/form';
 import { getAccountSimpleList } from '#/api/erp/finance/account';
-import { getItemPage } from '#/api/mdm/item';
 import { getCustomerSimpleList as getCrmCustomerSimpleList } from '#/api/crm/customer';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
@@ -328,17 +330,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: async () => {
-          const res = await getItemPage({ pageNo: 1, pageSize: 100, status: 0 });
-          return res.list || [];
-        },
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
@@ -529,17 +523,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: async () => {
-          const res = await getItemPage({ pageNo: 1, pageSize: 100, status: 0 });
-          return res.list || [];
-        },
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/sale/return/modules/item-form.vue b/src/views/erp/sale/return/modules/item-form.vue
index 04cb817..1664f09 100644
--- a/src/views/erp/sale/return/modules/item-form.vue
+++ b/src/views/erp/sale/return/modules/item-form.vue
@@ -14,9 +14,9 @@
 import { Input, InputNumber, Select } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getItemPage } from '#/api/mdm/item';
 import { getWarehouseStockCount } from '#/api/erp/stock/stock';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 import { useFormItemColumns } from '../data';
 
@@ -44,7 +44,6 @@
 ]);
 
 const tableData = ref<ErpSaleReturnApi.SaleReturnItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<MdmItemApi.Item[]>([]); // 鐗╂枡涓嬫媺閫夐」
 const warehouseOptions = ref<any[]>([]); // 浠撳簱涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
@@ -164,11 +163,14 @@
   emit('update:items', [...tableData.value]);
 }
 
-/** 澶勭悊浜у搧鍙樻洿锛氫紭鍏堜粠鍏宠仈璁㈠崟鐗╂枡涓~鍏咃紝鍏滃簳浠庡叏閮ㄧ墿鏂欎腑鏌ユ壘 */
-function handleProductChange(row: ErpSaleReturnApi.SaleReturnItem) {
+/** 澶勭悊浜у搧鍙樻洿锛氫紭鍏堜粠鍏宠仈璁㈠崟鐗╂枡涓~鍏咃紝鍏滃簳浣跨敤寮规閫変腑鐨勭墿鏂� */
+function handleProductChange(
+  row: ErpSaleReturnApi.SaleReturnItem,
+  item?: MdmItemApi.Item,
+) {
   // 浼樺厛浠庡叧鑱旇鍗曠殑鐗╂枡涓煡鎵�
   const orderItem = props.orderItems.find(
-    (item) => item.productId === row.productId,
+    (order) => order.productId === row.productId,
   );
   if (orderItem) {
     row.productName = orderItem.productName;
@@ -181,14 +183,12 @@
     handleRowChange(row);
     return;
   }
-  // 鍏滃簳锛氫粠鍏ㄩ儴鐗╂枡涓煡鎵�
-  const product = productOptions.value.find((item) => item.id === row.productId);
-  if (product) {
-    row.productName = product.name || '';
-    row.productPrice = product.salesPrice ?? 0;
-    row.productUnitId = product.unitMeasureId;
-    row.productUnitName = product.unitMeasureName;
-    row.productBarCode = product.barCode;
+  if (item) {
+    row.productName = item.name || '';
+    row.productPrice = item.salesPrice ?? 0;
+    row.productUnitId = item.unitMeasureId;
+    row.productUnitName = item.unitMeasureName;
+    row.productBarCode = item.barCode;
     row.taxPercent = 0;
     row.count = row.count || 1;
     handleRowChange(row);
@@ -250,8 +250,6 @@
 
 /** 鍒濆鍖� */
 onMounted(async () => {
-  const res = await getItemPage({ pageNo: 1, pageSize: 100, status: 0 });
-  productOptions.value = res.list || [];
   warehouseOptions.value = await getWarehouseSimpleList();
 });
 </script>
@@ -272,15 +270,24 @@
     </template>
     <template #productId="{ row }">
       <Select
+        v-if="orderItems?.length"
         :disabled="disabled"
         v-model:value="row.productId"
-        :options="orderItems?.length ? orderItems : productOptions"
-        :field-names="orderItems?.length ? { label: 'productName', value: 'productId' } : { label: 'name', value: 'id' }"
+        :options="orderItems"
+        :field-names="{ label: 'productName', value: 'productId' }"
         class="w-full"
         placeholder="璇烽�夋嫨浜у搧"
         show-search
         @change="handleProductChange(row)"
       />
+      <MdmItemSelect
+        v-else
+        v-model:model-value="row.productId"
+        :label="row.productName"
+        :disabled="disabled"
+        placeholder="璇烽�夋嫨浜у搧"
+        @change="(item) => handleProductChange(row, item)"
+      />
     </template>
     <template #count="{ row }">
       <InputNumber
diff --git a/src/views/erp/stock/check/data.ts b/src/views/erp/stock/check/data.ts
index e65fce8..1d594d5 100644
--- a/src/views/erp/stock/check/data.ts
+++ b/src/views/erp/stock/check/data.ts
@@ -1,13 +1,15 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
+import { markRaw } from 'vue';
+
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
@@ -171,14 +173,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/stock/check/modules/item-form.vue b/src/views/erp/stock/check/modules/item-form.vue
index db56943..b0c70fb 100644
--- a/src/views/erp/stock/check/modules/item-form.vue
+++ b/src/views/erp/stock/check/modules/item-form.vue
@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import type { ErpProductApi } from '#/api/erp/product/product';
+import type { MdmItemApi } from '#/api/mdm/item';
 import type { ErpStockCheckApi } from '#/api/erp/stock/check';
 
 import { computed, nextTick, onMounted, ref, watch } from 'vue';
@@ -13,9 +13,9 @@
 import { Input, InputNumber, Select } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getStockCount } from '#/api/erp/stock/stock';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 import { useFormItemColumns } from '../data';
 
@@ -32,7 +32,6 @@
 const emit = defineEmits(['update:items']);
 
 const tableData = ref<ErpStockCheckApi.StockCheckItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<ErpProductApi.Product[]>([]); // 浜у搧涓嬫媺閫夐」
 const warehouseOptions = ref<any[]>([]); // 浠撳簱涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
@@ -132,21 +131,20 @@
 }
 
 /** 澶勭悊浜у搧鍙樻洿 */
-async function handleProductChange(productId: any, row: any) {
-  const product = productOptions.value.find((p) => p.id === productId);
-  if (!product) {
+async function handleProductChange(item: MdmItemApi.Item | undefined, row: any) {
+  if (!item?.id) {
     return;
   }
-  row.productId = productId;
-  row.productUnitId = product.unitId;
-  row.productBarCode = product.barCode;
-  row.productUnitName = product.unitName;
-  row.productName = product.name;
+  row.productId = item.id;
+  row.productUnitId = item.unitMeasureId;
+  row.productBarCode = item.barCode;
+  row.productUnitName = item.unitMeasureName;
+  row.productName = item.name;
   row.stockCount = row.warehouseId
-    ? (await getStockCount(productId, row.warehouseId)) || 0
-    : (await getStockCount(productId)) || 0;
+    ? (await getStockCount(item.id, row.warehouseId)) || 0
+    : (await getStockCount(item.id)) || 0;
   row.actualCount = row.stockCount || 0;
-  row.productPrice = product.purchasePrice || 0;
+  row.productPrice = item.purchasePrice || 0;
   row.count = row.actualCount - row.stockCount || 0;
   handleRowChange(row);
 }
@@ -205,7 +203,6 @@
 
 /** 鍒濆鍖� */
 onMounted(async () => {
-  productOptions.value = await getProductSimpleList();
   warehouseOptions.value = await getWarehouseSimpleList();
   // 鐩殑锛氭柊澧炴椂锛岄粯璁ゆ坊鍔犱竴琛�
   if (tableData.value.length === 0) {
@@ -229,15 +226,12 @@
       />
     </template>
     <template #productId="{ row }">
-      <Select
-        v-model:value="row.productId"
-        :options="productOptions"
-        :field-names="{ label: 'name', value: 'id' }"
-        class="w-full"
+      <MdmItemSelect
+        v-model:model-value="row.productId"
+        :label="row.productName"
         placeholder="璇烽�夋嫨浜у搧"
-        show-search
         :disabled="disabled"
-        @change="handleProductChange($event, row)"
+        @change="(item) => handleProductChange(item, row)"
       />
     </template>
     <template #actualCount="{ row }">
diff --git a/src/views/erp/stock/in/data.ts b/src/views/erp/stock/in/data.ts
index 353ec6c..636c875 100644
--- a/src/views/erp/stock/in/data.ts
+++ b/src/views/erp/stock/in/data.ts
@@ -1,14 +1,16 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
+import { markRaw } from 'vue';
+
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getSupplierSimpleList } from '#/api/srm/supplier';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
@@ -178,14 +180,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/stock/in/modules/item-form.vue b/src/views/erp/stock/in/modules/item-form.vue
index d1e1f78..5b82b0d 100644
--- a/src/views/erp/stock/in/modules/item-form.vue
+++ b/src/views/erp/stock/in/modules/item-form.vue
@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import type { ErpProductApi } from '#/api/erp/product/product';
+import type { MdmItemApi } from '#/api/mdm/item';
 import type { ErpStockInApi } from '#/api/erp/stock/in';
 
 import { computed, nextTick, onMounted, ref, watch } from 'vue';
@@ -13,9 +13,9 @@
 import { Input, InputNumber, Select } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getStockCount } from '#/api/erp/stock/stock';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 import { useFormItemColumns } from '../data';
 
@@ -32,7 +32,6 @@
 const emit = defineEmits(['update:items']);
 
 const tableData = ref<ErpStockInApi.StockInItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<ErpProductApi.Product[]>([]); // 浜у搧涓嬫媺閫夐」
 const warehouseOptions = ref<any[]>([]); // 浠撳簱涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
@@ -132,20 +131,19 @@
 }
 
 /** 澶勭悊浜у搧鍙樻洿 */
-async function handleProductChange(productId: any, row: any) {
-  const product = productOptions.value.find((p) => p.id === productId);
-  if (!product) {
+async function handleProductChange(item: MdmItemApi.Item | undefined, row: any) {
+  if (!item?.id) {
     return;
   }
-  row.productId = productId;
-  row.productUnitId = product.unitId;
-  row.productBarCode = product.barCode;
-  row.productUnitName = product.unitName;
-  row.productName = product.name;
+  row.productId = item.id;
+  row.productUnitId = item.unitMeasureId;
+  row.productBarCode = item.barCode;
+  row.productUnitName = item.unitMeasureName;
+  row.productName = item.name;
   row.stockCount = row.warehouseId
-    ? (await getStockCount(productId, row.warehouseId)) || 0
-    : (await getStockCount(productId)) || 0;
-  row.productPrice = product.purchasePrice || 0;
+    ? (await getStockCount(item.id, row.warehouseId)) || 0
+    : (await getStockCount(item.id)) || 0;
+  row.productPrice = item.purchasePrice || 0;
   row.count = row.count || 1;
   handleRowChange(row);
 }
@@ -195,7 +193,6 @@
 
 /** 鍒濆鍖� */
 onMounted(async () => {
-  productOptions.value = await getProductSimpleList();
   warehouseOptions.value = await getWarehouseSimpleList();
   // 鐩殑锛氭柊澧炴椂锛岄粯璁ゆ坊鍔犱竴琛�
   if (tableData.value.length === 0) {
@@ -219,15 +216,12 @@
       />
     </template>
     <template #productId="{ row }">
-      <Select
-        v-model:value="row.productId"
-        :options="productOptions"
-        :field-names="{ label: 'name', value: 'id' }"
-        class="w-full"
+      <MdmItemSelect
+        v-model:model-value="row.productId"
+        :label="row.productName"
         placeholder="璇烽�夋嫨浜у搧"
-        show-search
         :disabled="disabled"
-        @change="handleProductChange($event, row)"
+        @change="(item) => handleProductChange(item, row)"
       />
     </template>
     <template #count="{ row }">
diff --git a/src/views/erp/stock/move/data.ts b/src/views/erp/stock/move/data.ts
index 4a0bac9..c48e3d7 100644
--- a/src/views/erp/stock/move/data.ts
+++ b/src/views/erp/stock/move/data.ts
@@ -1,13 +1,15 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
+import { markRaw } from 'vue';
+
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
@@ -169,14 +171,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/stock/move/modules/item-form.vue b/src/views/erp/stock/move/modules/item-form.vue
index fd85283..70f04fd 100644
--- a/src/views/erp/stock/move/modules/item-form.vue
+++ b/src/views/erp/stock/move/modules/item-form.vue
@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import type { ErpProductApi } from '#/api/erp/product/product';
+import type { MdmItemApi } from '#/api/mdm/item';
 import type { ErpStockMoveApi } from '#/api/erp/stock/move';
 
 import { computed, nextTick, onMounted, ref, watch } from 'vue';
@@ -13,9 +13,9 @@
 import { Input, InputNumber, Select } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getStockCount } from '#/api/erp/stock/stock';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 import { useFormItemColumns } from '../data';
 
@@ -32,7 +32,6 @@
 const emit = defineEmits(['update:items']);
 
 const tableData = ref<ErpStockMoveApi.StockMoveItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<ErpProductApi.Product[]>([]); // 浜у搧涓嬫媺閫夐」
 const warehouseOptions = ref<any[]>([]); // 浠撳簱涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
@@ -140,20 +139,19 @@
 }
 
 /** 澶勭悊浜у搧鍙樻洿 */
-async function handleProductChange(productId: any, row: any) {
-  const product = productOptions.value.find((p) => p.id === productId);
-  if (!product) {
+async function handleProductChange(item: MdmItemApi.Item | undefined, row: any) {
+  if (!item?.id) {
     return;
   }
-  row.productId = productId;
-  row.productUnitId = product.unitId;
-  row.productBarCode = product.barCode;
-  row.productUnitName = product.unitName;
-  row.productName = product.name;
+  row.productId = item.id;
+  row.productUnitId = item.unitMeasureId;
+  row.productBarCode = item.barCode;
+  row.productUnitName = item.unitMeasureName;
+  row.productName = item.name;
   row.stockCount = row.fromWarehouseId
-    ? (await getStockCount(productId, row.fromWarehouseId)) || 0
-    : (await getStockCount(productId)) || 0;
-  row.productPrice = product.purchasePrice || 0;
+    ? (await getStockCount(item.id, row.fromWarehouseId)) || 0
+    : (await getStockCount(item.id)) || 0;
+  row.productPrice = item.purchasePrice || 0;
   row.count = row.count || 1;
   handleRowChange(row);
 }
@@ -203,7 +201,6 @@
 
 /** 鍒濆鍖� */
 onMounted(async () => {
-  productOptions.value = await getProductSimpleList();
   warehouseOptions.value = await getWarehouseSimpleList();
   // 鐩殑锛氭柊澧炴椂锛岄粯璁ゆ坊鍔犱竴琛�
   if (tableData.value.length === 0) {
@@ -239,15 +236,12 @@
       />
     </template>
     <template #productId="{ row }">
-      <Select
-        v-model:value="row.productId"
-        :options="productOptions"
-        :field-names="{ label: 'name', value: 'id' }"
-        class="w-full"
+      <MdmItemSelect
+        v-model:model-value="row.productId"
+        :label="row.productName"
         placeholder="璇烽�夋嫨浜у搧"
-        show-search
         :disabled="disabled"
-        @change="handleProductChange($event, row)"
+        @change="(item) => handleProductChange(item, row)"
       />
     </template>
     <template #count="{ row }">
diff --git a/src/views/erp/stock/out/data.ts b/src/views/erp/stock/out/data.ts
index 524e3a6..594fe54 100644
--- a/src/views/erp/stock/out/data.ts
+++ b/src/views/erp/stock/out/data.ts
@@ -1,14 +1,16 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
+import { markRaw } from 'vue';
+
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getCustomerSimpleList } from '#/api/erp/sale/customer';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getSimpleUserList } from '#/api/system/user';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'edit';
@@ -180,16 +182,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        fieldNames: {
-          label: 'name',
-          value: 'id',
-        },
       },
     },
     {
diff --git a/src/views/erp/stock/out/modules/item-form.vue b/src/views/erp/stock/out/modules/item-form.vue
index 1de8431..b1b614b 100644
--- a/src/views/erp/stock/out/modules/item-form.vue
+++ b/src/views/erp/stock/out/modules/item-form.vue
@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import type { ErpProductApi } from '#/api/erp/product/product';
+import type { MdmItemApi } from '#/api/mdm/item';
 import type { ErpStockOutApi } from '#/api/erp/stock/out';
 
 import { computed, nextTick, onMounted, ref, watch } from 'vue';
@@ -13,9 +13,9 @@
 import { Input, InputNumber, Select } from 'ant-design-vue';
 
 import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
-import { getProductSimpleList } from '#/api/erp/product/product';
 import { getStockCount } from '#/api/erp/stock/stock';
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 import { useFormItemColumns } from '../data';
 
@@ -32,7 +32,6 @@
 const emit = defineEmits(['update:items']);
 
 const tableData = ref<ErpStockOutApi.StockOutItem[]>([]); // 琛ㄦ牸鏁版嵁
-const productOptions = ref<ErpProductApi.Product[]>([]); // 浜у搧涓嬫媺閫夐」
 const warehouseOptions = ref<any[]>([]); // 浠撳簱涓嬫媺閫夐」
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
@@ -129,20 +128,19 @@
 }
 
 /** 澶勭悊浜у搧鍙樻洿 */
-async function handleProductChange(productId: any, row: any) {
-  const product = productOptions.value.find((p) => p.id === productId);
-  if (!product) {
+async function handleProductChange(item: MdmItemApi.Item | undefined, row: any) {
+  if (!item?.id) {
     return;
   }
-  row.productId = productId;
-  row.productUnitId = product.unitId;
-  row.productBarCode = product.barCode;
-  row.productUnitName = product.unitName;
-  row.productName = product.name;
+  row.productId = item.id;
+  row.productUnitId = item.unitMeasureId;
+  row.productBarCode = item.barCode;
+  row.productUnitName = item.unitMeasureName;
+  row.productName = item.name;
   row.stockCount = row.warehouseId
-    ? (await getStockCount(productId, row.warehouseId)) || 0
-    : (await getStockCount(productId)) || 0;
-  row.productPrice = product.purchasePrice || 0;
+    ? (await getStockCount(item.id, row.warehouseId)) || 0
+    : (await getStockCount(item.id)) || 0;
+  row.productPrice = item.purchasePrice || 0;
   row.count = row.count || 1;
   handleRowChange(row);
 }
@@ -192,7 +190,6 @@
 
 /** 鍒濆鍖� */
 onMounted(async () => {
-  productOptions.value = await getProductSimpleList();
   warehouseOptions.value = await getWarehouseSimpleList();
   // 鐩殑锛氭柊澧炴椂锛岄粯璁ゆ坊鍔犱竴琛�
   if (tableData.value.length === 0) {
@@ -216,15 +213,12 @@
       />
     </template>
     <template #productId="{ row }">
-      <Select
-        v-model:value="row.productId"
-        :options="productOptions"
-        :field-names="{ label: 'name', value: 'id' }"
-        class="w-full"
+      <MdmItemSelect
+        v-model:model-value="row.productId"
+        :label="row.productName"
         placeholder="璇烽�夋嫨浜у搧"
-        show-search
         :disabled="disabled"
-        @change="handleProductChange($event, row)"
+        @change="(item) => handleProductChange(item, row)"
       />
     </template>
     <template #count="{ row }">
diff --git a/src/views/erp/stock/record/data.ts b/src/views/erp/stock/record/data.ts
index e4e3d0e..25b9b03 100644
--- a/src/views/erp/stock/record/data.ts
+++ b/src/views/erp/stock/record/data.ts
@@ -4,9 +4,11 @@
 import { DICT_TYPE } from '@vben/constants';
 import { getDictOptions } from '@vben/hooks';
 
-import { getProductSimpleList } from '#/api/erp/product/product';
+import { markRaw } from 'vue';
+
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
 import { getRangePickerDefaultProps } from '#/utils';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 鎼滅储琛ㄥ崟 */
 export function useGridFormSchema(): VbenFormSchema[] {
@@ -14,14 +16,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/erp/stock/stock/data.ts b/src/views/erp/stock/stock/data.ts
index 037bb9c..5cee07a 100644
--- a/src/views/erp/stock/stock/data.ts
+++ b/src/views/erp/stock/stock/data.ts
@@ -1,8 +1,10 @@
 import type { VbenFormSchema } from '#/adapter/form';
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 
-import { getProductSimpleList } from '#/api/erp/product/product';
+import { markRaw } from 'vue';
+
 import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 
 /** 鎼滅储琛ㄥ崟 */
 export function useGridFormSchema(): VbenFormSchema[] {
@@ -10,14 +12,9 @@
     {
       fieldName: 'productId',
       label: '浜у搧',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧',
-        allowClear: true,
-        showSearch: true,
-        api: getProductSimpleList,
-        labelField: 'name',
-        valueField: 'id',
       },
     },
     {
diff --git a/src/views/mes/qc/template/data.ts b/src/views/mes/qc/template/data.ts
index 2403139..5cf1673 100644
--- a/src/views/mes/qc/template/data.ts
+++ b/src/views/mes/qc/template/data.ts
@@ -17,7 +17,7 @@
 
 import { z } from '#/adapter/form';
 import { generateAutoCode } from '#/api/mes/md/autocode/record';
-import { getItemSimpleList } from '#/api/mdm/item';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 import { MdUnitMeasureSelect } from '#/views/mes/md/unitmeasure/components';
 import { QcIndicatorSelect } from '#/views/mes/qc/indicator/components';
 
@@ -421,18 +421,9 @@
     {
       fieldName: 'itemId',
       label: '浜у搧鐗╂枡',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨浜у搧鐗╂枡',
-        allowClear: true,
-        showSearch: true,
-        api: getItemSimpleList,
-        labelField: 'name',
-        valueField: 'id',
-        optionRender: (option: any) => {
-          const item = option.data;
-          return `${item.code} - ${item.name}`;
-        },
       },
       formItemClass: 'col-span-3',
       rules: 'required',
diff --git a/src/views/srm/tender/detail.vue b/src/views/srm/tender/detail.vue
index fda47ec..afcabf7 100644
--- a/src/views/srm/tender/detail.vue
+++ b/src/views/srm/tender/detail.vue
@@ -19,9 +19,10 @@
   createAward, deleteAward, getAward, getAwardByProject, approveAward, generatePurchaseOrder,
   confirmTenderProject,
 } from '#/api/srm/tender';
-import { getSupplierList } from '#/api/srm/supplier';
-import { getItemSimpleList } from '#/api/mdm/item';
 import type { MdmItemApi } from '#/api/mdm/item';
+
+import { getSupplierList } from '#/api/srm/supplier';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 import {
   TENDER_STATUS,
   TENDER_STATUS_CELLTAG,
@@ -45,16 +46,10 @@
 const activeTab = ref('info');
 
 // ========== 涓嬫媺閫夐」鏁版嵁 ==========
-const mdmItemList = ref<MdmItemApi.Item[]>([]);
 const supplierList = ref<{ id: number; name: string }[]>([]);
 
 onMounted(async () => {
-  const [items, suppliers] = await Promise.all([
-    getItemSimpleList(),
-    getSupplierList(),
-  ]);
-  mdmItemList.value = items;
-  supplierList.value = suppliers;
+  supplierList.value = await getSupplierList();
 });
 
 const filterOption = (input: string, option: any) =>
@@ -80,11 +75,6 @@
   return ids;
 });
 
-// 鐗╂枡涓嬫媺鍙�夊垪琛紙鎺掗櫎宸叉坊鍔犵殑锛�
-const availableMdmItems = computed(() =>
-  mdmItemList.value.filter((item) => !addedProductIds.value.has(item.id!)),
-);
-
 async function loadProject() {
   project.value = await getTenderProject(projectId);
 }
@@ -93,6 +83,11 @@
   try { materialList.value = await getMaterialList(projectId); } finally { materialLoading.value = false; }
 }
 async function handleSaveMaterial() {
+  // 鍚屼竴鎷涙爣椤圭洰涓嬩笉鍏佽閲嶅娣诲姞鍚屼竴鐗╂枡
+  if (materialForm.value.productId && addedProductIds.value.has(materialForm.value.productId)) {
+    message.warning('璇ョ墿鏂欏凡娣诲姞锛岃鍕块噸澶嶆坊鍔�');
+    return;
+  }
   if (materialForm.value.id) {
     await updateMaterial(materialForm.value);
   } else {
@@ -101,8 +96,7 @@
   materialFormVisible.value = false;
   loadMaterials();
 }
-function onMaterialSelect(itemId: number) {
-  const item = mdmItemList.value.find((i) => i.id === itemId);
+function onMaterialSelect(item?: MdmItemApi.Item) {
   if (item) {
     materialForm.value.productCode = item.code;
     materialForm.value.productName = item.name;
@@ -918,14 +912,12 @@
       <a-modal v-model:open="materialFormVisible" :title="materialForm.id ? '缂栬緫鐗╂枡' : '娣诲姞鐗╂枡'" :width="560" @ok="handleSaveMaterial">
         <a-form layout="vertical" class="mt-4">
           <a-form-item label="MDM鐗╂枡" required>
-            <a-select v-model:value="materialForm.productId" show-search placeholder="鎼滅储骞堕�夋嫨MDM鐗╂枡" :filter-option="filterOption" option-label-prop="label" @change="onMaterialSelect">
-              <a-select-option v-for="item in availableMdmItems" :key="item.id" :value="item.id" :label="`${item.code} ${item.name}`">
-                <div class="flex flex-col">
-                  <span class="font-medium">{{ item.code }}</span>
-                  <span class="text-xs text-gray-400">{{ item.name }}{{ item.specification ? ` 路 ${item.specification}` : '' }}</span>
-                </div>
-              </a-select-option>
-            </a-select>
+            <MdmItemSelect
+              v-model:model-value="materialForm.productId"
+              :label="materialForm.productName"
+              placeholder="璇烽�夋嫨MDM鐗╂枡"
+              @change="onMaterialSelect"
+            />
           </a-form-item>
           <a-row :gutter="12">
             <a-col :span="12">
diff --git a/src/views/wls/arrivalnotice/data.ts b/src/views/wls/arrivalnotice/data.ts
index 4fd3a0b..995e60f 100644
--- a/src/views/wls/arrivalnotice/data.ts
+++ b/src/views/wls/arrivalnotice/data.ts
@@ -11,10 +11,10 @@
 
 import { z } from '#/adapter/form';
 import { generateAutoCode } from '#/api/mes/md/autocode/record';
-import { getItemPage } from '#/api/mdm/item';
 import { getRangePickerDefaultProps } from '#/utils';
-import { MdVendorSelect } from '#/views/mes/md/vendor/components';
+import { MdmItemSelect } from '#/views/basicData/mdm/components';
 import { ErpPurchaseOrderSelect } from '#/views/erp/purchase/order/components';
+import { MdVendorSelect } from '#/views/mes/md/vendor/components';
 
 /** 琛ㄥ崟绫诲瀷 */
 export type FormType = 'create' | 'detail' | 'update';
@@ -347,19 +347,9 @@
     {
       fieldName: 'itemId',
       label: '鐗╂枡',
-      component: 'ApiSelect',
+      component: markRaw(MdmItemSelect),
       componentProps: {
         placeholder: '璇烽�夋嫨鐗╂枡',
-        allowClear: true,
-        showSearch: true,
-        api: getItemPage,
-        resultField: 'list',
-        labelField: 'name',
-        valueField: 'id',
-        optionRender: (option: any) => {
-          const item = option.data;
-          return `${item.code} - ${item.name}`;
-        },
       },
       rules: 'required',
     },

--
Gitblit v1.9.3