Dualside print update realisation + add backend versioning

This commit is contained in:
2026-09-18 03:07:25 +03:00
parent 10b78d5d81
commit 0bfeeadeb1
4 changed files with 59 additions and 37 deletions

View File

@ -55,17 +55,6 @@
}
}
.version {
position: fixed;
bottom: 8px;
left: 8px;
font-size: 10px;
line-height: 1;
color: rgba(245, 247, 250, 0.35);
user-select: none;
pointer-events: none;
z-index: 10;
}
</style>
{#if needRefresh}
@ -81,5 +70,3 @@
<ScanPage onBack={handleBack} />
{/if}
</main>
<span class="version">Версия 1.0.3</span>

View File

@ -1,4 +1,6 @@
<script>
import { onMount } from 'svelte';
/** @type {Array<{ id: 'print' | 'scan' | 'photo' | 'access', label: string, grad: string, glow: string, icon: string }>} */
const actions = [
{
@ -31,10 +33,30 @@
}
];
/** @param {'print' | 'scan' | 'photo' | 'access'} id */
export let onAction = (id) => {
/**
* @type {{ onAction?: (id: 'print' | 'scan' | 'photo' | 'access') => void }}
*/
let { onAction = (id) => {
console.log('Выбрано действие:', id);
};
} } = $props();
let backendVersion = $state('—');
onMount(async () => {
try {
const res = await fetch('/api/version');
if (!res.ok) throw new Error('HTTP ' + res.status);
const text = await res.text();
try {
const json = JSON.parse(text);
backendVersion = json.version ?? json.data ?? text;
} catch {
backendVersion = text;
}
} catch (e) {
backendVersion = 'offline';
}
});
</script>
<div class="menu-container">
@ -64,8 +86,6 @@
</div>
<style>
/* Стили остаются здесь, но убираем глобальные сбросы body/html */
.menu-container {
width: 100%;
min-height: 100vh;
@ -93,14 +113,12 @@
color: #8b93a1;
}
/* Сетка 2×2 */
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
/* Карточка-кнопка в стиле мобильного UI */
.card {
display: flex;
flex-direction: column;
@ -128,12 +146,10 @@
}
}
/* Эффект нажатия, как в мобильных приложениях */
.card:active {
transform: scale(0.96);
}
/* Иконка с градиентом и свечением */
.icon {
width: 58px;
height: 58px;
@ -152,7 +168,6 @@
text-align: center;
}
/* «Домашняя» полоска внизу, как на iPhone */
.footer {
margin-top: auto;
padding: 32px 0 8px;
@ -166,4 +181,29 @@
border-radius: 999px;
background: rgba(255, 255, 255, 0.22);
}
.version {
position: fixed;
bottom: 8px;
left: 8px;
display: flex;
flex-direction: column;
gap: 2px;
font-size: 8px;
line-height: 1.1;
color: rgba(245, 247, 250, 0.35);
user-select: none;
pointer-events: none;
z-index: 10;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.version span:first-child {
color: rgba(245, 247, 250, 0.25);
}
</style>
<div class="version">
<span>v{backendVersion}</span>
<span>v1.0.4</span>
</div>

View File

@ -1,6 +1,5 @@
<!-- lib/pages/print/PrintProgress.svelte -->
<script>
const currentStatus = $derived.by(() => {
if (!store.job) return 'idle';
const f = store.job.files.find(f => f.status === 'printing');
@ -13,10 +12,9 @@
const OFFICE_EXT = ['DOC', 'DOCX', 'ODT', 'XLS', 'XLSX', 'ODS', 'PPT', 'PPTX', 'ODP'];
const STATUS_LABEL = {
queued: 'В очереди',
queued: 'Ожидает',
printing: 'Печатается…',
awaiting_flip: 'Переверните',
awaiting: 'Далее',
awaiting_flip: 'Переложите бумагу',
done: 'Готово',
error: 'Ошибка',
cancelled: 'Отменено'
@ -79,7 +77,9 @@
{#if store.job}
{#each store.job.files as f, i (i + '-' + f.name)}
{@const b = badge(f.name)}
<section class="file-card" class:current={f.status === 'awaiting_flip' || f.status === 'awaiting' || f.status === 'printing'}>
{@const isLastDone = f.status === 'done' && !store.job.files.slice(i + 1).some(f => f.status === 'printing' || f.status === 'queued')}
{@const hasNextQueued = store.job.files.slice(i + 1).some(f => f.status === 'queued')}
<section class="file-card" class:current={f.status === 'awaiting_flip' || f.status === 'printing' || isLastDone}>
<div class="file-row">
{#if b}<span class="type-badge">{b}</span>{/if}
<span class="file-name" title={f.name}>{f.name}</span>
@ -89,15 +89,12 @@
<!-- ── Инструкция для РУЧНОГО ДУПЛЕКСА (после 1-го прохода) ── -->
{#if f.status === 'awaiting_flip'}
<ol class="pickup-hint flip-hint">
{#if f.remove_top_sheet}
<li>Уберите верхний листок</li>
{/if}
<li>Не переворачивая, положите остальные листы в слот ручной подачи</li>
</ol>
{/if}
<!-- ── Инструкция для обычного «забери документ» ── -->
{#if f.status === 'awaiting'}
{#if isLastDone && hasNextQueued}
<ol class="pickup-hint">
<li>Возьмите готовый документ</li>
<li>Нажмите далее</li>
@ -128,8 +125,8 @@
<button class="next-btn next-btn-flip" onclick={store.advanceJob}>
Готово — печатать обратную сторону
</button>
{:else if store.job?.phase === 'awaiting_pickup'}
<!-- Обычное: забрал документ → следующий -->
{:else if store.job?.phase === 'awaiting_pickup' && store.job.files.some(f => f.status === 'queued')}
<!-- Обычное: забрал документ → следующий (только если есть следующий) -->
<button class="next-btn" onclick={store.advanceJob}>Далее</button>
{:else}
<!-- Кнопка видна, но серая и disabled пока сервер не допечатал -->
@ -182,9 +179,8 @@
.file-name { flex: 1; min-width: 0; font-size: 15px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-status { flex-shrink: 0; font-size: 14px; font-weight: 700; }
.st-done { color: #22c55e; }
.st-awaiting { color: #fbbf24; }
.st-printing { color: #a5b4fc; }
.st-queued { color: #8b93a1; }
.st-printing { color: #a5b4fc; }
.st-error { color: #ef4444; }
.st-cancelled { color: #6b7280; }