From 73a8b690a2e4ed608212bda2110698a599563210 Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期一, 01 九月 2025 13:50:40 +0800 Subject: [PATCH] 完成打印机打印功能 --- src/views/inventoryManagement/dispatchLog/index.vue | 584 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 577 insertions(+), 7 deletions(-) diff --git a/src/views/inventoryManagement/dispatchLog/index.vue b/src/views/inventoryManagement/dispatchLog/index.vue index 504074e..27d8f33 100644 --- a/src/views/inventoryManagement/dispatchLog/index.vue +++ b/src/views/inventoryManagement/dispatchLog/index.vue @@ -19,6 +19,7 @@ <!-- <el-button type="primary" @click="openForm('add')">鏂板</el-button> --> <el-button @click="handleOut">瀵煎嚭</el-button> <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button> + <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button> </div> </div> <div class="table_list"> @@ -128,6 +129,120 @@ @pagination="paginationChange" /> </div> + + <!-- 鎵撳嵃棰勮寮圭獥 --> + <el-dialog + v-model="printPreviewVisible" + title="鎵撳嵃棰勮" + width="90%" + :close-on-click-modal="false" + class="print-preview-dialog" + > + <div class="print-preview-container"> + <div class="print-preview-header"> + <el-button type="primary" @click="executePrint">鎵ц鎵撳嵃</el-button> + <el-button @click="printPreviewVisible = false">鍏抽棴棰勮</el-button> + </div> + <div class="print-preview-content"> + <div v-if="printData.length === 0" style="text-align: center; padding: 50px; color: #999;"> + 鏆傛棤鎵撳嵃鏁版嵁 + </div> + <div v-else style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;"> + 鍏� {{ printData.length }} 鏉℃暟鎹緟鎵撳嵃 + </div> + <div v-for="(item, index) in printData" :key="index" class="print-page"> + <div class="delivery-note"> + <div class="header"> + <div class="company-name">榧庤瘹鐟炲疄涓氭湁闄愯矗浠诲叕鍙�</div> + <div class="document-title">闆跺敭鍙戣揣鍗�</div> + </div> + + <div class="info-section"> + <div class="info-row"> + <div> + <span class="label">鍙戣揣鏃ユ湡锛�</span> + <span class="value">{{ formatDate(item.createTime) }}</span> + </div> + <div> + + <span class="label">瀹㈡埛鍚嶇О锛�</span> + <span class="value">{{ item.supplierName || '寮犵埍鏈�' }}</span> + </div> + </div> + <div class="info-row"> + <span class="label">鍗曞彿锛�</span> + <span class="value">{{ item.code }}</span> + </div> + </div> + + <div class="table-section"> + <table class="product-table"> + <thead> + <tr> + <th>浜у搧鍚嶇О</th> + <th>瑙勬牸鍨嬪彿</th> + <th>鍗曚綅</th> + <th>鍗曚环</th> + <th>闆跺敭鏁伴噺</th> + <th>闆跺敭閲戦</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ item.productCategory || '鐮傜伆鐮�' }}</td> + <td>{{ item.specificationModel || '鏍囧噯' }}</td> + <td>{{ item.unit || '鍧�' }}</td> + <td>{{ item.taxInclusiveUnitPrice || '0' }}</td> + <td>{{ item.inboundNum || '2000' }}</td> + <td>{{ item.taxInclusiveTotalPrice || '0' }}</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="label">鍚堣</td> + <td class="total-value"></td> + <td class="total-value"></td> + <td class="total-value"></td> + <td class="total-value">{{ item.inboundNum || '2000' }}</td> + <td class="total-value">{{ item.taxInclusiveTotalPrice || '0' }}</td> + </tr> + </tfoot> + </table> + </div> + + <div class="footer-section"> + <div class="footer-row"> + <div class="footer-item"> + <span class="label">鏀惰揣鐢佃瘽锛�</span> + <span class="value"></span> + </div> + <div class="footer-item"> + <span class="label">鏀惰揣浜猴細</span> + <span class="value"></span> + </div> + <div class="footer-item address-item"> + <span class="label">鏀惰揣鍦板潃锛�</span> + <span class="value address-value"></span> + </div> + </div> + <div class="footer-row"> + <div class="footer-item"> + <span class="label">鎿嶄綔鍛橈細</span> + <span class="value">{{ userStore.nickname || '鎾曞紑鍓�' }}</span> + </div> + <div class="footer-item"> + <span class="label">鎵撳嵃鏃ユ湡锛�</span> + <span class="value">{{ formatDateTime(new Date()) }}</span> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </el-dialog> + + </div> </template> @@ -136,7 +251,6 @@ import { ref } from "vue"; import { ElMessageBox } from "element-plus"; import useUserStore from "@/store/modules/user"; -import { userListNoPage } from "@/api/system/user.js"; import { getStockOutPage, delStockOut, @@ -146,19 +260,18 @@ const { proxy } = getCurrentInstance(); const tableData = ref([]); const selectedRows = ref([]); -const userList = ref([]); const tableLoading = ref(false); -const productList = ref([]) const page = reactive({ current: 1, size: 100, }); const total = ref(0); -const fileList = ref([]); + +// 鎵撳嵃鐩稿叧 +const printPreviewVisible = ref(false); +const printData = ref([]); // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁 -const operationType = ref(""); -const dialogFormVisible = ref(false); const data = reactive({ searchForm: { supplierName: "", @@ -268,6 +381,296 @@ proxy.$modal.msg("宸插彇娑�"); }); }; + +// 鎵撳嵃鍔熻兘 +const handlePrint = () => { + if (selectedRows.value.length === 0) { + proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁"); + return; + } + printData.value = [...selectedRows.value]; + console.log('鎵撳嵃鏁版嵁:', printData.value); + printPreviewVisible.value = true; +}; + +// 鎵ц鎵撳嵃 +const executePrint = () => { + console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length); + console.log('鎵撳嵃鏁版嵁:', printData.value); + + // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙� + const printWindow = window.open('', '_blank', 'width=800,height=600'); + + // 鏋勫缓鎵撳嵃鍐呭 + let printContent = ` + <!DOCTYPE html> + <html> + <head> + <meta charset="UTF-8"> + <title>鎵撳嵃棰勮</title> + <style> + body { + margin: 0; + padding: 0; + font-family: "SimSun", serif; + background: white; + } + .print-page { + width: 200mm; + height: 75mm; + padding: 10mm; + padding-left: 20mm; + background: white; + box-sizing: border-box; + page-break-after: always; + page-break-inside: avoid; + } + .print-page:last-child { + page-break-after: avoid; + } + .delivery-note { + width: 100%; + height: 100%; + font-size: 12px; + line-height: 1.2; + display: flex; + flex-direction: column; + color: #000; + } + .header { + text-align: center; + margin-bottom: 8px; + } + .company-name { + font-size: 18px; + font-weight: bold; + margin-bottom: 4px; + } + .document-title { + font-size: 16px; + font-weight: bold; + } + .info-section { + margin-bottom: 8px; + display: flex; + justify-content: space-between; + align-items: center; + } + .info-row { + line-height: 20px; + } + .label { + font-weight: bold; + width: 60px; + font-size: 12px; + } + .value { + margin-right: 20px; + min-width: 80px; + font-size: 12px; + } + .table-section { + margin-bottom: 40px; + // flex: 0.6; + } + .product-table { + width: 100%; + border-collapse: collapse; + border: 1px solid #000; + } + .product-table th, .product-table td { + border: 1px solid #000; + padding: 6px; + text-align: center; + font-size: 12px; + line-height: 1.4; + } + .product-table th { + font-weight: bold; + } + .total-value { + font-weight: bold; + } + .footer-section { + margin-top: auto; + } + .footer-row { + display: flex; + margin-bottom: 3px; + line-height: 22px; + justify-content: space-between; + } + .footer-item { + display: flex; + margin-right: 20px; + } + .footer-item .label { + font-weight: bold; + width: 80px; + font-size: 12px; + } + .footer-item .value { + min-width: 80px; + font-size: 12px; + } + .address-item .address-value { + min-width: 200px; + } + @media print { + body { + margin: 0; + padding: 0; + } + .print-page { + margin: 0; + padding: 10mm; + /* padding-left: 20mm; */ + page-break-inside: avoid; + page-break-after: always; + } + .print-page:last-child { + page-break-after: avoid; + } + } + </style> + </head> + <body> + `; + + // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈� + printData.value.forEach((item, index) => { + printContent += ` + <div class="print-page"> + <div class="delivery-note"> + <div class="header"> + <div class="company-name">榧庤瘹鐟炲疄涓氭湁闄愯矗浠诲叕鍙�</div> + <div class="document-title">闆跺敭鍙戣揣鍗�</div> + </div> + + <div class="info-section"> + <div class="info-row"> + <div> + <span class="label">鍙戣揣鏃ユ湡锛�</span> + <span class="value">${formatDate(item.createTime)}</span> + </div> + <div> + <span class="label">瀹㈡埛鍚嶇О锛�</span> + <span class="value">${item.supplierName || '寮犵埍鏈�'}</span> + </div> + </div> + <div class="info-row"> + <span class="label">鍗曞彿锛�</span> + <span class="value">${item.code || ''}</span> + </div> + </div> + + <div class="table-section"> + <table class="product-table"> + <thead> + <tr> + <th>浜у搧鍚嶇О</th> + <th>瑙勬牸鍨嬪彿</th> + <th>鍗曚綅</th> + <th>鍗曚环</th> + <th>闆跺敭鏁伴噺</th> + <th>闆跺敭閲戦</th> + </tr> + </thead> + <tbody> + <tr> + <td>${item.productCategory || '鐮傜伆鐮�'}</td> + <td>${item.specificationModel || '鏍囧噯'}</td> + <td>${item.unit || '鍧�'}</td> + <td>${item.taxInclusiveUnitPrice || '0'}</td> + <td>${item.inboundNum || '2000'}</td> + <td>${item.taxInclusiveTotalPrice || '0'}</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="label">鍚堣</td> + <td class="total-value"></td> + <td class="total-value"></td> + <td class="total-value"></td> + <td class="total-value">${item.inboundNum || '2000'}</td> + <td class="total-value">${item.taxInclusiveTotalPrice || '0'}</td> + </tr> + </tfoot> + </table> + </div> + + <div class="footer-section"> + <div class="footer-row"> + <div class="footer-item"> + <span class="label">鏀惰揣鐢佃瘽锛�</span> + <span class="value"></span> + </div> + <div class="footer-item"> + <span class="label">鏀惰揣浜猴細</span> + <span class="value"></span> + </div> + <div class="footer-item address-item"> + <span class="label">鏀惰揣鍦板潃锛�</span> + <span class="value address-value"></span> + </div> + </div> + <div class="footer-row"> + <div class="footer-item"> + <span class="label">鎿嶄綔鍛橈細</span> + <span class="value">${userStore.nickname || '鎾曞紑鍓�'}</span> + </div> + <div class="footer-item"> + <span class="label">鎵撳嵃鏃ユ湡锛�</span> + <span class="value">${formatDateTime(new Date())}</span> + </div> + </div> + </div> + </div> + </div> + `; + }); + + printContent += ` + </body> + </html> + `; + + // 鍐欏叆鍐呭鍒版柊绐楀彛 + printWindow.document.write(printContent); + printWindow.document.close(); + + // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗� + printWindow.onload = () => { + setTimeout(() => { + printWindow.print(); + printWindow.close(); + printPreviewVisible.value = false; + }, 500); + }; +}; + + + +// 鏍煎紡鍖栨棩鏈� +const formatDate = (dateString) => { + if (!dateString) return getCurrentDate(); + const date = new Date(dateString); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const day = String(date.getDate()).padStart(2, "0"); + return `${year}/${month}/${day}`; +}; + +// 鏍煎紡鍖栨棩鏈熸椂闂� +const formatDateTime = (date) => { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const day = String(date.getDate()).padStart(2, "0"); + const hours = String(date.getHours()).padStart(2, "0"); + const minutes = String(date.getMinutes()).padStart(2, "0"); + const seconds = String(date.getSeconds()).padStart(2, "0"); + return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; +}; // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD function getCurrentDate() { const today = new Date(); @@ -281,4 +684,171 @@ }); </script> -<style scoped lang="scss"></style> +<style scoped lang="scss"> +.print-preview-dialog { + .el-dialog__body { + padding: 0; + max-height: 80vh; + overflow-y: auto; + } +} + +.print-preview-container { + .print-preview-header { + padding: 15px; + border-bottom: 1px solid #e4e7ed; + text-align: center; + + .el-button { + margin: 0 10px; + } + } + + .print-preview-content { + padding: 20px; + background-color: #f5f5f5; + min-height: 400px; +} +} + +.print-page { + width: 220mm; + height: 90mm; + padding: 10mm; + margin: 0 auto; + background: white; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + margin-bottom: 10px; + box-sizing: border-box; +} + +.delivery-note { + width: 100%; + height: 100%; + font-family: "SimSun", serif; + font-size: 10px; + line-height: 1.2; + display: flex; + flex-direction: column; +} + +.header { + text-align: center; + margin-bottom: 8px; + + .company-name { + font-size: 18px; + font-weight: bold; + margin-bottom: 4px; + } + + .document-title { + font-size: 16px; + font-weight: bold; + } +} + +.info-section { + margin-bottom: 8px; + display: flex; + justify-content: space-between; + align-items: center; + + .info-row { + line-height: 20px; + + .label { + font-weight: bold; + width: 60px; + font-size: 14px; + } + + .value { + margin-right: 20px; + min-width: 80px; + font-size: 14px; + } + } +} + +.table-section { + margin-bottom: 4px; + flex: 1; + + .product-table { + width: 100%; + border-collapse: collapse; + border: 1px solid #000; + + th, td { + border: 1px solid #000; + padding: 6px; + text-align: center; + font-size: 14px; + line-height: 1.4; + } + + th { + font-weight: bold; + } + + .total-label { + text-align: right; + font-weight: bold; + } + + .total-value { + font-weight: bold; + } + } +} + +.footer-section { + .footer-row { + display: flex; + margin-bottom: 3px; + line-height: 20px; + justify-content: space-between; + + .footer-item { + display: flex; + margin-right: 20px; + + .label { + font-weight: bold; + width: 80px; + font-size: 14px; + } + + .value { + min-width: 80px; + font-size: 14px; + } + + &.address-item { + .address-value { + min-width: 200px; + } + } + } + } +} + +@media print { + .app-container { + display: none; + } + + .print-page { + box-shadow: none; + margin: 0; + padding: 10mm; + padding-left: 20mm; + page-break-inside: avoid; + page-break-after: always; + } + .print-page:last-child { + page-break-after: avoid; + } +} +</style> -- Gitblit v1.9.3