Files
42_104/caddy/www/instascan_invoice_parser.html
2026-06-23 19:33:50 +08:00

145 lines
5.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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;
}
video {
border: 2px solid #000;
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/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/schmich/instascan-builds/master/instascan.min.js"></script>
</head>
<body>
<h1>QR Code Scanner</h1>
<select id="cameraSelector"></select>
<video id="preview"></video>
<div id="result">請將 QR Code 對準攝影機。</div>
<script>
$(document).ready(function () {
const videoElement = document.getElementById('preview');
const resultDiv = document.getElementById('result');
const cameraSelector = document.getElementById('cameraSelector');
let scanner = new Instascan.Scanner({ video: videoElement });
let cameras = [];
// 瀏覽器支援檢查
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
alert('您的瀏覽器不支援攝影機訪問。請使用最新版本的 Chrome 或 Safari。');
return;
}
alert('開始檢查攝影機是否可用...');
// 列出所有攝影機
Instascan.Camera.getCameras()
.then(function (availableCameras) {
if (availableCameras.length > 0) {
cameras = availableCameras;
cameraSelector.innerHTML = cameras
.map((camera, index) => `<option value="${index}">${camera.name || `攝影機 ${index + 1}`}</option>`)
.join('');
alert(`找到 ${cameras.length} 個攝影機,請選擇要使用的攝影機。`);
startScanner(cameras[0]); // 預設啟用第一個攝影機
} else {
alert('未找到攝影機。');
resultDiv.textContent = '未找到攝影機。';
}
})
.catch(function (error) {
alert(`無法啟用攝影機:${error.message}`);
resultDiv.textContent = `無法啟用攝影機:${error.message}`;
});
// 改變選擇的攝影機
cameraSelector.addEventListener('change', function () {
const selectedCameraIndex = parseInt(cameraSelector.value, 10);
if (cameras[selectedCameraIndex]) {
startScanner(cameras[selectedCameraIndex]);
}
});
// 啟動掃描器
function startScanner(camera) {
scanner.stop().then(() => {
scanner.start(camera).catch(function (error) {
alert(`無法啟動攝影機:${error.message}`);
resultDiv.textContent = `無法啟動攝影機:${error.message}`;
});
});
}
// 掃描 QR Code
scanner.addListener('scan', function (content) {
alert(`識別到的 QR Code${content}`);
resultDiv.textContent = `識別到的 QR Code${content}`;
parseQRCode(content);
});
// 解析 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>