printedparts: QR label with gage tag + revision; record taken rev
Label switches from CODE128 to a QR encoding 'TAG|rev' (gage lab tag + latest print-file revision), so a physical part carries which revision it was printed from - short payload stays low-version + reliable at 0.5in (margin quiet zone, EC M, no logo). Item exposes latestrevision; kiosk strips the |rev to resolve and records the scanned revision on the take (migration 0004 adds printeditemtransactions.revision) for traceability of which rev was consumed. Manual entry records a null revision.
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
<div class="controls">
|
||||
<h3>Print 3D Parts Bin Labels (1in x 0.5in)</h3>
|
||||
<p>
|
||||
Each label is one page on 1in x 0.5in roll stock: CODE128 barcode of
|
||||
the gage lab tag (the internal code is used when a part has no tag),
|
||||
scannable at the parts kiosk.
|
||||
Each label is one page on 1in x 0.5in roll stock: a QR of the gage lab
|
||||
tag plus its latest print-file revision (TAG|rev), so a scanned part
|
||||
carries which revision it was printed from. Scannable at the parts kiosk.
|
||||
</p>
|
||||
|
||||
<div v-if="loading" class="loading-msg">Loading parts...</div>
|
||||
@@ -43,23 +43,38 @@
|
||||
|
||||
<div class="labels-container">
|
||||
<div v-for="(label, index) in printLabels" :key="index" class="bin-label">
|
||||
<svg :ref="element => setBarcodeElement(element, index)" class="bin-barcode"></svg>
|
||||
<div class="bin-code">{{ label.gagelabtag || label.itemcode }}</div>
|
||||
<img v-if="qrDataUrls[index]" :src="qrDataUrls[index]" class="bin-qr" alt="" />
|
||||
<div class="bin-code">{{ labelText(label) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, watch, nextTick } from 'vue'
|
||||
import JsBarcode from 'jsbarcode'
|
||||
import { ref, computed, onMounted, watch } from 'vue'
|
||||
import QRCode from 'qrcode'
|
||||
import { printedpartsApi } from '@/api'
|
||||
|
||||
const items = ref([])
|
||||
const selectedItems = ref([])
|
||||
const copies = ref(1)
|
||||
const loading = ref(true)
|
||||
const barcodeElements = ref({})
|
||||
const qrDataUrls = ref({})
|
||||
|
||||
// The QR encodes 'TAG|rev' (gage lab tag, or internal code when untagged, plus
|
||||
// the latest print-file revision) so a scanned part carries which revision it
|
||||
// was printed from. Short data keeps the QR low-version and reliable at 0.5in.
|
||||
function labelTag(item) {
|
||||
return item.gagelabtag || item.itemcode
|
||||
}
|
||||
function labelPayload(item) {
|
||||
return item.latestrevision != null
|
||||
? `${labelTag(item)}|${item.latestrevision}` : labelTag(item)
|
||||
}
|
||||
function labelText(item) {
|
||||
return item.latestrevision != null
|
||||
? `${labelTag(item)} rev ${item.latestrevision}` : labelTag(item)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
@@ -103,27 +118,17 @@ function toggleItem(item) {
|
||||
}
|
||||
}
|
||||
|
||||
function setBarcodeElement(element, index) {
|
||||
if (element) barcodeElements.value[index] = element
|
||||
}
|
||||
|
||||
watch(printLabels, async labels => {
|
||||
await nextTick()
|
||||
labels.forEach((label, index) => {
|
||||
const element = barcodeElements.value[index]
|
||||
if (element) {
|
||||
// CODE128 of the gage lab tag (or the internal code when untagged) fits
|
||||
// 1x0.5in with comfortable scanner tolerance; a QR here would be marginal.
|
||||
JsBarcode(element, label.gagelabtag || label.itemcode, {
|
||||
format: 'CODE128',
|
||||
displayValue: false,
|
||||
width: 1.4,
|
||||
height: 26,
|
||||
margin: 0
|
||||
})
|
||||
}
|
||||
})
|
||||
}, { deep: true })
|
||||
const urls = {}
|
||||
await Promise.all(labels.map(async (label, index) => {
|
||||
// margin 2 = quiet zone (scannability); EC 'M' keeps modules big for the
|
||||
// short payload on tiny media; no logo overlay on a 0.36in code.
|
||||
urls[index] = await QRCode.toDataURL(labelPayload(label), {
|
||||
margin: 2, errorCorrectionLevel: 'M', width: 160
|
||||
})
|
||||
}))
|
||||
qrDataUrls.value = urls
|
||||
}, { deep: true, immediate: true })
|
||||
|
||||
function print() {
|
||||
window.print()
|
||||
@@ -180,7 +185,9 @@ function print() {
|
||||
background: #fff;
|
||||
outline: 1px dashed #bbb;
|
||||
}
|
||||
.bin-barcode { width: 0.92in; height: 0.3in; }
|
||||
/* Square QR sized to leave room for the text line; pixelated keeps the
|
||||
modules crisp (no blur) when the data-URL image scales, so it scans. */
|
||||
.bin-qr { width: 0.36in; height: 0.36in; image-rendering: pixelated; }
|
||||
.bin-code {
|
||||
font-size: 6.5pt;
|
||||
font-family: monospace;
|
||||
|
||||
Reference in New Issue
Block a user