- 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→顶层跳登录、登录后回外壳默认驾驶舱。
161 lines
6.6 KiB
HTML
161 lines
6.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="studio.css">
|
||
<link rel="stylesheet" href="../shared/pro.css">
|
||
</head>
|
||
<body data-pro-title="模板配置台">
|
||
<!-- iAOP 模板配置台(issue #132 / PRD 5.7「⑤.7 模板配置台」)
|
||
纯静态单页应用(无构建链):导入页 / 超参配置页 / 驾驶舱编排页 / 版本页。
|
||
三级 RBAC 对齐 core/template-console/rbac.py 的 readonly/engineer/admin;
|
||
配置台只产出「模板资产包」(导出 JSON),不直接改内核运行时(耦合边界)。 -->
|
||
<header id="topbar">
|
||
<h1>iAOP 模板配置台 <span class="sub">Template Console · PRD 5.7</span></h1>
|
||
<div id="topbar-right">
|
||
<label for="role-select">当前角色</label>
|
||
<select id="role-select">
|
||
<option value="readonly">Viewer(只读)</option>
|
||
<option value="engineer" selected>Editor(配置)</option>
|
||
<option value="admin">Publisher(发布+回滚)</option>
|
||
</select>
|
||
<span id="role-hint" class="hint"></span>
|
||
</div>
|
||
</header>
|
||
|
||
<nav id="tabs">
|
||
<button class="tab active" data-page="import">① 点位导入</button>
|
||
<button class="tab" data-page="hyper">② 模型超参</button>
|
||
<button class="tab" data-page="layout">③ 驾驶舱编排</button>
|
||
<button class="tab" data-page="version">④ 版本发布</button>
|
||
</nav>
|
||
|
||
<!-- ======================= ① 导入页 ======================= -->
|
||
<section class="page active" id="page-import">
|
||
<div class="panel">
|
||
<h2>点位字典 CSV 导入</h2>
|
||
<p class="hint">字段规范对齐 PRD 5.1 / core/edge-gateway/point_dict:
|
||
device_id, point_id, name, unit, dataType, sampleRate, qualityCode, opcNode, protocol</p>
|
||
<div id="drop-zone" class="drop-zone">
|
||
拖拽 CSV 文件到这里,或
|
||
<input type="file" id="csv-file" accept=".csv,text/csv">
|
||
<button id="btn-download-template">下载错误模板(示例 CSV)</button>
|
||
</div>
|
||
<textarea id="csv-text" rows="6" placeholder="或直接粘贴 CSV 内容…"></textarea>
|
||
<div class="row">
|
||
<label>行业模板
|
||
<select id="import-template">
|
||
<option value="ti">氯化(ti-cl4)</option>
|
||
<option value="resin">树脂(resin)</option>
|
||
</select>
|
||
</label>
|
||
<button id="btn-validate" class="primary need-edit">开始校验</button>
|
||
</div>
|
||
<div id="import-progress-wrap" hidden>
|
||
<div id="import-progress"><div id="import-progress-bar"></div></div>
|
||
<div id="import-progress-text" class="hint"></div>
|
||
</div>
|
||
<div id="import-summary"></div>
|
||
<table id="issue-table" hidden>
|
||
<thead><tr><th>行号</th><th>级别</th><th>字段</th><th>原因</th></tr></thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ======================= ② 超参配置页 ======================= -->
|
||
<section class="page" id="page-hyper">
|
||
<div class="split">
|
||
<aside class="tree panel">
|
||
<h2>模型类型(4 类)</h2>
|
||
<ul id="model-tree"></ul>
|
||
</aside>
|
||
<div class="panel" id="hyper-form-panel">
|
||
<h2 id="hyper-title">超参配置</h2>
|
||
<form id="hyper-form"></form>
|
||
</div>
|
||
<div class="panel">
|
||
<h2>实时 JSON 预览</h2>
|
||
<pre id="hyper-json" class="json-view"></pre>
|
||
<div class="row">
|
||
<button id="btn-hyper-save" class="primary need-edit">保存到配置项</button>
|
||
<span id="hyper-save-hint" class="hint"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ======================= ③ 驾驶舱编排页 ======================= -->
|
||
<section class="page" id="page-layout">
|
||
<div class="split">
|
||
<aside class="panel" id="widget-lib">
|
||
<h2>组件库</h2>
|
||
<p class="hint">点击添加到画布(组件类型对齐 iAOP-cockpit-layout-v1)</p>
|
||
<ul id="widget-lib-list"></ul>
|
||
</aside>
|
||
<div class="panel">
|
||
<h2>画布(12 列栅格)</h2>
|
||
<div id="canvas"></div>
|
||
<div class="row">
|
||
<button id="btn-layout-clear" class="need-edit">清空画布</button>
|
||
<button id="btn-layout-load-ti" class="need-edit">载入 ti-cl4 基线</button>
|
||
</div>
|
||
</div>
|
||
<aside class="panel" id="bind-panel">
|
||
<h2>数据源绑定</h2>
|
||
<div id="bind-form-wrap"><p class="hint">选中画布中的组件后进行绑定</p></div>
|
||
<h2>布局 JSON</h2>
|
||
<pre id="layout-json" class="json-view"></pre>
|
||
</aside>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ======================= ④ 版本页 ======================= -->
|
||
<section class="page" id="page-version">
|
||
<div class="split-2">
|
||
<div class="panel">
|
||
<h2>版本列表</h2>
|
||
<div class="row">
|
||
<input id="release-version" placeholder="版本号(semver,如 1.0.0)" value="1.0.0">
|
||
<input id="release-author" placeholder="作者" value="engineer">
|
||
<button id="btn-publish" class="primary need-publish">发布当前配置</button>
|
||
</div>
|
||
<p class="hint">发布 = 固化当前超参 + 布局 + 校验结果为快照(对齐 core/template-console/release.py);
|
||
配置台只产出模板资产包,不直接改内核运行时。</p>
|
||
<table id="version-table">
|
||
<thead><tr><th>版本</th><th>状态</th><th>时间</th><th>作者</th><th>操作</th></tr></thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
<div class="panel">
|
||
<h2>diff 视图</h2>
|
||
<div class="row">
|
||
<select id="diff-left"></select>
|
||
<span class="hint">vs</span>
|
||
<select id="diff-right"></select>
|
||
<button id="btn-diff">对比</button>
|
||
</div>
|
||
<pre id="diff-view" class="json-view"></pre>
|
||
<div class="row">
|
||
<button id="btn-export-pack" class="primary">导出模板资产包</button>
|
||
<span class="hint">资产包 = 选中版本快照(超参/布局/点位校验报告),供内核灰度推送</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<script src="../auth/user_store.js"></script>
|
||
<script src="../shared/session.js"></script>
|
||
<script src="../shared/pro-header.js"></script>
|
||
<script src="studio.js"></script>
|
||
</body>
|
||
</html>
|