printStockEnterHt.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <template>
  2. <ele-modal
  3. title="入库单"
  4. :visible.sync="QRvisible"
  5. v-if="QRvisible"
  6. width="1100px"
  7. @close="close"
  8. >
  9. <div id="printSectionHt">
  10. <div
  11. v-for="(rowItem, idx) in formData"
  12. :key="rowItem.id || idx"
  13. style="
  14. font-family: SimSun, serif;
  15. padding: 20px;
  16. width: 24cm;
  17. min-height: 14cm;
  18. margin: 0 auto;
  19. box-sizing: border-box;
  20. page-break-after: always;
  21. "
  22. >
  23. <!-- 入库单标题 -->
  24. <div style="text-align: center; margin-bottom: 20px;">
  25. <h2 style="margin: 0; font-size: 24px; font-weight: bold;">{{ groupName }}入库单</h2>
  26. </div>
  27. <!-- 供应商/客户信息 -->
  28. <div style="margin-bottom: 20px; width: 100%;">
  29. <div style="width: 100%; display: flex;">
  30. <div style="width: 40%;">
  31. 供应商名称:{{ rowItem.extInfo?.supplierName || '' }}
  32. </div>
  33. <div style="width: 30%;">
  34. 日期:{{ rowItem.storageTime || '' }}
  35. </div>
  36. <div style="width: 30%;">
  37. 编号:{{ rowItem.bizNo || '' }}
  38. </div>
  39. </div>
  40. </div>
  41. <!-- 入库物品表格 -->
  42. <table
  43. border="1"
  44. cellspacing="0"
  45. style="
  46. width: 100%;
  47. border-collapse: collapse;
  48. font-size: 14px;
  49. "
  50. >
  51. <thead>
  52. <tr>
  53. <th style="border: 1px solid #000; padding: 4px; text-align: center; width: 5%;">编号</th>
  54. <th style="border: 1px solid #000; padding: 4px; text-align: center; width: 20%;">型号规格</th>
  55. <th v-if="rowItem.bizType == 6" style="border: 1px solid #000; padding: 4px; text-align: center; width: 12%;">客户</th>
  56. <th style="border: 1px solid #000; padding: 4px; text-align: center; width: 8%;">颜色</th>
  57. <th style="border: 1px solid #000; padding: 4px; text-align: center; width: 8%;">单位</th>
  58. <th style="border: 1px solid #000; padding: 4px; text-align: center; width: 8%;">入库数量</th>
  59. <th style="border: 1px solid #000; padding: 4px; text-align: center; width: 10%;">批次号</th>
  60. <th style="border: 1px solid #000; padding: 4px; text-align: center; width: 8%;">单价</th>
  61. <th style="border: 1px solid #000; padding: 4px; text-align: center; width: 10%;">金额</th>
  62. </tr>
  63. </thead>
  64. <tbody>
  65. <tr v-for="(row, index) in rowItem.outInDetailList" :key="index">
  66. <td style="border: 1px solid #000; padding: 4px; text-align: center;">{{ index + 1 }}</td>
  67. <td style="border: 1px solid #000; padding: 4px; text-align: center;">{{row.categoryModel || '' }}{{ row.categoryModel && row?.specification ? '/' : '' }}{{ row?.specification || '' }}</td>
  68. <td v-if="rowItem.bizType == 6" style="border: 1px solid #000; padding: 4px; text-align: center;">{{ row?.clientName || '' }}</td>
  69. <td style="border: 1px solid #000; padding: 4px; text-align: center;">{{ row?.colorKey || '' }}</td>
  70. <td style="border: 1px solid #000; padding: 4px; text-align: center;">{{ row?.measureUnit || '' }}</td>
  71. <td style="border: 1px solid #000; padding: 4px; text-align: center;">{{ row?.measureQuantity || '' }}</td>
  72. <td style="border: 1px solid #000; padding: 4px; text-align: center;">{{ row?.batchNo || '' }}</td>
  73. <td style="border: 1px solid #000; padding: 4px; text-align: center;"></td>
  74. <td style="border: 1px solid #000; padding: 4px; text-align: center;"></td>
  75. </tr>
  76. <!-- 合计行 -->
  77. <tr>
  78. <td style="border: 1px solid #000; padding: 4px; text-align: center;" colspan="2">合计:</td>
  79. <td v-if="rowItem.bizType == 6" style="border: 1px solid #000; padding: 4px; text-align: center;"></td>
  80. <td style="border: 1px solid #000; padding: 4px; text-align: center;"></td>
  81. <td style="border: 1px solid #000; padding: 4px; text-align: center;"></td>
  82. <td style="border: 1px solid #000; padding: 4px; text-align: center;">{{ getTotalAmount(rowItem) }}</td>
  83. <td style="border: 1px solid #000; padding: 4px; text-align: center;"></td>
  84. <td style="border: 1px solid #000; padding: 4px; text-align: center;"></td>
  85. <td style="border: 1px solid #000; padding: 4px; text-align: center;"></td>
  86. </tr>
  87. </tbody>
  88. </table>
  89. <!-- 签字区域 -->
  90. <div style="margin-top: 20px; display: flex; width: 100%;">
  91. <div style="width: 25%;">
  92. <strong>主管:</strong>{{ rowItem.verifyName || '' }}
  93. </div>
  94. <div style="width: 25%;">
  95. <strong>仓库:</strong>{{ warehouseMap[rowItem.id] || '' }}
  96. </div>
  97. <div style="width: 25%;">
  98. <strong>记账:</strong>{{ rowItem.extInfo?.createUserName || '' }}
  99. </div>
  100. <div style="width: 25%;">
  101. <strong>经手人:</strong>{{ rowItem?.fromUser || '' }}
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. <div slot="footer">
  107. <el-button type="primary" @click="exportExcel">导出</el-button>
  108. <el-button @click="print">打印预览</el-button>
  109. <el-button @click="close">关闭</el-button>
  110. </div>
  111. </ele-modal>
  112. </template>
  113. <script>
  114. import storageApi from '@/api/warehouseManagement';
  115. import { saveAs } from 'file-saver';
  116. export default {
  117. name: 'print',
  118. components: {},
  119. props: {
  120. groupName: {
  121. type: String,
  122. default: ''
  123. }
  124. },
  125. data() {
  126. return {
  127. QRvisible: false,
  128. formData: [],
  129. warehouseMap: {}
  130. };
  131. },
  132. methods: {
  133. // 计算单个入库单的总数量
  134. getTotalAmount(rowItem) {
  135. if (!rowItem?.outInDetailList || !Array.isArray(rowItem.outInDetailList)) {
  136. return 0;
  137. }
  138. return rowItem.outInDetailList.reduce((sum, row) => {
  139. const amount = parseFloat(row.measureQuantity || 0);
  140. return sum + (isNaN(amount) ? 0 : amount);
  141. }, 0);
  142. },
  143. async init(ids, rows) {
  144. console.log('ids~~', ids, rows);
  145. // 批量获取每个入库单的详情
  146. const res = await storageApi.getInboundDetailsByIds(ids);
  147. this.formData = res;
  148. // 构建仓库映射
  149. this.warehouseMap = {};
  150. rows.forEach((row) => {
  151. this.warehouseMap[row.id] = row.warehouseName || '';
  152. });
  153. console.log('formData', this.formData, this.warehouseMap);
  154. this.QRvisible = true;
  155. },
  156. close() {
  157. this.formData = [];
  158. this.warehouseMap = {};
  159. this.QRvisible = false;
  160. },
  161. print() {
  162. const printSection = document.getElementById('printSectionHt');
  163. // 创建打印任务
  164. const printWindow = window.open('', '_blank');
  165. printWindow.document.open();
  166. printWindow.document.write('<html><head><title>打印预览</title>');
  167. printWindow.document.write(
  168. '<style type="text/css">' +
  169. '@page { size: 24cm 14cm; margin: 0; }' +
  170. 'body { margin: 0; padding: 0; }' +
  171. 'div[style*="page-break-after"] { page-break-after: always; }' +
  172. '</style>'
  173. );
  174. printWindow.document.write('</head><body>');
  175. printWindow.document.write(printSection.innerHTML);
  176. printWindow.document.write('</body></html>');
  177. printWindow.document.close();
  178. printWindow.onload = function () {
  179. printWindow.print();
  180. };
  181. },
  182. exportExcel() {
  183. const border =
  184. 'border-top:1px solid #000;border-right:1px solid #000;border-bottom:1px solid #000;border-left:1px solid #000;';
  185. const cellBase = `${border}padding:4px;mso-number-format:"\\@";vertical-align:middle;text-align:center;mso-horizontal-align:center;`;
  186. const th = `${cellBase}font-weight:bold;font-family:'宋体';font-size:12pt;`;
  187. const td = `${cellBase}font-family:'宋体';font-size:11pt;`;
  188. const labelLeft = `${border}padding:4px;mso-number-format:"\\@";vertical-align:middle;text-align:left;mso-horizontal-align:left;font-family:'宋体';font-size:11pt;`;
  189. const title = `${this.groupName || ''}入库单`;
  190. // 遍历多个单据生成多个表格
  191. let tables = '';
  192. this.formData.forEach((rowItem) => {
  193. const list = rowItem.outInDetailList || [];
  194. const totalAmount = this.getTotalAmount(rowItem);
  195. const warehouseName = this.warehouseMap[rowItem.id] || '';
  196. const isBizType6 = rowItem.bizType == 6;
  197. const supplierValue = rowItem.extInfo?.supplierName || '';
  198. const totalCols = isBizType6 ? 9 : 8;
  199. const colWidths = isBizType6
  200. ? [55, 200, 100, 70, 70, 70, 80, 70, 80]
  201. : [55, 200, 70, 70, 70, 80, 70, 80];
  202. const colGroup = colWidths
  203. .map((w) => `<col width="${w}" style="width:${w}pt;" />`)
  204. .join('');
  205. const customerTh = isBizType6
  206. ? `<td align="center" valign="middle" style="${th}">客户</td>`
  207. : '';
  208. const rows = list
  209. .map(
  210. (item, index) => `
  211. <tr height="24" style="height:24pt;">
  212. <td align="center" valign="middle" style="${td}">${index + 1}</td>
  213. <td align="center" valign="middle" style="${td}">${item.categoryModel || ''}${item.categoryModel && item.specification ? '/' : ''}${item.specification || ''}</td>
  214. ${isBizType6 ? `<td align="center" valign="middle" style="${td}">${item.clientName || ''}</td>` : ''}
  215. <td align="center" valign="middle" style="${td}">${item.colorKey || ''}</td>
  216. <td align="center" valign="middle" style="${td}">${item.measureUnit || ''}</td>
  217. <td align="center" valign="middle" style="${td}">${item.measureQuantity || ''}</td>
  218. <td align="center" valign="middle" style="${td}">${item.batchNo || ''}</td>
  219. <td align="center" valign="middle" style="${td}"></td>
  220. <td align="center" valign="middle" style="${td}"></td>
  221. </tr>`
  222. )
  223. .join('');
  224. const customerEmpty = isBizType6
  225. ? '<td align="center" valign="middle" style="${td}"></td>'
  226. : '';
  227. tables += `
  228. <table border="1" cellspacing="0" cellpadding="0" align="center"
  229. style="border-collapse:collapse;border:1px solid #000;mso-border-alt:solid #000 0.5pt;font-family:'宋体';font-size:11pt;text-align:center;">
  230. <colgroup>${colGroup}</colgroup>
  231. <tr height="40" style="height:40pt;">
  232. <td colspan="${totalCols}" align="center" valign="middle" style="${border}padding:6px;text-align:center;font-family:'宋体';font-size:22pt;font-weight:bold;">${title}</td>
  233. </tr>
  234. <tr height="26" style="height:26pt;">
  235. <td colspan="${isBizType6 ? 3 : 3}" align="left" valign="middle" style="${labelLeft}">供应商名称:${supplierValue}</td>
  236. <td align="left" valign="middle" style="${labelLeft}">日期:${rowItem.storageTime || ''}</td>
  237. <td colspan="${isBizType6 ? 3 : 2}" align="left" valign="middle" style="${labelLeft}">编号:${rowItem.bizNo || ''}</td>
  238. </tr>
  239. <tr height="28" style="height:28pt;">
  240. <td align="center" valign="middle" style="${th}">编号</td>
  241. <td align="center" valign="middle" style="${th}">型号规格</td>
  242. ${customerTh}
  243. <td align="center" valign="middle" style="${th}">颜色</td>
  244. <td align="center" valign="middle" style="${th}">单位</td>
  245. <td align="center" valign="middle" style="${th}">入库数量</td>
  246. <td align="center" valign="middle" style="${th}">批次号</td>
  247. <td align="center" valign="middle" style="${th}">单价</td>
  248. <td align="center" valign="middle" style="${th}">金额</td>
  249. </tr>
  250. ${rows}
  251. <tr height="26" style="height:26pt;">
  252. <td colspan="2" align="center" valign="middle" style="${td};font-weight:bold;">合计:</td>
  253. ${customerEmpty}
  254. <td align="center" valign="middle" style="${td}"></td>
  255. <td align="center" valign="middle" style="${td}"></td>
  256. <td align="center" valign="middle" style="${td};font-weight:bold;">${totalAmount}</td>
  257. <td align="center" valign="middle" style="${td}"></td>
  258. <td align="center" valign="middle" style="${td}"></td>
  259. <td align="center" valign="middle" style="${td}"></td>
  260. </tr>
  261. <tr height="28" style="height:28pt;">
  262. <td align="left" valign="middle" style="${labelLeft}">主管:${rowItem.verifyName || ''}</td>
  263. <td align="left" valign="middle" style="${labelLeft}">仓库:${warehouseName}</td>
  264. <td align="left" valign="middle" style="${labelLeft}">记账:${rowItem.extInfo?.createUserName || ''}</td>
  265. <td colspan="${isBizType6 ? 6 : 5}" align="left" valign="middle" style="${labelLeft}">经手人:${rowItem.fromUser || ''}</td>
  266. </tr>
  267. </table>
  268. <br style="mso-special-character:line-break;page-break-before:always" />`;
  269. });
  270. const html = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">
  271. <head>
  272. <meta charset="UTF-8" />
  273. <style>
  274. br { mso-data-placement: same-cell; }
  275. table { mso-displayed-decimal-separator:"."; mso-displayed-thousand-separator:","; }
  276. td { mso-ignore:padding; }
  277. </style>
  278. <!--[if gte mso 9]><xml>
  279. <x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
  280. <x:Name>${title}</x:Name>
  281. <x:WorksheetOptions>
  282. <x:DefaultRowHeight>260</x:DefaultRowHeight>
  283. <x:Print><x:ValidPrinterInfo/><x:HorizontalResolution>600</x:HorizontalResolution><x:VerticalResolution>600</x:VerticalResolution></x:Print>
  284. <x:Selected/>
  285. <x:DoNotDisplayGridlines/>
  286. </x:WorksheetOptions>
  287. </x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook>
  288. </xml><![endif]-->
  289. </head>
  290. <body>${tables}</body></html>`;
  291. const blob = new Blob(['\uFEFF' + html], {
  292. type: 'application/vnd.ms-excel;charset=utf-8'
  293. });
  294. const firstBizNo = this.formData[0]?.bizNo || '';
  295. const suffix = this.formData.length > 1 ? `等${this.formData.length}条` : firstBizNo;
  296. saveAs(blob, `${title}_${suffix}.xls`);
  297. }
  298. }
  299. };
  300. </script>
  301. <style scoped lang="scss">
  302. table {
  303. border-collapse: collapse;
  304. }
  305. th, td {
  306. border: 1px solid #000;
  307. text-align: center;
  308. padding: 8px;
  309. }
  310. @media print {
  311. .no-print {
  312. display: none;
  313. }
  314. }
  315. </style>