From 2cdbad409e82d4354e4eca5cffa65c6bef7a4d20 Mon Sep 17 00:00:00 2001
From: zss <zss@example.com>
Date: 星期一, 16 三月 2026 13:36:37 +0800
Subject: [PATCH] bom添加产品编码

---
 src/views/energyManagement/officeEnergyConsumption/index.vue |  421 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 390 insertions(+), 31 deletions(-)

diff --git a/src/views/energyManagement/officeEnergyConsumption/index.vue b/src/views/energyManagement/officeEnergyConsumption/index.vue
index c3fbf82..0def5d5 100644
--- a/src/views/energyManagement/officeEnergyConsumption/index.vue
+++ b/src/views/energyManagement/officeEnergyConsumption/index.vue
@@ -11,14 +11,21 @@
                      style="width: 140px;"
                      @change="handleQuery">
             <el-option label="姘�"
-                       value="water" />
+                       value="姘�" />
             <el-option label="鐢�"
-                       value="electricity" />
+                       value="鐢�" />
             <el-option label="姘�"
-                       value="gas" />
+                       value="姘�" />
           </el-select>
         </el-form-item>
-        <!-- <el-form-item label="鏃ユ湡鑼冨洿:">
+        <el-form-item label="鑳芥簮鍚嶇О:">
+          <el-input v-model="searchForm.energyName"
+                    placeholder="璇疯緭鍏�"
+                    clearable
+                    style="width: 160px;"
+                    @keyup.enter="handleQuery" />
+        </el-form-item>
+        <el-form-item label="鏃ユ湡鑼冨洿:">
           <el-date-picker v-model="searchForm.dateRange"
                           type="daterange"
                           range-separator="鑷�"
@@ -27,7 +34,7 @@
                           value-format="YYYY-MM-DD"
                           style="width: 240px;"
                           @change="handleQuery" />
-        </el-form-item> -->
+        </el-form-item>
         <el-form-item>
           <el-button type="primary"
                      @click="handleQuery">鎼滅储</el-button>
@@ -35,10 +42,12 @@
         </el-form-item>
       </el-form>
       <div>
-        <!-- <el-button type="primary"
-                   @click="handleAdd">鏂板</el-button> -->
+        <el-button type="primary"
+                   @click="handleAdd">鏂板</el-button>
         <el-button type="success"
                    @click="handleExport">瀵煎嚭</el-button>
+        <el-button type="warning"
+                   @click="handleImport">瀵煎叆</el-button>
       </div>
     </div>
     <!-- 鏁版嵁琛ㄦ牸 -->
@@ -102,8 +111,8 @@
                          label="澶囨敞"
                          min-width="150"
                          show-overflow-tooltip />
-        <!-- <el-table-column label="鎿嶄綔"
-                         width="180"
+        <el-table-column label="鎿嶄綔"
+                         width="220"
                          align="center"
                          fixed="right">
           <template #default="scope">
@@ -113,8 +122,11 @@
             <el-button type="danger"
                        link
                        @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+            <el-button type="info"
+                       link
+                       @click="downLoadFile(scope.row)">闄勪欢</el-button>
           </template>
-        </el-table-column> -->
+        </el-table-column>
       </el-table>
       <div class="pagination-container">
         <el-pagination v-model:current-page="page.current"
@@ -199,6 +211,28 @@
         </span>
       </template>
     </el-dialog>
+    <!-- 闄勪欢鍒楄〃寮圭獥 -->
+    <FileListDialog ref="fileListRef"
+                    v-model="fileListDialogVisible"
+                    :show-upload-button="true"
+                    :show-delete-button="true"
+                    :is-show-pagination="true"
+                    :page="filePagination"
+                    :upload-method="handleUpload"
+                    :delete-method="handleFileDelete"
+                    @pagination="paginationSearch"
+                    title="闄勪欢鍒楄〃" />
+    <ImportDialog ref="importDialogRef"
+                  v-model="importDialogVisible"
+                  title="瀵煎叆鏄庣粏"
+                  :action="importAction"
+                  :headers="importHeaders"
+                  :auto-upload="false"
+                  :on-success="handleImportSuccess"
+                  :on-error="handleImportError"
+                  @confirm="handleImportConfirm"
+                  @download-template="handleDownloadTemplate"
+                  @close="handleImportClose" />
   </div>
 </template>
 
@@ -206,11 +240,18 @@
   import { ref, reactive, onMounted, getCurrentInstance } from "vue";
   import { ElMessage, ElMessageBox } from "element-plus";
   import { Watermelon, Lightning } from "@element-plus/icons-vue";
+  import ImportDialog from "@/components/Dialog/ImportDialog.vue";
+  import { getToken } from "@/utils/auth";
+  import FileListDialog from "@/components/Dialog/FileListDialog.vue";
+  import request from "@/utils/request";
   import {
     energyConsumptionDetailListPage,
     energyConsumptionDetailAdd,
     energyConsumptionDetailDelete,
     energyTypeListPage,
+    fileListPage,
+    energyConsumptionDetailFileAdd,
+    energyConsumptionDetailFileDel,
   } from "@/api/energyManagement/energyType";
 
   // 鎼滅储琛ㄥ崟
@@ -247,6 +288,25 @@
   const formRef = ref(null);
   const isEdit = ref(false);
   const currentId = ref(null);
+
+  // 闄勪欢鐩稿叧
+  const fileListRef = ref(null);
+  const fileListDialogVisible = ref(false);
+  const currentFileRow = ref(null);
+  const filePagination = ref({
+    current: 1,
+    size: 10,
+    total: 0,
+  });
+
+  // 瀵煎叆鐩稿叧
+  const importDialogRef = ref(null);
+  const importDialogVisible = ref(false);
+  const importAction =
+    import.meta.env.VITE_APP_BASE_API + "/energyConsumptionDetail/importData";
+  const importHeaders = ref({
+    Authorization: `Bearer ${getToken()}`,
+  });
 
   // 琛ㄥ崟鏁版嵁
   const form = reactive({
@@ -314,15 +374,16 @@
       current: page.current,
       size: page.size,
       type: "鍔炲叕",
-      // energyType: searchForm.energyType,
-      // startDate:
-      //   searchForm.dateRange && searchForm.dateRange.length === 2
-      //     ? searchForm.dateRange[0]
-      //     : null,
-      // endDate:
-      //   searchForm.dateRange && searchForm.dateRange.length === 2
-      //     ? searchForm.dateRange[1]
-      //     : null,
+      energyTyep: searchForm.energyType,
+      energyName: searchForm.energyName,
+      startDate:
+        searchForm.dateRange && searchForm.dateRange.length === 2
+          ? searchForm.dateRange[0]
+          : null,
+      endDate:
+        searchForm.dateRange && searchForm.dateRange.length === 2
+          ? searchForm.dateRange[1]
+          : null,
     };
     energyConsumptionDetailListPage(params)
       .then(res => {
@@ -358,6 +419,7 @@
   // 閲嶇疆
   const handleReset = () => {
     searchForm.energyType = "";
+    searchForm.energyName = "";
     searchForm.dateRange = [];
     page.current = 1;
     handleQuery();
@@ -478,6 +540,205 @@
     });
   };
 
+  // 涓嬭浇鏂囦欢
+  const downLoadFile = row => {
+    currentFileRow.value = row;
+    fileListPage({
+      energyConsumptionDetailId: row.id,
+      current: filePagination.value.current,
+      size: filePagination.value.size,
+    }).then(res => {
+      if (fileListRef.value) {
+        fileListRef.value.open(res.data.records);
+      }
+      filePagination.value.total = res.data.total || 0;
+    });
+  };
+
+  // 涓婁紶闄勪欢
+  const handleUpload = async () => {
+    if (!currentFileRow.value) {
+      ElMessage.warning("璇峰厛閫夋嫨鏁版嵁");
+      return null;
+    }
+
+    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);
+
+          const uploadRes = await request({
+            url: "/file/upload",
+            method: "post",
+            data: formData,
+            headers: {
+              "Content-Type": "multipart/form-data",
+              Authorization: `Bearer ${getToken()}`,
+            },
+          });
+
+          if (uploadRes.code === 200) {
+            // 淇濆瓨闄勪欢淇℃伅
+            const fileData = {
+              energyConsumptionDetailId: currentFileRow.value.id,
+              name: uploadRes.data.originalName || file.name,
+              url: uploadRes.data.tempPath || uploadRes.data.url,
+            };
+
+            const saveRes = await energyConsumptionDetailFileAdd(fileData);
+            if (saveRes.code === 200) {
+              proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+              // 閲嶆柊鍔犺浇鏂囦欢鍒楄〃
+              const listRes = await fileListPage({
+                energyConsumptionDetailId: currentFileRow.value.id,
+                current: filePagination.value.current,
+                size: filePagination.value.size,
+              });
+              if (listRes.code === 200 && fileListRef.value) {
+                const fileList = (listRes.data?.records || []).map(item => ({
+                  name: item.name,
+                  url: item.url,
+                  id: item.id,
+                  ...item,
+                }));
+                fileListRef.value.setList(fileList);
+                filePagination.value.total = listRes.data?.total || 0;
+              }
+              // 杩斿洖鏂版枃浠朵俊鎭�
+              resolve({
+                name: fileData.name,
+                url: fileData.url,
+                id: Date.now(),
+              });
+            } else {
+              ElMessage.error(uploadRes.message || "鏂囦欢涓婁紶澶辫触");
+              resolve(null);
+            }
+          }
+        } catch (error) {
+          ElMessage.error("鏂囦欢涓婁紶澶辫触");
+          resolve(null);
+        } finally {
+          document.body.removeChild(input);
+        }
+      };
+
+      document.body.appendChild(input);
+      input.click();
+    });
+  };
+
+  // 鍒嗛〉鎼滅储
+  const paginationSearch = async (page, size) => {
+    filePagination.value.current = page;
+    filePagination.value.size = size;
+    const listRes = await fileListPage({
+      energyConsumptionDetailId: currentFileRow.value.id,
+      current: filePagination.value.current,
+      size: filePagination.value.size,
+    });
+    if (listRes.code === 200) {
+      const fileList = (listRes.data?.records || []).map(item => ({
+        name: item.name,
+        url: item.url,
+        id: item.id,
+        ...item,
+      }));
+
+      fileListRef.value.setList(fileList);
+      filePagination.value.total = listRes.data?.total || 0;
+    }
+  };
+
+  // 鍒犻櫎闄勪欢
+  const handleFileDelete = async row => {
+    try {
+      const res = await energyConsumptionDetailFileDel([row.id]);
+      if (res.code === 200) {
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        // 閲嶆柊鍔犺浇鏂囦欢鍒楄〃
+        if (currentFileRow.value && fileListRef.value) {
+          const listRes = await fileListPage({
+            energyConsumptionDetailId: currentFileRow.value.id,
+            current: filePagination.value.current,
+            size: filePagination.value.size,
+          });
+          if (listRes.code === 200) {
+            const fileList = (listRes.data?.records || []).map(item => ({
+              name: item.name,
+              url: item.url,
+              id: item.id,
+              ...item,
+            }));
+            fileListRef.value.setList(fileList);
+            filePagination.value.total = listRes.data?.total || 0;
+          }
+        }
+        return true; // 杩斿洖 true 琛ㄧず鍒犻櫎鎴愬姛锛岀粍浠朵細鏇存柊鍒楄〃
+      } else {
+        proxy.$modal.msgError(res.msg || "鍒犻櫎澶辫触");
+        return false;
+      }
+    } catch (error) {
+      ElMessage.error("鍒犻櫎澶辫触");
+      return false;
+    }
+  };
+
+  // 瀵煎叆
+  const handleImport = () => {
+    importDialogVisible.value = true;
+  };
+
+  // 瀵煎叆鎴愬姛
+  const handleImportSuccess = response => {
+    if (response.code === 200) {
+      ElMessage.success("瀵煎叆鎴愬姛");
+      importDialogVisible.value = false;
+      handleQuery();
+    } else {
+      ElMessage.error(response.message || "瀵煎叆澶辫触");
+    }
+  };
+
+  // 瀵煎叆澶辫触
+  const handleImportError = error => {
+    ElMessage.error("瀵煎叆澶辫触锛岃妫�鏌ユ枃浠舵牸寮忔槸鍚︽纭�");
+  };
+
+  // 纭瀵煎叆
+  const handleImportConfirm = () => {
+    if (importDialogRef.value) {
+      importDialogRef.value.submit();
+    }
+  };
+
+  // 涓嬭浇妯℃澘
+  const handleDownloadTemplate = () => {
+    proxy.download(
+      "/energyConsumptionDetail/downloadTemplate",
+      {},
+      "鐢熶骇鑳借�楀鍏ユā鏉�.xlsx"
+    );
+  };
+
+  // 鍏抽棴瀵煎叆寮圭獥
+  const handleImportClose = () => {
+    importDialogVisible.value = false;
+  };
+
   onMounted(() => {
     getEnergyTypeList();
     handleQuery();
@@ -494,7 +755,9 @@
   .search_form {
     display: flex;
     justify-content: space-between;
-    align-items: center;
+    align-items: flex-start;
+    flex-wrap: wrap;
+    gap: 16px;
     margin-bottom: 24px;
     padding: 20px;
     background-color: #ffffff;
@@ -504,6 +767,28 @@
 
     &:hover {
       box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08);
+    }
+
+    :deep(.el-form) {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 0;
+
+      .el-form-item {
+        margin-right: 16px;
+        margin-bottom: 0;
+
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+
+    > div {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 8px;
+      flex-shrink: 0;
     }
   }
 
@@ -636,28 +921,83 @@
     font-size: 12px;
   }
 
-  @media (max-width: 768px) {
-    .app-container {
-      padding: 16px;
+  @media (max-width: 1200px) {
+    .search_form {
+      :deep(.el-form) {
+        .el-form-item {
+          margin-right: 12px;
+          margin-bottom: 8px;
+        }
+      }
     }
+  }
 
+  @media (max-width: 992px) {
     .search_form {
       flex-direction: column;
-      align-items: flex-start;
+      align-items: stretch;
       gap: 12px;
 
-      .el-form {
+      :deep(.el-form) {
         width: 100%;
 
         .el-form-item {
-          width: 100%;
+          margin-right: 12px;
+          margin-bottom: 8px;
+          flex: 1;
+          min-width: 200px;
+
+          &:last-child {
+            margin-right: 12px;
+          }
         }
       }
 
       > div {
         width: 100%;
-        display: flex;
-        gap: 12px;
+        justify-content: flex-end;
+      }
+    }
+  }
+
+  @media (max-width: 768px) {
+    .app-container {
+      padding: 12px;
+    }
+
+    .search_form {
+      padding: 16px;
+      gap: 12px;
+
+      :deep(.el-form) {
+        flex-direction: column;
+        width: 100%;
+
+        .el-form-item {
+          width: 100%;
+          margin-right: 0;
+          margin-bottom: 12px;
+
+          &:last-child {
+            margin-right: 0;
+            margin-bottom: 0;
+          }
+
+          .el-form-item__content {
+            width: 100%;
+
+            .el-input,
+            .el-select,
+            .el-date-editor {
+              width: 100% !important;
+            }
+          }
+        }
+      }
+
+      > div {
+        width: 100%;
+        justify-content: stretch;
 
         .el-button {
           flex: 1;
@@ -665,17 +1005,36 @@
       }
     }
 
+    .table_list {
+      height: calc(100vh - 300px);
+    }
+
     :deep(.el-table) {
       th,
       td {
-        padding: 10px 0;
+        padding: 8px 0;
         font-size: 12px;
       }
     }
 
     :deep(.el-dialog) {
-      width: 90% !important;
-      margin: 20px auto !important;
+      width: 95% !important;
+      margin: 10px auto !important;
+    }
+  }
+
+  @media (max-width: 480px) {
+    .search_form {
+      padding: 12px;
+
+      > div {
+        flex-direction: column;
+        gap: 8px;
+
+        .el-button {
+          width: 100%;
+        }
+      }
     }
   }
   .consumption-value {

--
Gitblit v1.9.3