<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="stylesheet" href="_ds/industry-22c874fd-9888-4e99-8234-d60d39b3d719/styles.css">
<script src="_ds/industry-22c874fd-9888-4e99-8234-d60d39b3d719/_ds_bundle.js"></script>
<style>
body{margin:0;background:#f2f2f3;min-width:1280px}
*{scrollbar-width:thin;scrollbar-color:var(--color-accent-300) transparent}
a{color:#5980a6}a:hover{color:#416180}
@keyframes omIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes omScan{to{background-position:28px 0}}
@keyframes omDraw{to{stroke-dashoffset:0}}
@keyframes omGrow{from{width:0}}
</style>
</helmet>
<dc-import name="ConsoleNav" active="failures" hint-size="100%,92px"></dc-import>
<div data-screen-label="失败中心" style="max-width:1400px;margin:0 auto;padding:22px 24px 64px;font-family:var(--font-body);animation:omIn .5s cubic-bezier(.2,.7,.2,1) both">
  <div style="display:flex;align-items:flex-end;gap:16px;margin-bottom:16px">
    <div>
      <div style="font-size:10px;letter-spacing:.18em;color:var(--color-accent-700);font-weight:500">06 · FAILURES</div>
      <h2 style="margin:2px 0 0;font-size:30px">失败中心</h2>
      <div class="text-muted" style="font-size:12.5px;margin-top:2px">跨任务聚类 · 失败指纹由稳定字段构成,工程师可拆分/合并/命名,结果反哺规则</div>
    </div>
    <span style="margin-left:auto"></span>
    <input class="input" placeholder="搜索指纹 / 日志特征 / run…" style="width:240px;font-size:12.5px;min-height:34px">
    <div class="seg" style="background:var(--color-bg)">
      <label class="seg-opt"><input type="radio" name="fcat" checked="{{ cAll }}" onChange="{{ setAll }}"><span>全部 7</span></label>
      <label class="seg-opt"><input type="radio" name="fcat" checked="{{ cDut }}" onChange="{{ setDut }}"><span>DUT_* 3</span></label>
      <label class="seg-opt"><input type="radio" name="fcat" checked="{{ cInfra }}" onChange="{{ setInfra }}"><span>INFRA_* 2</span></label>
      <label class="seg-opt"><input type="radio" name="fcat" checked="{{ cScript }}" onChange="{{ setScript }}"><span>SCRIPT 1</span></label>
      <label class="seg-opt"><input type="radio" name="fcat" checked="{{ cUnk }}" onChange="{{ setUnk }}"><span>UNKNOWN 1</span></label>
    </div>
  </div>

  <div style="display:flex;gap:16px;align-items:center;border:1px solid var(--color-divider);padding:8px 14px;margin-bottom:16px;font-size:10.5px;color:var(--color-neutral-700);flex-wrap:wrap">
    <span style="font-size:10px;letter-spacing:.12em;color:var(--color-neutral-600)">视觉语言</span>
    <span><span style="display:inline-block;width:10px;height:9px;background:var(--color-accent-800);vertical-align:-1px"></span> DUT_* 实心 — 真实信号,计入版本结论</span>
    <span><span style="display:inline-block;width:10px;height:9px;background:repeating-linear-gradient(135deg,rgba(29,31,32,.35) 0 2px,transparent 2px 5px);border:1px solid var(--color-divider);vertical-align:-1px"></span> INFRA_* 斜线 — 基础设施噪声,单独监控误报率</span>
    <span><span style="display:inline-block;width:10px;height:9px;background:var(--color-neutral-300);vertical-align:-1px"></span> SCRIPT 灰 — 脚本/参数问题</span>
    <span><span style="display:inline-block;width:10px;height:9px;border:1px dashed var(--color-neutral-500);vertical-align:-1px"></span> UNKNOWN 虚线 — 证据不足,等待分类</span>
    <span><span style="display:inline-block;width:10px;height:9px;background:#b03d2e;vertical-align:-1px"></span> 阻断 — 门禁级</span>
  </div>

  <div class="card blueprint" style-hover="border-color:var(--color-accent-400);box-shadow:var(--shadow-sm)" style="transition:border-color .15s ease,box-shadow .15s ease;padding:0;gap:0;overflow:visible">
    <i class="corner tl"></i><i class="corner tr"></i><i class="corner bl"></i><i class="corner br"></i>
    <div style="display:grid;grid-template-columns:30px 92px 240px 1fr 120px 130px 150px 110px;gap:10px;align-items:center;padding:9px 14px;border-bottom:1px solid var(--color-divider);font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--color-neutral-600)">
      <span></span><span>指纹</span><span>状态码</span><span>摘要</span><span>次数 · 14D</span><span>首次 / 最近</span><span>关联版本</span><span>状态</span>
    </div>
    <sc-for list="{{ rows }}" as="r" hint-placeholder-count="7">
      <div>
        <div onClick="{{ r.toggle }}" style="{{ r.rowStyle }}">
          <span style="{{ r.chevStyle }}">{{ r.chev }}</span>
          <span style="font-family:ui-monospace,Menlo,monospace;font-size:12px;font-weight:700">{{ r.id }}</span>
          <span><span style="{{ r.tagStyle }}">{{ r.code }}</span></span>
          <span style="font-size:13px">{{ r.summary }}<sc-if value="{{ r.blocking }}" hint-placeholder-val="{{ false }}"><span style="font-family:ui-monospace,Menlo,monospace;font-size:9.5px;background:#b03d2e;color:#f7f4f2;padding:1px 6px;margin-left:8px;vertical-align:1px">阻断</span></sc-if></span>
          <span style="display:flex;align-items:flex-end;gap:8px"><span style="font-family:var(--font-heading);font-weight:600;font-size:18px;line-height:1">{{ r.count }}</span><span style="display:flex;align-items:flex-end;gap:2px;height:16px">
            <sc-for list="{{ r.bars }}" as="b" hint-placeholder-count="7"><span style="{{ b.s }}"></span></sc-for>
          </span></span>
          <span style="font-family:ui-monospace,Menlo,monospace;font-size:10.5px;color:var(--color-neutral-600);line-height:1.5">{{ r.first }}<br>{{ r.last }}</span>
          <span style="display:flex;gap:4px;flex-wrap:wrap">
            <sc-for list="{{ r.vers }}" as="v" hint-placeholder-count="2"><span style="font-family:ui-monospace,Menlo,monospace;font-size:9.5px;border:1px solid var(--color-divider);padding:1px 6px;color:var(--color-neutral-700)">{{ v }}</span></sc-for>
          </span>
          <span><span style="{{ r.stTagStyle }}">{{ r.status }}</span></span>
        </div>
        <sc-if value="{{ r.open }}" hint-placeholder-val="{{ false }}">
          <div style="display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:16px;padding:14px 16px 16px 54px;background:var(--color-neutral-100);border-bottom:1px solid var(--color-divider)">
            <div>
              <div style="font-size:10px;letter-spacing:.1em;color:var(--color-neutral-600);margin-bottom:7px">指纹特征字段 · SIGNATURE</div>
              <div style="font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:1.9;color:var(--color-neutral-800)">
                <sc-for list="{{ r.feats }}" as="ft" hint-placeholder-count="4"><div style="display:flex;gap:10px"><span style="color:var(--color-neutral-500);min-width:88px">{{ ft.k }}</span><span>{{ ft.v }}</span></div></sc-for>
              </div>
            </div>
            <div>
              <div style="font-size:10px;letter-spacing:.1em;color:var(--color-neutral-600);margin-bottom:7px">关联运行 · {{ r.count }} 次</div>
              <div style="display:flex;flex-direction:column;gap:5px">
                <sc-for list="{{ r.runs }}" as="rn" hint-placeholder-count="3"><a href="Evidence.dc.html" style="font-family:ui-monospace,Menlo,monospace;font-size:10.5px;border:1px solid var(--color-accent-400);color:var(--color-accent-700);padding:3px 8px;text-decoration:none;width:fit-content">{{ rn }}</a></sc-for>
              </div>
            </div>
            <div style="display:flex;flex-direction:column;gap:8px">
              <div>
                <div style="font-size:10px;letter-spacing:.1em;color:var(--color-neutral-600);margin-bottom:7px">最短复现 · REPRO</div>
                <div style="font-size:12px;line-height:1.6;border:1px solid var(--color-divider);padding:8px 10px;background:var(--color-bg)">{{ r.repro }}</div>
              </div>
              <div style="display:flex;gap:8px;flex-wrap:wrap">
                <button class="btn btn-primary" style="font-size:12px;padding:5px 12px">生成缺陷草稿</button>
                <button class="btn btn-secondary" style="font-size:12px;padding:5px 12px">创建复现任务</button>
                <button class="btn btn-secondary" style="font-size:12px;padding:5px 12px">合并…</button>
                <button class="btn btn-secondary" style="font-size:12px;padding:5px 12px">拆分</button>
              </div>
            </div>
          </div>
        </sc-if>
      </div>
    </sc-for>
  </div>
  <div style="display:flex;gap:16px;margin-top:12px;font-size:11px;color:var(--color-neutral-600)">
    <span>聚类由归一化结构字段计算签名,语义模型仅辅助合并建议</span>
    <span style="margin-left:auto">30 天:去重后 7 簇 ← 43 次原始失败 · 重复问题合并率 84%</span>
  </div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props="{&quot;$preview&quot;:{&quot;width&quot;:1440,&quot;height&quot;:880}}">
class Component extends DCLogic {
  state = { cat: 'all', openId: 'FS-0091' };
  renderVals() {
    const mono = { fontFamily: 'ui-monospace,Menlo,monospace' };
    const tagOf = code => {
      if (code.startsWith('DUT')) return { ...mono, fontSize: '10px', padding: '2px 8px', background: 'var(--color-accent-800)', color: '#f2f2f3' };
      if (code.startsWith('INFRA')) return { ...mono, fontSize: '10px', padding: '2px 8px', background: 'repeating-linear-gradient(135deg,rgba(29,31,32,.12) 0 2px,transparent 2px 5px)', border: '1px solid var(--color-divider)', color: 'var(--color-neutral-800)' };
      if (code === 'UNKNOWN') return { ...mono, fontSize: '10px', padding: '2px 8px', border: '1px dashed var(--color-neutral-500)', color: 'var(--color-neutral-700)' };
      return { ...mono, fontSize: '10px', padding: '2px 8px', background: 'var(--color-neutral-200)', color: 'var(--color-neutral-800)' };
    };
    const stOf = st => {
      const base = { fontSize: '10.5px', padding: '2px 9px', letterSpacing: '.02em' };
      if (st === '已建单') return { ...base, background: 'var(--color-accent-100)', color: 'var(--color-accent-800)' };
      if (st === '待建单') return { ...base, border: '1px solid #b03d2e', color: '#8a2e22' };
      if (st === '待分类') return { ...base, border: '1px dashed var(--color-neutral-500)', color: 'var(--color-neutral-700)' };
      if (st === '已修复') return { ...base, border: '1px solid var(--color-accent-400)', color: 'var(--color-accent-700)' };
      return { ...base, background: 'var(--color-neutral-200)', color: 'var(--color-neutral-800)' };
    };
    const C = [
      { id: 'FS-0074', cat: 'dut', code: 'DUT_DATA_FAILURE', summary: '4k 混合负载后 LBA 区间校验失败', blocking: true, count: 2, hist: [0,0,0,0,0,1,1], first: '首 07-26', last: '近 昨日', vers: ['3.3.0-rc2'], status: '待建单',
        feats: [{k:'step',v:'data.verify_hash'},{k:'lba_range',v:'0x2E41_0000–0x2E41_3FFF'},{k:'pattern',v:'写入后休眠,唤醒读校验 mismatch'},{k:'smart',v:'无介质错误计数增长'},{k:'data_loss',v:'true · 门禁级'}],
        runs: ['run-20260726-0007 · cycle 41', 'run-20260726-0009 · cycle 17'], repro: '写入 32G 校验集 → S4 → 唤醒读校验;固定 SAMPLE-002,预计 45min ×10 循环' },
      { id: 'FS-0091', cat: 'dut', code: 'DUT_ENUMERATION_FAILURE', summary: 'S4 唤醒后掉盘,链路未训练', blocking: false, count: 12, hist: [0,1,1,2,2,3,3], first: '首 07-18', last: '近 昨日', vers: ['3.3.0-rc1', '3.3.0-rc2'], status: '已建单',
        feats: [{k:'step',v:'dut.verify_enumeration'},{k:'kernel',v:'nvme nvme0: Device not ready; aborting reset'},{k:'power_state',v:'S4 resume · RTC 唤醒'},{k:'env',v:'HOST-L02 · BIOS F26b · 42–47°C'},{k:'recovery',v:'L3 Reset 后 100% 恢复'}],
        runs: ['run-20260726-0007 · cycle 41', 'run-20260725-0021 · cycle 63', 'run-20260722-0004 · cycle 12', '… 另 9 次'], repro: 'S4 循环 ×20 · 固定 WS-03 + SAMPLE-002 · 复现率 ~15% · 预计 3.5h' },
      { id: 'FS-0071', cat: 'dut', code: 'DUT_PERFORMANCE_REGRESSION', summary: '高温限速触发,4k 写长尾退化', blocking: false, count: 9, hist: [1,0,1,1,2,2,2], first: '首 07-12', last: '近 今日', vers: ['3.2.1', '3.3.0-rc2'], status: '观察',
        feats: [{k:'step',v:'io.run_profile 4k_mixed'},{k:'threshold',v:'P99 > 基线 +8%'},{k:'temp_window',v:'46°C 以上触发'},{k:'freq',v:'A:4 → B:9 · 偶发转频发'}],
        runs: ['run-20260727-0001 · cycle 33', 'run-20260726-0007 · cycle 08'], repro: '恒温箱 45°C · 4k_mixed 30min ×5 · 观察限速计数器' },
      { id: 'FS-0088', cat: 'infra', code: 'INFRA_HOST_OS_FAILURE', summary: 'Windows 蓝屏 DRIVER_POWER_STATE_FAILURE', blocking: false, count: 5, hist: [1,1,0,1,1,0,1], first: '首 07-08', last: '近 07-25', vers: ['跨版本'], status: '处理中',
        feats: [{k:'bugcheck',v:'0x9F · 冷启动循环期间'},{k:'scope',v:'跨 3 工位,与固件版本无关'},{k:'suspect',v:'主机 NIC 驱动电源管理'},{k:'guard',v:'不计入 DUT 结论'}],
        runs: ['run-20260725-0018 · cycle 88', 'run-20260721-0002 · cycle 41'], repro: 'golden image 更新 NIC 驱动后回归 ×50 冷启动' },
      { id: 'FS-0059', cat: 'infra', code: 'INFRA_NETWORK_FAILURE', summary: '交换机端口抖动导致 Agent 误报失联', blocking: false, count: 3, hist: [1,1,1,0,0,0,0], first: '首 06-30', last: '近 07-21', vers: ['—'], status: '已修复',
        feats: [{k:'signal',v:'OOB 心跳正常 + Agent 断连'},{k:'fix',v:'更换 SW-02 端口 6 网线'},{k:'lesson',v:'已加入判定规则:双路径交叉验证'}],
        runs: ['run-20260721-0006'], repro: '—' },
      { id: 'FS-0067', cat: 'script', code: 'TEST_SCRIPT_FAILURE', summary: 'fio 3.36 参数不兼容私有 profile', blocking: false, count: 9, hist: [2,2,1,1,1,1,1], first: '首 07-02', last: '近 今日', vers: ['—'], status: '处理中',
        feats: [{k:'stderr',v:'unrecognized option --write_hist_log'},{k:'owner',v:'测试平台组'},{k:'workaround',v:'连接器已降级参数集'}],
        runs: ['run-20260727-0002 · precheck'], repro: 'fio --version 校验加入 precheck,连接器 healthcheck 拦截' },
      { id: 'FS-0102', cat: 'unknown', code: 'UNKNOWN', summary: 'verify_hash 超时但各信号正常', blocking: false, count: 1, hist: [0,0,0,0,0,0,1], first: '首 昨日', last: '近 昨日', vers: ['3.2.1'], status: '待分类',
        feats: [{k:'signal',v:'主机/DUT/网络均正常'},{k:'evidence_gap',v:'缺 blktrace · 已加入下次采集'},{k:'action',v:'等待工程师分类 → 反哺规则'}],
        runs: ['run-20260726-0011 · cycle 12'], repro: '纳入观察名单 · 同参数复跑 ×5 后再判' }
    ];
    const cat = this.state.cat;
    const rows = C.filter(c => cat === 'all' || c.cat === cat).map(c => {
      const open = this.state.openId === c.id;
      const maxH = Math.max(...c.hist, 1);
      return {
        ...c, open,
        toggle: () => this.setState({ openId: open ? null : c.id }),
        chev: open ? '▾' : '▸',
        chevStyle: { color: 'var(--color-accent-700)', fontSize: '11px' },
        tagStyle: tagOf(c.code), stTagStyle: stOf(c.status),
        bars: c.hist.map(h => ({ s: { width: '5px', height: Math.max(2, (h / maxH) * 16) + 'px', background: h ? (c.cat === 'infra' ? 'repeating-linear-gradient(135deg,rgba(29,31,32,.4) 0 1px,transparent 1px 3px)' : c.cat === 'dut' ? 'var(--color-accent-700)' : 'var(--color-neutral-400)') : 'var(--color-neutral-200)', border: h && c.cat === 'infra' ? '1px solid var(--color-divider)' : 'none' } })),
        rowStyle: {
          display: 'grid', gridTemplateColumns: '30px 92px 240px 1fr 120px 130px 150px 110px', gap: '10px', alignItems: 'center',
          padding: '11px 14px', cursor: 'pointer', transition: 'background .15s ease',
          borderBottom: '1px solid rgba(29,31,32,.08)',
          background: open ? 'var(--color-accent-100)' : 'transparent',
          borderLeft: c.blocking ? '3px solid #b03d2e' : '3px solid transparent'
        }
      };
    });
    const set = c => () => this.setState({ cat: c });
    return {
      rows,
      cAll: cat === 'all', cDut: cat === 'dut', cInfra: cat === 'infra', cScript: cat === 'script', cUnk: cat === 'unknown',
      setAll: set('all'), setDut: set('dut'), setInfra: set('infra'), setScript: set('script'), setUnk: set('unknown')
    };
  }
}
</script>
</body>
</html>
