barcode-ninja-scanner / index.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 Ninja Scanner</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></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); }
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-md">
<!-- Header -->
<header class="mb-8 text-center">
<h1 class="text-3xl font-bold text-indigo-600 mb-2">Barcode Ninja</h1>
<p class="text-gray-600">Scan, track, and manage barcodes efficiently</p>
<div class="flex space-x-2 mt-2">
<a href="scan-app.html" class="text-blue-500 hover:text-blue-700 inline-block">UniScan X App</a>
<span class="text-gray-400">|</span>
<a href="scan.html" class="text-blue-500 hover:text-blue-700 inline-block">Classic Scanner</a>
<span class="text-gray-400">|</span>
<a href="history.html" class="text-blue-500 hover:text-blue-700 inline-block">Scan History</a>
</div>
</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">Barcode 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> Scan Now
</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 id="lastScanned" class="mt-4 p-3 bg-indigo-50 rounded-lg hidden">
<p class="text-sm text-gray-600 mb-1">Last scanned:</p>
<p id="lastScannedCode" class="font-mono text-lg font-bold text-indigo-700"></p>
</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>
<p class="text-sm text-gray-500 mb-4">Barcodes in this list will trigger special notifications when scanned.</p>
</div>
<!-- History Section -->
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-800">Recent Scans</h2>
<button id="clearHistoryBtn" class="text-sm text-indigo-600 hover:text-indigo-800">Clear All</button>
</div>
<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-2 rounded-lg shadow-lg transform translate-y-16 transition-transform duration-300 opacity-0 hidden">
<div class="flex items-center">
<span id="toastMessage"></span>
</div>
</div>
</div>
<script>
// App State
const state = {
scanHistory: [],
watchlist: [],
maxHistorySize: 10
};
// DOM Elements
const elements = {
scanBtn: document.getElementById('scanBtn'),
scannerPlaceholder: document.getElementById('scannerPlaceholder'),
lastScanned: document.getElementById('lastScanned'),
lastScannedCode: document.getElementById('lastScannedCode'),
watchlistInput: document.getElementById('watchlistInput'),
scanHistory: document.getElementById('scanHistory'),
clearHistoryBtn: document.getElementById('clearHistoryBtn'),
toast: document.getElementById('toast'),
toastMessage: document.getElementById('toastMessage')
};
// Initialize Feather Icons
feather.replace();
// Event Listeners
elements.scanBtn.addEventListener('click', initiateScan);
elements.clearHistoryBtn.addEventListener('click', clearHistory);
elements.watchlistInput.addEventListener('change', updateWatchlist);
// Functions
function initiateScan() {
// In a real app, this would trigger the device camera
// For demo purposes, we'll simulate a scan
simulateScan();
}
function simulateScan() {
// Generate a random barcode for demo
const barcode = 'BC' + Math.floor(100000 + Math.random() * 900000);
handleScannedBarcode(barcode);
}
function handleScannedBarcode(barcode) {
// Check if already scanned
if (state.scanHistory.includes(barcode)) {
showToast('This barcode has already been scanned!', 'warning');
return;
}
// Check if in watchlist
if (state.watchlist.includes(barcode)) {
showToast('⚠️ Special barcode detected!', 'warning');
}
// Add to history
addToHistory(barcode);
// Send to server
sendToServer(barcode);
}
function addToHistory(barcode) {
// Maintain max history size
if (state.scanHistory.length >= state.maxHistorySize) {
state.scanHistory.pop();
}
state.scanHistory.unshift(barcode);
updateHistoryDisplay();
}
function updateHistoryDisplay() {
if (state.scanHistory.length === 0) {
elements.scanHistory.innerHTML = '<p class="text-gray-500 text-center py-4">No scans yet</p>';
elements.lastScanned.classList.add('hidden');
return;
}
// Update last scanned display
elements.lastScannedCode.textContent = state.scanHistory[0];
elements.lastScanned.classList.remove('hidden');
// Update history list
elements.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('');
}
function clearHistory() {
state.scanHistory = [];
updateHistoryDisplay();
showToast('Scan history cleared', 'info');
}
function updateWatchlist() {
const text = elements.watchlistInput.value;
state.watchlist = text.split('\n').filter(barcode => barcode.trim() !== '');
showToast('Watchlist updated', 'success');
}
function sendToServer(barcode) {
// In a real app, this would be a POST request
console.log('Sending to server:', barcode);
// fetch('/api/scan', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ barcode })
// });
showToast(`Barcode "${barcode}" sent to server`, 'success');
}
function showToast(message, type = 'info') {
elements.toastMessage.textContent = message;
// Set color based on type
const colors = {
info: 'bg-gray-800',
success: 'bg-green-600',
warning: 'bg-yellow-600',
error: 'bg-red-600'
};
elements.toast.className = `fixed bottom-4 right-4 text-white px-4 py-2 rounded-lg shadow-lg transform translate-y-16 transition-transform duration-300 ${colors[type]}`;
// Show toast
elements.toast.classList.remove('hidden');
elements.toast.style.opacity = '1';
elements.toast.style.transform = 'translateY(0)';
// Hide after delay
setTimeout(() => {
elements.toast.style.opacity = '0';
elements.toast.style.transform = 'translateY(16px)';
setTimeout(() => elements.toast.classList.add('hidden'), 300);
}, 3000);
}
// For demo: simulate scanning by pressing 'S' key
document.addEventListener('keydown', (e) => {
if (e.key === 's') {
simulateScan();
}
});
</script>
</body>
</html>