barcode-ninja-scanner / scan-app.html
zengxi123's picture
创建一个条形扫码uni-app x应用程序,它是html文件+uvue文件的格式。
fefdb8d verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Barcode Scanner App</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<style>
.scan-animation {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4); }
70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}
.toast {
transition: all 0.3s ease;
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-md">
<header class="mb-8 text-center">
<h1 class="text-3xl font-bold text-indigo-600 mb-2">UniScan X</h1>
<p class="text-gray-600">Advanced barcode scanning solution</p>
</header>
<!-- Scanner Section -->
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-800">Scanner</h2>
<button id="scanBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg flex items-center transition">
<i data-feather="maximize" class="mr-2"></i> Start Scan
</button>
</div>
<div class="text-center">
<div id="scannerPlaceholder" class="mx-auto w-full h-48 bg-gray-200 rounded-lg flex items-center justify-center scan-animation">
<div class="text-center">
<i data-feather="camera" class="w-12 h-12 mx-auto text-gray-400 mb-2"></i>
<p class="text-gray-500">Ready to scan</p>
</div>
</div>
</div>
</div>
<!-- Watchlist Section -->
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Special Watchlist</h2>
<textarea id="watchlistInput" rows="3" class="w-full p-3 border border-gray-300 rounded-lg mb-3 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Enter barcodes to watch (one per line)"></textarea>
</div>
<!-- Scan History -->
<div class="bg-white rounded-xl shadow-md p-6">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Recent Scans</h2>
<div id="scanHistory" class="space-y-2">
<p class="text-gray-500 text-center py-4">No scans yet</p>
</div>
</div>
<!-- Toast Notification -->
<div id="toast" class="fixed bottom-4 right-4 bg-gray-800 text-white px-4 py-3 rounded-lg shadow-lg hidden toast">
<div class="flex items-center">
<span id="toastMessage"></span>
</div>
</div>
</div>
<script>
// State Management
const state = {
scanHistory: [],
watchlist: [],
maxHistorySize: 10,
isScanning: false
};
// DOM Elements
const dom = {
scanBtn: document.getElementById('scanBtn'),
scannerPlaceholder: document.getElementById('scannerPlaceholder'),
watchlistInput: document.getElementById('watchlistInput'),
scanHistory: document.getElementById('scanHistory'),
toast: document.getElementById('toast'),
toastMessage: document.getElementById('toastMessage')
};
// Initialize Feather Icons
feather.replace();
// Event Listeners
dom.scanBtn.addEventListener('click', startScanProcess);
dom.watchlistInput.addEventListener('change', updateWatchlist);
// Scanner Functionality
function startScanProcess() {
if (state.isScanning) return;
state.isScanning = true;
dom.scanBtn.disabled = true;
dom.scannerPlaceholder.innerHTML = `
<div class="text-center">
<div class="border-4 border-indigo-400 rounded-lg w-64 h-32 mb-4"></div>
<p class="text-gray-700">Scanning...</p>
</div>
`;
// Simulate scanning (in real app, this would use device camera)
setTimeout(() => {
const barcode = generateRandomBarcode();
handleScannedBarcode(barcode);
state.isScanning = false;
dom.scanBtn.disabled = false;
resetScannerUI();
}, 2000);
}
function resetScannerUI() {
dom.scannerPlaceholder.innerHTML = `
<div class="text-center">
<i data-feather="camera" class="w-12 h-12 mx-auto text-gray-400 mb-2"></i>
<p class="text-gray-500">Ready to scan</p>
</div>
`;
feather.replace();
}
// Barcode Processing
function generateRandomBarcode() {
return 'BC' + Math.floor(100000 + Math.random() * 900000);
}
function handleScannedBarcode(barcode) {
if (isBarcodeInHistory(barcode)) {
showToast('This barcode has already been scanned!', 'warning');
return;
}
addBarcodeToHistory(barcode);
updateHistoryDisplay();
if (isBarcodeInWatchlist(barcode)) {
showToast('⚠️ Special barcode detected!', 'warning');
} else {
sendBarcodeToServer(barcode);
}
}
function isBarcodeInHistory(barcode) {
return state.scanHistory.includes(barcode);
}
function isBarcodeInWatchlist(barcode) {
return state.watchlist.includes(barcode);
}
function addBarcodeToHistory(barcode) {
if (state.scanHistory.length >= state.maxHistorySize) {
state.scanHistory.pop();
}
state.scanHistory.unshift(barcode);
}
// Watchlist Management
function updateWatchlist() {
const text = dom.watchlistInput.value;
state.watchlist = text.split('\n')
.map(item => item.trim())
.filter(item => item !== '');
}
// History Display
function updateHistoryDisplay() {
if (state.scanHistory.length === 0) {
dom.scanHistory.innerHTML = '<p class="text-gray-500 text-center py-4">No scans yet</p>';
return;
}
dom.scanHistory.innerHTML = state.scanHistory.map(barcode => `
<div class="flex justify-between items-center p-2 bg-gray-50 rounded-lg">
<span class="font-mono">${barcode}</span>
<span class="text-xs text-gray-500">Just now</span>
</div>
`).join('');
}
// Server Communication
function sendBarcodeToServer(barcode) {
fetch('https://api.example.com/scans', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ barcode })
})
.then(response => {
if (!response.ok) throw new Error('Server error');
showToast(`Barcode "${barcode}" saved successfully`, 'success');
})
.catch(error => {
console.error('Error:', error);
showToast('Failed to save barcode', 'error');
});
}
// Toast Notifications
function showToast(message, type = 'info') {
dom.toastMessage.textContent = message;
const colors = {
info: 'bg-gray-800',
success: 'bg-green-600',
warning: 'bg-yellow-600',
error: 'bg-red-600'
};
dom.toast.className = `fixed bottom-4 right-4 text-white px-4 py-3 rounded-lg shadow-lg toast ${colors[type]}`;
dom.toast.classList.remove('hidden');
setTimeout(() => {
dom.toast.classList.add('hidden');
}, 3000);
}
</script>
</body>
</html>