mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 02:00:46 +08:00
Improve compare progress for large BGP sheets.
Show pending check items instead of a fake 100% pass, publish sheet results as each finishes, and use keyset chunk loads with rows-loaded progress. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c5efbbd016
commit
9adf9f2764
5 changed files with 255 additions and 62 deletions
|
|
@ -500,6 +500,8 @@ const en = {
|
|||
runStatusFailed: "Failed",
|
||||
runStatusDoneSec: "Done {{s}}s",
|
||||
runProgress: "{{phase}} · sheet {{i}}/{{n}} · {{sheet}} · {{s}}s elapsed",
|
||||
runRowsLoaded: "Loaded {{side}} {{n}} rows",
|
||||
sheetPending: "Pending",
|
||||
ranWithDuration: "Compare finished ({{s}}s)",
|
||||
unchangedNotStored: "Success rows were counted but not stored. Set “Store success rows” to sample and re-run for spot-check.",
|
||||
unchangedSampleHint: "{{total}} success rows total; browsing a sample of {{listed}} (hydrated from source tables for cutover spot-check). Pass rate uses all {{total}}.",
|
||||
|
|
|
|||
|
|
@ -499,6 +499,8 @@ const zh = {
|
|||
runStatusFailed: "失败",
|
||||
runStatusDoneSec: "完成 {{s}}s",
|
||||
runProgress: "{{phase}} · 表 {{i}}/{{n}} · {{sheet}} · 已用 {{s}}s",
|
||||
runRowsLoaded: "已加载 {{side}} {{n}} 行",
|
||||
sheetPending: "等待中",
|
||||
ranWithDuration: "比对完成(耗时 {{s}} 秒)",
|
||||
unchangedNotStored: "成功行仅统计数量未落库。可在任务配置将「成功行保存」改为抽样后重新比对(抽查用)。",
|
||||
unchangedSampleHint: "成功共 {{total}} 条,明细抽样 {{listed}} 条(从原表补全显示,割接抽查用)。通过率按全部 {{total}} 计。",
|
||||
|
|
|
|||
|
|
@ -12152,6 +12152,15 @@ body:has(.bs-cmp-board:fullscreen) {
|
|||
box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.22);
|
||||
}
|
||||
|
||||
.bs-cmp-nav__item.is-pending .bs-cmp-nav__dot {
|
||||
background: #64748b;
|
||||
box-shadow: 0 0 0 2px rgba(100, 116, 139, 0.25);
|
||||
}
|
||||
|
||||
.bs-cmp-nav__item.is-pending .bs-cmp-nav__name {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.bs-cmp-nav__name {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
|
|
|
|||
|
|
@ -1198,7 +1198,8 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
Number(c.success_count ?? c.unchanged ?? 0);
|
||||
|
||||
const sheetPassRateOf = (c: {
|
||||
pass_rate?: number;
|
||||
pass_rate?: number | null;
|
||||
status?: string;
|
||||
fail_count?: number;
|
||||
diff_count?: number;
|
||||
removed?: number;
|
||||
|
|
@ -1206,7 +1207,10 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
success_count?: number;
|
||||
unchanged?: number;
|
||||
added?: number;
|
||||
}) => {
|
||||
}): number | null => {
|
||||
const st = String(c.status || "");
|
||||
if (st === "pending" || st === "running" || st === "queued") return null;
|
||||
if (c.pass_rate === null) return null;
|
||||
// Always recompute from fail/success so added never skews pass rate
|
||||
const fail = sheetFailOf(c);
|
||||
const ok = sheetSuccessOf(c);
|
||||
|
|
@ -1222,6 +1226,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
title?: string;
|
||||
metric_id: string;
|
||||
mode?: string;
|
||||
status?: string;
|
||||
added?: number;
|
||||
removed?: number;
|
||||
changed?: number;
|
||||
|
|
@ -1231,10 +1236,13 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
fail_count?: number;
|
||||
success_count?: number;
|
||||
diff_count?: number;
|
||||
pass_rate?: number;
|
||||
pass_rate?: number | null;
|
||||
}>;
|
||||
// Failures first so ops can scan quickly when many sheets
|
||||
// Failures first; keep pending/running at the end so completed fails stay visible
|
||||
return [...raw].sort((a, b) => {
|
||||
const pa = ["pending", "running", "queued"].includes(String(a.status || "")) ? 1 : 0;
|
||||
const pb = ["pending", "running", "queued"].includes(String(b.status || "")) ? 1 : 0;
|
||||
if (pa !== pb) return pa - pb;
|
||||
const da = sheetFailOf(a);
|
||||
const db = sheetFailOf(b);
|
||||
if (da !== db) return db - da;
|
||||
|
|
@ -1245,6 +1253,9 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
const activeFail = sheetFailOf(activeSheetCard || {});
|
||||
const activeSuccess = sheetSuccessOf(activeSheetCard || {});
|
||||
const activePassRate = sheetPassRateOf(activeSheetCard || {});
|
||||
const activeSheetPending = ["pending", "running", "queued"].includes(
|
||||
String(activeSheetCard?.status || ""),
|
||||
);
|
||||
const activeAdded = Number(activeSheetCard?.added || 0);
|
||||
const showFailCol =
|
||||
kindFilter === "diff" || kindFilter === "all" || kindFilter === "added";
|
||||
|
|
@ -1868,6 +1879,8 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
before_count?: number;
|
||||
after_count?: number;
|
||||
diff_rows?: number;
|
||||
load_side?: string;
|
||||
rows_loaded?: number;
|
||||
};
|
||||
|
||||
// Poll active compare runs so the modal can be closed and reopened safely.
|
||||
|
|
@ -3020,6 +3033,14 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
s: String(Math.round(Number(runProgress.elapsed_ms || 0) / 1000)),
|
||||
})}
|
||||
</span>
|
||||
{Number(runProgress.rows_loaded || 0) > 0 ? (
|
||||
<span className="muted">
|
||||
{t("bizCompare.runRowsLoaded", {
|
||||
side: String(runProgress.load_side || "—"),
|
||||
n: String(runProgress.rows_loaded || 0),
|
||||
})}
|
||||
</span>
|
||||
) : null}
|
||||
{runDetail.message ? (
|
||||
<span className="muted bs-cmp-progress__msg">{String(runDetail.message)}</span>
|
||||
) : null}
|
||||
|
|
@ -3098,11 +3119,14 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
const unchanged = Number(s.summary?.unchanged || 0);
|
||||
const fail = removed + changed;
|
||||
const judged = fail + unchanged;
|
||||
const st = String((s as any).status || "done");
|
||||
const pending = ["pending", "running", "queued"].includes(st);
|
||||
return {
|
||||
sheet_id: sheetIdentity(s),
|
||||
title: sheetLabel(s),
|
||||
metric_id: s.metric_id,
|
||||
mode: s.mode,
|
||||
status: st,
|
||||
added: s.summary?.added,
|
||||
removed,
|
||||
changed,
|
||||
|
|
@ -3112,9 +3136,11 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
fail_count: fail,
|
||||
success_count: unchanged,
|
||||
diff_count: fail,
|
||||
pass_rate: judged
|
||||
? Math.round((unchanged / judged) * 1000) / 10
|
||||
: 100,
|
||||
pass_rate: pending
|
||||
? null
|
||||
: judged
|
||||
? Math.round((unchanged / judged) * 1000) / 10
|
||||
: 100,
|
||||
};
|
||||
})
|
||||
).map((c) => {
|
||||
|
|
@ -3124,6 +3150,9 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
const id = sheetIdentity(c);
|
||||
const label = sheetLabel(c);
|
||||
const active = resultSheetId === id;
|
||||
const pending = ["pending", "running", "queued"].includes(
|
||||
String((c as any).status || ""),
|
||||
);
|
||||
return (
|
||||
<button
|
||||
key={id}
|
||||
|
|
@ -3131,10 +3160,14 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
role="tab"
|
||||
aria-selected={active}
|
||||
className={`bs-cmp-nav__item${active ? " is-active" : ""}${
|
||||
fail > 0 ? " has-diff" : " is-clean"
|
||||
pending ? " is-pending" : fail > 0 ? " has-diff" : " is-clean"
|
||||
}`}
|
||||
onClick={() => setResultSheetId(id)}
|
||||
title={`${label} · ${t("bizCompare.kindFail")} ${fail} · ${t("bizCompare.kindSuccess")} ${ok} · ${t("bizCompare.passRateShort")} ${rate}%`}
|
||||
title={
|
||||
pending
|
||||
? `${label} · ${t("bizCompare.sheetPending")}`
|
||||
: `${label} · ${t("bizCompare.kindFail")} ${fail} · ${t("bizCompare.kindSuccess")} ${ok} · ${t("bizCompare.passRateShort")} ${rate}%`
|
||||
}
|
||||
>
|
||||
<span className="bs-cmp-nav__dot" aria-hidden />
|
||||
<span className="bs-cmp-nav__name">{label}</span>
|
||||
|
|
@ -3144,13 +3177,13 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
fail > 0 ? " is-hot" : ""
|
||||
}`}
|
||||
>
|
||||
{fail}
|
||||
{pending ? "—" : fail}
|
||||
</span>
|
||||
<span className="bs-cmp-nav__num bs-cmp-nav__num--ok is-hot">
|
||||
{ok}
|
||||
{pending ? "—" : ok}
|
||||
</span>
|
||||
<span className="bs-cmp-nav__num bs-cmp-nav__num--rate">
|
||||
{rate}%
|
||||
{pending || rate === null ? "…" : `${rate}%`}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
|
|
@ -3161,7 +3194,13 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
|
||||
<div className="bs-cmp-main">
|
||||
<div
|
||||
className={`bs-cmp-strip${activeFail > 0 ? " is-warn" : " is-ok"}`}
|
||||
className={`bs-cmp-strip${
|
||||
activeSheetPending
|
||||
? " is-pending"
|
||||
: activeFail > 0
|
||||
? " is-warn"
|
||||
: " is-ok"
|
||||
}`}
|
||||
>
|
||||
<div className="bs-cmp-strip__sheet">
|
||||
<span className="bs-cmp-strip__sheet-tag">
|
||||
|
|
@ -3174,18 +3213,28 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
{sheetLabel(activeSheetCard)}
|
||||
</strong>
|
||||
<span className="muted bs-cmp-strip__sheet-mode">
|
||||
{activeFail > 0 ? t("bizCompare.kindFail") : t("bizCompare.kindPass")}
|
||||
{activeSheetPending
|
||||
? t("bizCompare.sheetPending")
|
||||
: activeFail > 0
|
||||
? t("bizCompare.kindFail")
|
||||
: t("bizCompare.kindPass")}
|
||||
{activeSheetCard?.mode === "presence"
|
||||
? ` · ${t("bizCompare.presenceShort")}`
|
||||
: ""}
|
||||
{` · ${activeSheetCard?.before_count ?? 0}→${activeSheetCard?.after_count ?? 0}`}
|
||||
{activeSheetPending
|
||||
? ""
|
||||
: ` · ${activeSheetCard?.before_count ?? 0}→${activeSheetCard?.after_count ?? 0}`}
|
||||
</span>
|
||||
</div>
|
||||
<div className="bs-cmp-strip__pass" title={t("bizCompare.passRate")}>
|
||||
<span className="bs-cmp-strip__pass-label">
|
||||
{t("bizCompare.passRate")}
|
||||
</span>
|
||||
<span className="bs-cmp-strip__pass-value">{activePassRate}%</span>
|
||||
<span className="bs-cmp-strip__pass-value">
|
||||
{activeSheetPending || activePassRate === null
|
||||
? "…"
|
||||
: `${activePassRate}%`}
|
||||
</span>
|
||||
</div>
|
||||
<div className="bs-cmp-strip__kinds" role="group">
|
||||
{(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue