From 1c0f01cc462d37e146c34127d2883ca51e26d508 Mon Sep 17 00:00:00 2001
From: 曹睿 <360930172@qq.com>
Date: 星期二, 24 六月 2025 17:12:32 +0800
Subject: [PATCH] fix: 修复PIMTable不支持懒加载问题。修复【来票登记】金额格式化显示NaN问题。 style: 重构来票登记页面。 feat: 完善文件上传组件功能。【来票台账】底部添加合计。【来票登记】添加上传附件

---
 src/views/procurementManagement/paymentHistory/index.vue                |    3 
 src/views/procurementManagement/procurementInvoiceLedger/index.vue      |   28 
 src/views/basicData/supplierManage/index.vue                            |    3 
 src/hooks/useModal.js                                                   |    3 
 src/views/basicData/product/index.vue                                   |    3 
 src/views/procurementManagement/invoiceEntry/index.vue                  |  820 ++-----------
 src/hooks/usePaginationApi.jsx                                          |    5 
 src/views/procurementManagement/paymentEntry/index.vue                  |    3 
 src/views/procurementManagement/thePaymentLedger/index.vue              |  109 
 src/components/Editor/index.vue                                         |  152 +-
 src/views/basicData/customerFile/index.vue                              |  630 ++++++----
 src/views/procurementManagement/invoiceEntry/indexOld.vue               |  725 ++++++++++++
 src/components/Upload/FileUpload.vue                                    |   29 
 src/views/equipmentManagement/ledger/index.vue                          |    1 
 src/views/procurementManagement/invoiceEntry/components/Modal.vue       |  407 ++++++
 src/api/procurementManagement/invoiceEntry.js                           |   82 
 src/views/personnelManagement/onboarding/index.vue                      |  189 +-
 src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue |  111 +
 src/views/reportAnalysis/projectProfit/index.vue                        |    1 
 src/api/procurementManagement/procurementInvoiceLedger.js               |   14 
 src/components/PIMTable/PIMTable.vue                                    |   28 
 src/views/procurementManagement/paymentLedger/index.vue                 |    1 
 src/views/procurementManagement/procurementLedger/index.vue             |    4 
 src/views/reportAnalysis/taxComparison/index.vue                        |    1 
 src/components/FileUpload/index.vue                                     |  212 ++-
 src/views/salesManagement/receiptPaymentHistory/index.vue               |    5 
 26 files changed, 2,256 insertions(+), 1,313 deletions(-)

diff --git a/src/api/procurementManagement/invoiceEntry.js b/src/api/procurementManagement/invoiceEntry.js
index 055a7b3..8325aa7 100644
--- a/src/api/procurementManagement/invoiceEntry.js
+++ b/src/api/procurementManagement/invoiceEntry.js
@@ -1,69 +1,69 @@
 // 閲囪喘-鏉ョエ鐧昏鎺ュ彛
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 // 鏌ヨ閲囪喘鍚堝悓鍙�
 export function getProduct(query) {
-    return request({
-        url: '/purchase/ledger/getProduct',
-        method: 'get',
-        params: query
-    })
+  return request({
+    url: "/purchase/ledger/getProduct",
+    method: "get",
+    params: query,
+  });
 }
 
 // 鏌ヨid閲囪喘鍚堝悓鍙�
 export function getPurchaseNoById(query) {
-    return request({
-        url: '/purchase/ledger/getPurchaseNoById',
-        method: 'get',
-        params: query
-    })
+  return request({
+    url: "/purchase/ledger/getPurchaseNoById",
+    method: "get",
+    params: query,
+  });
 }
 // 鏍规嵁閲囪喘鍚堝悓鍙锋煡璇㈣缁嗕俊鎭�
 export function getInfo(query) {
-    return request({
-        url: '/purchase/ledger/getInfo',
-        method: 'get',
-        params: query
-    })
+  return request({
+    url: "/purchase/ledger/getInfo",
+    method: "get",
+    params: query,
+  });
 }
 // 涓诲垪琛ㄦ煡璇�
 export function gePurchaseList(query) {
-    return request({
-        url: '/purchase/ledger/list',
-        method: 'get',
-        params: query
-    })
+  return request({
+    url: "/purchase/ledger/list",
+    method: "get",
+    params: query,
+  });
 }
 // 涓诲垪琛ㄦ煡璇�
 export function getRegistrationById(query) {
-    return request({
-        url: '/purchase/registration/getRegistrationById',
-        method: 'get',
-        params: query
-    })
+  return request({
+    url: "/purchase/registration/getRegistrationById",
+    method: "get",
+    params: query,
+  });
 }
 // 鏂板缂栬緫鏉ョエ鐧昏
 export function addOrUpdateRegistration(query) {
-    return request({
-        url: '/purchase/registration/addOrUpdateRegistration',
-        method: 'post',
-        data: query
-    })
+  return request({
+    url: "/purchase/registration/addOrUpdateRegistration",
+    method: "post",
+    data: query,
+  });
 }
 // 鍒犻櫎鏉ョエ鐧昏
 export function delRegistration(query) {
-    return request({
-        url: '/purchase/registration/delRegistration',
-        method: 'delete',
-        data: query
-    })
+  return request({
+    url: "/purchase/registration/delRegistration",
+    method: "delete",
+    data: query,
+  });
 }
 
 // 涓诲垪琛ㄦ煡璇�
 export function gePurchaseListPage(query) {
-    return request({
-        url: '/purchase/ledger/listPage',
-        method: 'get',
-        params: query
-    })
+  return request({
+    url: "/purchase/ledger/listPage",
+    method: "get",
+    params: query,
+  });
 }
diff --git a/src/api/procurementManagement/procurementInvoiceLedger.js b/src/api/procurementManagement/procurementInvoiceLedger.js
index fb73655..b828c4a 100644
--- a/src/api/procurementManagement/procurementInvoiceLedger.js
+++ b/src/api/procurementManagement/procurementInvoiceLedger.js
@@ -10,13 +10,13 @@
   });
 }
 // 鏌ヨ璇︽儏
-export function getInvoiceById(query) {
-  return request({
-    url: "/purchase/registration/getRegistrationById",
-    method: "get",
-    params: query,
-  });
-}
+// export function getInvoiceById(query) {
+//   return request({
+//     url: "/purchase/registration/getRegistrationById",
+//     method: "get",
+//     params: query,
+//   });
+// }
 // 鏂板銆佺紪杈�
 export function addOrUpdateInvoice(query) {
   return request({
diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue
index efd0edc..c283e42 100644
--- a/src/components/Editor/index.vue
+++ b/src/components/Editor/index.vue
@@ -27,18 +27,18 @@
 </template>
 
 <script setup>
-import axios from 'axios'
-import { QuillEditor } from "@vueup/vue-quill"
-import "@vueup/vue-quill/dist/vue-quill.snow.css"
-import { getToken } from "@/utils/auth"
+import axios from "axios";
+import { QuillEditor } from "@vueup/vue-quill";
+import "@vueup/vue-quill/dist/vue-quill.snow.css";
+import { getToken } from "@/utils/auth";
 
-const { proxy } = getCurrentInstance()
+const { proxy } = getCurrentInstance();
 
-const quillEditorRef = ref()
-const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload") // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+const quillEditorRef = ref();
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
 const headers = ref({
-  Authorization: "Bearer " + getToken()
-})
+  Authorization: "Bearer " + getToken(),
+});
 
 const props = defineProps({
   /* 缂栬緫鍣ㄧ殑鍐呭 */
@@ -69,8 +69,8 @@
   type: {
     type: String,
     default: "url",
-  }
-})
+  },
+});
 
 const options = ref({
   theme: "snow",
@@ -79,74 +79,78 @@
   modules: {
     // 宸ュ叿鏍忛厤缃�
     toolbar: [
-      ["bold", "italic", "underline", "strike"],      // 鍔犵矖 鏂滀綋 涓嬪垝绾� 鍒犻櫎绾�
-      ["blockquote", "code-block"],                   // 寮曠敤  浠g爜鍧�
-      [{ list: "ordered" }, { list: "bullet" }],      // 鏈夊簭銆佹棤搴忓垪琛�
-      [{ indent: "-1" }, { indent: "+1" }],           // 缂╄繘
-      [{ size: ["small", false, "large", "huge"] }],  // 瀛椾綋澶у皬
-      [{ header: [1, 2, 3, 4, 5, 6, false] }],        // 鏍囬
-      [{ color: [] }, { background: [] }],            // 瀛椾綋棰滆壊銆佸瓧浣撹儗鏅鑹�
-      [{ align: [] }],                                // 瀵归綈鏂瑰紡
-      ["clean"],                                      // 娓呴櫎鏂囨湰鏍煎紡
-      ["link", "image", "video"]                      // 閾炬帴銆佸浘鐗囥�佽棰�
+      ["bold", "italic", "underline", "strike"], // 鍔犵矖 鏂滀綋 涓嬪垝绾� 鍒犻櫎绾�
+      ["blockquote", "code-block"], // 寮曠敤  浠g爜鍧�
+      [{ list: "ordered" }, { list: "bullet" }], // 鏈夊簭銆佹棤搴忓垪琛�
+      [{ indent: "-1" }, { indent: "+1" }], // 缂╄繘
+      [{ size: ["small", false, "large", "huge"] }], // 瀛椾綋澶у皬
+      [{ header: [1, 2, 3, 4, 5, 6, false] }], // 鏍囬
+      [{ color: [] }, { background: [] }], // 瀛椾綋棰滆壊銆佸瓧浣撹儗鏅鑹�
+      [{ align: [] }], // 瀵归綈鏂瑰紡
+      ["clean"], // 娓呴櫎鏂囨湰鏍煎紡
+      ["link", "image", "video"], // 閾炬帴銆佸浘鐗囥�佽棰�
     ],
   },
   placeholder: "璇疯緭鍏ュ唴瀹�",
-  readOnly: props.readOnly
-})
+  readOnly: props.readOnly,
+});
 
 const styles = computed(() => {
-  let style = {}
+  let style = {};
   if (props.minHeight) {
-    style.minHeight = `${props.minHeight}px`
+    style.minHeight = `${props.minHeight}px`;
   }
   if (props.height) {
-    style.height = `${props.height}px`
+    style.height = `${props.height}px`;
   }
-  return style
-})
+  return style;
+});
 
-const content = ref("")
-watch(() => props.modelValue, (v) => {
-  if (v !== content.value) {
-    content.value = v == undefined ? "<p></p>" : v
-  }
-}, { immediate: true })
+const content = ref("");
+watch(
+  () => props.modelValue,
+  (v) => {
+    if (v !== content.value) {
+      content.value = v == undefined ? "<p></p>" : v;
+    }
+  },
+  { immediate: true }
+);
 
 // 濡傛灉璁剧疆浜嗕笂浼犲湴鍧�鍒欒嚜瀹氫箟鍥剧墖涓婁紶浜嬩欢
 onMounted(() => {
-  if (props.type == 'url') {
-    let quill = quillEditorRef.value.getQuill()
-    let toolbar = quill.getModule("toolbar")
+  if (props.type == "url") {
+    let quill = quillEditorRef.value.getQuill();
+    let toolbar = quill.getModule("toolbar");
     toolbar.addHandler("image", (value) => {
       if (value) {
-        proxy.$refs.uploadRef.click()
+        proxy.$refs.uploadRef.click();
       } else {
-        quill.format("image", false)
+        quill.format("image", false);
       }
-    })
-    quill.root.addEventListener('paste', handlePasteCapture, true)
+    });
+    quill.root.addEventListener("paste", handlePasteCapture, true);
   }
-})
+});
 
 // 涓婁紶鍓嶆牎妫�鏍煎紡鍜屽ぇ灏�
 function handleBeforeUpload(file) {
-  const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]
-  const isJPG = type.includes(file.type)
+  const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
+  const isJPG = type.includes(file.type);
   //妫�楠屾枃浠舵牸寮�
   if (!isJPG) {
-    proxy.$modal.msgError(`鍥剧墖鏍煎紡閿欒!`)
-    return false
+    proxy.$modal.msgError(`鍥剧墖鏍煎紡閿欒!`);
+    return false;
   }
   // 鏍℃鏂囦欢澶у皬
   if (props.fileSize) {
-    const isLt = file.size / 1024 / 1024 < props.fileSize
+    const isLt = file.size / 1024 / 1024 < props.fileSize;
     if (!isLt) {
-      proxy.$modal.msgError(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${props.fileSize} MB!`)
-      return false
+      proxy.$modal.msgError(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${props.fileSize} MB!`);
+      return false;
     }
   }
-  return true
+  return true;
 }
 
 // 涓婁紶鎴愬姛澶勭悊
@@ -154,44 +158,55 @@
   // 濡傛灉涓婁紶鎴愬姛
   if (res.code == 200) {
     // 鑾峰彇瀵屾枃鏈疄渚�
-    let quill = toRaw(quillEditorRef.value).getQuill()
+    let quill = toRaw(quillEditorRef.value).getQuill();
     // 鑾峰彇鍏夋爣浣嶇疆
-    let length = quill.selection.savedRange.index
+    let length = quill.selection.savedRange.index;
     // 鎻掑叆鍥剧墖锛宺es.url涓烘湇鍔″櫒杩斿洖鐨勫浘鐗囬摼鎺ュ湴鍧�
-    quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName)
+    quill.insertEmbed(
+      length,
+      "image",
+      import.meta.env.VITE_APP_BASE_API + res.fileName
+    );
     // 璋冩暣鍏夋爣鍒版渶鍚�
-    quill.setSelection(length + 1)
+    quill.setSelection(length + 1);
   } else {
-    proxy.$modal.msgError("鍥剧墖鎻掑叆澶辫触")
+    proxy.$modal.msgError("鍥剧墖鎻掑叆澶辫触");
   }
 }
 
 // 涓婁紶澶辫触澶勭悊
 function handleUploadError() {
-  proxy.$modal.msgError("鍥剧墖鎻掑叆澶辫触")
+  proxy.$modal.msgError("鍥剧墖鎻掑叆澶辫触");
 }
 
 // 澶嶅埗绮樿创鍥剧墖澶勭悊
 function handlePasteCapture(e) {
-  const clipboard = e.clipboardData || window.clipboardData
+  const clipboard = e.clipboardData || window.clipboardData;
   if (clipboard && clipboard.items) {
     for (let i = 0; i < clipboard.items.length; i++) {
-      const item = clipboard.items[i]
-      if (item.type.indexOf('image') !== -1) {
-        e.preventDefault()
-        const file = item.getAsFile()
-        insertImage(file)
+      const item = clipboard.items[i];
+      if (item.type.indexOf("image") !== -1) {
+        e.preventDefault();
+        const file = item.getAsFile();
+        insertImage(file);
       }
     }
   }
 }
 
 function insertImage(file) {
-  const formData = new FormData()
-  formData.append("file", file)
-  axios.post(uploadUrl.value, formData, { headers: { "Content-Type": "multipart/form-data", Authorization: headers.value.Authorization } }).then(res => {
-    handleUploadSuccess(res.data)
-  })
+  const formData = new FormData();
+  formData.append("file", file);
+  axios
+    .post(uploadUrl.value, formData, {
+      headers: {
+        "Content-Type": "multipart/form-data",
+        Authorization: headers.value.Authorization,
+      },
+    })
+    .then((res) => {
+      handleUploadSuccess(res.data);
+    });
 }
 </script>
 
@@ -199,7 +214,8 @@
 .editor-img-uploader {
   display: none;
 }
-.editor, .ql-toolbar {
+.editor,
+.ql-toolbar {
   white-space: pre-wrap !important;
   line-height: normal !important;
 }
diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue
index d217897..e39a6ed 100644
--- a/src/components/FileUpload/index.vue
+++ b/src/components/FileUpload/index.vue
@@ -22,18 +22,40 @@
     <!-- 涓婁紶鎻愮ず -->
     <div class="el-upload__tip" v-if="showTip && !disabled">
       璇蜂笂浼�
-      <template v-if="fileSize"> 澶у皬涓嶈秴杩� <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
-      <template v-if="fileType"> 鏍煎紡涓� <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
+      <template v-if="fileSize">
+        澶у皬涓嶈秴杩� <b style="color: #f56c6c">{{ fileSize }}MB</b>
+      </template>
+      <template v-if="fileType">
+        鏍煎紡涓� <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
+      </template>
       鐨勬枃浠�
     </div>
     <!-- 鏂囦欢鍒楄〃 -->
-    <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
-      <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
-        <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
+    <transition-group
+      class="upload-file-list el-upload-list el-upload-list--text"
+      name="el-fade-in-linear"
+      tag="ul"
+    >
+      <li
+        :key="file.uid"
+        class="el-upload-list__item ele-upload-list__item-content"
+        v-for="(file, index) in fileList"
+      >
+        <el-link
+          :href="`${baseUrl}${file.url}`"
+          :underline="false"
+          target="_blank"
+        >
           <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
         </el-link>
         <div class="ele-upload-list__item-content-action">
-          <el-link :underline="false" @click="handleDelete(index)" type="danger" v-if="!disabled">&nbsp;鍒犻櫎</el-link>
+          <el-link
+            :underline="false"
+            @click="handleDelete(index)"
+            type="danger"
+            v-if="!disabled"
+            >&nbsp;鍒犻櫎</el-link
+          >
         </div>
       </li>
     </transition-group>
@@ -41,152 +63,160 @@
 </template>
 
 <script setup>
-import { getToken } from "@/utils/auth"
-import Sortable from 'sortablejs'
+import { getToken } from "@/utils/auth";
+import Sortable from "sortablejs";
 
 const props = defineProps({
   modelValue: [String, Object, Array],
   // 涓婁紶鎺ュ彛鍦板潃
   action: {
     type: String,
-    default: "/common/upload"
+    default: "/common/upload",
   },
   // 涓婁紶鎼哄甫鐨勫弬鏁�
   data: {
-    type: Object
+    type: Object,
   },
   // 鏁伴噺闄愬埗
   limit: {
     type: Number,
-    default: 5
+    default: 5,
   },
   // 澶у皬闄愬埗(MB)
   fileSize: {
     type: Number,
-    default: 5
+    default: 5,
   },
   // 鏂囦欢绫诲瀷, 渚嬪['png', 'jpg', 'jpeg']
   fileType: {
     type: Array,
-    default: () => ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf"]
+    default: () => ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf"],
   },
   // 鏄惁鏄剧ず鎻愮ず
   isShowTip: {
     type: Boolean,
-    default: true
+    default: true,
   },
   // 绂佺敤缁勪欢锛堜粎鏌ョ湅鏂囦欢锛�
   disabled: {
     type: Boolean,
-    default: false
+    default: false,
   },
   // 鎷栧姩鎺掑簭
   drag: {
     type: Boolean,
-    default: true
-  }
-})
+    default: true,
+  },
+});
 
-const { proxy } = getCurrentInstance()
-const emit = defineEmits()
-const number = ref(0)
-const uploadList = ref([])
-const baseUrl = import.meta.env.VITE_APP_BASE_API
-const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + props.action) // 涓婁紶鏂囦欢鏈嶅姟鍣ㄥ湴鍧�
-const headers = ref({ Authorization: "Bearer " + getToken() })
-const fileList = ref([])
+const { proxy } = getCurrentInstance();
+const emit = defineEmits();
+const number = ref(0);
+const uploadList = ref([]);
+const baseUrl = import.meta.env.VITE_APP_BASE_API;
+const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + props.action); // 涓婁紶鏂囦欢鏈嶅姟鍣ㄥ湴鍧�
+const headers = ref({ Authorization: "Bearer " + getToken() });
+const fileList = ref([]);
 const showTip = computed(
   () => props.isShowTip && (props.fileType || props.fileSize)
-)
+);
 
-watch(() => props.modelValue, val => {
-  if (val) {
-    let temp = 1
-    // 棣栧厛灏嗗�艰浆涓烘暟缁�
-    const list = Array.isArray(val) ? val : props.modelValue.split(',')
-    // 鐒跺悗灏嗘暟缁勮浆涓哄璞℃暟缁�
-    fileList.value = list.map(item => {
-      if (typeof item === "string") {
-        item = { name: item, url: item }
-      }
-      item.uid = item.uid || new Date().getTime() + temp++
-      return item
-    })
-  } else {
-    fileList.value = []
-    return []
-  }
-},{ deep: true, immediate: true })
+watch(
+  () => props.modelValue,
+  (val) => {
+    if (val) {
+      let temp = 1;
+      // 棣栧厛灏嗗�艰浆涓烘暟缁�
+      const list = Array.isArray(val) ? val : props.modelValue.split(",");
+      // 鐒跺悗灏嗘暟缁勮浆涓哄璞℃暟缁�
+      fileList.value = list.map((item) => {
+        if (typeof item === "string") {
+          item = { name: item, url: item };
+        }
+        item.uid = item.uid || new Date().getTime() + temp++;
+        return item;
+      });
+    } else {
+      fileList.value = [];
+      return [];
+    }
+  },
+  { deep: true, immediate: true }
+);
 
 // 涓婁紶鍓嶆牎妫�鏍煎紡鍜屽ぇ灏�
 function handleBeforeUpload(file) {
   // 鏍℃鏂囦欢绫诲瀷
   if (props.fileType.length) {
-    const fileName = file.name.split('.')
-    const fileExt = fileName[fileName.length - 1]
-    const isTypeOk = props.fileType.indexOf(fileExt) >= 0
+    const fileName = file.name.split(".");
+    const fileExt = fileName[fileName.length - 1];
+    const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
     if (!isTypeOk) {
-      proxy.$modal.msgError(`鏂囦欢鏍煎紡涓嶆纭紝璇蜂笂浼�${props.fileType.join("/")}鏍煎紡鏂囦欢!`)
-      return false
+      proxy.$modal.msgError(
+        `鏂囦欢鏍煎紡涓嶆纭紝璇蜂笂浼�${props.fileType.join("/")}鏍煎紡鏂囦欢!`
+      );
+      return false;
     }
   }
   // 鏍℃鏂囦欢鍚嶆槸鍚﹀寘鍚壒娈婂瓧绗�
-  if (file.name.includes(',')) {
-    proxy.$modal.msgError('鏂囦欢鍚嶄笉姝g‘锛屼笉鑳藉寘鍚嫳鏂囬�楀彿!')
-    return false
+  if (file.name.includes(",")) {
+    proxy.$modal.msgError("鏂囦欢鍚嶄笉姝g‘锛屼笉鑳藉寘鍚嫳鏂囬�楀彿!");
+    return false;
   }
   // 鏍℃鏂囦欢澶у皬
   if (props.fileSize) {
-    const isLt = file.size / 1024 / 1024 < props.fileSize
+    const isLt = file.size / 1024 / 1024 < props.fileSize;
     if (!isLt) {
-      proxy.$modal.msgError(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${props.fileSize} MB!`)
-      return false
+      proxy.$modal.msgError(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${props.fileSize} MB!`);
+      return false;
     }
   }
-  proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...")
-  number.value++
-  return true
+  proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+  number.value++;
+  return true;
 }
 
 // 鏂囦欢涓暟瓒呭嚭
 function handleExceed() {
-  proxy.$modal.msgError(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃 ${props.limit} 涓�!`)
+  proxy.$modal.msgError(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃 ${props.limit} 涓�!`);
 }
 
 // 涓婁紶澶辫触
 function handleUploadError(err) {
-  proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触")
-  proxy.$modal.closeLoading()
+  proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+  proxy.$modal.closeLoading();
 }
 
 // 涓婁紶鎴愬姛鍥炶皟
 function handleUploadSuccess(res, file) {
   if (res.code === 200) {
-    uploadList.value.push({ name: res.fileName, url: res.fileName })
-    uploadedSuccessfully()
+    uploadList.value.push({ name: res.fileName, url: res.fileName });
+    uploadedSuccessfully();
   } else {
-    number.value--
-    proxy.$modal.closeLoading()
-    proxy.$modal.msgError(res.msg)
-    proxy.$refs.fileUpload.handleRemove(file)
-    uploadedSuccessfully()
+    number.value--;
+    proxy.$modal.closeLoading();
+    proxy.$modal.msgError(res.msg);
+    proxy.$refs.fileUpload.handleRemove(file);
+    uploadedSuccessfully();
   }
 }
 
 // 鍒犻櫎鏂囦欢
 function handleDelete(index) {
-  fileList.value.splice(index, 1)
-  emit("update:modelValue", listToString(fileList.value))
+  fileList.value.splice(index, 1);
+  emit("update:modelValue", listToString(fileList.value));
 }
 
 // 涓婁紶缁撴潫澶勭悊
 function uploadedSuccessfully() {
   if (number.value > 0 && uploadList.value.length === number.value) {
-    fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value)
-    uploadList.value = []
-    number.value = 0
-    emit("update:modelValue", listToString(fileList.value))
-    proxy.$modal.closeLoading()
+    fileList.value = fileList.value
+      .filter((f) => f.url !== undefined)
+      .concat(uploadList.value);
+    uploadList.value = [];
+    number.value = 0;
+    emit("update:modelValue", listToString(fileList.value));
+    proxy.$modal.closeLoading();
   }
 }
 
@@ -194,40 +224,40 @@
 function getFileName(name) {
   // 濡傛灉鏄痷rl閭d箞鍙栨渶鍚庣殑鍚嶅瓧 濡傛灉涓嶆槸鐩存帴杩斿洖
   if (name.lastIndexOf("/") > -1) {
-    return name.slice(name.lastIndexOf("/") + 1)
+    return name.slice(name.lastIndexOf("/") + 1);
   } else {
-    return name
+    return name;
   }
 }
 
 // 瀵硅薄杞垚鎸囧畾瀛楃涓插垎闅�
 function listToString(list, separator) {
-  let strs = ""
-  separator = separator || ","
+  let strs = "";
+  separator = separator || ",";
   for (let i in list) {
     if (list[i].url) {
-      strs += list[i].url + separator
+      strs += list[i].url + separator;
     }
   }
-  return strs != '' ? strs.substr(0, strs.length - 1) : ''
+  return strs != "" ? strs.substr(0, strs.length - 1) : "";
 }
 
 // 鍒濆鍖栨嫋鎷芥帓搴�
 onMounted(() => {
   if (props.drag) {
     nextTick(() => {
-      const element = document.querySelector('.upload-file-list')
+      const element = document.querySelector(".upload-file-list");
       Sortable.create(element, {
-        ghostClass: 'file-upload-darg',
+        ghostClass: "file-upload-darg",
         onEnd: (evt) => {
-          const movedItem = fileList.value.splice(evt.oldIndex, 1)[0]
-          fileList.value.splice(evt.newIndex, 0, movedItem)
-          emit('update:modelValue', listToString(fileList.value))
-        }
-      })
-    })
+          const movedItem = fileList.value.splice(evt.oldIndex, 1)[0];
+          fileList.value.splice(evt.newIndex, 0, movedItem);
+          emit("update:modelValue", listToString(fileList.value));
+        },
+      });
+    });
   }
-})
+});
 </script>
 <style scoped lang="scss">
 .file-upload-darg {
diff --git a/src/components/PIMTable/PIMTable.vue b/src/components/PIMTable/PIMTable.vue
index 3c9e756..d1b778d 100644
--- a/src/components/PIMTable/PIMTable.vue
+++ b/src/components/PIMTable/PIMTable.vue
@@ -5,18 +5,20 @@
     :border="border"
     :data="tableData"
     :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
-    height="calc(100vh - 18.5em)"
+    :height="height"
     :highlight-current-row="highlightCurrentRow"
     :row-class-name="rowClassName"
     :row-style="rowStyle"
     :row-key="rowKey"
     style="width: 100%"
     tooltip-effect="dark"
-    @row-click="rowClick"
-    @current-change="currentChange"
+    :expand-row-keys="expandRowKeys"
     :show-summary="isShowSummary"
     :summary-method="summaryMethod"
+    @row-click="rowClick"
+    @current-change="currentChange"
     @selection-change="handleSelectionChange"
+    @expand-change="expandChange"
     class="lims-table"
   >
     <el-table-column
@@ -224,7 +226,7 @@
 const uploadHeader = proxy.uploadHeader;
 const javaApi = proxy.javaApi;
 
-const emit = defineEmits(["pagination"]);
+const emit = defineEmits(["pagination", "expand-change", "selection-change"]);
 
 // Filters
 const typeFn = (val, row) => {
@@ -241,9 +243,13 @@
     type: Boolean,
     default: false,
   },
-  handleSelectionChange: {
-    type: Function,
-    default: () => {},
+  height: {
+    type: [Number, String],
+    default: "calc(100vh - 18.5em)",
+  },
+  expandRowKeys: {
+    type: Array,
+    default: () => [],
   },
   summaryMethod: {
     type: Function,
@@ -405,6 +411,14 @@
 const paginationSearch = ({ page, limit }) => {
   emit("pagination", { page: page, limit: limit });
 };
+
+const expandChange = (row, expandedRows) => {
+  emit("expand-change", row, expandedRows);
+};
+
+const handleSelectionChange = (newSelection) => {
+  emit("selection-change", newSelection);
+};
 </script>
 
 <style scoped lang="scss">
diff --git a/src/components/Upload/FileUpload.vue b/src/components/Upload/FileUpload.vue
index 53de217..295a528 100644
--- a/src/components/Upload/FileUpload.vue
+++ b/src/components/Upload/FileUpload.vue
@@ -18,8 +18,20 @@
     type: Boolean,
     default: false,
   },
+  showTip: {
+    type: Boolean,
+    default: true,
+  },
+  autoUpload: {
+    type: Boolean,
+    default: false,
+  },
+  limit: {
+    type: Number,
+    default: 1,
+  },
 });
-const emits = defineEmits(["success", "error"]);
+const emits = defineEmits(["success", "remove"]);
 
 const uploadRef = ref();
 const fileList = ref([]);
@@ -29,10 +41,12 @@
 };
 
 const handleFileSuccess = (response, file, fileList) => {
-  upload.open = false;
-  upload.isUploading = false;
-  uploadRef.value.handleRemove(file);
+  // uploadRef.value.handleRemove(file);
   emits("success", response, file, fileList);
+};
+
+const handleRemove = (file) => {
+  emits("remove", file);
 };
 
 defineExpose({
@@ -51,10 +65,11 @@
     :accept="accept"
     :headers="headers"
     :disabled="disabled"
-    :auto-upload="false"
-    :limit="1"
+    :auto-upload="autoUpload"
+    :limit="limit"
     :drag="true"
     :on-success="handleFileSuccess"
+    :on-remove="handleRemove"
   >
     <div class="el-upload__text">
       <el-icon class="el-icon--upload"><upload-filled /></el-icon>
@@ -64,7 +79,7 @@
       </div>
     </div>
     <template #tip>
-      <div class="el-upload__tip text-center">
+      <div v-if="showTip" class="el-upload__tip text-center">
         鍙兘涓婁紶xlsx/xls鏂囦欢锛屼笖涓嶈秴杩�10M
         <el-button
           type="primary"
diff --git a/src/hooks/useModal.js b/src/hooks/useModal.js
index 12d945c..0d443a1 100644
--- a/src/hooks/useModal.js
+++ b/src/hooks/useModal.js
@@ -8,11 +8,10 @@
   const openModal = (e) => {
     id.value = e;
     modalOptions.value = {
-      title: e ? "缂栬緫璁惧鍙拌处" : "鏂板璁惧鍙拌处",
+      title: e ? `淇敼${options.title}` : `鏂板${options.title}`,
       content: "纭畾鎵ц姝ゆ搷浣滃悧锛�",
       confirmText: "纭畾",
       cancelText: "鍙栨秷",
-      ...options,
     };
     visible.value = true;
   };
diff --git a/src/hooks/usePaginationApi.jsx b/src/hooks/usePaginationApi.jsx
index e28c816..749b078 100644
--- a/src/hooks/usePaginationApi.jsx
+++ b/src/hooks/usePaginationApi.jsx
@@ -1,6 +1,7 @@
 import { ref, reactive, watchEffect, unref } from "vue";
 import useFormData from "@/hooks/useFormData";
 import { deepClone, isEqual } from "@/utils/index.js"
+import { ElMessage } from 'element-plus'
 
 /**
  * 鍒嗛〉api
@@ -85,7 +86,7 @@
       ...getFinalParams(),
       current: pagination.currentPage,
       size: pagination.pageSize
-    }).then(({ code, data, ...rest }) => {
+    }).then(({ code, data, msg, ...rest }) => {
       if (code == 200) {
         // pagination.currentPage = meta.current_page;
         // pagination.pageSize = meta.per_page;
@@ -96,7 +97,7 @@
         loading.value = false;
       } else {
         loading.value = false;
-        ElMessage({ message: data.msg, type: "error" });
+        ElMessage({ message: msg, type: "error" });
       }
     });
   }
diff --git a/src/views/basicData/customerFile/index.vue b/src/views/basicData/customerFile/index.vue
index d67c4b6..c4fa332 100644
--- a/src/views/basicData/customerFile/index.vue
+++ b/src/views/basicData/customerFile/index.vue
@@ -1,97 +1,170 @@
 <template>
-<div class="app-container">
-  <div class="search_form">
-    <div>
-      <span class="search_title">瀹㈡埛鍚嶇О锛�</span>
-      <el-input
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title">瀹㈡埛鍚嶇О锛�</span>
+        <el-input
           v-model="searchForm.customerName"
           style="width: 240px"
           placeholder="璇疯緭鍏�"
           @change="handleQuery"
           clearable
           :prefix-icon="Search"
-      />
-      <el-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button>
+        />
+        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+          >鎼滅储</el-button
+        >
+      </div>
+      <div>
+        <el-button type="primary" @click="openForm('add')">鏂板瀹㈡埛</el-button>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="info" plain icon="Upload" @click="handleImport"
+          >瀵煎叆</el-button
+        >
+        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+      </div>
     </div>
-    <div>
-      <el-button type="primary" @click="openForm('add')">鏂板瀹㈡埛</el-button>
-      <el-button @click="handleOut">瀵煎嚭</el-button>
-      <el-button type="info" plain icon="Upload" @click="handleImport">瀵煎叆</el-button>
-      <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+    <div class="table_list">
+      <PIMTable
+        rowKey="id"
+        :column="tableColumn"
+        :tableData="tableData"
+        :page="page"
+        :isSelection="true"
+        @selection-change="handleSelectionChange"
+        :tableLoading="tableLoading"
+        @pagination="pagination"
+        :total="total"
+      ></PIMTable>
     </div>
-  </div>
-  <div class="table_list">
-    <PIMTable :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true" :handleSelectionChange="handleSelectionChange"
-              :tableLoading="tableLoading" @pagination="pagination" :total="total"></PIMTable>
-  </div>
-  <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">
-      <el-row :gutter="30">
-        <el-col :span="12">
-          <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerName">
-            <el-input v-model="form.customerName" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="绾崇◣浜鸿瘑鍒彿锛�" prop="taxpayerIdentificationNumber">
-            <el-input v-model="form.taxpayerIdentificationNumber" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row :gutter="30">
-        <el-col :span="12">
-          <el-form-item label="鍏徃鍦板潃锛�" prop="companyAddress">
-            <el-input v-model="form.companyAddress" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="鍏徃鐢佃瘽锛�" prop="companyPhone">
-            <el-input v-model="form.companyPhone" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row :gutter="30">
-        <el-col :span="12">
-          <el-form-item label="鑱旂郴浜猴細" prop="contactPerson">
-            <el-input v-model="form.contactPerson" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="鑱旂郴鐢佃瘽锛�" prop="contactPhone">
-            <el-input v-model="form.contactPhone" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row :gutter="30">
-        <el-col :span="12">
-          <el-form-item label="閾惰鍩烘湰鎴凤細" prop="basicBankAccount">
-            <el-input v-model="form.basicBankAccount" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="閾惰璐﹀彿锛�" prop="bankAccount">
-            <el-input v-model="form.bankAccount" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row :gutter="30">
-        <el-col :span="12">
-          <el-form-item label="寮�鎴疯鍙凤細" prop="bankCode">
-            <el-input v-model="form.bankCode" placeholder="璇疯緭鍏�" clearable/>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row :gutter="30">
-        <el-col :span="12">
-          <el-form-item label="缁存姢浜猴細" prop="maintainer">
-            <el-select v-model="form.maintainer" placeholder="璇烽�夋嫨" clearable disabled>
-              <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="缁存姢鏃堕棿锛�" prop="maintenanceTime" >
-            <el-date-picker
+    <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"
+      >
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerName">
+              <el-input
+                v-model="form.customerName"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item
+              label="绾崇◣浜鸿瘑鍒彿锛�"
+              prop="taxpayerIdentificationNumber"
+            >
+              <el-input
+                v-model="form.taxpayerIdentificationNumber"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鍏徃鍦板潃锛�" prop="companyAddress">
+              <el-input
+                v-model="form.companyAddress"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍏徃鐢佃瘽锛�" prop="companyPhone">
+              <el-input
+                v-model="form.companyPhone"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鑱旂郴浜猴細" prop="contactPerson">
+              <el-input
+                v-model="form.contactPerson"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鑱旂郴鐢佃瘽锛�" prop="contactPhone">
+              <el-input
+                v-model="form.contactPhone"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="閾惰鍩烘湰鎴凤細" prop="basicBankAccount">
+              <el-input
+                v-model="form.basicBankAccount"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="閾惰璐﹀彿锛�" prop="bankAccount">
+              <el-input
+                v-model="form.bankAccount"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="寮�鎴疯鍙凤細" prop="bankCode">
+              <el-input
+                v-model="form.bankCode"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="缁存姢浜猴細" prop="maintainer">
+              <el-select
+                v-model="form.maintainer"
+                placeholder="璇烽�夋嫨"
+                clearable
+                disabled
+              >
+                <el-option
+                  v-for="item in userList"
+                  :key="item.nickName"
+                  :label="item.nickName"
+                  :value="item.nickName"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="缁存姢鏃堕棿锛�" prop="maintenanceTime">
+              <el-date-picker
                 style="width: 100%"
                 v-model="form.maintenanceTime"
                 value-format="YYYY-MM-DD"
@@ -100,155 +173,186 @@
                 placeholder="璇烽�夋嫨"
                 clearable
                 disabled
-            />
-          </el-form-item>
-        </el-col>
-      </el-row>
-    </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>
-  <!-- 鐢ㄦ埛瀵煎叆瀵硅瘽妗� -->
-  <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
-    <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
-      <el-icon class="el-icon--upload"><upload-filled /></el-icon>
-      <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
-      <template #tip>
-        <div class="el-upload__tip text-center">
-          <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
-          <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">涓嬭浇妯℃澘</el-link>
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </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-upload>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
-        <el-button @click="upload.open = false">鍙� 娑�</el-button>
-      </div>
-    </template>
-  </el-dialog>
-</div>
+    </el-dialog>
+    <!-- 鐢ㄦ埛瀵煎叆瀵硅瘽妗� -->
+    <el-dialog
+      :title="upload.title"
+      v-model="upload.open"
+      width="400px"
+      append-to-body
+    >
+      <el-upload
+        ref="uploadRef"
+        :limit="1"
+        accept=".xlsx, .xls"
+        :headers="upload.headers"
+        :action="upload.url + '?updateSupport=' + upload.updateSupport"
+        :disabled="upload.isUploading"
+        :on-progress="handleFileUploadProgress"
+        :on-success="handleFileSuccess"
+        :auto-upload="false"
+        drag
+      >
+        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+        <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+        <template #tip>
+          <div class="el-upload__tip text-center">
+            <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
+            <el-link
+              type="primary"
+              :underline="false"
+              style="font-size: 12px; vertical-align: baseline"
+              @click="importTemplate"
+              >涓嬭浇妯℃澘</el-link
+            >
+          </div>
+        </template>
+      </el-upload>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
+          <el-button @click="upload.open = false">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
 </template>
 
 <script setup>
-import { ref } from 'vue'
-import {Search} from "@element-plus/icons-vue";
-import {addCustomer, delCustomer, getCustomer, listCustomer, updateCustomer} from "@/api/basicData/customerFile.js";
-import {ElMessageBox } from "element-plus";
-import {userListNoPage} from "@/api/system/user.js";
-import useUserStore from "@/store/modules/user"
-import {getToken} from "@/utils/auth.js";
-const { proxy } = getCurrentInstance()
-const userStore = useUserStore()
+import { ref } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import {
+  addCustomer,
+  delCustomer,
+  getCustomer,
+  listCustomer,
+  updateCustomer,
+} from "@/api/basicData/customerFile.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
+import { getToken } from "@/utils/auth.js";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore();
 
 const tableColumn = ref([
   {
-    label: '瀹㈡埛鍚嶇О',
-    prop: 'customerName',
+    label: "瀹㈡埛鍚嶇О",
+    prop: "customerName",
     width: 220,
   },
   {
-    label: '绾崇◣浜鸿瘑鍒爜',
-    prop: 'taxpayerIdentificationNumber',
+    label: "绾崇◣浜鸿瘑鍒爜",
+    prop: "taxpayerIdentificationNumber",
     width: 220,
   },
   {
-    label: '鍦板潃鍙婅仈绯绘柟寮�',
-    prop: 'addressPhone',
+    label: "鍦板潃鍙婅仈绯绘柟寮�",
+    prop: "addressPhone",
     width: 220,
   },
   {
-    label: '鑱旂郴浜�',
-    prop: 'contactPerson'
+    label: "鑱旂郴浜�",
+    prop: "contactPerson",
   },
   {
-    label: '鑱旂郴鐢佃瘽',
-    prop: 'contactPhone',
+    label: "鑱旂郴鐢佃瘽",
+    prop: "contactPhone",
   },
   {
-    label: '閾惰鍩烘湰鎴�',
-    prop: 'basicBankAccount',
+    label: "閾惰鍩烘湰鎴�",
+    prop: "basicBankAccount",
   },
   {
-    label: '閾惰璐﹀彿',
-    prop: 'bankAccount',
+    label: "閾惰璐﹀彿",
+    prop: "bankAccount",
   },
   {
-    label: '寮�鎴疯鍙�',
-    prop: 'bankCode',
+    label: "寮�鎴疯鍙�",
+    prop: "bankCode",
   },
   {
-    label: '缁存姢浜�',
-    prop: 'maintainer',
+    label: "缁存姢浜�",
+    prop: "maintainer",
   },
   {
-    label: '缁存姢鏃堕棿',
-    prop: 'maintenanceTime',
+    label: "缁存姢鏃堕棿",
+    prop: "maintenanceTime",
   },
   {
     dataType: "action",
     label: "鎿嶄綔",
-    align: 'center',
+    align: "center",
     operation: [
       {
         name: "缂栬緫",
         type: "text",
         clickFun: (row) => {
-          openForm('edit', row);
+          openForm("edit", row);
         },
       },
     ],
   },
-])
-const tableData = ref([])
-const selectedRows = ref([])
-const userList = ref([])
-const tableLoading = ref(false)
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const userList = ref([]);
+const tableLoading = ref(false);
 const page = reactive({
   current: 1,
   size: 10,
-})
-const total = ref(0)
+});
+const total = ref(0);
 
 // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref('')
-const dialogFormVisible = ref(false)
+const operationType = ref("");
+const dialogFormVisible = ref(false);
 const data = reactive({
   searchForm: {
-    customerName: '',
+    customerName: "",
   },
   form: {
-    customerName: '',
-    taxpayerIdentificationNumber: '',
-    companyAddress: '',
-    companyPhone: '',
-    contactPerson: '',
-    contactPhone: '',
-    maintainer: '',
-    maintenanceTime: '',
-    basicBankAccount:'',
-    bankAccount:'',
-    bankCode:''
+    customerName: "",
+    taxpayerIdentificationNumber: "",
+    companyAddress: "",
+    companyPhone: "",
+    contactPerson: "",
+    contactPhone: "",
+    maintainer: "",
+    maintenanceTime: "",
+    basicBankAccount: "",
+    bankAccount: "",
+    bankCode: "",
   },
   rules: {
     customerName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    taxpayerIdentificationNumber: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    taxpayerIdentificationNumber: [
+      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+    ],
     companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     contactPerson: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     contactPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
-    maintenanceTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+    maintenanceTime: [
+      { required: false, message: "璇烽�夋嫨", trigger: "change" },
+    ],
     basicBankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     bankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     bankCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-
-  }
-})
+  },
+});
 const upload = reactive({
   // 鏄惁鏄剧ず寮瑰嚭灞傦紙瀹㈡埛瀵煎叆锛�
   open: false,
@@ -259,147 +363,145 @@
   // 璁剧疆涓婁紶鐨勮姹傚ご閮�
   headers: { Authorization: "Bearer " + getToken() },
   // 涓婁紶鐨勫湴鍧�
-  url: import.meta.env.VITE_APP_BASE_API + "/basic/customer/importData"
-})
-const { searchForm, form, rules } = toRefs(data)
+  url: import.meta.env.VITE_APP_BASE_API + "/basic/customer/importData",
+});
+const { searchForm, form, rules } = toRefs(data);
 
 // 鏌ヨ鍒楄〃
 /** 鎼滅储鎸夐挳鎿嶄綔 */
 const handleQuery = () => {
-  page.current = 1
-  getList()
-}
+  page.current = 1;
+  getList();
+};
 const pagination = (obj) => {
   page.current = obj.page;
   page.size = obj.limit;
-  getList()
-}
+  getList();
+};
 const getList = () => {
-  tableLoading.value = true
-  listCustomer({...searchForm.value, ...page}).then(res => {
-    tableLoading.value = false
-    tableData.value = res.records
-    total.value = res.total
-  })
-}
+  tableLoading.value = true;
+  listCustomer({ ...searchForm.value, ...page }).then((res) => {
+    tableLoading.value = false;
+    tableData.value = res.records;
+    total.value = res.total;
+  });
+};
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
-  selectedRows.value = selection
-}
+  selectedRows.value = selection;
+};
 /** 鎻愪氦涓婁紶鏂囦欢 */
 function submitFileForm() {
-  proxy.$refs["uploadRef"].submit()
+  proxy.$refs["uploadRef"].submit();
 }
 /** 瀵煎叆鎸夐挳鎿嶄綔 */
 function handleImport() {
-  upload.title = "瀹㈡埛瀵煎叆"
-  upload.open = true
+  upload.title = "瀹㈡埛瀵煎叆";
+  upload.open = true;
 }
 // 鎵撳紑寮规
 const openForm = (type, row) => {
-  operationType.value = type
-  form.value = {}
-  form.value.maintainer = userStore.nickName
+  operationType.value = type;
+  form.value = {};
+  form.value.maintainer = userStore.nickName;
   form.value.maintenanceTime = getCurrentDate();
-  userListNoPage().then(res => {
-    userList.value = res.data
-  })
-  if (type === 'edit') {
-    getCustomer(row.id).then(res => {
-      form.value = {...res.data}
-    })
+  userListNoPage().then((res) => {
+    userList.value = res.data;
+  });
+  if (type === "edit") {
+    getCustomer(row.id).then((res) => {
+      form.value = { ...res.data };
+    });
   }
-  dialogFormVisible.value = true
-}
+  dialogFormVisible.value = true;
+};
 // 鎻愪氦琛ㄥ崟
 const submitForm = () => {
-  proxy.$refs["formRef"].validate(valid => {
+  proxy.$refs["formRef"].validate((valid) => {
     if (valid) {
       if (operationType.value === "edit") {
-        submitEdit()
+        submitEdit();
       } else {
-        submitAdd()
+        submitAdd();
       }
     }
-  })
-}
+  });
+};
 // 鎻愪氦鏂板
 const submitAdd = () => {
-  addCustomer(form.value).then(res => {
-    proxy.$modal.msgSuccess("鎻愪氦鎴愬姛")
-    closeDia()
-    getList()
-  })
-}
+  addCustomer(form.value).then((res) => {
+    proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+    closeDia();
+    getList();
+  });
+};
 // 鎻愪氦淇敼
 const submitEdit = () => {
-  updateCustomer(form.value).then(res => {
-    proxy.$modal.msgSuccess("鎻愪氦鎴愬姛")
-    closeDia()
-    getList()
-  })
-}
+  updateCustomer(form.value).then((res) => {
+    proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+    closeDia();
+    getList();
+  });
+};
 // 鍏抽棴寮规
 const closeDia = () => {
-  proxy.resetForm("formRef")
-  dialogFormVisible.value = false
-}
+  proxy.resetForm("formRef");
+  dialogFormVisible.value = false;
+};
 // 瀵煎嚭
 const handleOut = () => {
-  ElMessageBox.confirm(
-      '閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�',
-      '瀵煎嚭', {
-        confirmButtonText: '纭',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning',
-      }
-  ).then(() => {
-    proxy.download("/basic/customer/export", {}, '瀹㈡埛妗f.xlsx')
-  }).catch(() => {
-    proxy.$modal.msg("宸插彇娑�")
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
   })
-}
+    .then(() => {
+      proxy.download("/basic/customer/export", {}, "瀹㈡埛妗f.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
 // 鍒犻櫎
 const handleDelete = () => {
-  let ids = []
+  let ids = [];
   if (selectedRows.value.length > 0) {
-    ids = selectedRows.value.map(item => item.id);
+    ids = selectedRows.value.map((item) => item.id);
   } else {
-    proxy.$modal.msgWarning('璇烽�夋嫨鏁版嵁')
-    return
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
   }
-  ElMessageBox.confirm(
-      '閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�',
-      '鍒犻櫎鎻愮ず', {
-        confirmButtonText: '纭',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning',
-      }
-  ).then(() => {
-    tableLoading.value = true
-    delCustomer(ids).then(res => {
-      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
-      getList()
-    }).finally(() => {
-      tableLoading.value = false
-    })
-  }).catch(() => {
-    proxy.$modal.msg("宸插彇娑�")
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
   })
-}
+    .then(() => {
+      tableLoading.value = true;
+      delCustomer(ids)
+        .then((res) => {
+          proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+          getList();
+        })
+        .finally(() => {
+          tableLoading.value = false;
+        });
+    })
+    .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');
+  const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+  const day = String(today.getDate()).padStart(2, "0");
   return `${year}-${month}-${day}`;
 }
 
-getList()
+getList();
 </script>
 
-<style scoped lang="scss">
-
-</style>
+<style scoped lang="scss"></style>
diff --git a/src/views/basicData/product/index.vue b/src/views/basicData/product/index.vue
index 506c1db..6d31b8d 100644
--- a/src/views/basicData/product/index.vue
+++ b/src/views/basicData/product/index.vue
@@ -83,11 +83,12 @@
         </el-button>
       </div>
       <PIMTable
+        rowKey="id"
         :column="tableColumn"
         :tableData="tableData"
         :page="page"
         :isSelection="true"
-        :handleSelectionChange="handleSelectionChange"
+        @selection-change="handleSelectionChange"
         :tableLoading="tableLoading"
         @pagination="pagination"
         :total="total"
diff --git a/src/views/basicData/supplierManage/index.vue b/src/views/basicData/supplierManage/index.vue
index 63a179c..5aaed78 100644
--- a/src/views/basicData/supplierManage/index.vue
+++ b/src/views/basicData/supplierManage/index.vue
@@ -28,11 +28,12 @@
     </div>
     <div class="table_list">
       <PIMTable
+        rowKey="id"
         :column="tableColumn"
         :tableData="tableData"
         :page="page"
         :isSelection="true"
-        :handleSelectionChange="handleSelectionChange"
+        @selection-change="handleSelectionChange"
         :tableLoading="tableLoading"
         @pagination="pagination"
         :total="total"
diff --git a/src/views/equipmentManagement/ledger/index.vue b/src/views/equipmentManagement/ledger/index.vue
index 1582f96..83c416e 100644
--- a/src/views/equipmentManagement/ledger/index.vue
+++ b/src/views/equipmentManagement/ledger/index.vue
@@ -25,6 +25,7 @@
         </div>
       </div>
       <PIMTable
+        rowKey="id"
         :column="columns"
         :tableData="dataList"
         :page="{
diff --git a/src/views/personnelManagement/onboarding/index.vue b/src/views/personnelManagement/onboarding/index.vue
index 61f1301..cc1e8e5 100644
--- a/src/views/personnelManagement/onboarding/index.vue
+++ b/src/views/personnelManagement/onboarding/index.vue
@@ -4,177 +4,184 @@
       <div>
         <span class="search_title">濮撳悕锛�</span>
         <el-input
-            v-model="searchForm.customerName"
-            style="width: 240px"
-            placeholder="璇疯緭鍏ュ悕绉版悳绱�"
-            @change="handleQuery"
-            clearable
-            :prefix-icon="Search"
+          v-model="searchForm.customerName"
+          style="width: 240px"
+          placeholder="璇疯緭鍏ュ悕绉版悳绱�"
+          @change="handleQuery"
+          clearable
+          :prefix-icon="Search"
         />
-        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button>
+        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+          >鎼滅储</el-button
+        >
       </div>
       <div>
         <el-button type="primary" @click="openForm">鏂板鍏ヨ亴</el-button>
       </div>
     </div>
     <div class="table_list">
-      <PIMTable :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true"
-                :handleSelectionChange="handleSelectionChange" :tableLoading="tableLoading" @pagination="pagination"
-                :total="total"></PIMTable>
+      <PIMTable
+        rowKey="id"
+        :column="tableColumn"
+        :tableData="tableData"
+        :page="page"
+        :isSelection="true"
+        @selection-change="handleSelectionChange"
+        :tableLoading="tableLoading"
+        @pagination="pagination"
+        :total="total"
+      ></PIMTable>
     </div>
   </div>
 </template>
 
 <script setup>
-import {Search} from "@element-plus/icons-vue";
-import {ref} from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { ref } from "vue";
 
 const data = reactive({
   searchForm: {
-    customerName: '',
+    customerName: "",
   },
   form: {
-    salesLedgerId: '',
-    customerName: '',
-    salesman: '',
-    projectName: '',
-    productData: []
+    salesLedgerId: "",
+    customerName: "",
+    salesman: "",
+    projectName: "",
+    productData: [],
   },
   rules: {
-    salesLedgerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }]
-  }
-})
-const { searchForm, form, rules } = toRefs(data)
+    salesLedgerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+  },
+});
+const { searchForm, form, rules } = toRefs(data);
 const tableColumn = ref([
   {
-    label: '鐘舵��',
-    prop: 'paymentDate',
-    dataType: 'tag',
+    label: "鐘舵��",
+    prop: "paymentDate",
+    dataType: "tag",
     formatData: (params) => {
       if (params == 0) {
-        return '鍦ㄨ亴';
+        return "鍦ㄨ亴";
       } else if (params == 1) {
-        return '绂昏亴';
+        return "绂昏亴";
       } else {
-        return null
+        return null;
       }
     },
     formatType: (params) => {
       if (params == 0) {
-        return 'primary';
+        return "primary";
       } else if (params == 1) {
-        return 'danger';
+        return "danger";
       } else {
-        return null
+        return null;
       }
-    }
+    },
   },
   {
-    label: '鍛樺伐缂栧彿',
-    prop: 'supplierName',
+    label: "鍛樺伐缂栧彿",
+    prop: "supplierName",
   },
   {
-    label: '濮撳悕',
-    prop: 'currentPaymentAmount',
+    label: "濮撳悕",
+    prop: "currentPaymentAmount",
   },
   {
-    label: '鎬у埆',
-    prop: 'paymentMethod'
+    label: "鎬у埆",
+    prop: "paymentMethod",
   },
   {
-    label: '绫嶈疮',
-    prop: 'registrant'
+    label: "绫嶈疮",
+    prop: "registrant",
   },
   {
-    label: '宀椾綅',
-    prop: 'registrationtDate'
+    label: "宀椾綅",
+    prop: "registrationtDate",
   },
   {
-    label: '瀹跺涵浣忓潃',
-    prop: 'registrationtDate'
+    label: "瀹跺涵浣忓潃",
+    prop: "registrationtDate",
   },
   {
-    label: '绗竴瀛﹀巻',
-    prop: 'registrationtDate'
+    label: "绗竴瀛﹀巻",
+    prop: "registrationtDate",
   },
   {
-    label: '涓撲笟',
-    prop: 'registrationtDate'
+    label: "涓撲笟",
+    prop: "registrationtDate",
   },
   {
-    label: '韬唤璇佸彿',
-    prop: 'registrationtDate'
+    label: "韬唤璇佸彿",
+    prop: "registrationtDate",
   },
   {
-    label: '骞撮緞',
-    prop: 'registrationtDate'
+    label: "骞撮緞",
+    prop: "registrationtDate",
   },
   {
-    label: '鑱旂郴鐢佃瘽',
-    prop: 'registrationtDate'
+    label: "鑱旂郴鐢佃瘽",
+    prop: "registrationtDate",
   },
   {
-    label: '绱ф�ヨ仈绯讳汉',
-    prop: 'registrationtDate'
+    label: "绱ф�ヨ仈绯讳汉",
+    prop: "registrationtDate",
   },
   {
-    label: '鑱旂郴鐢佃瘽',
-    prop: 'registrationtDate'
+    label: "鑱旂郴鐢佃瘽",
+    prop: "registrationtDate",
   },
   {
-    label: '鍚堝悓骞撮檺',
-    prop: 'registrationtDate'
+    label: "鍚堝悓骞撮檺",
+    prop: "registrationtDate",
   },
   {
-    label: '鍚堝悓寮�濮嬫棩鏈�',
-    prop: 'registrationtDate'
+    label: "鍚堝悓寮�濮嬫棩鏈�",
+    prop: "registrationtDate",
   },
   {
-    label: '鍚堝悓缁撴潫鏃ユ湡',
-    prop: 'registrationtDate'
+    label: "鍚堝悓缁撴潫鏃ユ湡",
+    prop: "registrationtDate",
   },
-])
-const tableData = ref([])
-const selectedRows = ref([])
-const tableLoading = ref(false)
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
 const page = reactive({
   current: 1,
   size: 100,
-})
-const total = ref(0)
-
+});
+const total = ref(0);
 
 // 鏌ヨ鍒楄〃
 /** 鎼滅储鎸夐挳鎿嶄綔 */
 const handleQuery = () => {
-  page.current = 1
-  getList()
-}
+  page.current = 1;
+  getList();
+};
 const pagination = (obj) => {
   page.current = obj.page;
   page.size = obj.limit;
-  getList()
-}
+  getList();
+};
 const getList = () => {
-  tableLoading.value = true
-  ledgerListPage({...searchForm.value, ...page}).then(res => {
-    tableLoading.value = false
+  tableLoading.value = true;
+  ledgerListPage({ ...searchForm.value, ...page }).then((res) => {
+    tableLoading.value = false;
     tableData.value = res.records;
-    total.value = res.total
-  })
-}
+    total.value = res.total;
+  });
+};
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
-  console.log('selection', selection)
-  selectedRows.value = selection.filter(item => item.salesContractNo !== undefined);
-}
+  console.log("selection", selection);
+  selectedRows.value = selection.filter(
+    (item) => item.salesContractNo !== undefined
+  );
+};
 
 // 鎵撳紑寮规
-const openForm = () => {
-
-}
+const openForm = () => {};
 </script>
 
-<style scoped>
-
-</style>
\ No newline at end of file
+<style scoped></style>
diff --git a/src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue b/src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue
new file mode 100644
index 0000000..0523e40
--- /dev/null
+++ b/src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue
@@ -0,0 +1,111 @@
+<template>
+  <PIMTable
+    rowKey="id"
+    :column="columns"
+    :tableData="dataList"
+    :tableLoading="loading"
+  >
+  </PIMTable>
+</template>
+
+<script setup>
+import { usePaginationApi } from "@/hooks/usePaginationApi";
+import { productList } from "@/api/procurementManagement/procurementLedger.js";
+
+defineOptions({
+  name: "鏉ョエ鐧昏鎶樺彔琛�",
+});
+
+const {
+  loading,
+  filters,
+  columns,
+  dataList,
+  pagination,
+  getTableData,
+  resetFilters,
+} = usePaginationApi(
+  productList,
+  {
+    salesLedgerId: undefined,
+    type: 2,
+  },
+  [
+    {
+      label: "浜у搧澶х被",
+      prop: "productCategory",
+    },
+    {
+      label: "瑙勬牸鍨嬪彿",
+      prop: "specificationModel",
+    },
+    {
+      label: "鍗曚綅",
+      prop: "unit",
+    },
+    {
+      label: "鏁伴噺",
+      prop: "quantity",
+    },
+    {
+      label: "绋庣巼(%)",
+      prop: "taxRate",
+    },
+    {
+      label: "鍚◣鍗曚环(鍏�)",
+      prop: "taxInclusiveUnitPrice",
+      formatData: (val) => {
+        return parseFloat(val).toFixed(2) ?? 0;
+      },
+    },
+    {
+      label: "鍚◣鎬讳环(鍏�)",
+      prop: "taxInclusiveTotalPrice",
+      formatData: (val) => {
+        return parseFloat(val).toFixed(2) ?? 0;
+      },
+    },
+    {
+      label: "涓嶅惈绋庢�讳环(鍏�)",
+      prop: "taxExclusiveTotalPrice",
+      formatData: (val) => {
+        return parseFloat(val).toFixed(2) ?? 0;
+      },
+    },
+    {
+      label: "鏈鏉ョエ閲戦(鍏�)",
+      prop: "ticketsAmount",
+      formatData: (val) => {
+        return parseFloat(val).toFixed(2) ?? 0;
+      },
+    },
+    {
+      label: "鏈潵绁ㄦ暟",
+      prop: "futureTickets",
+    },
+    {
+      label: "鏈潵绁ㄩ噾棰�(鍏�)",
+      prop: "futureTicketsAmount",
+      formatData: (val) => {
+        return parseFloat(val).toFixed(2) ?? 0;
+      },
+    },
+  ],
+  {},
+  {},
+  (data) => {
+    dataList.value = data;
+  }
+);
+
+const getList = (id) => {
+  filters.salesLedgerId = id;
+  getTableData();
+};
+
+defineExpose({
+  getList,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/procurementManagement/invoiceEntry/components/Modal.vue b/src/views/procurementManagement/invoiceEntry/components/Modal.vue
new file mode 100644
index 0000000..41a0745
--- /dev/null
+++ b/src/views/procurementManagement/invoiceEntry/components/Modal.vue
@@ -0,0 +1,407 @@
+<template>
+  <el-dialog :title="modalOptions.title" v-model="visible" width="70%">
+    <el-form
+      ref="formRef"
+      :model="form"
+      :rules="rules"
+      label-width="120px"
+      label-position="top"
+    >
+      <el-row :gutter="30">
+        <el-col :span="12">
+          <el-form-item label="閲囪喘鍚堝悓鍙凤細" prop="purchaseLedgerNo">
+            <el-input v-model="form.purchaseLedgerNo" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
+            <el-input
+              v-model="form.salesContractNo"
+              placeholder="鑷姩濉厖"
+              clearable
+              disabled
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="渚涘簲鍟嗗悕绉帮細" prop="supplierName">
+            <el-input
+              v-model="form.supplierName"
+              placeholder="鑷姩濉厖"
+              clearable
+              disabled
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
+            <el-input
+              v-model="form.projectName"
+              placeholder="鑷姩濉厖"
+              clearable
+              disabled
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="鍙戠エ鍙凤細" prop="invoiceNumber">
+            <el-input
+              v-model="form.invoiceNumber"
+              placeholder="璇疯緭鍏�"
+              clearable
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="鍙戠エ閲戦(鍏�)锛�" prop="invoiceAmount">
+            <el-input
+              type="number"
+              :step="0.01"
+              :min="0"
+              v-model="form.invoiceAmount"
+              placeholder="鑷姩濉厖"
+              clearable
+              :disabled="true"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="褰曞叆浜猴細" prop="issUer">
+            <el-input
+              v-model="form.issUer"
+              placeholder="璇疯緭鍏�"
+              clearable
+              disabled
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="寮�绁ㄦ棩鏈燂細" prop="entryDate">
+            <el-date-picker
+              style="width: 100%"
+              v-model="form.entryDate"
+              type="date"
+              clearable
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="涓婁紶闄勪欢">
+            <FileUpload
+              :showTip="false"
+              accept="*"
+              :autoUpload="true"
+              :action="action"
+              :headers="{
+                Authorization: 'Bearer ' + getToken(),
+              }"
+              :limit="10"
+              @success="uploadSuccess"
+              @remove="removeFile"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate"> </el-form-item>
+      <PIMTable
+        rowKey="id"
+        :column="columns"
+        :tableData="form.productData"
+        height="auto"
+      >
+        <template #ticketsNumRef="{ row }">
+          <el-input-number
+            v-model="row.ticketsNum"
+            placeholder="璇烽�夋嫨"
+            :min="0"
+            :step="0.1"
+            clearable
+            style="width: 100%"
+            @change="invoiceNumBlur(row)"
+          />
+        </template>
+        <template #ticketsAmountRef="{ row }">
+          <el-input-number
+            v-model="row.ticketsAmount"
+            placeholder="璇烽�夋嫨"
+            :min="0"
+            :step="0.1"
+            clearable
+            style="width: 100%"
+            @change="invoiceAmountBlur(row)"
+          />
+        </template>
+      </PIMTable>
+    </el-form>
+    <template #footer>
+      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
+      <el-button type="primary" :loading="modalLoading" @click="submitForm">
+        {{ modalOptions.confirmText }}
+      </el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance } from "vue";
+import { useModal } from "@/hooks/useModal";
+import useFormData from "@/hooks/useFormData";
+import FileUpload from "@/components/Upload/FileUpload.vue";
+import {
+  getPurchaseNoById,
+  getInfo,
+  addOrUpdateRegistration,
+} from "@/api/procurementManagement/invoiceEntry.js";
+import { getPurchaseById } from "@/api/procurementManagement/procurementLedger.js";
+import { getToken } from "@/utils/auth";
+import useUserStore from "@/store/modules/user";
+
+defineOptions({
+  name: "鏉ョエ鐧昏妯℃�佹",
+});
+
+const userStore = useUserStore();
+const action = import.meta.env.VITE_APP_BASE_API + "/file/upload";
+const formRef = ref();
+const { proxy } = getCurrentInstance();
+const { form } = useFormData({
+  purchaseLedgerNo: undefined, // 閲囪喘鍚堝悓鍙�
+  salesContractNo: undefined, // 閿�鍞悎鍚屽彿
+  supplierName: undefined, // 渚涘簲鍟嗗悕绉�
+  projectName: undefined, // 椤圭洰鍚嶇О
+  invoiceNumber: undefined, // 鍙戠エ鍙�
+  invoiceAmount: undefined, // 鍙戠エ閲戦(鍏�)
+  issUerId: userStore.id, // 褰曞叆浜�
+  issUer: userStore.nickName, // 褰曞叆浜�
+  entryDate: undefined, // 寮�绁ㄦ棩鏈�
+  salesContractNoId: undefined, // 寮�绁ㄦ棩鏈�
+  productData: [], // 琛ㄦ牸
+  tempFileIds: [], // 鏂囦欢
+});
+
+const rules = ref({
+  invoiceNumber: [
+    { required: true, message: "璇疯緭鍏ュ彂绁ㄥ彿", trigger: "blur" },
+    { type: "string" },
+  ],
+  invoiceAmount: [
+    { required: true, message: "璇疯緭鍏ュ彂绁ㄩ噾棰�", trigger: "blur" },
+  ],
+});
+
+const {
+  id,
+  visible,
+  loading: modalLoading,
+  openModal,
+  modalOptions,
+  handleConfirm,
+  closeModal,
+} = useModal({
+  title: "鏉ョエ鐧昏",
+});
+
+const columns = [
+  {
+    label: "浜у搧澶х被",
+    prop: "productCategory",
+  },
+  {
+    label: "瑙勬牸鍨嬪彿",
+    prop: "specificationModel",
+  },
+  {
+    label: "鍗曚綅",
+    prop: "unit",
+    width: 80,
+  },
+  {
+    label: "鏁伴噺",
+    prop: "quantity",
+    width: 80,
+  },
+  {
+    label: "绋庣巼(%)",
+    prop: "taxRate",
+    width: 80,
+  },
+  {
+    label: "褰曞叆鏃ユ湡",
+    prop: "registerDate",
+    width: 120,
+  },
+  {
+    label: "鍚◣鍗曚环(鍏�)",
+    prop: "taxInclusiveUnitPrice",
+    width: 150,
+    formatData: (val) => {
+      return parseFloat(val).toFixed(2) ?? 0;
+    },
+  },
+  {
+    label: "鍚◣鎬讳环(鍏�)",
+    prop: "taxInclusiveTotalPrice",
+    width: 150,
+    formatData: (val) => {
+      return parseFloat(val).toFixed(2) ?? 0;
+    },
+  },
+  {
+    label: "涓嶅惈绋庢�讳环(鍏�)",
+    prop: "taxExclusiveTotalPrice",
+    width: 150,
+    formatData: (val) => {
+      return parseFloat(val).toFixed(2) ?? 0;
+    },
+  },
+  {
+    label: "鏈鏉ョエ鏁�",
+    prop: "ticketsNum",
+    dataType: "slot",
+    slot: "ticketsNumRef",
+    width: 180,
+    align: "center",
+  },
+  {
+    label: "鏈鏉ョエ閲戦(鍏�)",
+    prop: "ticketsAmount",
+    dataType: "slot",
+    slot: "ticketsAmountRef",
+    width: 180,
+    align: "center",
+  },
+  {
+    label: "鏈潵绁ㄦ暟",
+    prop: "futureTickets",
+  },
+  {
+    label: "鏈潵绁ㄩ噾棰�(鍏�)",
+    prop: "futureTicketsAmount",
+  },
+];
+
+const getTableData = async (type, id) => {
+  if (type == "add") {
+    const { data } = await getPurchaseNoById({ id });
+    form.purchaseLedgerNo = data.purchaseContractNumber;
+    form.invoiceAmount = data.invoiceAmount;
+    form.invoiceNumber = data.invoiceNumber;
+    form.entryDate = data.entryDate;
+    form.salesContractNoId = data.salesContractNoId;
+
+    const { data: infoData } = await getInfo({ id });
+    form.salesContractNo = infoData.salesContractNo;
+    form.projectName = infoData.projectName;
+    form.supplierName = infoData.supplierName;
+    form.productData = infoData.productData;
+  } else if (type == "edit") {
+    const data = await getPurchaseById({ id, type: 2 });
+    form.purchaseLedgerNo = data.purchaseContractNumber;
+    form.invoiceAmount = data.invoiceAmount;
+    form.invoiceNumber = data.invoiceNumber;
+    form.salesContractNo = data.salesContractNo;
+    form.projectName = data.projectName;
+    form.supplierName = data.supplierName;
+    form.entryDate = data.entryDate;
+    form.productData = data.productData;
+  }
+};
+
+//鏈鏉ョエ鏁板け鐒︽搷浣�
+const invoiceNumBlur = (row) => {
+  if (!row.ticketsNum || row.ticketsNum === "") {
+    row.ticketsNum = 0;
+  }
+  if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
+    proxy.$modal.msgWarning("鏈寮�绁ㄦ暟涓嶅緱澶т簬鏈紑绁ㄦ暟");
+    row.ticketsNum = 0;
+    return;
+  }
+  // 璁$畻鏈鏉ョエ閲戦
+  row.ticketsAmount = row.ticketsNum * row.taxInclusiveUnitPrice;
+  // 璁$畻鏈潵绁ㄦ暟
+  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
+  // 璁$畻鏈潵绁ㄩ噾棰�
+  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
+  calculateinvoiceAmount();
+};
+
+// 鏈鏉ョエ閲戦澶辩劍鎿嶄綔
+const invoiceAmountBlur = (row) => {
+  if (!row.ticketsAmount) {
+    row.ticketsAmount = 0;
+  }
+  // 璁$畻鏄惁瓒呰繃鏉ョエ鎬婚噾棰�
+  if (row.ticketsAmount > row.tempFutureTicketsAmount) {
+    proxy.$modal.msgWarning("鏈鏉ョエ閲戦涓嶅緱澶т簬鏈潵绁ㄩ噾棰�");
+    row.ticketsAmount = 0;
+  }
+  // 璁$畻鏈鏉ョエ鏁�
+  row.ticketsNum = Number(
+    (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2)
+  );
+  // 璁$畻鏈潵绁ㄦ暟
+  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
+  // 璁$畻鏈潵绁ㄩ噾棰�
+  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
+  calculateinvoiceAmount();
+};
+
+const calculateinvoiceAmount = () => {
+  let invoiceAmountTotal = 0;
+  form.productData.forEach((item) => {
+    if (item.ticketsAmount) {
+      invoiceAmountTotal += item.ticketsAmount;
+    }
+  });
+  form.invoiceAmount = invoiceAmountTotal.toFixed(2);
+};
+
+const open = (type, eid) => {
+  openModal();
+  getTableData(type, eid);
+  id.value = eid;
+};
+
+const uploadSuccess = (response) => {
+  form.tempFileIds.push(response.data.tempId);
+  console.log(form);
+};
+
+const removeFile = (file) => {
+  const { tempId } = file.response.data;
+  form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId);
+};
+
+const submitForm = () => {
+  formRef.value.validate(async (valid, fields) => {
+    if (valid) {
+      modalLoading.value = true;
+      const { code } = await addOrUpdateRegistration({
+        purchaseLedgerId: id.value,
+        purchaseContractNumber: form.purchaseLedgerNo,
+        invoiceNumber: form.invoiceNumber,
+        invoiceAmount: form.invoiceAmount,
+        salesContractNo: form.salesContractNo,
+        projectName: form.projectName,
+        productData: form.productData,
+        issUerId: form.issUerId, // 褰曞叆浜�
+        issUer: form.issUer, // 褰曞叆浜�
+        salesContractNoId: form.salesContractNoId,
+        supplierName: form.supplierName,
+        tempFileIds: form.tempFileIds,
+      });
+      modalLoading.value = false;
+      if (code == 200) {
+        closeModal();
+      }
+    }
+  });
+};
+
+defineExpose({
+  open,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/procurementManagement/invoiceEntry/index.vue b/src/views/procurementManagement/invoiceEntry/index.vue
index d9c9231..6de82f0 100644
--- a/src/views/procurementManagement/invoiceEntry/index.vue
+++ b/src/views/procurementManagement/invoiceEntry/index.vue
@@ -1,699 +1,185 @@
 <template>
   <div class="app-container">
     <div class="search_form">
-      <div>
-        <span class="search_title">閲囪喘鍚堝悓鍙凤細</span>
-        <el-input
-          v-model="searchForm.purchaseContractNumber"
-          style="width: 240px"
-          placeholder="璇疯緭鍏�"
-          @change="handleQuery"
-          clearable
-          prefix-icon="Search"
-        />
-        <el-button
-          type="primary"
-          @click="handleQuery"
-          style="margin-left: 10px"
-        >
-          鎼滅储
-        </el-button>
-      </div>
-      <div>
-        <el-button type="primary" @click="handleAdd">鏂板鐧昏</el-button>
-        <el-button @click="handleOut">瀵煎嚭</el-button>
-        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
-      </div>
+      <el-form :model="filters" :inline="true">
+        <el-form-item label="閲囪喘鍚堝悓鍙凤細">
+          <el-input
+            v-model="filters.purchaseContractNumber"
+            placeholder="璇疯緭鍏�"
+            clearable
+            prefix-icon="Search"
+            @change="getTableData"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="getTableData"> 鎼滅储 </el-button>
+          <el-button @click="resetFilters"> 閲嶇疆 </el-button>
+        </el-form-item>
+      </el-form>
     </div>
     <div class="table_list">
-      <el-table
-        :data="tableData"
-        border
-        v-loading="tableLoading"
-        @selection-change="handleSelectionChange"
-        :expand-row-keys="expandedRowKeys"
-        :row-key="(row) => row.id"
-        show-summary
-        :summary-method="summarizeMainTable"
-        @expand-change="expandChange"
-        height="calc(100vh - 18.5em)"
-      >
-        <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="quantity" />
-              <el-table-column label="绋庣巼(%)" prop="taxRate" />
-              <el-table-column
-                label="鍚◣鍗曚环(鍏�)"
-                prop="taxInclusiveUnitPrice"
-                :formatter="formattedNumber"
-              />
-              <el-table-column
-                label="鍚◣鎬讳环(鍏�)"
-                prop="taxInclusiveTotalPrice"
-                :formatter="formattedNumber"
-              />
-              <el-table-column
-                label="涓嶅惈绋庢�讳环(鍏�)"
-                prop="taxExclusiveTotalPrice"
-                :formatter="formattedNumber"
-              />
-              <el-table-column label="鏈鏉ョエ鏁�" prop="ticketsNum" />
-              <el-table-column
-                label="鏈鏉ョエ閲戦(鍏�)"
-                prop="ticketsAmount"
-                :formatter="formattedNumber"
-              />
-              <el-table-column label="鏈潵绁ㄦ暟" prop="futureTickets" />
-              <el-table-column
-                label="鏈潵绁ㄩ噾棰�(鍏�)"
-                prop="futureTicketsAmount"
-                :formatter="formattedNumber"
-              />
-            </el-table>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-        <el-table-column
-          label="閲囪喘鍚堝悓鍙�"
-          prop="purchaseContractNumber"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="閿�鍞悎鍚屽彿"
-          prop="salesContractNo"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="渚涘簲鍟嗗悕绉�"
-          prop="supplierName"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="椤圭洰鍚嶇О"
-          prop="projectName"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="鍚堝悓閲戦(鍏�)"
-          prop="contractAmount"
-          show-overflow-tooltip
-          :formatter="formattedNumber"
-        />
-        <el-table-column
-          label="宸插紑绁ㄩ噾棰�(鍏�)"
-          prop="receiptPaymentAmount"
-          show-overflow-tooltip
-          :formatter="formattedNumber"
-        />
-        <el-table-column
-          label="寰呭紑绁ㄩ噾棰�(鍏�)"
-          prop="unReceiptPaymentAmount"
-          show-overflow-tooltip
-          :formatter="formattedNumber"
-        />
-        <!-- <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center">
-          <template #default="scope">
-            <el-button link type="primary" size="small" @click="openForm('edit', scope.row);">缂栬緫</el-button>
-          </template>
-        </el-table-column> -->
-      </el-table>
-      <pagination
-        v-show="total > 0"
-        :total="total"
-        layout="total, sizes, prev, pager, next, jumper"
-        :page="page.current"
-        :limit="page.size"
-        @pagination="paginationChange"
-      />
-    </div>
-    <el-dialog
-      v-model="dialogFormVisible"
-      :title="operationType === 'add' ? '鏂板鏉ョエ鐧昏' : '缂栬緫鏉ョエ鐧昏'"
-      width="80%"
-      @close="closeDia"
-    >
-      <el-form
-        :model="form"
-        label-width="140px"
-        label-position="top"
-        :rules="rules"
-        ref="formRef"
-      >
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="閲囪喘鍚堝悓鍙凤細" prop="purchaseLedgerNo">
-              <el-input v-model="form.purchaseLedgerNo" disabled />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
-              <el-input
-                v-model="form.salesContractNo"
-                placeholder="鑷姩濉厖"
-                clearable
-                disabled
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="渚涘簲鍟嗗悕绉帮細" prop="supplierName">
-              <el-input
-                v-model="form.supplierName"
-                placeholder="鑷姩濉厖"
-                clearable
-                disabled
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
-              <el-input
-                v-model="form.projectName"
-                placeholder="鑷姩濉厖"
-                clearable
-                disabled
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="鍙戠エ鍙凤細" prop="invoiceNumber">
-              <el-input
-                v-model="form.invoiceNumber"
-                placeholder="璇疯緭鍏�"
-                clearable
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="鍙戠エ閲戦(鍏�)锛�" prop="invoiceAmount">
-              <el-input
-                type="number"
-                :step="0.01"
-                v-model="form.invoiceAmount"
-                placeholder="璇疯緭鍏�"
-                clearable
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="褰曞叆浜猴細" prop="issUer">
-              <el-input
-                v-model="form.issUer"
-                placeholder="璇疯緭鍏�"
-                clearable
-                disabled
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="寮�绁ㄦ棩鏈燂細" prop="issueDate">
-              <el-date-picker
-                style="width: 100%"
-                v-model="form.issueDate"
-                type="date"
-                clearable
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <!-- <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="褰曞叆鏃ユ湡锛�" prop="createTime">
-              <el-date-picker
-                style="width: 100%"
-                v-model="form.createTime"
-                type="date"
-                placeholder="璇烽�夋嫨"
-                clearable
-              />
-            </el-form-item>
-          </el-col>
-        </el-row> -->
-        <el-row>
-          <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate"> </el-form-item>
-        </el-row>
-        <el-table
-          :data="productData"
-          border
-          @selection-change="productSelected"
-          show-summary
-          style="width: 100%"
-          :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" width="70" />
-          <el-table-column label="鏁伴噺" prop="quantity" width="70" />
-          <el-table-column label="绋庣巼(%)" prop="taxRate" width="80" />
-          <el-table-column label="褰曞叆鏃ユ湡" prop="createTime" width="120" />
-          <el-table-column
-            label="鍚◣鍗曚环(鍏�)"
-            width="150"
-            prop="taxInclusiveUnitPrice"
-            :formatter="formattedNumber"
-          />
-          <el-table-column
-            label="鍚◣鎬讳环(鍏�)"
-            width="150"
-            prop="taxInclusiveTotalPrice"
-            :formatter="formattedNumber"
-          />
-          <el-table-column
-            label="涓嶅惈绋庢�讳环(鍏�)"
-            width="150"
-            prop="taxExclusiveTotalPrice"
-            :formatter="formattedNumber"
-          />
-          <el-table-column label="鏈鏉ョエ鏁�" prop="ticketsNum" width="170">
-            <template #default="scope">
-              <el-input-number
-                v-model="scope.row.ticketsNum"
-                placeholder="璇烽�夋嫨"
-                :min="0"
-                :step="0.1"
-                clearable
-                style="width: 100%"
-                @change="invoiceNumBlur(scope.row)"
-              />
-            </template>
-          </el-table-column>
-          <el-table-column
-            label="鏈鏉ョエ閲戦(鍏�)"
-            prop="ticketsAmount"
-            :min="0"
-            :step="0.1"
-            :formatter="formattedNumber"
-            @change="invoiceAmountBlur"
-            width="170"
-          >
-            <template #default="scope">
-              <el-input-number
-                v-model="scope.row.ticketsAmount"
-                placeholder="璇烽�夋嫨"
-                :min="0"
-                :step="0.1"
-                clearable
-                style="width: 100%"
-                @change="invoiceAmountBlur(scope.row)"
-              />
-            </template>
-          </el-table-column>
-          <el-table-column
-            label="鏈潵绁ㄦ暟"
-            prop="futureTickets"
-            :="
-              (row) =>
-                row.futureTickets == null || row.futureTickets === ''
-                  ? row.quantity
-                  : row.futureTickets
-            "
-          >
-          </el-table-column>
-          <el-table-column
-            label="鏈潵绁ㄩ噾棰�(鍏�)"
-            prop="futureTicketsAmount"
-            :formatter="
-              (row) =>
-                row.futureTicketsAmount !== undefined &&
-                row.futureTicketsAmount !== null &&
-                row.futureTicketsAmount !== ''
-                  ? row.futureTicketsAmount
-                  : row.taxExclusiveTotalPrice
-            "
-          >
-          </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 class="actions">
+        <div></div>
+        <div>
+          <el-button type="primary" @click="handleAdd('add')">
+            鏂板鐧昏
+          </el-button>
+          <el-button @click="handleOut">瀵煎嚭</el-button>
+          <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
         </div>
-      </template>
-    </el-dialog>
+      </div>
+      <PIMTable
+        rowKey="id"
+        :column="columns"
+        :tableData="dataList"
+        :tableLoading="loading"
+        :isSelection="true"
+        :page="{
+          current: pagination.currentPage,
+          size: pagination.pageSize,
+          total: pagination.total,
+        }"
+        :expand-row-keys="expandRowKeys"
+        @expand-change="expandChange"
+        @selection-change="handleSelectionChange"
+      >
+        <template #expand="{ row }">
+          <ExpandTable ref="expandTableRef" />
+        </template>
+        <template #operation="{ row }">
+          <el-button
+            text
+            type="primary"
+            size="small"
+            @click="handleEdit('edit', row.id)"
+          >
+            缂栬緫
+          </el-button>
+        </template>
+      </PIMTable>
+    </div>
+    <Modal ref="modalRef"></Modal>
   </div>
 </template>
 
 <script setup>
-import pagination from "@/components/PIMTable/Pagination.vue";
-import { ref } from "vue";
-import { ElMessageBox } from "element-plus";
-import { userListNoPage } from "@/api/system/user.js";
-import { productList } from "@/api/procurementManagement/procurementLedger.js";
-import useUserStore from "@/store/modules/user";
-const userStore = useUserStore();
+import { usePaginationApi } from "@/hooks/usePaginationApi";
+import { gePurchaseListPage } from "@/api/procurementManagement/invoiceEntry.js";
+import { nextTick, onMounted, getCurrentInstance } from "vue";
+import ExpandTable from "./components/ExpandTable.vue";
+import Modal from "./components/Modal.vue";
+
+defineOptions({
+  name: "鏉ョエ鐧昏",
+});
+
 const { proxy } = getCurrentInstance();
-const tableData = ref([]);
-const productData = ref([]);
+const expandRowKeys = ref([]);
+const expandTableRef = ref();
+const modalRef = ref();
 const selectedRows = ref([]);
-const productSelectedRows = ref([]);
-const userList = ref([]);
-const purchaseLedgerList = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
-  current: 1,
-  size: 100,
-});
-const total = ref(0);
-const fileList = ref([]);
-import {
-  addOrUpdateRegistration,
-  delRegistration,
+
+const {
+  loading,
+  filters,
+  columns,
+  dataList,
+  pagination,
+  getTableData,
+  resetFilters,
+} = usePaginationApi(
   gePurchaseListPage,
-  getInfo,
-  getProduct,
-  getPurchaseNoById,
-  getRegistrationById,
-} from "@/api/procurementManagement/invoiceEntry.js";
+  {
+    purchaseContractNumber: undefined,
+  },
+  [
+    {
+      type: "expand",
+      dataType: "slot",
+      slot: "expand",
+    },
+    {
+      label: "閿�鍞悎鍚屽彿",
+      prop: "salesContractNo",
+    },
+    {
+      label: "渚涘簲鍟嗗悕绉�",
+      prop: "supplierName",
+    },
+    {
+      label: "椤圭洰鍚嶇О",
+      prop: "projectName",
+    },
+    {
+      label: "鍚堝悓閲戦(鍏�)",
+      prop: "contractAmount",
+      formatData: (val) => {
+        return parseFloat(val).toFixed(2) ?? 0;
+      },
+    },
+    {
+      label: "宸插紑绁ㄩ噾棰�(鍏�)",
+      prop: "receiptPaymentAmount",
+      formatData: (val) => {
+        return parseFloat(val).toFixed(2) ?? 0;
+      },
+    },
+    {
+      label: "寰呭紑绁ㄩ噾棰�(鍏�)",
+      prop: "unReceiptPaymentAmount",
+      formatData: (val) => {
+        return parseFloat(val).toFixed(2) ?? 0;
+      },
+    },
+    // {
+    //   fixed: "right",
+    //   label: "鎿嶄綔",
+    //   dataType: "slot",
+    //   slot: "operation",
+    //   align: "center",
+    //   width: "200px",
+    // },
+  ]
+);
 
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref("");
-const dialogFormVisible = ref(false);
-const data = reactive({
-  searchForm: {
-    purchaseContractNumber: "",
-  },
-  form: {
-    issueDate: "", // 寮�绁ㄦ棩鏈�
-    purchaseLedgerId: "",
-    purchaseLedgerNo: "",
-    issUerId: "", // 寮�绁ㄤ汉id
-    issUer: "", // 寮�绁ㄤ汉濮撳悕
-    invoiceNumber: "", // 鍙戠エ鍙�
-    invoiceAmount: "", // 鍙戠エ閲戦
-    createTime: "", // 褰曞叆鏃ユ湡
-  },
-  rules: {
-    invoiceNumber: [
-      { required: true, message: "璇疯緭鍏ュ彂绁ㄥ彿", trigger: "blur" },
-      { type: "string" },
-    ],
-    invoiceAmount: [
-      { required: true, message: "璇疯緭鍏ュ彂绁ㄩ噾棰�", trigger: "blur" },
-    ],
-  },
-});
-const { searchForm, form, rules } = toRefs(data);
-// 浜у搧琛ㄥ崟寮规鏁版嵁
-const productFormVisible = ref(false);
-const productOperationType = ref("");
-const currentId = ref("");
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
-  page.current = 1;
-  getList();
-};
-const paginationChange = (obj) => {
-  page.current = obj.page;
-  page.size = obj.limit;
-  getList();
-};
-const getList = () => {
-  tableLoading.value = true;
-  gePurchaseListPage({ ...searchForm.value, ...page })
-    .then((res) => {
-      tableLoading.value = false;
-      tableData.value = res.records;
-      tableData.value.map((item) => {
-        item.children = [];
-      });
-      total.value = res.total;
-      expandedRowKeys.value = [];
-    })
-    .catch(() => {
-      tableLoading.value = false;
-    });
-};
-const formattedNumber = (row, column, cellValue) => {
-  return parseFloat(cellValue).toFixed(2);
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
   selectedRows.value = selection.filter(
     (item) => item.purchaseContractNumber !== undefined
   );
 };
-const productSelected = (selectedRows) => {
-  productSelectedRows.value = selectedRows;
-};
-const expandedRowKeys = ref([]);
-// 灞曞紑琛�
-const expandChange = (row, expandedRows) => {
-  if (expandedRows.length > 0) {
-    expandedRowKeys.value = [];
-    try {
-      productList({ salesLedgerId: row.id, type: 2 }).then((res) => {
-        const index = tableData.value.findIndex((item) => item.id === row.id);
-        if (index > -1) {
-          tableData.value[index].children = res;
-        }
-        expandedRowKeys.value.push(row.id);
-      });
-    } catch (error) {
-      console.log(error);
-    }
-  } else {
-    expandedRowKeys.value = [];
-  }
-};
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
-  return proxy.summarizeTable(
-    param,
-    ["contractAmount", "receiptPaymentAmount", "unReceiptPaymentAmount"],
-    {
-      ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
-      futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
-    }
-  );
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param) => {
-  return proxy.summarizeTable(
-    param,
-    [
-      "taxInclusiveUnitPrice",
-      "taxInclusiveTotalPrice",
-      "taxExclusiveTotalPrice",
-      "ticketsNum",
-      "ticketsAmount",
-      "futureTickets",
-      "futureTicketsAmount",
-    ],
-    {
-      ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
-      futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
-    }
-  );
-};
 
-const handleAdd = () => {
+const handleAdd = (type) => {
   if (selectedRows.value.length !== 1) {
     proxy.$modal.msgWarning("璇峰厛閫変腑涓�鏉℃暟鎹�");
     return;
   }
-  openForm("add", selectedRows.value[0]);
+  modalRef.value.open(type, selectedRows.value[0].id);
 };
 
-// 鎵撳紑寮规
-const openForm = (type, row) => {
-  invoiceNumBlur(row);
-  operationType.value = type;
-  form.value = {};
-  productData.value = [];
-  fileList.value = [];
-  form.value.issUerId = userStore.id;
-  form.value.issUer = userStore.name;
-  form.value.issueDate = getNowFormatDate();
-  userListNoPage().then((res) => {
-    userList.value = res.data;
-  });
-  // 鏂板鏃朵紶鍏ュ綋鍓嶈id骞舵煡璇㈤噰璐悎鍚屽彿
-  if (type === "add" && row && row.id) {
-    form.value.purchaseLedgerId = row.id;
-    getPurchaseNoById({ id: row.id }).then((res) => {
-      let result = res.data;
-      (purchaseLedgerList.value = result),
-        (form.value.purchaseLedgerNo = result.purchaseContractNumber);
-      form.value.invoiceAmount = result.invoiceAmount;
-      form.value.invoiceNumber = result.invoiceNumber;
-      setInfo(result.id);
-    });
-  } else {
-    getProduct().then((res) => {
-      purchaseLedgerList.value = res;
-    });
-  }
-  if (type === "edit") {
-    currentId.value = row.id;
-    getRegistrationById({ id: row.id }).then((res) => {
-      form.value = { ...res };
-      productData.value = form.value.productData;
-      if (form.value.salesLedgerFiles) {
-        fileList.value = form.value.salesLedgerFiles;
-      } else {
-        fileList.value = [];
-      }
-    });
-  }
-  dialogFormVisible.value = true;
-};
-// 閫夋嫨閲囪喘鍚堝悓鍙疯祴鍊�
-const setInfo = (value) => {
-  getInfo({ id: value }).then((res) => {
-    let result = res.data;
-    form.value.salesContractNo = result.salesContractNo;
-    form.value.projectName = result.projectName;
-    productData.value = result.productData;
-    form.value.supplierName = result.supplierName;
-  });
-};
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
-  proxy.$refs["formRef"].validate((valid) => {
-    if (valid) {
-      form.value.productData = proxy.HaveJson(productData.value);
-      addOrUpdateRegistration(form.value).then((res) => {
-        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-        closeDia();
-        getList();
-      });
-    }
-  });
-};
-// 鍏抽棴寮规
-const closeDia = () => {
-  proxy.resetForm("formRef");
-  dialogFormVisible.value = false;
-};
-// 瀵煎嚭
-const handleOut = () => {
-  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  })
-    .then(() => {
-      proxy.download("/purchase/registration/export", {}, "鏉ョエ鐧昏.xlsx");
-    })
-    .catch(() => {
-      proxy.$modal.msg("宸插彇娑�");
-    });
-};
-// 鍒犻櫎
-const handleDelete = () => {
-  let ids = [];
-  if (selectedRows.value.length > 0) {
-    ids = selectedRows.value.map((item) => item.id);
-  } else {
-    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
-    return;
-  }
-  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  })
-    .then(() => {
-      delRegistration(ids).then((res) => {
-        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-        getList();
-      });
-    })
-    .catch(() => {
-      proxy.$modal.msg("宸插彇娑�");
-    });
-};
-//鏈鏉ョエ鏁板け鐒︽搷浣�
-const invoiceNumBlur = (row) => {
-  if (!row.ticketsNum || row.ticketsNum === "") {
-    row.ticketsNum = 0;
-  }
-  if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
-    proxy.$modal.msgWarning("鏈寮�绁ㄦ暟涓嶅緱澶т簬鏈紑绁ㄦ暟");
-    row.ticketsNum = 0;
-    return;
-  }
-  // 璁$畻鏈鏉ョエ閲戦
-  row.ticketsAmount = row.ticketsNum * row.taxInclusiveUnitPrice;
-  // 璁$畻鏈潵绁ㄦ暟
-  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
-  // 璁$畻鏈潵绁ㄩ噾棰�
-  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
-  calculateinvoiceAmount();
-};
-// 鏈鏉ョエ閲戦澶辩劍鎿嶄綔
-const invoiceAmountBlur = (row) => {
-  if (!row.ticketsAmount) {
-    row.ticketsAmount = 0;
-  }
-  // 璁$畻鏄惁瓒呰繃鏉ョエ鎬婚噾棰�
-  if (row.ticketsAmount > row.tempFutureTicketsAmount) {
-    proxy.$modal.msgWarning("鏈鏉ョエ閲戦涓嶅緱澶т簬鏈潵绁ㄩ噾棰�");
-    row.ticketsAmount = 0;
-  }
-  // 璁$畻鏈鏉ョエ鏁�
-  row.ticketsNum = (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2);
-  // 璁$畻鏈潵绁ㄦ暟
-  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
-  // 璁$畻鏈潵绁ㄩ噾棰�
-  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
-  calculateinvoiceAmount();
+const handleEdit = (type, id) => {
+  modalRef.value.open(type, id);
 };
 
-// 鑾峰彇褰撳墠鏃ユ湡鍑芥暟
-function getNowFormatDate() {
-  let date = new Date(),
-    year = date.getFullYear(), //鑾峰彇瀹屾暣鐨勫勾浠�(4浣�)
-    month = date.getMonth() + 1, //鑾峰彇褰撳墠鏈堜唤(0-11,0浠h〃1鏈�)
-    strDate = date.getDate(); // 鑾峰彇褰撳墠鏃�(1-31)
-  if (month < 10) month = `0${month}`; // 濡傛灉鏈堜唤鏄釜浣嶆暟锛屽湪鍓嶉潰琛�0
-  if (strDate < 10) strDate = `0${strDate}`; // 濡傛灉鏃ユ槸涓綅鏁帮紝鍦ㄥ墠闈㈣ˉ0
-  return `${year}-${month}-${strDate}`;
-}
+const handleOut = () => {};
+const handleDelete = () => {};
 
-function calculateinvoiceAmount() {
-  console.log("productData", productData.value);
-  var invoiceAmountTotal = 0;
-  productData.value.forEach((item) => {
-    if (item.ticketsAmount) {
-      invoiceAmountTotal += item.ticketsAmount;
-    }
-  });
-  form.value.invoiceAmount = invoiceAmountTotal.toFixed(2);
-}
+const expandChange = async (row, expandedRows) => {
+  await nextTick();
+  expandTableRef.value.getList(row.id);
+};
 
-getList();
+onMounted(() => {
+  getTableData();
+});
 </script>
 
-<style scoped lang="scss"></style>
+<style lang="scss" scoped>
+.table_list {
+  margin-top: unset;
+}
+.actions {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+</style>
diff --git a/src/views/procurementManagement/invoiceEntry/indexOld.vue b/src/views/procurementManagement/invoiceEntry/indexOld.vue
new file mode 100644
index 0000000..60d5124
--- /dev/null
+++ b/src/views/procurementManagement/invoiceEntry/indexOld.vue
@@ -0,0 +1,725 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title">閲囪喘鍚堝悓鍙凤細</span>
+        <el-input
+          v-model="searchForm.purchaseContractNumber"
+          style="width: 240px"
+          placeholder="璇疯緭鍏�"
+          @change="handleQuery"
+          clearable
+          prefix-icon="Search"
+        />
+        <el-button
+          type="primary"
+          @click="handleQuery"
+          style="margin-left: 10px"
+        >
+          鎼滅储
+        </el-button>
+      </div>
+      <div>
+        <el-button type="primary" @click="handleAdd">鏂板鐧昏</el-button>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+      </div>
+    </div>
+    <div class="table_list">
+      <el-table
+        :data="tableData"
+        border
+        v-loading="tableLoading"
+        @selection-change="handleSelectionChange"
+        :expand-row-keys="expandedRowKeys"
+        :row-key="(row) => row.id"
+        show-summary
+        :summary-method="summarizeMainTable"
+        @expand-change="expandChange"
+        height="calc(100vh - 18.5em)"
+      >
+        <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="quantity" />
+              <el-table-column label="绋庣巼(%)" prop="taxRate" />
+              <el-table-column
+                label="鍚◣鍗曚环(鍏�)"
+                prop="taxInclusiveUnitPrice"
+                :formatter="formattedNumber"
+              />
+              <el-table-column
+                label="鍚◣鎬讳环(鍏�)"
+                prop="taxInclusiveTotalPrice"
+                :formatter="formattedNumber"
+              />
+              <el-table-column
+                label="涓嶅惈绋庢�讳环(鍏�)"
+                prop="taxExclusiveTotalPrice"
+                :formatter="formattedNumber"
+              />
+              <el-table-column label="鏈鏉ョエ鏁�" prop="ticketsNum" />
+              <el-table-column
+                label="鏈鏉ョエ閲戦(鍏�)"
+                prop="ticketsAmount"
+                :formatter="formattedNumber"
+              />
+              <el-table-column label="鏈潵绁ㄦ暟" prop="futureTickets" />
+              <el-table-column
+                label="鏈潵绁ㄩ噾棰�(鍏�)"
+                prop="futureTicketsAmount"
+                :formatter="formattedNumber"
+              />
+            </el-table>
+          </template>
+        </el-table-column>
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column
+          label="閲囪喘鍚堝悓鍙�"
+          prop="purchaseContractNumber"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="閿�鍞悎鍚屽彿"
+          prop="salesContractNo"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="渚涘簲鍟嗗悕绉�"
+          prop="supplierName"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="椤圭洰鍚嶇О"
+          prop="projectName"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍚堝悓閲戦(鍏�)"
+          prop="contractAmount"
+          show-overflow-tooltip
+          :formatter="formattedNumber"
+        />
+        <el-table-column
+          label="宸插紑绁ㄩ噾棰�(鍏�)"
+          prop="receiptPaymentAmount"
+          show-overflow-tooltip
+          :formatter="formattedNumber"
+        />
+        <el-table-column
+          label="寰呭紑绁ㄩ噾棰�(鍏�)"
+          prop="unReceiptPaymentAmount"
+          show-overflow-tooltip
+          :formatter="formattedNumber"
+        />
+        <el-table-column
+          fixed="right"
+          label="鎿嶄綔"
+          min-width="60"
+          align="center"
+        >
+          <template #default="scope">
+            <el-button
+              text
+              type="primary"
+              size="small"
+              @click="openForm('edit', scope.row)"
+            >
+              缂栬緫
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        layout="total, sizes, prev, pager, next, jumper"
+        :page="page.current"
+        :limit="page.size"
+        @pagination="paginationChange"
+      />
+    </div>
+    <el-dialog
+      v-model="dialogFormVisible"
+      :title="operationType === 'add' ? '鏂板鏉ョエ鐧昏' : '缂栬緫鏉ョエ鐧昏'"
+      width="80%"
+      @close="closeDia"
+    >
+      <el-form
+        :model="form"
+        label-width="140px"
+        label-position="top"
+        :rules="rules"
+        ref="formRef"
+      >
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="閲囪喘鍚堝悓鍙凤細" prop="purchaseLedgerNo">
+              <el-input v-model="form.purchaseLedgerNo" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
+              <el-input
+                v-model="form.salesContractNo"
+                placeholder="鑷姩濉厖"
+                clearable
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="渚涘簲鍟嗗悕绉帮細" prop="supplierName">
+              <el-input
+                v-model="form.supplierName"
+                placeholder="鑷姩濉厖"
+                clearable
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
+              <el-input
+                v-model="form.projectName"
+                placeholder="鑷姩濉厖"
+                clearable
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鍙戠エ鍙凤細" prop="invoiceNumber">
+              <el-input
+                v-model="form.invoiceNumber"
+                placeholder="璇疯緭鍏�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍙戠エ閲戦(鍏�)锛�" prop="invoiceAmount">
+              <el-input
+                type="number"
+                :step="0.01"
+                v-model="form.invoiceAmount"
+                placeholder="鑷姩濉厖"
+                clearable
+                :disabled="true"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="褰曞叆浜猴細" prop="issUer">
+              <el-input
+                v-model="form.issUer"
+                placeholder="璇疯緭鍏�"
+                clearable
+                disabled
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="寮�绁ㄦ棩鏈燂細" prop="issueDate">
+              <el-date-picker
+                style="width: 100%"
+                v-model="form.issueDate"
+                type="date"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="涓婁紶闄勪欢">
+              <FileUpload :showTip="false" accept="*" :autoUpload="true" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <!-- <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="褰曞叆鏃ユ湡锛�" prop="createTime">
+              <el-date-picker
+                style="width: 100%"
+                v-model="form.createTime"
+                type="date"
+                placeholder="璇烽�夋嫨"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row> -->
+        <el-row>
+          <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate"> </el-form-item>
+        </el-row>
+        <el-table
+          :data="productData"
+          border
+          @selection-change="productSelected"
+          show-summary
+          style="width: 100%"
+          :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" width="70" />
+          <el-table-column label="鏁伴噺" prop="quantity" width="70" />
+          <el-table-column label="绋庣巼(%)" prop="taxRate" width="80" />
+          <el-table-column label="褰曞叆鏃ユ湡" prop="createTime" width="120" />
+          <el-table-column
+            label="鍚◣鍗曚环(鍏�)"
+            width="150"
+            prop="taxInclusiveUnitPrice"
+            :formatter="formattedNumber"
+          />
+          <el-table-column
+            label="鍚◣鎬讳环(鍏�)"
+            width="150"
+            prop="taxInclusiveTotalPrice"
+            :formatter="formattedNumber"
+          />
+          <el-table-column
+            label="涓嶅惈绋庢�讳环(鍏�)"
+            width="150"
+            prop="taxExclusiveTotalPrice"
+            :formatter="formattedNumber"
+          />
+          <el-table-column label="鏈鏉ョエ鏁�" prop="ticketsNum" width="170">
+            <template #default="scope">
+              <el-input-number
+                v-model="scope.row.ticketsNum"
+                placeholder="璇烽�夋嫨"
+                :min="0"
+                :step="0.1"
+                clearable
+                style="width: 100%"
+                @change="invoiceNumBlur(scope.row)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="鏈鏉ョエ閲戦(鍏�)"
+            prop="ticketsAmount"
+            :min="0"
+            :step="0.1"
+            :formatter="formattedNumber"
+            width="170"
+          >
+            <template #default="scope">
+              <el-input-number
+                v-model="scope.row.ticketsAmount"
+                placeholder="璇烽�夋嫨"
+                :min="0"
+                :step="0.1"
+                clearable
+                style="width: 100%"
+                @change="invoiceAmountBlur(scope.row)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="鏈潵绁ㄦ暟"
+            prop="futureTickets"
+            :formatter="
+              (row) =>
+                row.futureTickets == null || row.futureTickets === ''
+                  ? row.quantity
+                  : row.futureTickets
+            "
+          >
+          </el-table-column>
+          <el-table-column
+            label="鏈潵绁ㄩ噾棰�(鍏�)"
+            prop="futureTicketsAmount"
+            :formatter="
+              (row) =>
+                row.futureTicketsAmount !== undefined &&
+                row.futureTicketsAmount !== null &&
+                row.futureTicketsAmount !== ''
+                  ? row.futureTicketsAmount
+                  : row.taxExclusiveTotalPrice
+            "
+          >
+          </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>
+  </div>
+</template>
+
+<script setup>
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { onMounted, ref } from "vue";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import { productList } from "@/api/procurementManagement/procurementLedger.js";
+import useUserStore from "@/store/modules/user";
+import FileUpload from "@/components/Upload/FileUpload.vue";
+
+const userStore = useUserStore();
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const productData = ref([]);
+const selectedRows = ref([]);
+const productSelectedRows = ref([]);
+const userList = ref([]);
+const purchaseLedgerList = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+  current: 1,
+  size: 100,
+});
+const total = ref(0);
+const fileList = ref([]);
+import {
+  addOrUpdateRegistration,
+  delRegistration,
+  gePurchaseListPage,
+  getInfo,
+  getProduct,
+  getPurchaseNoById,
+  getRegistrationById,
+} from "@/api/procurementManagement/invoiceEntry.js";
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+  searchForm: {
+    purchaseContractNumber: "",
+  },
+  form: {
+    issueDate: "", // 寮�绁ㄦ棩鏈�
+    purchaseLedgerId: "",
+    purchaseLedgerNo: "",
+    issUerId: "", // 寮�绁ㄤ汉id
+    issUer: "", // 寮�绁ㄤ汉濮撳悕
+    invoiceNumber: "", // 鍙戠エ鍙�
+    invoiceAmount: "", // 鍙戠エ閲戦
+    createTime: "", // 褰曞叆鏃ユ湡
+  },
+  rules: {
+    invoiceNumber: [
+      { required: true, message: "璇疯緭鍏ュ彂绁ㄥ彿", trigger: "blur" },
+      { type: "string" },
+    ],
+    invoiceAmount: [
+      { required: true, message: "璇疯緭鍏ュ彂绁ㄩ噾棰�", trigger: "blur" },
+    ],
+  },
+});
+const { searchForm, form, rules } = toRefs(data);
+// 浜у搧琛ㄥ崟寮规鏁版嵁
+const productFormVisible = ref(false);
+const productOperationType = ref("");
+const currentId = ref("");
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+const paginationChange = (obj) => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+const getList = () => {
+  tableLoading.value = true;
+  gePurchaseListPage({ ...searchForm.value, ...page })
+    .then((res) => {
+      tableLoading.value = false;
+      tableData.value = res.records;
+      tableData.value.map((item) => {
+        item.children = [];
+      });
+      total.value = res.total;
+      expandedRowKeys.value = [];
+    })
+    .catch(() => {
+      tableLoading.value = false;
+    });
+};
+const formattedNumber = (row, column, cellValue) => {
+  return parseFloat(cellValue).toFixed(2) ?? 0;
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection.filter(
+    (item) => item.purchaseContractNumber !== undefined
+  );
+};
+const productSelected = (selectedRows) => {
+  productSelectedRows.value = selectedRows;
+};
+const expandedRowKeys = ref([]);
+// 灞曞紑琛�
+const expandChange = (row, expandedRows) => {
+  if (expandedRows.length > 0) {
+    expandedRowKeys.value = [];
+    try {
+      productList({ salesLedgerId: row.id, type: 2 }).then((res) => {
+        const index = tableData.value.findIndex((item) => item.id === row.id);
+        if (index > -1) {
+          tableData.value[index].children = res;
+        }
+        expandedRowKeys.value.push(row.id);
+      });
+    } catch (error) {
+      console.log(error);
+    }
+  } else {
+    expandedRowKeys.value = [];
+  }
+};
+// 涓昏〃鍚堣鏂规硶
+const summarizeMainTable = (param) => {
+  return proxy.summarizeTable(
+    param,
+    ["contractAmount", "receiptPaymentAmount", "unReceiptPaymentAmount"],
+    {
+      ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+      futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+    }
+  );
+};
+// 瀛愯〃鍚堣鏂规硶
+const summarizeChildrenTable = (param) => {
+  return proxy.summarizeTable(
+    param,
+    [
+      "taxInclusiveUnitPrice",
+      "taxInclusiveTotalPrice",
+      "taxExclusiveTotalPrice",
+      "ticketsNum",
+      "ticketsAmount",
+      "futureTickets",
+      "futureTicketsAmount",
+    ],
+    {
+      ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+      futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+    }
+  );
+};
+
+const handleAdd = () => {
+  if (selectedRows.value.length !== 1) {
+    proxy.$modal.msgWarning("璇峰厛閫変腑涓�鏉℃暟鎹�");
+    return;
+  }
+  openForm("add", selectedRows.value[0]);
+};
+
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+  invoiceNumBlur(row);
+  operationType.value = type;
+  form.value = {};
+  productData.value = [];
+  fileList.value = [];
+  form.value.issUerId = userStore.id;
+  form.value.issUer = userStore.name;
+  form.value.issueDate = getNowFormatDate();
+  userListNoPage().then((res) => {
+    userList.value = res.data;
+  });
+  // 鏂板鏃朵紶鍏ュ綋鍓嶈id骞舵煡璇㈤噰璐悎鍚屽彿
+  if (type === "add" && row && row.id) {
+    form.value.purchaseLedgerId = row.id;
+    getPurchaseNoById({ id: row.id }).then((res) => {
+      let result = res.data;
+      purchaseLedgerList.value = result;
+      form.value.purchaseLedgerNo = result.purchaseContractNumber;
+      form.value.invoiceAmount = result.invoiceAmount;
+      form.value.invoiceNumber = result.invoiceNumber;
+      setInfo(result.id);
+    });
+  } else {
+    getProduct().then((res) => {
+      purchaseLedgerList.value = res;
+    });
+  }
+  if (type === "edit") {
+    currentId.value = row.id;
+    getRegistrationById({ id: row.id }).then((res) => {
+      const { code, data } = res;
+      if (code == 200) {
+        form.value.invoiceAmount = data.invoiceAmount;
+        productData.value = data.productData;
+        if (data.salesLedgerFiles) {
+          fileList.value = data.salesLedgerFiles;
+        } else {
+          fileList.value = [];
+        }
+      }
+    });
+  }
+  dialogFormVisible.value = true;
+};
+// 閫夋嫨閲囪喘鍚堝悓鍙疯祴鍊�
+const setInfo = (value) => {
+  getInfo({ id: value }).then((res) => {
+    let result = res.data;
+    form.value.salesContractNo = result.salesContractNo;
+    form.value.projectName = result.projectName;
+    productData.value = result.productData;
+    form.value.supplierName = result.supplierName;
+  });
+};
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+  proxy.$refs["formRef"].validate((valid) => {
+    if (valid) {
+      form.value.productData = proxy.HaveJson(productData.value);
+      addOrUpdateRegistration(form.value).then((res) => {
+        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+        closeDia();
+        getList();
+      });
+    }
+  });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+  proxy.resetForm("formRef");
+  dialogFormVisible.value = false;
+};
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download("/purchase/registration/export", {}, "鏉ョエ鐧昏.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+// 鍒犻櫎
+const handleDelete = () => {
+  let ids = [];
+  if (selectedRows.value.length > 0) {
+    ids = selectedRows.value.map((item) => item.id);
+  } else {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      delRegistration(ids).then((res) => {
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        getList();
+      });
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+//鏈鏉ョエ鏁板け鐒︽搷浣�
+const invoiceNumBlur = (row) => {
+  if (!row.ticketsNum || row.ticketsNum === "") {
+    row.ticketsNum = 0;
+  }
+  if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
+    proxy.$modal.msgWarning("鏈寮�绁ㄦ暟涓嶅緱澶т簬鏈紑绁ㄦ暟");
+    row.ticketsNum = 0;
+    return;
+  }
+  // 璁$畻鏈鏉ョエ閲戦
+  row.ticketsAmount = row.ticketsNum * row.taxInclusiveUnitPrice;
+  // 璁$畻鏈潵绁ㄦ暟
+  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
+  // 璁$畻鏈潵绁ㄩ噾棰�
+  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
+  calculateinvoiceAmount();
+};
+// 鏈鏉ョエ閲戦澶辩劍鎿嶄綔
+const invoiceAmountBlur = (row) => {
+  if (!row.ticketsAmount) {
+    row.ticketsAmount = 0;
+  }
+  // 璁$畻鏄惁瓒呰繃鏉ョエ鎬婚噾棰�
+  if (row.ticketsAmount > row.tempFutureTicketsAmount) {
+    proxy.$modal.msgWarning("鏈鏉ョエ閲戦涓嶅緱澶т簬鏈潵绁ㄩ噾棰�");
+    row.ticketsAmount = 0;
+  }
+  // 璁$畻鏈鏉ョエ鏁�
+  row.ticketsNum = (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2);
+  // 璁$畻鏈潵绁ㄦ暟
+  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
+  // 璁$畻鏈潵绁ㄩ噾棰�
+  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
+  calculateinvoiceAmount();
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡鍑芥暟
+function getNowFormatDate() {
+  let date = new Date(),
+    year = date.getFullYear(), //鑾峰彇瀹屾暣鐨勫勾浠�(4浣�)
+    month = date.getMonth() + 1, //鑾峰彇褰撳墠鏈堜唤(0-11,0浠h〃1鏈�)
+    strDate = date.getDate(); // 鑾峰彇褰撳墠鏃�(1-31)
+  if (month < 10) month = `0${month}`; // 濡傛灉鏈堜唤鏄釜浣嶆暟锛屽湪鍓嶉潰琛�0
+  if (strDate < 10) strDate = `0${strDate}`; // 濡傛灉鏃ユ槸涓綅鏁帮紝鍦ㄥ墠闈㈣ˉ0
+  return `${year}-${month}-${strDate}`;
+}
+
+function calculateinvoiceAmount() {
+  console.log("productData", productData.value);
+  var invoiceAmountTotal = 0;
+  productData.value.forEach((item) => {
+    if (item.ticketsAmount) {
+      invoiceAmountTotal += item.ticketsAmount;
+    }
+  });
+  form.value.invoiceAmount = invoiceAmountTotal.toFixed(2);
+}
+
+onMounted(() => {
+  getList();
+});
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/procurementManagement/paymentEntry/index.vue b/src/views/procurementManagement/paymentEntry/index.vue
index 59faa6d..3dc9bb7 100644
--- a/src/views/procurementManagement/paymentEntry/index.vue
+++ b/src/views/procurementManagement/paymentEntry/index.vue
@@ -62,13 +62,14 @@
     </div>
     <div class="table_list">
       <PIMTable
+        rowKey="id"
         :column="tableColumn"
         :tableData="tableData"
         :page="page"
         :isSelection="true"
         :isShowSummary="isShowSummarySon"
         :summaryMethod="summarizeMainTable1"
-        :handleSelectionChange="handleSelectionChange"
+        @selection-change="handleSelectionChange"
         :tableLoading="tableLoading"
         @pagination="pagination"
         :total="total"
diff --git a/src/views/procurementManagement/paymentHistory/index.vue b/src/views/procurementManagement/paymentHistory/index.vue
index aa64726..58e5f92 100644
--- a/src/views/procurementManagement/paymentHistory/index.vue
+++ b/src/views/procurementManagement/paymentHistory/index.vue
@@ -36,13 +36,14 @@
     </el-form>
     <div class="table_list">
       <PIMTable
+        rowKey="id"
         :column="tableColumn"
         :tableData="tableData"
         :page="page"
         :isSelection="true"
         :isShowSummary="isShowSummarySon"
         :summaryMethod="summarizeMainTable1"
-        :handleSelectionChange="handleSelectionChange"
+        @selection-change="handleSelectionChange"
         :tableLoading="tableLoading"
         @pagination="pagination"
         :total="total"
diff --git a/src/views/procurementManagement/paymentLedger/index.vue b/src/views/procurementManagement/paymentLedger/index.vue
index 69a0947..665242c 100644
--- a/src/views/procurementManagement/paymentLedger/index.vue
+++ b/src/views/procurementManagement/paymentLedger/index.vue
@@ -79,6 +79,7 @@
       <el-col :span="10">
         <div class="table_list">
           <PIMTable
+            rowKey="id"
             :column="tableColumnSon"
             :tableData="originalTableDataSon"
             :isSelection="false"
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/index.vue b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
index c0e11d6..d161978 100644
--- a/src/views/procurementManagement/procurementInvoiceLedger/index.vue
+++ b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
@@ -42,23 +42,22 @@
     </el-form>
     <div class="table_list">
       <PIMTable
+        rowKey="id"
         :column="columns"
         :tableLoading="loading"
         :tableData="dataList"
         :isSelection="true"
+        height="calc(100vh - 18.5em)"
+        :isShowSummary="true"
+        :summaryMethod="summarizeMainTable"
         :page="{
           current: pagination.currentPage,
           size: pagination.pageSize,
           total: pagination.total,
         }"
-        :handleSelectionChange="handleSelectionChange"
+        @selection-change="handleSelectionChange"
         @pagination="onCurrentChange"
       >
-        <!-- <template #operation>
-          <el-button type="primary" text @click="handleEdit" size="small">
-            缂栬緫
-          </el-button>
-        </template> -->
       </PIMTable>
     </div>
   </div>
@@ -177,6 +176,23 @@
   }
 );
 
+// 涓昏〃鍚堣鏂规硶
+const summarizeMainTable = (param) => {
+  return proxy.summarizeTable(
+    param,
+    [
+      "taxInclusiveTotalPrice",
+      "ticketsAmount",
+      "unTicketsPrice",
+      "invoiceAmount",
+    ],
+    {
+      ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+      futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+    }
+  );
+};
+
 const handleSelectionChange = (val) => {
   multipleVal.value = val;
 };
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 1086c81..5ac4a96 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -646,11 +646,11 @@
   purchaseListPage({ ...searchForm.value, ...page })
     .then((res) => {
       tableLoading.value = false;
-      tableData.value = res.records;
+      tableData.value = res.data.records;
       tableData.value.map((item) => {
         item.children = [];
       });
-      total.value = res.total;
+      total.value = res.data.total;
       expandedRowKeys.value = [];
     })
     .catch(() => {
diff --git a/src/views/procurementManagement/thePaymentLedger/index.vue b/src/views/procurementManagement/thePaymentLedger/index.vue
index 38fac3a..5fa9e6f 100644
--- a/src/views/procurementManagement/thePaymentLedger/index.vue
+++ b/src/views/procurementManagement/thePaymentLedger/index.vue
@@ -4,93 +4,98 @@
       <div>
         <span class="search_title">渚涘簲鍟嗗悕绉�/鍚堝悓鍙凤細</span>
         <el-input
-            v-model="searchForm.supplierNameOrContractNo"
-            style="width: 240px"
-            placeholder="杈撳叆渚涘簲鍟嗗悕绉�/鍚堝悓鍙锋悳绱�"
-            @change="handleQuery"
-            clearable
-            :prefix-icon="Search"
+          v-model="searchForm.supplierNameOrContractNo"
+          style="width: 240px"
+          placeholder="杈撳叆渚涘簲鍟嗗悕绉�/鍚堝悓鍙锋悳绱�"
+          @change="handleQuery"
+          clearable
+          :prefix-icon="Search"
         />
-        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button>
+        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+          >鎼滅储</el-button
+        >
       </div>
     </div>
     <div class="table_list">
-      <PIMTable :column="tableColumn" :tableData="tableData" :page="page"
-                :tableLoading="tableLoading" @pagination="pagination" :total="total"></PIMTable>
+      <PIMTable
+        rowKey="id"
+        :column="tableColumn"
+        :tableData="tableData"
+        :page="page"
+        :tableLoading="tableLoading"
+        @pagination="pagination"
+        :total="total"
+      ></PIMTable>
     </div>
   </div>
 </template>
 
 <script setup>
-import { ref } from 'vue'
-import {Search} from "@element-plus/icons-vue";
-import {
-  registrationList,
-} from "@/api/procurementManagement/paymentEntry.js";
+import { ref } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { registrationList } from "@/api/procurementManagement/paymentEntry.js";
 const tableColumn = ref([
   {
-    label: '浠樻鏃ユ湡',
-    prop: 'paymentDate',
+    label: "浠樻鏃ユ湡",
+    prop: "paymentDate",
   },
   {
-    label: '渚涘簲鍟嗗悕绉�',
-    prop: 'supplierName',
+    label: "渚涘簲鍟嗗悕绉�",
+    prop: "supplierName",
   },
   {
-    label: '浠樻閲戦',
-    prop: 'currentPaymentAmount',
+    label: "浠樻閲戦",
+    prop: "currentPaymentAmount",
   },
   {
-    label: '鐧昏浜�',
-    prop: 'registrant'
+    label: "鐧昏浜�",
+    prop: "registrant",
   },
   {
-    label: '鐧昏鏃ユ湡',
-    prop: 'registrationtDate'
+    label: "鐧昏鏃ユ湡",
+    prop: "registrationtDate",
   },
-])
-const tableData = ref([])
-const tableLoading = ref(false)
-const purchaseLedgerList = ref([])
-const invoiceNumberList = ref([])
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+const purchaseLedgerList = ref([]);
+const invoiceNumberList = ref([]);
 const page = reactive({
   current: 1,
   size: 10,
-})
-const total = ref(0)
+});
+const total = ref(0);
 
 // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref('')
-const dialogFormVisible = ref(false)
+const operationType = ref("");
+const dialogFormVisible = ref(false);
 const data = reactive({
   searchForm: {
-    supplierNameOrContractNo: '',
+    supplierNameOrContractNo: "",
   },
-})
-const { searchForm, form, rules } = toRefs(data)
+});
+const { searchForm, form, rules } = toRefs(data);
 
 // 鏌ヨ鍒楄〃
 /** 鎼滅储鎸夐挳鎿嶄綔 */
 const handleQuery = () => {
-  page.current = 1
-  getList()
-}
+  page.current = 1;
+  getList();
+};
 const pagination = ({ current, limit }) => {
   page.current = current;
   page.size = limit;
-  getList()
-}
+  getList();
+};
 const getList = () => {
-  tableLoading.value = true
-  registrationList({...searchForm.value, ...page}).then(res => {
-    tableLoading.value = false
-    tableData.value = res.rows
-    total.value = res.total
-  })
-}
-getList()
+  tableLoading.value = true;
+  registrationList({ ...searchForm.value, ...page }).then((res) => {
+    tableLoading.value = false;
+    tableData.value = res.rows;
+    total.value = res.total;
+  });
+};
+getList();
 </script>
 
-<style scoped lang="scss">
-
-</style>
+<style scoped lang="scss"></style>
diff --git a/src/views/reportAnalysis/projectProfit/index.vue b/src/views/reportAnalysis/projectProfit/index.vue
index 82031bb..bae35bb 100644
--- a/src/views/reportAnalysis/projectProfit/index.vue
+++ b/src/views/reportAnalysis/projectProfit/index.vue
@@ -11,6 +11,7 @@
     </el-form>
     <div class="table_list">
       <PIMTable
+        rowKey="id"
         :column="columns"
         :tableLoading="loading"
         :tableData="dataList"
diff --git a/src/views/reportAnalysis/taxComparison/index.vue b/src/views/reportAnalysis/taxComparison/index.vue
index fc4c929..b04ebce 100644
--- a/src/views/reportAnalysis/taxComparison/index.vue
+++ b/src/views/reportAnalysis/taxComparison/index.vue
@@ -20,6 +20,7 @@
     </el-form>
     <div class="table_list">
       <PIMTable
+        rowKey="id"
         :column="columns"
         :tableData="dataList"
         :page="{
diff --git a/src/views/salesManagement/receiptPaymentHistory/index.vue b/src/views/salesManagement/receiptPaymentHistory/index.vue
index 9e7ad7d..7dd8f18 100644
--- a/src/views/salesManagement/receiptPaymentHistory/index.vue
+++ b/src/views/salesManagement/receiptPaymentHistory/index.vue
@@ -48,16 +48,17 @@
     </el-form>
     <div class="table_list">
       <PIMTable
+        rowKey="id"
         :column="tableColumn"
         :tableData="tableData"
         :page="page"
         :isSelection="true"
         :isShowSummary="isShowSummarySon"
         :summaryMethod="summarizeMainTable1"
-        :handleSelectionChange="handleSelectionChange"
         :tableLoading="tableLoading"
-        @pagination="pagination"
         :total="total"
+        @pagination="pagination"
+        @selection-change="handleSelectionChange"
       ></PIMTable>
     </div>
   </div>

--
Gitblit v1.9.3