Basic functionality with WASP printer
This commit is contained in:
128
index-csv.php
Normal file → Executable file
128
index-csv.php
Normal file → Executable file
@@ -152,10 +152,20 @@ if ($isPosted && $mode === 'csv') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute pagination
|
// Single-label physical dimensions (as fed by the label printer: 3.7cm wide × 2.5cm tall)
|
||||||
|
// Content is rotated 90° so it reads correctly when applied to a spine.
|
||||||
|
$single_feed_w_cm = 3.7;
|
||||||
|
$single_feed_h_cm = 2.5;
|
||||||
|
// After rotation, the visible label area is 2.5cm wide × 3.7cm tall
|
||||||
|
$single_label_w_cm = 2.5;
|
||||||
|
$single_label_h_cm = 3.7;
|
||||||
|
|
||||||
|
$is_single = ($mode === 'single' && !empty($records));
|
||||||
|
|
||||||
|
// Compute pagination (CSV/sheet mode only)
|
||||||
$perPage = $cols * $rows;
|
$perPage = $cols * $rows;
|
||||||
$pages = [];
|
$pages = [];
|
||||||
if ($records) {
|
if ($records && !$is_single) {
|
||||||
$pages = array_chunk($records, $perPage);
|
$pages = array_chunk($records, $perPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,10 +203,17 @@ if ($records) {
|
|||||||
--show-outlines: <?= $show_outlines === '1' ? 1 : 0 ?>;
|
--show-outlines: <?= $show_outlines === '1' ? 1 : 0 ?>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<?php if ($is_single): ?>
|
||||||
|
@page {
|
||||||
|
size: <?= $single_feed_w_cm ?>cm <?= $single_feed_h_cm ?>cm landscape;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
<?php else: ?>
|
||||||
@page {
|
@page {
|
||||||
size: var(--page-w) var(--page-h);
|
size: var(--page-w) var(--page-h);
|
||||||
margin: 0; /* we handle margins inside the .sheet via padding */
|
margin: 0; /* we handle margins inside the .sheet via padding */
|
||||||
}
|
}
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: var(--font);
|
font-family: var(--font);
|
||||||
@@ -300,10 +317,78 @@ if ($records) {
|
|||||||
|
|
||||||
.controls { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
|
.controls { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
|
||||||
|
|
||||||
|
/* ====== SINGLE LABEL (standalone) ====== */
|
||||||
|
.single-label-wrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
.single-label-feed {
|
||||||
|
/* Outer box matches the physical feed size (3.7cm × 2.5cm landscape) */
|
||||||
|
width: <?= $single_feed_w_cm ?>cm;
|
||||||
|
height: <?= $single_feed_h_cm ?>cm;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px dashed #999;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.single-label {
|
||||||
|
/* Inner content sized as portrait (2.5cm × 3.7cm), then rotated to fit the landscape feed */
|
||||||
|
width: <?= $single_label_w_cm ?>cm;
|
||||||
|
height: <?= $single_label_h_cm ?>cm;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0.06cm;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 0.24cm;
|
||||||
|
|
||||||
|
/* Rotate 90° clockwise and re-center within the feed box */
|
||||||
|
transform: rotate(90deg);
|
||||||
|
transform-origin: center center;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-top: calc(-<?= $single_label_h_cm ?>cm / 2);
|
||||||
|
margin-left: calc(-<?= $single_label_w_cm ?>cm / 2);
|
||||||
|
}
|
||||||
|
.single-label .label-text {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.04cm;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-size: inherit;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
.single-label .barcode-block {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-end;
|
||||||
|
margin-top: 0.02cm;
|
||||||
|
}
|
||||||
|
.single-label .barcode-block svg {
|
||||||
|
display: block;
|
||||||
|
height: 0.8cm;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
.pane, .controls, .error, .info, .subtle, h1 { display: none !important; }
|
.pane, .controls, .error, .info, .subtle, h1, .wrap { display: none !important; }
|
||||||
body { margin: 0; background: white; }
|
body { margin: 0; padding: 0; background: white; }
|
||||||
.sheet { border: none; }
|
.sheet { border: none; }
|
||||||
|
|
||||||
|
/* Single label: fill the page exactly */
|
||||||
|
.single-label-wrap { display: flex !important; padding: 0; margin: 0; justify-content: start; }
|
||||||
|
.single-label-feed {
|
||||||
|
width: <?= $single_feed_w_cm ?>cm;
|
||||||
|
height: <?= $single_feed_h_cm ?>cm;
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sheet mode: show sheets */
|
||||||
|
.sheets { display: grid !important; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
@@ -448,8 +533,8 @@ function jump(id){ document.getElementById(id)?.scrollIntoView({behavior:'smooth
|
|||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<!-- Preview / Sheets -->
|
<!-- Preview / Sheets (CSV mode) -->
|
||||||
<?php if ($records && !$errors): ?>
|
<?php if ($records && !$errors && !$is_single): ?>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<button onclick="goPrint()">Print</button>
|
<button onclick="goPrint()">Print</button>
|
||||||
<span class="info"><?= count($records) ?> label(s), <?= count($pages) ?> sheet(s) @ <?= $cols ?>×<?= $rows ?>.</span>
|
<span class="info"><?= count($records) ?> label(s), <?= count($pages) ?> sheet(s) @ <?= $cols ?>×<?= $rows ?>.</span>
|
||||||
@@ -486,6 +571,16 @@ function jump(id){ document.getElementById(id)?.scrollIntoView({behavior:'smooth
|
|||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Single label preview -->
|
||||||
|
<?php if ($is_single && !$errors):
|
||||||
|
$rec = $records[0];
|
||||||
|
?>
|
||||||
|
<div class="controls">
|
||||||
|
<button onclick="goPrint()">Print Label</button>
|
||||||
|
<span class="info">Single label — <?= $single_label_w_cm ?>cm × <?= $single_label_h_cm ?>cm</span>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (!$autoloadOk): ?>
|
<?php if (!$autoloadOk): ?>
|
||||||
<div class="error">
|
<div class="error">
|
||||||
Composer autoload not found. Install the barcode library with:<br>
|
Composer autoload not found. Install the barcode library with:<br>
|
||||||
@@ -495,5 +590,26 @@ function jump(id){ document.getElementById(id)?.scrollIntoView({behavior:'smooth
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if ($is_single && !$errors):
|
||||||
|
$rec = $records[0];
|
||||||
|
?>
|
||||||
|
<div class="single-label-wrap">
|
||||||
|
<div class="single-label-feed">
|
||||||
|
<div class="single-label">
|
||||||
|
<div class="label-text">
|
||||||
|
<div class="label-text-line"><?= nl2br(safe($rec['data1'] ?? '')) ?></div>
|
||||||
|
<div class="label-text-line"><?= nl2br(safe($rec['data2'] ?? '')) ?></div>
|
||||||
|
<div class="label-text-line"><?= nl2br(safe($rec['data3'] ?? '')) ?></div>
|
||||||
|
<div class="label-text-line"><?= nl2br(safe($rec['data4'] ?? '')) ?></div>
|
||||||
|
</div>
|
||||||
|
<div class="barcode-block">
|
||||||
|
<?= render_datamatrix_svg((string)($rec['barcode'] ?? '')) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user