From 19f2e3bdbe04e7ea79c6a0bdc8c7318d4837b189 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 28 五月 2026 17:36:45 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_pro_山西_晋和园

---
 src/views/procurementManagement/procurementLedger/index.vue | 1021 +++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 791 insertions(+), 230 deletions(-)

diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 9bbe87e..43203b2 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -40,8 +40,14 @@
     </div>
     <div class="table_list">
       <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
-        <el-button type="primary" @click="openForm('add')">鏂板鍙拌处</el-button>
-        <el-button type="primary" plain @click="handleImport">瀵煎叆</el-button>
+        <el-button type="success"
+                   plain
+                   @click="handleBatchGenerate">鎵归噺鐢熸垚鏁版嵁</el-button>
+        <el-button type="primary"
+                   @click="openForm('add')">鏂板鍙拌处</el-button>
+        <el-button type="primary"
+                   plain
+                   @click="handleImport">瀵煎叆</el-button>
         <el-button @click="handleOut">瀵煎嚭</el-button>
         <el-button type="danger" plain @click="handleDelete">鍒犻櫎
         </el-button>
@@ -52,12 +58,23 @@
         <el-table-column align="center" type="selection" width="55" />
         <el-table-column type="expand">
           <template #default="props">
-            <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
-              <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" />
-              <el-table-column label="鍏ュ簱瀹℃牳鐘舵��" prop="stockInApprovalStatus" width="120">
+            <el-table :data="props.row.children"
+                      border
+                      show-summary
+                      :summary-method="summarizeChildrenTable">
+              <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" />
+              <el-table-column label="鍏ュ簱瀹℃牳鐘舵��"
+                               prop="stockInApprovalStatus"
+                               width="120">
                 <template #default="scope">
                   <el-tag :type="getStockInApprovalStatusType(scope.row.stockInApprovalStatus)" size="small">
                     {{ scope.row.stockInApprovalStatus || '--' }}
@@ -370,133 +387,45 @@
 </template>
 
 <script setup>
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-import FileListDialog from "@/components/Dialog/FileListDialog.vue";
-import Detail from "./detail.vue";
-import { getToken } from "@/utils/auth";
-import pagination from "@/components/PIMTable/Pagination.vue";
-import {
-  ref,
-  onMounted,
-  reactive,
-  toRefs,
-  getCurrentInstance,
-  nextTick,
-} from "vue";
-import { Search, Delete } from "@element-plus/icons-vue";
-import { ElMessageBox, ElMessage } from "element-plus";
-import { userListNoPage } from "@/api/system/user.js";
-import {
-  addOrUpdateSalesLedgerProduct,
-  delProduct,
-  delLedgerFile,
-  getProductInfoByContractNo,
-} from "@/api/salesManagement/salesLedger.js";
-import {
-  addOrEditPurchase,
-  addPurchaseTemplate,
-  updatePurchaseTemplate,
-  createPurchaseNo,
-  delPurchase,
-  getSalesNo,
-  purchaseListPage,
-  productList,
-  getPurchaseById,
-  getOptions,
-  getPurchaseTemplateList,
-  delPurchaseTemplate,
-} from "@/api/procurementManagement/procurementLedger.js";
-import useFormData from "@/hooks/useFormData.js";
-const FileList = defineAsyncComponent(() =>
-  import("@/components/Dialog/FileList.vue")
-);
-
-const detailRef = ref(null);
-
-const { proxy } = getCurrentInstance();
-const { tax_rate } = proxy.useDict("tax_rate");
-const tableData = ref([]);
-const productData = ref([]);
-const selectedRows = ref([]);
-const productSelectedRows = ref([]);
-const modelOptions = ref([]);
-const userList = ref([]);
-const productOptions = ref([]);
-const salesContractList = ref([]);
-const supplierList = ref([]);
-const tableLoading = ref(false);
-const recordId = ref();
-const fileListDialogVisible = ref(false);
-const page = reactive({
-  current: 1,
-  size: 100,
-});
-const total = ref(0);
-const fileList = ref([]);
-import useUserStore from "@/store/modules/user";
-import { modelList, productTreeList } from "@/api/basicData/product.js";
-import dayjs from "dayjs";
-import FileUpload from "@/components/AttachmentUpload/file/index.vue";
-
-const userStore = useUserStore();
-
-// 鏄惁鏄剧ず閿�鍞悎鍚屽彿缁戝畾
-const showSalesContractBinding = false;
-
-// 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
-const approvalStatusText = {
-  1: "寰呭鏍�",
-  2: "瀹℃壒涓�",
-  3: "瀹℃壒閫氳繃",
-  4: "瀹℃壒澶辫触",
-};
-
-// 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
-const getApprovalStatusType = status => {
-  const typeMap = {
-    1: "info", // 寰呭鏍� - 鐏拌壊
-    2: "warning", // 瀹℃壒涓� - 姗欒壊
-    3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
-    4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
-  };
-  return typeMap[status] || "";
-};
-
-// 鑾峰彇鍏ュ簱鐘舵�佹爣绛剧被鍨�
-const getStockInStatusType = status => {
-  const typeMap = {
-    "寰呭叆搴�": "info", // 寰呭叆搴� - 鐏拌壊
-    "鍏ュ簱涓�": "warning", // 鍏ュ簱涓� - 姗欒壊
-    "瀹屽叏鍏ュ簱": "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
-  };
-  return typeMap[status] || "";
-};
-
-// 鑾峰彇鍏ュ簱瀹℃牳鐘舵�佹爣绛剧被鍨�
-const getStockInApprovalStatusType = status => {
-  const typeMap = {
-    "寰呭叆搴�": "info", // 寰呭叆搴� - 鐏拌壊
-    "鍏ュ簱涓�": "warning", // 鍏ュ簱涓� - 姗欒壊
-    "瀹屽叏鍏ュ簱": "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
-  };
-  return typeMap[status] || "";
-};
-
-const templateName = ref("");
-const filterInputValue = ref("");
-const templateList = ref([]);
-const isTemplateNameDuplicate = ref(false); // 鏍囪妯℃澘鍚嶇О鏄惁閲嶅
-// 褰撳墠閫変腑鐨勬ā鏉縄D锛堢敤浜庡尯鍒嗘柊澧炴ā鏉胯繕鏄洿鏂版ā鏉匡級
-const currentTemplateId = ref(null);
-
-// 妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶�
-const checkTemplateNameDuplicate = name => {
-  if (!name || name.trim() === "") {
-    isTemplateNameDuplicate.value = false;
-    return false;
-  }
-  const isDuplicate = templateList.value.some(
-    item => item.templateName === name.trim()
+  import FormDialog from "@/components/Dialog/FormDialog.vue";
+  import FileListDialog from "@/components/Dialog/FileListDialog.vue";
+  import { getToken } from "@/utils/auth";
+  import pagination from "@/components/PIMTable/Pagination.vue";
+  import {
+    ref,
+    onMounted,
+    reactive,
+    toRefs,
+    getCurrentInstance,
+    nextTick,
+  } from "vue";
+  import { Search, Delete } from "@element-plus/icons-vue";
+  import { ElMessageBox, ElMessage } from "element-plus";
+  import { userListNoPage } from "@/api/system/user.js";
+  import {
+    addOrUpdateSalesLedgerProduct,
+    delProduct,
+    delLedgerFile,
+    getProductInfoByContractNo,
+  } from "@/api/salesManagement/salesLedger.js";
+  import {
+    addOrEditPurchase,
+    addPurchaseTemplate,
+    updatePurchaseTemplate,
+    createPurchaseNo,
+    delPurchase,
+    getSalesNo,
+    purchaseListPage,
+    productList,
+    getPurchaseById,
+    getOptions,
+    getPurchaseTemplateList,
+    delPurchaseTemplate,
+    batchGeneratePurchaseInboundSteps,
+  } from "@/api/procurementManagement/procurementLedger.js";
+  import useFormData from "@/hooks/useFormData.js";
+  const FileList = defineAsyncComponent(() =>
+    import("@/components/Dialog/FileList.vue")
   );
   isTemplateNameDuplicate.value = isDuplicate;
   return isDuplicate;
@@ -509,18 +438,353 @@
   return ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp'].includes(ext);
 };
 
-// 闃叉姈瀹氭椂鍣�
-let duplicateCheckTimer = null;
-const onTemplateFilterChange = val => {
-  filterInputValue.value = val ?? "";
-  // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
-  if (duplicateCheckTimer) {
-    clearTimeout(duplicateCheckTimer);
-  }
-  // 瀹炴椂妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶嶏紙闃叉姈澶勭悊锛岄伩鍏嶉绻佹彁绀猴級
-  if (val && val.trim()) {
-    duplicateCheckTimer = setTimeout(() => {
-      const isDuplicate = checkTemplateNameDuplicate(val);
+  const userStore = useUserStore();
+
+  // 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
+  const approvalStatusText = {
+    1: "寰呭鏍�",
+    2: "瀹℃壒涓�",
+    3: "瀹℃壒閫氳繃",
+    4: "瀹℃壒澶辫触",
+  };
+
+  // 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
+  const getApprovalStatusType = status => {
+    const typeMap = {
+      1: "info", // 寰呭鏍� - 鐏拌壊
+      2: "warning", // 瀹℃壒涓� - 姗欒壊
+      3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
+      4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
+    };
+    return typeMap[status] || "";
+  };
+
+  // 鑾峰彇鍏ュ簱鐘舵�佹爣绛剧被鍨�
+  const getStockInStatusType = status => {
+    const typeMap = {
+      寰呭叆搴�: "info", // 寰呭叆搴� - 鐏拌壊
+      鍏ュ簱涓�: "warning", // 鍏ュ簱涓� - 姗欒壊
+      瀹屽叏鍏ュ簱: "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
+    };
+    return typeMap[status] || "";
+  };
+
+  // 鑾峰彇鍏ュ簱瀹℃牳鐘舵�佹爣绛剧被鍨�
+  const getStockInApprovalStatusType = status => {
+    const typeMap = {
+      寰呭叆搴�: "info", // 寰呭叆搴� - 鐏拌壊
+      鍏ュ簱涓�: "warning", // 鍏ュ簱涓� - 姗欒壊
+      瀹屽叏鍏ュ簱: "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
+    };
+    return typeMap[status] || "";
+  };
+
+  const templateName = ref("");
+  const filterInputValue = ref("");
+  const templateList = ref([]);
+  const isTemplateNameDuplicate = ref(false); // 鏍囪妯℃澘鍚嶇О鏄惁閲嶅
+  // 褰撳墠閫変腑鐨勬ā鏉縄D锛堢敤浜庡尯鍒嗘柊澧炴ā鏉胯繕鏄洿鏂版ā鏉匡級
+  const currentTemplateId = ref(null);
+
+  // 妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶�
+  const checkTemplateNameDuplicate = name => {
+    if (!name || name.trim() === "") {
+      isTemplateNameDuplicate.value = false;
+      return false;
+    }
+    const isDuplicate = templateList.value.some(
+      item => item.templateName === name.trim()
+    );
+    isTemplateNameDuplicate.value = isDuplicate;
+    return isDuplicate;
+  };
+
+  // 闃叉姈瀹氭椂鍣�
+  let duplicateCheckTimer = null;
+  const onTemplateFilterChange = val => {
+    filterInputValue.value = val ?? "";
+    // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+    if (duplicateCheckTimer) {
+      clearTimeout(duplicateCheckTimer);
+    }
+    // 瀹炴椂妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶嶏紙闃叉姈澶勭悊锛岄伩鍏嶉绻佹彁绀猴級
+    if (val && val.trim()) {
+      duplicateCheckTimer = setTimeout(() => {
+        const isDuplicate = checkTemplateNameDuplicate(val);
+        if (isDuplicate) {
+          ElMessage({
+            message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
+            type: "warning",
+            duration: 2000,
+          });
+        }
+      }, 300); // 300ms 闃叉姈
+    } else {
+      isTemplateNameDuplicate.value = false;
+    }
+  };
+
+  // allow-create 鏃讹紝杈撳叆涓嶅瓨鍦ㄧ殑鍐呭浼氫綔涓� string 鍊艰繑鍥烇紱杩欓噷鍚屾鍥炶緭鍏ユ浠ョ‘淇濇枃瀛椾笉涓�
+  const onTemplateChange = async val => {
+    if (typeof val === "string") {
+      filterInputValue.value = val;
+      // 閫夋嫨鎴栬緭鍏ユ椂妫�鏌ラ噸澶�
+      checkTemplateNameDuplicate(val);
+    }
+
+    // 杩囨护鏁版嵁锛屾煡鎵惧尮閰嶇殑妯℃澘
+    const matchedTemplate = templateList.value.find(
+      item => item.templateName === val
+    );
+
+    if (matchedTemplate?.id) {
+      // 璁板綍褰撳墠閫変腑鐨勬ā鏉縄D锛屽悗缁繚瀛樻椂杩涜鏇存柊鎿嶄綔
+      currentTemplateId.value = matchedTemplate.id;
+      // 閫変腑宸叉湁妯℃澘鏃讹紝涓嶅簲瑙嗕负鈥滄ā鏉垮悕绉伴噸澶嶅鑷翠笉鍙繚瀛樷��
+      isTemplateNameDuplicate.value = false;
+      // 濡傛灉鎵惧埌妯℃澘锛屽彧璧嬪�间緵搴斿晢銆侀」鐩悕绉般�佷粯娆炬柟寮忓拰浜у搧淇℃伅
+      if (matchedTemplate.supplierId) {
+        form.value.supplierId = matchedTemplate.supplierId;
+      }
+      if (matchedTemplate.supplierName) {
+        form.value.supplierName = matchedTemplate.supplierName;
+      }
+      if (matchedTemplate.projectName) {
+        form.value.projectName = matchedTemplate.projectName;
+      }
+      if (matchedTemplate.paymentMethod) {
+        form.value.paymentMethod = matchedTemplate.paymentMethod;
+      }
+      // 妯℃澘鏁版嵁涓殑浜у搧瀛楁鏄� productList锛岄渶瑕佽浆鎹负 productData
+      productData.value =
+        matchedTemplate.productList || matchedTemplate.productData || [];
+    } else {
+      // 鏈尮閰嶅埌宸叉湁妯℃澘锛岃涓烘柊妯℃澘
+      currentTemplateId.value = null;
+      // 濡傛灉娌℃湁鎵惧埌妯℃澘锛岄噸缃〃鍗曪紙淇濇寔褰撳墠琛ㄥ崟鐘舵�侊級
+      const currentFormData = { ...form.value };
+      const currentProductData = [...productData.value];
+
+      // 濡傛灉瀵硅瘽妗嗘湭鎵撳紑锛屽厛鎵撳紑
+      if (!dialogFormVisible.value) {
+        operationType.value = "add";
+        dialogFormVisible.value = true;
+      }
+
+      // 绛夊緟涓嬩竴涓� tick 鍚庢仮澶嶆暟鎹�
+      await nextTick();
+      form.value = {
+        ...form.value,
+        ...currentFormData,
+      };
+      productData.value = currentProductData;
+    }
+  };
+
+  // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+  const operationType = ref("");
+  const dialogFormVisible = ref(false);
+  const data = reactive({
+    searchForm: {
+      supplierName: "", // 渚涘簲鍟嗗悕绉�
+      purchaseContractNumber: "", // 閲囪喘鍚堝悓缂栧彿
+      salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+      projectName: "", // 椤圭洰鍚嶇О
+      entryDate: null, // 褰曞叆鏃ユ湡
+      entryDateStart: undefined,
+      entryDateEnd: undefined,
+    },
+    form: {
+      purchaseContractNumber: "",
+      salesLedgerId: "",
+      projectName: "",
+      recorderId: "",
+      entryDate: "",
+      productData: [],
+      supplierName: "",
+      supplierId: "",
+      paymentMethod: "",
+      executionDate: "",
+      isChecked: false,
+    },
+    rules: {
+      purchaseContractNumber: [
+        { required: false, message: "璇疯緭鍏�", trigger: "blur" },
+      ],
+      projectName: [
+        { required: true, message: "璇疯緭鍏ラ」鐩悕绉�", trigger: "blur" },
+      ],
+      supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+      entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+      executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+    },
+  });
+  const { form, rules } = toRefs(data);
+  const { form: searchForm } = useFormData({
+    ...data.searchForm,
+    // 璁剧疆褰曞叆鏃ユ湡鑼冨洿涓哄綋澶�
+    entryDate: [
+      dayjs().startOf("day").format("YYYY-MM-DD"),
+      dayjs().endOf("day").format("YYYY-MM-DD"),
+    ],
+    entryDateStart: dayjs().startOf("day").format("YYYY-MM-DD"),
+    entryDateEnd: dayjs().endOf("day").format("YYYY-MM-DD"),
+  });
+
+  // 浜у搧琛ㄥ崟寮规鏁版嵁
+  const productFormVisible = ref(false);
+  const productOperationType = ref("");
+  const productOperationIndex = ref("");
+  const currentId = ref("");
+  const productFormData = reactive({
+    productForm: {
+      productId: "",
+      productCategory: "",
+      productModelId: "",
+      specificationModel: "",
+      unit: "",
+      quantity: "",
+      taxInclusiveUnitPrice: "",
+      taxRate: "",
+      taxInclusiveTotalPrice: "",
+      taxExclusiveTotalPrice: "",
+      invoiceType: "",
+      warnNum: "",
+      isChecked: false,
+    },
+    productRules: {
+      productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+      productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+      unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+      quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+      taxInclusiveUnitPrice: [
+        { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+      ],
+      taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+      warnNum: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+      taxInclusiveTotalPrice: [
+        { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+      ],
+      taxExclusiveTotalPrice: [
+        { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+      ],
+      invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+      isChecked: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+    },
+  });
+  const { productForm, productRules } = toRefs(productFormData);
+  const upload = reactive({
+    // 涓婁紶鐨勫湴鍧�
+    url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+    // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+    headers: { Authorization: "Bearer " + getToken() },
+  });
+
+  // 瀵煎叆鐩稿叧
+  const importUploadRef = ref(null);
+  const importUpload = reactive({
+    title: "瀵煎叆閲囪喘鍙拌处",
+    open: false,
+    url: import.meta.env.VITE_APP_BASE_API + "/purchase/ledger/import",
+    headers: { Authorization: "Bearer " + getToken() },
+    isUploading: false,
+    beforeUpload: file => {
+      const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
+      const isLt10M = file.size / 1024 / 1024 < 10;
+      if (!isExcel) {
+        proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
+        return false;
+      }
+      if (!isLt10M) {
+        proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
+        return false;
+      }
+      return true;
+    },
+    onChange: (file, fileList) => {
+      // noop
+    },
+    onProgress: (event, file, fileList) => {
+      // noop
+    },
+    onSuccess: (response, file, fileList) => {
+      importUpload.isUploading = false;
+      if (response?.code === 200) {
+        proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
+        importUpload.open = false;
+        if (importUploadRef.value) {
+          importUploadRef.value.clearFiles?.();
+        }
+        getList();
+      } else {
+        proxy.$modal.msgError(response?.msg || "瀵煎叆澶辫触");
+      }
+    },
+    onError: () => {
+      importUpload.isUploading = false;
+      proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
+    },
+  });
+
+  const handleImport = () => {
+    importUpload.title = "瀵煎叆閲囪喘鍙拌处";
+    importUpload.open = true;
+    importUpload.isUploading = false;
+    if (importUploadRef.value) {
+      importUploadRef.value.clearFiles?.();
+    }
+  };
+
+  // 涓嬭浇瀵煎叆妯℃澘锛堝鍚庣璺緞涓嶅悓锛屽彲鍦ㄦ澶勮皟鏁达級
+  const downloadTemplate = () => {
+    proxy.download(
+      "/purchase/ledger/exportTemplate",
+      {},
+      "閲囪喘鍙拌处瀵煎叆妯℃澘.xlsx"
+    );
+  };
+
+  const submitImportFile = () => {
+    importUpload.isUploading = true;
+    proxy.$refs["importUploadRef"]?.submit?.();
+  };
+
+  const changeDaterange = value => {
+    if (value) {
+      searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+      searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+    } else {
+      searchForm.entryDateStart = undefined;
+      searchForm.entryDateEnd = undefined;
+    }
+    handleQuery();
+  };
+
+  const formattedNumber = (row, column, cellValue) => {
+    return parseFloat(cellValue).toFixed(2);
+  };
+  // 鏌ヨ鍒楄〃
+  /** 鎼滅储鎸夐挳鎿嶄綔 */
+  const handleQuery = () => {
+    page.current = 1;
+    getList();
+  };
+
+  // 淇濆瓨妯℃澘
+  const handleButtonClick = async () => {
+    // 妫�鏌ユā鏉垮悕绉版槸鍚︿负绌�
+    if (!templateName.value || templateName.value.trim() === "") {
+      ElMessage({
+        message: "璇疯緭鍏ユā鏉垮悕绉�",
+        type: "warning",
+      });
+      return;
+    }
+
+    // 濡傛灉鏄�滄柊澧炴ā鏉库�濓紙娌℃湁閫変腑宸叉湁妯℃澘锛夛紝鎵嶉渶瑕佸仛閲嶅悕鏍¢獙锛�
+    // 鑻ユ槸閫変腑宸叉湁妯℃澘鍚庝慨鏀癸紝鍒欏厑璁镐娇鐢ㄥ師鍚嶇О锛堣涓烘洿鏂帮級
+    if (!currentTemplateId.value) {
+      const isDuplicate = checkTemplateNameDuplicate(templateName.value);
       if (isDuplicate) {
         ElMessage({
           message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
@@ -997,39 +1261,13 @@
       getSalesNo(),
       getOptions(),
     ]);
-
-    salesContractList.value = salesRes || [];
-    // 渚涘簲鍟嗚繃婊ゅ嚭isWhite=0 鐨勬暟鎹�
-    supplierList.value = (supplierRes.data || []).filter(
-      item => item.isWhite === 0
-    );
-
-    form.value.entryDate = getCurrentDate();
-
-    if (type === "add") {
-      // 鏂板鏃剁敓鎴愰噰璐悎鍚屽彿
-      try {
-        const purchaseNoRes = await createPurchaseNo();
-        if (purchaseNoRes?.data) {
-          form.value.purchaseContractNumber = purchaseNoRes.data;
-        }
-      } catch (error) {
-        console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
-        proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
-      }
-    } else if (type === "edit" && row?.id) {
-      // 缂栬緫鏃跺姞杞芥暟鎹�
-      currentId.value = row.id;
-      try {
-        const purchaseRes = await getPurchaseById({ id: row.id, type: 2 });
-        form.value = { ...purchaseRes, stockInStatus: row.stockInStatus };
-        fileList.value = purchaseRes.storageBlobVOS || [];
-        // 浣跨敤 productList 鎺ュ彛鑾峰彇浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
-        const productRes = await productList({ salesLedgerId: row.id, type: 2 });
-        productData.value = productRes.data || [];
-      } catch (error) {
-        console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
-        proxy.$modal.msgError("鍔犺浇鏁版嵁澶辫触");
+  };
+  // 鎵撳紑寮规
+  const openForm = async (type, row) => {
+    // 缂栬緫鏃舵鏌ュ叆搴撶姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
+    if (type === "edit" && row) {
+      if (row.stockInStatus === "瀹屽叏鍏ュ簱") {
+        proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑璁板綍涓嶈兘缂栬緫");
         return;
       }
     }
@@ -1086,8 +1324,45 @@
 
   if (operationType.value === "edit" && file.id) {
     try {
-      await delLedgerFile([file.id]);
-      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      // 骞惰鍔犺浇鍩虹鏁版嵁
+      const [salesRes, supplierRes] = await Promise.all([
+        getSalesNo(),
+        getOptions(),
+      ]);
+
+      salesContractList.value = salesRes || [];
+      // 渚涘簲鍟嗚繃婊ゅ嚭isWhite=0 鐨勬暟鎹�
+      supplierList.value = (supplierRes.data || []).filter(
+        item => item.isWhite === 0
+      );
+
+      form.value.entryDate = getCurrentDate();
+
+      if (type === "edit" && row?.id) {
+        // 缂栬緫鏃跺姞杞芥暟鎹�
+        currentId.value = row.id;
+        try {
+          const purchaseRes = await getPurchaseById({ id: row.id, type: 2 });
+          form.value = { ...purchaseRes, stockInStatus: row.stockInStatus };
+          fileList.value = purchaseRes.storageBlobVOS || [];
+          // 浣跨敤 productList 鎺ュ彛鑾峰彇浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
+          const productRes = await productList({
+            salesLedgerId: row.id,
+            type: 2,
+          });
+          productData.value = productRes.data || [];
+        } catch (error) {
+          console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
+          proxy.$modal.msgError("鍔犺浇鏁版嵁澶辫触");
+          return;
+        }
+      }
+
+      if (form.value.salesLedgerId == -1) {
+        form.value.salesLedgerId = null;
+      }
+      console.log(form.value, "form.value===========");
+      dialogFormVisible.value = true;
     } catch (error) {
       console.error("鍒犻櫎鏂囦欢澶辫触:", error);
       proxy.$modal.msgError("鍒犻櫎鏂囦欢澶辫触");
@@ -1095,43 +1370,96 @@
   }
 }
 
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
-  proxy.$refs["formRef"].validate(valid => {
-    if (valid) {
-      if (productData.value.length > 0) {
-        // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
-        let processedProductData = productData.value;
+  // 绉婚櫎鏂囦欢
+  async function handleRemove(file) {
+    if (!file?.id) {
+      return;
+    }
+    console.log("handleRemove", file.id);
+    if (file.size > 1024 * 1024 * 10) {
+      // 浠呭墠绔竻鐞嗭紝涓嶈皟鐢ㄥ垹闄ゆ帴鍙e拰鎻愮ず
+      return;
+    }
+
+    if (operationType.value === "edit" && file.id) {
+      try {
+        await delLedgerFile([file.id]);
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      } catch (error) {
+        console.error("鍒犻櫎鏂囦欢澶辫触:", error);
+        proxy.$modal.msgError("鍒犻櫎鏂囦欢澶辫触");
+      }
+    }
+  }
+
+  // 鎻愪氦琛ㄥ崟
+  const submitForm = () => {
+    proxy.$refs["formRef"].validate(async valid => {
+      if (valid) {
+        if (productData.value.length > 0) {
+          // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
+          let processedProductData = productData.value;
+          if (operationType.value === "add") {
+            processedProductData = productData.value.map(product => {
+              const { id, ...rest } = product;
+              return rest;
+            });
+          }
+          form.value.productData = proxy.HaveJson(processedProductData);
+        } else {
+          proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+          return;
+        }
+        form.value.storageBlobDTOS = fileList.value;
+        form.value.type = 2;
+
+        // 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
+        if (!form.value.salesLedgerId) {
+          form.value.salesContractNo = "";
+        }
+
+        // 鏂板鏃朵笉浼犻�抜d
+        const submitData = { ...form.value };
         if (operationType.value === "add") {
           processedProductData = productData.value.map(product => {
             const { id, ...rest } = product;
             return rest;
           });
         }
-        form.value.productData = proxy.HaveJson(processedProductData);
-      } else {
-        proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
-        return;
-      }
-      form.value.storageBlobDTOS = fileList.value;
-      form.value.type = 2;
 
-      // 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
-      if (!form.value.salesLedgerId) {
-        form.value.salesContractNo = "";
-      }
+        // 濡傛灉閲囪喘鍚堝悓鍙蜂负绌猴紝鍒欐牴鎹綍鍏ユ棩鏈熻嚜鍔ㄧ敓鎴�
+        if (!submitData.purchaseContractNumber) {
+          try {
+            const purchaseNoRes = await createPurchaseNo(submitData.entryDate);
+            if (purchaseNoRes?.data) {
+              submitData.purchaseContractNumber = purchaseNoRes.data;
+            }
+          } catch (error) {
+            console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
+            proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
+            return;
+          }
+        }
 
-      // 鏂板鏃朵笉浼犻�抜d
-      const submitData = { ...form.value };
-      if (operationType.value === "add") {
-        delete submitData.id;
+        addOrEditPurchase(submitData).then(res => {
+          proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+          closeDia();
+          getList();
+        });
       }
-
-      addOrEditPurchase(submitData).then(res => {
-        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-        closeDia();
-        getList();
-      });
+    });
+  };
+  // 鍏抽棴寮规
+  const closeDia = () => {
+    proxy.resetForm("formRef");
+    dialogFormVisible.value = false;
+  };
+  // 鎵撳紑浜у搧寮规
+  const openProductForm = async (type, row, index) => {
+    // 缂栬緫鏃舵鏌ヤ骇鍝佸叆搴撳鏍哥姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
+    if (type === "edit" && row && row.stockInApprovalStatus === "瀹屽叏鍏ュ簱") {
+      proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑浜у搧涓嶈兘缂栬緫");
+      return;
     }
   });
 };
@@ -1482,15 +1810,23 @@
         productForm.value.taxInclusiveUnitPrice = "0";
       }
     }
-    // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
-    else if (productForm.value.taxInclusiveUnitPrice) {
-      productForm.value.quantity = (
-        Number(productForm.value.taxInclusiveTotalPrice) /
-        Number(productForm.value.taxInclusiveUnitPrice)
-      ).toFixed(2);
-      // 纭繚缁撴灉涓嶄负璐熸暟
-      if (Number(productForm.value.quantity) < 0) {
-        productForm.value.quantity = "0";
+    // 妫�鏌ラ�変腑鐨勪骇鍝佷腑鏄惁鏈夊畬鍏ㄥ叆搴撶殑
+    const hasFullyStocked = productSelectedRows.value.some(
+      row => row.stockInApprovalStatus === "瀹屽叏鍏ュ簱"
+    );
+    if (hasFullyStocked) {
+      proxy.$modal.msgWarning("閫変腑鐨勪骇鍝佷腑鍖呭惈瀹屽叏鍏ュ簱鐨勪骇鍝侊紝鏃犳硶鍒犻櫎");
+      return;
+    }
+    if (operationType.value === "add") {
+      productData.value = productData.value.filter(
+        item => !productSelectedRows.value.includes(item)
+      );
+      productSelectedRows.value = [];
+    } else {
+      let ids = [];
+      if (productSelectedRows.value.length > 0) {
+        ids = productSelectedRows.value.map(item => item.id);
       }
     }
     // 鍙嶇畻涓嶅惈绋庢�讳环
@@ -1603,22 +1939,247 @@
         message: res?.msg || "鍒犻櫎澶辫触",
         type: "error",
       });
+  };
+
+  const handleBatchGenerate = async () => {
+    if (selectedRows.value.length === 0) {
+      proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+      return;
     }
-  } catch (error) {
-    if (error !== "cancel") {
-      console.error("鍒犻櫎妯℃澘澶辫触:", error);
-      ElMessage({
-        message: "鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯",
-        type: "error",
+    const ids = selectedRows.value.map((item) => item.id);
+    
+    ElMessageBox.confirm("纭鎵归噺鐢熸垚鏁版嵁锛�", "鎵归噺鐢熸垚", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "info",
+    })
+      .then(() => {
+        proxy.$modal.loading("姝e湪鎵归噺鐢熸垚鏁版嵁锛岃绋嶅��...");
+        batchGeneratePurchaseInboundSteps({ ids })
+          .then((res) => {
+            proxy.$modal.msgSuccess("鎵归噺鐢熸垚鎴愬姛");
+            getList();
+          })
+          .catch(() => {
+            proxy.$modal.msgError("鎵归噺鐢熸垚澶辫触");
+          })
+          .finally(() => {
+            proxy.$modal.closeLoading();
+          });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
       });
-    }
+  };
+
+  // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+  function getCurrentDate() {
+    const today = new Date();
+    const year = today.getFullYear();
+    const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+    const day = String(today.getDate()).padStart(2, "0");
+    return `${year}-${month}-${day}`;
   }
 };
 
-onMounted(() => {
-  getList();
-  getTemplateList();
-});
+  const mathNum = () => {
+    if (!productForm.value.taxRate) {
+      proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+      return;
+    }
+    if (!productForm.value.taxInclusiveUnitPrice) {
+      return;
+    }
+    if (!productForm.value.quantity) {
+      return;
+    }
+    // 鍚◣鎬讳环璁$畻
+    productForm.value.taxInclusiveTotalPrice =
+      proxy.calculateTaxIncludeTotalPrice(
+        productForm.value.taxInclusiveUnitPrice,
+        productForm.value.quantity
+      );
+    if (productForm.value.taxRate) {
+      // 涓嶅惈绋庢�讳环璁$畻
+      productForm.value.taxExclusiveTotalPrice =
+        proxy.calculateTaxExclusiveTotalPrice(
+          productForm.value.taxInclusiveTotalPrice,
+          productForm.value.taxRate
+        );
+    }
+  };
+  const reverseMathNum = field => {
+    if (!productForm.value.taxRate) {
+      proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+      return;
+    }
+    const taxRate = Number(productForm.value.taxRate);
+    if (!taxRate) return;
+
+    // 纭繚杈撳叆鍊间笉涓鸿礋鏁�
+    if (
+      field === "taxInclusiveTotalPrice" ||
+      field === "taxExclusiveTotalPrice"
+    ) {
+      const value = Number(productForm.value[field]);
+      if (value < 0) {
+        productForm.value[field] = "0";
+        proxy.$modal.msgWarning("鍊间笉鑳藉皬浜�0");
+        return;
+      }
+    }
+
+    if (field === "taxInclusiveTotalPrice") {
+      // 宸茬煡鍚◣鎬讳环鍜屾暟閲忥紝鍙嶇畻鍚◣鍗曚环
+      if (productForm.value.quantity) {
+        productForm.value.taxInclusiveUnitPrice = (
+          Number(productForm.value.taxInclusiveTotalPrice) /
+          Number(productForm.value.quantity)
+        ).toFixed(2);
+        // 纭繚缁撴灉涓嶄负璐熸暟
+        if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
+          productForm.value.taxInclusiveUnitPrice = "0";
+        }
+      }
+      // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
+      else if (productForm.value.taxInclusiveUnitPrice) {
+        productForm.value.quantity = (
+          Number(productForm.value.taxInclusiveTotalPrice) /
+          Number(productForm.value.taxInclusiveUnitPrice)
+        ).toFixed(2);
+        // 纭繚缁撴灉涓嶄负璐熸暟
+        if (Number(productForm.value.quantity) < 0) {
+          productForm.value.quantity = "0";
+        }
+      }
+      // 鍙嶇畻涓嶅惈绋庢�讳环
+      productForm.value.taxExclusiveTotalPrice = (
+        Number(productForm.value.taxInclusiveTotalPrice) /
+        (1 + taxRate / 100)
+      ).toFixed(2);
+      // 纭繚缁撴灉涓嶄负璐熸暟
+      if (Number(productForm.value.taxExclusiveTotalPrice) < 0) {
+        productForm.value.taxExclusiveTotalPrice = "0";
+      }
+    } else if (field === "taxExclusiveTotalPrice") {
+      // 鍙嶇畻鍚◣鎬讳环
+      productForm.value.taxInclusiveTotalPrice = (
+        Number(productForm.value.taxExclusiveTotalPrice) *
+        (1 + taxRate / 100)
+      ).toFixed(2);
+      // 纭繚缁撴灉涓嶄负璐熸暟
+      if (Number(productForm.value.taxInclusiveTotalPrice) < 0) {
+        productForm.value.taxInclusiveTotalPrice = "0";
+      }
+      // 宸茬煡鏁伴噺锛屽弽绠楀惈绋庡崟浠�
+      if (productForm.value.quantity) {
+        productForm.value.taxInclusiveUnitPrice = (
+          Number(productForm.value.taxInclusiveTotalPrice) /
+          Number(productForm.value.quantity)
+        ).toFixed(2);
+        // 纭繚缁撴灉涓嶄负璐熸暟
+        if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
+          productForm.value.taxInclusiveUnitPrice = "0";
+        }
+      }
+      // 宸茬煡鍚◣鍗曚环锛屽弽绠楁暟閲�
+      else if (productForm.value.taxInclusiveUnitPrice) {
+        productForm.value.quantity = (
+          Number(productForm.value.taxInclusiveTotalPrice) /
+          Number(productForm.value.taxInclusiveUnitPrice)
+        ).toFixed(2);
+        // 纭繚缁撴灉涓嶄负璐熸暟
+        if (Number(productForm.value.quantity) < 0) {
+          productForm.value.quantity = "0";
+        }
+      }
+    }
+  };
+  // 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
+  const salesLedgerChange = async row => {
+    console.log("row", row);
+    var index = salesContractList.value.findIndex(item => item.id == row);
+    console.log("index", index);
+    if (index > -1) {
+      await querygProductInfoByContractNo();
+    }
+  };
+
+  const querygProductInfoByContractNo = async () => {
+    const { code, data } = await getProductInfoByContractNo({
+      contractNo: form.value.salesLedgerId,
+    });
+    if (code == 200) {
+      productData.value = data || [];
+    }
+  };
+
+  // 鑾峰彇妯℃澘淇℃伅
+  const getTemplateList = async () => {
+    let res = await getPurchaseTemplateList();
+    if (res && res.code === 200 && Array.isArray(res.data)) {
+      templateList.value = res.data;
+    }
+  };
+
+  // 鎵撳紑闄勪欢寮规
+  const openFileDialog = async row => {
+    recordId.value = row.id;
+    fileListDialogVisible.value = true;
+  };
+
+  // 鍒犻櫎妯℃澘
+  const handleDeleteTemplate = async item => {
+    if (!item.id) {
+      proxy.$modal.msgWarning("鏃犳硶鍒犻櫎璇ユā鏉�");
+      return;
+    }
+
+    try {
+      await ElMessageBox.confirm(
+        `纭畾瑕佸垹闄ゆā鏉�"${item.templateName}"鍚楋紵`,
+        "鍒犻櫎纭",
+        {
+          confirmButtonText: "纭畾",
+          cancelButtonText: "鍙栨秷",
+          type: "warning",
+        }
+      );
+
+      const res = await delPurchaseTemplate([item.id]);
+      if (res && res.code === 200) {
+        ElMessage({
+          message: "鍒犻櫎鎴愬姛",
+          type: "success",
+        });
+        // 濡傛灉鍒犻櫎鐨勬槸褰撳墠閫変腑鐨勬ā鏉匡紝娓呯┖閫夋嫨
+        if (templateName.value === item.templateName) {
+          templateName.value = "";
+          filterInputValue.value = "";
+        }
+        // 閲嶆柊鑾峰彇妯℃澘鍒楄〃
+        await getTemplateList();
+      } else {
+        ElMessage({
+          message: res?.msg || "鍒犻櫎澶辫触",
+          type: "error",
+        });
+      }
+    } catch (error) {
+      if (error !== "cancel") {
+        console.error("鍒犻櫎妯℃澘澶辫触:", error);
+        ElMessage({
+          message: "鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯",
+          type: "error",
+        });
+      }
+    }
+  };
+
+  onMounted(() => {
+    getList();
+    getTemplateList();
+  });
 </script>
 
 <style scoped lang="scss">

--
Gitblit v1.9.3