.flow{ background:#fafbfc; border:1px solid var(--line); border-radius:4px; padding:12px 14px; }
.flow ol{ counter-reset:step; }
.kbd{ border:1px solid #ccc; border-bottom-width:2px; border-radius:3px; padding:0 5px; font-size:12px; background:#fafafa; }
- @media print{ .doc-toolbar{ display:none; } main#doc{ max-width:none; padding:0; } }
+ .doc-layout{ display:flex; align-items:flex-start; max-width:1180px; margin:0 auto; }
+ .doc-nav{ position:sticky; top:56px; flex:0 0 230px; align-self:flex-start; max-height:calc(100vh - 56px);
+ overflow:auto; padding:18px 10px 40px 6px; border-right:1px solid var(--line); }
+ .doc-nav .doc-nav-inner{ display:flex; flex-direction:column; }
+ .doc-nav a{ display:block; font-size:13px; color:#444; text-decoration:none; padding:4px 9px; border-radius:3px; line-height:1.5; }
+ .doc-nav a:hover{ background:#f2f7fa; color:var(--blue); }
+ .doc-nav a.sub{ padding-left:22px; font-size:12.5px; color:#667; }
+ .doc-nav a.active{ background:#eef7fb; color:var(--blue); font-weight:bold; }
+ main#doc{ max-width:none; flex:1 1 auto; margin:0; padding:24px 22px 80px; }
+ h2,h3,h4{ scroll-margin-top:64px; }
+ @media (max-width:760px){ .doc-nav{ display:none; } }
+ @media print{ .doc-toolbar, .doc-nav{ display:none; } main#doc{ max-width:none; padding:0; } }
</style>
</head>
<body>
</div>
</div>
+<div class="doc-layout">
+ <nav class="doc-nav"><div class="doc-nav-inner" id="toc"></div></nav>
+
<main id="doc">
<p class="muted">文档版本:v0.3 最后更新:2026-08-17 状态:开发中(演示数据已标注)</p>
<h1>StationBuilder 产品与交互设计方案</h1>
<li><b>约定</b>:标注 <span class="todo">尚未实现</span> 的项表示已在界面或方案中设计、但当前版本尚未打通能力(多为演示 / 占位)。</li>
<li><b>维护</b>:本文件为单一 HTML 源(<code>public/design-doc.html</code>),后续功能改动需同步更新对应章节,未实现项持续标注,直到能力落地后移除标记。</li>
<li><b>导出</b>:顶部按钮分别导出 PDF(调用浏览器打印)、Word(<code>.doc</code> 兼容格式)、Markdown(由本页内容实时转换)。</li>
+ <li><b>目录</b>:页面左侧为章节目录(自动生成),点击可跳转至对应章节;滚动阅读时自动高亮当前所在章节。</li>
</ul>
<h2>2. 产品概述</h2>
<li><b>下载 Markdown</b>:由本页 DOM 实时转换为 Markdown 文本导出。</li>
</ul>
</main>
+</div>
<script>
+// 自动生成左侧目录(TOC)并实现滚动高亮
+(function buildToc(){
+ function run(){
+ var main = document.getElementById('doc');
+ var toc = document.getElementById('toc');
+ if(!main || !toc) return;
+ var heads = main.querySelectorAll('h2, h3');
+ var links = [];
+ heads.forEach(function(h, i){
+ var id = 'doc-sec-' + (i+1);
+ h.id = id;
+ var a = document.createElement('a');
+ a.href = '#' + id;
+ a.textContent = h.textContent;
+ if(h.tagName.toLowerCase() === 'h3') a.className = 'sub';
+ toc.appendChild(a);
+ links.push({ id: id, a: a });
+ });
+ if('IntersectionObserver' in window){
+ var obs = new IntersectionObserver(function(entries){
+ entries.forEach(function(e){
+ if(e.isIntersecting){
+ links.forEach(function(l){ l.a.classList.remove('active'); });
+ var cur = links.filter(function(l){ return l.id === e.target.id; })[0];
+ if(cur) cur.a.classList.add('active');
+ }
+ });
+ }, { rootMargin: '-64px 0px -72% 0px', threshold: 0 });
+ heads.forEach(function(h){ obs.observe(h); });
+ }
+ }
+ if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', run);
+ else run();
+})();
+
function saveBlob(blob, filename){
const url = URL.createObjectURL(blob);
const a = document.createElement('a');