upgrade: adopt V8.32.0-dev.1 (theme preview iframe fix, editor simple mode)
Overlay 46 upstream items; full patch set re-applied (all patched files reset by overlay regardless of upstream change status — lesson recorded). Verified: theme suites 35/35; dual-baseline 418 passed vs pristine 389+29 ours, FAILED-set diff EMPTY (same 10 Windows env fails). Live: container 8.32.0-dev.1 healthy, hesupipe 192 entries intact, trade-pro build 203 pages 0 errors. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -156,3 +156,18 @@ iframe{min-height:590px;height:calc(100vh - 224px)}
|
||||
.studio-body .left-pane,.studio-body .right-pane{top:140px!important}
|
||||
.studio-actions-menu{right:0;max-width:calc(100vw - 18px)}
|
||||
}
|
||||
|
||||
/* V8.32: first-use focused studio without removing advanced capabilities. */
|
||||
.sf-next-action{margin-left:auto;font-size:12px;color:#30516b;font-weight:650;background:#eef4f8;padding:6px 10px;border-radius:7px;white-space:normal}
|
||||
.sf-inspector-mode{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:9px 14px 12px;border-bottom:1px solid #eef1f4;color:#66798a;font-size:11px}
|
||||
.sf-inspector-mode button{background:#f5f8fb;border:1px solid #dce5ee;border-radius:7px;padding:8px 10px;color:#285276;font-weight:700;cursor:pointer;font-size:11px}
|
||||
body:not(.sf-advanced-mode) #tabStyle,body:not(.sf-advanced-mode) #tabResponsive{display:none!important}
|
||||
.sf-photo-action{border:1px solid #dbe9f5;background:#f6fafd;border-radius:10px;display:grid;gap:7px;padding:12px;margin:14px 0}
|
||||
.sf-photo-action button{width:100%;justify-content:center}
|
||||
.sf-photo-action small{font-size:11px;color:#64778b;line-height:1.5}
|
||||
.sf-close-inspector{display:none;background:white;border:1px solid #d8e1ea;border-radius:8px;padding:7px 10px;color:#385872;cursor:pointer;font-size:11px}
|
||||
.sf-steps{justify-content:flex-start}.sf-steps .sf-guide-link{margin-left:0}
|
||||
@media(max-width:1060px){.sf-close-inspector{display:inline-flex}.sf-next-action{display:none}}
|
||||
@media(max-width:720px){.sf-steps .sf-guide-link{margin-left:auto}.sf-inspector-mode{padding:8px 11px}}
|
||||
|
||||
.sf-photo-action strong{font-size:13px;color:#28516e}.sf-direct-upload{display:grid;gap:7px;color:#506b82;font-size:12px;font-weight:650}.sf-direct-upload input{font-size:11px;width:100%;max-width:100%}
|
||||
|
||||
+30
-8
@@ -13,6 +13,7 @@ let libraryOpen=false;
|
||||
let sharedPreview=null;
|
||||
let siteNavDraft=[],siteDesignReviewToken=null;
|
||||
let selectedChildId=null;
|
||||
let advancedMode=false,themePreviewSeq=0,themePreviewAbort=null;
|
||||
let inspectorTab='content',paletteSearch='',blockSearch='',previewRequest=0,previewController=null,savePromise=null,lastContinuousEdit=0,insertAfterId=null;
|
||||
|
||||
let snapshots=[],snapshotCursor=-1,draggedChild=null,draftRevision=0,siteDesign=null,siteDesignRevision=0,siteDesignPreview=null;
|
||||
@@ -284,24 +285,40 @@ const Studio={
|
||||
filterPalette(value){paletteSearch=String(value||'').slice(0,70);Studio.renderPalette()},
|
||||
clearPaletteSearch(){paletteSearch='';const inp=$('#paletteSearch');if(inp){inp.value='';inp.focus()}Studio.renderPalette()},
|
||||
showThemePreview(){const dialog=$('#themePreviewModal');if(!dialog)return;const current=['automotive','industrial','corporate','minimal'].includes(site?.theme)?site.theme:'corporate';$('#themePreviewTheme').value=current;if(!dialog.open)dialog.showModal();Studio.themeDevice('desktop');Studio.updateThemePreview()},
|
||||
closeThemePreview(){const dialog=$('#themePreviewModal');if(dialog?.open)dialog.close();const frame=$('#themePreviewFrame');if(frame)frame.removeAttribute('src')},
|
||||
closeThemePreview(){themePreviewSeq++;themePreviewAbort?.abort();const dialog=$('#themePreviewModal');if(dialog?.open)dialog.close();const frame=$('#themePreviewFrame');if(frame){frame.removeAttribute('src');frame.removeAttribute('srcdoc')}},
|
||||
themeDevice(device){
|
||||
const width={desktop:'100%',tablet:'780px',phone:'390px'}[device];if(!width)return;
|
||||
$('#themePreviewFrameShell').style.width=width;
|
||||
document.querySelectorAll('[data-theme-device]').forEach(btn=>btn.setAttribute('aria-pressed',String(btn.dataset.themeDevice===device)));
|
||||
},
|
||||
updateThemePreview(){
|
||||
async updateThemePreview(){
|
||||
const theme=$('#themePreviewTheme')?.value,page=$('#themePreviewPage')?.value;
|
||||
const url=window.SiteForgeStudioExperience.previewUrl(theme,page);
|
||||
if(!url)return;
|
||||
const frame=$('#themePreviewFrame'),status=$('#themePreviewStatus');if(!frame)return;
|
||||
status.textContent='正在加载主题示例…(不影响已保存的页面)';
|
||||
frame.onload=()=>{if($('#themePreviewModal')?.open)status.textContent='已加载示例。可切换主题、页面类型和设备继续比较。'};
|
||||
frame.onerror=()=>{status.textContent='示例加载失败,请稍后重试。'};
|
||||
frame.src=url;
|
||||
const frame=$('#themePreviewFrame'),status=$('#themePreviewStatus'),retry=$('#themePreviewRetry');if(!frame)return;
|
||||
const seq=++themePreviewSeq;
|
||||
themePreviewAbort?.abort();themePreviewAbort=new AbortController();
|
||||
status.textContent='正在检查主题预览…';retry.hidden=true;frame.removeAttribute('src');frame.removeAttribute('srcdoc');
|
||||
try{
|
||||
const response=await fetch(url,{credentials:'same-origin',signal:themePreviewAbort.signal,cache:'no-store'});
|
||||
if(!response.ok||!(response.headers.get('content-type')||'').includes('text/html'))throw Error(response.status===401?'登录已过期':`服务返回 ${response.status}`);
|
||||
const content=await response.text();
|
||||
if(seq!==themePreviewSeq||!$('#themePreviewModal')?.open)return;
|
||||
// srcdoc keeps the preview in an opaque sandboxed origin: no allow-same-origin,
|
||||
// no repeated HTML request, no frame-header conflict, and no access to editor data.
|
||||
const base=new URL(url,['http:','https:'].includes(location.protocol)?location.href:'https://siteforge.invalid').href;
|
||||
const safeBase=html(base);
|
||||
const withBase=/<head(?:\s[^>]*)?>/i.test(content)?content.replace(/<head(\s[^>]*)?>/i,(match)=>match+`<base href=\"${safeBase}\">`):`<base href=\"${safeBase}\">`+content;
|
||||
status.textContent='正在渲染主题页面…';
|
||||
frame.onload=()=>{if(seq===themePreviewSeq&&$('#themePreviewModal')?.open)status.textContent='预览已显示 · 可切换主题和设备';};
|
||||
frame.srcdoc=withBase;
|
||||
}catch(error){
|
||||
if(seq!==themePreviewSeq||error.name==='AbortError')return;
|
||||
status.textContent='预览失败:'+error.message+'。请点击重新加载或在完整主题图库中打开。';retry.hidden=false;
|
||||
}
|
||||
}, toggleLibrary(force){libraryOpen=typeof force==='boolean'?force:!libraryOpen;const el=$('#sfLibraryPanel'),btn=$('#sfAddBlock');if(el)el.hidden=!libraryOpen;if(btn){btn.setAttribute('aria-expanded',String(libraryOpen));btn.textContent=libraryOpen?'× 收起区块库':'+ 添加内容区块'};Studio.updateGuidance()},
|
||||
showHelp(){const dlg=$('#sfGuideDialog');if(dlg&&!dlg.open)dlg.showModal()},
|
||||
updateGuidance(){const one=$('#sfStep1'),two=$('#sfStep2'),three=$('#sfStep3');if(!one||!two||!three)return;one.classList.toggle('active',selected<0||libraryOpen);two.classList.toggle('active',selected>=0&&!dirty&&!libraryOpen);three.classList.toggle('active',dirty);},
|
||||
updateGuidance(){const one=$('#sfStep1'),two=$('#sfStep2'),three=$('#sfStep3');if(!one||!two||!three)return;one.classList.toggle('active',selected<0||libraryOpen);two.classList.toggle('active',selected>=0&&!dirty&&!libraryOpen);three.classList.toggle('active',dirty);const note=$('#sfNextAction');if(note)note.textContent=dirty?'更改尚未保存:点击右上角「保存草稿」':libraryOpen?'选择一种内容,添加后直接修改文字或图片':selected>=0?'正在编辑「'+(schema?.blocks?.[blocks[selected]?.type]?.name||'当前区块')+'」,右侧可直接修改':'先在左侧添加区块或选中页面内容';},
|
||||
draw(){
|
||||
const list=$('#blockList');$('#blockCount').textContent=blocks.length+' 区块';
|
||||
const found=editorTools.filterBlocks(blocks,blockSearch,schema.blocks);
|
||||
@@ -315,6 +332,8 @@ const Studio={
|
||||
blockKeydown(event,i){if(event.target!==event.currentTarget)return;if(event.key==='Enter'||event.key===' '){event.preventDefault();Studio.select(i)}else if(event.altKey && (event.key==='ArrowUp'||event.key==='ArrowDown')){event.preventDefault();Studio.moveBlock(i,event.key==='ArrowUp'?-1:1)}},
|
||||
changeInspectorTab(tab){if(!['content','style','responsive'].includes(tab))return;inspectorTab=tab;Studio.applyInspectorTab()},
|
||||
applyInspectorTab(){for(const key of ['content','style','responsive']){const active=key===inspectorTab;const btn=$('#tab'+key.charAt(0).toUpperCase()+key.slice(1));btn?.setAttribute('aria-selected',String(active));const pane=$('[data-inspector-section="'+key+'"]');if(pane)pane.hidden=!active}},
|
||||
toggleAdvanced(){advancedMode=!advancedMode;document.body.classList.toggle('sf-advanced-mode',advancedMode);const button=$('#studioAdvancedButton');button?.setAttribute('aria-pressed',String(advancedMode));if(button)button.textContent=advancedMode?'收起高级设置':'更多设计设置';const detail=$('#sfModeExplanation');if(detail)detail.textContent=advancedMode?'可调整布局、样式和手机显示':'当前显示常用设置';if(!advancedMode){inspectorTab='content';Studio.applyInspectorTab()}},
|
||||
closePane(){document.body.classList.remove('show-inspector','show-structure')},
|
||||
togglePane(which){const type=which==='left'?'show-structure':'show-inspector';document.body.classList.toggle(type);if(type==='show-structure')document.body.classList.remove('show-inspector');else document.body.classList.remove('show-structure');},
|
||||
updateHistoryButtons(){const state=editorTools.historyState(snapshots,snapshotCursor);for(const id of ['#studioUndo','#quickUndo']){const el=$(id);if(el)el.disabled=!state.canUndo}for(const id of ['#studioRedo','#quickRedo']){const el=$(id);if(el)el.disabled=!state.canRedo}},
|
||||
|
||||
@@ -362,6 +381,9 @@ const Studio={
|
||||
if(['title','subtitle','description','image','body'].includes(field))out+='<small class="prop-tip">可输入 {{site.name}}、{{page.title}} 等变量。</small>';
|
||||
out+='</div>';
|
||||
}
|
||||
const mediaTarget=selectedChildId?editorTools.findChildInRoot(blocks,b.id,selectedChildId)?.child:b;
|
||||
const mediaFields=schema.blocks[mediaTarget?.type]?.fields||[];
|
||||
if(mediaTarget&&(['gallery','carousel'].includes(mediaTarget.type)||mediaFields.includes('image')))out+=`<div class="sf-photo-action"><strong>图片设置</strong><button class="ui-btn ghost" type="button" onclick="Studio.chooseMedia()">从图片素材库选择</button><label class="sf-direct-upload">或上传一张新图片<input aria-label="上传新图片" type="file" accept="image/png,image/jpeg,image/webp,image/gif,image/avif" onchange="Studio.uploadImage(this.files[0]);this.value=''"></label><small>预览先显示在草稿里,点击保存后才会保留。</small></div>`;
|
||||
if(b.type==='layout')out+=Studio.childQuickEditor(b);
|
||||
out+='</div><div data-inspector-section="responsive">';
|
||||
if(b.type==='layout'){
|
||||
|
||||
@@ -123,7 +123,7 @@ function content(){if(!currentSite())return noSite();let arr=state.entries.filte
|
||||
(arr.length?`<div class="table-wrap"><table class="data-table"><thead><tr><th>名称</th><th>内容类型</th><th>页面地址</th><th>状态</th><th>操作</th></tr></thead><tbody>${arr.slice(0,200).map(e=>`<tr><td><strong>${esc(e.title)}</strong></td><td>${esc(typeName[e.type]||e.type)}</td><td class="muted">${esc(e.route)}</td><td><span class="pill ${e.status==='draft'?'warn':'success'}">${e.status==='draft'?'草稿':'已保存'}</span></td><td class="action-cell"><button class="btn btn-tiny" data-action="edit-entry" data-id="${esc(e.id)}">修改内容</button> <a class="btn btn-tiny" href="/editor/${encodeURIComponent(state.site.id)}/${encodeURIComponent(e.id)}">设计页面 ↗</a></td></tr>`).join('')}</tbody></table></div>`:emptyState('没有找到内容','可以清除筛选条件,或者添加新内容。',actionButton('+ 添加内容','new-entry')))+
|
||||
`${arr.length>200?'<p class="muted">当前显示前 200 条,请使用搜索缩小范围。</p>':''}</div>`;
|
||||
}
|
||||
function design(){if(!currentSite())return noSite();const s=state.site;const cards=Object.entries(themeName).map(([id,name])=>`<div class="theme-card"><div class="theme-preview ${id}">${name}</div><div class="theme-desc"><h3>${name} ${s.theme===id?'<span class="pill success">当前使用</span>':''}</h3><p>${({automotive:'适合汽车出口、车型及品牌展示',industrial:'适合制造业、产品与技术参数',corporate:'适合集团公司、服务和案例',minimal:'适合作品展示和品牌形象','trade-pro':'适合外贸 B2B 英文站点与询盘'})[id]}</p><button class="btn btn-tiny ${s.theme===id?'btn-muted':'btn-primary'}" ${s.theme===id?'disabled':''} data-action="set-theme" data-theme="${id}">${s.theme===id?'正在使用':'使用此主题'}</button></div></div>`).join('');
|
||||
function design(){if(!currentSite())return noSite();const s=state.site;const cards=Object.entries(themeName).map(([id,name])=>`<div class="theme-card"><div class="theme-preview ${id}">${name}</div><div class="theme-desc"><h3>${name} ${s.theme===id?'<span class="pill success">当前使用</span>':''}</h3><p>${({automotive:'适合汽车出口、车型及品牌展示',industrial:'适合制造业、产品与技术参数',corporate:'适合集团公司、服务和案例',minimal:'适合作品展示和品牌形象','trade-pro':'适合外贸 B2B 英文站点与询盘'})[id]}</p><button class="btn btn-tiny ${s.theme===id?'btn-muted':'btn-primary'}" ${s.theme===id?'disabled':''} data-action="set-theme" data-theme="${id}">${s.theme===id?'正在使用':'使用此主题'}</button><a class="btn btn-tiny btn-muted" href="/theme-gallery?theme=${encodeURIComponent(id)}" target="_blank" rel="noopener">预览页面效果</a></div></div>`).join('');
|
||||
return htmlHeading('外观与设计','先选一套网站风格,再打开可视化编辑器修改图文、导航和手机端布局。')+
|
||||
`<div class="section-heading"><div><h2>第一步 · 选择行业主题</h2><p>更换主题不会删除您已经录入的业务内容和 URL。</p></div><a href="/theme-gallery" class="btn btn-tiny">查看完整主题预览 ↗</a></div><div class="choice-cards">${cards}</div>`+
|
||||
`<div class="section-heading"><div><h2>第二步 · 设计网页</h2><p>挑选要修改的页面;可在设计器中编辑导航、页眉、页脚及各设备布局。</p></div></div><div class="panel"><div class="panel-head"><div><h2>选择要设计的页面</h2><p>修改先保存为草稿,正式发布设计后才会参与下一次静态构建。</p></div></div><div class="grid-2 grid-equal">${state.entries.filter(e=>e.type==='page').slice(0,8).map(e=>`<a class="site-card" href="/editor/${encodeURIComponent(s.id)}/${encodeURIComponent(e.id)}"><span class="site-icon">▤</span><span><h3>${esc(e.title)}</h3><p>${esc(e.route)}</p></span><span class="arrow">›</span></a>`).join('')||'<div class="muted">尚无页面,请先添加内容。</div>'}</div></div><div class="help-hint" style="margin-top:19px"><strong>提示</strong>:网站设置用于公司信息和域名;可视化编辑器用于调整页面外观。两者不会混在同一表单里。</div>`;
|
||||
|
||||
Reference in New Issue
Block a user