Ver Fonte

feat: 添加冲差单打印模板及打印功能(宝盛)

xieyong há 5 dias atrás
pai
commit
168d62f750

+ 368 - 0
src/views/saleManage/saleOrder/adjustmentNote‌/components/print-template-adjustment.vue

@@ -0,0 +1,368 @@
+<template>
+  <ele-modal
+    title="冲差单"
+    :visible.sync="QRvisible"
+    v-if="QRvisible"
+    width="80%"
+  >
+    <div
+      id="printSection"
+      style="
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        flex-direction: column;
+      "
+    >
+      <div
+        style="
+          text-align: center;
+          font-size: 20px;
+          font-weight: 800;
+          text-decoration: underline;
+          margin-bottom: 10px;
+        "
+        >{{ groupName + '冲差单' || '冲差单' }}</div
+      >
+      <div class="info-grid">
+        <span>冲差单编码:{{ formData.orderNo }}</span>
+        <span>冲差类型:{{ getDictLabel('冲差类型', formData.type) }}</span>
+        <span>冲差方式:{{ getDictLabel('冲差方式', formData.method) }}</span>
+        <span>调整类型:{{ getDictLabel('调整类型', formData.adjustType) }}</span>
+      </div>
+      <div class="info-grid">
+        <span>关联订单编码:{{ formData.sourceNo }}</span>
+        <span>冲差范围:{{ getDictLabel('冲差范围', formData.rangeType) }}</span>
+        <span>冲差原因:{{ getDictLabel('冲差原因', formData.reason) }}</span>
+        <span></span>
+      </div>
+      <div class="info-grid">
+        <span style="grid-column: span 4"
+          >调整说明:{{ formData.remark || '' }}</span
+        >
+      </div>
+      <table
+        cellspacing="0"
+        border
+        style="
+          width: 100%;
+          table-layout: fixed;
+          word-break: break-all;
+          word-wrap: break-word;
+          font-size: 12px;
+          margin-bottom: 10px;
+        "
+      >
+        <tbody>
+          <tr align="center">
+            <td style="padding: 5px" width="50px">编号</td>
+            <td style="padding: 5px">物料编码</td>
+            <td style="padding: 5px">物料名称</td>
+            <td style="padding: 5px">规格型号</td>
+            <td style="padding: 5px">单位</td>
+            <td style="padding: 5px">数量</td>
+            <td style="padding: 5px">原单价</td>
+            <td style="padding: 5px">差额</td>
+            <td style="padding: 5px">新单价</td>
+            <td style="padding: 5px">税率</td>
+            <td style="padding: 5px">折让单价</td>
+            <td style="padding: 5px">合计</td>
+            <td style="padding: 5px">折让合计</td>
+          </tr>
+
+          <tr align="center" v-for="(item, index) in formData?.productList">
+            <td style="padding: 5px">{{ index + 1 }}</td>
+            <td style="padding: 5px">{{ item.productCode }}</td>
+            <td style="padding: 5px">{{ item.productName }}</td>
+            <td style="padding: 5px">
+              {{ item.specification || ''
+              }}{{ item.modelType ? '/' + item.modelType : '' }}
+            </td>
+            <td style="padding: 5px">{{ item.measuringUnit }}</td>
+            <td style="padding: 5px">{{ item.quantity }}</td>
+            <td style="padding: 5px">{{ item.price }}</td>
+            <td style="padding: 5px">{{ item.priceDifference }}</td>
+            <td style="padding: 5px">{{ item.adjustPrice }}</td>
+            <td style="padding: 5px">
+              {{ item.taxRate ? item.taxRate + '%' : '' }}
+            </td>
+            <td style="padding: 5px">{{ item.adjustDiscountPrice }}</td>
+            <td style="padding: 5px">{{ item.adjustAmount }}</td>
+            <td style="padding: 5px">{{ item.adjustDiscountAmount }}</td>
+          </tr>
+          <tr align="center">
+            <td style="padding: 5px" colspan="2">合计</td>
+            <td style="padding: 5px; text-align: left;" colspan="11">
+              <div style="display: flex; flex-wrap: wrap;">
+                <span style="flex: 1; min-width: 200px"
+                  >原总金额:{{ formData.amount }}</span
+                >
+                <span style="flex: 1; min-width: 200px"
+                  >原优惠后总金额:{{ formData.discountAmount }}</span
+                >
+                <span style="flex: 1; min-width: 200px"
+                  >总差异金额:{{ formData.differenceAmount }}</span
+                >
+                <span style="flex: 1; min-width: 200px"
+                  >新总金额:{{ formData.adjustAmount }}</span
+                >
+                <span style="flex: 1; min-width: 200px"
+                  >新优惠后总金额:{{ formData.adjustDiscountAmount }}</span
+                >
+              </div>
+            </td>
+          </tr>
+          <tr align="center">
+            <td style="padding: 5px" colspan="2">合计金额(大写金额)</td>
+            <td style="padding: 5px; text-align: left;" colspan="11">
+              <div style="display: flex; margin-top: 6px;">
+                <span style="flex: 1"
+                  >{{ convertToChinese(formData.adjustAmount) }}</span
+                >
+              </div>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+      <div
+        style="
+          display: flex;
+          justify-content: space-between;
+          width: 100%;
+          font-size: 13px;
+        "
+      >
+        <span style="flex: 1">创建人:{{ formData.createUserName }}</span>
+        <span style="flex: 1">创建时间:{{ formData.createTime }}</span>
+      </div>
+    </div>
+    <div slot="footer">
+      <el-button @click="exportExcel">导出</el-button>
+      <el-button @click="print">打印预览</el-button>
+      <el-button @click="close">关闭</el-button>
+    </div>
+  </ele-modal>
+</template>
+
+<script>
+import { getInfo } from '@/api/saleManage/adjustmentNote‌';
+import { formatPrice } from '@/BIZComponents/setProduct.js';
+import { mapGetters } from 'vuex';
+import { saveAs } from 'file-saver';
+import { convertToChinese } from '@/utils/util';
+
+export default {
+  name: 'printTemplateAdjustment',
+  computed: {
+    ...mapGetters(['user', 'getDictValue'])
+  },
+  props: {
+    groupName: ''
+  },
+  data() {
+    return {
+      QRvisible: false,
+      formData: {}
+    };
+  },
+
+  methods: {
+    convertToChinese,
+    // 获取字典 label
+    getDictLabel(dictName, val) {
+      if (!val) return '';
+      const label = this.getDictValue(dictName, val);
+      return label || '';
+    },
+    async open(id) {
+      this.formData = (await getInfo(id)) || {};
+      // 后端返回的字段可能是 detailList / productList / datasource / originalList 等多种命名,这里做归一化
+      this.formData.productList =
+        this.formData.detailList ||
+        this.formData.productList ||
+        this.formData.datasource ||
+        this.formData.originalList ||
+        [];
+      this.QRvisible = true;
+    },
+    close() {
+      this.QRvisible = false;
+    },
+    // 差额合计(priceDifference × quantity)
+    getDiffTotal() {
+      let num = 0;
+      (this.formData.productList || []).forEach((item) => {
+        if (item.priceDifference && item.quantity) {
+          num += Number(item.priceDifference) * Number(item.quantity);
+        }
+      });
+      return formatPrice(num);
+    },
+    print() {
+      const printSection = document.getElementById('printSection');
+      // 创建打印任务
+      const printWindow = window.open('', '_blank');
+      // 收集当前页面里所有 <style> 标签的 CSS,打印窗口需要这些样式
+      const styleSheets = Array.from(
+        document.querySelectorAll('style')
+      )
+        .map((s) => s.innerHTML)
+        .join('\n');
+      printWindow.document.open();
+      printWindow.document.write(
+        `<html><head><title>打印预览</title><style>${styleSheets}</style></head><body>`
+      );
+      printWindow.document.write(printSection.innerHTML);
+      printWindow.document.write('</body></html>');
+      printWindow.document.close();
+      printWindow.onload = function () {
+        printWindow.print();
+      };
+    },
+    exportExcel() {
+      const list = this.formData?.productList || [];
+      const diffTotal = this.getDiffTotal();
+
+      const border =
+        'border-top:1px solid #000;border-right:1px solid #000;border-bottom:1px solid #000;border-left:1px solid #000;';
+      const cellBase = `${border}padding:4px;mso-number-format:"\\@";vertical-align:middle;text-align:center;mso-horizontal-align:center;`;
+      const th = `${cellBase}font-weight:bold;font-family:'宋体';font-size:12pt;`;
+      const td = `${cellBase}font-family:'宋体';font-size:11pt;`;
+      const labelLeft = `${border}padding:4px;mso-number-format:"\\@";vertical-align:middle;text-align:left;mso-horizontal-align:left;font-family:'宋体';font-size:11pt;`;
+
+      const colWidths = [40, 90, 110, 100, 50, 60, 70, 70, 70, 60, 80, 80, 90];
+      const colGroup = colWidths
+        .map((w) => `<col width="${w}" style="width:${w}pt;" />`)
+        .join('');
+
+      const rows = list
+        .map(
+          (item, index) => `
+        <tr height="24" style="height:24pt;">
+          <td align="center" valign="middle" style="${td}">${index + 1}</td>
+          <td align="center" valign="middle" style="${td}">${item.productCode || ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.productName || ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.specification || ''}${item.modelType ? '/' + item.modelType : ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.measuringUnit || ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.quantity ?? ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.price ?? ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.priceDifference ?? ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.adjustPrice ?? ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.taxRate ? item.taxRate + '%' : ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.adjustDiscountPrice ?? ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.adjustAmount ?? ''}</td>
+          <td align="center" valign="middle" style="${td}">${item.adjustDiscountAmount ?? ''}</td>
+        </tr>`
+        )
+        .join('');
+
+      const title = `${this.groupName || ''}冲差单`;
+      const table = `
+        <table border="1" cellspacing="0" cellpadding="0" align="center"
+          style="border-collapse:collapse;border:1px solid #000;mso-border-alt:solid #000 0.5pt;font-family:'宋体';font-size:11pt;text-align:center;">
+          <colgroup>${colGroup}</colgroup>
+          <tr height="40" style="height:40pt;">
+            <td colspan="13" align="center" valign="middle" style="${border}padding:6px;text-align:center;font-family:'宋体';font-size:22pt;font-weight:bold;">${title}</td>
+          </tr>
+          <tr height="26" style="height:26pt;">
+            <td width="25%" colspan="3" align="left" valign="middle" style="${labelLeft}">冲差单编码:${this.formData.orderNo || ''}</td>
+            <td width="25%" colspan="3" align="left" valign="middle" style="${labelLeft}">冲差类型:${this.getDictLabel('冲差类型', this.formData.type)}</td>
+            <td width="25%" colspan="3" align="left" valign="middle" style="${labelLeft}">冲差方式:${this.getDictLabel('冲差方式', this.formData.method)}</td>
+            <td width="25%" colspan="4" align="left" valign="middle" style="${labelLeft}">调整类型:${this.getDictLabel('调整类型', this.formData.adjustType)}</td>
+          </tr>
+          <tr height="26" style="height:26pt;">
+            <td width="25%" colspan="3" align="left" valign="middle" style="${labelLeft}">关联订单编码:${this.formData.sourceNo || ''}</td>
+            <td width="25%" colspan="3" align="left" valign="middle" style="${labelLeft}">冲差范围:${this.getDictLabel('冲差范围', this.formData.rangeType)}</td>
+            <td width="25%" colspan="3" align="left" valign="middle" style="${labelLeft}">冲差原因:${this.getDictLabel('冲差原因', this.formData.reason)}</td>
+            <td width="25%" colspan="4"></td>
+          </tr>
+          <tr height="26" style="height:26pt;">
+            <td width="100%" colspan="13" align="left" valign="middle" style="${labelLeft}">调整说明:${this.formData.remark || ''}</td>
+          </tr>
+          <tr height="28" style="height:28pt;">
+            <td align="center" valign="middle" style="${th}">编号</td>
+            <td align="center" valign="middle" style="${th}">物料编码</td>
+            <td align="center" valign="middle" style="${th}">物料名称</td>
+            <td align="center" valign="middle" style="${th}">规格型号</td>
+            <td align="center" valign="middle" style="${th}">单位</td>
+            <td align="center" valign="middle" style="${th}">数量</td>
+            <td align="center" valign="middle" style="${th}">原单价</td>
+            <td align="center" valign="middle" style="${th}">差额</td>
+            <td align="center" valign="middle" style="${th}">新单价</td>
+            <td align="center" valign="middle" style="${th}">税率</td>
+            <td align="center" valign="middle" style="${th}">折让单价</td>
+            <td align="center" valign="middle" style="${th}">合计</td>
+            <td align="center" valign="middle" style="${th}">折让合计</td>
+          </tr>
+          ${rows}
+          <tr height="26" style="height:26pt;">
+            <td align="center" valign="middle" style="${td};font-weight:bold;">合计</td>
+            <td colspan="12" align="left" valign="middle" style="${td};font-weight:bold;">
+              <span>原总金额:${this.formData.amount ?? ''}</span>
+              <span style="margin-left:24px;">原优惠后总金额:${this.formData.discountAmount ?? ''}</span>
+              <span style="margin-left:24px;">总差异金额:${this.formData.differenceAmount ?? ''}</span>
+              <span style="margin-left:24px;">新总金额:${this.formData.adjustAmount ?? ''}</span>
+              <span style="margin-left:24px;">新优惠后总金额:${this.formData.adjustDiscountAmount ?? ''}</span>
+            </td>
+          </tr>
+          <tr height="26" style="height:26pt;">
+            <td align="center" valign="middle" style="${td};font-weight:bold;">合计金额(大写金额)</td>
+            <td colspan="12" align="left" valign="middle" style="${td};font-weight:bold;">
+              ${convertToChinese(this.formData.adjustAmount)}
+            </td>
+          </tr>
+          <tr height="28" style="height:28pt;">
+            <td colspan="6" align="left" valign="middle" style="${labelLeft}">创建人:${this.formData.createUserName || ''}</td>
+            <td colspan="7" align="left" valign="middle" style="${labelLeft}">创建时间:${this.formData.createTime || ''}</td>
+          </tr>
+        </table>`;
+
+      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">
+        <head>
+        <meta charset="UTF-8" />
+        <style>
+          br { mso-data-placement: same-cell; }
+          table { mso-displayed-decimal-separator:"."; mso-displayed-thousand-separator:","; }
+          td { mso-ignore:padding; }
+        </style>
+        <!--[if gte mso 9]><xml>
+        <x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
+        <x:Name>${title}</x:Name>
+        <x:WorksheetOptions>
+          <x:DefaultRowHeight>260</x:DefaultRowHeight>
+          <x:Print><x:ValidPrinterInfo/><x:HorizontalResolution>600</x:HorizontalResolution><x:VerticalResolution>600</x:VerticalResolution></x:Print>
+          <x:Selected/>
+          <x:DoNotDisplayGridlines/>
+        </x:WorksheetOptions>
+        </x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook>
+        </xml><![endif]-->
+        </head>
+        <body>${table}</body></html>`;
+
+      const blob = new Blob(['' + html], {
+        type: 'application/vnd.ms-excel;charset=utf-8'
+      });
+      saveAs(blob, `${title}_${this.formData.orderNo || ''}.xls`);
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+.info-grid {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  width: 100%;
+  min-width: 800px;
+  margin-bottom: 10px;
+  font-size: 13px;
+  gap: 8px 16px;
+
+  > span {
+    text-align: left;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+}
+</style>

+ 41 - 0
src/views/saleManage/saleOrder/adjustmentNote‌/index.vue

@@ -42,6 +42,19 @@
             >
               批量删除
             </el-button>
+
+            <el-dropdown trigger="click" :disabled="selection?.length === 0">
+              <el-button type="primary" class="el-icon-printer" size="small">
+                打印<i class="el-icon-arrow-down el-icon--right"></i>
+              </el-button>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item
+                  v-if="$hasPermission('eom:purchaseorderreceive:printBs')"
+                  @click.native="handlePrint('printTemplateAdjustmentRef')"
+                  >冲差单</el-dropdown-item
+                >
+              </el-dropdown-menu>
+            </el-dropdown>
           </template>
 
           <!-- 查看详情列 -->
@@ -142,6 +155,11 @@
       ref="processSubmitDialogRef"
       @reload="reload"
     ></process-submit-dialog>
+    <!-- 冲差单打印模板 -->
+    <printTemplateAdjustment
+      ref="printTemplateAdjustmentRef"
+      :groupName="groupName"
+    ></printTemplateAdjustment>
   </div>
 </template>
 
@@ -149,6 +167,7 @@
   import searchTable from './components/searchTable.vue';
   import addAdjustDialog from './components/addAdjustDialog.vue';
   import detailAdjustDialog from './components/detailAdjustDialog.vue';
+  import printTemplateAdjustment from './components/print-template-adjustment.vue';
 
   import popModal from '@/components/pop-modal';
   import orderDetailDialog from '@/views/saleManage/saleOrder/components/detailDialog.vue';
@@ -162,6 +181,7 @@
   import processSubmitDialog from '@/BIZComponents/processSubmitDialog/processSubmitDialog.vue';
   import tabMixins from '@/mixins/tableColumnsMixin';
   import { getTableList, deleteInfo, deleteBatch } from '@/api/saleManage/adjustmentNote‌';
+  import { enterprisePage } from '@/api/contractManage/contractBook';
   import { reviewStatus } from '@/enum/dict';
   export default {
     mixins: [dictMixins,tabMixins],
@@ -172,6 +192,7 @@
       orderDetailDialog,
       addAdjustDialog,
       detailAdjustDialog,
+      printTemplateAdjustment
     },
     provide() {
       return {
@@ -203,6 +224,7 @@
         addInvoiceDialogFlag: false,
         accountInfoDialogFlag: false,
         processSubmitDialogFlag: false,
+        groupName: '',
         currentRow: {},
         activeComp: 'saleorder',
         tabOptions: [
@@ -365,6 +387,14 @@
       this.requestDict('冲差范围');
       this.requestDict('冲差方式');
       this.requestDict('冲差类型');
+      enterprisePage({
+        pageNum: 1,
+        size: 200
+      }).then((res) => {
+        if (res.list?.length > 0) {
+          this.groupName = res.list[0].name;
+        }
+      });
     },
     activated() {
     // 由 keep-alive 切回时刷新列表,但保留搜索条件与当前页码
@@ -497,6 +527,17 @@
         // if (type === 'orderNo') {
         //   this.$refs.orderDetailDialogRef.open({ id: row.orderId });
         // }
+      },
+      // 打印
+      handlePrint(ref) {
+        if (this.selection.length > 1)
+          return this.$message.warning('请选择一条');
+        let flag = this.selection.some((item) =>
+          [2].includes(item.status)
+        );
+        if (!flag)
+          return this.$message.warning('抱歉需要已审核的冲差单才能打印,请检查');
+        this.$refs[ref].open(this.selection[0].id);
       }
     }
   };