Qr
This commit is contained in:
parent
6150baa25d
commit
11e8e84064
@ -2,22 +2,27 @@
|
||||
ViewData["Title"] = "QR Scanner";
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
<style>
|
||||
@@font-face {
|
||||
font-family: 'OCR-A';
|
||||
src: url('../assets/fonts/ocraext.ttf');
|
||||
<style scoped>
|
||||
.error {
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.QrPrintFont {
|
||||
font-family: 'OCR-A', monospace;
|
||||
.barcode-format-checkbox {
|
||||
margin-right: 10px;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.table td img {
|
||||
display: block !important;
|
||||
select {
|
||||
width: 200px; /* Adjust width as needed */
|
||||
padding: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml")
|
||||
<div id="registerItem" class="row">
|
||||
<div class="row card">
|
||||
@ -28,11 +33,25 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div id="app" v-if="displayStatus == null" data-aos="fade-right">
|
||||
<h1 data-aos="fade-right">QR & Barcode Scanner</h1>
|
||||
<div id="reader" data-aos="fade-right"></div>
|
||||
</div>
|
||||
<select v-if="displayStatus == null" class="form-select" v-model="selectedCameraId" v-on:change="updateCamera">
|
||||
<option v-for="device in videoInputDevices" :key="device.deviceId" :value="device.deviceId">
|
||||
{{ device.label || `Camera ${videoInputDevices.indexOf(device) + 1}` }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<div id="registerItem" v-if="displayStatus == null" data-aos="fade-right">
|
||||
<p style="text-align:center; padding:10px;">Scan QR Code Here:</p>
|
||||
<qrcode-stream :constraints="selectedConstraints"
|
||||
:formats="['qr_code']"
|
||||
:track="trackFunctionSelected.value"
|
||||
v-on:camera-on="onCameraReady"
|
||||
v-on:detect="onDecode"
|
||||
v-on:error="onError">
|
||||
</qrcode-stream>
|
||||
|
||||
<p class="error">{{ error }}</p>
|
||||
|
||||
</div>
|
||||
<!--RECEIVE OR RETURN INTERFACE -->
|
||||
<div style="text-align: center; margin: 20px 0;" v-if="displayStatus === 'arrived'">
|
||||
<h2>Item Receive Information :</h2>
|
||||
@ -190,7 +209,7 @@
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Deploy Station : </label>
|
||||
<div class="col-sm-8">
|
||||
<select class="btn btn-primary dropdown-toggle col-md-10" v-model="selectedStation" >
|
||||
<select class="btn btn-primary dropdown-toggle col-md-10" v-model="selectedStation">
|
||||
<option class="btn-light" value="" disabled selected>Select Station</option>
|
||||
<option class="btn-light" v-for="(station, index) in stationList" :key="index" :value="station.stationId">{{ station.stationName}}</option>
|
||||
</select>
|
||||
@ -242,7 +261,7 @@
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Consignment Note : </label>
|
||||
<div class="col-sm-8">
|
||||
<input type="file" v-model="consignmentNote" class="form-control-file" v-on:change="handleFileUpload" accept="image/png, image/jpeg, application/pdf" />
|
||||
<input type="file" v-on:change="handleFileUpload" class="form-control-file" accept="image/png, image/jpeg, application/pdf" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -295,7 +314,7 @@
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Consignment Note:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="file" v-model="consignmentNote" class="form-control-file" v-on:change="handleFileUpload" accept="image/png, image/jpeg, application/pdf" />
|
||||
<input type="file" class="form-control-file" v-on:change="handleFileUpload" accept="image/png, image/jpeg, application/pdf" />
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Return Item</button>
|
||||
@ -330,17 +349,15 @@
|
||||
@{
|
||||
await Html.RenderPartialAsync("_ValidationScriptsPartial");
|
||||
}
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/html5-qrcode/minified/html5-qrcode.min.js"></script>
|
||||
<script src="~/js/vue-qrcode-reader.umd.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
const app = Vue.createApp({
|
||||
|
||||
data() {
|
||||
return {
|
||||
thisItem: null,
|
||||
qrCodeResult: null,
|
||||
html5QrCodeScanner: null,
|
||||
debounceTimeout: null,
|
||||
selectedUser: "",
|
||||
selectedStation: "",
|
||||
stationList: [],
|
||||
@ -352,15 +369,34 @@
|
||||
remark: null,
|
||||
consignmentNote: null,
|
||||
receiveReturn: null,
|
||||
UniqueID : null,
|
||||
UniqueID: null,
|
||||
|
||||
//QR VARIABLE
|
||||
qrCodeResult: null,
|
||||
debounceTimeout: null,
|
||||
error: "",
|
||||
selectedConstraints: { facingMode: "environment" },
|
||||
trackFunctionSelected: { text: 'outline', value: null },
|
||||
barcodeFormats: {
|
||||
qr_code: true, // Hanya mendukung QR Code
|
||||
code_128: true,
|
||||
ean_13: true
|
||||
},
|
||||
constraintOptions: [
|
||||
{ label: "Rear Camera", constraints: { facingMode: "environment" } },
|
||||
{ label: "Front Camera", constraints: { facingMode: "user" } }
|
||||
],
|
||||
videoInputDevices: [],
|
||||
selectedCameraId: null,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.trackFunctionSelected.value = this.paintOutline;
|
||||
this.fetchStation();
|
||||
this.fetchUser();
|
||||
this.startScanner();
|
||||
},
|
||||
methods: {
|
||||
|
||||
handleFileUpload(event) {
|
||||
const file = event.target.files[0];
|
||||
|
||||
@ -486,41 +522,6 @@
|
||||
alert('Inventory PSTW Error: An error occurred.');
|
||||
}
|
||||
},
|
||||
startScanner() {
|
||||
|
||||
let qrboxFunction = function (viewfinderWidth, viewfinderHeight) {
|
||||
let minEdgePercentage = 0.7; // 70%
|
||||
let minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight);
|
||||
let qrboxSize = Math.floor(minEdgeSize * minEdgePercentage);
|
||||
return {
|
||||
width: qrboxSize,
|
||||
height: qrboxSize
|
||||
};
|
||||
}
|
||||
|
||||
const config = {
|
||||
fps: 60,
|
||||
qrbox: qrboxFunction
|
||||
};
|
||||
|
||||
navigator.mediaDevices.getUserMedia({ video: true })
|
||||
.then(() => {
|
||||
this.html5QrCodeScanner = new Html5QrcodeScanner("reader", config, false);
|
||||
this.html5QrCodeScanner.render((decodedText) => {
|
||||
if (!this.debounceTimeout) {
|
||||
this.debounceTimeout = setTimeout(() => {
|
||||
this.qrCodeResult = decodedText;
|
||||
this.UniqueID = decodedText.split('/').pop();
|
||||
this.fetchItem(decodedText.split('/').pop());
|
||||
this.debounceTimeout = null;
|
||||
}, this.debounceTime);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error accessing camera:", err);
|
||||
});
|
||||
},
|
||||
async fetchItem(itemid) {
|
||||
try {
|
||||
const response = await fetch('/InvMainAPI/GetItem/' + itemid, {
|
||||
@ -542,7 +543,7 @@
|
||||
this.thisItem = null;
|
||||
}
|
||||
} else {
|
||||
console.error('Failed to fetch item information');
|
||||
this.error = 'Qr Code Not Register to the system';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching item information:', error);
|
||||
@ -590,8 +591,6 @@
|
||||
this.displayStatus = null;
|
||||
this.qrCodeResult = null;
|
||||
this.thisItem = null;
|
||||
|
||||
this.startScanner();
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
@ -603,6 +602,76 @@
|
||||
this.updateItemMovement();
|
||||
},
|
||||
|
||||
// Split Url dapatkan unique ID Je
|
||||
onDecode(detectedCodes) {
|
||||
if (detectedCodes.length > 0) {
|
||||
this.qrCodeResult = detectedCodes[0].rawValue; // Ambil URL dari rawValue
|
||||
this.UniqueID = this.qrCodeResult.split('/').pop(); // Ambil UniqueID dari URL
|
||||
this.fetchItem(this.UniqueID);
|
||||
}
|
||||
},
|
||||
|
||||
//Showing Qr Error
|
||||
onError(err) {
|
||||
let message = `[${err.name}]: `;
|
||||
if (err.name === "NotAllowedError") {
|
||||
message += "You have to allow camera accecss.";
|
||||
} else if (err.name === "NotFoundError") {
|
||||
message += "There's no camera detect.";
|
||||
} else if (err.name === "NotReadableError") {
|
||||
message += "You are using camera on the other application.";
|
||||
} else {
|
||||
message += err.message;
|
||||
}
|
||||
this.error = message;
|
||||
},
|
||||
|
||||
//Setting Camera
|
||||
async onCameraReady() {
|
||||
try {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
this.videoInputDevices = devices.filter(device => device.kind === 'videoinput');
|
||||
|
||||
if (this.videoInputDevices.length > 0) {
|
||||
// Keep the selected camera if already chosen
|
||||
if (!this.selectedCameraId) {
|
||||
this.selectedCameraId = this.videoInputDevices[0].deviceId;
|
||||
}
|
||||
|
||||
this.selectedConstraints = { deviceId: { exact: this.selectedCameraId } };
|
||||
} else {
|
||||
this.error = "No camera detected.";
|
||||
}
|
||||
} catch (err) {
|
||||
this.error = "Error accessing camera: " + err.message;
|
||||
}
|
||||
},
|
||||
|
||||
//Update Camera Category
|
||||
updateCamera() {
|
||||
this.selectedConstraints = { deviceId: { exact: this.selectedCameraId } };
|
||||
},
|
||||
|
||||
//Red box if QR Detect
|
||||
paintOutline(detectedCodes, ctx) {
|
||||
for (const detectedCode of detectedCodes) {
|
||||
const [firstPoint, ...otherPoints] = detectedCode.cornerPoints;
|
||||
|
||||
ctx.strokeStyle = 'red'; // Warna garis merah
|
||||
ctx.lineWidth = 3;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(firstPoint.x, firstPoint.y);
|
||||
for (const { x, y } of otherPoints) {
|
||||
ctx.lineTo(x, y);
|
||||
}
|
||||
ctx.lineTo(firstPoint.x, firstPoint.y);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
},
|
||||
|
||||
//Ni return message
|
||||
receiveReturnMessage() {
|
||||
$("#returnModal").modal("show");
|
||||
},
|
||||
@ -612,6 +681,7 @@
|
||||
},
|
||||
},
|
||||
});
|
||||
app.component("qrcode-stream", VueQrcodeReader.QrcodeStream);
|
||||
|
||||
app.mount('#registerItem');
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://192.168.11.107:5124",
|
||||
"applicationUrl": "http://localhost:5124",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
@ -22,7 +22,7 @@
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://192.168.11.107:7036;http://192.168.11.107:5124",
|
||||
"applicationUrl": "https://localhost:7036;http://localhost:5124",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
|
||||
3
wwwroot/js/vue-qrcode-reader.umd.js
Normal file
3
wwwroot/js/vue-qrcode-reader.umd.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user