mirror of
https://github.com/hansjone/netx.git
synced 2026-10-13 03:13:21 +08:00
Show before/after values for all non-key compare result columns.
Key stays single-value; other fields always render a paired 前/后 cell so cutover diffs are readable at a glance. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
157188bd3e
commit
97796478b0
4 changed files with 102 additions and 50 deletions
|
|
@ -381,6 +381,8 @@ const en = {
|
||||||
failFields: "Failed fields",
|
failFields: "Failed fields",
|
||||||
failFieldsEmpty: "—",
|
failFieldsEmpty: "—",
|
||||||
failWholeRow: "Whole row",
|
failWholeRow: "Whole row",
|
||||||
|
pairBefore: "Before",
|
||||||
|
pairAfter: "After",
|
||||||
sheetAllPass: "All match",
|
sheetAllPass: "All match",
|
||||||
filterFailField: "Failed compare field",
|
filterFailField: "Failed compare field",
|
||||||
filterFailFieldAll: "Any failed field",
|
filterFailFieldAll: "Any failed field",
|
||||||
|
|
|
||||||
|
|
@ -381,6 +381,8 @@ const zh = {
|
||||||
failFields: "失败项",
|
failFields: "失败项",
|
||||||
failFieldsEmpty: "—",
|
failFieldsEmpty: "—",
|
||||||
failWholeRow: "整行",
|
failWholeRow: "整行",
|
||||||
|
pairBefore: "前",
|
||||||
|
pairAfter: "后",
|
||||||
sheetAllPass: "全部一致",
|
sheetAllPass: "全部一致",
|
||||||
filterFailField: "失败比对项",
|
filterFailField: "失败比对项",
|
||||||
filterFailFieldAll: "全部失败项",
|
filterFailFieldAll: "全部失败项",
|
||||||
|
|
|
||||||
|
|
@ -10735,8 +10735,47 @@ html.login-page--paused .login-page__flare {
|
||||||
background: rgba(245, 158, 11, 0.08);
|
background: rgba(245, 158, 11, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bs-cmp-pair {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
min-width: 4.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-pair__row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.6em minmax(0, 1fr);
|
||||||
|
gap: 6px;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-pair__tag {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
color: #64748b;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-val-cell--diff .bs-cmp-pair__row:first-child .bs-cmp-pair__tag {
|
||||||
|
color: #fca5a5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-val-cell--diff .bs-cmp-pair__row:last-child .bs-cmp-pair__tag {
|
||||||
|
color: #86efac;
|
||||||
|
}
|
||||||
|
|
||||||
.bs-cmp-val {
|
.bs-cmp-val {
|
||||||
font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
|
font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
|
||||||
|
color: #e2e8f0;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-val.is-empty {
|
||||||
|
color: #64748b;
|
||||||
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-val--pre {
|
.bs-cmp-val--pre {
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,51 @@ function failFieldNames(d: DiffRow): string[] {
|
||||||
return Object.keys(d.changes || {});
|
return Object.keys(d.changes || {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Non-key fields: always show before/after pair for cutover review. */
|
||||||
|
function PairCell(props: {
|
||||||
|
beforeText: string;
|
||||||
|
afterText: string;
|
||||||
|
mismatch: boolean;
|
||||||
|
reason?: string;
|
||||||
|
beforeLabel: string;
|
||||||
|
afterLabel: string;
|
||||||
|
}) {
|
||||||
|
const { beforeText, afterText, mismatch, reason, beforeLabel, afterLabel } = props;
|
||||||
|
const pre = beforeText || "—";
|
||||||
|
const post = afterText || "—";
|
||||||
|
return (
|
||||||
|
<td
|
||||||
|
className={`bs-cmp-val-cell bs-cmp-val-cell--pair${
|
||||||
|
mismatch ? " bs-cmp-val-cell--diff" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="bs-cmp-pair">
|
||||||
|
<div className="bs-cmp-pair__row">
|
||||||
|
<span className="bs-cmp-pair__tag">{beforeLabel}</span>
|
||||||
|
<span
|
||||||
|
className={`bs-cmp-val${mismatch ? " bs-cmp-val--pre" : ""}${
|
||||||
|
!beforeText ? " is-empty" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pre}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="bs-cmp-pair__row">
|
||||||
|
<span className="bs-cmp-pair__tag">{afterLabel}</span>
|
||||||
|
<span
|
||||||
|
className={`bs-cmp-val${mismatch ? " bs-cmp-val--post" : ""}${
|
||||||
|
!afterText ? " is-empty" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{post}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{reason ? <div className="bs-cmp-val-reason muted">{reason}</div> : null}
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function toggleInList(list: string[], name: string, on: boolean): string[] {
|
function toggleInList(list: string[], name: string, on: boolean): string[] {
|
||||||
if (on) return list.includes(name) ? list : [...list, name];
|
if (on) return list.includes(name) ? list : [...list, name];
|
||||||
return list.filter((x) => x !== name);
|
return list.filter((x) => x !== name);
|
||||||
|
|
@ -2263,58 +2308,22 @@ export function BizComparePage() {
|
||||||
{resultColumns.extras.map((f) => {
|
{resultColumns.extras.map((f) => {
|
||||||
const pv = cellText(pre[f]);
|
const pv = cellText(pre[f]);
|
||||||
const av = cellText(post[f]);
|
const av = cellText(post[f]);
|
||||||
const isCmp = resultColumns.compareSet.has(f);
|
|
||||||
const ch = d.changes?.[f];
|
const ch = d.changes?.[f];
|
||||||
if (!isCmp) {
|
const isCmp = resultColumns.compareSet.has(f);
|
||||||
const show =
|
// Compare fields: engine mismatch; display fields: value differ / side missing
|
||||||
d.kind === "removed" ? pv || "—" : av || pv || "—";
|
const mismatch = isCmp
|
||||||
return (
|
? Boolean(ch) || d.kind === "added" || d.kind === "removed"
|
||||||
<td key={f} className="bs-cmp-val-cell bs-cmp-val-cell--ctx">
|
: pv !== av;
|
||||||
<span className="bs-cmp-val">{show}</span>
|
|
||||||
</td>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (d.kind === "added") {
|
|
||||||
return (
|
|
||||||
<td key={f} className="bs-cmp-val-cell">
|
|
||||||
<span className="bs-cmp-val bs-cmp-val--post">
|
|
||||||
{av || "—"}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (d.kind === "removed") {
|
|
||||||
return (
|
|
||||||
<td key={f} className="bs-cmp-val-cell">
|
|
||||||
<span className="bs-cmp-val bs-cmp-val--pre">
|
|
||||||
{pv || "—"}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const mismatch = Boolean(ch);
|
|
||||||
if (!mismatch) {
|
|
||||||
return (
|
|
||||||
<td key={f} className="bs-cmp-val-cell">
|
|
||||||
<span className="bs-cmp-val">{pv || av || "—"}</span>
|
|
||||||
</td>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<td key={f} className="bs-cmp-val-cell bs-cmp-val-cell--diff">
|
<PairCell
|
||||||
<span className="bs-cmp-val bs-cmp-val--pre">
|
key={f}
|
||||||
{pv || "—"}
|
beforeText={pv}
|
||||||
</span>
|
afterText={av}
|
||||||
<span className="bs-cmp-val-arrow" aria-hidden>
|
mismatch={mismatch}
|
||||||
→
|
reason={ch?.reason}
|
||||||
</span>
|
beforeLabel={t("bizCompare.pairBefore")}
|
||||||
<span className="bs-cmp-val bs-cmp-val--post">
|
afterLabel={t("bizCompare.pairAfter")}
|
||||||
{av || "—"}
|
/>
|
||||||
</span>
|
|
||||||
{ch?.reason ? (
|
|
||||||
<div className="bs-cmp-val-reason muted">{ch.reason}</div>
|
|
||||||
) : null}
|
|
||||||
</td>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue