- web/index.html 重写为 SPA 外壳:Sider/顶栏常驻,模块页在 #module-frame iframe 内容区加载,点菜单只换 iframe 地址, 彻底消灭整页刷新与白闪(此前只是铺底色缓解) - 新增 shared/shell.js:IAOP_SHELL.navigate() 导航、外壳 hash (#/admin/#models) 与 iframe 地址双向同步、登录守卫、移动端 模块新标签打开;iframe 地址用 location.replace 避免污染 joint history;250ms 轮询回同步(replace 不触发 load 事件); 导航时乐观高亮(后台标签轮询被节流不能作为唯一途径); 前进/后退若恢复了 iframe 旧地址则以外壳 hash 为准强制对齐 - pro-header.js 三模式:外壳(菜单点击走 IAOP_SHELL、导出 IAOP_PRO.setActive)/被嵌(iframe 内,隐藏页内跨页链接与重复 用户标识、保留 Tab-hash 联动)/独立(原行为);菜单渲染后派发 pro:menu-rendered 事件消除导航先于渲染的高亮竞态 - session.js:logout/守卫重定向作用于顶层窗口(iframe 内不再 只跳 iframe 自己) - 修复 iframe 替换元素宽高 bug:fixed 时左右定位不拉伸(回退 固有 300x150),改显式 calc 宽高 - 登录页 next 默认回外壳 ../index.html 实测(本地 http.server + WebBridge 真实浏览器):菜单切换/ 子菜单切换/前进/后退/直达链接(#/admin/#models) URL、iframe、 菜单高亮、子菜单高亮全链路一致,Sider 节点全程不重建; 登录守卫 logout→顶层跳登录、登录后回外壳默认驾驶舱。
78 lines
3.6 KiB
HTML
78 lines
3.6 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<!-- 首屏防闪(issue #131):跨页跳转时外部 CSS 未到的瞬间,
|
||
先用与最终布局一致的底色铺满画布(左 Sider 深色 + 内容区灰),
|
||
消除深色 Sider 区域的白闪(FOUC)。 -->
|
||
<style>html{background:#f0f2f5}@media (min-width:721px){html{background:linear-gradient(90deg,#001529 208px,#f0f2f5 208px)}}</style>
|
||
<!-- 被 SPA 外壳 iframe 嵌入时内容区无 Sider,立即改回纯灰底(首帧前生效) -->
|
||
<script>if(window!==window.top){document.documentElement.style.background="#f0f2f5"}</script>
|
||
<title>iAOP 对话助手(增强版)</title>
|
||
<link rel="stylesheet" href="assistant.css">
|
||
<link rel="stylesheet" href="../shared/pro.css">
|
||
</head>
|
||
<body data-pro-title="对话助手">
|
||
<!-- iAOP 对话助手增强版(issue #133 / PRD 5.4「④ LLM 网关 + RAG」)
|
||
在 chat_widget.html(#77 雏形)之上完善:消息流 + RAG 引用溯源 +
|
||
路由分级提示(本地/云端)+ DLP 拦截反馈,直连已部署推理服务。
|
||
既有 chat_widget.html 保留不动(仍由 chat_api.py 托管联调)。 -->
|
||
<div id="app">
|
||
<header id="topbar">
|
||
<h1>iAOP 对话助手 <span class="sub">NL 查询 / 报警解释 / 交接班报告 · PRD 5.4</span></h1>
|
||
<div id="service-status">
|
||
<span id="infer-dot" class="dot">●</span>
|
||
<span id="infer-text" class="hint">推理服务检测中…</span>
|
||
</div>
|
||
</header>
|
||
|
||
<div id="messages"></div>
|
||
|
||
<!-- 报警解释场景的结构化输入(PRD 场景A:告警 → 原因+处置建议) -->
|
||
<div id="alarm-inputs" class="scenario-inputs" hidden>
|
||
<select id="alarm-severity">
|
||
<option value="P0">P0(红色告警)</option>
|
||
<option value="P1">P1(加强监控)</option>
|
||
<option value="P2">P2(提示)</option>
|
||
</select>
|
||
<input id="alarm-point" placeholder="告警点位,如 CLF-01.TEMP">
|
||
</div>
|
||
<!-- 交接班报告场景输入(PRD 场景C:按模板章节生成,≤ 2 分钟) -->
|
||
<div id="handover-inputs" class="scenario-inputs" hidden>
|
||
<input id="handover-shift" placeholder="班次,如 早班 08:00-16:00">
|
||
<span class="hint">章节模板:生产概况/异常事项/安全注意事项/能耗/待办(handover_brief.ti.yaml)</span>
|
||
</div>
|
||
|
||
<!-- DLP 拦截反馈条(PRD 5.4:拦截可感知) -->
|
||
<div id="dlp-banner" hidden>
|
||
<strong>DLP 拦截:</strong><span id="dlp-detail"></span>
|
||
<button id="btn-local-fallback">转本地模型处理</button>
|
||
<button id="btn-dlp-dismiss">取消发送</button>
|
||
</div>
|
||
|
||
<div id="panel">
|
||
<select id="scenario">
|
||
<option value="nl_query">自然语言查询</option>
|
||
<option value="alarm_explain">报警解释</option>
|
||
<option value="shift_handover">交接班报告</option>
|
||
</select>
|
||
<input id="question" placeholder="请输入问题,如:氯气流量最近1小时趋势">
|
||
<button id="send">发送</button>
|
||
</div>
|
||
<div class="hint" id="footer-hint">
|
||
路由分级:敏感/核心 → 本地(数据不出厂);脱敏/通用 → 云端;DLP 命中 → 拦截。
|
||
回答附 RAG 引用溯源(知识库命中时)。
|
||
</div>
|
||
</div>
|
||
<script src="../auth/user_store.js"></script>
|
||
<script src="../shared/session.js"></script>
|
||
<script>
|
||
// 登录守卫(PRD 8.2):未登录跳登录页,登录后回跳本页(后端优先/本地降级)
|
||
IAOP_SESSION.requireLoginElseRedirect("../auth/login.html");
|
||
</script>
|
||
<script src="../shared/pro-header.js"></script>
|
||
<script src="assistant.js"></script>
|
||
</body>
|
||
</html>
|