yyb
5 小时以前 52459bcaba196c47a0f28079729b48ce012eaef1
feat: 添加销售订单二维码功能及相关样式,更新操作列宽度
已修改1个文件
150 ■■■■■ 文件已修改
src/views/salesManagement/salesLedger/index.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue
@@ -221,6 +221,8 @@
                               align="center">
                <template #default="scope">
                  <el-tag v-if="scope.row.productStockStatus == 1"
                  type="warning">部分入库</el-tag>
                  <el-tag v-else-if="scope.row.productStockStatus == 2"
                          type="success">已入库</el-tag>
                  <el-tag v-else-if="scope.row.productStockStatus == 0"
                          type="info">未出库</el-tag>
@@ -375,7 +377,7 @@
                         show-overflow-tooltip />
        <el-table-column fixed="right"
                         label="操作"
                         width="200"
                         width="280"
                         align="center">
          <template #default="scope">
            <el-button link
@@ -389,6 +391,9 @@
            <el-button link
                       type="primary"
                       @click="downLoadFile(scope.row)">附件</el-button>
            <el-button link
                       type="primary"
                       @click="openLedgerQrDialog(scope.row)">二维码</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -1662,6 +1667,11 @@
        <el-table-column prop="quantity"
                         label="数量"
                         width="100" />
        <el-table-column prop="stockedQuantity"
                         label="已入库数量"
                         width="120"
                         align="center"
                         show-overflow-tooltip />
        <el-table-column prop="floorCode"
                         label="楼层编号"
                         show-overflow-tooltip />
@@ -1674,6 +1684,24 @@
          确认入库
        </el-button>
      </template>
    </el-dialog>
    <el-dialog v-model="ledgerQrDialogVisible"
               title="销售订单二维码"
               width="360px"
               draggable
               :close-on-click-modal="false">
      <div class="ledger-qr-dialog">
        <img v-if="ledgerQrCompositeUrl"
             :src="ledgerQrCompositeUrl"
             alt="销售订单二维码"
             class="ledger-qr-composite-img" />
        <el-button type="primary"
                   class="ledger-qr-save-btn"
                   :disabled="!ledgerQrCompositeUrl"
                   @click="downloadLedgerQrCode">
          保存图片
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>
@@ -1722,6 +1750,7 @@
  import { printSalesOrder } from "./components/salesOrderPrint.js";
  import { printSalesDeliveryNote } from "./components/salesDeliveryPrint.js";
  import { printSalesLabel } from "./components/salesLabelPrint.js";
  import QRCode from "qrcode";
  // import { salesLedgerProductSetProcessFlowConfig } from "@/api/salesManagement/salesProcessFlowConfig.js";
  const userStore = useUserStore();
@@ -1756,6 +1785,109 @@
  const selectedStockProductIds = ref([]);
  const stockLoading = ref(false);
  const currentStockLedgerId = ref(null);
  const ledgerQrDialogVisible = ref(false);
  const ledgerQrCompositeUrl = ref("");
  const ledgerQrDownloadBaseName = ref("");
  const sanitizeLedgerQrFilename = s =>
    String(s)
      .replace(/[\\/:*?"<>|]/g, "_")
      .trim()
      .slice(0, 80) || "ledger";
  const wrapLedgerQrTextLines = (ctx, text, maxWidth) => {
    const chars = [...text];
    const lines = [];
    let line = "";
    for (const ch of chars) {
      const test = line + ch;
      if (ctx.measureText(test).width > maxWidth && line.length) {
        lines.push(line);
        line = ch;
      } else {
        line = test;
      }
    }
    if (line) lines.push(line);
    return lines;
  };
  const buildLedgerQrCompositeDataUrl = row =>
    new Promise((resolve, reject) => {
      const payload = JSON.stringify({ id: row.id });
      QRCode.toDataURL(payload, { width: 220, margin: 2 })
        .then(qrDataUrl => {
          const contract = (row.salesContractNo ?? "").trim() || "—";
          const img = new Image();
          img.onload = () => {
            const QR_SIZE = 220;
            const padTop = 16;
            const gapAfterQr = 14;
            const bottomPad = 48;
            const horizontalPad = 20;
            const lineHeight = 20;
            const fontSize = 14;
            const label = `销售合同号:${contract}`;
            const canvas = document.createElement("canvas");
            const ctx = canvas.getContext("2d");
            canvas.width = Math.max(QR_SIZE + horizontalPad * 2, 280);
            ctx.font = `${fontSize}px "Microsoft YaHei", "PingFang SC", sans-serif`;
            const lines = wrapLedgerQrTextLines(ctx, label, canvas.width - horizontalPad * 2);
            const textBlockHeight = lines.length * lineHeight;
            canvas.height = padTop + QR_SIZE + gapAfterQr + textBlockHeight + bottomPad;
            ctx.fillStyle = "#ffffff";
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            const qrX = (canvas.width - QR_SIZE) / 2;
            ctx.drawImage(img, qrX, padTop, QR_SIZE, QR_SIZE);
            ctx.fillStyle = "#606266";
            ctx.font = `${fontSize}px "Microsoft YaHei", "PingFang SC", sans-serif`;
            ctx.textAlign = "center";
            ctx.textBaseline = "top";
            const textY0 = padTop + QR_SIZE + gapAfterQr;
            lines.forEach((ln, i) => {
              ctx.fillText(ln, canvas.width / 2, textY0 + i * lineHeight);
            });
            const baseName = sanitizeLedgerQrFilename(
              contract !== "—" ? contract : String(row.id)
            );
            resolve({ dataUrl: canvas.toDataURL("image/png"), baseName });
          };
          img.onerror = () => reject(new Error("二维码图片加载失败"));
          img.src = qrDataUrl;
        })
        .catch(reject);
    });
  const openLedgerQrDialog = async row => {
    if (row?.id === undefined || row?.id === null || row?.id === "") {
      ElMessage.warning("无法生成二维码:缺少台账 ID");
      return;
    }
    ledgerQrCompositeUrl.value = "";
    ledgerQrDownloadBaseName.value = "";
    try {
      const { dataUrl, baseName } = await buildLedgerQrCompositeDataUrl(row);
      ledgerQrCompositeUrl.value = dataUrl;
      ledgerQrDownloadBaseName.value = baseName;
      ledgerQrDialogVisible.value = true;
    } catch {
      ElMessage.error("二维码生成失败");
    }
  };
  const downloadLedgerQrCode = () => {
    if (!ledgerQrCompositeUrl.value) return;
    const a = document.createElement("a");
    a.href = ledgerQrCompositeUrl.value;
    a.download = `销售销售订单二维码-${ledgerQrDownloadBaseName.value}.png`;
    a.click();
  };
  // 用户信息表单弹框数据
  const operationType = ref("");
@@ -4377,4 +4509,20 @@
    justify-content: space-between;
    margin-bottom: 10px;
  }
  .ledger-qr-dialog {
    text-align: center;
    padding-bottom: 8px;
  }
  .ledger-qr-composite-img {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 0 auto 28px;
  }
  .ledger-qr-save-btn {
    margin-bottom: 12px;
  }
</style>