0}, {props.extraCopies} {props.plCopies(props.extraCopies)}{/if}
{/if}
-
- 10р/л от 1
- 9р/л от 25
- 4р/л от 1000
-
+
+
+
+ Двусторонняя 15р/л
+
+
+
+
+
+ 10р/л от 1
+
+
+
+ 9р/л от 25
+
+
+
Итого
{props.totalPrice}₽
@@ -272,7 +297,26 @@
.empty-hint { color: #8b93a1; font-size: 15px; margin: 0; }
.actions { padding: 16px 20px 32px; display: flex; flex-direction: column; gap: 12px; }
.file-count { color: #8b93a1; font-size: 13px; margin: 0; text-align: center; line-height: 1.4; }
- .pricing-info { display: flex; justify-content: center; gap: 12px; font-size: 10px; line-height: 1.2; color: rgba(255,255,255,0.25); margin-bottom: 4px; user-select: none; flex-wrap: wrap; }
+ .pricing-info {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 6px;
+ margin-bottom: 4px;
+ user-select: none;
+ }
+ .pricing-row {
+ display: flex;
+ justify-content: center;
+ gap: 12px;
+ font-size: 10px;
+ line-height: 1.2;
+ color: rgba(255, 255, 255, 0.25);
+ flex-wrap: wrap;
+ }
+ .pricing-row-duplex {
+ margin-bottom: 2px;
+ }
.price-tier { transition: color 0.2s ease; }
.price-tier.active { color: rgba(255,255,255,0.6); }
.price-summary { display: flex; justify-content: space-between; align-items: baseline; width: 100%; }
diff --git a/src/lib/pages/print/store.svelte.js b/src/lib/pages/print/store.svelte.js
index 19a1a62..b12bd82 100644
--- a/src/lib/pages/print/store.svelte.js
+++ b/src/lib/pages/print/store.svelte.js
@@ -1,6 +1,6 @@
// lib/pages/print/store.svelte.js
import { onDestroy, tick } from 'svelte';
-import { getPricePerPage } from '$lib/common/utils/pricing.util.js';
+import { getPricePerPage, getSheetsCount } from '$lib/common/utils/pricing.util.js';
import { detectFileType, pagesLabel as _pagesLabel } from '$lib/common/utils/file.util.js';
import { loadPdfDocument, renderPageToImage } from '$lib/common/services/pdf.service.js';
@@ -34,20 +34,44 @@ export function createPrintStore() {
const jobActive = $derived(!!job && job.phase !== 'finished' && job.phase !== 'cancelled');
let uid = 0;
- const totalPrice = $derived(
- files.reduce((sum, f) => {
- const pages = f.selectedPages?.size || 0;
- return sum + pages * f.copies * getPricePerPage(pages);
- }, 0)
- );
+ const totalPrice = $derived(
+ files.reduce((sum, f) => {
+ const pages = f.selectedPages?.size || 0;
+ const isDuplex = f.sides === 'Двусторонняя';
+
+ const sheets = getSheetsCount(pages, isDuplex);
+
+ const pricePerSheet = getPricePerPage(
+ isDuplex ? sheets : pages,
+ f.sides ?? 'Односторонняя'
+ );
+
+ return sum + sheets * f.copies * pricePerSheet;
+ }, 0)
+ );
const extraCopies = $derived(files.reduce((sum, f) => sum + (f.copies - 1), 0));
- function updateFile(id, changes) {
- files = files.map((f) => (f.id === id ? { ...f, ...changes } : f));
- if (activeFile?.id === id) {
- activeFile = files.find((f) => f.id === id);
- }
- }
+ function updateFile(id, changes) {
+ files = files.map((f) => {
+ if (f.id !== id) return f;
+
+ const next = { ...f, ...changes };
+
+ const blockDuplex =
+ next.fileType !== 'office' &&
+ (next.selectedPages?.size ?? 0) <= 1;
+
+ if (blockDuplex && next.sides === 'Двусторонняя') {
+ next.sides = 'Односторонняя';
+ }
+
+ return next;
+ });
+
+ if (activeFile?.id === id) {
+ activeFile = files.find((f) => f.id === id);
+ }
+ }
async function ensurePdfLoaded(entry) {
if (entry.pdfDoc) return entry.pdfDoc;
@@ -227,9 +251,17 @@ export function createPrintStore() {
alert('⚠️ Некорректный ответ сервера печати.');
return;
}
- job = data;
- showPayment = false;
- await advanceJob();
+ job = data;
+ showPayment = false;
+
+ const hasDuplex = files.some((f) => f.sides === 'Двусторонняя');
+ const needsManualStart =
+ hasDuplex &&
+ (job.phase === 'waiting_start' || job.phase === 'awaiting_clear_output');
+
+ if (!needsManualStart) {
+ await advanceJob();
+ }
} catch {
alert('⚠️ Не удалось связаться с сервером печати.');
} finally {