From 90482d0e7dd8226e5a5730d11d4ebb1b32642a8d Mon Sep 17 00:00:00 2001 From: pavlov346346-source Date: Tue, 15 Sep 2026 18:42:32 +0300 Subject: [PATCH] fix: stop signature PDF pages from double-rendering a cover renderOfferPdfPages routed the signature templates' inner pages back through the classic module's own renderPages, which drew its own extra cover page on top of the real content pages -- doubling the render work and producing an extra page. Route straight to the plain base renderer instead. Also await the gourmet-hero template's photo cards instead of firing them off unawaited. Co-Authored-By: Claude Sonnet 5 --- public/app-runtime.js | 5 +---- public/core/signature-offer-pdf-v18.js | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/public/app-runtime.js b/public/app-runtime.js index ea4f56e..7d9077e 100644 --- a/public/app-runtime.js +++ b/public/app-runtime.js @@ -1614,10 +1614,7 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс } async function renderOfferPdfPages(s){ const signature=window.SunSignatureOfferPDFV18,classic=window.SunClassicOfferPDFV1767; - if(signature?.renderPages){ - const viaSignature=async snap=>classic?.renderPages?classic.renderPages(snap,renderOfferPdfPagesBase):renderOfferPdfPagesBase(snap); - return signature.renderPages(s,viaSignature); - } + if(signature?.renderPages)return signature.renderPages(s,renderOfferPdfPagesBase); if(classic?.renderPages)return classic.renderPages(s,renderOfferPdfPagesBase); return renderOfferPdfPagesBase(s); } diff --git a/public/core/signature-offer-pdf-v18.js b/public/core/signature-offer-pdf-v18.js index c237c12..e2bee54 100644 --- a/public/core/signature-offer-pdf-v18.js +++ b/public/core/signature-offer-pdf-v18.js @@ -87,7 +87,7 @@ logoOrBrand(ctx,logo,p,{x:W-M-190,y:44,dark:true},s.brandName);text(ctx,'КЕЙТЕРИНГ ДЛЯ',M,90,420,60,{font:'700 46px Arial',color:'#fff',maxLines:1});text(ctx,'ВАШЕГО СОБЫТИЯ',M,150,420,60,{font:'700 46px Arial',color:'#fff',maxLines:1});text(ctx,'Индивидуальное меню, безупречная подача и сервис, о котором будут говорить ваши гости.',M,235,400,24,{font:'14px Arial',color:p.muted,maxLines:3});if(hero)coverImage(ctx,hero,520,60,426,340,18);roundRect(ctx,520,420,240,42,12,p.paper,p.line);text(ctx,String((s.items||[]).length)+' блюд в меню',540,432,220,18,{font:'700 12px Arial',color:p.accent,maxLines:1}); const tabs=['РЫБНЫЕ','МЯСНЫЕ','ВЕГЕТАРИАНСКИЕ','САЛАТЫ','ДЕСЕРТЫ'];let tx=M;tabs.forEach((t,i)=>{const w2=text(ctx,t,tx,505,200,16,{font:'700 11px Arial',color:i===0?'#fff':p.muted,maxLines:1});if(i===0)line(ctx,tx,528,tx+70,528,p.accent,2);tx+=90}); const featured=(s.items||[]).slice(0,3);const cardW=(W-2*M-2*14)/3; - (async()=>{const imgs=await Promise.all(featured.map(it=>loadImage(it.photoData||'')));featured.forEach((it,i)=>{const xx=M+i*(cardW+14);roundRect(ctx,xx,555,cardW,230,16,p.paper,p.line);if(imgs[i])coverImage(ctx,imgs[i],xx,555,cardW,150,16);text(ctx,String(i+1).padStart(2,'0'),xx+14,715,40,16,{font:'700 12px Arial',color:p.accent,maxLines:1});text(ctx,it.name||'Позиция меню',xx+14,735,cardW-28,20,{font:'600 13px Arial',color:'#fff',maxLines:2});if(it.weight)text(ctx,String(it.weight),xx+14,cardW>0?765:765,cardW-28,14,{font:'10px Arial',color:p.muted,maxLines:1})})})(); + {const imgs=await Promise.all(featured.map(it=>loadImage(it.photoData||'')));featured.forEach((it,i)=>{const xx=M+i*(cardW+14);roundRect(ctx,xx,555,cardW,230,16,p.paper,p.line);if(imgs[i])coverImage(ctx,imgs[i],xx,555,cardW,150,16);text(ctx,String(i+1).padStart(2,'0'),xx+14,715,40,16,{font:'700 12px Arial',color:p.accent,maxLines:1});text(ctx,it.name||'Позиция меню',xx+14,735,cardW-28,20,{font:'600 13px Arial',color:'#fff',maxLines:2});if(it.weight)text(ctx,String(it.weight),xx+14,765,cardW-28,14,{font:'10px Arial',color:p.muted,maxLines:1})})} roundRect(ctx,M,822,W-2*M,52,14,null,p.accent,1.4);text(ctx,'СМОТРЕТЬ ПОЛНОЕ МЕНЮ →',0,838,W,18,{font:'700 12px Arial',color:p.accent,align:'center',maxLines:1}); statCards(ctx,s,p,M,910,306,100,[[Math.round(classicBoxCount(s))||0,'КОРОБОК'],[(s.items||[]).length,'ПОЗИЦИЙ']],{dark:true});priceBand(ctx,s,p,376,910,306,100,{dark:true});checklistCard(ctx,p,698,910,248,100,'ДОСТАВКА',CHECK_LINES.slice(0,2),{dark:true}); addonRow(ctx,p,M,1045,W-2*M,150,ADDON_LINES,{dark:true});