Files
knowledge-governance/docs/previews/monitor-a-compact-table.html
zheromiku dcdc8d1ddd feat: 知识治理平台(含已验证发布/回滚契约)
全栈知识治理平台首次入库(P1-P10 + 发布链路模拟验证闭环):

- 治理核心:源目录/变更集/人工审核/发布批次/发布执行(fail-closed 闸口)
- 测试通道:WeKnora 测试 KB 上传/轮询/验收;poll 完成时写入
  parser_generation/index_generation,修复 manual/seed 路径发布闸口永久拦截
- 发布适配器 v071(本地 source=测试角色 / 云端 target=生产角色 模拟验证通过):
  * ES 导出/导入 mapping 自适应(.keyword 子字段、可选 tenant_id)
  * OSS locator 支持嵌套 scheme;chunks.seq_id 由目标序列分配
  * bundle 归档同身份重试原子替换;verifier 按 bundle chunk_type 计数
  * 回滚 job payload 支持 prior_execution_id(strict 解码)
- 三通道发布+回滚演练实测:publish 4/4 verified,检索命中,
  rollback 4/4 rolled_back,目标端 PG is_enabled=false、ES is_enabled=false
- 前端 A·Data-console 风格全站统一,120 用例通过
- 门禁:go vet / go test 全包通过,gofmt 干净
2026-09-30 10:54:06 +08:00

160 lines
12 KiB
HTML
Raw Permalink 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.0">
<title>解析监控 · 方向A 紧凑表格版 [预览稿·模拟数据]</title>
<style>
:root{--line:#e5e7eb;--ink:#111827;--sub:#6b7280;--bg:#f7f8fa;--fail:#b91c1c;--ok:#0b6e4f;--warn:#b45309;--run:#1d4ed8}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.5 "PingFang SC","Microsoft YaHei",sans-serif}
header{display:flex;align-items:center;gap:14px;padding:12px 20px;background:#fff;border-bottom:1px solid var(--line)}
header h1{font-size:17px;margin:0}
.meta{color:var(--sub);font-size:12px}
button{font:inherit;padding:5px 12px;border:1px solid var(--line);border-radius:6px;background:#fff;cursor:pointer}
button.primary{background:#111827;color:#fff;border-color:#111827}
button.danger{color:var(--fail)}
.preview-tag{margin-left:auto;background:#fef3c7;color:#92400e;border:1px solid #fcd34d;font-size:12px;padding:2px 10px;border-radius:999px}
main{max-width:1400px;margin:0 auto;padding:14px 20px;display:flex;flex-direction:column;gap:14px}
section{background:#fff;border:1px solid var(--line);border-radius:8px}
.shead{display:flex;align-items:center;gap:10px;padding:10px 14px;border-bottom:1px solid var(--line)}
.shead h2{font-size:14px;margin:0}
.shead .spacer{flex:1}
.counts{display:flex;gap:6px;flex-wrap:wrap}
.count{font-size:12px;padding:2px 9px;border-radius:999px;border:1px solid var(--line);color:var(--sub)}
.count b{color:var(--ink)}
.count.wait b{color:var(--warn)}.count.run b{color:var(--run)}.count.ok b{color:var(--ok)}.count.fail b{color:var(--fail)}
table{width:100%;border-collapse:collapse;font-size:13px}
th{color:var(--sub);font-weight:500;text-align:left;font-size:12px;padding:7px 14px;border-bottom:1px solid var(--line);white-space:nowrap}
td{padding:8px 14px;border-bottom:1px solid #f1f3f6;vertical-align:middle}
tr:last-child td{border-bottom:none}
tr.fail-row{background:#fef8f8}
tr:hover td{background:#fafbfc}
.badge{font-size:12px;padding:1px 8px;border-radius:4px;border:1px solid var(--line);white-space:nowrap}
.badge.add{color:var(--ok)}.badge.update,.badge.move{color:var(--run)}.badge.move_scope{color:var(--warn)}.badge.delete{color:var(--fail)}
.badge.in{background:#eef6ff;border-color:#bfdbfe}.badge.out{background:#f0fdf4;border-color:#bbf7d0}
.s{font-size:12px;white-space:nowrap}.s.failed{color:var(--fail)}.s.completed{color:var(--ok)}.s.processing{color:var(--run)}.s.pending{color:var(--sub)}.s.stalled{color:var(--warn)}
code{font:12px ui-monospace,Consolas,monospace;color:var(--sub)}
.tiny{font-size:12px;color:var(--sub)}
input[type=text]{font:inherit;padding:5px 8px;border:1px solid var(--line);border-radius:6px;width:120px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:8px 20px;font-size:13px}
footer{display:flex;gap:0;overflow-x:auto;background:#fff;border:1px solid var(--line);border-radius:8px;font-size:12px}
footer div{padding:8px 16px;border-right:1px solid var(--line);white-space:nowrap}
footer div:last-child{border-right:none}
footer .bad{color:var(--fail)}footer .good{color:var(--ok)}
#drawer{position:fixed;top:0;right:-420px;width:400px;height:100%;background:#fff;border-left:1px solid var(--line);box-shadow:-4px 0 18px rgba(0,0,0,.06);transition:right .18s;padding:16px;z-index:9;overflow:auto}
#drawer.open{right:0}
#drawer h3{margin:0 0 4px;font-size:15px;word-break:break-all}
#drawer .close{float:right;border:none;background:none;font-size:18px;cursor:pointer;color:var(--sub)}
.timeline{list-style:none;margin:14px 0;padding:0;border-left:2px solid var(--line)}
.timeline li{position:relative;padding:0 0 16px 18px;font-size:13px}
.timeline li::before{content:'';position:absolute;left:-6px;top:4px;width:10px;height:10px;border-radius:50%;background:#fff;border:2px solid var(--sub)}
.timeline li.done::before{border-color:var(--ok);background:var(--ok)}
.timeline li.bad::before{border-color:var(--fail);background:var(--fail)}
.timeline li time{display:block;font-size:12px;color:var(--sub)}
.err{background:#fef2f2;border:1px solid #fecaca;color:var(--fail);font-size:12px;padding:8px 10px;border-radius:6px;margin:8px 0}
.dl{display:grid;grid-template-columns:110px 1fr;gap:6px;font-size:13px;margin-top:12px}
.dl dt{color:var(--sub)}.dl dd{margin:0;word-break:break-all}
@media(max-width:1024px){.grid2{grid-template-columns:1fr}}
</style>
</head>
<body>
<header>
<h1>解析监控</h1>
<span class="meta">快照 2026-09-12 08:00 · 下次自动 08:05</span>
<span class="meta">活跃 Worker <b>2</b> · 等待 <b style="color:var(--warn)">3</b> · 运行 <b style="color:var(--run)">4</b> · 失败 <b style="color:var(--fail)">2</b></span>
<button class="spacer" style="margin-left:auto">刷新</button>
<span class="preview-tag">预览稿 · 模拟数据 · 方向A</span>
</header>
<main>
<section>
<div class="shead"><h2>快照差异 → 解析队列 → 死信 → 资源(单页主线,表格为主)</h2>
<div class="counts spacer">
<span class="count wait">待确认 <b>3</b></span><span class="count run">处理中 <b>4</b></span>
<span class="count ok">成功 <b>4530</b></span><span class="count fail">失败 <b>2</b></span>
</div>
<label class="tiny">筛选
<select><option>对内+对外</option><option>对内</option><option>对外</option></select>
</label>
</div>
</section>
<section>
<div class="shead"><h2>1 · 快照差异(待确认置顶)</h2><span class="tiny">国内工业 · from 09-08 → to 09-12</span><span class="spacer"></span><span class="tiny">操作人</span><input type="text" value="姚工"></div>
<table>
<thead><tr><th style="width:34px"><input type="checkbox" checked></th><th>变更</th><th>文件</th><th>路径(旧 → 新)</th><th>目标</th><th>证据</th><th style="width:110px">操作</th></tr></thead>
<tbody>
<tr><td><input type="checkbox" checked></td><td><span class="badge add">新增</span></td><td><a href="#" onclick="openDrawer('CR20B用户手册V2.pdf');return false">CR20B用户手册V2.pdf</a></td><td class="tiny">— → 01|产品资料/CR20B/</td><td><span class="badge in">对内</span></td><td class="tiny">内容Hash 8e3f…(来源提供)</td><td><button class="primary" style="font-size:12px">确认处理</button></td></tr>
<tr><td><input type="checkbox" checked></td><td><span class="badge update">更新</span></td><td><a href="#" onclick="openDrawer('DobotStudio固件说明.docx');return false">DobotStudio固件说明.docx</a></td><td class="tiny">同一文件,版本 r12 → r13</td><td><span class="badge in">对内</span><span class="badge out">对外</span></td><td class="tiny">内容Hash变化(真更新)</td><td><button class="primary" style="font-size:12px">确认处理</button></td></tr>
<tr><td><input type="checkbox" checked></td><td><span class="badge move_scope">范围变化</span></td><td><a href="#" onclick="openDrawer('越疆售后FAQ.xlsx');return false">越疆售后FAQ.xlsx</a></td><td class="tiny">对内 → 对内+对外</td><td><span class="badge out">对外</span></td><td class="tiny">Hash未变,仅标注</td><td><button class="primary" style="font-size:12px">确认处理</button></td></tr>
<tr><td>—</td><td><span class="badge move">移动</span></td><td>安装指南.pdf</td><td class="tiny">01|产品资料/ → 快速入门/安装指南.pdf</td><td><span class="badge in">对内</span></td><td class="tiny">同名同Hash → 自动改名,不重解析</td><td class="tiny">已自动处理</td></tr>
<tr class="fail-row"><td>—</td><td><span class="badge delete">删除</span></td><td>旧手册.pdf</td><td class="tiny">02|已下架资料/旧手册.pdf →</td><td>—</td><td class="tiny">来源缺失</td><td class="tiny">等待移除确认</td></tr>
</tbody>
</table>
</section>
<section>
<div class="shead"><h2>2 · 解析队列(失败/停滞置顶)</h2><span class="tiny">共 4536 · 1小时:成功 88.9% · p95 30分钟</span><span class="spacer"></span><input type="text" value="姚工"><button class="danger">批量重试(2)</button></div>
<table>
<thead><tr><th style="width:34px"></th><th>状态</th><th>阶段链</th><th>文件</th><th>目标</th><th>错误码</th><th>已停留</th><th>重试</th></tr></thead>
<tbody>
<tr class="fail-row"><td><input type="checkbox" checked></td><td class="s failed">失败</td><td class="tiny">✓✓✓✗···· <b style="color:var(--fail)">文档解析</b></td><td><a href="#" onclick="openDrawer('CR20A.pdf');return false">CR20A.pdf</a></td><td><span class="badge out">对外</span></td><td><code>validation_failed</code></td><td>—</td><td>1</td></tr>
<tr class="fail-row"><td><input type="checkbox" checked></td><td class="s failed">失败</td><td class="tiny">✓✓✓✓✓✗· <b style="color:var(--fail)">索引增强</b></td><td><a href="#" onclick="openDrawer('MG400碰撞检测.mp4笔记.pdf');return false">MG400碰撞检测笔记.pdf</a></td><td><span class="badge in">对内</span></td><td><code>remote_permanent</code></td><td>—</td><td>5/5 耗尽 · 死信</td></tr>
<tr><td>—</td><td class="s processing">解析中</td><td class="tiny">✓✓✓✗···· 文档解析</td><td>XVision标定手册.pdf</td><td><span class="badge in">对内</span></td><td>—</td><td>6分钟</td><td>0</td></tr>
<tr><td>—</td><td class="s pending">等待</td><td class="tiny">等待接单</td><td>NeoSs常见问题.docx</td><td><span class="badge out">对外</span></td><td>—</td><td>2分钟</td><td>0</td></tr>
<tr><td>—</td><td class="s completed">成功</td><td class="tiny">✓✓✓✓✓✓✓ 完成</td><td>CR5说明书V3.pdf</td><td><span class="badge in">对内</span></td><td>—</td><td>完成</td><td>2</td></tr>
</tbody>
</table>
</section>
<section>
<div class="shead"><h2>3 · 失败队列 DLQ(2条开放死信)</h2><span class="tiny">仅投影;原始任务与审计不可变。重试=新尝试</span></div>
<table>
<thead><tr><th>错误码</th><th>类型</th><th>文件</th><th>尝试</th><th>进入死信</th><th></th></tr></thead>
<tbody>
<tr><td><code>remote_permanent</code></td><td>上传解析</td><td>MG400碰撞检测笔记.pdf</td><td>5/5</td><td class="tiny">09-11 21:04</td><td><button>重试</button></td></tr>
<tr><td><code>artifact_invalid</code></td><td>上传解析</td><td>测试固件包.zip.bin</td><td>1/1</td><td class="tiny">09-12 02:11</td><td class="tiny">文件校验永久失败,需来源修复</td></tr>
</tbody>
</table>
</section>
<footer>
<div>10s <b class="good">100%</b></div>
<div>1小时 · 成功 <b class="good">88.9%</b> 失败 11.1%</div>
<div>24小时 · 成功 <b class="good">96.4%</b></div>
<div>耗时 p50 30秒 · p95 30分钟 · 均值 6.9分钟</div>
<div>CPU <b>42%</b> 内存 18.6/32GB</div>
<div>WeKnora <b class="good">可达</b></div>
<div>MinerU <b class="bad">容量已满(429)</b></div>
<div>PostgreSQL <b class="good">可接单</b></div>
</footer>
</main>
<div id="drawer">
<button class="close" onclick="document.getElementById('drawer').classList.remove('open')">✕</button>
<h3 id="drawer-title">CR20A.pdf</h3>
<p class="tiny">对内+对外 · kb-external · 版本 r7 · 发布 tp-8841</p>
<div class="err">validation_failed:解析服务返回 422,切片数量=0。建议:确认 MinerU 接单容量后批量重试。</div>
<ul class="timeline">
<li class="done">下载完成<time>08:01:02 · 3.2MB</time></li>
<li class="done">内容Hash校验 8e3f…d41a<time>08:01:04</time></li>
<li class="done">上传 WeKnora<time>08:01:07 · 成功</time></li>
<li class="bad">文档解析<time>08:03:40 · 失败(validation_failed)</time></li>
<li>索引与增强(未执行)</li>
</ul>
<dl class="dl">
<dt>内容Hash</dt><dd>8e3f19…d41a(来源提供)</dd>
<dt>文件身份</dt><dd>来源稳定ID ext-9931 · 置信度 official_id</dd>
<dt>最近尝试</dt><dd>job-3f9a… · 第2次 · 164秒</dd>
<dt>死信</dt><dd>否(仍可重试)</dd>
</dl>
<p style="margin-top:16px"><button class="danger" style="width:100%">重试该文件</button></p>
</div>
<script>
function openDrawer(name){document.getElementById('drawer-title').textContent=name;document.getElementById('drawer').classList.add('open')}
</script>
</body>
</html>