| | |
| | | <el-form-item label="设备名称"> |
| | | <el-input |
| | | v-model="filters.deviceName" |
| | | style="width: 240px" |
| | | style="width: 200px" |
| | | placeholder="请输入设备名称" |
| | | clearable |
| | | @change="getTableData" |
| | |
| | | <el-form-item label="规格型号"> |
| | | <el-input |
| | | v-model="filters.deviceModel" |
| | | style="width: 240px" |
| | | style="width: 200px" |
| | | placeholder="请输入规格型号" |
| | | clearable |
| | | @change="getTableData" |
| | |
| | | <el-form-item label="供应商"> |
| | | <el-input |
| | | v-model="filters.supplierName" |
| | | style="width: 240px" |
| | | style="width: 200px" |
| | | placeholder="请输入供应商" |
| | | clearable |
| | | @change="getTableData" |
| | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 详情对话框 --> |
| | | <el-dialog v-model="detailDialogVisible" title="设备台账详情" width="60%" draggable> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="设备名称">{{ detailData.deviceName }}</el-descriptions-item> |
| | | <el-descriptions-item label="规格型号">{{ detailData.deviceModel }}</el-descriptions-item> |
| | | <el-descriptions-item label="设备品牌">{{ detailData.deviceBrand }}</el-descriptions-item> |
| | | <el-descriptions-item label="设备类型">{{ detailData.type }}</el-descriptions-item> |
| | | <el-descriptions-item label="供应商">{{ detailData.supplierName }}</el-descriptions-item> |
| | | <el-descriptions-item label="存放位置">{{ detailData.storageLocation }}</el-descriptions-item> |
| | | <el-descriptions-item label="单位">{{ detailData.unit }}</el-descriptions-item> |
| | | <el-descriptions-item label="数量">{{ detailData.number }}</el-descriptions-item> |
| | | <el-descriptions-item label="启用折旧">{{ detailData.isDepr === 1 ? '是' : '否' }}</el-descriptions-item> |
| | | <el-descriptions-item label="每年折旧金额">{{ detailData.annualDepreciationAmount }}</el-descriptions-item> |
| | | <el-descriptions-item label="含税单价">{{ detailData.taxIncludingPriceUnit }}</el-descriptions-item> |
| | | <el-descriptions-item label="含税总价">{{ detailData.taxIncludingPriceTotal }}</el-descriptions-item> |
| | | <el-descriptions-item label="税率(%)">{{ detailData.taxRate }}</el-descriptions-item> |
| | | <el-descriptions-item label="不含税总价">{{ detailData.unTaxIncludingPriceTotal }}</el-descriptions-item> |
| | | <el-descriptions-item label="录入日期">{{ detailData.createTime }}</el-descriptions-item> |
| | | <el-descriptions-item label="预计运行时间">{{ detailData.planRuntimeTime ? dayjs(detailData.planRuntimeTime).format('YYYY-MM-DD') : '' }}</el-descriptions-item> |
| | | <el-descriptions-item label="设备图片" :span="2"> |
| | | <div v-if="detailData.storageBlobVOs && detailData.storageBlobVOs.length > 0" style="display: flex; gap: 10px; flex-wrap: wrap;"> |
| | | <el-image |
| | | v-for="(file, index) in detailData.storageBlobVOs" |
| | | :key="index" |
| | | :src="file.previewURL || file.url" |
| | | :preview-src-list="detailData.storageBlobVOs.map(u => u.previewURL || u.url)" |
| | | :initial-index="index" |
| | | style="width: 100px; height: 100px" |
| | | fit="cover" |
| | | /> |
| | | </div> |
| | | <span v-else>无图片</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <template #footer> |
| | | <el-button @click="detailDialogVisible = false">关闭</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | // import { Search } from "@element-plus/icons-vue"; |
| | | import { getLedgerPage, delLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { getLedgerPage, delLedger, getLedgerById } from "@/api/equipmentManagement/ledger"; |
| | | import { onMounted, getCurrentInstance, ref, reactive } from "vue"; |
| | | import Modal from "./Modal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | |
| | | const qrDialogVisible = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | const qrRowData = ref(null); |
| | | |
| | | const detailDialogVisible = ref(false); |
| | | const detailData = ref({}); |
| | | |
| | | // 导入相关 |
| | | const uploadRef = ref(null) |
| | |
| | | label: "操作", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 150, |
| | | width: 180, |
| | | operation: [ |
| | | { |
| | | name: "详情", |
| | | clickFun: (row) => { |
| | | handleDetail(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "编辑", |
| | | clickFun: (row) => { |
| | |
| | | }, |
| | | }, |
| | | { |
| | | name: "生成二维码", |
| | | name: "二维码", |
| | | clickFun: (row) => { |
| | | showQRCode(row) |
| | | }, |
| | |
| | | }; |
| | | const edit = (id) => { |
| | | modalRef.value.loadForm(id); |
| | | }; |
| | | const handleDetail = async (row) => { |
| | | const { code, data } = await getLedgerById(row.id); |
| | | if (code == 200) { |
| | | detailData.value = data; |
| | | detailDialogVisible.value = true; |
| | | } |
| | | }; |
| | | const changePage = ({ page, limit }) => { |
| | | pagination.currentPage = page; |
| | |
| | | const showQRCode = async (row) => { |
| | | // 直接使用URL,不要用JSON.stringify包装 |
| | | const qrContent = proxy.javaApi + '/device-info?deviceId=' + row.id; |
| | | qrCodeUrl.value = await QRCode.toDataURL(qrContent); |
| | | const qrDataUrl = await QRCode.toDataURL(qrContent, { width: 200, margin: 2 }); |
| | | |
| | | // 创建canvas合成带名称的二维码图片 |
| | | const canvas = document.createElement('canvas'); |
| | | const ctx = canvas.getContext('2d'); |
| | | const qrSize = 200; |
| | | const textHeight = 30; |
| | | const padding = 10; |
| | | canvas.width = qrSize + padding * 2; |
| | | canvas.height = qrSize + textHeight + padding * 2; |
| | | |
| | | // 填充白色背景 |
| | | ctx.fillStyle = '#ffffff'; |
| | | ctx.fillRect(0, 0, canvas.width, canvas.height); |
| | | |
| | | // 绘制二维码 |
| | | const qrImg = new Image(); |
| | | qrImg.src = qrDataUrl; |
| | | await new Promise((resolve) => { qrImg.onload = resolve; }); |
| | | ctx.drawImage(qrImg, padding, padding, qrSize, qrSize); |
| | | |
| | | // 绘制设备名称 |
| | | ctx.fillStyle = '#333333'; |
| | | ctx.font = 'bold 14px Arial'; |
| | | ctx.textAlign = 'center'; |
| | | ctx.fillText(row.deviceName || '', canvas.width / 2, qrSize + padding + 20); |
| | | |
| | | qrCodeUrl.value = canvas.toDataURL('image/png'); |
| | | qrRowData.value = row; |
| | | qrDialogVisible.value = true; |
| | | }; |