From 7972a9b96ccec053cb34a7c31008c5c98c87ad9b Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期二, 20 一月 2026 17:45:17 +0800
Subject: [PATCH] Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New

---
 src/views/inventoryManagement/receiptManagement/components/formDia.vue |  400 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 400 insertions(+), 0 deletions(-)

diff --git a/src/views/inventoryManagement/receiptManagement/components/formDia.vue b/src/views/inventoryManagement/receiptManagement/components/formDia.vue
new file mode 100644
index 0000000..5ea86b2
--- /dev/null
+++ b/src/views/inventoryManagement/receiptManagement/components/formDia.vue
@@ -0,0 +1,400 @@
+<template>
+  <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="70%"
+    @close="closeDia">
+    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+      <el-form-item label="閲囪喘璁㈠崟鍙�" prop="purchaseContractNumber">
+        <el-select
+          v-model="form.purchaseContractNumber"
+          placeholder="璇烽�夋嫨閲囪喘璁㈠崟鍙�"
+          clearable
+          filterable
+          :loading="loadingPurchaseOptions"
+          @change="handlePurchaseChange"
+          :disabled="operationType === 'edit'"
+          style="width: 100%"
+        >
+          <el-option
+            v-for="item in purchaseOptions"
+            :key="item.purchaseContractNumber"
+            :label="formatPurchaseOption(item)"
+            :value="item.purchaseContractNumber"
+          />
+        </el-select>
+      </el-form-item>
+      <el-table
+        :data="productList"
+        border
+        v-loading="loadingProducts"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column align="center" type="selection" width="55" />
+        <el-table-column
+          align="center"
+          label="搴忓彿"
+          type="index"
+          width="60"
+        />
+        <el-table-column label="浜у搧澶х被" prop="productCategory" />
+        <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+        <el-table-column label="鍗曚綅" prop="unit" width="70" />
+        <!-- <el-table-column label="渚涘簲鍟�" prop="supplierName" width="100" /> -->
+        <el-table-column label="閲囪喘鏁伴噺" prop="quantity" width="100" />
+        <el-table-column label="寰呭叆搴撴暟閲�" prop="quantity0" width="100" />
+        <el-table-column label="鏈鍏ュ簱鏁伴噺" prop="quantityStock" width="150">
+          <template #default="scope">
+            <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" />
+          </template>
+        </el-table-column>
+        <el-table-column label="绋庣巼(%)" prop="taxRate" width="120" />
+        <el-table-column label="鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" width="150">
+					<template #default="scope">
+						<el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" :disabled="operationType === 'edit'"/>
+					</template>
+				</el-table-column>
+        <el-table-column
+          label="鎬讳环(鍏�)"
+					:formatter="formattedNumber"
+          prop="taxInclusiveTotalPrice"
+          width="150"
+        >
+        </el-table-column>
+      </el-table>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button type="primary" @click="submitForm">纭</el-button>
+        <el-button @click="closeDia">鍙栨秷</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
+import useUserStore from '@/store/modules/user'
+import {
+  updateStockIn,
+  addSutockIn,
+  selectProductRecordListByPuechaserId
+} from "@/api/inventoryManagement/stockIn.js";
+import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js";
+
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close', 'success'])
+
+const operationType = ref('')// 鎿嶄綔绫诲瀷: 'add' 鎴� 'edit'
+const dialogFormVisible = ref(false)// 寮规鏄剧ず鐘舵��
+const productList = ref([]);// 浜у搧鍒楄〃鏁版嵁
+const loadingProducts = ref(false);// 浜у搧鍔犺浇鐘舵��
+const selectedRows = ref([]) // 浜у搧琛ㄦ牸閫変腑琛�
+const purchaseOptions = ref([])
+const loadingPurchaseOptions = ref(false)
+const loading = ref(false);
+
+const data = reactive({
+  form: {
+    id: null,
+    purchaseContractNumber: '', // 閲囪喘璁㈠崟鍙�
+    supplierId: null,       // 渚涘簲鍟咺D
+    supplierName: '',       // 渚涘簲鍟嗗悕绉�
+    inboundTime: '',        // 鍏ュ簱鏃堕棿
+    inboundBatch: '',       // 鍏ュ簱鎵规
+    recorderId: userStore.userId, // 褰曞叆浜篒D
+    recorderName: userStore.name, // 褰曞叆浜哄鍚�
+    entryDate: getCurrentDate(),  // 褰曞叆鏃ユ湡
+    remark: '',             // 澶囨敞
+  },
+  rules: {
+    purchaseContractNumber: [{ required: true, message: "璇疯緭鍏ラ噰璐悎鍚屽彿", trigger: "blur" }],
+    supplierId: [{ required: true, message: "璇烽�夋嫨渚涘簲鍟�", trigger: "change" }],
+    inboundTime: [{ required: true, message: "璇烽�夋嫨鍏ュ簱鏃堕棿", trigger: "change" }],
+    inboundBatch: [{ required: true, message: "璇疯緭鍏ュ叆搴撴壒娆�", trigger: "blur" }]
+  }
+})
+const { form, rules } = toRefs(data)
+
+// 鍔ㄦ�佽绠楀璇濇鏍囬
+const getDialogTitle = () => {
+  return operationType.value === 'add' ? '鏂板鍏ュ簱' : '缂栬緫鍏ュ簱'
+}
+
+const formatPurchaseOption = (item = {}) => {
+  const contract = item.purchaseContractNumber || '--';
+  const supplier = item.supplierName ? ` 路 ${item.supplierName}` : '';
+  return `${contract}${supplier}`;
+};
+
+const loadPurchaseOptions = async (keyword = '') => {
+  try {
+    loadingPurchaseOptions.value = true;
+    const res = await purchaseListPage({
+      current: -1,
+      size: -1,
+      purchaseContractNumber: keyword,
+    });
+    const records = res.data?.records || [];
+    purchaseOptions.value = records;
+    if (
+      form.value.purchaseContractNumber &&
+      !purchaseOptions.value.find(
+        (item) => item.purchaseContractNumber === form.value.purchaseContractNumber
+      )
+    ) {
+      purchaseOptions.value.push({
+        purchaseContractNumber: form.value.purchaseContractNumber,
+        supplierName: form.value.supplierName,
+        supplierId: form.value.supplierId,
+      });
+    }
+  } finally {
+    loadingPurchaseOptions.value = false;
+  }
+};
+
+const handlePurchaseChange = (value) => {
+  form.value.purchaseContractNumber = value || '';
+  const matched = purchaseOptions.value.find(
+    (item) => item.purchaseContractNumber === value
+  );
+  if (matched) {
+    form.value.supplierName = matched.supplierName || form.value.supplierName;
+    form.value.supplierId = matched.supplierId || form.value.supplierId;
+  }
+  if (!value) {
+    productList.value = [];
+    return;
+  }
+  fetchProductsByContract();
+};
+
+const exceedsAddLimit = (product) => {
+  const stock = Number(product?.quantityStock ?? 0);
+  const waiting = Number(product?.quantity0 ?? 0);
+  if (!Number.isFinite(stock) || !Number.isFinite(waiting)) {
+    return false;
+  }
+  return stock > waiting;
+};
+
+const exceedsEditLimit = (product) => {
+  const stock = Number(product?.quantityStock ?? 0);
+  const waiting = Number(product?.quantity0 ?? 0);
+  const original = Number(product?.originalQuantityStock ?? 0);
+  if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) {
+    return false;
+  }
+  return stock > waiting + original;
+};
+
+const formattedNumber = (row, column, cellValue) => {
+  return parseFloat(cellValue).toFixed(2);
+};
+
+// 璁$畻鎬讳环
+const calculateTotalPrice = (row) => {
+  const quantityStock = Number(row?.quantityStock ?? 0);
+  const taxInclusiveUnitPrice = Number(row?.taxInclusiveUnitPrice ?? 0);
+  
+  if (Number.isFinite(quantityStock) && Number.isFinite(taxInclusiveUnitPrice)) {
+    row.taxInclusiveTotalPrice = quantityStock * taxInclusiveUnitPrice;
+  } else {
+    row.taxInclusiveTotalPrice = 0;
+  }
+};
+
+const fetchProductsByContract = async () => {
+  if (!form.value.purchaseContractNumber) {
+    proxy.$modal.msgWarning('璇烽�夋嫨鍚堝悓鍙�')
+    return
+  }
+  try {
+    loadingProducts.value = true
+    const productRes = await selectProductRecordListByPuechaserId({
+      purchaseContractNumber: form.value.purchaseContractNumber
+    });
+    if (!productRes.data || productRes.data.length === 0) {
+      proxy.$modal.msgWarning('璇ュ悎鍚屼笅娌℃湁浜у搧璁板綍')
+      productList.value = [];
+      return
+    }
+    productList.value = productRes.data.map(item => ({
+      ...item,
+      quantityStock: 0,
+      taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0),
+      taxInclusiveTotalPrice: 0,
+      originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0),
+    }))
+  } catch (error) {
+    console.error('鏌ヨ浜у搧璁板綍澶辫触:', error)
+    proxy.$modal.msgError('鏌ヨ浜у搧璁板綍澶辫触')
+    productList.value = [];
+  } finally {
+    loadingProducts.value = false
+  }
+}
+
+const updatePro = async () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning('璇峰厛閫夋嫨浜у搧');
+    return;
+  }
+  const target = selectedRows.value[0];
+  const stock = Number(target?.quantityStock ?? 0);
+  if (!Number.isFinite(stock) || stock <= 0) {
+    proxy.$modal.msgWarning('璇峰~鍐欐湁鏁堢殑鍏ュ簱鏁伴噺');
+    return;
+  }
+  if (exceedsEditLimit(target)) {
+    proxy.$modal.msgError('鏈鍏ュ簱鏁伴噺涓嶈兘瓒呰繃鍘熷叆搴撴暟閲忎笌寰呭叆搴撴暟閲忎箣鍜�');
+    return;
+  }
+  const stockInData = {
+    id: selectedRows.value[0].recordId,
+    quantityStock: Number(selectedRows.value[0].quantityStock),
+  };
+  await updateStockIn(stockInData)
+  proxy.$modal.msgSuccess('淇敼鍏ュ簱鎴愬姛')
+  closeDia()
+  emit('success')
+}
+
+const submitForm = async () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning('璇峰厛閫夋嫨閲囪喘鍚堝悓骞堕�夋嫨浜у搧')
+    return
+  }
+  if(operationType.value !== 'add'){
+    await updatePro()
+    return
+  }
+  try {
+    await proxy.$refs.formRef.validate()
+    const invalidProducts = selectedRows.value.filter((product) => {
+        const stock = Number(product?.quantityStock ?? 0);
+        if (!Number.isFinite(stock) || stock <= 0) {
+          return true;
+        }
+        return exceedsAddLimit(product);
+    })
+
+    if (invalidProducts.length > 0) {
+      proxy.$modal.msgError('鏈鍏ュ簱鏁伴噺闇�澶т簬0锛屼笖涓嶈兘瓒呰繃寰呭叆搴撴暟閲�')
+      return
+    }
+
+    const stockInData = {
+      ...form.value,
+      inboundTime: formatDateTime(form.value.inboundTime),
+      nickName: userStore.nickName,
+      details: selectedRows.value.map(product => ({
+        id: product.id,
+        inboundQuantity: Number(product.quantityStock),
+				unitPrice: Number(product.taxInclusiveUnitPrice),
+        taxRate: Number(product.taxRate),
+				taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice)
+      })),
+    };
+    loading.value = true
+    await addSutockIn(stockInData)
+
+    proxy.$modal.msgSuccess('鏂板鍏ュ簱鎴愬姛')
+    closeDia()
+    emit('success')
+
+  } catch (error) {
+    console.error('鎻愪氦澶辫触:', error)
+    if (!error.errors) {
+      proxy.$modal.msgError('鎿嶄綔澶辫触锛岃閲嶈瘯')
+    }
+  } finally {
+    loading.value = false
+  }
+}
+
+const closeDia = () => {
+  proxy.$refs.formRef.resetFields()
+  dialogFormVisible.value = false
+  emit('close')
+}
+
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection.filter(item => item.id);
+}
+
+function formatDateTime(date = new Date(), includeTime = true) {
+  const d = new Date(date);
+  const year = d.getFullYear();
+  const month = String(d.getMonth() + 1).padStart(2, '0');
+  const day = String(d.getDate()).padStart(2, '0');
+
+  if (!includeTime) {
+    return `${year}-${month}-${day}`;
+  }
+
+  const hours = String(d.getHours()).padStart(2, '0');
+  const minutes = String(d.getMinutes()).padStart(2, '0');
+  const seconds = String(d.getSeconds()).padStart(2, '0');
+
+  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}
+
+function getCurrentDate() {
+  return formatDateTime(new Date(), false);
+}
+
+const openDialog = async (type, row) => {
+  operationType.value = type
+  dialogFormVisible.value = true
+  selectedRows.value = []
+  await loadPurchaseOptions();
+
+  if (type === 'add') {
+    form.value = {
+      id: null,
+      purchaseContractNumber: '',
+      supplierId: null,
+      supplierName: '',
+      inboundTime: '',
+      inboundBatch: '',
+      recorderId: userStore.userId,
+      recorderName: userStore.name,
+      entryDate: getCurrentDate(),
+      remark: ''
+    }
+    productList.value = []
+  } else {
+    form.value = JSON.parse(JSON.stringify(row))
+    try {
+      loadingProducts.value = true
+      const res = await selectProductRecordListByPuechaserId({
+        purchaseContractNumber: form.value.purchaseContractNumber,
+        id: row.id
+      });
+      productList.value = res.data.map(item => ({
+        ...item,
+        quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
+        taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0),
+        taxInclusiveTotalPrice: Number(item?.quantityStock ?? 0) * Number(item?.taxInclusiveUnitPrice ?? 0),
+        originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
+      }))
+      selectedRows.value = productList.value
+    } catch (error) {
+      console.error('鍔犺浇浜у搧澶辫触:', error)
+      proxy.$modal.msgError('鍔犺浇浜у搧澶辫触')
+      productList.value = []
+    } finally {
+      loadingProducts.value = false
+    }
+  }
+}
+
+defineExpose({
+  openDialog,
+})
+</script>
+
+<style scoped lang="scss"></style>
+
+
+

--
Gitblit v1.9.3