HEX
Server: Apache
System: Linux vpshost11508.publiccloud.com.br 5.15.179-grsec-vpshost-10.lc.el8.x86_64 #1 SMP Mon Apr 7 12:04:45 -03 2025 x86_64
User: wicomm2 (10002)
PHP: 8.3.0
Disabled: apache_child_terminate,dl,escapeshellarg,escapeshellcmd,exec,link,mail,openlog,passthru,pcntl_alarm,pcntl_exec,pcntl_fork,pcntl_get_last_error,pcntl_getpriority,pcntl_setpriority,pcntl_signal,pcntl_signal_dispatch,pcntl_sigprocmask,pcntl_sigtimedwait,pcntl_sigwaitinfo,pcntl_strerror,pcntl_wait,pcntl_waitpid,pcntl_wexitstatus,pcntl_wifexited,pcntl_wifsignaled,pcntl_wifstopped,pcntl_wstopsig,pcntl_wtermsig,php_check_syntax,php_strip_whitespace,popen,proc_close,proc_open,shell_exec,symlink,system
Upload Files
File: /home/storage/5/78/dd/wicomm2/public_html/clientes/leitorean/index.html
<!doctype html>
<html lang="pt-br">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>Leitor EAN-13</title>
  <style>
    body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; padding: 16px; }
    video { width: 100%; max-width: 520px; border-radius: 12px; background: #000; }
    .row { display:flex; gap:12px; flex-wrap:wrap; margin-top: 12px; }
    button { padding: 10px 14px; border-radius: 10px; border: 1px solid #ddd; background: #fff; cursor:pointer; }
    .result { margin-top: 12px; font-size: 18px; }
    .hint { color:#666; font-size: 14px; margin-top: 6px; }
    .ok { color: #0a7; }
    .bad { color: #c22; }
    code { background:#f6f6f6; padding:2px 6px; border-radius:8px; }
  </style>
</head>
<body>
  <h1>Leitor de Código de Barras (EAN-13)</h1>

  <video id="video" autoplay muted playsinline></video>

  <div class="row">
    <button id="start">Iniciar</button>
    <button id="stop" disabled>Parar</button>
    <button id="copy" disabled>Copiar</button>
  </div>

  <div class="result">
    <strong>EAN-13:</strong> <span id="text">—</span>
    <div class="hint" id="hint">Aponte a câmera para um EAN-13 (13 dígitos).</div>
    <div class="hint" id="status"></div>
  </div>

  <script type="module">
    import {
      BrowserMultiFormatReader,
      BarcodeFormat,
      DecodeHintType,
      NotFoundException
    } from "https://cdn.jsdelivr.net/npm/@zxing/browser@0.1.5/+esm";

    const video = document.getElementById("video");
    const startBtn = document.getElementById("start");
    const stopBtn  = document.getElementById("stop");
    const copyBtn  = document.getElementById("copy");
    const textEl   = document.getElementById("text");
    const hintEl   = document.getElementById("hint");
    const statusEl = document.getElementById("status");

    // Hints para focar só em EAN-13
    const hints = new Map();
    hints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.EAN_13]);

    const reader = new BrowserMultiFormatReader(hints, 500); // 500ms entre tentativas
    let controls = null;

    function isValidEan13(code) {
      if (!/^\d{13}$/.test(code)) return false;
      const digits = code.split("").map(Number);
      const checkDigit = digits[12];

      // Soma: posições 1..12 (índice 0..11). ÍMPARES *1, PARES *3 (no padrão EAN)
      // (considerando a primeira posição como "1")
      let sum = 0;
      for (let i = 0; i < 12; i++) {
        const pos = i + 1;
        sum += digits[i] * (pos % 2 === 0 ? 3 : 1);
      }
      const calc = (10 - (sum % 10)) % 10;
      return calc === checkDigit;
    }

    function setResult(value) {
      textEl.textContent = value ?? "—";
      copyBtn.disabled = !value;
    }

    function setStatus(msg, kind) {
      statusEl.textContent = msg ?? "";
      statusEl.className = "hint " + (kind || "");
    }

    async function start() {
      setResult(null);
      setStatus("", "");
      hintEl.textContent = "Abrindo câmera…";

      try {
        const constraints = { video: { facingMode: "environment" }, audio: false };

        controls = await reader.decodeFromConstraints(
          constraints,
          video,
          (result, err) => {
            if (result) {
              const value = result.getText();

              // ZXing pode ler outros formatos em raros casos; reforçamos:
              if (!/^\d{13}$/.test(value)) {
                setStatus("Lido, mas não parece EAN-13 (precisa ter 13 dígitos).", "bad");
                return;
              }

              if (!isValidEan13(value)) {
                setResult(value);
                setStatus("13 dígitos lidos, mas o dígito verificador não confere ❌", "bad");
                return;
              }

              setResult(value);
              hintEl.textContent = "Lido com sucesso ✅";
              setStatus("EAN-13 válido ✔️", "ok");

              // opcional: parar automaticamente ao ler válido
              stop();
            } else if (err && !(err instanceof NotFoundException)) {
              console.error(err);
              setStatus("Erro ao ler. Ajuste distância/luz/foco.", "bad");
            }
          }
        );

        startBtn.disabled = true;
        stopBtn.disabled = false;
        hintEl.textContent = "Aponte para o EAN-13…";
      } catch (e) {
        console.error(e);
        hintEl.textContent = "Não consegui abrir a câmera. Verifique permissões e se está em HTTPS.";
        setStatus("Dica: no iPhone, use Safari e HTTPS para câmera.", "bad");
      }
    }

    function stop() {
      if (controls) controls.stop();
      controls = null;
      startBtn.disabled = false;
      stopBtn.disabled = true;
    }

    startBtn.addEventListener("click", start);
    stopBtn.addEventListener("click", stop);

    copyBtn.addEventListener("click", async () => {
      const value = textEl.textContent;
      if (!value || value === "—") return;
      await navigator.clipboard.writeText(value);
      setStatus("Copiado 📋", "ok");
    });
  </script>

  <p class="hint">
    Observações: câmera em celular normalmente exige <code>HTTPS</code> (exceto <code>localhost</code>).
  </p>
</body>
</html>