#
Junjie
1 天以前 6f95ffdcf6caa911f5e7c34b7797d0496d4a50f2
src/main/webapp/components/DevpCard.js
@@ -15,6 +15,7 @@
                <div style="margin-bottom: 10px;width: 33%;"><el-input size="mini" v-model="controlParam.taskNo" placeholder="工作号"></el-input></div>
                <div style="margin-bottom: 10px;width: 33%;"><el-input size="mini" v-model="controlParam.targetStationId" placeholder="目标站"></el-input></div>
                <div style="margin-bottom: 10px;"><el-button @click="controlCommand()" size="mini">下发</el-button></div>
                <div style="margin-bottom: 10px;"><el-button @click="resetCommand()" size="mini">复位</el-button></div>
            </div>
        </div>
        <div style="max-height: 55vh; overflow:auto;">
@@ -42,7 +43,20 @@
                <el-descriptions-item label="运行阻塞">{{ item.runBlock ? 'Y' : 'N' }}</el-descriptions-item>
                <el-descriptions-item label="启动入库">{{ item.enableIn ? 'Y' : 'N' }}</el-descriptions-item>
                <el-descriptions-item label="托盘高度">{{ item.palletHeight }}</el-descriptions-item>
                <el-descriptions-item label="条码">{{ item.barcode }}</el-descriptions-item>
                <el-descriptions-item label="条码">
                  <el-popover v-if="item.barcode" placement="top" width="460" trigger="hover">
                    <div style="text-align: center;">
                      <img
                        :src="getBarcodePreview(item.barcode)"
                        :alt="'barcode-' + item.barcode"
                        style="display: block; max-width: 100%; height: auto; margin: 0 auto; image-rendering: pixelated; background: #fff;"
                      />
                      <div style="margin-top: 4px; font-size: 12px; word-break: break-all;">{{ item.barcode }}</div>
                    </div>
                    <span slot="reference" style="cursor: pointer; color: #409EFF;">{{ item.barcode }}</span>
                  </el-popover>
                  <span v-else>-</span>
                </el-descriptions-item>
                <el-descriptions-item label="重量">{{ item.weight }}</el-descriptions-item>
                <el-descriptions-item label="故障代码">{{ item.error }}</el-descriptions-item>
                <el-descriptions-item label="故障信息">{{ item.errorMsg }}</el-descriptions-item>
@@ -91,6 +105,7 @@
        taskNo: "",
        targetStationId: "",
      },
      barcodePreviewCache: {},
      pageSize: 25,
      currentPage: 1,
      timer: null
@@ -135,6 +150,124 @@
      this.pageSize = size;
      this.currentPage = 1;
    },
    getBarcodePreview(barcode) {
      const value = String(barcode || "").trim();
      if (!value) {
        return "";
      }
      if (this.barcodePreviewCache[value]) {
        return this.barcodePreviewCache[value];
      }
      const encodeResult = this.encodeCode128(value);
      if (!encodeResult) {
        return "";
      }
      const svg = this.buildCode128Svg(encodeResult, value);
      const dataUrl = "data:image/svg+xml;charset=UTF-8," + encodeURIComponent(svg);
      this.$set(this.barcodePreviewCache, value, dataUrl);
      return dataUrl;
    },
    encodeCode128(value) {
      if (!value) {
        return null;
      }
      const isNumeric = /^\d+$/.test(value);
      if (isNumeric && value.length % 2 === 0) {
        return this.encodeCode128C(value);
      }
      return this.encodeCode128B(value);
    },
    encodeCode128B(value) {
      const codes = [104];
      for (let i = 0; i < value.length; i++) {
        const code = value.charCodeAt(i) - 32;
        if (code < 0 || code > 94) {
          return null;
        }
        codes.push(code);
      }
      return this.buildCode128Pattern(codes);
    },
    encodeCode128C(value) {
      if (value.length % 2 !== 0) {
        return null;
      }
      const codes = [105];
      for (let i = 0; i < value.length; i += 2) {
        codes.push(parseInt(value.substring(i, i + 2), 10));
      }
      return this.buildCode128Pattern(codes);
    },
    buildCode128Pattern(codes) {
      const patterns = this.getCode128Patterns();
      let checksum = codes[0];
      for (let i = 1; i < codes.length; i++) {
        checksum += codes[i] * i;
      }
      const checkCode = checksum % 103;
      const fullCodes = codes.concat([checkCode, 106]);
      let bars = "";
      for (let i = 0; i < fullCodes.length; i++) {
        const code = fullCodes[i];
        if (patterns[code] == null) {
          return null;
        }
        bars += patterns[code];
      }
      bars += "11";
      return bars;
    },
    buildCode128Svg(bars, text) {
      const quietModules = 20;
      const modules = quietModules * 2 + bars.split("").reduce((sum, n) => sum + parseInt(n, 10), 0);
      const moduleWidth = modules > 300 ? 1 : 2;
      const width = modules * moduleWidth;
      const barTop = 10;
      const barHeight = 110;
      let x = quietModules * moduleWidth;
      let black = true;
      let rects = "";
      for (let i = 0; i < bars.length; i++) {
        const w = parseInt(bars[i], 10) * moduleWidth;
        if (black) {
          rects += '<rect x="' + x + '" y="' + barTop + '" width="' + w + '" height="' + barHeight + '" fill="#000" shape-rendering="crispEdges" />';
        }
        x += w;
        black = !black;
      }
      return (
        '<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="145" viewBox="0 0 ' + width + ' 145">' +
        '<rect width="100%" height="100%" fill="#fff" />' +
        rects +
        '<text x="' + (width / 2) + '" y="136" text-anchor="middle" font-family="monospace" font-size="14" fill="#111">' +
        this.escapeXml(text) +
        "</text>" +
        "</svg>"
      );
    },
    getCode128Patterns() {
      return [
        "212222", "222122", "222221", "121223", "121322", "131222", "122213", "122312", "132212", "221213",
        "221312", "231212", "112232", "122132", "122231", "113222", "123122", "123221", "223211", "221132",
        "221231", "213212", "223112", "312131", "311222", "321122", "321221", "312212", "322112", "322211",
        "212123", "212321", "232121", "111323", "131123", "131321", "112313", "132113", "132311", "211313",
        "231113", "231311", "112133", "112331", "132131", "113123", "113321", "133121", "313121", "211331",
        "231131", "213113", "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111",
        "314111", "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
        "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", "134111",
        "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", "421211", "212141",
        "214121", "412121", "111143", "111341", "131141", "114113", "114311", "411113", "411311", "113141",
        "114131", "311141", "411131", "211412", "211214", "211232", "2331112"
      ];
    },
    escapeXml(text) {
      return String(text)
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&apos;");
    },
    getDevpStateInfo() {
      if (this.readOnly) {
          // Frontend filtering for readOnly mode
@@ -199,5 +332,31 @@
        },
      });
    },
    resetCommand() {
      let that = this;
      //下发命令
      $.ajax({
        url: baseUrl + "/station/command/reset",
        headers: {
          token: localStorage.getItem("token"),
        },
        contentType: "application/json",
        method: "post",
        data: JSON.stringify(that.controlParam),
        success: (res) => {
          if (res.code == 200) {
            that.$message({
              message: res.msg,
              type: "success",
            });
          } else {
            that.$message({
              message: res.msg,
              type: "warning",
            });
          }
        },
      });
    },
  },
});