From 1e26592ce9418c5c9d02d1bba9cbe42170d9895f Mon Sep 17 00:00:00 2001
From: 周宾 <2802492122@qq.com>
Date: 星期一, 08 十二月 2025 11:24:33 +0800
Subject: [PATCH] 修改设备模块

---
 src/views/equipmentManagement/ledger/index.vue |  436 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 427 insertions(+), 9 deletions(-)

diff --git a/src/views/equipmentManagement/ledger/index.vue b/src/views/equipmentManagement/ledger/index.vue
index 3ecac9d..0a2ce3c 100644
--- a/src/views/equipmentManagement/ledger/index.vue
+++ b/src/views/equipmentManagement/ledger/index.vue
@@ -1,38 +1,456 @@
 <template>
   <div class="app-container">
-    <el-form :model="filters">
-      <el-form-item label="鎼滅储">
+    <el-form :model="filters" :inline="true">
+      <el-form-item label="璁惧鍚嶇О">
         <el-input
-          v-model="filters.searchText"
+          v-model="filters.deviceName"
           style="width: 240px"
-          placeholder="璇疯緭鍏�"
+          placeholder="璇疯緭鍏ヨ澶囧悕绉�"
           clearable
           :prefix-icon="Search"
           @change="getTableData"
         />
       </el-form-item>
+      <el-form-item label="瑙勬牸鍨嬪彿">
+        <el-input
+            v-model="filters.deviceModel"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="渚涘簲鍟�">
+        <el-input
+            v-model="filters.supplierName"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ヤ緵搴斿晢"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="鍗曚綅">
+        <el-input
+            v-model="filters.unit"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ュ崟浣�"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="褰曞叆鏃ユ湡:">
+        <el-date-picker v-model="filters.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+                        placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
+      </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>
-    <PIMTable :column="columns" />
+    <div class="table_list">
+      <div class="actions">
+        <div></div>
+        <div>
+          <el-button type="primary" @click="add" icon="Plus"> 鏂板 </el-button>
+          <el-button plain icon="Upload" @click="handleImport">瀵煎叆</el-button>
+          <el-button @click="handleOut" icon="download">瀵煎嚭</el-button>
+          <el-button
+            type="danger"
+            icon="Delete"
+            :disabled="multipleList.length <= 0"
+            @click="deleteRow(multipleList.map((item) => item.id))"
+          >
+            鎵归噺鍒犻櫎
+          </el-button>
+        </div>
+      </div>
+      <PIMTable
+        rowKey="id"
+        isSelection
+        :column="columns"
+        :tableData="dataList"
+        :page="{
+          current: pagination.currentPage,
+          size: pagination.pageSize,
+          total: pagination.total,
+        }"
+        @selection-change="handleSelectionChange"
+        @pagination="changePage"
+      >
+      </PIMTable>
+    </div>
+    <Modal ref="modalRef" @success="getTableData"></Modal>
+    <el-dialog v-model="qrDialogVisible" title="浜岀淮鐮�" width="300px">
+      <div style="text-align:center;">
+        <img :src="qrCodeUrl" alt="浜岀淮鐮�" style="width:200px;height:200px;" />
+        <div style="margin-top:6px;font-size:14px;color:#333;">{{ qrRowData?.deviceName }}</div>
+        <div style="margin:10px 0;">
+          <el-button type="primary" @click="downloadQRCode">涓嬭浇浜岀淮鐮佸浘鐗�</el-button>
+        </div>
+      </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"
+        :before-upload="upload.beforeUpload"
+        :on-progress="upload.onProgress"
+        :on-success="upload.onSuccess"
+        :on-error="upload.onError"
+        :on-change="upload.onChange"
+        :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 { usePaginationApi } from "@/hooks/usePaginationApi";
-import { Search } from "@element-plus/icons-vue";
+// import { Search } from "@element-plus/icons-vue";
+import { getLedgerPage, delLedger } from "@/api/equipmentManagement/ledger";
+import { onMounted, getCurrentInstance } from "vue";
+import Modal from "./Modal.vue";
+import { ElMessageBox, ElMessage } from "element-plus";
+import dayjs from "dayjs";
+import QRCode from "qrcode";
+import { ref } from "vue";
+import { getToken } from "@/utils/auth.js";
 
 defineOptions({
   name: "璁惧鍙拌处",
 });
 
-const { filters, columns, getTableData } = usePaginationApi(
-  () => {},
+// 琛ㄦ牸澶氶�夋閫変腑椤�
+const multipleList = ref([]);
+const { proxy } = getCurrentInstance();
+const modalRef = ref();
+const qrDialogVisible = ref(false);
+const qrCodeUrl = ref("");
+const qrRowData = ref(null);
+
+const {
+  filters,
+  columns,
+  dataList,
+  pagination,
+  getTableData,
+  resetFilters,
+  onCurrentChange,
+} = usePaginationApi(
+  getLedgerPage,
   {
-    searchText: undefined,
+    deviceName: undefined,
+    deviceModel: undefined,
+    supplierName: undefined,
+    unit: undefined,
+    entryDateStart: undefined,
+    entryDateEnd: undefined,
   },
   [
     {
       label: "璁惧鍚嶇О",
+      align: "center",
+      prop: "deviceName",
     },
+    {
+      label: "瑙勬牸鍨嬪彿",
+      align: "center",
+      prop: "deviceModel",
+    },
+    {
+      label: "璁惧鍝佺墝",
+      align: "center",
+      prop: "deviceBrand",
+    },
+    {
+      label: "渚涘簲鍟�",
+      align: "center",
+      prop: "supplierName",
+    },
+    {
+      label: "鍗曚綅",
+      align: "center",
+      prop: "unit",
+    },
+    {
+      label: "瀛樻斁浣嶇疆",
+      align: "center",
+      prop: "storageLocation",
+    },
+    {
+      label: "鏁伴噺",
+      align: "center",
+      prop: "number",
+    },
+    {
+      label: "璧勪骇鍘熷��",
+      align: "center",
+      prop: "taxIncludingPriceUnit",
+    },
+    {
+      label: "鍚敤鎶樻棫",
+      align: "center",
+      prop: "enableDepreciation",
+      formatData: (v) => (v ? "鏄�" : "鍚�"),
+    },
+    {
+      label: "褰曞叆浜�",
+      align: "center",
+      prop: "createUser",
+    },
+    {
+      label: "褰曞叆鏃ユ湡",
+      align: "center",
+      prop: "createTime",
+    },
+		{
+			dataType: "action",
+			label: "鎿嶄綔",
+			align: "center",
+			fixed: 'right',
+			width: 150,
+			operation: [
+				{
+					name: "缂栬緫",
+					type: "text",
+					clickFun: (row) => {
+						edit(row.id)
+					},
+				},
+				{
+					name: "鐢熸垚浜岀淮鐮�",
+					type: "text",
+					clickFun: (row) => {
+						showQRCode(row)
+					},
+				},
+			],
+		},
   ]
 );
+
+const upload = reactive({
+  // 鏄惁鏄剧ず寮瑰嚭灞傦紙瀹㈡埛瀵煎叆锛�
+  open: false,
+  // 寮瑰嚭灞傛爣棰橈紙瀹㈡埛瀵煎叆锛�
+  title: "",
+  // 鏄惁绂佺敤涓婁紶
+  isUploading: false,
+  // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+  headers: { Authorization: "Bearer " + getToken() },
+  // 涓婁紶鐨勫湴鍧�
+  url: import.meta.env.VITE_APP_BASE_API + "/device/ledger/import",
+  // 鏂囦欢涓婁紶鍓嶇殑鍥炶皟
+  beforeUpload: (file) => {
+    console.log('鏂囦欢鍗冲皢涓婁紶', file);
+    // 鍙互鍦ㄦ澶勫仛鏂囦欢绫诲瀷鎴栧ぇ灏忔牎楠�
+    const isValid = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
+    if (!isValid) {
+      proxy.$modal.msgError("鍙兘涓婁紶 Excel 鏂囦欢");
+    }
+    return isValid;
+  },
+  // 鏂囦欢鐘舵�佹敼鍙樻椂鐨勫洖璋�
+  onChange: (file, fileList) => {
+    console.log('鏂囦欢鐘舵�佹敼鍙�', file, fileList);
+  },
+  // 鏂囦欢涓婁紶鎴愬姛鏃剁殑鍥炶皟
+  onSuccess: (response, file, fileList) => {
+    console.log('涓婁紶鎴愬姛', response, file, fileList);
+    upload.isUploading = false;
+    if(response.code === 200){
+      proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+      upload.open = false;
+      proxy.$refs["uploadRef"].clearFiles();
+      getTableData();
+    }else if(response.code === 500){
+      proxy.$modal.msgError(response.msg);
+    }else{
+      proxy.$modal.msgWarning(response.msg);
+    }
+  },
+  // 鏂囦欢涓婁紶澶辫触鏃剁殑鍥炶皟
+  onError: (error, file, fileList) => {
+    console.error('涓婁紶澶辫触', error, file, fileList);
+    upload.isUploading = false;
+    proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+  },
+  // 鏂囦欢涓婁紶杩涘害鍥炶皟
+  onProgress: (event, file, fileList) => {
+    console.log('涓婁紶涓�...', event.percent);
+  }
+});
+
+/** 鎻愪氦涓婁紶鏂囦欢 */
+const submitFileForm = () => {
+  upload.isUploading = true;
+  proxy.$refs["uploadRef"].submit();
+}
+
+/** 涓嬭浇妯℃澘 */
+const importTemplate = () => {
+  proxy.download("/device/ledger/downloadTemplate", {}, "璁惧鍙拌处妯℃澘.xlsx");
+}
+
+// 澶氶�夊悗鍋氫粈涔�
+const handleSelectionChange = (selectionList) => {
+  multipleList.value = selectionList;
+};
+
+const add = () => {
+  modalRef.value.openModal();
+};
+const edit = (id) => {
+  modalRef.value.loadForm(id);
+};
+const changePage = ({ page, limit }) => {
+  pagination.currentPage = page;
+	pagination.pageSize = limit;
+  onCurrentChange(page);
+};
+const deleteRow = (id) => {
+  ElMessageBox.confirm("姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?", "鎻愮ず", {
+    confirmButtonText: "纭畾",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  }).then(async () => {
+    const { code } = await delLedger(id);
+    if (code == 200) {
+      ElMessage({
+        type: "success",
+        message: "鍒犻櫎鎴愬姛",
+      });
+      getTableData();
+    }
+  });
+};
+
+const changeDaterange = (value) => {
+  if (value) {
+    filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+    filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+  } else {
+    filters.entryDateStart = undefined;
+    filters.entryDateEnd = undefined;
+  }
+  getTableData();
+};
+/** 瀵煎叆鎸夐挳鎿嶄綔 */
+const handleImport = () => {
+  upload.title = "璁惧鍙拌处瀵煎叆";
+  upload.open = true;
+}
+
+const handleOut = () => {
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download(`/device/ledger/export`, {}, "璁惧鍙拌处妗f.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+const showQRCode = async (row) => {
+  // 鐩存帴浣跨敤URL锛屼笉瑕佺敤JSON.stringify鍖呰
+  const qrContent = proxy.javaApi + '/device-info?deviceId=' + row.id;
+  qrCodeUrl.value = await QRCode.toDataURL(qrContent);
+  qrRowData.value = row;
+  qrDialogVisible.value = true;
+};
+
+const downloadQRCode = () => {
+  const name = qrRowData.value?.deviceName || "浜岀淮鐮�";
+  const img = new Image();
+  img.src = qrCodeUrl.value;
+  img.onload = () => {
+    const padding = 10;
+    const qrSize = 200;
+    const textHeight = 24; // space for text
+    const width = qrSize + padding * 2;
+    const height = qrSize + padding * 2 + textHeight;
+    const canvas = document.createElement("canvas");
+    canvas.width = width;
+    canvas.height = height;
+    const ctx = canvas.getContext("2d");
+    // background
+    ctx.fillStyle = "#ffffff";
+    ctx.fillRect(0, 0, width, height);
+    // draw QR centered
+    ctx.drawImage(img, padding, padding, qrSize, qrSize);
+    // draw name centered below
+    ctx.fillStyle = "#333";
+    ctx.font = "14px Arial";
+    ctx.textAlign = "center";
+    ctx.textBaseline = "middle";
+    const maxTextWidth = width - padding * 2;
+    let displayName = name;
+    // ellipsis if too long
+    while (ctx.measureText(displayName).width > maxTextWidth && displayName.length > 0) {
+      displayName = displayName.slice(0, -1);
+    }
+    if (displayName !== name) displayName = displayName + "鈥�";
+    ctx.fillText(displayName, width / 2, qrSize + padding + textHeight / 2);
+
+    const dataUrl = canvas.toDataURL("image/png");
+    const a = document.createElement("a");
+    a.href = dataUrl;
+    a.download = `${name}.png`;
+    a.click();
+  };
+};
+
+onMounted(() => {
+  getTableData();
+});
 </script>
+
+<style lang="scss" scoped>
+.table_list {
+  margin-top: unset;
+}
+.actions {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+</style>

--
Gitblit v1.9.3