From 7b7accc4ce1c1ccfc7a006980e1d3e4d0fbc56e8 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 06 一月 2026 16:57:33 +0800
Subject: [PATCH] 双奇点 1.编辑采购台账时,删除产品时,弹出两个提示需修改下 2.采购台账添加附件操作按钮和页面

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

diff --git a/src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue b/src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue
new file mode 100644
index 0000000..016fef6
--- /dev/null
+++ b/src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue
@@ -0,0 +1,401 @@
+<template>
+  <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '鏂板鑷畾涔夊叆搴�' : '缂栬緫鑷畾涔夊叆搴�'" width="70%"
+    @close="closeDia">
+    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+      <div style="margin-bottom: 10px;" v-if="operationType === 'add'">
+        <el-button type="primary" @click="addProductRow">鏂板</el-button>
+      </div>
+      <el-table
+        :data="productList"
+        border
+        v-loading="loadingProducts"
+      >
+        <el-table-column
+          align="center"
+          label="搴忓彿"
+          type="index"
+          width="60"
+        />
+        <el-table-column label="浜у搧鍥剧墖" align="center" prop="productCategory" width="100">
+          <template #default="scope">
+            <el-upload
+              :action="uploadUrl"
+              :before-upload="handleBeforeUpload"
+              :on-success="(res,file)=>{handleUploadSuccess(res,file,scope.row)}"
+              :on-error="handleUploadError"
+              name="file"
+              :show-file-list="false"
+              :headers="headers"
+              accept="image/*"
+              :data="{ type: 9 }"
+            >
+              <img class="upload-img" v-if="scope.row.url" :src="javaApiUrl+scope.row.url"></img>
+              <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
+            </el-upload>
+          </template>
+        </el-table-column>
+        <el-table-column label="浜у搧鍚嶇О" prop="productCategory" width="200">
+          <template #default="scope">
+            <el-input v-model="scope.row.productCategory" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+          </template>
+        </el-table-column>
+        <el-table-column label="浜у搧楂樺害" prop="specificationModel" width="200">
+          <template #default="scope">
+            <el-input v-model="scope.row.specificationModel" placeholder="璇疯緭鍏ヤ骇鍝侀珮搴�" />
+          </template>
+        </el-table-column>
+        <el-table-column label="绾哥瑙勬牸" prop="cartonSpecifications" width="200">
+          <template #default="scope">
+            <el-input v-model="scope.row.cartonSpecifications" placeholder="璇疯緭鍏ョ焊绠辫鏍�" />
+          </template>
+        </el-table-column>
+        <el-table-column label="鍏ュ簱鏁伴噺-浠�" prop="inboundNum" width="150">
+          <template #default="scope">
+            <el-input-number :step="1" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" />
+          </template>
+        </el-table-column>
+        <el-table-column label="姣忎欢鏁伴噺/鏀�" prop="boxNum" width="150">
+          <template #default="scope">
+            <el-input-number :step="1" :min="0" style="width: 100%" v-model="scope.row.boxNum" @change="() => calculateTotalPrice(scope.row)" />
+          </template>
+        </el-table-column>
+        <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)" />
+         </template>
+       </el-table-column>
+        <el-table-column label="鍏ュ簱鏃ユ湡" prop="inboundDate" width="180">
+          <template #default="scope">
+            <el-date-picker
+              v-model="scope.row.inboundDate"
+              type="date"
+              placeholder="璇烽�夋嫨鍏ュ簱鏃ユ湡"
+              value-format="YYYY-MM-DD"
+              format="YYYY-MM-DD"
+              style="width: 100%"
+            />
+          </template>
+        </el-table-column>
+<!--        <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="taxInclusiveTotalPrice" -->
+<!--           width="150" -->
+<!--         >-->
+<!--        </el-table-column>-->
+        <el-table-column label="鎿嶄綔" width="80" v-if="operationType === 'add'">
+          <template #default="scope">
+            <el-button type="danger" size="small" @click="removeProductRow(scope.$index)">鍒犻櫎</el-button>
+          </template>
+        </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 {
+  addStockInCustom,
+  updateStockInCustom,
+} from "@/api/inventoryManagement/stockIn.js";
+import { getToken } from "@/utils/auth";
+const headers = ref({
+  Authorization: "Bearer " + getToken(),
+});
+
+const javaApiUrl = __BASE_API__;
+
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close', 'success'])
+
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+
+const operationType = ref('')// 鎿嶄綔绫诲瀷: 'add' 鎴� 'edit'
+const dialogFormVisible = ref(false)// 寮规鏄剧ず鐘舵��
+const productList = ref([]);// 浜у搧鍒楄〃鏁版嵁
+const loadingProducts = ref(false);// 浜у搧鍔犺浇鐘舵��
+const loading = ref(false);
+
+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 itemTypeOptions = [
+  { label: '鐗╂枡', value: '鐗╂枡' },
+  { label: '鍘熸枡', value: '鍘熸枡' },
+  { label: '鎴愬搧', value: '鎴愬搧' },
+  { label: '鍏朵粬', value: '鍏朵粬' },
+]
+
+const taxRateOptions = [
+  { label: '1', value: 1 },
+  { label: '6', value: 6 },
+  { label: '13', value: 13 },
+]
+
+const data = reactive({
+  form: {
+    id: null,
+    supplierId: null,       // 渚涘簲鍟咺D
+    supplierName: '',       // 渚涘簲鍟嗗悕绉�
+    recorderId: userStore.userId, // 褰曞叆浜篒D
+    recorderName: userStore.name, // 褰曞叆浜哄鍚�
+    entryDate: getCurrentDate(),  // 褰曞叆鏃ユ湡
+    remark: '',             // 澶囨敞
+  },
+  rules: {
+    supplierName: [{ required: true, message: "璇疯緭鍏ヤ緵搴斿晢鍚嶇О", trigger: "blur" }]
+  }
+})
+const { form, rules } = toRefs(data)
+
+// 鏂板浜у搧琛�
+const addProductRow = () => {
+  productList.value.push({
+    id: null,
+    productCategory: '',
+    specificationModel: '',
+    cartonSpecifications:'',
+    supplierName: form.value.supplierName || '',
+    itemType: '',
+    inboundNum: 0,
+    inboundDate: '',
+    quantityStock: 0,
+    taxInclusiveUnitPrice: 0,
+    taxInclusiveTotalPrice: 0,
+    taxRate: null,
+    taxExclusiveTotalPrice: 0,
+    boxNum: 0,
+  });
+};
+
+// 鍒犻櫎浜у搧琛�
+const removeProductRow = (index) => {
+  productList.value.splice(index, 1);
+};
+
+// 璁$畻鎬讳环锛堟牴鎹暟閲忋�佸崟浠峰拰鍚◣鍗曚环锛�
+const calculateTotalPrice = (row) => {
+  // 璁$畻鏅�氭�讳环锛歲uantityStock * taxInclusiveUnitPrice
+  const quantity = Number(row.quantityStock || 0);
+  const taxInclusiveUnitPrice = Number(row.taxInclusiveUnitPrice || 0);
+  row.taxInclusiveTotalPrice = quantity * taxInclusiveUnitPrice;
+  calculateExclusivePrice(row);
+};
+
+// 璁$畻涓嶅惈绋庢�讳环锛堟牴鎹惈绋庢�讳环鍜岀◣鐜囷級
+const calculateExclusivePrice = (row) => {
+  const taxInclusiveTotalPrice = Number(row.taxInclusiveTotalPrice || 0);
+  const taxRate = Number(row.taxRate || 0);
+  row.taxExclusiveTotalPrice = taxInclusiveTotalPrice / (1 + taxRate / 100);
+};
+
+const submitForm = async () => {
+  try {
+    await proxy.$refs.formRef.validate()
+    
+    if (!productList.value.length) {
+      proxy.$modal.msgError('璇疯嚦灏戞坊鍔犱竴鏉′骇鍝佹暟鎹�')
+      return
+    }
+
+    // 楠岃瘉鑷畾涔夋坊鍔犵殑鏁版嵁蹇呭~瀛楁
+    for (let i = 0; i < productList.value.length; i++) {
+      const product = productList.value[i];
+      if (!product.productCategory || !product.specificationModel) {
+        proxy.$modal.msgError(`绗�${i + 1}琛屼骇鍝佹暟鎹湭濉啓瀹屾暣锛堜骇鍝併�佷骇鍝侀珮搴︺�侀珮搴﹀崟浣嶄负蹇呭~锛塦)
+        return
+      }
+      if (!product.url) {
+        proxy.$modal.msgError(`绗�${i + 1}琛屼骇鍝佹湭涓婁紶浜у搧鍥剧墖`)
+        return
+      }
+      if (!product.cartonSpecifications) {
+        proxy.$modal.msgError(`绗�${i + 1}琛屼骇鍝佹湭濉啓绾哥瑙勬牸`)
+        return
+      }
+      // if (!product.itemType) {
+      //   proxy.$modal.msgError(`绗�${i + 1}琛岃閫夋嫨鐗╁搧绫诲瀷`)
+      //   return
+      // }
+      const stock = Number(product?.inboundNum ?? 0);
+      if (!Number.isFinite(stock) || stock <= 0) {
+        proxy.$modal.msgError(`绗�${i + 1}琛屾湰娆″叆搴撴暟閲忛渶澶т簬0`)
+        return
+      }
+      const boxNum = Number(product?.boxNum ?? 0);
+      if (!Number.isFinite(boxNum) || boxNum <= 0) {
+        proxy.$modal.msgError(`绗�${i + 1}琛屾瘡浠舵暟閲�/鏀渶澶т簬0`)
+        return
+      }
+      const taxInclusiveUnitPrice = Number(product?.taxInclusiveUnitPrice ?? 0);
+      if (!Number.isFinite(taxInclusiveUnitPrice) || taxInclusiveUnitPrice <= 0) {
+        proxy.$modal.msgError(`绗�${i + 1}琛屽崟浠凤紙鍏冿級闇�澶т簬0`)
+        return
+      }
+      if (!product.inboundDate) {
+        proxy.$modal.msgError(`绗�${i + 1}琛岃閫夋嫨鍏ュ簱鏃ユ湡`)
+        return
+      }
+      
+    }
+
+    const payloadList = productList.value.map(product => ({
+      id: product.id ?? null,
+			inboundNum: Number(product.inboundNum),
+      productCategory: product.productCategory,
+      specificationModel: product.specificationModel,
+      supplierName: product.supplierName || form.value.supplierName,
+      itemType: product.itemType,
+      inboundDate: formatDateTime(product.inboundDate, false),
+      taxRate: Number(product.taxRate || 0),
+      taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0),
+			taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice || 0),
+			taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice || 0),
+      boxNum:Number(product.boxNum),
+      cartonSpecifications: product.cartonSpecifications,
+      url: product.url||'',
+    }));
+    loading.value = true
+    if (operationType.value === 'edit') {
+      const editPayload = payloadList[0]
+      await updateStockInCustom(editPayload)
+    } else {
+      await addStockInCustom(payloadList)
+    }
+
+    proxy.$modal.msgSuccess(operationType.value === 'edit' ? '缂栬緫鑷畾涔夊叆搴撴垚鍔�' : '鏂板鑷畾涔夊叆搴撴垚鍔�')
+    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
+  productList.value = []
+  emit('close')
+}
+
+// 涓婁紶鍓嶆牎妫�鏍煎紡鍜屽ぇ灏�
+function handleBeforeUpload(file) {
+  const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
+  const isJPG = type.includes(file.type);
+  //妫�楠屾枃浠舵牸寮�
+  if (!isJPG) {
+    proxy.$modal.msgError(`鍥剧墖鏍煎紡閿欒!`);
+    return false;
+  }
+  return true;
+}
+const handleUploadSuccess = (res, file,item) => { 
+  // 濡傛灉涓婁紶鎴愬姛
+  if (res.code == 200) {
+    item.url = res.data?.tempPath||''
+  } else {
+    proxy.$modal.msgError("鍥剧墖鎻掑叆澶辫触");
+  }
+}
+// 涓婁紶澶辫触澶勭悊
+function handleUploadError() {
+  proxy.$modal.msgError("鍥剧墖鎻掑叆澶辫触");
+}
+
+const openDialog = async (type, row) => {
+  operationType.value = type
+  dialogFormVisible.value = true
+
+  if (type === 'add') {
+    form.value = {
+      id: null,
+      supplierId: null,
+      supplierName: '',
+      recorderId: userStore.userId,
+      recorderName: userStore.name,
+      entryDate: getCurrentDate(),
+      remark: ''
+    }
+    productList.value = []
+  } else {
+    // 缂栬緫妯″紡锛氬皢琛屾暟鎹~鍏呭埌琛ㄦ牸涓互鏀寔淇敼
+    form.value = {
+      id: row?.id ?? null,
+      supplierId: row?.supplierId ?? null,
+      supplierName: row?.supplierName ?? '',
+      recorderId: userStore.userId,
+      recorderName: userStore.name,
+      entryDate: getCurrentDate(),
+      remark: row?.remark ?? ''
+    }
+    productList.value = [{
+      id: row?.id ?? null,
+      productCategory: row?.productCategory ?? '',
+      specificationModel: row?.specificationModel ?? '',
+      supplierName: row?.supplierName ?? '',
+      itemType: row?.itemType ?? '',
+      inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0),
+      inboundDate: row?.inboundDate ?? row?.createTime ?? '',
+      quantityStock: Number(row?.quantityStock ?? 0),
+      taxRate: Number(row?.taxRate ?? 0),
+      taxInclusiveUnitPrice: Number(row?.taxInclusiveUnitPrice ?? 0),
+      taxInclusiveTotalPrice: Number(row?.taxInclusiveTotalPrice ?? 0),
+      taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0),
+      boxNum: Number(row?.boxNum ?? 0),
+      cartonSpecifications: row?.cartonSpecifications ?? '',
+      url: row?.url ?? '',
+    }]
+  }
+}
+
+defineExpose({
+  openDialog,
+})
+</script>
+
+<style scoped lang="scss">
+  .upload-img{
+    width: 80px;
+    height: 80px;
+    object-fit: contain;
+  }
+</style>
+

--
Gitblit v1.9.3