.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; } }
+ @media (max-width:760px){
+ .doc-layout{ flex-direction:column; padding-left:0; }
+ .doc-nav{ position:sticky; top:56px; flex:none; width:100%; max-height:34vh; border-right:0; border-bottom:1px solid var(--line); padding:8px 10px; }
+ main#doc{ padding:18px 14px 80px; }
+ }
+ @media print{ .doc-toolbar, .doc-nav{ display:none; } main#doc{ max-width:none; padding:0; width:100%; }
+ .figure{ page-break-inside:avoid; break-inside:avoid; }
+ .figure img{ max-width:100%; width:auto; }
+ table{ page-break-inside:avoid; break-inside:avoid; }
+ tr{ page-break-inside:avoid; break-inside:avoid; }
+ h2,h3,h4{ page-break-after:avoid; break-after:avoid; }
+ img{ -webkit-print-color-adjust:exact; print-color-adjust:exact; }
+ }
/* 页面截图(参考 MachineCube 手册撰写方式:小节标题 + 说明 + 下图 + 配图 + 图注)*/
body{ counter-reset: fig; }
.figure{ margin:14px 0; border:1px solid var(--line); background:#fbfcfd; }
<nav class="doc-nav"><div class="doc-nav-inner" id="toc"></div></nav>
<main id="doc">
- <p class="muted">文档版本:v0.15 最后更新:2026-08-19 修改人:wang.yu 状态:开发中(演示数据已标注)</p>
+ <p class="muted">文档版本:v0.16 最后更新:2026-08-19 修改人:wang.yu 状态:开发中(演示数据已标注)</p>
<h1>StationBuilder 产品与交互设计方案</h1>
<h2>1. 文档说明</h2>
<tr><td>品牌区 iStation / iStation Team / StationBuilder⌄</td><td>标识当前产品与模块</td><td>静态</td><td>纯展示</td></tr>
<tr><td><b>设计方案</b> 链接</td><td>打开本设计文档</td><td>静态链接 <code>/design-doc.html</code></td><td>新标签页打开;位于登录者名称左侧</td></tr>
<tr><td>模型选择(AI 问答 · 模型名⌄)</td><td>切换 AI 问答模型</td><td>前端 <code>MODELS</code> 常量</td><td>点击弹出模型列表,仅「免费」模型可选(其余置灰);<b>仅影响 AI 问答,不影响生成(生成使用后端固定配置模型)</b></td></tr>
- <tr><td>登录者头像 W / 邮箱</td><td>当前登录身份展示;返回登录页</td><td>静态演示</td><td>点击头像回到内部登录页 <span class="todo">登录态尚未实现</span></td></tr>
+ <tr><td>登录者头像 W / 邮箱</td><td>当前登录身份展示</td><td>静态演示</td><td>演示态,点击头像返回登录页 <span class="todo">登录态尚未实现</span>(登录页不在本文档单列章节)</td></tr>
</table>
<h3>4.2 左侧导航整体结构(side-nav)</h3>
<h2>5. 页面详细说明</h2>
- <h3>5.1 内部登录(login)</h3>
- <table>
- <tr><th>元素</th><th>功能</th><th>数据来源</th><th>交互效果</th></tr>
- <tr><td>「使用公司账号登录」按钮</td><td>模拟登录进入主界面</td><td>静态</td><td>点击进入站点项目页 <span class="todo">真实账号体系尚未实现</span></td></tr>
- </table>
-
- <h4>5.1.1 交互细节</h4>
- <figure><img src="design-doc-assets/login.png" alt="登录页"/><figcaption>登录页:iStation StationBuilder 统一登录入口。</figcaption></figure>
- <p><b>① 字段 / 表格逐列</b>:本页无可编辑字段,仅一个登录动作入口。</p>
- <p><b>② 按钮与操作</b></p>
- <table>
- <tr><th>按钮</th><th>点击效果</th><th>编辑方式</th><th>确定 / 取消 / 关闭</th></tr>
- <tr><td>使用公司账号登录(SSO)</td><td>调用 <code>onLogin()</code> → <code>go("projects")</code>,进入「站点项目」页</td><td>无表单、无弹窗</td><td>无确认/取消/关闭步骤(真实账号体系 <span class="todo">尚未实现</span>)</td></tr>
- </table>
- <p><b>③ 导航流</b></p>
- <ul>
- <li><b>入口</b>:点击右上角头像(<code>.avatar-button</code>,标题"查看内部登录页")→ <code>go("login")</code>;应用启动默认页为 projects,非强制经过本页。</li>
- <li><b>上一步</b>:无(登录为根入口)。</li>
- <li><b>下一步</b>:站点项目(projects)。</li>
- </ul>
-
<h3>5.2 站点项目 / 站点列表(projects)</h3>
<table>
<tr><th>元素</th><th>功能</th><th>数据来源</th><th>交互效果</th></tr>
<li><b>下一步</b>:Asset 资产设置(assets)。</li>
</ul>
+ <h4>5.3.2 AI 智能补全(站点基本属性)</h4>
+ <figure><img src="design-doc-assets/ai-complete-basic.png" alt="AI 智能补全·基本属性"/><figcaption>AI 智能补全进行中:点击「开始补全」后,面板下方出现黑底白字的「AI 智能补全」终端,实时滚动输出分析过程。</figcaption></figure>
+ <p>「开始补全」调用 <code>POST /api/db/sites/:id/complete</code>(流式 NDJSON)。终端(<code>.modal-console</code>)实时逐行输出 AI 的思考 / 分析过程(如「▶ 开始 AI 智能补全:基于站点名称 / 领域 / 描述分析并生成补充描述…」);流结束后将生成的补充描述写入「补充要求」并自动保存。点击「查看提示词」可查看本次组合提示词。补全过程中「开始补全」按钮显示「补全中…」并禁用,避免重复触发 <span class="todo">补充描述质量将按反馈持续优化</span>。</p>
+
<h3>5.4 Asset 资产设置(assets)</h3>
<table>
<tr><th>元素</th><th>功能</th><th>数据来源</th><th>交互效果</th></tr>
<li><b>下一步</b>:功能与菜单(functions)。</li>
</ul>
+ <h4>5.4.2 AI 智能补全(Asset 资产设置)</h4>
+ <figure><img src="design-doc-assets/ai-complete-assets.png" alt="AI 智能补全·资产"/><figcaption>AI 资产补全进行中:终端实时输出设备类型 / 数量 / 命名规则的推断过程。</figcaption></figure>
+ <p>「开始补全」调用 <code>POST /api/db/sites/:id/complete-assets</code>(流式 NDJSON)。终端实时输出 AI 对设备类型、数量与命名规则的推断过程;结果将<strong>追加在用户已填项下方</strong>(不改动已填内容),资产配置列表随之更新,资产层级预览重算;结束自动保存。点击「查看提示词」查看完整提示词。</p>
+
<h3>5.5 功能与菜单(functions)</h3>
<p>三个子页签:</p>
<table>
<li><b>下一步</b>:生成确认(generate)。(generate 之后无 UI 入口进入站点结果/页面预览,见 5.7 / 5.8)</li>
</ul>
+ <h4>5.5.2 AI 智能补全(功能与菜单 · Cube 扩展页面)</h4>
+ <figure><img src="design-doc-assets/ai-complete-functions.png" alt="AI 智能补全·Cube"/><figcaption>AI Cube 页面补全进行中:基于站点信息与设备资产层级,实时推断并补充 Cube 扩展页面。</figcaption></figure>
+ <p>在「Cube 扩展页面」页签中点击「开始补全」,调用 <code>POST /api/db/sites/:id/complete-cubes</code>(流式 NDJSON)。终端实时输出 AI 对站点所需 Cube 扩展页面的推断(页面名称 + 详细内容);结果追加在用户已建页面下方并自动保存。点击「查看提示词」可查看完整组合提示词。</p>
+
<h3>5.6 生成确认(generate)</h3>
<table>
<tr><th>元素</th><th>功能</th><th>数据来源</th><th>交互效果</th></tr>
</ul>
<h3>5.13 界面截图(UI 总览)</h3>
- <p>以下截图覆盖了当前 StationBuilder 原型的主要页面。截图在 1440×900 视口下使用 Playwright + Chromium 自动抓取,图片存放于 <code>public/design-doc-assets/</code>。各页的字段、按钮与导航流逐项说明见 5.1–5.12 的「交互细节」子章。</p>
- <p class="note">å\8f¯è¾¾æ\80§è¯´æ\98\8eï¼\9aç\99»å½\95ã\80\81ç«\99ç\82¹é¡¹ç\9b®ã\80\81å\9fºæ\9c¬å±\9eæ\80§ã\80\81Assetã\80\81å\8a\9fè\83½ä¸\8eè\8f\9cå\8d\95ã\80\81ç\94\9fæ\88\90确认ã\80\81ç«\99ç\82¹ç»\93æ\9e\9cï¼\88ç«\99ç\82¹é¡¹ç\9b®ç\82¹å\87»<b>å·²ç\94\9fæ\88\90</b>ç«\99ç\82¹è¿\9bå\85¥ï¼\89ã\80\81é¢\86å\9f\9fæ\96¹æ¡\88åº\93ã\80\81æ\96¹æ¡\88详æ\83\85ã\80\81页é\9d¢æ ·å¼\8fåº\93ã\80\81设å¤\87模ç\89\88å\9d\87å\8f¯æ£å¸¸è®¿é\97®ï¼\9b<b>页é\9d¢é¢\84è§\88ï¼\885.8ï¼\89å½\93å\89\8dæ\97 UI å\85¥å\8f£</b>ï¼\88代ç \81䏿\97 <code>go("preview")</code> è°\83ç\94¨ï¼\89ï¼\8cæ\95\85æ\9cªå\8d\95ç\8b¬æ\88ªå\9b¾ï¼\8cå\85¶æ¼\94示å¤\96壳è§\81 5.8.1ã\80\82</p>
+ <p>以下截图覆盖了当前 StationBuilder 原型的主要页面。截图在 1440×900 视口下使用 Playwright + Chromium 自动抓取,图片存放于 <code>public/design-doc-assets/</code>。各页的字段、按钮与导航流逐项说明见 5.2–5.12 的「交互细节」子章;其中 5.3 / 5.4 / 5.5 另含「AI 智能补全」子章(5.3.2 / 5.4.2 / 5.5.2),展示 AI 流式输出过程。</p>
+ <p class="note">可达性说明:站点项目、基本属性、Asset、功能与菜单、生成确认、站点结果(站点项目点击<b>已生成</b>站点进入)、领域方案库、方案详情、页面样式库、设备模版均可正常访问;<b>页面预览(5.8)当前无 UI 入口</b>(代码中无 <code>go("preview")</code> 调用),故未单独截图,其演示外壳见 5.8.1。</p>
- <figure><img src="design-doc-assets/login.png" alt="登录页"/><figcaption>登录页:iStation StationBuilder 统一登录入口。</figcaption></figure>
<figure><img src="design-doc-assets/projects.png" alt="站点项目"/><figcaption>站点项目:全部站点列表、统计概览、筛选与新建入口。</figcaption></figure>
<figure><img src="design-doc-assets/basic.png" alt="站点基本属性"/><figcaption>站点基本属性:站点名称、域名、业务描述、关键词、文件上传等基本信息维护。</figcaption></figure>
<figure><img src="design-doc-assets/assets.png" alt="Asset 资产设置"/><figcaption>Asset 资产设置:设备类型、数量、命名规则与资产层级预览。</figcaption></figure>
<h3>11.1 版本变更记录(Changelog)</h3>
<table class="changelog">
<tr><th>版本</th><th>日期</th><th>修改人</th><th>说明</th></tr>
+ <tr><td>v0.16</td><td>2026-08-19</td><td>wang.yu</td><td>设计方案文档修订:① 左侧目录改为任意宽度常驻可见(移除窄屏 <code>display:none</code>,窄屏下列表转为顶部可滚动常驻栏),点击章节后目录不再消失;② 移除「内部登录」章节(5.1)及 5.13 登录截图,可达性说明去掉登录;③ 新增 AI 智能补全子章(5.3.2 / 5.4.2 / 5.5.2),附 AI 流式输出终端截图(ai-complete-basic/assets/functions.png);④ 修复 PDF 导出图片被分页截断(<code>@media print</code> 增加 <code>page-break-inside:avoid</code> 与图片适配);⑤ 修复 Word 导出无图片(<code>downloadWord</code> 将图片转为 base64 data URI 内嵌)。</td></tr>
<tr><td>v0.15</td><td>2026-08-19</td><td>wang.yu</td><td>领域方案库列表增强:列顺序调整为「所属领域 → 方案名称 → 版本 → 状态 → 创建人 → 设备/页面/文档 → 操作」,版本/状态列收窄、所属领域/方案名称列加宽;新增筛选栏(查找 方案名称/创建人 + 所属领域下拉 + 状态下拉 + 条数)与可排序列头(所属领域/方案名称/状态/创建人,升降切换带 ▲▼),卡片视图复用同结果。</td></tr>
<tr><td>v0.14</td><td>2026-08-19</td><td>wang.yu</td><td>左侧目录(TOC)贴齐浏览器最左侧:<code>.doc-layout</code> 取消 <code>margin:0 auto</code> 自动居中(改为 <code>margin:0; padding-left:12px</code>),宽屏下不再左右留白,目录紧贴视口左缘。</td></tr>
<tr><td>v0.13</td><td>2026-08-18</td><td>wang.yu</td><td>截图显示宽度由 500px 调整为 360px(<code>.figure img</code> 的 <code>max-width</code>),等比例缩放并居中,适配常见浏览宽度。</td></tr>
setTimeout(()=>URL.revokeObjectURL(url), 60000);
}
function downloadPDF(){ window.print(); }
-function downloadWord(){
- const html = document.getElementById('doc').innerHTML;
+function blobToDataURL(blob){
+ return new Promise((resolve,reject)=>{
+ const r=new FileReader();
+ r.onload=()=>resolve(r.result);
+ r.onerror=reject;
+ r.readAsDataURL(blob);
+ });
+}
+async function downloadWord(){
+ const src = document.getElementById('doc');
+ const clone = src.cloneNode(true);
+ const imgs = [...clone.querySelectorAll('img')];
+ await Promise.all(imgs.map(async (img)=>{
+ const srcAttr = img.getAttribute('src');
+ if(!srcAttr || /^data:/i.test(srcAttr)) return;
+ try{
+ const resp = await fetch(srcAttr);
+ if(!resp.ok) return;
+ const du = await blobToDataURL(await resp.blob());
+ img.setAttribute('src', du);
+ img.style.maxWidth = '360px';
+ }catch(e){ /* 失败则保留原相对路径,不影响导出其它内容 */ }
+ }));
const head = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head><meta charset="utf-8"></head><body>';
- const blob = new Blob([''+head+html+'</body></html>'], {type:'application/msword;charset=utf-8'});
+ const blob = new Blob([''+head+clone.innerHTML+'</body></html>'], {type:'application/msword;charset=utf-8'});
saveBlob(blob, 'StationBuilder-设计方案.doc');
}
function inlineOf(node){