Files
cms-SiteForge/app/templates/editor.html
T
浅念 8884e100f9 upgrade: adopt V8.31.1 (theme 1.3/1.4 redesigns, editor deep-canvas, guided launch, component library)
Overlay 190 upstream items (V8.22→8.31) preserving trade-pro theme,
registry tests, and design docs. Re-applied full patch set on identical
anchors (discovery/env_for/blocks.css/type-mapping/locale-override/
theme_color/frontend entries/test_theme_pro_v3 mods) plus compose pins.

Verified: theme suites 35/35; dual-baseline full run 415 passed vs
pristine 386+29 ours, FAILED-set diff EMPTY (same 10 Windows env fails).
Live: container 8.31.1-dev.1 healthy, hesupipe 192 entries intact,
trade-pro build 203 pages 0 errors.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-26 09:43:17 +08:00

152 lines
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>SiteForge Studio · 可视化建站</title><link rel="stylesheet" href="/ui/editor.css"><script defer src="/ui/editor-helpers.js"></script><script defer src="/ui/studio-experience-v829.js"></script><script defer src="/ui/editor.js"></script><link rel="stylesheet" href="/ui/professional-ui.css"><script defer src="/ui/professional-ui.js"></script></head>
<body data-sf-page="editor">
<div class="studio">
<header class="studio-top sf-easy-top">
<div class="brand"><a href="/" title="返回网站管理">◈</a><div><b>SiteForge</b><small>页面编辑</small></div></div>
<div class="file-name sf-easy-file"><small id="siteName">加载中</small><strong id="pageName">页面编辑器</strong></div>
<button type="button" id="studioThemePreviewButton" class="ui-btn ghost sf-theme-preview-entry" onclick="Studio.showThemePreview()" title="不影响当前网站,先比较四套主题">◫ 主题效果</button>
<div class="sf-pane-controls"><button type="button" onclick="Studio.togglePane('left')">☰ 内容</button><button type="button" onclick="Studio.togglePane('right')">⚙ 编辑</button></div>
<div class="top-center sf-easy-device" role="group" aria-label="预览设备">
<button id="deviceDesktop" class="icon-btn on" onclick="Studio.device('desktop')" title="电脑预览" aria-label="电脑预览">电脑</button>
<button id="deviceTablet" class="icon-btn" onclick="Studio.device('tablet')" title="平板预览" aria-label="平板预览">平板</button>
<button id="devicePhone" class="icon-btn" onclick="Studio.device('phone')" title="手机预览" aria-label="手机预览">手机</button>
</div>
<span id="saveStatus" class="save-status sf-easy-save-status" role="status" aria-live="polite">读取中…</span>
<button id="saveDraftButton" type="button" class="ui-btn ghost sf-save-btn" onclick="Studio.save()">保存草稿</button>
<button id="publishDesignButton" type="button" class="ui-btn primary sf-publish-btn" onclick="Studio.publishDesign()">发布设计</button>
<button type="button" id="quickUndo" class="sf-history-quick" onclick="Studio.undo()" title="撤销上一步 (Ctrl+Z)" aria-label="撤销上一步" disabled>↶</button><button type="button" id="quickRedo" class="sf-history-quick" onclick="Studio.redo()" title="重做 (Ctrl+Shift+Z)" aria-label="重做" disabled>↷</button>
<details class="studio-actions"><summary title="其他功能">更多 ▾</summary><div class="studio-actions-menu"><button type="button" class="ui-btn ghost sf-more-theme" onclick="Studio.showThemePreview()">◫ 比较四套主题效果</button>
<button id="studioUndo" class="ui-btn ghost" onclick="Studio.undo()" disabled>↶ 撤销</button>
<button id="studioRedo" class="ui-btn ghost" onclick="Studio.redo()" disabled>↷ 重做</button>
<button class="ui-btn ghost" onclick="Studio.showHistory()">版本历史</button><button class="ui-btn ghost" onclick="Studio.showSharedComponents()">管理公共组件</button>
<button class="ui-btn ghost" onclick="Studio.showSiteDesign()">全站页眉与页脚</button>
<button class="ui-btn ghost" onclick="Studio.showTokens()">全站设计规范</button>
<button class="ui-btn ghost" onclick="Studio.refreshPreview()">刷新预览</button>
<button class="ui-btn ghost" onclick="Studio.buildSite()">构建静态网站</button>
<button class="ui-btn ghost" onclick="Studio.discardDraft()">放弃草稿</button>
</div></details>
</header>
<div class="sf-steps" aria-label="编辑操作指引"><div class="sf-steps-label">只需 3 步</div><span class="sf-step" id="sfStep1">① 点击页面中的内容</span><span class="sf-step-separator">→</span><span class="sf-step" id="sfStep2">② 直接编辑或调整布局</span><span class="sf-step-separator">→</span><span class="sf-step" id="sfStep3">③ 保存并发布</span><button type="button" class="sf-guide-link" onclick="Studio.showHelp()">新手使用指南 ?</button></div>
<div class="studio-body">
<aside class="left-pane" aria-label="页面内容和区块">
<div class="pane-heading"><div><span class="overline">页面内容</span><h3>编辑页面</h3></div><span class="chip" id="blockCount">0 个区块</span></div>
<div class="field sf-page-picker"><label for="pageSelect">当前编辑的页面</label><select id="pageSelect" onchange="Studio.choosePage(this.value)"></select></div>
<div class="sf-global-entry"><button type="button" class="ui-btn ghost" onclick="Studio.showSiteDesign()">☰ 编辑全站菜单、页眉与页脚</button><small>改一次,全站下一次构建统一生效</small></div>
<div class="sf-add-area"><button type="button" id="sfAddBlock" class="sf-add-button" aria-expanded="false" aria-controls="sfLibraryPanel" onclick="Studio.toggleLibrary()">+ 添加内容区块</button><p>例如图片横幅、公司简介、产品列表等</p></div>
<section id="sfLibraryPanel" class="sf-library-panel" hidden aria-label="添加区块"><div class="sf-panel-caption">点击类型即可添加到当前页面 <button type="button" onclick="Studio.toggleLibrary(false)" aria-label="收起添加面板">收起 ×</button></div><div class="sf-palette-filter"><label class="sr-only" for="paletteSearch">查找内容组件</label><input id="paletteSearch" type="search" placeholder="搜索:横幅、图片、文字…" autocomplete="off" oninput="Studio.filterPalette(this.value)"><button type="button" aria-label="清空组件搜索" onclick="Studio.clearPaletteSearch()">清除</button></div><div id="paletteSummary" class="sf-palette-summary" role="status"></div><div class="palette sf-palette-categories" id="palette"></div><details class="sf-subsection"><summary>从我的组件库添加</summary><p style="font-size:11px;padding:0 9px;color:#7a8795">复制:独立编辑 · 关联插入:后续可选择同步新版</p><div class="palette" id="reusablePalette"></div></details></section>
<div class="section-label">当前页面的内容 <span class="section-caption">点击一项进行编辑</span></div>
<div class="structure-filter"><label for="blockSearch" class="sr-only">搜索页面内容</label><input id="blockSearch" type="search" placeholder="查找横幅、文字、产品…" autocomplete="off" oninput="Studio.filter(this.value)"><button type="button" onclick="Studio.clearFilter()" aria-label="清除搜索">×</button></div>
<div id="sfInsertHint" class="sf-insert-hint" role="status" hidden></div><div id="blockList" class="block-list" role="list" aria-label="当前页面区块"></div>
<p class="structure-hint">支持从左侧拖动排序,也可以直接使用画布上的操作条。</p>
<details class="sf-advanced"><summary>高级页面设置 <span>模板、布局和组件保存</span></summary>
<div class="field"><label for="pageTemplate">页面模板</label><select id="pageTemplate" onchange="Studio.changeTemplateKind(this.value)"></select></div>
<div class="field"><label for="layoutMode">排版方式</label><select id="layoutMode" onchange="Studio.setLayoutMode(this.value)"><option value="append">保留原页面,追加区块</option><option value="replace">用这些区块重新排版页面</option></select></div>
<div class="sf-advanced-buttons"><button type="button" class="ui-btn ghost" onclick="Studio.showSharedComponents()">管理公共组件与同步更新</button><button type="button" class="ui-btn ghost" onclick="Studio.resetPreset()">使用模板预设布局</button><button type="button" class="ui-btn ghost" onclick="Studio.saveReusable()">将所选区块存为组件</button></div>
<p class="sf-advanced-note">更换模板预设可能替换当前草稿,请先保存;不会直接改变在线网站。</p>
</details>
</aside>
<section class="preview-workspace"><div class="preview-head"><span class="live-dot" id="previewDot"></span><span id="previewState" role="status" aria-live="polite">实时预览</span><code id="routeDisplay">/</code><span class="preview-note">单击区块或列内组件即可编辑 · 拖动 ⠿ 可排序 · 拖动列间分隔线可调宽</span></div><div class="stage"><div class="device-frame" id="deviceFrame"><iframe id="sitePreview" title="页面预览" sandbox="allow-scripts" referrerpolicy="no-referrer"></iframe></div></div>
<div class="stage-footer"><span id="deviceDetails">桌面端 · 自适应宽度</span><span>当前是草稿预览,不是线上网站</span></div></section>
<aside class="right-pane"><div class="pane-heading"><div><span class="overline">步骤 2 · 修改内容</span><h3>编辑选中的区块</h3></div><span class="chip" id="blockTypeLabel">页面</span></div>
<div class="inspector-nav" role="tablist" aria-label="属性编辑分类"><button type="button" role="tab" id="tabContent" aria-selected="true" onclick="Studio.changeInspectorTab('content')">内容</button><button type="button" role="tab" id="tabStyle" aria-selected="false" onclick="Studio.changeInspectorTab('style')">样式</button><button type="button" role="tab" id="tabResponsive" aria-selected="false" onclick="Studio.changeInspectorTab('responsive')">手机/平板</button></div>
<div class="inspector" id="inspector"><div class="no-selection">直接点击中间画布的任意区块,即可开始编辑。</div></div>
<details class="right-foot sf-advanced-foot"><summary>高级:动态数据变量</summary><p>支持 <code>{{site.name}}</code>、<code>{{page.title}}</code> 等变量;动态内容列表可以按网站内容类型绑定。</p></details>
</aside>
</div>
<dialog id="themePreviewModal" class="sf-theme-showcase" aria-labelledby="themePreviewTitle">
<div class="sf-showcase-head"><div><small>仅预览 · 不修改网站内容</small><h2 id="themePreviewTitle">选择适合网站的主题效果</h2><p>先比较布局和手机显示效果,再决定是否到「网站设计」中应用主题。</p></div><button type="button" class="ui-btn ghost" onclick="Studio.closeThemePreview()" aria-label="关闭主题预览">关闭 ×</button></div>
<div class="sf-showcase-tools"><label>主题风格<select id="themePreviewTheme" onchange="Studio.updateThemePreview()"><option value="automotive">汽车与出行</option><option value="industrial">工业与制造</option><option value="corporate">企业品牌</option><option value="minimal">简约展示</option></select></label><label>参考页面<select id="themePreviewPage" onchange="Studio.updateThemePreview()"><option value="home">首页</option><option value="listing">产品列表</option><option value="product">产品详情</option><option value="article">文章详情</option><option value="about">关于我们</option><option value="contact">联系我们</option></select></label><div class="sf-showcase-device" role="group" aria-label="主题参考设备"><button type="button" data-theme-device="desktop" aria-pressed="true" onclick="Studio.themeDevice('desktop')">电脑</button><button type="button" data-theme-device="tablet" aria-pressed="false" onclick="Studio.themeDevice('tablet')">平板</button><button type="button" data-theme-device="phone" aria-pressed="false" onclick="Studio.themeDevice('phone')">手机</button></div></div>
<p class="sf-showcase-status" id="themePreviewStatus" role="status" aria-live="polite">示例使用主题最新版本,可能与你网站锁定的主题版本不同。不会修改当前页面。</p><div class="sf-showcase-stage"><div id="themePreviewFrameShell" class="sf-showcase-frame"><iframe id="themePreviewFrame" title="主题示例页面" sandbox="allow-scripts" referrerpolicy="no-referrer" loading="lazy"></iframe></div></div>
<div class="sf-showcase-footer"><span>预览不会保存、更换或发布主题。确认效果后请到网站设计里操作。</span><a class="ui-btn ghost" href="/theme-gallery" target="_blank" rel="noopener">打开完整主题图库 ↗</a></div>
</dialog>
<dialog id="sfGuideDialog" class="sf-help-dialog" aria-labelledby="sfGuideTitle">
<div class="sf-help-head"><div><span class="overline">新手指南</span><h2 id="sfGuideTitle">3 分钟学会编辑页面</h2></div><button type="button" class="ui-btn ghost" onclick="document.querySelector('#sfGuideDialog').close()">关闭 ×</button></div>
<ol class="sf-help-steps"><li><b>先选页面</b><p>左侧顶部切换要编辑的页面;选择现有内容区块,或点击橙色的“添加内容区块”。</p></li><li><b>修改内容</b><p>在右侧“内容”里改标题、文案和图片;切换“样式”或“手机/平板”调整外观。中间自动展示效果。</p></li><li><b>保存草稿,再发布</b><p>点击右上角“保存草稿”可以保留工作。核对后点击“发布设计”,它会更新内容库;正式网站还需要执行静态构建和部署。</p></li></ol>
<div class="sf-guide-note">撤销、版本历史、全站页眉、静态构建等低频功能在右上角「更多」。</div>
<button type="button" class="ui-btn primary sf-guide-done" onclick="document.querySelector('#sfGuideDialog').close()">知道了,开始编辑</button>
</dialog>
<dialog id="designModal" style="border:1px solid #e2e8f0;border-radius:14px;padding:24px;width:min(460px,90vw);box-shadow:0 16px 52px #142a492f"><h2>全站设计规范</h2><p>调整后保存并刷新预览,发布构建自动采用该规范。</p><form id="designForm" method="dialog" style="display:grid;gap:12px"><label>标题缩放 <input name="heading_scale" type="number" min="0.8" max="1.5" step="0.1"></label><label>圆角 <input name="radius" type="number" min="0" max="32"></label><label>版心宽度 <input name="container_width" type="number" min="880" max="1600"></label><label>板块间距 <input name="section_spacing" type="number" min="20" max="140"></label><label>字体 <select name="font"><option value="system">系统字体</option><option value="serif">衬线字体</option><option value="modern">现代字体</option></select></label><label>按钮风格 <select name="button_style"><option value="rounded">圆角</option><option value="square">直角</option><option value="pill">胶囊</option></select></label><label>导航风格 <select name="header_style"><option value="standard">标准</option><option value="compact">紧凑</option></select></label><div style="display:flex;gap:12px"><button class="ui-btn primary" type="button" onclick="Studio.saveTokens()">保存全站规范</button><button class="ui-btn ghost" value="cancel">取消</button></div></form></dialog>
<dialog id="siteDesignModal" style="border:1px solid #e2e8f0;border-radius:14px;padding:22px;width:min(750px,96vw);max-height:88vh;overflow:auto;box-shadow:0 18px 56px #142a492f">
<h2>全站设计 · 页眉、导航、页脚与响应式</h2>
<p style="color:#64748b">先保存独立草稿;预览只显示在编辑器内。发布后,所有页面的下次静态构建才会使用新设计。</p>
<div id="siteDesignStatus" role="status" style="font-weight:600;margin-bottom:12px">读取中...</div>
<form id="siteDesignForm" method="dialog" style="display:grid;gap:12px">
<fieldset style="display:grid;gap:9px;border:1px solid #e2e8f0;border-radius:8px"><legend>页眉与导航</legend>
<label><input type="checkbox" name="show_announcement"> 显示顶部提示栏</label>
<label>提示栏文字 <input name="announcement" maxlength="140" style="width:100%"></label>
<label><input type="checkbox" name="show_search"> 显示站内搜索</label>
<label><input type="checkbox" name="show_cta"> 显示联系按钮</label>
<label>按钮文字 <input name="cta_text" maxlength="40"></label>
<label>按钮路径 <input name="cta_href" placeholder="/contact/"></label>
<section class="sf-visual-nav" aria-label="可视化全站导航管理">
<div class="sf-visual-nav-header"><strong>网站菜单</strong><span>直接编辑文字和链接,支持三级菜单</span></div>
<div id="siteNavRows" role="group" aria-label="导航菜单列表"></div>
<button class="ui-btn ghost" type="button" onclick="Studio.addSiteNav()">+ 添加一级菜单</button>
<p class="sf-visual-nav-help">点击“添加子菜单”即可建立下拉菜单。使用 ↑ ↓ 排序;保存草稿前会校验路径。</p>
<textarea name="nav" hidden aria-hidden="true"></textarea>
</section>
</fieldset>
<fieldset style="display:grid;gap:9px;border:1px solid #e2e8f0;border-radius:8px"><legend>全站页脚</legend>
<label>企业名称或页脚标题 <input name="footer_title" maxlength="120" style="width:100%"></label>
<label>页脚简介 <textarea name="footer_description" rows="2" maxlength="650" style="display:block;width:100%"></textarea></label>
<label>联系邮箱 <input name="footer_email" type="email" maxlength="150"></label>
<label><input name="footer_show_nav" type="checkbox"> 页脚显示导航链接</label>
</fieldset>
<fieldset style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px;border:1px solid #e2e8f0;border-radius:8px"><legend>不同设备布局</legend>
<label>平板板块间距 <input name="tablet_gap" type="number" min="20" max="120"></label>
<label>手机板块间距 <input name="mobile_gap" type="number" min="16" max="100"></label>
<label>手机内容边距 <input name="mobile_container_padding" type="number" min="8" max="48"></label>
<label><input name="mobile_hide_announcement" type="checkbox"> 手机隐藏提示栏</label>
<label><input name="mobile_hide_footer_links" type="checkbox"> 手机隐藏页脚导航</label>
</fieldset>
<fieldset style="border:1px solid #e2e8f0;border-radius:10px;padding:15px;display:grid;gap:12px"><legend>手机底部快捷导航 Tabs(可选)</legend>
<p style="margin:0;color:#64748b;font-size:13px">默认关闭。需要时开启后添加 1–5 个按钮。它们只显示在手机上,平板和电脑不显示。</p>
<label><input name="mobile_tabs_enabled" type="checkbox" onchange="Studio.toggleMobileTabsForm()"> 开启手机底部 Tabs</label>
<div id="mobileTabsEditor" hidden style="display:grid;gap:10px">
<div id="mobileTabsRows" style="display:grid;gap:9px"></div>
<button class="ui-btn ghost" type="button" onclick="Studio.addMobileTab()">+ 添加一个 Tab(最多 5 个)</button>
<small style="color:#64748b">标题建议不超过 4 个字;链接使用站内路径(如 /products/)。菜单按钮会打开右侧导航抽屉。</small>
</div>
</fieldset>
<div style="display:flex;flex-wrap:wrap;gap:8px">
<button class="ui-btn ghost" type="button" onclick="Studio.previewSiteDesign()">预览草稿</button>
<button class="ui-btn ghost" type="button" onclick="Studio.discardSiteDesign()">放弃全站草稿</button>
<button class="ui-btn ghost" type="button" onclick="Studio.saveSiteDesign()">保存全站草稿</button>
<button class="ui-btn ghost" type="button" onclick="Studio.showSiteDesignHistory()">历史版本</button>
<button class="ui-btn primary" type="button" onclick="Studio.publishSiteDesign()">审核差异并发布</button>
<button class="ui-btn ghost" value="cancel">关闭</button>
</div>
</form>
</dialog>
<dialog id="siteDesignReviewModal" class="sf-global-review" aria-labelledby="siteDesignReviewTitle">
<h2 id="siteDesignReviewTitle">全站设计发布审核</h2>
<p>本次变更将在下一次静态构建后影响本站所有页面,线上已发布网站不会立即改变。</p>
<div id="siteDesignReviewBody" role="status" aria-live="polite"></div>
<div class="sf-review-buttons"><button type="button" class="ui-btn ghost" onclick="document.querySelector('#siteDesignReviewModal').close()">返回编辑</button>
<button type="button" class="ui-btn primary" onclick="Studio.confirmReviewedSiteDesign()">确认更新全站设计</button></div>
</dialog>
<dialog id="siteDesignHistoryModal" class="sf-global-review" aria-label="全站设计发布历史">
<h2>全站设计历史</h2><p>恢复历史版本只会生成新草稿,不修改已上线的网站。</p>
<div id="siteDesignHistoryBody" aria-live="polite"></div>
<button type="button" class="ui-btn ghost" onclick="document.querySelector('#siteDesignHistoryModal').close()">关闭</button>
</dialog>
<dialog id="siteMediaModal" style="border:1px solid #dce5f1;border-radius:14px;padding:24px;width:min(720px,94vw);max-height:85vh;overflow:auto">
<h2>本站图片素材库</h2><p style="font-size:13px;color:#66758a">选择图片后更新当前组件;保存草稿、发布设计后才会参与静态构建。</p>
<div id="siteMediaGrid" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(135px,1fr));gap:12px"></div>
<button type="button" class="ui-btn ghost" onclick="document.querySelector('#siteMediaModal').close()" style="margin-top:15px">关闭</button>
</dialog>
<dialog id="studioHistoryModal" aria-labelledby="studioHistoryTitle" style="border:1px solid #dce5f1;border-radius:14px;padding:24px;width:min(680px,95vw);max-height:82vh;overflow:auto">
<h2 id="studioHistoryTitle">页面设计版本历史</h2>
<p style="color:#64748b">保存草稿、发布设计都会创建不可变快照。恢复只写入新草稿,不会直接修改已发布站点。</p>
<div id="studioHistoryItems" aria-live="polite"></div>
<button class="ui-btn ghost" type="button" onclick="document.querySelector('#studioHistoryModal').close()">关闭</button>
</dialog>
<dialog id="sharedComponentModal" class="sf-shared-dialog" aria-label="公共组件版本与引用管理">
<div class="sf-shared-dialog-head"><div><span class="overline">全站设计系统</span><h2>公共组件管理</h2></div><button class="ui-btn ghost" type="button" onclick="document.querySelector('#sharedComponentModal').close()">关闭 ×</button></div>
<p>选择组件查看版本和引用页面。更新组件源文件不会自动改变任何已发布网站。</p>
<div id="sharedComponentBody"></div><section id="sharedComponentDetail" aria-live="polite"></section>
</dialog>
<div id="toast" class="toast" role="status" aria-live="polite"></div>
</div></body></html>