Replace barcode with QR code + large ID on printed labels
Deploy to LXC / deploy (push) Successful in 18s

- QR code on left encodes the short ID (not URL)
- Text centred on right: title, brand/model, serial, large bold ID
- ID displayed at 11pt bold with letter-spacing for readability
- Removed barcode dependency from print pages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-09 17:40:58 +07:00
parent 941b41d3de
commit ac0dd18d8f
4 changed files with 46 additions and 40 deletions
@@ -3,7 +3,7 @@ import { db } from '$lib/server/db/index.js';
import { components } from '$lib/server/db/schema.js';
import { eq } from 'drizzle-orm';
import { error } from '@sveltejs/kit';
import { generateBarcodeSvg } from '$lib/server/barcode.js';
import { generateQrSvg } from '$lib/server/qr.js';
export const load: PageServerLoad = async ({ params }) => {
const [component] = await db
@@ -20,7 +20,7 @@ export const load: PageServerLoad = async ({ params }) => {
if (!component) error(404, 'Component not found');
const shortId = component.id.slice(0, 8).toUpperCase();
const barcodeDataUrl = await generateBarcodeSvg(shortId);
const qrSvg = await generateQrSvg(shortId);
return { component, barcodeDataUrl, shortId };
return { component, qrSvg, shortId };
};
@@ -36,19 +36,27 @@
</div>
{#each Array(copies) as _}
<div class="label" style="width: 70mm; height: 29mm; background: white; color: black; box-sizing: border-box; padding: 1mm 2mm; margin: 0 auto 8px auto; border: 1px dashed #ccc; overflow: hidden;">
<div style="display: flex; flex-direction: column; justify-content: center; height: 100%; font-family: Arial, Helvetica, sans-serif;">
<div style="font-size: 9pt; font-weight: bold; color: #000; line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{data.component.title}
<div class="label" style="width: 70mm; height: 29mm; background: white; color: black; box-sizing: border-box; padding: 1mm; margin: 0 auto 8px auto; border: 1px dashed #ccc; overflow: hidden;">
<div style="display: flex; align-items: center; gap: 2mm; height: 100%; font-family: Arial, Helvetica, sans-serif;">
<div style="width: 22mm; height: 22mm; flex-shrink: 0;">
{@html data.qrSvg}
</div>
<div style="font-size: 6pt; color: #444; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{data.component.componentType}
{#if data.component.brand}&middot; {data.component.brand}{/if}
{#if data.component.partNumber} &middot; P/N: {data.component.partNumber}{/if}
</div>
<div style="margin-top: 0.5mm;">
<img src={data.barcodeDataUrl} alt={data.shortId}
style="height: 6mm; width: auto; max-width: 65mm; display: block;" />
<div style="flex: 1; min-width: 0; text-align: center;">
<div style="font-size: 9pt; font-weight: bold; color: #000; line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{data.component.title}
</div>
<div style="font-size: 6pt; color: #444; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{data.component.componentType}
{#if data.component.brand}&middot; {data.component.brand}{/if}
</div>
{#if data.component.partNumber}
<div style="font-size: 6pt; color: #666; margin-top: 0.3mm;">
P/N: {data.component.partNumber}
</div>
{/if}
<div style="font-size: 11pt; font-weight: bold; color: #000; margin-top: 0.5mm; letter-spacing: 1px;">
{data.shortId}
</div>
</div>
</div>
</div>
@@ -3,7 +3,7 @@ import { db } from '$lib/server/db/index.js';
import { devices } from '$lib/server/db/schema.js';
import { eq } from 'drizzle-orm';
import { error } from '@sveltejs/kit';
import { generateBarcodeSvg } from '$lib/server/barcode.js';
import { generateQrSvg } from '$lib/server/qr.js';
export const load: PageServerLoad = async ({ params }) => {
const [device] = await db
@@ -23,7 +23,7 @@ export const load: PageServerLoad = async ({ params }) => {
if (!device) error(404, 'Device not found');
const shortId = device.id.slice(0, 8).toUpperCase();
const barcodeDataUrl = await generateBarcodeSvg(shortId);
const qrSvg = await generateQrSvg(shortId);
return { device, barcodeDataUrl, shortId };
return { device, qrSvg, shortId };
};
@@ -36,31 +36,29 @@
</div>
{#each Array(copies) as _}
<div class="label" style="width: 70mm; height: 29mm; background: white; color: black; box-sizing: border-box; padding: 1mm 2mm; margin: 0 auto 8px auto; border: 1px dashed #ccc; overflow: hidden;">
<div style="display: flex; flex-direction: column; justify-content: center; height: 100%; font-family: Arial, Helvetica, sans-serif;">
<div style="font-size: 9pt; font-weight: bold; color: #000; line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{data.device.title}
<div class="label" style="width: 70mm; height: 29mm; background: white; color: black; box-sizing: border-box; padding: 1mm; margin: 0 auto 8px auto; border: 1px dashed #ccc; overflow: hidden;">
<div style="display: flex; align-items: center; gap: 2mm; height: 100%; font-family: Arial, Helvetica, sans-serif;">
<div style="width: 22mm; height: 22mm; flex-shrink: 0;">
{@html data.qrSvg}
</div>
{#if data.device.brand || data.device.model}
<div style="font-size: 6pt; color: #444; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{[data.device.brand, data.device.model].filter(Boolean).join(' ')}
<div style="flex: 1; min-width: 0; text-align: center;">
<div style="font-size: 9pt; font-weight: bold; color: #000; line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{data.device.title}
</div>
{/if}
{#if data.device.serialNumber}
<div style="font-size: 5pt; color: #666;">
S/N: {data.device.serialNumber}
{#if data.device.voltage} · {data.device.voltage}{/if}
{#if data.device.frequency} · {data.device.frequency}{/if}
</div>
{:else if data.device.voltage || data.device.frequency}
<div style="font-size: 5pt; color: #666;">
{[data.device.voltage, data.device.frequency].filter(Boolean).join(' · ')}
</div>
{/if}
<div style="margin-top: 0.5mm;">
<img src={data.barcodeDataUrl} alt={data.shortId}
style="height: 6mm; width: auto; max-width: 65mm; display: block;" />
{#if data.device.brand || data.device.model}
<div style="font-size: 6pt; color: #444; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{[data.device.brand, data.device.model].filter(Boolean).join(' ')}
</div>
{/if}
{#if data.device.serialNumber}
<div style="font-size: 6pt; color: #666; margin-top: 0.3mm;">
S/N: {data.device.serialNumber}
</div>
{/if}
<div style="font-size: 11pt; font-weight: bold; color: #000; margin-top: 0.5mm; letter-spacing: 1px;">
{data.shortId}
</div>
</div>
</div>
</div>
{/each}