From 8a3bfdab689684fe5ee19b2f69842e450fc7c60a Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期五, 30 一月 2026 14:02:39 +0800
Subject: [PATCH] fix: 完成生产数据分析页面

---
 src/views/procurementManagement/procurementInvoiceLedger/index.vue |  615 ++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 381 insertions(+), 234 deletions(-)

diff --git a/src/views/procurementManagement/procurementInvoiceLedger/index.vue b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
index 6ae4766..00ae65a 100644
--- a/src/views/procurementManagement/procurementInvoiceLedger/index.vue
+++ b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
@@ -1,274 +1,261 @@
 <template>
   <div class="app-container">
-    <div class="search_form">
-      <div>
-        <span class="search_title">閲囪喘鍚堝悓鍙凤細</span>
+    <el-form :model="filters" :inline="true">
+      <el-form-item label="閲囪喘鍚堝悓鍙�">
         <el-input
-          v-model="searchForm.purchaseContractNumber"
+          v-model="filters.purchaseContractNumber"
           style="width: 240px"
           placeholder="璇疯緭鍏�"
-          @change="handleQuery"
           clearable
           :prefix-icon="Search"
+          @change="getTableData"
         />
-        <span class="search_title" style="margin-left: 10px">渚涘簲鍟嗭細</span>
+      </el-form-item>
+      <el-form-item label="渚涘簲鍟�">
         <el-input
-          v-model="searchForm.supplierName"
+          v-model="filters.supplierName"
           style="width: 240px"
           placeholder="璇疯緭鍏�"
-          @change="handleQuery"
           clearable
           :prefix-icon="Search"
+          @change="getTableData"
         />
-        <span class="search_title" style="margin-left: 10px">鏉ョエ鏃ユ湡锛�</span>
+      </el-form-item>
+      <el-form-item label="鏉ョエ鏃ユ湡">
         <el-date-picker
           style="width: 240px"
-          v-model="searchForm.issueDate"
+          v-model="filters.createdAt"
           value-format="YYYY-MM-DD"
           format="YYYY-MM-DD"
           type="daterange"
           start-placeholder="寮�濮嬫椂闂�"
           end-placeholder="缁撴潫鏃堕棿"
           clearable
-          @change="changeDateRange"
-          @clear="clearRange"
+          @change="getTableData"
         />
-        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
-          >鎼滅储</el-button
-        >
-      </div>
-      <div>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+        <el-button @click="resetFilters"> 閲嶇疆 </el-button>
         <el-button @click="handleOut">瀵煎嚭</el-button>
-      </div>
-    </div>
+      </el-form-item>
+    </el-form>
     <div class="table_list">
-      <el-table
-        :data="tableData"
-        border
-        v-loading="tableLoading"
-        :expand-row-keys="expandedRowKeys"
-        :row-key="(row) => row.id"
-        show-summary
-        :summary-method="summarizeMainTable"
-        @expand-change="expandChange"
-        height="calc(100vh - 18.5em)"
+      <PIMTable
+        rowKey="id"
+        :column="columns"
+        :tableLoading="loading"
+        :tableData="dataList"
+        :isSelection="true"
+        height="calc(100vh - 19.5em)"
+        :isShowSummary="true"
+        :summaryMethod="summarizeMainTable"
+        :page="{
+          current: pagination.currentPage,
+          size: pagination.pageSize,
+          total: pagination.total,
+        }"
+        @selection-change="handleSelectionChange"
+        @pagination="changePage"
       >
-        <el-table-column align="center" label="搴忓彿" type="index" 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
-          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="invoiceNumber"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="鍚堝悓閲戦(鍏�)"
-          prop="invoiceAmount"
-          show-overflow-tooltip
-          :formatter="formattedNumber"
-        />
-        <el-table-column label="寮�绁ㄤ汉" prop="issUer" show-overflow-tooltip />
-        <el-table-column
-          label="寮�绁ㄦ棩鏈�"
-          prop="issueDate"
-          show-overflow-tooltip
-        />
-      </el-table>
-      <pagination
-        v-show="total > 0"
-        :total="total"
-        layout="total, sizes, prev, pager, next, jumper"
-        :page="page.current"
-        :limit="page.size"
-        @pagination="paginationChange"
-      />
+        <template #operation="{ row }">
+          <el-button
+            type="primary"
+            link
+            @click="openEdit(row)"
+          >
+            缂栬緫
+          </el-button>
+          <el-button
+            type="primary"
+            link
+            @click="downLoadFile(row)"
+          >
+            闄勪欢
+          </el-button>
+          <el-button
+            type="primary"
+            link
+            @click="handleDelete(row)"
+          >
+            鍒犻櫎
+          </el-button>
+        </template>
+      </PIMTable>
     </div>
+    <FileListDialog 
+      ref="fileListRef" 
+      v-model="fileListDialogVisible"
+      title="闄勪欢鍒楄〃"
+      :showUploadButton="true"
+      :showDeleteButton="true"
+      :deleteMethod="handleDeleteFile"
+      :uploadMethod="handleFileUpload"
+      :rulesRegulationsManagementId="currentRowId"
+    />
+    <EditModal ref="editmodalRef" @success="getTableData"></EditModal>
   </div>
 </template>
 
 <script setup>
-import pagination from "@/components/PIMTable/Pagination.vue";
-import { ref } from "vue";
-import { Search } from "@element-plus/icons-vue";
+import { ref, getCurrentInstance } from "vue";
+import { usePaginationApi } from "@/hooks/usePaginationApi";
+import {
+	Search,
+} from "@element-plus/icons-vue";
+import {
+	delRegistration,
+	productRecordPage,
+	delCommonFile,
+} from "@/api/procurementManagement/procurementInvoiceLedger.js";
+import request from "@/utils/request";
+import { getToken } from "@/utils/auth";
+import { onMounted } from "vue";
 import { ElMessageBox } from "element-plus";
-import { productRecordList } from "@/api/procurementManagement/procurementInvoiceLedger.js";
-import { invoiceListPage } from "@/api/procurementManagement/procurementInvoiceLedger.js";
-import dayjs from "dayjs";
+import EditModal from "./Modal/EditModal.vue";
+import FileListDialog from '@/components/Dialog/FileListDialog.vue';
+import useUserStore from "@/store/modules/user.js";
+const userStore = useUserStore();
+
+defineOptions({
+  name: "鏉ョエ鍙拌处",
+});
+
+const editmodalRef = ref();
+const fileListRef = ref(null);
+const fileListDialogVisible = ref(false);
+const currentRowId = ref(null); // 褰撳墠鏌ョ湅闄勪欢鐨勮ID
 
 const { proxy } = getCurrentInstance();
-const tableData = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
-  current: 1,
-  size: 100,
-});
-const total = ref(0);
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const data = reactive({
-  searchForm: {
-    purchaseContractNumber: "",
-    supplierName: "",
-    issueDate: [
-      dayjs().startOf("month").format("YYYY-MM-DD"),
-      dayjs().endOf("month").format("YYYY-MM-DD"),
-    ],
-    issueDateStart: dayjs().startOf("month").format("YYYY-MM-DD"),
-    issueDateEnd: dayjs().endOf("month").format("YYYY-MM-DD"),
+const multipleVal = ref([]);
+const {
+  loading,
+  filters,
+  columns,
+  dataList,
+  pagination,
+  getTableData,
+  resetFilters,
+  onCurrentChange,
+} = usePaginationApi(
+  productRecordPage,
+  {
+    purchaseContractNumber: undefined, // 閲囪喘鍚堝悓鍙�
+    supplierName: undefined, // 渚涘簲鍟�
+    createdAt: [], // 鏉ョエ鏃ユ湡
   },
-  form: {
-    issueDate: "", // 寮�绁ㄦ棩鏈�
-    purchaseLedgerId: "",
-    purchaseLedgerNo: "",
-    issUerId: "", // 寮�绁ㄤ汉id
-    issUer: "", // 寮�绁ㄤ汉濮撳悕
-  },
-  rules: {
-    purchaseLedgerId: [
-      { required: true, message: "璇烽�夋嫨", trigger: "change" },
-    ],
-  },
-});
-const { searchForm } = toRefs(data);
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
-  page.current = 1;
-  getList();
-};
-const paginationChange = (obj) => {
-  page.current = obj.page;
-  page.size = obj.limit;
-  getList();
-};
-const getList = () => {
-  tableLoading.value = true;
-  const { issueDate, ...rest } = searchForm.value;
-  invoiceListPage({ ...rest, ...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 expandedRowKeys = ref([]);
-// 灞曞紑琛�
-const expandChange = (row, expandedRows) => {
-  if (expandedRows.length > 0) {
-    expandedRowKeys.value = [];
-    try {
-      productRecordList({ id: row.id }).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 = [];
+  [
+    {
+      label: "閲囪喘鍚堝悓鍙�",
+      prop: "purchaseContractNumber",
+      width: 150,
+    },
+    {
+      label: "閿�鍞悎鍚屽彿",
+      prop: "salesContractNo",
+      width: 150,
+    },
+    {
+      label: "椤圭洰鍚嶇О",
+      prop: "projectName",
+      width: 240,
+    },
+    {
+      label: "渚涘簲鍟嗗悕绉�",
+      prop: "supplierName",
+      width: 240,
+    },
+    {
+      label: "浜у搧澶х被",
+      prop: "productCategory",
+      width: 150,
+    },
+    {
+      label: "瑙勬牸鍨嬪彿",
+      prop: "specificationModel",
+      width: 150,
+    },
+    {
+      label: "鍙戠エ鍙�",
+      prop: "invoiceNumber",
+      width: 200,
+    },
+    {
+      label: "鍚堝悓閲戦(鍏�)",
+      prop: "taxInclusiveTotalPrice",
+      width: 200,
+      formatData: (cell) => {
+        return cell ? parseFloat(cell).toFixed(2) : 0;
+      },
+    },
+    {
+      label: "寮�绁ㄦ棩鏈�",
+      prop: "createdAt",
+      width: 110,
+    },
+    {
+      label: "寮�绁ㄩ噾棰�",
+      prop: "ticketsAmount",
+      width: 200,
+      formatData: (cell) => {
+        return cell ? parseFloat(cell).toFixed(2) : 0;
+      },
+    },
+    {
+      label: "涓嶅惈绋庨噾棰�",
+      prop: "unTicketsPrice",
+      width: 200,
+      formatData: (cell) => {
+        return cell ? parseFloat(cell).toFixed(2) : 0;
+      },
+    },
+    {
+      label: "澧炲�肩◣",
+      prop: "invoiceAmount",
+      width: 200,
+    },
+    {
+      label: "褰曞叆浜�",
+      prop: "issUer",
+      width: 200,
+    },
+    {
+      fixed: "right",
+      width: 200,
+      label: "鎿嶄綔",
+      dataType: "slot",
+      slot: "operation",
+      align: "center",
+    },
+  ],
+  {},
+  {
+    createdAt: (aim) => ({
+      createdAtStart: aim ? aim[0] : undefined,
+      createdAtEnd: aim ? aim[1] : undefined,
+    }),
   }
-};
+);
+
 // 涓昏〃鍚堣鏂规硶
 const summarizeMainTable = (param) => {
-  return proxy.summarizeTable(param, ["invoiceAmount"], {
-    ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
-    futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
-  });
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param) => {
   return proxy.summarizeTable(
     param,
     [
-      "taxInclusiveUnitPrice",
       "taxInclusiveTotalPrice",
-      "taxExclusiveTotalPrice",
-      "ticketsNum",
       "ticketsAmount",
-      "futureTickets",
-      "futureTicketsAmount",
+      "unTicketsPrice",
+      "invoiceAmount",
     ],
     {
       ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
       futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
     }
   );
+};
+
+const handleSelectionChange = (val) => {
+  multipleVal.value = val;
 };
 
 // 瀵煎嚭
@@ -286,24 +273,184 @@
     });
 };
 
-const changeDateRange = (date) => {
-  if (date) {
-    searchForm.receiptPaymentDateStart = date[0];
-    searchForm.receiptPaymentDateEnd = date[1];
-    getList();
+const changePage = ({ page, limit }) => {
+  pagination.currentPage = page;
+	pagination.pageSize = limit;
+  onCurrentChange(page);
+};
+
+const downLoadFile = row => {
+  currentRowId.value = row.id;
+  if (fileListRef.value) {
+    fileListRef.value.open(row.commonFiles || []);
   }
 };
 
-const clearRange = () => {
-  searchForm.value.issueDate = [];
-  searchForm.value.issueDateStart = undefined;
-  searchForm.value.issueDateEnd = undefined;
-  getList();
+// 涓婁紶闄勪欢锛堣嚜瀹氫箟涓婁紶鏂规硶锛�
+const handleFileUpload = async () => {
+  if (!currentRowId.value) {
+    proxy.$modal.msgWarning("缂哄皯鐧昏ID锛屾棤娉曚繚瀛橀檮浠�");
+    return;
+  }
+  
+  return new Promise((resolve) => {
+    // 鍒涘缓涓�涓殣钘忕殑鏂囦欢杈撳叆鍏冪礌
+    const input = document.createElement('input');
+    input.type = 'file';
+    input.style.display = 'none';
+    input.onchange = async (e) => {
+      const file = e.target.files[0];
+      if (!file) {
+        resolve(null);
+        return;
+      }
+      
+      try {
+        // 浣跨敤 FormData 涓婁紶鏂囦欢
+        const formData = new FormData();
+        formData.append('file', file);
+        formData.append('type', '4'); // type 鍙傛暟锛岀敤鎴锋湭鎸囧畾鍏蜂綋鍊硷紝鍏堜紶绌哄瓧绗︿覆
+        formData.append('id', currentRowId.value); // 褰撳墠琛岀殑 id
+        
+        const uploadRes = await request({
+          url: '/file/uploadByCommon',
+          method: 'post',
+          data: formData,
+          headers: {
+            'Content-Type': 'multipart/form-data',
+            Authorization: `Bearer ${getToken()}`
+          }
+        });
+        
+        if (uploadRes.code === 200) {
+          proxy.$modal.msgSuccess("闄勪欢涓婁紶鎴愬姛");
+          
+          // 鍒锋柊鍒楄〃鑾峰彇鏈�鏂版暟鎹�
+          await new Promise((resolveRefresh) => {
+            // 璋冪敤 API 鑾峰彇鏈�鏂板垪琛ㄦ暟鎹�
+            productRecordPage({
+              ...filters,
+              current: pagination.currentPage,
+              size: pagination.pageSize
+            }).then(({ code, data }) => {
+              if (code === 200) {
+                // 鏇存柊鏁版嵁鍒楄〃
+                dataList.value = data.records;
+                pagination.total = data.total;
+                
+                // 浠庡閮ㄦ暟鎹幏鍙� commonFiles
+                const currentRow = dataList.value.find(row => row.id === currentRowId.value);
+                if (currentRow && fileListRef.value) {
+                  // 鍒锋柊闄勪欢鍒楄〃锛屼娇鐢ㄤ粠澶栭儴鑾峰彇鐨勬渶鏂� commonFiles
+                  fileListRef.value.open(currentRow.commonFiles || []);
+                }
+                resolveRefresh();
+              } else {
+                resolveRefresh();
+              }
+            }).catch(() => {
+              resolveRefresh();
+            });
+          });
+          
+          resolve({
+            name: uploadRes.data?.originalName || file.name,
+            url: uploadRes.data?.tempPath || uploadRes.data?.url,
+            id: uploadRes.data?.id
+          });
+        } else {
+          proxy.$modal.msgError(uploadRes.msg || "鏂囦欢涓婁紶澶辫触");
+          resolve(null);
+        }
+      } catch (error) {
+        console.error("闄勪欢涓婁紶澶辫触:", error);
+        proxy.$modal.msgError("闄勪欢涓婁紶澶辫触");
+        resolve(null);
+      } finally {
+        document.body.removeChild(input);
+      }
+    };
+    
+    document.body.appendChild(input);
+    input.click();
+  });
+};
+
+// 鍒犻櫎闄勪欢
+const handleDeleteFile = async (file) => {
+  try {
+    await delCommonFile([file.id]);
+    proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+    
+    // 鍒锋柊鍒楄〃鑾峰彇鏈�鏂版暟鎹�
+    await new Promise((resolveRefresh) => {
+      // 璋冪敤 API 鑾峰彇鏈�鏂板垪琛ㄦ暟鎹�
+      productRecordPage({
+        ...filters,
+        current: pagination.currentPage,
+        size: pagination.pageSize
+      }).then(({ code, data }) => {
+        if (code === 200) {
+          // 鏇存柊鏁版嵁鍒楄〃
+          dataList.value = data.records;
+          pagination.total = data.total;
+          
+          // 浠庡閮ㄦ暟鎹幏鍙� commonFiles
+          const currentRow = dataList.value.find(row => row.id === currentRowId.value);
+          if (currentRow && fileListRef.value) {
+            // 鍒锋柊闄勪欢鍒楄〃锛屼娇鐢ㄤ粠澶栭儴鑾峰彇鐨勬渶鏂� commonFiles
+            fileListRef.value.open(currentRow.commonFiles || []);
+          }
+          resolveRefresh();
+        } else {
+          resolveRefresh();
+        }
+      }).catch(() => {
+        resolveRefresh();
+      });
+    });
+    
+    return true;
+  } catch (error) {
+    proxy.$modal.msgError("鍒犻櫎澶辫触");
+    return false;
+  }
+};
+
+const openEdit = (row) => {
+  editmodalRef.value.open(row);
+};
+// 鍒犻櫎
+const handleDelete = (row) => {
+	let ids = [];
+	ids.push(row.id);
+	ElMessageBox.confirm("璇ュ紑绁ㄥ彴璐﹀皢琚垹闄�,鏄惁纭鍒犻櫎", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			loading.value = true;
+			delRegistration(ids).then((res) => {
+				getTableData();
+			});
+			loading.value = false;
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
 };
 
 onMounted(() => {
-  getList();
+  getTableData();
 });
 </script>
 
-<style scoped lang="scss"></style>
+<style lang="scss" scoped>
+.table_list {
+  margin-top: unset;
+}
+.tagBox {
+  margin-top: 4px;
+}
+</style>

--
Gitblit v1.9.3