diff --git a/public/core/offer-workspace-v1769.js b/public/core/offer-workspace-v1769.js
index 3390a87..e0ff9de 100644
--- a/public/core/offer-workspace-v1769.js
+++ b/public/core/offer-workspace-v1769.js
@@ -4,10 +4,20 @@
const VERSION='17.6.9';
const RELEASE='20260908-v17-6-9-offer-pdf-tabs-gallery';
const MODES=new Set(['preview','editor','templates']);
+ const GALLERY_KEY='sunOfferGalleryOverridesV1769';
+ const DEFAULT_GALLERY=['offer-gallery/001.jpg','offer-gallery/002.jpg'];
const $=id=>document.getElementById(id);
const modal=()=>$('sunClientOfferModal');
const dialog=()=>modal()?.querySelector('.dialog')||null;
- let mode='preview',wasOpen=false;
+ const toast=(text,type='info',ms=4200)=>{try{return window.SunEnterprise?.toast?.(text,type,ms)}catch(_){};};
+ let mode='preview',wasOpen=false,activeOrderId='';
+ let openersPatched=false,classicPatched=false;
+
+ function readGalleryMap(){try{const v=JSON.parse(localStorage.getItem(GALLERY_KEY)||'{}');return v&&typeof v==='object'&&!Array.isArray(v)?v:{}}catch(_){return{}}}
+ function writeGalleryMap(map){try{localStorage.setItem(GALLERY_KEY,JSON.stringify(map));window.dispatchEvent(new CustomEvent('sun:offer-gallery-v1769-change',{detail:{orderId:activeOrderId}}));return true}catch(e){console.error('[Caterium v17.6.9] gallery persist failed',e);toast('Не удалось сохранить фото: хранилище заполнено.','error',6000);return false}}
+ function galleryFor(orderId=activeOrderId){const map=readGalleryMap(),v=map[String(orderId||'')];return Array.isArray(v)&&v.length?v.slice(0,2).map((x,i)=>x||DEFAULT_GALLERY[i]):DEFAULT_GALLERY.slice()}
+ function saveGallerySlot(index,value){if(!activeOrderId){toast('Сначала сохраните заказ, чтобы закрепить фотографии предложения.','warn',5200);return false}const map=readGalleryMap(),key=String(activeOrderId),arr=Array.isArray(map[key])?map[key].slice(0,2):DEFAULT_GALLERY.slice();while(arr.length<2)arr.push(DEFAULT_GALLERY[arr.length]);arr[index]=value||DEFAULT_GALLERY[index];map[key]=arr;const ok=writeGalleryMap(map);if(ok){syncGalleryUi();refreshOffer();}return ok}
+ function currentDraftId(){try{if(window.draft?.id!=null)return String(window.draft.id)}catch(_){}const raw=document.querySelector('#orderForm [name="id"],#orderId,#order-id')?.value;return raw?String(raw):''}
function installStyle(){
if($('sunOfferWorkspaceV1769Style'))return;
@@ -72,26 +82,56 @@
if(focus){const target=mode==='editor'?$('sunOfferEditor'):mode==='templates'?$('sunOfferTemplateV1764'):m.querySelector('.sun-offer-frame-wrap');target?.scrollTo?.({top:0,behavior:'instant'});}
}
+ function syncGalleryUi(){const arr=galleryFor();for(let i=0;i<2;i++){const img=$(`sunOfferGalleryPreview${i}`);if(img)img.src=arr[i]||DEFAULT_GALLERY[i]}}
function upgradeGalleryUi(){
- const wrap=modal()?.querySelector('.sun-offer-editor-gallery-images');if(!wrap||wrap.dataset.sunV1769==='1')return false;
- const inputs=wrap.querySelectorAll('[data-offer-gallery-slot]');
- if(inputs.length===2){wrap.dataset.sunV1769='1';return true;}
- const old=[...wrap.querySelectorAll('img')].map(x=>x.getAttribute('src')).filter(Boolean);
- wrap.innerHTML=[0,1].map(i=>`
.padStart(3,'0')}.jpg`})
`).join('');
- wrap.dataset.sunV1769='1';return true;
+ const wrap=modal()?.querySelector('.sun-offer-editor-gallery-images');if(!wrap)return false;
+ if(wrap.dataset.sunV1769==='1'){syncGalleryUi();return true;}
+ wrap.innerHTML=[0,1].map(i=>``).join('');
+ wrap.dataset.sunV1769='1';syncGalleryUi();return true;
}
- function enhance(){installStyle();ensureTabs();upgradeGalleryUi();}
+ async function fileToDataUrl(file){
+ const maxSide=1400,target=700*1024;
+ let bitmap;try{bitmap=await createImageBitmap(file)}catch(_){return await new Promise((res,rej)=>{const r=new FileReader();r.onload=()=>res(String(r.result||''));r.onerror=rej;r.readAsDataURL(file)})}
+ try{
+ let scale=Math.min(1,maxSide/Math.max(bitmap.width,bitmap.height)),quality=.86,best='';
+ for(let i=0;i<5;i++){
+ const c=document.createElement('canvas');c.width=Math.max(1,Math.round(bitmap.width*scale));c.height=Math.max(1,Math.round(bitmap.height*scale));const x=c.getContext('2d',{alpha:false});x.fillStyle='#fff';x.fillRect(0,0,c.width,c.height);x.drawImage(bitmap,0,0,c.width,c.height);const url=c.toDataURL('image/jpeg',quality);best=url;if(Math.round((url.length-22)*.75)<=target)break;quality=Math.max(.62,quality-.07);scale*=.86;
+ }
+ return best;
+ }finally{bitmap.close?.()}
+ }
+
+ function refreshOffer(){try{window.dispatchEvent(new CustomEvent('sunoffertemplatechange',{detail:{galleryOnly:true,orderId:activeOrderId}}))}catch(_){}}
+ function patchOpeners(){
+ if(openersPatched)return true;const one=window.sunOpenClientOffer,cur=window.sunOpenCurrentClientOffer;if(typeof one!=='function'||typeof cur!=='function')return false;
+ window.sunOpenClientOffer=function(id,...rest){activeOrderId=String(id??'');const out=one.call(this,id,...rest);setTimeout(syncGalleryUi,80);return out};
+ window.sunOpenCurrentClientOffer=function(...args){activeOrderId=currentDraftId();const out=cur.apply(this,args);setTimeout(syncGalleryUi,80);return out};
+ window.sunOpenClientOffer.__sunV1769=true;window.sunOpenCurrentClientOffer.__sunV1769=true;openersPatched=true;return true;
+ }
+ function patchClassic(){
+ if(classicPatched)return true;const api=window.SunClassicOfferPDFV1767;if(!api||typeof api.renderPages!=='function')return false;const original=api.renderPages.bind(api);
+ api.renderPages=async function(snapshot,...rest){const s=structuredClone(snapshot||{}),id=String(s.orderId||activeOrderId||'');if(id){s.finalGallery=galleryFor(id)}return original(s,...rest)};api.renderPages.__sunV1769=true;classicPatched=true;return true;
+ }
+
+ function enhance(){installStyle();ensureTabs();upgradeGalleryUi();patchOpeners();patchClassic();}
+
+ document.addEventListener('change',async e=>{
+ const input=e.target.closest?.('[data-offer-gallery-slot]');if(!input)return;const file=input.files?.[0];if(!file)return;if(!/^image\/(jpeg|png|webp)$/i.test(file.type||'')){toast('Поддерживаются JPG, PNG и WEBP.','warn');input.value='';return}const idx=Number(input.dataset.offerGallerySlot);input.disabled=true;toast(`Оптимизирую фото ${idx+1}…`);try{const data=await fileToDataUrl(file);if(!data)throw new Error('Не удалось обработать изображение.');saveGallerySlot(idx,data);toast(`Фото ${idx+1} сохранено для этого предложения.`,'success')}catch(err){console.error(err);toast(err?.message||String(err),'error')}finally{input.disabled=false;input.value=''}
+ },true);
document.addEventListener('click',e=>{
+ const reset=e.target.closest?.('[data-offer-gallery-reset]');if(reset){e.preventDefault();saveGallerySlot(Number(reset.dataset.offerGalleryReset),DEFAULT_GALLERY[Number(reset.dataset.offerGalleryReset)]);toast('Фото возвращено к стандартному.','success');return}
const edit=e.target.closest?.('#sunOfferEdit');if(edit&&modal()?.classList.contains('on')){e.preventDefault();e.stopImmediatePropagation();setMode(mode==='editor'?'preview':'editor');return;}
const pdf=e.target.closest?.('#sunOfferPdf');if(pdf&&modal()?.classList.contains('on')&&mode!=='preview')setMode('preview',false);
},true);
+ window.addEventListener('sun:offer-gallery-v1769-change',syncGalleryUi);
const observer=new MutationObserver(()=>{
const m=modal();if(!m)return;enhance();const open=m.classList.contains('on');if(open&&!wasOpen)setMode('preview',false);wasOpen=open;
});
observer.observe(document.documentElement,{subtree:true,childList:true,attributes:true,attributeFilter:['class']});
installStyle();enhance();
- window.SunOfferWorkspaceV1769={VERSION,RELEASE,setMode,enhance,checks:()=>({version:VERSION,mode,modal:Boolean(modal()),tabs:Boolean($('sunOfferWorkspaceTabsV1769'))})};
+ const retry=setInterval(()=>{if(patchOpeners()&&patchClassic())clearInterval(retry)},350);setTimeout(()=>clearInterval(retry),15000);
+ window.SunOfferWorkspaceV1769={VERSION,RELEASE,GALLERY_KEY,setMode,enhance,galleryFor,checks:()=>({version:VERSION,mode,modal:Boolean(modal()),tabs:Boolean($('sunOfferWorkspaceTabsV1769')),activeOrderId,openersPatched,classicPatched})};
})();