Unify compare header dividers and nest Result/Detail under Verdict like other groups.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-21 16:22:50 +08:00
parent dfcdeccaa6
commit bf6e870b72
4 changed files with 97 additions and 160 deletions

View file

@ -506,6 +506,8 @@ const en = {
colMode: "Mode", colMode: "Mode",
colStatus: "Status", colStatus: "Status",
colKind: "Verdict", colKind: "Verdict",
colResult: "Result",
colDetail: "Detail",
colFailFields: "Failed fields", colFailFields: "Failed fields",
colActions: "Actions", colActions: "Actions",
colKey: "Identity", colKey: "Identity",

View file

@ -503,6 +503,8 @@ const zh = {
colMode: "模式", colMode: "模式",
colStatus: "状态", colStatus: "状态",
colKind: "结论", colKind: "结论",
colResult: "结果",
colDetail: "明细",
colFailFields: "失败项", colFailFields: "失败项",
colActions: "操作", colActions: "操作",
colKey: "身份", colKey: "身份",

View file

@ -12214,10 +12214,7 @@ body:has(.bs-cmp-board:fullscreen) {
border-collapse: separate; border-collapse: separate;
border-spacing: 0; border-spacing: 0;
--bs-cmp-group-h: 30px; --bs-cmp-group-h: 30px;
--bs-cmp-zone-line: rgba(148, 163, 184, 0.42); --bs-cmp-line: rgba(148, 163, 184, 0.22);
--bs-cmp-zone-key: #3b82f6;
--bs-cmp-zone-compare: #f59e0b;
--bs-cmp-zone-display: #94a3b8;
} }
.bs-cmp-diff-table thead th { .bs-cmp-diff-table thead th {
@ -12229,6 +12226,8 @@ body:has(.bs-cmp-board:fullscreen) {
white-space: nowrap; white-space: nowrap;
vertical-align: middle; vertical-align: middle;
padding: 7px 10px; padding: 7px 10px;
border-bottom: 1px solid var(--bs-cmp-line);
border-right: 1px solid var(--bs-cmp-line);
} }
.bs-cmp-diff-table thead tr.bs-cmp-group-row th { .bs-cmp-diff-table thead tr.bs-cmp-group-row th {
@ -12237,34 +12236,12 @@ body:has(.bs-cmp-board:fullscreen) {
text-align: center; text-align: center;
font-size: 11px; font-size: 11px;
font-weight: 700; font-weight: 700;
letter-spacing: 0.06em; letter-spacing: 0.04em;
padding: 6px 12px; padding: 6px 12px;
height: var(--bs-cmp-group-h); height: var(--bs-cmp-group-h);
} color: #cbd5e1;
background: rgba(15, 23, 42, 0.98);
/* Merged-cell style group headers */ border-top: 1px solid var(--bs-cmp-line);
.bs-cmp-group {
border-top: 1px solid var(--bs-cmp-zone-line) !important;
border-bottom: 1px solid var(--bs-cmp-zone-line) !important;
border-right: 1px solid var(--bs-cmp-zone-line) !important;
}
.bs-cmp-group--key {
background: rgba(37, 99, 235, 0.16) !important;
color: #93c5fd !important;
border-left: 2px solid var(--bs-cmp-zone-key) !important;
}
.bs-cmp-group--compare {
background: rgba(245, 158, 11, 0.12) !important;
color: #fbbf24 !important;
border-left: 2px solid var(--bs-cmp-zone-compare) !important;
}
.bs-cmp-group--display {
background: rgba(148, 163, 184, 0.1) !important;
color: #e2e8f0 !important;
border-left: 2px solid var(--bs-cmp-zone-display) !important;
} }
.bs-cmp-diff-table thead tr.bs-cmp-field-row th { .bs-cmp-diff-table thead tr.bs-cmp-field-row th {
@ -12273,40 +12250,13 @@ body:has(.bs-cmp-board:fullscreen) {
vertical-align: middle; vertical-align: middle;
padding-top: 6px; padding-top: 6px;
padding-bottom: 7px; padding-bottom: 7px;
border-bottom: 1px solid var(--bs-cmp-zone-line);
background: rgba(15, 23, 42, 0.98); background: rgba(15, 23, 42, 0.98);
color: #e2e8f0; color: #e2e8f0;
} }
.bs-cmp-diff-table thead tr.bs-cmp-field-row th.bs-cmp-col-key { .bs-cmp-diff-table thead th.bs-cmp-zone-start,
background: rgba(30, 41, 70, 0.92); .bs-cmp-diff-table tbody td.bs-cmp-zone-start {
} border-left: 1px solid var(--bs-cmp-line);
.bs-cmp-diff-table thead tr.bs-cmp-field-row th.bs-cmp-col-compare {
background: rgba(42, 34, 18, 0.92);
}
.bs-cmp-diff-table thead tr.bs-cmp-field-row th.bs-cmp-col-display {
background: rgba(30, 36, 48, 0.95);
}
.bs-cmp-diff-table thead th.bs-cmp-zone-start.bs-cmp-col-key,
.bs-cmp-diff-table tbody td.bs-cmp-zone-start--key {
border-left: 2px solid var(--bs-cmp-zone-key);
}
.bs-cmp-diff-table thead th.bs-cmp-zone-start.bs-cmp-col-compare,
.bs-cmp-diff-table tbody td.bs-cmp-zone-start--compare {
border-left: 2px solid var(--bs-cmp-zone-compare);
}
.bs-cmp-diff-table thead th.bs-cmp-zone-start.bs-cmp-col-display,
.bs-cmp-diff-table tbody td.bs-cmp-zone-start--display {
border-left: 2px solid var(--bs-cmp-zone-display);
}
.bs-cmp-diff-table thead th.bs-cmp-zone-end {
border-right: 1px solid var(--bs-cmp-zone-line);
} }
.bs-cmp-diff-table tbody td { .bs-cmp-diff-table tbody td {
@ -12322,33 +12272,24 @@ body:has(.bs-cmp-board:fullscreen) {
background: rgba(37, 99, 235, 0.1); background: rgba(37, 99, 235, 0.1);
} }
/* 结论 column */ /* 结果 column sticky */
.bs-cmp-sticky-kind { .bs-cmp-sticky-kind {
position: sticky; position: sticky;
left: 0; left: 0;
z-index: 1; z-index: 1;
background: rgba(15, 23, 42, 0.96); background: rgba(15, 23, 42, 0.96);
border-right: 1px solid var(--bs-cmp-zone-line, rgba(148, 163, 184, 0.42));
} }
.bs-cmp-diff-table thead th.bs-cmp-sticky-kind { .bs-cmp-diff-table thead th.bs-cmp-sticky-kind {
z-index: 4; z-index: 4;
background: rgba(15, 23, 42, 0.98); background: rgba(15, 23, 42, 0.98);
vertical-align: middle;
text-align: center; text-align: center;
font-weight: 700; box-shadow: 1px 0 0 var(--bs-cmp-line);
color: #cbd5e1;
letter-spacing: 0.04em;
border-bottom: 1px solid var(--bs-cmp-zone-line);
box-shadow: 1px 0 0 rgba(148, 163, 184, 0.16);
} }
.bs-cmp-diff-table thead th.bs-cmp-col-fail { .bs-cmp-diff-table thead th.bs-cmp-col-fail {
z-index: 3; z-index: 3;
text-align: center; text-align: center;
vertical-align: middle;
border-right: 1px solid var(--bs-cmp-zone-line);
border-bottom: 1px solid var(--bs-cmp-zone-line);
} }
.bs-cmp-diff-table tbody tr:nth-child(even) td.bs-cmp-sticky-kind { .bs-cmp-diff-table tbody tr:nth-child(even) td.bs-cmp-sticky-kind {

View file

@ -167,7 +167,6 @@ function PairCell(props: {
beforeLabel: string; beforeLabel: string;
afterLabel: string; afterLabel: string;
zoneStart?: boolean; zoneStart?: boolean;
zoneKind?: "compare" | "display";
}) { }) {
const { const {
beforeText, beforeText,
@ -178,7 +177,6 @@ function PairCell(props: {
beforeLabel, beforeLabel,
afterLabel, afterLabel,
zoneStart = false, zoneStart = false,
zoneKind = "compare",
} = props; } = props;
const pre = beforeText || "—"; const pre = beforeText || "—";
const post = afterText || "—"; const post = afterText || "—";
@ -206,7 +204,7 @@ function PairCell(props: {
className={`bs-cmp-val-cell bs-cmp-val-cell--pair${ className={`bs-cmp-val-cell bs-cmp-val-cell--pair${
mismatch || isAdded || isRemoved ? " bs-cmp-val-cell--diff" : "" mismatch || isAdded || isRemoved ? " bs-cmp-val-cell--diff" : ""
}${isAdded ? " is-added" : ""}${isRemoved ? " is-removed" : ""}${ }${isAdded ? " is-added" : ""}${isRemoved ? " is-removed" : ""}${
zoneStart ? ` bs-cmp-zone-start bs-cmp-zone-start--${zoneKind}` : "" zoneStart ? " bs-cmp-zone-start" : ""
}`} }`}
> >
<div className="bs-cmp-pair"> <div className="bs-cmp-pair">
@ -3084,98 +3082,93 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
const displayCols = resultColumns.extras.filter( const displayCols = resultColumns.extras.filter(
(f) => !resultColumns.compareSet.has(f), (f) => !resultColumns.compareSet.has(f),
); );
const verdictColSpan = showFailCol ? 2 : 1;
const hasGroups = const hasGroups =
keyCols.length + compareCols.length + displayCols.length > 0; keyCols.length + compareCols.length + displayCols.length > 0;
return ( return (
<> <>
{hasGroups ? ( <tr className="bs-cmp-group-row">
<tr className="bs-cmp-group-row"> <th
colSpan={verdictColSpan}
className="bs-cmp-group bs-cmp-group--verdict"
>
{t("bizCompare.colKind")}
</th>
{keyCols.length ? (
<th <th
rowSpan={2} colSpan={keyCols.length}
className="bs-cmp-col-kind bs-cmp-sticky-kind" className="bs-cmp-group bs-cmp-group--key"
> >
{t("bizCompare.colKind")} {t("bizCompare.keyFields")}
</th> </th>
{showFailCol ? ( ) : null}
<th rowSpan={2} className="bs-cmp-col-fail"> {compareCols.length ? (
{t("bizCompare.colFailFields")} <th
</th> colSpan={compareCols.length}
) : null} className="bs-cmp-group bs-cmp-group--compare"
{keyCols.length ? ( >
<th {t("bizCompare.compareFields")}
colSpan={keyCols.length}
className="bs-cmp-group bs-cmp-group--key"
>
{t("bizCompare.keyFields")}
</th>
) : null}
{compareCols.length ? (
<th
colSpan={compareCols.length}
className="bs-cmp-group bs-cmp-group--compare"
>
{t("bizCompare.compareFields")}
</th>
) : null}
{displayCols.length ? (
<th
colSpan={displayCols.length}
className="bs-cmp-group bs-cmp-group--display"
>
{t("bizCompare.displayField")}
</th>
) : null}
</tr>
) : (
<tr>
<th className="bs-cmp-col-kind bs-cmp-sticky-kind">
{t("bizCompare.colKind")}
</th> </th>
{showFailCol ? ( ) : null}
<th className="bs-cmp-col-fail"> {displayCols.length ? (
{t("bizCompare.colFailFields")} <th
</th> colSpan={displayCols.length}
) : null} className="bs-cmp-group bs-cmp-group--display"
</tr> >
)} {t("bizCompare.displayField")}
{hasGroups ? ( </th>
<tr className="bs-cmp-field-row"> ) : null}
{keyCols.map((k, ki) => ( </tr>
<th <tr className="bs-cmp-field-row">
key={k} <th className="bs-cmp-col-kind bs-cmp-sticky-kind bs-cmp-zone-start">
className={`bs-cmp-col-key${ <span className="bs-cmp-th__name">
ki === 0 ? " bs-cmp-zone-start" : "" {t("bizCompare.colResult")}
}${ki === keyCols.length - 1 ? " bs-cmp-zone-end" : ""}`} </span>
> </th>
<span className="bs-cmp-th__name">{k}</span> {showFailCol ? (
</th> <th className="bs-cmp-col-fail">
))} <span className="bs-cmp-th__name">
{compareCols.map((f, fi) => ( {t("bizCompare.colDetail")}
<th </span>
key={f} </th>
className={`bs-cmp-col-compare${ ) : null}
fi === 0 ? " bs-cmp-zone-start" : "" {hasGroups
}${ ? keyCols.map((k, ki) => (
fi === compareCols.length - 1 ? " bs-cmp-zone-end" : "" <th
}`} key={k}
> className={`bs-cmp-col-key${
<span className="bs-cmp-th__name">{f}</span> ki === 0 ? " bs-cmp-zone-start" : ""
</th> }`}
))} >
{displayCols.map((f, fi) => ( <span className="bs-cmp-th__name">{k}</span>
<th </th>
key={f} ))
className={`bs-cmp-col-display${ : null}
fi === 0 ? " bs-cmp-zone-start" : "" {hasGroups
}${ ? compareCols.map((f, fi) => (
fi === displayCols.length - 1 ? " bs-cmp-zone-end" : "" <th
}`} key={f}
> className={`bs-cmp-col-compare${
<span className="bs-cmp-th__name">{f}</span> fi === 0 ? " bs-cmp-zone-start" : ""
</th> }`}
))} >
</tr> <span className="bs-cmp-th__name">{f}</span>
) : null} </th>
))
: null}
{hasGroups
? displayCols.map((f, fi) => (
<th
key={f}
className={`bs-cmp-col-display${
fi === 0 ? " bs-cmp-zone-start" : ""
}`}
>
<span className="bs-cmp-th__name">{f}</span>
</th>
))
: null}
</tr>
</> </>
); );
})()} })()}
@ -3214,7 +3207,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
<td <td
key={k} key={k}
className={`bs-cmp-key-cell${ className={`bs-cmp-key-cell${
ki === 0 ? " bs-cmp-zone-start bs-cmp-zone-start--key" : "" ki === 0 ? " bs-cmp-zone-start" : ""
}`} }`}
> >
{cellText(d.key?.[k] ?? pre[k] ?? post[k]) || "—"} {cellText(d.key?.[k] ?? pre[k] ?? post[k]) || "—"}
@ -3247,7 +3240,6 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
beforeLabel={t("bizCompare.pairBefore")} beforeLabel={t("bizCompare.pairBefore")}
afterLabel={t("bizCompare.pairAfter")} afterLabel={t("bizCompare.pairAfter")}
zoneStart={zoneStart} zoneStart={zoneStart}
zoneKind={isCmp ? "compare" : "display"}
/> />
); );
})} })}