harden presenter runtime lifecycle
This commit is contained in:
1 parent
472b7f06fc
commit
3c46a4ea14
9 files changed
+154
-32
No files matched your search
+33
-12
@@ -563,7 +563,7 @@
|
||||
body.ppt-audience #hint,body.ppt-audience #nav,
|
||||
body.ppt-preview #hint,body.ppt-preview #nav{display:none!important}
|
||||
body.ppt-audience{cursor:none}
|
||||
body.ppt-preview{pointer-events:none}
|
||||
body.ppt-preview{pointer-events:none}body.ppt-preview #deck{transition:none!important}
|
||||
body.ppt-presenter>#deck,body.ppt-presenter>#nav,body.ppt-presenter>#hint,
|
||||
body.ppt-presenter>.bg{visibility:hidden}
|
||||
#ppt-presenter{position:fixed;inset:0;z-index:90;display:none;min-width:0;min-height:0;overflow:hidden;background:#101216;color:#f5f6f7;font-family:Inter,"Noto Sans SC",sans-serif}
|
||||
@@ -583,9 +583,9 @@
|
||||
.ppt-stage-label{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:11px 14px;color:#aeb4be;font-size:13px;border-bottom:1px solid #292d34}
|
||||
.ppt-annotation-tools{display:flex;align-items:center;gap:5px;margin-left:auto}.ppt-annotation-tools .ppt-ui-btn{padding:6px 9px;font-size:12px}.ppt-annotation-tools .ppt-ui-btn.is-active{color:#111318;background:#ff5b63;border-color:#ff5b63}.ppt-annotation-tools .ppt-grid-btn.is-active{color:#111318;background:#edf1f5;border-color:#edf1f5}.ppt-annotation-tools .ppt-clear-btn{min-width:0}.ppt-grid-btn{display:inline-flex;align-items:center;gap:6px}.ppt-grid-icon{display:grid;grid-template-columns:repeat(2,4px);gap:2px}.ppt-grid-icon i{width:4px;height:4px;background:currentColor}
|
||||
.ppt-frame-viewport{position:relative;display:grid;place-items:center;min-width:0;min-height:0;overflow:hidden;background:#08090b}
|
||||
.ppt-frame{display:block;width:0;height:0;max-width:100%;max-height:100%;aspect-ratio:16/9;border:0;background:#08090b}.ppt-next-frame{opacity:.86}
|
||||
.ppt-frame{display:block;width:0;height:0;max-width:100%;max-height:100%;aspect-ratio:16/9;border:0;background:#08090b}.ppt-next-frame{opacity:.86}#ppt-next-card.is-end .ppt-frame{visibility:hidden}#ppt-next-card.is-end .ppt-frame-viewport::after{content:"演示结束";position:absolute;color:#727a86;font:650 14px/1 Inter,"Noto Sans SC",sans-serif;letter-spacing:.08em}
|
||||
.ppt-annotation-layer{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:4;width:0;height:0;pointer-events:none;touch-action:none}.ppt-annotation-layer.is-active{pointer-events:auto;cursor:crosshair}
|
||||
#ppt-audience-ink{position:fixed;inset:0;z-index:70;width:100vw;height:100vh;pointer-events:none}#ppt-audience-cover{position:fixed;inset:0;z-index:80;display:none;pointer-events:none}
|
||||
#ppt-audience-ink{position:fixed;inset:0;z-index:70;width:100vw;height:100vh;pointer-events:none}#ppt-audience-cover{position:fixed;inset:0;z-index:80;display:none;pointer-events:none}#ppt-audience-cover.is-ended{display:grid!important;place-items:center;background:#101216!important;color:#f5f6f7;font:650 clamp(24px,3vw,46px)/1.2 Inter,"Noto Sans SC",sans-serif;letter-spacing:.08em}
|
||||
.ppt-preview-stack.is-overview>.ppt-stage-card{display:none}.ppt-presenter-overview{grid-row:1/-1;display:grid;grid-template-rows:auto minmax(0,1fr);min-width:0;min-height:0}.ppt-presenter-overview[hidden]{display:none}.ppt-overview-head{display:flex;align-items:center;justify-content:space-between;padding:13px 15px;border-bottom:1px solid #292d34}.ppt-overview-head strong{font-size:15px}.ppt-overview-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;align-content:start;overflow:auto;padding:14px}.ppt-overview-page{appearance:none;min-height:112px;display:grid;grid-template-rows:auto 1fr auto;gap:12px;padding:13px;border:1px solid #343943;border-radius:10px;background:#111318;color:#eef1f4;text-align:left;cursor:pointer}.ppt-overview-page:hover{background:#1d2128;border-color:#636b78}.ppt-overview-page.is-current{border-color:#84a8ff;box-shadow:inset 0 0 0 1px #84a8ff}.ppt-overview-page-no{color:#8f97a3;font:600 12px/1 var(--mono,monospace)}.ppt-overview-page-title{font-size:14px;font-weight:650;line-height:1.35}.ppt-overview-page-meta{display:flex;justify-content:space-between;gap:8px;color:#7f8793;font-size:11px}
|
||||
.ppt-notes-card{display:grid;grid-template-rows:auto minmax(0,1fr);min-height:0}.ppt-notes-head{padding:16px 18px;border-bottom:1px solid #292d34}.ppt-notes-label{margin-bottom:6px;color:#848c98;font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}.ppt-notes-title{font-size:21px;font-weight:680;line-height:1.32}.ppt-purpose-block{margin-top:14px;padding:11px 12px;border-left:3px solid #84a8ff;background:#111318}.ppt-purpose-copy{color:#c9ced6;font-size:14px;line-height:1.55}.ppt-notes-draft-head{display:flex;align-items:flex-end;justify-content:space-between;gap:10px;margin-top:15px;padding-top:13px;border-top:1px solid #2d3139}.ppt-notes-draft-head .ppt-notes-label{margin:0 0 4px}.ppt-note-meta{color:#8f97a3;font-size:12px}
|
||||
.ppt-notes-tools{display:flex;align-items:center;gap:6px}.ppt-notes-tools .ppt-ui-btn{padding:7px 9px}.ppt-note-editor{width:100%;height:100%;min-height:0;resize:none;border:0;outline:0;background:#171a20;color:#edf0f3;padding:18px;font:400 var(--ppt-note-size,17px)/1.72 Inter,"Noto Sans SC",sans-serif}.ppt-note-editor:focus{box-shadow:inset 0 0 0 1px #3d4654}
|
||||
@@ -600,6 +600,7 @@
|
||||
@media(max-width:1100px){.ppt-presenter-bottom{grid-template-columns:minmax(292px,1fr) auto minmax(86px,.6fr);gap:12px}.ppt-time-stat{min-width:82px;padding:0 11px}.ppt-time-value{font-size:20px}.ppt-controls .ppt-ui-btn,.ppt-session-actions .ppt-ui-btn{min-width:60px;padding:8px 9px}}
|
||||
@media(max-width:900px){.ppt-presenter-top{padding:12px 16px;flex-wrap:wrap}.ppt-presenter-top .ppt-presenter-meta{gap:6px}.ppt-presenter-top .ppt-ui-btn{padding:8px 9px}.ppt-presenter-main,#ppt-presenter[data-layout="slides"] .ppt-presenter-main,#ppt-presenter[data-layout="notes"] .ppt-presenter-main{grid-template-columns:minmax(0,1.45fr) minmax(250px,.72fr);gap:12px;padding:12px 16px}.ppt-preview-stack{gap:12px;grid-template-rows:minmax(0,1fr) clamp(104px,20vh,150px)}.ppt-saved{display:none}.ppt-presenter-bottom{grid-template-columns:minmax(270px,1fr) auto 74px;gap:8px;padding:9px 16px}.ppt-time-stat{min-width:0;padding:0 9px}.ppt-time-value{font-size:18px}.ppt-time-hint{max-width:78px;overflow:hidden;text-overflow:ellipsis}.ppt-controls,.ppt-session-actions{gap:5px}.ppt-controls .ppt-ui-btn,.ppt-session-actions .ppt-ui-btn{min-width:52px;padding:7px 8px;font-size:12px}.ppt-page-state strong{font-size:14px}.ppt-dialog-grid{grid-template-columns:1fr}.ppt-segmented.screen{grid-template-columns:repeat(2,1fr)}}
|
||||
@media(max-height:700px){.ppt-presenter-top{padding-top:10px;padding-bottom:10px}.ppt-presenter-main{padding-top:10px;padding-bottom:10px}.ppt-preview-stack{grid-template-rows:minmax(0,1fr) clamp(88px,16vh,118px);gap:10px}.ppt-stage-label{padding:7px 10px}.ppt-notes-head{padding:12px 14px}.ppt-purpose-block{margin-top:10px;padding:8px 10px}.ppt-notes-draft-head{margin-top:10px;padding-top:9px}.ppt-presenter-bottom{padding-top:8px;padding-bottom:8px}.ppt-control-stack{gap:5px}.ppt-session-actions{padding-top:5px}}
|
||||
/* ============ /演讲者模式 ============ */
|
||||
|
||||
/* ESC 索引页: 动画元素强制可见 (覆盖 motion-ready 的 opacity:0) */
|
||||
#overview [data-anim]{opacity:1!important;transform:none!important}
|
||||
@@ -1602,7 +1603,7 @@ window.__pptPresenter=(()=>{
|
||||
|
||||
function noteAt(i){
|
||||
const id=slideId(i);
|
||||
return notes().find(n=>n.id===id)||{id,title:slides[i]?.dataset.title||`第 ${i+1} 页`,purpose:'待补充本页目的',talk:['待补充讲述要点'],transition:'待补充转场'};
|
||||
return notes().find(n=>n.id===id)||{id,title:slides[i]?.dataset.title||`第 ${i+1} 页`,purpose:'—',talk:[],transition:''};
|
||||
}
|
||||
function slideLabel(i){return `${i+1} / ${total} · ${noteAt(i).title||slideId(i)}`;}
|
||||
function escapeHTML(value){return String(value??'').replace(/[&<>"']/g,ch=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[ch]));}
|
||||
@@ -1616,7 +1617,7 @@ window.__pptPresenter=(()=>{
|
||||
if(n.transition)parts.push(`【转场】\n${n.transition}`);
|
||||
const optional=[['舞台提示',n.cue],['互动',n.interaction],['表达提示',n.delivery],['翻页时机',n.advance],['备用方案',n.fallback],['读音提醒',n.pronunciation]];
|
||||
optional.forEach(([label,value])=>{const text=valueLines(value);if(text)parts.push(`【${label}】\n${text}`);});
|
||||
return parts.join('\n\n');
|
||||
return parts.join('\n\n')||'—';
|
||||
}
|
||||
function noteStorageKey(id){return `guizang-ppt-note:${location.pathname}:${id}`;}
|
||||
function loadNoteValue(id,i,n){
|
||||
@@ -1634,6 +1635,14 @@ window.__pptPresenter=(()=>{
|
||||
url.searchParams.set('mode',targetMode);url.searchParams.set('session',session);url.searchParams.set('slide',String(i+1));
|
||||
return url.href;
|
||||
}
|
||||
function postPreviewGoto(frame,i){
|
||||
try{frame.contentWindow?.postMessage({__guizangPptSync:1,session,role:'presenter',type:'preview-goto',index:i},'*');}catch(e){}
|
||||
}
|
||||
function updatePreviewFrame(frame,i){
|
||||
frame.dataset.slide=String(i);
|
||||
if(!frame.dataset.previewBound){frame.dataset.previewBound='1';frame.addEventListener('load',()=>postPreviewGoto(frame,Number(frame.dataset.slide)));}
|
||||
if(!frame.getAttribute('src'))frame.src=frameUrl('preview',i);else postPreviewGoto(frame,i);
|
||||
}
|
||||
function plannedMsAt(i){
|
||||
const minutes=Number(noteAt(i).minutes);
|
||||
return Number.isFinite(minutes)&&minutes>0?minutes*60000:null;
|
||||
@@ -1790,8 +1799,9 @@ window.__pptPresenter=(()=>{
|
||||
if(mode!=='presenter')return;mountShell();
|
||||
const n=noteAt(idx),next=Math.min(idx+1,total-1),id=slideId(idx),editor=document.getElementById('ppt-note-editor');
|
||||
const currentFrame=document.getElementById('ppt-current-frame'),nextFrame=document.getElementById('ppt-next-frame');
|
||||
if(currentFrame.dataset.slide!==String(idx)){currentFrame.src=frameUrl('preview',idx);currentFrame.dataset.slide=String(idx);}
|
||||
if(nextFrame.dataset.slide!==String(next)){nextFrame.src=frameUrl('preview',next);nextFrame.dataset.slide=String(next);}
|
||||
if(currentFrame.dataset.slide!==String(idx))updatePreviewFrame(currentFrame,idx);
|
||||
if(nextFrame.dataset.slide!==String(next))updatePreviewFrame(nextFrame,next);
|
||||
document.getElementById('ppt-next-card').classList.toggle('is-end',idx===total-1);
|
||||
document.getElementById('ppt-current-label').textContent=`${idx+1} / ${total}`;
|
||||
document.getElementById('ppt-next-label').textContent=idx===total-1?'已到尾页':`${next+1} / ${total}`;
|
||||
document.getElementById('ppt-notes-title').textContent=n.title||`第 ${idx+1} 页`;
|
||||
@@ -1898,8 +1908,13 @@ window.__pptPresenter=(()=>{
|
||||
}
|
||||
function applyAudienceScreen(value){
|
||||
const cover=document.getElementById('ppt-audience-cover');if(!cover)return;
|
||||
cover.classList.remove('is-ended');cover.textContent='';
|
||||
if(value==='black'||value==='white'){cover.style.display='block';cover.style.background=value;}else cover.style.display='none';
|
||||
}
|
||||
function showAudienceEnded(){
|
||||
const cover=document.getElementById('ppt-audience-cover');if(cover){cover.style.display='';cover.style.background='';cover.textContent='演示已结束';cover.classList.add('is-ended');}
|
||||
setTimeout(()=>{try{window.close();}catch(e){}},120);
|
||||
}
|
||||
function setScreenMode(value){
|
||||
const next=['normal','black','white','frozen'].includes(value)?value:'normal',wasFrozen=audienceFrozen;
|
||||
screenMode=next;audienceFrozen=next==='frozen';emit({type:'screen',mode:next});
|
||||
@@ -1959,6 +1974,7 @@ window.__pptPresenter=(()=>{
|
||||
return;
|
||||
}
|
||||
if(mode!=='audience')return;
|
||||
if(message.type==='bye'){showAudienceEnded();return;}
|
||||
if(message.type==='screen'){applyAudienceScreen(message.mode);return;}
|
||||
if(message.type==='laser'&&Number(message.index)===idx){audienceLaser=message.point||null;audienceLaserHideAt=Date.now()+650;renderInks();return;}
|
||||
if(message.type==='circle'&&Number(message.index)===idx&&message.circle){audienceCircles.push(message.circle);renderInks();return;}
|
||||
@@ -1968,14 +1984,18 @@ window.__pptPresenter=(()=>{
|
||||
emit({type:'ack',index:idx,seq:Number(message.seq)});
|
||||
}
|
||||
}
|
||||
function receivePreview(message){
|
||||
if(!message||message.__guizangPptSync!==1||message.session!==session||message.role!=='presenter'||message.type!=='preview-goto')return;
|
||||
go(Number(message.index),{force:true});
|
||||
}
|
||||
function sendGoto(force=false){
|
||||
if(mode!=='presenter'||audienceFrozen)return;if(force||lastAckIndex!==idx)seq++;
|
||||
emit({type:'goto',index:idx,seq,screenMode,circles});updateSyncStatus();
|
||||
}
|
||||
function syncState(){
|
||||
if(popupBlocked)return'blocked';if(audienceWindow&&audienceWindow.closed)return'disconnected';if(audienceFrozen)return'frozen';
|
||||
if(!lastAckAt)return audienceOpenedAt&&Date.now()-audienceOpenedAt<2600?'connecting':(audienceOpenedAt?'unsynced':'disconnected');
|
||||
if(Date.now()-lastAckAt>2600||lastAckIndex!==idx||lastAckSeq<seq)return'unsynced';return'synced';
|
||||
if(!lastAckAt)return audienceOpenedAt&&Date.now()-audienceOpenedAt<2600?'connecting':'disconnected';
|
||||
if(Date.now()-lastAckAt>2600)return'disconnected';if(lastAckIndex!==idx||lastAckSeq<seq)return'unsynced';return'synced';
|
||||
}
|
||||
function updateSyncStatus(){
|
||||
const el=document.getElementById('ppt-sync');if(!el)return;const state=syncState();
|
||||
@@ -1994,7 +2014,7 @@ window.__pptPresenter=(()=>{
|
||||
window.__setLowPowerMode?.(true,{persist:false});updateShell();armAutoAdvance();if(openAudience)reopenAudience();
|
||||
}
|
||||
function exitPresenter(){
|
||||
if(rehearsalActive)finishRehearsal(false);else if(timerRunning){commitRunningTime();timerRunning=false;}togglePresenterOverview(false);emit({type:'bye'});mode='deck';document.body.classList.remove('ppt-presenter');document.title=originalTitle;window.__setLowPowerMode?.(lowPowerBeforePresenter,{persist:false});
|
||||
if(rehearsalActive)finishRehearsal(false);else if(timerRunning){commitRunningTime();timerRunning=false;}togglePresenterOverview(false);emit({type:'bye'});audienceWindow=null;audienceOpenedAt=0;lastAckAt=0;lastAckIndex=-1;lastAckSeq=-1;mode='deck';document.body.classList.remove('ppt-presenter');document.title=originalTitle;window.__setLowPowerMode?.(lowPowerBeforePresenter,{persist:false});
|
||||
}
|
||||
function initAudience(){
|
||||
mode='audience';document.body.classList.add('ppt-audience');document.title=`观众屏 · ${originalTitle}`;
|
||||
@@ -2002,7 +2022,7 @@ window.__pptPresenter=(()=>{
|
||||
const resize=()=>{sizeInk(document.getElementById('ppt-audience-ink'),innerWidth,innerHeight);renderInks();};addEventListener('resize',resize);resize();
|
||||
initTransport();emit({type:'ready',index:idx});
|
||||
}
|
||||
function initPreview(){mode='preview';document.body.classList.add('ppt-preview');window.__setLowPowerMode?.(true,{persist:false});}
|
||||
function initPreview(){mode='preview';document.body.classList.add('ppt-preview');window.__setLowPowerMode?.(true,{persist:false});addEventListener('message',e=>{if(e.source===parent)receivePreview(e.data);});}
|
||||
function onSlideChange(nextIndex){
|
||||
if(mode!=='presenter')return;rollSlideTimer(nextIndex);circles=[];draftCircle=null;laserPoint=null;annotationPointerDown=false;armAutoAdvance();updateShell();sendGoto();
|
||||
}
|
||||
@@ -2013,9 +2033,9 @@ window.__pptPresenter=(()=>{
|
||||
if(mode==='deck'&&e.key?.toLowerCase()==='p'&&!e.metaKey&&!e.ctrlKey&&!e.altKey){e.preventDefault();enterPresenter(true);return true;}
|
||||
if(mode!=='presenter')return false;
|
||||
const key=e.key?.toLowerCase();
|
||||
if(e.key==='?'||key==='/'){e.preventDefault();openShortcuts();return true;}
|
||||
const dialog=document.getElementById('ppt-dialog');
|
||||
if(!dialog?.hidden){if(e.key==='Escape'){e.preventDefault();closeDialog();}return true;}
|
||||
if(e.key==='?'||key==='/'){e.preventDefault();openShortcuts();return true;}
|
||||
if(e.key==='Escape'){e.preventDefault();if(annotationTool!=='none')setAnnotationTool('none');else togglePresenterOverview();return true;}
|
||||
if(presenterOverviewOn)return true;
|
||||
if(key==='l'){e.preventDefault();setAnnotationTool('laser');return true;}
|
||||
@@ -2044,6 +2064,7 @@ window.__pptPresenter=(()=>{
|
||||
},250);
|
||||
return{initMode,onSlideChange,handleKey,slideLabel,enterPresenter,reopenAudience,toggleOverview:togglePresenterOverview,debugState:()=>({mode,idx,session,syncState:syncState(),timerRunning,rehearsalActive,presenterOverviewOn,autoEnabled,autoGlobalSeconds,autoRemainingMs,screenMode,annotationTool,circles:[...circles],audienceCircles:[...audienceCircles],layoutMode})};
|
||||
})();
|
||||
/* =============== /演讲者模式 / 观众屏同步 =============== */
|
||||
|
||||
addEventListener('keydown',e=>{
|
||||
if(window.__pptPresenter?.handleKey(e))return;
|
||||
|
||||
+33
-12
@@ -207,7 +207,7 @@
|
||||
body.ppt-audience #hint,body.ppt-audience #nav,
|
||||
body.ppt-preview #hint,body.ppt-preview #nav{display:none!important}
|
||||
body.ppt-audience{cursor:none}
|
||||
body.ppt-preview{pointer-events:none}
|
||||
body.ppt-preview{pointer-events:none}body.ppt-preview #deck{transition:none!important}
|
||||
body.ppt-presenter>#deck,body.ppt-presenter>#nav,body.ppt-presenter>#hint,
|
||||
body.ppt-presenter>.bg{visibility:hidden}
|
||||
#ppt-presenter{position:fixed;inset:0;z-index:90;display:none;min-width:0;min-height:0;overflow:hidden;background:#101216;color:#f5f6f7;font-family:Inter,"Noto Sans SC",sans-serif}
|
||||
@@ -227,9 +227,9 @@
|
||||
.ppt-stage-label{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:11px 14px;color:#aeb4be;font-size:13px;border-bottom:1px solid #292d34}
|
||||
.ppt-annotation-tools{display:flex;align-items:center;gap:5px;margin-left:auto}.ppt-annotation-tools .ppt-ui-btn{padding:6px 9px;font-size:12px}.ppt-annotation-tools .ppt-ui-btn.is-active{color:#111318;background:#ff5b63;border-color:#ff5b63}.ppt-annotation-tools .ppt-grid-btn.is-active{color:#111318;background:#edf1f5;border-color:#edf1f5}.ppt-annotation-tools .ppt-clear-btn{min-width:0}.ppt-grid-btn{display:inline-flex;align-items:center;gap:6px}.ppt-grid-icon{display:grid;grid-template-columns:repeat(2,4px);gap:2px}.ppt-grid-icon i{width:4px;height:4px;background:currentColor}
|
||||
.ppt-frame-viewport{position:relative;display:grid;place-items:center;min-width:0;min-height:0;overflow:hidden;background:#08090b}
|
||||
.ppt-frame{display:block;width:0;height:0;max-width:100%;max-height:100%;aspect-ratio:16/9;border:0;background:#08090b}.ppt-next-frame{opacity:.86}
|
||||
.ppt-frame{display:block;width:0;height:0;max-width:100%;max-height:100%;aspect-ratio:16/9;border:0;background:#08090b}.ppt-next-frame{opacity:.86}#ppt-next-card.is-end .ppt-frame{visibility:hidden}#ppt-next-card.is-end .ppt-frame-viewport::after{content:"演示结束";position:absolute;color:#727a86;font:650 14px/1 Inter,"Noto Sans SC",sans-serif;letter-spacing:.08em}
|
||||
.ppt-annotation-layer{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:4;width:0;height:0;pointer-events:none;touch-action:none}.ppt-annotation-layer.is-active{pointer-events:auto;cursor:crosshair}
|
||||
#ppt-audience-ink{position:fixed;inset:0;z-index:70;width:100vw;height:100vh;pointer-events:none}#ppt-audience-cover{position:fixed;inset:0;z-index:80;display:none;pointer-events:none}
|
||||
#ppt-audience-ink{position:fixed;inset:0;z-index:70;width:100vw;height:100vh;pointer-events:none}#ppt-audience-cover{position:fixed;inset:0;z-index:80;display:none;pointer-events:none}#ppt-audience-cover.is-ended{display:grid!important;place-items:center;background:#101216!important;color:#f5f6f7;font:650 clamp(24px,3vw,46px)/1.2 Inter,"Noto Sans SC",sans-serif;letter-spacing:.08em}
|
||||
.ppt-preview-stack.is-overview>.ppt-stage-card{display:none}.ppt-presenter-overview{grid-row:1/-1;display:grid;grid-template-rows:auto minmax(0,1fr);min-width:0;min-height:0}.ppt-presenter-overview[hidden]{display:none}.ppt-overview-head{display:flex;align-items:center;justify-content:space-between;padding:13px 15px;border-bottom:1px solid #292d34}.ppt-overview-head strong{font-size:15px}.ppt-overview-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;align-content:start;overflow:auto;padding:14px}.ppt-overview-page{appearance:none;min-height:112px;display:grid;grid-template-rows:auto 1fr auto;gap:12px;padding:13px;border:1px solid #343943;border-radius:10px;background:#111318;color:#eef1f4;text-align:left;cursor:pointer}.ppt-overview-page:hover{background:#1d2128;border-color:#636b78}.ppt-overview-page.is-current{border-color:#84a8ff;box-shadow:inset 0 0 0 1px #84a8ff}.ppt-overview-page-no{color:#8f97a3;font:600 12px/1 var(--mono,monospace)}.ppt-overview-page-title{font-size:14px;font-weight:650;line-height:1.35}.ppt-overview-page-meta{display:flex;justify-content:space-between;gap:8px;color:#7f8793;font-size:11px}
|
||||
.ppt-notes-card{display:grid;grid-template-rows:auto minmax(0,1fr);min-height:0}.ppt-notes-head{padding:16px 18px;border-bottom:1px solid #292d34}.ppt-notes-label{margin-bottom:6px;color:#848c98;font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}.ppt-notes-title{font-size:21px;font-weight:680;line-height:1.32}.ppt-purpose-block{margin-top:14px;padding:11px 12px;border-left:3px solid #84a8ff;background:#111318}.ppt-purpose-copy{color:#c9ced6;font-size:14px;line-height:1.55}.ppt-notes-draft-head{display:flex;align-items:flex-end;justify-content:space-between;gap:10px;margin-top:15px;padding-top:13px;border-top:1px solid #2d3139}.ppt-notes-draft-head .ppt-notes-label{margin:0 0 4px}.ppt-note-meta{color:#8f97a3;font-size:12px}
|
||||
.ppt-notes-tools{display:flex;align-items:center;gap:6px}.ppt-notes-tools .ppt-ui-btn{padding:7px 9px}.ppt-note-editor{width:100%;height:100%;min-height:0;resize:none;border:0;outline:0;background:#171a20;color:#edf0f3;padding:18px;font:400 var(--ppt-note-size,17px)/1.72 Inter,"Noto Sans SC",sans-serif}.ppt-note-editor:focus{box-shadow:inset 0 0 0 1px #3d4654}
|
||||
@@ -244,6 +244,7 @@
|
||||
@media(max-width:1100px){.ppt-presenter-bottom{grid-template-columns:minmax(292px,1fr) auto minmax(86px,.6fr);gap:12px}.ppt-time-stat{min-width:82px;padding:0 11px}.ppt-time-value{font-size:20px}.ppt-controls .ppt-ui-btn,.ppt-session-actions .ppt-ui-btn{min-width:60px;padding:8px 9px}}
|
||||
@media(max-width:900px){.ppt-presenter-top{padding:12px 16px;flex-wrap:wrap}.ppt-presenter-top .ppt-presenter-meta{gap:6px}.ppt-presenter-top .ppt-ui-btn{padding:8px 9px}.ppt-presenter-main,#ppt-presenter[data-layout="slides"] .ppt-presenter-main,#ppt-presenter[data-layout="notes"] .ppt-presenter-main{grid-template-columns:minmax(0,1.45fr) minmax(250px,.72fr);gap:12px;padding:12px 16px}.ppt-preview-stack{gap:12px;grid-template-rows:minmax(0,1fr) clamp(104px,20vh,150px)}.ppt-saved{display:none}.ppt-presenter-bottom{grid-template-columns:minmax(270px,1fr) auto 74px;gap:8px;padding:9px 16px}.ppt-time-stat{min-width:0;padding:0 9px}.ppt-time-value{font-size:18px}.ppt-time-hint{max-width:78px;overflow:hidden;text-overflow:ellipsis}.ppt-controls,.ppt-session-actions{gap:5px}.ppt-controls .ppt-ui-btn,.ppt-session-actions .ppt-ui-btn{min-width:52px;padding:7px 8px;font-size:12px}.ppt-page-state strong{font-size:14px}.ppt-dialog-grid{grid-template-columns:1fr}.ppt-segmented.screen{grid-template-columns:repeat(2,1fr)}}
|
||||
@media(max-height:700px){.ppt-presenter-top{padding-top:10px;padding-bottom:10px}.ppt-presenter-main{padding-top:10px;padding-bottom:10px}.ppt-preview-stack{grid-template-rows:minmax(0,1fr) clamp(88px,16vh,118px);gap:10px}.ppt-stage-label{padding:7px 10px}.ppt-notes-head{padding:12px 14px}.ppt-purpose-block{margin-top:10px;padding:8px 10px}.ppt-notes-draft-head{margin-top:10px;padding-top:9px}.ppt-presenter-bottom{padding-top:8px;padding-bottom:8px}.ppt-control-stack{gap:5px}.ppt-session-actions{padding-top:5px}}
|
||||
/* ============ /演讲者模式 ============ */
|
||||
|
||||
/* ============================================================
|
||||
============ LAYOUTS API · 面向 agent 的类(v2)============
|
||||
@@ -779,7 +780,7 @@ window.__pptPresenter=(()=>{
|
||||
|
||||
function noteAt(i){
|
||||
const id=slideId(i);
|
||||
return notes().find(n=>n.id===id)||{id,title:slides[i]?.dataset.title||`第 ${i+1} 页`,purpose:'待补充本页目的',talk:['待补充讲述要点'],transition:'待补充转场'};
|
||||
return notes().find(n=>n.id===id)||{id,title:slides[i]?.dataset.title||`第 ${i+1} 页`,purpose:'—',talk:[],transition:''};
|
||||
}
|
||||
function slideLabel(i){return `${i+1} / ${total} · ${noteAt(i).title||slideId(i)}`;}
|
||||
function escapeHTML(value){return String(value??'').replace(/[&<>"']/g,ch=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[ch]));}
|
||||
@@ -793,7 +794,7 @@ window.__pptPresenter=(()=>{
|
||||
if(n.transition)parts.push(`【转场】\n${n.transition}`);
|
||||
const optional=[['舞台提示',n.cue],['互动',n.interaction],['表达提示',n.delivery],['翻页时机',n.advance],['备用方案',n.fallback],['读音提醒',n.pronunciation]];
|
||||
optional.forEach(([label,value])=>{const text=valueLines(value);if(text)parts.push(`【${label}】\n${text}`);});
|
||||
return parts.join('\n\n');
|
||||
return parts.join('\n\n')||'—';
|
||||
}
|
||||
function noteStorageKey(id){return `guizang-ppt-note:${location.pathname}:${id}`;}
|
||||
function loadNoteValue(id,i,n){
|
||||
@@ -811,6 +812,14 @@ window.__pptPresenter=(()=>{
|
||||
url.searchParams.set('mode',targetMode);url.searchParams.set('session',session);url.searchParams.set('slide',String(i+1));
|
||||
return url.href;
|
||||
}
|
||||
function postPreviewGoto(frame,i){
|
||||
try{frame.contentWindow?.postMessage({__guizangPptSync:1,session,role:'presenter',type:'preview-goto',index:i},'*');}catch(e){}
|
||||
}
|
||||
function updatePreviewFrame(frame,i){
|
||||
frame.dataset.slide=String(i);
|
||||
if(!frame.dataset.previewBound){frame.dataset.previewBound='1';frame.addEventListener('load',()=>postPreviewGoto(frame,Number(frame.dataset.slide)));}
|
||||
if(!frame.getAttribute('src'))frame.src=frameUrl('preview',i);else postPreviewGoto(frame,i);
|
||||
}
|
||||
function plannedMsAt(i){
|
||||
const minutes=Number(noteAt(i).minutes);
|
||||
return Number.isFinite(minutes)&&minutes>0?minutes*60000:null;
|
||||
@@ -967,8 +976,9 @@ window.__pptPresenter=(()=>{
|
||||
if(mode!=='presenter')return;mountShell();
|
||||
const n=noteAt(idx),next=Math.min(idx+1,total-1),id=slideId(idx),editor=document.getElementById('ppt-note-editor');
|
||||
const currentFrame=document.getElementById('ppt-current-frame'),nextFrame=document.getElementById('ppt-next-frame');
|
||||
if(currentFrame.dataset.slide!==String(idx)){currentFrame.src=frameUrl('preview',idx);currentFrame.dataset.slide=String(idx);}
|
||||
if(nextFrame.dataset.slide!==String(next)){nextFrame.src=frameUrl('preview',next);nextFrame.dataset.slide=String(next);}
|
||||
if(currentFrame.dataset.slide!==String(idx))updatePreviewFrame(currentFrame,idx);
|
||||
if(nextFrame.dataset.slide!==String(next))updatePreviewFrame(nextFrame,next);
|
||||
document.getElementById('ppt-next-card').classList.toggle('is-end',idx===total-1);
|
||||
document.getElementById('ppt-current-label').textContent=`${idx+1} / ${total}`;
|
||||
document.getElementById('ppt-next-label').textContent=idx===total-1?'已到尾页':`${next+1} / ${total}`;
|
||||
document.getElementById('ppt-notes-title').textContent=n.title||`第 ${idx+1} 页`;
|
||||
@@ -1075,8 +1085,13 @@ window.__pptPresenter=(()=>{
|
||||
}
|
||||
function applyAudienceScreen(value){
|
||||
const cover=document.getElementById('ppt-audience-cover');if(!cover)return;
|
||||
cover.classList.remove('is-ended');cover.textContent='';
|
||||
if(value==='black'||value==='white'){cover.style.display='block';cover.style.background=value;}else cover.style.display='none';
|
||||
}
|
||||
function showAudienceEnded(){
|
||||
const cover=document.getElementById('ppt-audience-cover');if(cover){cover.style.display='';cover.style.background='';cover.textContent='演示已结束';cover.classList.add('is-ended');}
|
||||
setTimeout(()=>{try{window.close();}catch(e){}},120);
|
||||
}
|
||||
function setScreenMode(value){
|
||||
const next=['normal','black','white','frozen'].includes(value)?value:'normal',wasFrozen=audienceFrozen;
|
||||
screenMode=next;audienceFrozen=next==='frozen';emit({type:'screen',mode:next});
|
||||
@@ -1136,6 +1151,7 @@ window.__pptPresenter=(()=>{
|
||||
return;
|
||||
}
|
||||
if(mode!=='audience')return;
|
||||
if(message.type==='bye'){showAudienceEnded();return;}
|
||||
if(message.type==='screen'){applyAudienceScreen(message.mode);return;}
|
||||
if(message.type==='laser'&&Number(message.index)===idx){audienceLaser=message.point||null;audienceLaserHideAt=Date.now()+650;renderInks();return;}
|
||||
if(message.type==='circle'&&Number(message.index)===idx&&message.circle){audienceCircles.push(message.circle);renderInks();return;}
|
||||
@@ -1145,14 +1161,18 @@ window.__pptPresenter=(()=>{
|
||||
emit({type:'ack',index:idx,seq:Number(message.seq)});
|
||||
}
|
||||
}
|
||||
function receivePreview(message){
|
||||
if(!message||message.__guizangPptSync!==1||message.session!==session||message.role!=='presenter'||message.type!=='preview-goto')return;
|
||||
go(Number(message.index),{force:true});
|
||||
}
|
||||
function sendGoto(force=false){
|
||||
if(mode!=='presenter'||audienceFrozen)return;if(force||lastAckIndex!==idx)seq++;
|
||||
emit({type:'goto',index:idx,seq,screenMode,circles});updateSyncStatus();
|
||||
}
|
||||
function syncState(){
|
||||
if(popupBlocked)return'blocked';if(audienceWindow&&audienceWindow.closed)return'disconnected';if(audienceFrozen)return'frozen';
|
||||
if(!lastAckAt)return audienceOpenedAt&&Date.now()-audienceOpenedAt<2600?'connecting':(audienceOpenedAt?'unsynced':'disconnected');
|
||||
if(Date.now()-lastAckAt>2600||lastAckIndex!==idx||lastAckSeq<seq)return'unsynced';return'synced';
|
||||
if(!lastAckAt)return audienceOpenedAt&&Date.now()-audienceOpenedAt<2600?'connecting':'disconnected';
|
||||
if(Date.now()-lastAckAt>2600)return'disconnected';if(lastAckIndex!==idx||lastAckSeq<seq)return'unsynced';return'synced';
|
||||
}
|
||||
function updateSyncStatus(){
|
||||
const el=document.getElementById('ppt-sync');if(!el)return;const state=syncState();
|
||||
@@ -1171,7 +1191,7 @@ window.__pptPresenter=(()=>{
|
||||
window.__setLowPowerMode?.(true,{persist:false});updateShell();armAutoAdvance();if(openAudience)reopenAudience();
|
||||
}
|
||||
function exitPresenter(){
|
||||
if(rehearsalActive)finishRehearsal(false);else if(timerRunning){commitRunningTime();timerRunning=false;}togglePresenterOverview(false);emit({type:'bye'});mode='deck';document.body.classList.remove('ppt-presenter');document.title=originalTitle;window.__setLowPowerMode?.(lowPowerBeforePresenter,{persist:false});
|
||||
if(rehearsalActive)finishRehearsal(false);else if(timerRunning){commitRunningTime();timerRunning=false;}togglePresenterOverview(false);emit({type:'bye'});audienceWindow=null;audienceOpenedAt=0;lastAckAt=0;lastAckIndex=-1;lastAckSeq=-1;mode='deck';document.body.classList.remove('ppt-presenter');document.title=originalTitle;window.__setLowPowerMode?.(lowPowerBeforePresenter,{persist:false});
|
||||
}
|
||||
function initAudience(){
|
||||
mode='audience';document.body.classList.add('ppt-audience');document.title=`观众屏 · ${originalTitle}`;
|
||||
@@ -1179,7 +1199,7 @@ window.__pptPresenter=(()=>{
|
||||
const resize=()=>{sizeInk(document.getElementById('ppt-audience-ink'),innerWidth,innerHeight);renderInks();};addEventListener('resize',resize);resize();
|
||||
initTransport();emit({type:'ready',index:idx});
|
||||
}
|
||||
function initPreview(){mode='preview';document.body.classList.add('ppt-preview');window.__setLowPowerMode?.(true,{persist:false});}
|
||||
function initPreview(){mode='preview';document.body.classList.add('ppt-preview');window.__setLowPowerMode?.(true,{persist:false});addEventListener('message',e=>{if(e.source===parent)receivePreview(e.data);});}
|
||||
function onSlideChange(nextIndex){
|
||||
if(mode!=='presenter')return;rollSlideTimer(nextIndex);circles=[];draftCircle=null;laserPoint=null;annotationPointerDown=false;armAutoAdvance();updateShell();sendGoto();
|
||||
}
|
||||
@@ -1190,9 +1210,9 @@ window.__pptPresenter=(()=>{
|
||||
if(mode==='deck'&&e.key?.toLowerCase()==='p'&&!e.metaKey&&!e.ctrlKey&&!e.altKey){e.preventDefault();enterPresenter(true);return true;}
|
||||
if(mode!=='presenter')return false;
|
||||
const key=e.key?.toLowerCase();
|
||||
if(e.key==='?'||key==='/'){e.preventDefault();openShortcuts();return true;}
|
||||
const dialog=document.getElementById('ppt-dialog');
|
||||
if(!dialog?.hidden){if(e.key==='Escape'){e.preventDefault();closeDialog();}return true;}
|
||||
if(e.key==='?'||key==='/'){e.preventDefault();openShortcuts();return true;}
|
||||
if(e.key==='Escape'){e.preventDefault();if(annotationTool!=='none')setAnnotationTool('none');else togglePresenterOverview();return true;}
|
||||
if(presenterOverviewOn)return true;
|
||||
if(key==='l'){e.preventDefault();setAnnotationTool('laser');return true;}
|
||||
@@ -1221,6 +1241,7 @@ window.__pptPresenter=(()=>{
|
||||
},250);
|
||||
return{initMode,onSlideChange,handleKey,slideLabel,enterPresenter,reopenAudience,toggleOverview:togglePresenterOverview,debugState:()=>({mode,idx,session,syncState:syncState(),timerRunning,rehearsalActive,presenterOverviewOn,autoEnabled,autoGlobalSeconds,autoRemainingMs,screenMode,annotationTool,circles:[...circles],audienceCircles:[...audienceCircles],layoutMode})};
|
||||
})();
|
||||
/* =============== /演讲者模式 / 观众屏同步 =============== */
|
||||
|
||||
addEventListener('keydown',e=>{
|
||||
if(window.__pptPresenter?.handleKey(e))return;
|
||||
|
||||
Reference in new issue
Block a user