zengxi123 commited on
Commit
fefdb8d
·
verified ·
1 Parent(s): 49b56fb

创建一个条形扫码uni-app x应用程序,它是html文件+uvue文件的格式。

Browse files

1.当它触发扫码时,发送POST请求,以将单号上传到数据库
2.创建一个存储十个条形码的数组,数组采用先进后出以确保最大只有十个,当扫码触发时将条形码数据加入这个数组中,当扫码得出的条形码数据已经在这个数组中时,应当发出提示说明单号已经扫描过,且不应该触发POST请求
3.它提供一个文本框,文本框放置需要注意的单号,以回车区分下一个,当扫码得出的条形码数据在文本框中时,应当给出提示
4.在编写代码时,你应该尽可能的去除耦合,以无数代码块的形式组成一个功能

Files changed (3) hide show
  1. history.html +64 -0
  2. index.html +3 -1
  3. scan-app.html +127 -156
history.html ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Scan History - Barcode Ninja</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/feather-icons"></script>
9
+ </head>
10
+ <body class="bg-gray-100 min-h-screen">
11
+ <div class="container mx-auto px-4 py-8 max-w-md">
12
+ <header class="mb-8 text-center">
13
+ <h1 class="text-3xl font-bold text-indigo-600 mb-2">Scan History</h1>
14
+ <div class="flex justify-center space-x-2 mt-2">
15
+ <a href="index.html" class="text-blue-500 hover:text-blue-700">Back to Scanner</a>
16
+ </div>
17
+ </header>
18
+
19
+ <div class="bg-white rounded-xl shadow-md p-6">
20
+ <div class="flex justify-between items-center mb-4">
21
+ <h2 class="text-xl font-semibold text-gray-800">Recent Scans</h2>
22
+ <button id="clearHistoryBtn" class="text-indigo-600 hover:text-indigo-800">Clear All</button>
23
+ </div>
24
+
25
+ <div id="historyList" class="space-y-2">
26
+ <p class="text-gray-500 text-center py-4">No scan history available</p>
27
+ </div>
28
+ </div>
29
+ </div>
30
+
31
+ <script>
32
+ // Initialize Feather Icons
33
+ feather.replace();
34
+
35
+ // Load history from localStorage
36
+ const history = JSON.parse(localStorage.getItem('scanHistory') || '[]');
37
+ const historyList = document.getElementById('historyList');
38
+ const clearHistoryBtn = document.getElementById('clearHistoryBtn');
39
+
40
+ // Display history
41
+ if (history.length === 0) {
42
+ historyList.innerHTML = '<p class="text-gray-500 text-center py-4">No scan history available</p>';
43
+ } else {
44
+ historyList.innerHTML = history.map(item => `
45
+ <div class="flex justify-between items-center p-3 bg-gray-50 rounded-lg">
46
+ <div>
47
+ <p class="font-mono font-medium">${item.barcode}</p>
48
+ <p class="text-xs text-gray-500">${new Date(item.timestamp).toLocaleString()}</p>
49
+ </div>
50
+ <span class="text-xs ${item.special ? 'text-yellow-600' : 'text-gray-400'}">
51
+ ${item.special ? 'Special' : 'Regular'}
52
+ </span>
53
+ </div>
54
+ `).join('');
55
+ }
56
+
57
+ // Clear history
58
+ clearHistoryBtn.addEventListener('click', () => {
59
+ localStorage.removeItem('scanHistory');
60
+ historyList.innerHTML = '<p class="text-gray-500 text-center py-4">No scan history available</p>';
61
+ });
62
+ </script>
63
+ </body>
64
+ </html>
index.html CHANGED
@@ -25,9 +25,11 @@
25
  <h1 class="text-3xl font-bold text-indigo-600 mb-2">Barcode Ninja</h1>
26
  <p class="text-gray-600">Scan, track, and manage barcodes efficiently</p>
27
  <div class="flex space-x-2 mt-2">
28
- <a href="scan-app.html" class="text-blue-500 hover:text-blue-700 inline-block">New Scanner App</a>
29
  <span class="text-gray-400">|</span>
30
  <a href="scan.html" class="text-blue-500 hover:text-blue-700 inline-block">Classic Scanner</a>
 
 
31
  </div>
32
  </header>
33
  <!-- Scanner Section -->
 
25
  <h1 class="text-3xl font-bold text-indigo-600 mb-2">Barcode Ninja</h1>
26
  <p class="text-gray-600">Scan, track, and manage barcodes efficiently</p>
27
  <div class="flex space-x-2 mt-2">
28
+ <a href="scan-app.html" class="text-blue-500 hover:text-blue-700 inline-block">UniScan X App</a>
29
  <span class="text-gray-400">|</span>
30
  <a href="scan.html" class="text-blue-500 hover:text-blue-700 inline-block">Classic Scanner</a>
31
+ <span class="text-gray-400">|</span>
32
+ <a href="history.html" class="text-blue-500 hover:text-blue-700 inline-block">Scan History</a>
33
  </div>
34
  </header>
35
  <!-- Scanner Section -->
scan-app.html CHANGED
@@ -6,57 +6,62 @@
6
  <title>Barcode Scanner App</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <script src="https://unpkg.com/feather-icons"></script>
9
- <script src="https://cdn.jsdelivr.net/npm/quagga/dist/quagga.min.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
10
  </head>
11
  <body class="bg-gray-100 min-h-screen">
12
  <div class="container mx-auto px-4 py-8 max-w-md">
 
 
 
 
 
13
  <!-- Scanner Section -->
14
- <div id="scannerContainer" class="bg-white rounded-xl shadow-md p-6 mb-6 hidden">
15
- <div class="relative h-64 w-full bg-black rounded-lg overflow-hidden">
16
- <video id="scannerVideo" class="absolute inset-0 w-full h-full object-cover"></video>
17
- <div class="absolute inset-0 flex items-center justify-center">
18
- <div class="border-4 border-indigo-400 rounded-lg w-64 h-32"></div>
19
- </div>
20
- </div>
21
- <div class="flex justify-between mt-4">
22
- <button id="cancelScan" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg">
23
- Cancel
24
- </button>
25
- <button id="toggleTorch" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg">
26
- Toggle Torch
27
  </button>
28
  </div>
29
- </div>
30
-
31
- <!-- Main UI -->
32
- <div id="mainUI">
33
- <header class="mb-8 text-center">
34
- <h1 class="text-3xl font-bold text-indigo-600 mb-2">Barcode Scanner</h1>
35
- <p class="text-gray-600">Scan and track barcodes efficiently</p>
36
- </header>
37
-
38
- <div class="bg-white rounded-xl shadow-md p-6 mb-6">
39
- <button id="startScan" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-3 rounded-lg font-medium">
40
- Start Scanning
41
- </button>
42
  </div>
 
43
 
44
- <div class="bg-white rounded-xl shadow-md p-6 mb-6">
45
- <h2 class="text-xl font-semibold text-gray-800 mb-4">Watchlist</h2>
46
- <textarea id="watchlist" rows="3" class="w-full p-3 border border-gray-300 rounded-lg mb-3"
47
- placeholder="Enter important barcodes (one per line)"></textarea>
48
- </div>
49
 
50
- <div class="bg-white rounded-xl shadow-md p-6">
51
- <h2 class="text-xl font-semibold text-gray-800 mb-4">Scan History</h2>
52
- <div id="scanHistory" class="space-y-2">
53
- <p class="text-gray-500 text-center py-4">No scans yet</p>
54
- </div>
55
  </div>
56
  </div>
57
 
58
  <!-- Toast Notification -->
59
- <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">
60
  <div class="flex items-center">
61
  <span id="toastMessage"></span>
62
  </div>
@@ -68,20 +73,15 @@
68
  const state = {
69
  scanHistory: [],
70
  watchlist: [],
71
- isScanning: false,
72
- scanner: null,
73
- torchEnabled: false
74
  };
75
 
76
  // DOM Elements
77
- const elements = {
78
- scannerContainer: document.getElementById('scannerContainer'),
79
- scannerVideo: document.getElementById('scannerVideo'),
80
- mainUI: document.getElementById('mainUI'),
81
- startScan: document.getElementById('startScan'),
82
- cancelScan: document.getElementById('cancelScan'),
83
- toggleTorch: document.getElementById('toggleTorch'),
84
- watchlist: document.getElementById('watchlist'),
85
  scanHistory: document.getElementById('scanHistory'),
86
  toast: document.getElementById('toast'),
87
  toastMessage: document.getElementById('toastMessage')
@@ -91,104 +91,94 @@
91
  feather.replace();
92
 
93
  // Event Listeners
94
- elements.startScan.addEventListener('click', startBarcodeScanner);
95
- elements.cancelScan.addEventListener('click', stopBarcodeScanner);
96
- elements.toggleTorch.addEventListener('click', toggleTorch);
97
- elements.watchlist.addEventListener('change', updateWatchlist);
98
 
99
- // Scanner Functions
100
- function startBarcodeScanner() {
101
- state.isScanning = true;
102
- elements.mainUI.classList.add('hidden');
103
- elements.scannerContainer.classList.remove('hidden');
104
 
105
- Quagga.init({
106
- inputStream: {
107
- name: "Live",
108
- type: "LiveStream",
109
- target: elements.scannerVideo,
110
- constraints: {
111
- width: 640,
112
- height: 480,
113
- facingMode: "environment"
114
- },
115
- },
116
- decoder: {
117
- readers: ["ean_reader", "ean_8_reader", "code_128_reader", "code_39_reader", "code_39_vin_reader", "codabar_reader", "upc_reader", "upc_e_reader"]
118
- },
119
- }, function(err) {
120
- if (err) {
121
- console.error(err);
122
- showToast("Scanner initialization failed", "error");
123
- return;
124
- }
125
- Quagga.start();
126
- });
127
 
128
- Quagga.onDetected(handleBarcodeDetection);
 
 
 
 
 
 
 
129
  }
130
 
131
- function stopBarcodeScanner() {
132
- state.isScanning = false;
133
- Quagga.stop();
134
- elements.scannerContainer.classList.add('hidden');
135
- elements.mainUI.classList.remove('hidden');
136
  }
137
 
138
- function toggleTorch() {
139
- if (!('ImageCapture' in window)) {
140
- showToast("Torch not supported on this device", "warning");
141
  return;
142
  }
143
 
144
- if (!state.torchEnabled) {
145
- const track = elements.scannerVideo.srcObject.getVideoTracks()[0];
146
- track.applyConstraints({
147
- advanced: [{torch: true}]
148
- });
149
- state.torchEnabled = true;
150
  } else {
151
- const track = elements.scannerVideo.srcObject.getVideoTracks()[0];
152
- track.applyConstraints({
153
- advanced: [{torch: false}]
154
- });
155
- state.torchEnabled = false;
156
  }
157
  }
158
 
159
- // Barcode Handling
160
- function handleBarcodeDetection(result) {
161
- const barcode = result.codeResult.code;
162
-
163
- if (isBarcodeScanned(barcode)) {
164
- showToast("Barcode already scanned", "warning");
165
- return;
166
- }
167
-
168
- addToHistory(barcode);
169
- checkWatchlist(barcode);
170
- sendToServer(barcode);
171
  }
172
 
173
- function isBarcodeScanned(barcode) {
174
- return state.scanHistory.includes(barcode);
175
  }
176
 
177
- function addToHistory(barcode) {
178
- if (state.scanHistory.length >= 10) {
179
  state.scanHistory.pop();
180
  }
181
  state.scanHistory.unshift(barcode);
182
- updateHistoryDisplay();
183
  }
184
 
 
 
 
 
 
 
 
 
 
185
  function updateHistoryDisplay() {
186
  if (state.scanHistory.length === 0) {
187
- elements.scanHistory.innerHTML = '<p class="text-gray-500 text-center py-4">No scans yet</p>';
188
  return;
189
  }
190
 
191
- elements.scanHistory.innerHTML = state.scanHistory.map(barcode => `
192
  <div class="flex justify-between items-center p-2 bg-gray-50 rounded-lg">
193
  <span class="font-mono">${barcode}</span>
194
  <span class="text-xs text-gray-500">Just now</span>
@@ -196,58 +186,39 @@
196
  `).join('');
197
  }
198
 
199
- function updateWatchlist() {
200
- state.watchlist = elements.watchlist.value
201
- .split('\n')
202
- .filter(barcode => barcode.trim() !== '');
203
- }
204
-
205
- function checkWatchlist(barcode) {
206
- if (state.watchlist.includes(barcode)) {
207
- showToast("⚠️ Watchlist barcode detected!", "warning");
208
- }
209
- }
210
-
211
- // API Communication
212
- function sendToServer(barcode) {
213
- fetch('https://api.example.com/barcodes', {
214
  method: 'POST',
215
- headers: {
216
- 'Content-Type': 'application/json',
217
- },
218
  body: JSON.stringify({ barcode })
219
  })
220
- .then(response => response.json())
221
- .then(data => {
222
- showToast(`Barcode ${barcode} saved`, "success");
223
  })
224
  .catch(error => {
225
  console.error('Error:', error);
226
- showToast("Failed to save barcode", "error");
227
  });
228
  }
229
 
230
- // UI Helpers
231
- function showToast(message, type = "info") {
232
- elements.toastMessage.textContent = message;
233
 
234
  const colors = {
235
- info: "bg-gray-800",
236
- success: "bg-green-600",
237
- warning: "bg-yellow-600",
238
- error: "bg-red-600"
239
  };
240
 
241
- 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]}`;
242
-
243
- elements.toast.classList.remove("hidden");
244
- elements.toast.style.opacity = "1";
245
- elements.toast.style.transform = "translateY(0)";
246
 
247
  setTimeout(() => {
248
- elements.toast.style.opacity = "0";
249
- elements.toast.style.transform = "translateY(16px)";
250
- setTimeout(() => elements.toast.classList.add("hidden"), 300);
251
  }, 3000);
252
  }
253
  </script>
 
6
  <title>Barcode Scanner App</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <script src="https://unpkg.com/feather-icons"></script>
9
+ <style>
10
+ .scan-animation {
11
+ animation: pulse 2s infinite;
12
+ }
13
+ @keyframes pulse {
14
+ 0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4); }
15
+ 70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
16
+ 100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
17
+ }
18
+ .toast {
19
+ transition: all 0.3s ease;
20
+ }
21
+ </style>
22
  </head>
23
  <body class="bg-gray-100 min-h-screen">
24
  <div class="container mx-auto px-4 py-8 max-w-md">
25
+ <header class="mb-8 text-center">
26
+ <h1 class="text-3xl font-bold text-indigo-600 mb-2">UniScan X</h1>
27
+ <p class="text-gray-600">Advanced barcode scanning solution</p>
28
+ </header>
29
+
30
  <!-- Scanner Section -->
31
+ <div class="bg-white rounded-xl shadow-md p-6 mb-6">
32
+ <div class="flex justify-between items-center mb-4">
33
+ <h2 class="text-xl font-semibold text-gray-800">Scanner</h2>
34
+ <button id="scanBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg flex items-center transition">
35
+ <i data-feather="maximize" class="mr-2"></i> Start Scan
 
 
 
 
 
 
 
 
36
  </button>
37
  </div>
38
+
39
+ <div class="text-center">
40
+ <div id="scannerPlaceholder" class="mx-auto w-full h-48 bg-gray-200 rounded-lg flex items-center justify-center scan-animation">
41
+ <div class="text-center">
42
+ <i data-feather="camera" class="w-12 h-12 mx-auto text-gray-400 mb-2"></i>
43
+ <p class="text-gray-500">Ready to scan</p>
44
+ </div>
45
+ </div>
 
 
 
 
 
46
  </div>
47
+ </div>
48
 
49
+ <!-- Watchlist Section -->
50
+ <div class="bg-white rounded-xl shadow-md p-6 mb-6">
51
+ <h2 class="text-xl font-semibold text-gray-800 mb-4">Special Watchlist</h2>
52
+ <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>
53
+ </div>
54
 
55
+ <!-- Scan History -->
56
+ <div class="bg-white rounded-xl shadow-md p-6">
57
+ <h2 class="text-xl font-semibold text-gray-800 mb-4">Recent Scans</h2>
58
+ <div id="scanHistory" class="space-y-2">
59
+ <p class="text-gray-500 text-center py-4">No scans yet</p>
60
  </div>
61
  </div>
62
 
63
  <!-- Toast Notification -->
64
+ <div id="toast" class="fixed bottom-4 right-4 bg-gray-800 text-white px-4 py-3 rounded-lg shadow-lg hidden toast">
65
  <div class="flex items-center">
66
  <span id="toastMessage"></span>
67
  </div>
 
73
  const state = {
74
  scanHistory: [],
75
  watchlist: [],
76
+ maxHistorySize: 10,
77
+ isScanning: false
 
78
  };
79
 
80
  // DOM Elements
81
+ const dom = {
82
+ scanBtn: document.getElementById('scanBtn'),
83
+ scannerPlaceholder: document.getElementById('scannerPlaceholder'),
84
+ watchlistInput: document.getElementById('watchlistInput'),
 
 
 
 
85
  scanHistory: document.getElementById('scanHistory'),
86
  toast: document.getElementById('toast'),
87
  toastMessage: document.getElementById('toastMessage')
 
91
  feather.replace();
92
 
93
  // Event Listeners
94
+ dom.scanBtn.addEventListener('click', startScanProcess);
95
+ dom.watchlistInput.addEventListener('change', updateWatchlist);
 
 
96
 
97
+ // Scanner Functionality
98
+ function startScanProcess() {
99
+ if (state.isScanning) return;
 
 
100
 
101
+ state.isScanning = true;
102
+ dom.scanBtn.disabled = true;
103
+ dom.scannerPlaceholder.innerHTML = `
104
+ <div class="text-center">
105
+ <div class="border-4 border-indigo-400 rounded-lg w-64 h-32 mb-4"></div>
106
+ <p class="text-gray-700">Scanning...</p>
107
+ </div>
108
+ `;
109
+
110
+ // Simulate scanning (in real app, this would use device camera)
111
+ setTimeout(() => {
112
+ const barcode = generateRandomBarcode();
113
+ handleScannedBarcode(barcode);
114
+ state.isScanning = false;
115
+ dom.scanBtn.disabled = false;
116
+ resetScannerUI();
117
+ }, 2000);
118
+ }
 
 
 
 
119
 
120
+ function resetScannerUI() {
121
+ dom.scannerPlaceholder.innerHTML = `
122
+ <div class="text-center">
123
+ <i data-feather="camera" class="w-12 h-12 mx-auto text-gray-400 mb-2"></i>
124
+ <p class="text-gray-500">Ready to scan</p>
125
+ </div>
126
+ `;
127
+ feather.replace();
128
  }
129
 
130
+ // Barcode Processing
131
+ function generateRandomBarcode() {
132
+ return 'BC' + Math.floor(100000 + Math.random() * 900000);
 
 
133
  }
134
 
135
+ function handleScannedBarcode(barcode) {
136
+ if (isBarcodeInHistory(barcode)) {
137
+ showToast('This barcode has already been scanned!', 'warning');
138
  return;
139
  }
140
 
141
+ addBarcodeToHistory(barcode);
142
+ updateHistoryDisplay();
143
+
144
+ if (isBarcodeInWatchlist(barcode)) {
145
+ showToast('⚠️ Special barcode detected!', 'warning');
 
146
  } else {
147
+ sendBarcodeToServer(barcode);
 
 
 
 
148
  }
149
  }
150
 
151
+ function isBarcodeInHistory(barcode) {
152
+ return state.scanHistory.includes(barcode);
 
 
 
 
 
 
 
 
 
 
153
  }
154
 
155
+ function isBarcodeInWatchlist(barcode) {
156
+ return state.watchlist.includes(barcode);
157
  }
158
 
159
+ function addBarcodeToHistory(barcode) {
160
+ if (state.scanHistory.length >= state.maxHistorySize) {
161
  state.scanHistory.pop();
162
  }
163
  state.scanHistory.unshift(barcode);
 
164
  }
165
 
166
+ // Watchlist Management
167
+ function updateWatchlist() {
168
+ const text = dom.watchlistInput.value;
169
+ state.watchlist = text.split('\n')
170
+ .map(item => item.trim())
171
+ .filter(item => item !== '');
172
+ }
173
+
174
+ // History Display
175
  function updateHistoryDisplay() {
176
  if (state.scanHistory.length === 0) {
177
+ dom.scanHistory.innerHTML = '<p class="text-gray-500 text-center py-4">No scans yet</p>';
178
  return;
179
  }
180
 
181
+ dom.scanHistory.innerHTML = state.scanHistory.map(barcode => `
182
  <div class="flex justify-between items-center p-2 bg-gray-50 rounded-lg">
183
  <span class="font-mono">${barcode}</span>
184
  <span class="text-xs text-gray-500">Just now</span>
 
186
  `).join('');
187
  }
188
 
189
+ // Server Communication
190
+ function sendBarcodeToServer(barcode) {
191
+ fetch('https://api.example.com/scans', {
 
 
 
 
 
 
 
 
 
 
 
 
192
  method: 'POST',
193
+ headers: { 'Content-Type': 'application/json' },
 
 
194
  body: JSON.stringify({ barcode })
195
  })
196
+ .then(response => {
197
+ if (!response.ok) throw new Error('Server error');
198
+ showToast(`Barcode "${barcode}" saved successfully`, 'success');
199
  })
200
  .catch(error => {
201
  console.error('Error:', error);
202
+ showToast('Failed to save barcode', 'error');
203
  });
204
  }
205
 
206
+ // Toast Notifications
207
+ function showToast(message, type = 'info') {
208
+ dom.toastMessage.textContent = message;
209
 
210
  const colors = {
211
+ info: 'bg-gray-800',
212
+ success: 'bg-green-600',
213
+ warning: 'bg-yellow-600',
214
+ error: 'bg-red-600'
215
  };
216
 
217
+ dom.toast.className = `fixed bottom-4 right-4 text-white px-4 py-3 rounded-lg shadow-lg toast ${colors[type]}`;
218
+ dom.toast.classList.remove('hidden');
 
 
 
219
 
220
  setTimeout(() => {
221
+ dom.toast.classList.add('hidden');
 
 
222
  }, 3000);
223
  }
224
  </script>