From 8efb46289cd626dfc461edc0e8dfa81d9cc6a9f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Sat, 7 Feb 2026 14:36:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(wms):=20=E6=96=B0=E5=A2=9E=E9=92=A2?= =?UTF-8?q?=E5=8D=B7=E5=8E=BB=E5=90=91=E6=A0=87=E7=AD=BE=E5=92=8C=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E4=BF=A1=E6=81=AF=E6=9F=A5=E7=9C=8B=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增钢卷去向标签(WhereTag)及相关配置 - 在base.vue中添加钢卷去向选择功能 - 新增异常信息查看弹窗组件(abnormal.vue) - 新增多个仓库视图页面(mini.vue, scrap.vue等) - 在发货单组件中新增Excel导出功能 - 优化标签打印功能,支持多种标签类型 - 修复报表查询时间参数问题 --- klp-ui/package.json | 1 + klp-ui/src/views/wms/coil/allocation.vue | 44 ++ .../wms/coil/panels/LabelRender/WhereTag.vue | 297 +++++++++++ .../wms/coil/panels/LabelRender/index.vue | 48 +- klp-ui/src/views/wms/coil/panels/abnormal.vue | 267 ++++++++++ klp-ui/src/views/wms/coil/panels/base.vue | 66 ++- klp-ui/src/views/wms/coil/views/jishu.vue | 28 ++ klp-ui/src/views/wms/coil/views/mini.vue | 28 ++ klp-ui/src/views/wms/coil/views/return.vue | 28 ++ klp-ui/src/views/wms/coil/views/scrap.vue | 28 ++ klp-ui/src/views/wms/coil/where.vue | 41 ++ .../views/wms/delivery/components/wayBill.vue | 466 ++++++++++++++++++ klp-ui/src/views/wms/report/zha_.vue | 2 + klp-ui/src/views/wms/report/zinc_.vue | 2 + 14 files changed, 1331 insertions(+), 15 deletions(-) create mode 100644 klp-ui/src/views/wms/coil/allocation.vue create mode 100644 klp-ui/src/views/wms/coil/panels/LabelRender/WhereTag.vue create mode 100644 klp-ui/src/views/wms/coil/panels/abnormal.vue create mode 100644 klp-ui/src/views/wms/coil/views/jishu.vue create mode 100644 klp-ui/src/views/wms/coil/views/mini.vue create mode 100644 klp-ui/src/views/wms/coil/views/return.vue create mode 100644 klp-ui/src/views/wms/coil/views/scrap.vue create mode 100644 klp-ui/src/views/wms/coil/where.vue diff --git a/klp-ui/package.json b/klp-ui/package.json index 89204e7f..3aa6eea9 100644 --- a/klp-ui/package.json +++ b/klp-ui/package.json @@ -48,6 +48,7 @@ "dom-to-image": "^2.6.0", "echarts": "5.4.0", "element-ui": "2.15.12", + "exceljs": "^4.4.0", "file-saver": "2.0.5", "flv.js": "^1.6.2", "fuse.js": "6.4.3", diff --git a/klp-ui/src/views/wms/coil/allocation.vue b/klp-ui/src/views/wms/coil/allocation.vue new file mode 100644 index 00000000..700d82fd --- /dev/null +++ b/klp-ui/src/views/wms/coil/allocation.vue @@ -0,0 +1,44 @@ + + + \ No newline at end of file diff --git a/klp-ui/src/views/wms/coil/panels/LabelRender/WhereTag.vue b/klp-ui/src/views/wms/coil/panels/LabelRender/WhereTag.vue new file mode 100644 index 00000000..372d849e --- /dev/null +++ b/klp-ui/src/views/wms/coil/panels/LabelRender/WhereTag.vue @@ -0,0 +1,297 @@ + + + + + diff --git a/klp-ui/src/views/wms/coil/panels/LabelRender/index.vue b/klp-ui/src/views/wms/coil/panels/LabelRender/index.vue index 960de4bc..76f239df 100644 --- a/klp-ui/src/views/wms/coil/panels/LabelRender/index.vue +++ b/klp-ui/src/views/wms/coil/panels/LabelRender/index.vue @@ -3,23 +3,29 @@
+ @@ -40,6 +46,7 @@ import { PDFDocument } from 'pdf-lib'; import MaterialTag from './MaterialTag.vue'; import OuterTagPreview from './OuterTagPreview.vue'; import GalvanizedTag from './GalvanizedTag.vue'; +import WhereTag from './WhereTag.vue'; // import SampleTagPreview from './SampleTagPreview.vue'; // import ForgeTagPreview from './ForgeTagPreview.vue'; // import SaltSprayTagPreview from './SaltSprayTagPreview.vue'; @@ -50,6 +57,7 @@ export default { MaterialTag, OuterTagPreview, GalvanizedTag, + WhereTag, // SampleTagPreview, // ForgeTagPreview, // SaltSprayTagPreview, @@ -57,6 +65,32 @@ export default { data() { return { labelType: '2', + tagSizeMap: { + '2': { + width: 100, + height: 80, + }, + '3': { + width: 180, + height: 100, + }, + '4': { + width: 180, + height: 100, + }, + 'where': { + width: 100, + height: 80, + }, + } + } + }, + computed: { + tagType() { + if (this.forceSpecialTag) { + return this.forceSpecialTag; + } + return this.labelType; } }, props: { @@ -64,6 +98,10 @@ export default { // type: String, // required: true, // }, + forceSpecialTag: { + type: String, + required: false, + }, content: { type: Object, required: true, @@ -139,8 +177,8 @@ export default { // 2. 计算纸张尺寸(与批量导出保持一致) // 根据 labelType 判断:'2' 是材料标签(100x80,宽100高80),'3' 是外标(180x100) const isMaterial = this.labelType === '2'; - const paperWidthMm = isMaterial ? 100 : 180; - const paperHeightMm = isMaterial ? 80 : 100; + const paperWidthMm = this.tagSizeMap[this.tagType].width || 100; + const paperHeightMm = this.tagSizeMap[this.tagType].height || 80; // 使用合适的scale值生成高清Canvas(但不超过纸张尺寸) const canvasScale = 3; // 提高清晰度(单张打印) diff --git a/klp-ui/src/views/wms/coil/panels/abnormal.vue b/klp-ui/src/views/wms/coil/panels/abnormal.vue new file mode 100644 index 00000000..20bf52e5 --- /dev/null +++ b/klp-ui/src/views/wms/coil/panels/abnormal.vue @@ -0,0 +1,267 @@ + + + diff --git a/klp-ui/src/views/wms/coil/panels/base.vue b/klp-ui/src/views/wms/coil/panels/base.vue index be1d1fde..90929464 100644 --- a/klp-ui/src/views/wms/coil/panels/base.vue +++ b/klp-ui/src/views/wms/coil/panels/base.vue @@ -146,7 +146,17 @@ + + + + @@ -335,6 +349,7 @@ import MutiSelect from "@/components/MutiSelect"; import html2canvas from 'html2canvas'; import { PDFDocument } from 'pdf-lib'; import { listUser } from "@/api/system/user"; +import AbnormalList from "./abnormal.vue"; export default { name: "MaterialCoil", @@ -354,8 +369,9 @@ export default { MemoInput, MutiSelect, OuterTagPreview, + AbnormalList, }, - dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status'], + dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status', 'warehouse_sync'], props: { qrcode: { type: Boolean, @@ -405,6 +421,14 @@ export default { type: Boolean, default: false, }, + editNext: { + type: Boolean, + default: false, + }, + forceSpecialTag: { + type: String, + required: false, + }, }, data() { return { @@ -568,6 +592,8 @@ export default { ], title: '详细信息' }, + abnormalOpen: false, + currentCoilId: '', userList: [], }; }, @@ -598,6 +624,24 @@ export default { this.userList = res.rows || []; }); }, + handleNextWarehouseChange(row) { + if (!this.editNext) { + return; + } + updateMaterialCoilSimple(row).then(res => { + if (res.code === 200) { + this.$message({ + message: '更新成功', + type: 'success', + }); + } else { + this.$message({ + message: res.msg || '更新失败', + type: 'error', + }); + } + }) + }, // 打印标签 handlePrintLabel(row) { const item = row.itemType === 'product' ? row.product : row.rawMaterial; @@ -701,12 +745,14 @@ export default { } }, handleAbnormal(row) { - this.$router.push({ - path: '/quality/detail', - query: { - coilId: row.coilId, - } - }) + // this.$router.push({ + // path: '/quality/detail', + // query: { + // coilId: row.coilId, + // } + // }) + this.currentCoilId = row.coilId; + this.abnormalOpen = true; }, // 取消按钮 cancel() { diff --git a/klp-ui/src/views/wms/coil/views/jishu.vue b/klp-ui/src/views/wms/coil/views/jishu.vue new file mode 100644 index 00000000..0971466b --- /dev/null +++ b/klp-ui/src/views/wms/coil/views/jishu.vue @@ -0,0 +1,28 @@ + + + \ No newline at end of file diff --git a/klp-ui/src/views/wms/coil/views/mini.vue b/klp-ui/src/views/wms/coil/views/mini.vue new file mode 100644 index 00000000..1376b45e --- /dev/null +++ b/klp-ui/src/views/wms/coil/views/mini.vue @@ -0,0 +1,28 @@ + + + \ No newline at end of file diff --git a/klp-ui/src/views/wms/coil/views/return.vue b/klp-ui/src/views/wms/coil/views/return.vue new file mode 100644 index 00000000..03c3c00d --- /dev/null +++ b/klp-ui/src/views/wms/coil/views/return.vue @@ -0,0 +1,28 @@ + + + \ No newline at end of file diff --git a/klp-ui/src/views/wms/coil/views/scrap.vue b/klp-ui/src/views/wms/coil/views/scrap.vue new file mode 100644 index 00000000..299be253 --- /dev/null +++ b/klp-ui/src/views/wms/coil/views/scrap.vue @@ -0,0 +1,28 @@ + + + \ No newline at end of file diff --git a/klp-ui/src/views/wms/coil/where.vue b/klp-ui/src/views/wms/coil/where.vue new file mode 100644 index 00000000..5ccea778 --- /dev/null +++ b/klp-ui/src/views/wms/coil/where.vue @@ -0,0 +1,41 @@ + + + \ No newline at end of file diff --git a/klp-ui/src/views/wms/delivery/components/wayBill.vue b/klp-ui/src/views/wms/delivery/components/wayBill.vue index aff4a514..e18961b9 100644 --- a/klp-ui/src/views/wms/delivery/components/wayBill.vue +++ b/klp-ui/src/views/wms/delivery/components/wayBill.vue @@ -186,6 +186,7 @@
保存为图片 打印 + 导出Excel @@ -194,6 +195,8 @@ import domtoimage from 'dom-to-image'; import { PDFDocument } from 'pdf-lib'; import html2canvas from 'html2canvas'; +import * as XLSX from 'xlsx'; +import ExcelJS from 'exceljs'; export default { props: { @@ -289,6 +292,26 @@ export default { } return pageRows; }, + readWaybill() { + const file = this.$refs.file.files[0]; + if (!file) { + return; + } + const reader = new FileReader(); + reader.readAsArrayBuffer(file); + reader.onload = (e) => { + const data = e.target.result; + const wb = XLSX.read(data, { type: 'array' }); + const ws = wb.Sheets[wb.SheetNames[0]]; + const json = XLSX.utils.sheet_to_eth(ws); + console.log(json); + // this.localWaybillDetails = json; + // this.refreshPagination(); + }; + reader.onerror = (e) => { + console.error('读取文件失败:', e); + }; + }, refreshPagination() { const src = Array.isArray(this.localWaybillDetails) ? this.localWaybillDetails : []; this.totalPages = Math.max(1, Math.ceil(src.length / this.perPage)); @@ -460,6 +483,449 @@ export default { a.click(); document.body.removeChild(a); } + }, + async exportExcelByXLSX() { + try { + // ===== 1. 构建真实数据(替换占位符,使用实际明细)===== + const headerData = [ + ['科伦普发货单'], // 标题行(r=0) + [ + `收货单位:${this.localWaybill.consigneeUnit || ''}`, + undefined, undefined, undefined, + `${this.localWaybill.deliveryYear || ''}年${this.localWaybill.deliveryMonth || ''}月${this.localWaybill.deliveryDay || ''}日`, + undefined, undefined, undefined, + `发货单位:${this.localWaybill.senderUnit || ''}` + ], // 收货/日期/发货单位行(r=1) + [ + `负责人:${this.localWaybill.principal || ''}`, + undefined, undefined, + `电话:${this.localWaybill.principalPhone || ''}`, + undefined, undefined, + `合同号:${this.localWaybill.contractCode || ''}`, + undefined, undefined, + `车牌:${this.localWaybill.licensePlate || ''}` + ], // 负责人/电话/合同号/车牌行(r=2) + ["品名", '切边', '包装', '仓库位置', '结算', '原料厂家', '卷号', '规格', '材质', '重量(t)', '单价', '备注'], // 表格表头(r=3) + ]; + + // 表格明细行(替换原有E1/F1等占位符,使用真实明细) + const detailRows = this.displayWaybillDetails.map(item => [ + item.productName || '', + item.edgeType || '', + item.packageType || '', + item.actualWarehouseName || '', + item.settlementType || '', + item.rawMaterialFactory || '', + item.coilNumber || '', + item.specification || '', + item.material || '', + item.weight || '', + item.unitPrice || '', + item.remark || '' + ]); + + // 底部备注/取货地点/签名栏 + const footerData = [ + [ + '1、品名:冷硬钢卷(酸连轧)、冷轧钢卷(脱脂退火火拉矫)、镀锌卷板,镀锌管料(镀锌分剪料);2、切边:净边/毛边;3、包装:裸包:周三径四;简包1:周三径四内外护角;简包2:周三径四+防锈纸;普包:周三径四+内外护角+防锈纸+端护板;精包1:周三径四+内外护角+防锈纸+薄膜+端护板+内外护板;精包2:周三径四+内外护角+防锈纸+薄膜+端护板+内外护板+木托。' + ], // 备注行(r=3+明细行数) + [`取货地点:${this.localWaybill.pickupLocation || ''}`], // 取货地点行 + [ + `发货:${this.localWaybill.deliveryman || ''}`, + undefined, undefined, undefined, + `司机:${this.localWaybill.driver || ''}`, + undefined, undefined, undefined, + `磅房:${this.localWaybill.weightRoom || ''}` + ] // 签名栏行 + ]; + + // 合并所有数据行 + const data = [...headerData, ...detailRows, ...footerData]; + const titleRowIdx = 0; // 标题行索引 + const headerRow1Idx = 1; // 收货单位行索引 + const headerRow2Idx = 2; // 负责人行索引 + const tableHeaderIdx = 3; // 表格表头行索引 + const remarkRowIdx = 3 + detailRows.length; // 备注行索引 + const pickupRowIdx = remarkRowIdx + 1; // 取货地点行索引 + const footerRowIdx = pickupRowIdx + 1; // 签名栏行索引 + + // ===== 2. 创建工作表并配置基础合并 ===== + const ws = XLSX.utils.aoa_to_sheet(data); + ws["!cellStyles"] = true; // 必须开启才能设置单元格样式 + ws["!merges"] = [ + { s: { c: 0, r: titleRowIdx }, e: { c: 11, r: titleRowIdx } }, // 标题跨列合并(A1-L1) + { s: { c: 0, r: headerRow1Idx }, e: { c: 3, r: headerRow1Idx } }, // 收货单位(A2-D2) + { s: { c: 4, r: headerRow1Idx }, e: { c: 7, r: headerRow1Idx } }, // 日期(E2-H2) + { s: { c: 8, r: headerRow1Idx }, e: { c: 11, r: headerRow1Idx } }, // 发货单位(I2-L2) + { s: { c: 0, r: headerRow2Idx }, e: { c: 2, r: headerRow2Idx } }, // 负责人(A3-C3) + { s: { c: 3, r: headerRow2Idx }, e: { c: 5, r: headerRow2Idx } }, // 电话(D3-F3) + { s: { c: 6, r: headerRow2Idx }, e: { c: 8, r: headerRow2Idx } }, // 合同号(G3-I3) + { s: { c: 9, r: headerRow2Idx }, e: { c: 11, r: headerRow2Idx } }, // 车牌(J3-L3) + { s: { c: 0, r: remarkRowIdx }, e: { c: 11, r: remarkRowIdx } }, // 备注跨列合并(A*_L*) + { s: { c: 0, r: pickupRowIdx }, e: { c: 11, r: pickupRowIdx } }, // 取货地点跨列合并 + { s: { c: 0, r: footerRowIdx }, e: { c: 3, r: footerRowIdx } }, // 发货(A*_D*) + { s: { c: 4, r: footerRowIdx }, e: { c: 7, r: footerRowIdx } }, // 司机(E*_H*) + { s: { c: 8, r: footerRowIdx }, e: { c: 11, r: footerRowIdx } }, // 磅房(I*_L*) + ]; + + // ===== 3. 配置列宽(完全匹配Web端表格列宽)===== + ws['!cols'] = [ + { wpx: 70 }, // 品名 + { wpx: 40 }, // 切边 + { wpx: 50 }, // 包装 + { wpx: 90 }, // 仓库位置 + { wpx: 60 }, // 结算 + { wpx: 70 }, // 原料厂家 + { wpx: 110 }, // 卷号 + { wpx: 90 }, // 规格 + { wpx: 80 }, // 材质 + { wpx: 70 }, // 重量(t) + { wpx: 50 }, // 单价 + { wpx: 130 }, // 备注 + ]; + + // ===== 4. 逐个配置单元格样式(核心:匹配Web端)===== + // 工具函数:生成单元格样式 + const createCellStyle = (options = {}) => { + const defaultStyle = { + font: { + name: "SimSun", // 宋体(匹配Web端SimSun) + sz: options.sz || 16, // 默认字号16px(表格单元格) + bold: options.bold ?? true, // 默认加粗(匹配Web端font-weight:900) + }, + alignment: { + horizontal: options.horizontal || "center", // 默认水平居中 + vertical: options.vertical || "center", // 默认垂直居中 + wrapText: options.wrapText || false, // 默认不换行 + }, + border: options.border || { + top: { style: "thin", color: { rgb: "000000" } }, + bottom: { style: "thin", color: { rgb: "000000" } }, + left: { style: "thin", color: { rgb: "000000" } }, + right: { style: "thin", color: { rgb: "000000" } }, + }, + }; + return defaultStyle; + }; + + // 4.1 标题单元格(A1):24px、宋体、加粗、居中、无边框 + const titleCell = XLSX.utils.encode_cell({ r: titleRowIdx, c: 0 }); + ws[titleCell].s = { + ...createCellStyle({ + sz: 24, // Web端title的24px + border: null, // 标题无边框 + }), + }; + + // 4.2 头部信息行(收货单位/负责人行):18px、宋体、加粗、居中、无边框 + const headerCells = [ + // 收货单位行(A2/E2/I2) + XLSX.utils.encode_cell({ r: headerRow1Idx, c: 0 }), + XLSX.utils.encode_cell({ r: headerRow1Idx, c: 4 }), + XLSX.utils.encode_cell({ r: headerRow1Idx, c: 8 }), + // 负责人行(A3/D3/G3/J3) + XLSX.utils.encode_cell({ r: headerRow2Idx, c: 0 }), + XLSX.utils.encode_cell({ r: headerRow2Idx, c: 3 }), + XLSX.utils.encode_cell({ r: headerRow2Idx, c: 6 }), + XLSX.utils.encode_cell({ r: headerRow2Idx, c: 9 }), + ]; + headerCells.forEach(cellAddr => { + if (ws[cellAddr]) { + ws[cellAddr].s = { + ...createCellStyle({ + sz: 18, // Web端label的18px + border: null, // 头部信息无边框 + }), + }; + } + }); + + // 4.3 表格表头(A4-L4):16px、宋体、加粗、居中、带边框 + for (let c = 0; c < 12; c++) { + const cellAddr = XLSX.utils.encode_cell({ r: tableHeaderIdx, c }); + if (ws[cellAddr]) { + ws[cellAddr].s = createCellStyle({ sz: 16 }); // 匹配Web表格16px + } + } + + // 4.4 表格明细行:16px、宋体、加粗、居中、带边框 + for (let r = tableHeaderIdx + 1; r < remarkRowIdx; r++) { + for (let c = 0; c < 12; c++) { + const cellAddr = XLSX.utils.encode_cell({ r, c }); + if (ws[cellAddr]) { + ws[cellAddr].s = createCellStyle({ sz: 16 }); + } + } + } + + // 4.5 备注行:18px、宋体、加粗、居中、自动换行、无边框 + const remarkCell = XLSX.utils.encode_cell({ r: remarkRowIdx, c: 0 }); + if (ws[remarkCell]) { + ws[remarkCell].s = { + ...createCellStyle({ + sz: 18, // Web端备注18px + wrapText: true, // 自动换行(匹配Web端text-align: justify) + border: null, // 备注无边框 + }), + }; + } + + // 4.6 取货地点行:18px、宋体、加粗、居中、无边框 + const pickupCell = XLSX.utils.encode_cell({ r: pickupRowIdx, c: 0 }); + if (ws[pickupCell]) { + ws[pickupCell].s = { + ...createCellStyle({ + sz: 18, // Web端取货地点18px + border: null, // 无边框 + }), + }; + } + + // 4.7 签名栏行:18px、宋体、加粗、居中、无边框 + const footerCells = [ + XLSX.utils.encode_cell({ r: footerRowIdx, c: 0 }), // 发货 + XLSX.utils.encode_cell({ r: footerRowIdx, c: 4 }), // 司机 + XLSX.utils.encode_cell({ r: footerRowIdx, c: 8 }), // 磅房 + ]; + footerCells.forEach(cellAddr => { + if (ws[cellAddr]) { + ws[cellAddr].s = { + ...createCellStyle({ + sz: 18, // Web端签名栏18px + border: null, // 无边框 + }), + }; + } + }); + + console.log(ws); + + // ===== 5. 生成Excel并下载 ===== + const wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, "科伦普发货单"); // 工作表名称更贴合业务 + + // 生成Excel文件(启用样式配置) + const excelBuffer = XLSX.write(wb, { + bookType: "xlsx", + type: "array", + cellStyles: true, // 必须开启才能导出样式 + sheetStubs: true + }); + const blob = new Blob([excelBuffer], { + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8", + }); + + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = `科伦普发货单_${this.waybill.waybillNo || Date.now()}.xlsx`; // 文件名更规范 + document.body.appendChild(link); + link.click(); + + // 清理资源 + setTimeout(() => { + document.body.removeChild(link); + URL.revokeObjectURL(url); + }, 100); + + } catch (error) { + console.error("Excel导出失败:", error); + this.$message.error("导出失败,请重试"); // 替换为Vue的message提示 + } + }, + async exportExcel() { + try { + // 1. 创建工作簿和工作表 + const workbook = new ExcelJS.Workbook(); + const worksheet = workbook.addWorksheet('科伦普发货单'); + worksheet.properties.defaultRowHeight = 25; // 设置默认行高(匹配Web端行高) + + // 2. 构建数据(复用原有业务数据) + const title = `科伦普发货单`; // 标题 + const header1 = { // 收货单位+日期+发货单位 + consignee: `收货单位:${this.localWaybill.consigneeUnit || ''}`, + date: `${this.localWaybill.deliveryYear || ''}年${this.localWaybill.deliveryMonth || ''}月${this.localWaybill.deliveryDay || ''}日`, + sender: `发货单位:${this.localWaybill.senderUnit || ''}` + }; + const header2 = { // 负责人+电话+合同号+车牌 + principal: `负责人:${this.localWaybill.principal || ''}`, + phone: `电话:${this.localWaybill.principalPhone || ''}`, + contract: `合同号:${this.localWaybill.contractCode || ''}`, + license: `车牌:${this.localWaybill.licensePlate || ''}` + }; + const tableHeader = ["品名", '切边', '包装', '仓库位置', '结算', '原料厂家', '卷号', '规格', '材质', '重量(t)', '单价', '备注']; // 表格表头 + const tableData = this.displayWaybillDetails.map(item => [ // 表格明细 + item.productName || '', + item.edgeType || '', + item.packageType || '', + item.actualWarehouseName || '', + item.settlementType || '', + item.rawMaterialFactory || '', + item.coilNumber || '', + item.specification || '', + item.material || '', + item.weight || '', + item.unitPrice || '', + item.remark || '' + ]); + const remark = '1、品名:冷硬钢卷(酸连轧)、冷轧钢卷(脱脂退火火拉矫)、镀锌卷板,镀锌管料(镀锌分剪料);2、切边:净边/毛边;3、包装:裸包:周三径四;简包1:周三径四内外护角;简包2:周三径四+防锈纸;普包:周三径四+内外护角+防锈纸+端护板;精包1:周三径四+内外护角+防锈纸+薄膜+端护板+内外护板;精包2:周三径四+内外护角+防锈纸+薄膜+端护板+内外护板+木托。'; + const pickupLocation = `取货地点:${this.localWaybill.pickupLocation || ''}`; + const footer = { // 签名栏 + deliveryman: `发货:${this.localWaybill.deliveryman || ''}`, + driver: `司机:${this.localWaybill.driver || ''}`, + weightRoom: `磅房:${this.localWaybill.weightRoom || ''}` + }; + + // 3. 写入数据到工作表(按行写入) + let rowIdx = 1; // exceljs行号从1开始 + // 3.1 标题行(第1行) + const titleCell = worksheet.getCell(`A${rowIdx}`); + titleCell.value = title; + worksheet.mergeCells(`A${rowIdx}:L${rowIdx}`); // 合并A1-L1 + // 3.2 收货单位行(第2行) + rowIdx++; + worksheet.getCell(`A${rowIdx}`).value = header1.consignee; + worksheet.getCell(`E${rowIdx}`).value = header1.date; + worksheet.getCell(`I${rowIdx}`).value = header1.sender; + worksheet.mergeCells(`A${rowIdx}:D${rowIdx}`); // 收货单位:A2-D2 + worksheet.mergeCells(`E${rowIdx}:H${rowIdx}`); // 日期:E2-H2 + worksheet.mergeCells(`I${rowIdx}:L${rowIdx}`); // 发货单位:I2-L2 + // 3.3 负责人行(第3行) + rowIdx++; + worksheet.getCell(`A${rowIdx}`).value = header2.principal; + worksheet.getCell(`D${rowIdx}`).value = header2.phone; + worksheet.getCell(`G${rowIdx}`).value = header2.contract; + worksheet.getCell(`J${rowIdx}`).value = header2.license; + worksheet.mergeCells(`A${rowIdx}:C${rowIdx}`); // 负责人:A3-C3 + worksheet.mergeCells(`D${rowIdx}:F${rowIdx}`); // 电话:D3-F3 + worksheet.mergeCells(`G${rowIdx}:I${rowIdx}`); // 合同号:G3-I3 + worksheet.mergeCells(`J${rowIdx}:L${rowIdx}`); // 车牌:J3-L3 + // 3.4 表格表头(第4行) + rowIdx++; + tableHeader.forEach((text, colIdx) => { + const colLetter = String.fromCharCode(65 + colIdx); // A=65, B=66... + worksheet.getCell(`${colLetter}${rowIdx}`).value = text; + }); + // 3.5 表格明细行 + tableData.forEach(item => { + rowIdx++; + item.forEach((text, colIdx) => { + const colLetter = String.fromCharCode(65 + colIdx); + worksheet.getCell(`${colLetter}${rowIdx}`).value = text; + }); + }); + // 3.6 备注行 + rowIdx++; + const remarkCell = worksheet.getCell(`A${rowIdx}`); + remarkCell.value = remark; + worksheet.mergeCells(`A${rowIdx}:L${rowIdx}`); // 合并A*_L* + // 3.7 取货地点行 + rowIdx++; + const pickupCell = worksheet.getCell(`A${rowIdx}`); + pickupCell.value = pickupLocation; + worksheet.mergeCells(`A${rowIdx}:L${rowIdx}`); // 合并A*_L* + // 3.8 签名栏行 + rowIdx++; + worksheet.getCell(`A${rowIdx}`).value = footer.deliveryman; + worksheet.getCell(`E${rowIdx}`).value = footer.driver; + worksheet.getCell(`I${rowIdx}`).value = footer.weightRoom; + worksheet.mergeCells(`A${rowIdx}:D${rowIdx}`); // 发货:A*_D* + worksheet.mergeCells(`E${rowIdx}:H${rowIdx}`); // 司机:E*_H* + worksheet.mergeCells(`I${rowIdx}:L${rowIdx}`); // 磅房:I*_L* + + // 4. 配置列宽(完全匹配Web端) + const columnWidths = [70, 40, 50, 90, 60, 70, 110, 90, 80, 70, 50, 130]; + worksheet.columns = columnWidths.map((width, idx) => ({ + key: `col${idx + 1}`, + width: width / 5 // exceljs的width单位是字符宽度,转换为px(约1px=0.072字符) + })); + + // 5. 配置样式(核心:匹配Web端) + // 工具函数:设置单元格样式 + const setCellStyle = (cell, options = {}) => { + // 默认样式:宋体、加粗、居中 + cell.font = { + name: 'SimSun', // 宋体(匹配Web端) + size: options.size || 16, // 默认16px(表格单元格) + bold: options.bold ?? true // 默认加粗 + }; + cell.alignment = { + horizontal: options.horizontal || 'left', // 水平居中 + vertical: options.vertical || 'middle', // 垂直居中 + wrapText: options.wrapText || false // 自动换行 + }; + // 边框:表格单元格带边框,其他区域无边框 + if (options.border) { + cell.border = { + top: { style: 'thin', color: { argb: 'FF000000' } }, + bottom: { style: 'thin', color: { argb: 'FF000000' } }, + left: { style: 'thin', color: { argb: 'FF000000' } }, + right: { style: 'thin', color: { argb: 'FF000000' } } + }; + } else { + cell.border = null; // 无边框 + } + }; + + // 5.1 标题样式(24px、宋体、加粗、居中、无边框) + setCellStyle(worksheet.getCell('A1'), { size: 24, border: false, horizontal: 'center' }); + // 5.2 头部信息样式(18px、宋体、加粗、居中、无边框) + setCellStyle(worksheet.getCell(`A2`), { size: 18, border: false }); + setCellStyle(worksheet.getCell(`E2`), { size: 18, border: false }); + setCellStyle(worksheet.getCell(`I2`), { size: 18, border: false }); + setCellStyle(worksheet.getCell(`A3`), { size: 18, border: false }); + setCellStyle(worksheet.getCell(`D3`), { size: 18, border: false }); + setCellStyle(worksheet.getCell(`G3`), { size: 18, border: false }); + setCellStyle(worksheet.getCell(`J3`), { size: 18, border: false }); + // 5.3 表格表头样式(16px、宋体、加粗、居中、带边框) + for (let col = 0; col < 12; col++) { + const colLetter = String.fromCharCode(65 + col); + setCellStyle(worksheet.getCell(`${colLetter}4`), { size: 16, border: true, horizontal: 'center' }); + } + // 5.4 表格明细样式(16px、宋体、加粗、居中、带边框) + for (let r = 5; r < rowIdx - 2; r++) { // 明细行范围:第5行到备注行前一行 + for (let col = 0; col < 12; col++) { + const colLetter = String.fromCharCode(65 + col); + setCellStyle(worksheet.getCell(`${colLetter}${r}`), { size: 16, border: true, horizontal: 'center' }); + } + } + // 5.5 备注样式(18px、宋体、加粗、居中、自动换行、无边框) + setCellStyle(remarkCell, { size: 18, border: false, wrapText: true }); + // 5.6 取货地点样式(18px、宋体、加粗、居中、无边框) + setCellStyle(pickupCell, { size: 18, border: false }); + // 5.7 签名栏样式(18px、宋体、加粗、居中、无边框) + setCellStyle(worksheet.getCell(`A${rowIdx}`), { size: 18, border: false }); + setCellStyle(worksheet.getCell(`E${rowIdx}`), { size: 18, border: false }); + setCellStyle(worksheet.getCell(`I${rowIdx}`), { size: 18, border: false }); + + // 第一行的行高 + const row1 = worksheet.getRow(1); + row1.height = 30; + // 备注行的行高 + const remarkRow = worksheet.getRow(12); + remarkRow.height = 100; + + // 6. 生成Excel文件并下载 + const buffer = await workbook.xlsx.writeBuffer(); // 生成二进制buffer + const blob = new Blob([buffer], { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = `科伦普发货单_${this.waybill.waybillNo || Date.now()}.xlsx`; + document.body.appendChild(link); + link.click(); + // 清理资源 + setTimeout(() => { + document.body.removeChild(link); + URL.revokeObjectURL(url); + }, 100); + + } catch (error) { + console.error('Excel导出失败:', error); + this.$message.error('导出失败,请重试'); + } } } } diff --git a/klp-ui/src/views/wms/report/zha_.vue b/klp-ui/src/views/wms/report/zha_.vue index e4554d6e..cce07f00 100644 --- a/klp-ui/src/views/wms/report/zha_.vue +++ b/klp-ui/src/views/wms/report/zha_.vue @@ -205,6 +205,8 @@ export default { } listCoilWithIds({ ...this.queryParams, + byCreateTimeStart: undefined, + byCreateTimeEnd: undefined, coilIds: coilIds, }).then(res => { this.list = res.rows diff --git a/klp-ui/src/views/wms/report/zinc_.vue b/klp-ui/src/views/wms/report/zinc_.vue index 6af79f67..c8df2f6c 100644 --- a/klp-ui/src/views/wms/report/zinc_.vue +++ b/klp-ui/src/views/wms/report/zinc_.vue @@ -205,6 +205,8 @@ export default { } listCoilWithIds({ ...this.queryParams, + byCreateTimeStart: undefined, + byCreateTimeEnd: undefined, coilIds: coilIds, }).then(res => { this.list = res.rows