138 lines
4.5 KiB
HTML
138 lines
4.5 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-TW">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>QR Code Scanner</title>
|
||
<style>
|
||
body {
|
||
font-family: Arial, sans-serif;
|
||
margin: 0;
|
||
padding: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: 100vh;
|
||
background-color: #f4f4f4;
|
||
}
|
||
#reader {
|
||
width: 300px;
|
||
margin-bottom: 10px;
|
||
}
|
||
select {
|
||
margin-bottom: 10px;
|
||
font-size: 16px;
|
||
padding: 5px;
|
||
}
|
||
#result {
|
||
font-size: 18px;
|
||
color: #333;
|
||
word-break: break-word;
|
||
max-width: 90%;
|
||
text-align: center;
|
||
}
|
||
</style>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5-qrcode/2.3.8/html5-qrcode.min.js"></script>
|
||
</head>
|
||
<body>
|
||
<h1>QR Code Scanner</h1>
|
||
<select id="cameraSelector"></select>
|
||
<div id="reader"></div>
|
||
<div id="result">請將 QR Code 對準攝影機。</div>
|
||
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", async function () {
|
||
const resultDiv = document.getElementById('result');
|
||
const cameraSelector = document.getElementById('cameraSelector');
|
||
const html5QrCode = new Html5Qrcode("reader");
|
||
|
||
let cameras = [];
|
||
|
||
// 獲取可用攝影機
|
||
try {
|
||
cameras = await Html5Qrcode.getCameras();
|
||
if (cameras.length === 0) {
|
||
resultDiv.textContent = '未找到攝影機。';
|
||
return;
|
||
}
|
||
|
||
cameraSelector.innerHTML = cameras
|
||
.map((camera, index) => `<option value="${camera.id}">${camera.label || `攝影機 ${index + 1}`}</option>`)
|
||
.join('');
|
||
|
||
alert(`找到 ${cameras.length} 個攝影機,請選擇要使用的攝影機。`);
|
||
startScanner(cameras[0].id); // 預設啟用第一個攝影機
|
||
|
||
} catch (error) {
|
||
alert(`無法取得攝影機:${error.message}`);
|
||
resultDiv.textContent = `無法取得攝影機:${error.message}`;
|
||
}
|
||
|
||
// 改變選擇的攝影機
|
||
cameraSelector.addEventListener('change', function () {
|
||
const selectedCameraId = cameraSelector.value;
|
||
startScanner(selectedCameraId);
|
||
});
|
||
|
||
// 啟動掃描器
|
||
function startScanner(cameraId) {
|
||
html5QrCode.start(
|
||
{ deviceId: cameraId },
|
||
{
|
||
fps: 10, // 每秒掃描次數
|
||
qrbox: 250 // QR Code 掃描框大小
|
||
},
|
||
function (decodedText) {
|
||
resultDiv.textContent = `識別到的 QR Code:${decodedText}`;
|
||
parseQRCode(decodedText);
|
||
},
|
||
function () {
|
||
// 移除多餘的警告日誌
|
||
}
|
||
).catch(function (error) {
|
||
alert(`無法啟動掃描器:${error.message}`);
|
||
resultDiv.textContent = `無法啟動掃描器:${error.message}`;
|
||
});
|
||
}
|
||
|
||
// 解析 QR Code
|
||
function parseQRCode(qrCode) {
|
||
try {
|
||
qrCode = qrCode.trim();
|
||
const invoiceNumber = qrCode.slice(0, 10);
|
||
const issueDate = qrCode.slice(10, 17);
|
||
const year = parseInt(issueDate.slice(0, 3)) + 1911;
|
||
const month = issueDate.slice(3, 5);
|
||
const day = issueDate.slice(5, 7);
|
||
const formattedDate = `${year}-${month}-${day}`;
|
||
const randomCode = qrCode.slice(17, 21);
|
||
const untaxedAmountHex = qrCode.slice(21, 29);
|
||
const untaxedAmount = parseInt(untaxedAmountHex, 16);
|
||
const totalAmountHex = qrCode.slice(29, 37);
|
||
const totalAmount = parseInt(totalAmountHex, 16);
|
||
const buyerTaxId = qrCode.slice(37, 45);
|
||
const sellerTaxId = qrCode.slice(45, 53);
|
||
const encryptedCode = qrCode.slice(53, 77);
|
||
|
||
resultDiv.innerHTML = `
|
||
<strong>發票號碼:</strong> ${invoiceNumber}<br>
|
||
<strong>開立日期:</strong> ${formattedDate}<br>
|
||
<strong>隨機碼:</strong> ${randomCode}<br>
|
||
<strong>未稅金額:</strong> ${untaxedAmount}<br>
|
||
<strong>總計金額:</strong> ${totalAmount}<br>
|
||
<strong>買方統一編號:</strong> ${buyerTaxId}<br>
|
||
<strong>賣方統一編號:</strong> ${sellerTaxId}<br>
|
||
<strong>加密驗證資訊:</strong> ${encryptedCode}<br>
|
||
`;
|
||
} catch (error) {
|
||
alert(`解析 QR Code 內容失敗:${error.message}`);
|
||
resultDiv.textContent = `解析 QR Code 內容失敗:${error.message}`;
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|