张诺
7 小时以前 cf7143ce23bda4368634cbee9464796c032d6201
src/views/equipmentManagement/ledger/index.vue
@@ -7,7 +7,6 @@
          style="width: 240px"
          placeholder="请输入设备名称"
          clearable
          :prefix-icon="Search"
          @change="getTableData"
        />
      </el-form-item>
@@ -17,7 +16,6 @@
            style="width: 240px"
            placeholder="请输入规格型号"
            clearable
            :prefix-icon="Search"
            @change="getTableData"
        />
      </el-form-item>
@@ -27,17 +25,6 @@
            style="width: 240px"
            placeholder="请输入供应商"
            clearable
            :prefix-icon="Search"
            @change="getTableData"
        />
      </el-form-item>
      <el-form-item label="单位">
        <el-input
            v-model="filters.unit"
            style="width: 240px"
            placeholder="请输入单位"
            clearable
            :prefix-icon="Search"
            @change="getTableData"
        />
      </el-form-item>
@@ -82,9 +69,9 @@
      </PIMTable>
    </div>
    <Modal ref="modalRef" @success="getTableData"></Modal>
    <el-dialog v-model="qrDialogVisible" title="二维码" width="300px">
      <div style="text-align:center;">
        <img :src="qrCodeUrl" alt="二维码" style="width:200px;height:200px;" />
    <el-dialog v-model="qrDialogVisible" title="二维码" width="300px" draggable>
      <div class="qr-dialog-content">
        <img :src="qrCodeUrl" alt="二维码" style="width:220px;height:auto;" />
        <div style="margin:10px 0;">
          <el-button type="primary" @click="downloadQRCode">下载二维码图片</el-button>
        </div>
@@ -130,83 +117,69 @@
    deviceName: undefined,
    deviceModel: undefined,
    supplierName: undefined,
    unit: undefined,
    entryDateStart: undefined,
    entryDateEnd: undefined,
  },
  [
    {
      label: "设备名称",
      align: "center",
      prop: "deviceName",
    },
    {
      label: "规格型号",
      align: "center",
      prop: "deviceModel",
    },
    {
      label: "设备品牌",
      prop: "deviceBrand",
    },
    {
      label: "设备类型",
      prop: "type",
    },
    {
      label: "供应商",
      align: "center",
      prop: "supplierName",
    },
    {
      label: "单位",
      align: "center",
      prop: "unit",
      label: "存放位置",
      prop: "storageLocation",
    },
    {
      label: "数量",
      align: "center",
      prop: "number",
    },
    {
      label: "含税单价",
      align: "center",
      prop: "taxIncludingPriceUnit",
    },
    {
      label: "含税总价",
      align: "center",
      prop: "taxIncludingPriceTotal",
    },
    {
      label: "税率",
      align: "center",
      prop: "taxRate",
    },
    {
      label: "不含税总价",
      align: "center",
      prop: "unTaxIncludingPriceTotal",
    },
    {
      label: "录入人",
      align: "center",
      prop: "createUser",
    },
    {
      label: "录入日期",
      align: "center",
      prop: "createTime",
      formatData: (v) => {
        if (!v) return '';
        // 如果包含时分秒,只取日期部分
        if (v.includes(' ')) {
          return v.split(' ')[0];
        }
        return v;
      },
    },
      {
         dataType: "action",
         label: "操作",
         align: "center",
         fixed: 'right',
         width: 140,
         width: 150,
         operation: [
            {
               name: "编辑",
               type: "text",
               clickFun: (row) => {
                  edit(row.id)
               },
            },
            {
               name: "生成二维码",
               type: "text",
               clickFun: (row) => {
                  showQRCode(row)
               },
@@ -274,10 +247,83 @@
    });
};
const loadImage = (src) =>
  new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = (err) => reject(err);
    img.src = src;
  });
const wrapTextLines = (ctx, text, maxWidth) => {
  const safeText = String(text || "").trim();
  if (!safeText) return [];
  const lines = [];
  let currentLine = "";
  for (const char of safeText) {
    const nextLine = currentLine + char;
    if (ctx.measureText(nextLine).width > maxWidth && currentLine) {
      lines.push(currentLine);
      currentLine = char;
    } else {
      currentLine = nextLine;
    }
  }
  if (currentLine) {
    lines.push(currentLine);
  }
  return lines;
};
const buildQrImageWithTitle = async (qrContent, deviceName) => {
  const baseQrDataUrl = await QRCode.toDataURL(qrContent, {
    width: 220,
    margin: 2,
  });
  const qrImage = await loadImage(baseQrDataUrl);
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  if (!ctx) return baseQrDataUrl;
  const titleText = deviceName || "未命名设备";
  const fontSize = 30;
  const sidePadding = 16;
  const topPadding = 14;
  const titleBottomGap = 10;
  const bottomPadding = 14;
  ctx.font = `${fontSize}px sans-serif`;
  const textMaxWidth = qrImage.width + 40;
  const titleLines = wrapTextLines(ctx, titleText, textMaxWidth);
  const lineHeight = 22;
  const titleHeight = titleLines.length * lineHeight;
  canvas.width = Math.max(qrImage.width + sidePadding * 2, textMaxWidth + sidePadding * 2);
  canvas.height = topPadding + titleHeight + titleBottomGap + qrImage.height + bottomPadding;
  ctx.fillStyle = "#ffffff";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.font = `${fontSize}px sans-serif`;
  ctx.fillStyle = "#303133";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  titleLines.forEach((line, index) => {
    const y = topPadding + lineHeight * index + lineHeight / 2;
    ctx.fillText(line, canvas.width / 2, y);
  });
  const qrX = (canvas.width - qrImage.width) / 2;
  const qrY = topPadding + titleHeight + titleBottomGap;
  ctx.drawImage(qrImage, qrX, qrY, qrImage.width, qrImage.height);
  return canvas.toDataURL("image/png");
};
const showQRCode = async (row) => {
  // 直接使用URL,不要用JSON.stringify包装
  const qrContent = proxy.javaApi + '/device-info?deviceId=' + row.id;
  qrCodeUrl.value = await QRCode.toDataURL(qrContent);
  qrCodeUrl.value = await buildQrImageWithTitle(qrContent, row.deviceName);
  qrRowData.value = row;
  qrDialogVisible.value = true;
};
@@ -290,12 +336,6 @@
};
onMounted(() => {
  filters.entryDate = [
    dayjs().format("YYYY-MM-DD"),
    dayjs().add(1, "day").format("YYYY-MM-DD"),
  ]
  filters.entryDateStart = dayjs().format("YYYY-MM-DD")
  filters.entryDateEnd = dayjs().add(1, "day").format("YYYY-MM-DD")
  getTableData();
});
</script>
@@ -309,4 +349,16 @@
  justify-content: space-between;
  margin-bottom: 10px;
}
.qr-dialog-content {
  text-align: center;
}
.qr-device-name {
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  word-break: break-all;
}
</style>