Files
knowledge-governance/docs/previews/refresh-2026-09-12/a-data-console.html
T
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

166 lines
11 KiB
HTML

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>方向A · Data-console(解析监控)</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Inter:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;700&display=swap">
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:Inter,"Noto Sans SC","PingFang SC",system-ui,sans-serif;background:#fafbfc;color:#0f1720;font-size:13px;line-height:1.5;-webkit-font-smoothing:antialiased}
.mono{font-family:"IBM Plex Mono","SF Mono",Menlo,monospace;font-variant-numeric:tabular-nums}
.app{display:grid;grid-template-columns:212px 1fr;min-height:100vh}
.side{background:#0e1c2b;color:#9fb6c6;padding:18px 0;display:flex;flex-direction:column;border-right:1px solid #0a141f}
.side .brand{padding:0 18px 16px;border-bottom:1px solid #1a2f44;display:flex;gap:10px;align-items:center}
.side .brand .dot{width:26px;height:26px;background:#2dd4bf;color:#04211d;display:grid;place-items:center;font-weight:700;font-size:13px;border-radius:4px}
.side .brand strong{color:#e8f2f8;font-size:13px;font-weight:600;letter-spacing:.02em}
.side .brand span{display:block;font-size:11px;color:#5b7789;margin-top:1px}
.side nav{padding:14px 8px;display:flex;flex-direction:column;gap:1px}
.side nav a{color:#8aa2b3;text-decoration:none;padding:7px 10px;font-size:12.5px;border-radius:4px;display:flex;justify-content:space-between;align-items:center}
.side nav a:hover{background:#152a3d;color:#d9e8f1}
.side nav a.on{background:#16324a;color:#fff;border-left:2px solid #2dd4bf;padding-left:8px}
.side nav a em{font-style:normal;font-family:"IBM Plex Mono",monospace;font-size:11px;color:#4d6a7d}
.side nav a.on em{color:#7dd8c8}
.side .foot{margin-top:auto;padding:14px 18px;border-top:1px solid #1a2f44;font-size:11px;color:#46647a}
.side .foot .live{color:#34d399}
.main{display:flex;flex-direction:column;min-width:0}
.top{height:44px;border-bottom:1px solid #e3e8ec;background:#fff;display:flex;align-items:center;gap:14px;padding:0 20px;font-size:12px;color:#57687a;position:sticky;top:0;z-index:5}
.top .crumb{color:#9aa8b4}
.top .crumb b{color:#0f1720;font-weight:600}
.top .meta{margin-left:auto;display:flex;gap:18px;font-family:"IBM Plex Mono",monospace;font-size:11px}
.top .meta span b{color:#0f1720;font-weight:500}
.top .meta .warn{color:#b45309}
.top .meta .ok{color:#047857}
.page{padding:22px 24px 40px;max-width:1240px;width:100%}
.page h1{font-size:20px;font-weight:600;letter-spacing:-.01em;margin-bottom:4px}
.page .sub{color:#57687a;font-size:12.5px;margin-bottom:20px;max-width:640px}
.tiles{display:grid;grid-template-columns:repeat(5,1fr);gap:1px;background:#e3e8ec;border:1px solid #e3e8ec;margin-bottom:22px}
.tile{background:#fff;padding:12px 14px}
.tile .lbl{font-size:11px;color:#57687a;margin-bottom:6px;letter-spacing:.02em}
.tile .num{font-family:"IBM Plex Mono",monospace;font-size:24px;font-weight:600;line-height:1;color:#0f1720}
.tile .delta{font-size:11px;margin-top:5px;font-family:"IBM Plex Mono",monospace}
.tile .delta.up{color:#047857}.tile .delta.dn{color:#b91c1c}.tile .delta.flat{color:#9aa8b4}
.tile.a-fail{border-top:2px solid #b91c1c}.tile.a-wait{border-top:2px solid #d97706}.tile.a-run{border-top:2px solid #2563eb}.tile.a-done{border-top:2px solid #059669}.tile.a-dead{border-top:2px solid #6b7280}
.sec-head{display:flex;align-items:baseline;gap:12px;margin:0 0 10px;padding-bottom:8px;border-bottom:1px solid #e3e8ec}
.sec-head h2{font-size:13px;font-weight:600;letter-spacing:.02em}
.sec-head .hint{font-size:11.5px;color:#8a98a4}
.sec-head .act{margin-left:auto;display:flex;gap:8px}
.btn{border:1px solid #d3dce3;background:#fff;color:#0f1720;padding:5px 11px;font-size:12px;border-radius:4px;cursor:pointer;font-weight:500}
.btn:hover{border-color:#94a3b8;background:#f8fafc}
.btn.pri{background:#0e1c2b;border-color:#0e1c2b;color:#fff}
.btn.pri:hover{background:#1a2f44}
.task{border:1px solid #e3e8ec;background:#fff;margin-bottom:1px}
.task:first-of-type{border-radius:6px 6px 0 0}
.task:last-of-type{border-radius:0 0 6px 6px}
.task .row{display:grid;grid-template-columns:20px minmax(0,1fr) auto;gap:12px;padding:12px 14px;align-items:start}
.task .chk{margin-top:3px}
.task h4{font-size:13px;font-weight:600;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.scope{font-family:"IBM Plex Mono",monospace;font-size:10.5px;padding:1px 6px;border-radius:3px;border:1px solid #e3e8ec;color:#57687a;background:#f8fafc}
.scope.in{color:#1d4ed8;border-color:#c7d7f2;background:#eff4fd}
.scope.out{color:#047857;border-color:#bfe3d4;background:#eefaf4}
.chg{font-size:10.5px;padding:1px 6px;border-radius:3px;font-weight:600}
.chg.add{color:#047857;background:#d7f2e4}
.chg.upd{color:#1d4ed8;background:#dbe7fd}
.why{font-size:11.5px;color:#8a1c1c;margin-top:5px;font-family:"IBM Plex Mono",monospace}
.why code{background:#fdecec;padding:0 5px;border-radius:3px;color:#b91c1c}
.chain{display:flex;gap:3px;margin-top:8px;flex-wrap:wrap;font-family:"IBM Plex Mono",monospace;font-size:10.5px}
.chain span{padding:2px 8px;border:1px solid #e3e8ec;background:#f8fafc;color:#8a98a4;border-radius:3px}
.chain span.done{background:#eefaf4;border-color:#bfe3d4;color:#047857}
.chain span.bad{background:#fdecec;border-color:#f2baba;color:#b91c1c;font-weight:600}
.chain span.act{background:#eff4fd;border-color:#c7d7f2;color:#1d4ed8}
.advice{font-size:11.5px;color:#57687a;margin-top:6px}
.task .ops{display:flex;flex-direction:column;gap:6px;align-items:flex-end}
.task-id{font-family:"IBM Plex Mono",monospace;font-size:10.5px;color:#9aa8b4}
.dlq{margin-top:22px;border:1px solid #e3e8ec;background:#fff;border-radius:6px;overflow:hidden}
.dlq ul{list-style:none}
.dlq li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:14px;padding:10px 14px;border-top:1px solid #f0f3f5;font-size:12px;align-items:center}
.dlq li:first-child{border-top:0}
.dlq .code{font-family:"IBM Plex Mono",monospace;font-size:11px;color:#b91c1c}
.dlq .path{color:#8a98a4;font-size:11.5px;margin-top:2px}
.strip{margin-top:26px;border:1px solid #e3e8ec;background:#fff;display:flex;flex-wrap:wrap;font-family:"IBM Plex Mono",monospace;font-size:11px;border-radius:6px;overflow:hidden}
.strip div{padding:9px 16px;border-right:1px solid #f0f3f5;color:#57687a}
.strip div b{color:#0f1720;font-weight:500}
.strip .bad{color:#b91c1c}.strip .good{color:#047857}
.strip div:last-child{border-right:0}
</style>
</head>
<body>
<div class="app">
<aside class="side">
<div class="brand"><div class="dot">治</div><div><strong>知识治理</strong><span>governance console</span></div></div>
<nav>
<a href="#">来源与目录 <em>8</em></a>
<a href="#" class="on">解析监控 <em>3</em></a>
<a href="#">发布管理 <em>2</em></a>
<a href="#">系统设置</a>
</nav>
<div class="foot"><span class="live">●</span> worker-01 心跳 4s 前<br>快照 2026-09-12 10:41</div>
</aside>
<div class="main">
<div class="top">
<div class="crumb">解析监控 / <b>需人工处理</b></div>
<div class="meta"><span>1h成功 <b class="warn">88.9%</b></span><span>24h成功 <b class="ok">96.4%</b></span><span>Worker <b>2</b></span><span>队列 <b>待 3 / 跑 4</b></span></div>
</div>
<div class="page">
<h1>需人工处理</h1>
<p class="sub">失败原因、处理链定位与建议直接放在卡片上。勾选后可批量重试,死信重新入队会保留原任务与全部审计行。</p>
<div class="tiles">
<div class="tile a-fail"><div class="lbl">失败</div><div class="num">2</div><div class="delta dn">+2 · 今日</div></div>
<div class="tile a-wait"><div class="lbl">停滞</div><div class="num">1</div><div class="delta dn">45分钟</div></div>
<div class="tile a-run"><div class="lbl">处理中</div><div class="num">4</div><div class="delta flat">—</div></div>
<div class="tile a-done"><div class="lbl">已完成</div><div class="num">48</div><div class="delta up">+6 · 今日</div></div>
<div class="tile a-dead"><div class="lbl">死信</div><div class="num">1</div><div class="delta flat">可重入队</div></div>
</div>
<div class="sec-head"><h2>失败任务</h2><span class="hint">3 条 · 按失败阶段排序</span><span class="act"><input placeholder="操作人" style="border:1px solid #d3dce3;border-radius:4px;padding:4px 8px;font-size:12px;width:110px"><button class="btn">仅看中英对照</button><button class="btn pri">批量重试所选 (2)</button></span></div>
<div class="task">
<div class="row">
<div class="chk"><input type="checkbox" checked></div>
<div>
<h4>CR20A 电气规格说明书.pdf <span class="scope out">对外</span> <span class="chg upd">更新</span></h4>
<div class="why">错误码 <code>remote_parse_failed</code> · 第 2 次尝试 · 已停留 71.1小时 · 失败于 文档解析</div>
<div class="chain"><span class="done">下载 ✓</span><span class="done">Hash ✓</span><span class="done">OSS ✓</span><span class="bad">文档解析 ✗</span><span>WeKnora 上传</span><span>索引</span><span>完成</span></div>
<div class="advice">建议先在 WeKnora 手动解析该文件确认格式,再决定是否重试。 <span class="task-id">cs-1 · tp-failed</span></div>
</div>
<div class="ops"><button class="btn pri">重试</button></div>
</div>
</div>
<div class="task">
<div class="row">
<div class="chk"><input type="checkbox" checked></div>
<div>
<h4>伺服驱动器调试手册.docx <span class="scope in">对内</span> <span class="chg add">新增</span></h4>
<div class="why">错误码 <code>mineru_timeout</code> · 第 1 次尝试 · 已停留 45分钟 · 失败于 索引 / 增强</div>
<div class="chain"><span class="done">下载 ✓</span><span class="done">Hash ✓</span><span class="done">OSS ✓</span><span class="done">文档解析 ✓</span><span class="done">WeKnora 上传 ✓</span><span class="bad">索引 ✗</span><span>完成</span></div>
<div class="advice">多为 MinerU 容量或超时问题,确认服务恢复接单后重试。 <span class="task-id">cs-3 · tp-044</span></div>
</div>
<div class="ops"><button class="btn pri">重试</button></div>
</div>
</div>
<div class="sec-head" style="margin-top:26px"><h2>死信(尝试耗尽)</h2><span class="hint">1 条 · 不可自动重试</span></div>
<div class="dlq"><ul>
<li><div><b>对外知识库 · test.upload</b> <span class="code">release_manifest_mismatch</span><div class="path">cs-2 · CR1A 固件变更记录.pdf · 尝试 5/5 · 2026-09-10 14:22</div></div><button class="btn">重新入队</button></li>
</ul></div>
<div class="strip">
<div>MinerU <b class="good">可接单</b></div>
<div>WeKnora 测试 <b class="good">可接单</b></div>
<div>PostgreSQL <b class="good">12ms</b></div>
<div>队列 <b>3 待 / 4 跑 / 0 重试</b></div>
<div>CPU 42% · 内存 18.6/32.0GB</div>
</div>
</div>
</div>
</div>
</body>
</html>