feat(operations): add automated reconciliation center

This commit is contained in:
lingniu
2026-07-16 19:14:53 +08:00
parent bbab018d55
commit d67f42b4f4
25 changed files with 1697 additions and 39 deletions

View File

@@ -401,6 +401,18 @@ button, a { -webkit-tap-highlight-color: transparent; }
.v2-ops-links article { display: grid; min-height: 46px; grid-template-columns: 8px minmax(0,1fr) auto; align-items: center; gap: 9px; border-bottom: 1px solid #eef2f7; padding: 7px 13px; }.v2-ops-links article > i, .v2-ops-sources article i { width: 7px; height: 7px; border-radius: 50%; background: #94a3b8; }.v2-ops-links article > i.is-ok, .v2-ops-sources article i.is-ok { background: var(--v2-green); }.v2-ops-links article > i.is-warning, .v2-ops-sources article i.is-warning { background: var(--v2-orange); }.v2-ops-links article > i.is-error, .v2-ops-sources article i.is-error { background: var(--v2-red); }.v2-ops-links article strong { font-size: 9px; }.v2-ops-links article p { margin: 3px 0 0; color: var(--v2-muted); font-size: 8px; }.v2-ops-links article > span { border-radius: 10px; background: #f1f5f9; padding: 3px 7px; color: #64748b; font-size: 8px; }
.v2-ops-runtime dl { margin: 0; padding: 7px 13px; }.v2-ops-runtime dl div { display: flex; min-height: 31px; align-items: center; justify-content: space-between; border-bottom: 1px solid #eef2f7; font-size: 9px; }.v2-ops-runtime dt { color: var(--v2-muted); }.v2-ops-runtime dd { margin: 0; }.v2-ops-clear, .v2-ops-findings { margin: 4px 13px 12px; border-radius: 6px; background: #f1fbf7; padding: 8px; color: #17815d; font-size: 8px; }.v2-ops-findings { background: #fff7ed; color: #b45309; }.v2-ops-findings p { margin: 3px 0; }
.v2-ops-sources > div { display: grid; grid-template-columns: repeat(3,1fr); }.v2-ops-sources article { min-width: 0; padding: 12px 14px; }.v2-ops-sources article + article { border-left: 1px solid var(--v2-border); }.v2-ops-sources article > div { display: flex; align-items: center; gap: 7px; }.v2-ops-sources article strong { font-size: 10px; }.v2-ops-sources article span { margin-left: auto; color: var(--v2-muted); font-size: 8px; }.v2-ops-sources article b { display: block; margin-top: 9px; font-size: 14px; }.v2-ops-sources article p { margin: 6px 0 0; color: #68768a; font-size: 8px; line-height: 1.45; }.v2-ops-sources article em { display: block; margin-top: 7px; color: var(--v2-blue); font-size: 8px; font-style: normal; }.is-ok { color: var(--v2-green) !important; }.is-warning { color: #b87900 !important; }.is-error { color: var(--v2-red) !important; }
.v2-reconcile-center { position: relative; border: 1px solid #cbd8e8; border-radius: 14px; background: #fff; box-shadow: 0 10px 32px rgba(31,53,80,.09); overflow: hidden; }
.v2-reconcile-heading { display: flex; min-height: 68px; align-items: center; justify-content: space-between; gap: 16px; border-bottom: 1px solid #e2e9f2; padding: 12px 16px; background: linear-gradient(105deg,#f7fbff 0%,#f2f7ff 58%,#eef5ff 100%); }.v2-reconcile-heading > div { display: grid; gap: 3px; }.v2-reconcile-heading small { color: #557494; font-size: 11px; }.v2-reconcile-heading strong { color: #17283b; font-size: 18px; }.v2-reconcile-heading span { color: #64758a; font-size: 12px; }.v2-reconcile-heading button { display: inline-flex; height: 36px; flex: 0 0 auto; align-items: center; gap: 6px; border: 1px solid #c5d4e5; border-radius: 8px; background: #fff; padding: 0 13px; color: #355272; cursor: pointer; font-size: 12px; }
.v2-reconcile-kpis { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); border-bottom: 1px solid #e3eaf2; }.v2-reconcile-kpis article { position: relative; min-width: 0; padding: 13px 16px; }.v2-reconcile-kpis article + article::before { position: absolute; inset: 13px auto 13px 0; width: 1px; background: #e4ebf3; content: ''; }.v2-reconcile-kpis small { display: block; color: #748398; font-size: 11px; }.v2-reconcile-kpis strong { display: block; margin: 5px 0 2px; color: #17283b; font-size: 22px; line-height: 1.1; }.v2-reconcile-kpis span { color: #8794a6; font-size: 10px; }.v2-reconcile-kpis article.is-active strong { color: #2464c8; }.v2-reconcile-kpis article.is-overdue strong { color: #c2413d; }
.v2-reconcile-layout { position: relative; display: grid; min-height: 480px; grid-template-columns: minmax(0,1fr) 260px; }.v2-reconcile-main { display: flex; min-width: 0; flex-direction: column; border-right: 1px solid #e3eaf2; }.v2-reconcile-toolbar { display: grid; grid-template-columns: minmax(240px,1fr) repeat(3,minmax(130px,auto)); gap: 8px; border-bottom: 1px solid #e7edf4; padding: 10px 12px; }.v2-reconcile-toolbar select, .v2-reconcile-search { height: 36px; border: 1px solid #d7e0eb; border-radius: 8px; background: #fff; color: #33465c; font-size: 12px; }.v2-reconcile-toolbar select { min-width: 0; padding: 0 10px; }.v2-reconcile-search { display: flex; align-items: center; gap: 8px; padding: 0 11px; }.v2-reconcile-search svg { color: #71849a; }.v2-reconcile-search input { width: 100%; min-width: 0; border: 0; outline: 0; color: #23374e; font: inherit; }
.v2-reconcile-table-wrap { min-height: 360px; flex: 1; overflow: auto; }.v2-reconcile-table { width: 100%; min-width: 920px; border-collapse: collapse; table-layout: fixed; }.v2-reconcile-table th { position: sticky; z-index: 1; top: 0; height: 38px; background: #f7f9fc; padding: 0 11px; color: #718095; font-size: 11px; font-weight: 600; text-align: left; }.v2-reconcile-table th:nth-child(1) { width: 72px; }.v2-reconcile-table th:nth-child(2) { width: 27%; }.v2-reconcile-table th:nth-child(3) { width: 19%; }.v2-reconcile-table th:nth-child(4) { width: 15%; }.v2-reconcile-table th:nth-child(5) { width: 21%; }.v2-reconcile-table th:nth-child(6) { width: 112px; }.v2-reconcile-table tbody tr { cursor: pointer; border-top: 1px solid #edf1f6; outline: none; }.v2-reconcile-table tbody tr:hover, .v2-reconcile-table tbody tr:focus-visible { background: #f7fbff; }.v2-reconcile-table tbody tr.is-selected { background: #eef6ff; box-shadow: inset 3px 0 #3478d4; }.v2-reconcile-table td { height: 62px; padding: 8px 11px; vertical-align: middle; }.v2-reconcile-table td strong { display: block; overflow: hidden; color: #263a50; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }.v2-reconcile-table td span:not(.v2-reconcile-severity):not(.v2-reconcile-status) { display: block; margin-top: 4px; overflow: hidden; color: #8290a2; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
.v2-reconcile-severity, .v2-reconcile-status { display: inline-flex; min-height: 24px; align-items: center; border-radius: 999px; padding: 0 8px; font-size: 10px; font-weight: 600; }.v2-reconcile-severity.is-critical { background: #fff0ef; color: #c53c36; }.v2-reconcile-severity.is-major { background: #fff6e5; color: #a96600; }.v2-reconcile-severity.is-minor { background: #eef4fa; color: #60758d; }.v2-reconcile-status { background: #edf3fb; color: #426485; }.v2-reconcile-status.is-pending { background: #fff4df; color: #a45f00; }.v2-reconcile-status.is-confirmed_source_a, .v2-reconcile-status.is-confirmed_source_b { background: #e9f2ff; color: #2464c8; }.v2-reconcile-status.is-recovered, .v2-reconcile-status.is-fixed { background: #eaf8f2; color: #167759; }
.v2-reconcile-empty { margin: 0; padding: 34px 16px; color: #77879a; font-size: 12px; text-align: center; }.v2-reconcile-pagination { display: flex; min-height: 46px; align-items: center; justify-content: space-between; border-top: 1px solid #e6edf4; padding: 7px 12px; color: #728197; font-size: 11px; }.v2-reconcile-pagination div { display: flex; gap: 6px; }.v2-reconcile-pagination button { height: 30px; border: 1px solid #d5dfeb; border-radius: 7px; background: #fff; padding: 0 11px; color: #405870; cursor: pointer; font-size: 11px; }.v2-reconcile-pagination button:disabled { cursor: not-allowed; opacity: .45; }
.v2-reconcile-trend { padding: 12px; background: #fbfcfe; }.v2-reconcile-trend > header { display: grid; gap: 3px; margin-bottom: 10px; }.v2-reconcile-trend header strong { color: #273b51; font-size: 13px; }.v2-reconcile-trend header span, .v2-reconcile-trend > p { color: #8390a2; font-size: 10px; }.v2-reconcile-trend article { display: grid; min-height: 25px; grid-template-columns: 36px minmax(0,1fr) 28px; align-items: center; gap: 7px; }.v2-reconcile-trend time, .v2-reconcile-trend article b { color: #718197; font-size: 9px; font-weight: 500; }.v2-reconcile-trend article > div { position: relative; height: 12px; border-radius: 3px; background: #edf2f7; overflow: hidden; }.v2-reconcile-trend article i { position: absolute; left: 0; height: 4px; }.v2-reconcile-trend article i.is-active { top: 0; background: #4c7fc4; }.v2-reconcile-trend article i.is-new { top: 4px; background: #e2a237; }.v2-reconcile-trend article i.is-recovered { top: 8px; background: #35a37b; }.v2-reconcile-trend > footer { display: flex; gap: 10px; margin-top: 10px; color: #758398; font-size: 9px; }.v2-reconcile-trend footer span { display: inline-flex; align-items: center; gap: 4px; }.v2-reconcile-trend footer i { width: 7px; height: 7px; border-radius: 2px; }.v2-reconcile-trend footer i.is-active { background: #4c7fc4; }.v2-reconcile-trend footer i.is-new { background: #e2a237; }.v2-reconcile-trend footer i.is-recovered { background: #35a37b; }
.v2-reconcile-detail { position: absolute; z-index: 5; top: 0; right: 0; bottom: 0; width: min(460px,52vw); border-left: 1px solid #c9d7e7; background: #fff; box-shadow: -14px 0 34px rgba(25,48,75,.15); overflow: hidden; }.v2-reconcile-detail > header { display: flex; min-height: 66px; align-items: flex-start; justify-content: space-between; gap: 12px; border-bottom: 1px solid #e3eaf2; padding: 12px 14px; background: #f6f9fd; }.v2-reconcile-detail > header div { display: flex; min-width: 0; flex-wrap: wrap; align-items: center; gap: 5px 8px; }.v2-reconcile-detail > header span { border-radius: 999px; background: #edf2f7; padding: 3px 7px; font-size: 10px; }.v2-reconcile-detail > header span.is-critical { background: #fff0ef; color: #c53c36; }.v2-reconcile-detail > header span.is-major { background: #fff6e5; color: #a96600; }.v2-reconcile-detail > header strong { width: 100%; color: #21364d; font-size: 15px; }.v2-reconcile-detail > header small { color: #738297; font-size: 10px; }.v2-reconcile-detail > header button { border: 0; background: transparent; color: #6f8093; cursor: pointer; font-size: 24px; line-height: 1; }.v2-reconcile-detail-body { height: calc(100% - 66px); padding: 12px 14px 20px; overflow: auto; }.v2-reconcile-identity { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); border: 1px solid #e1e8f0; border-radius: 9px; overflow: hidden; }.v2-reconcile-identity div { min-width: 0; padding: 10px; }.v2-reconcile-identity div + div { border-left: 1px solid #e5ebf2; }.v2-reconcile-identity small, .v2-reconcile-identity span { display: block; color: #8491a2; font-size: 9px; }.v2-reconcile-identity strong { display: block; margin: 4px 0; overflow: hidden; color: #2b3e54; font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }.v2-reconcile-summary { margin: 11px 0; border-radius: 8px; background: #f3f7fb; padding: 10px 12px; color: #4b5e73; font-size: 11px; line-height: 1.55; }
.v2-reconcile-evidence, .v2-reconcile-review, .v2-reconcile-actions { margin-top: 12px; border: 1px solid #e0e7ef; border-radius: 9px; overflow: hidden; }.v2-reconcile-evidence > header, .v2-reconcile-review > header, .v2-reconcile-actions > header { display: flex; min-height: 39px; align-items: center; justify-content: space-between; border-bottom: 1px solid #e5ebf2; padding: 0 11px; background: #fafbfd; }.v2-reconcile-evidence header strong, .v2-reconcile-review header strong, .v2-reconcile-actions header strong { color: #34495f; font-size: 11px; }.v2-reconcile-evidence header span, .v2-reconcile-review header span, .v2-reconcile-actions header span { color: #8794a4; font-size: 9px; }.v2-reconcile-evidence dl { margin: 0; }.v2-reconcile-evidence dl div { display: grid; grid-template-columns: 118px minmax(0,1fr); border-top: 1px solid #eef2f6; }.v2-reconcile-evidence dl div:first-child { border-top: 0; }.v2-reconcile-evidence dt { padding: 9px 10px; background: #fafbfd; color: #708095; font-size: 9px; }.v2-reconcile-evidence dd { min-width: 0; margin: 0; padding: 8px 10px; }.v2-reconcile-evidence pre { margin: 0; overflow: auto; color: #30475f; font: 10px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace; white-space: pre-wrap; word-break: break-word; }
.v2-reconcile-review { padding-bottom: 11px; }.v2-reconcile-review > header { margin-bottom: 9px; }.v2-reconcile-review > label { display: grid; gap: 5px; margin: 8px 11px; color: #66778b; font-size: 10px; }.v2-reconcile-review select, .v2-reconcile-review textarea { border: 1px solid #d5dfeb; border-radius: 7px; background: #fff; padding: 8px 9px; color: #30465d; font: inherit; }.v2-reconcile-review textarea { min-height: 78px; resize: vertical; }.v2-reconcile-review > button { height: 33px; margin: 3px 11px 0; border: 0; border-radius: 7px; background: #316fc3; padding: 0 13px; color: #fff; cursor: pointer; font-size: 11px; }.v2-reconcile-review > button:disabled { cursor: not-allowed; opacity: .5; }.v2-reconcile-review > p { margin: 7px 11px 0; color: #c23c37; font-size: 10px; }
.v2-reconcile-actions > ol { margin: 0; padding: 9px 12px; list-style: none; }.v2-reconcile-actions li { display: grid; grid-template-columns: 10px minmax(0,1fr); gap: 8px; padding: 7px 0; }.v2-reconcile-actions li > i { width: 7px; height: 7px; margin-top: 4px; border-radius: 50%; background: #5d83b5; }.v2-reconcile-actions li strong { color: #354b61; font-size: 10px; }.v2-reconcile-actions li p { margin: 3px 0; color: #627489; font-size: 10px; line-height: 1.4; }.v2-reconcile-actions li span { color: #8b97a7; font-size: 9px; }.v2-reconcile-actions > p { margin: 0; padding: 14px; color: #8290a1; font-size: 10px; }
.v2-source-diagnostic { position: relative; border: 1px solid #cfdbea; border-radius: 12px; background: #fff; box-shadow: 0 8px 28px rgba(31,53,80,.08); overflow: hidden; }.v2-source-diagnostic > header { display: flex; min-height: 58px; align-items: center; justify-content: space-between; border-bottom: 1px solid #e5ebf3; padding: 9px 14px; background: linear-gradient(100deg,#f8fbff,#f4f8ff); }.v2-source-diagnostic > header div { display: grid; gap: 2px; }.v2-source-diagnostic > header small { color: #547297; font-size: 9px; }.v2-source-diagnostic > header strong { font-size: 15px; }.v2-source-diagnostic > header span { color: var(--v2-muted); font-size: 9px; }.v2-source-diagnostic > header button, .v2-source-search > button, .v2-source-policy-cell button { display: inline-flex; height: 32px; align-items: center; justify-content: center; gap: 5px; border: 1px solid #cbd8e8; border-radius: 7px; background: #fff; padding: 0 12px; color: #355272; cursor: pointer; font-size: 10px; }.v2-source-diagnostic button:disabled { cursor: not-allowed; opacity: .5; }
.v2-source-search { position: relative; display: flex; gap: 8px; padding: 12px 14px; }.v2-source-search > label { display: flex; min-width: 280px; flex: 1; height: 36px; align-items: center; gap: 8px; border: 1px solid #cbd8e8; border-radius: 8px; padding: 0 11px; color: #6c7c91; }.v2-source-search input { min-width: 0; flex: 1; border: 0; outline: 0; background: transparent; font: inherit; font-size: 11px; }.v2-source-search > button { height: 36px; border-color: #2f6fe4; background: #2f6fe4; color: #fff; }.v2-source-candidates { position: absolute; z-index: 12; top: 51px; right: 114px; left: 14px; max-height: 310px; overflow: auto; border: 1px solid #d6e0ec; border-radius: 9px; background: #fff; box-shadow: 0 12px 32px rgba(31,53,80,.18); }.v2-source-candidates > button { display: grid; width: 100%; grid-template-columns: 150px minmax(180px,1fr) auto; gap: 10px; border: 0; border-bottom: 1px solid #edf1f6; background: #fff; padding: 10px 12px; text-align: left; cursor: pointer; }.v2-source-candidates > button:hover { background: #f5f9ff; }.v2-source-candidates strong { font-size: 11px; }.v2-source-candidates span, .v2-source-candidates em, .v2-source-candidates p { color: var(--v2-muted); font-size: 9px; font-style: normal; }.v2-source-candidates p { margin: 0; padding: 14px; }.v2-source-candidates footer { position: sticky; bottom: 0; display: flex; align-items: center; justify-content: space-between; border-top: 1px solid #e5ebf3; background: #fff; padding: 7px 10px; }.v2-source-candidates footer div { display: flex; gap: 5px; }.v2-source-candidates footer button { border: 1px solid #d2dce8; border-radius: 5px; background: #fff; padding: 4px 8px; color: #52657d; font-size: 8px; }
.v2-source-empty { display: grid; min-height: 110px; place-content: center; gap: 6px; color: var(--v2-muted); text-align: center; }.v2-source-empty strong { color: #42556e; font-size: 13px; }.v2-source-empty span { font-size: 10px; }.v2-source-summary { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); border-block: 1px solid #e7edf4; background: #fafcff; }.v2-source-summary article { min-width: 0; padding: 11px 14px; }.v2-source-summary article + article { border-left: 1px solid #e7edf4; }.v2-source-summary small, .v2-source-summary span { display: block; overflow: hidden; color: var(--v2-muted); font-size: 9px; text-overflow: ellipsis; white-space: nowrap; }.v2-source-summary strong { display: block; margin: 5px 0; overflow: hidden; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }.v2-source-recommendation { margin: 12px 14px 8px; border-left: 3px solid #2f6fe4; border-radius: 6px; background: #f3f7ff; padding: 9px 11px; }.v2-source-recommendation strong { font-size: 10px; }.v2-source-recommendation p { margin: 4px 0; color: #405774; font-size: 9px; line-height: 1.5; }.v2-source-recommendation span, .v2-source-readonly { color: #728299; font-size: 8px; }.v2-source-readonly { margin: 0 14px 8px; border-radius: 6px; background: #fff8e8; padding: 7px 9px; color: #966500; }
@@ -1135,6 +1147,7 @@ button, a { -webkit-tap-highlight-color: transparent; }
.v2-alert-rules { display: flex; flex-direction: column; }
.v2-alert-rule-list { max-height: 300px; flex: none; }
.v2-ops-kpis { grid-template-columns: repeat(3,1fr); }.v2-ops-grid { grid-template-columns: 1fr; }.v2-ops-sources > div { grid-template-columns: 1fr; }.v2-ops-sources article + article { border-top: 1px solid var(--v2-border); border-left: 0; }
.v2-reconcile-kpis { grid-template-columns: repeat(3,1fr); }.v2-reconcile-layout { grid-template-columns: minmax(0,1fr) 220px; }.v2-reconcile-toolbar { grid-template-columns: minmax(220px,1fr) repeat(2,minmax(120px,auto)); }.v2-reconcile-toolbar select:last-child { grid-column: span 2; }
.v2-source-summary { grid-template-columns: repeat(2,1fr); }.v2-source-summary article:nth-child(3) { border-left: 0; }.v2-source-summary article:nth-child(n+3) { border-top: 1px solid #e7edf4; }
}
@@ -1454,6 +1467,7 @@ button, a { -webkit-tap-highlight-color: transparent; }
.v2-alert-rule-editor > footer { align-items: stretch; flex-direction: column; }
.v2-alert-notifications > footer { flex-direction: column; gap: 5px; }
.v2-ops-page { padding: 8px; }.v2-ops-heading { align-items: flex-start; flex-direction: column; gap: 8px; }.v2-ops-kpis { grid-template-columns: 1fr 1fr; }.v2-ops-kpis article + article::before { display: none; }.v2-ops-kpis article { border-bottom: 1px solid var(--v2-border); }
.v2-reconcile-heading { align-items: flex-start; flex-direction: column; }.v2-reconcile-heading button { width: 100%; justify-content: center; }.v2-reconcile-kpis { grid-template-columns: 1fr 1fr; }.v2-reconcile-kpis article + article::before { display: none; }.v2-reconcile-kpis article { border-bottom: 1px solid #e5ebf2; }.v2-reconcile-layout { display: block; min-height: 520px; }.v2-reconcile-main { border-right: 0; }.v2-reconcile-toolbar { grid-template-columns: 1fr 1fr; }.v2-reconcile-search { grid-column: 1 / -1; }.v2-reconcile-toolbar select:last-child { grid-column: 1 / -1; }.v2-reconcile-trend { border-top: 1px solid #e3eaf2; }.v2-reconcile-detail { position: fixed; inset: 54px 0 0; width: auto; border-left: 0; }.v2-reconcile-identity { grid-template-columns: 1fr; }.v2-reconcile-identity div + div { border-top: 1px solid #e5ebf2; border-left: 0; }.v2-reconcile-evidence dl div { grid-template-columns: 96px minmax(0,1fr); }
.v2-source-diagnostic > header { align-items: flex-start; flex-direction: column; gap: 8px; }.v2-source-diagnostic > header button { width: 100%; }.v2-source-search { flex-direction: column; }.v2-source-search > label { width: auto; min-width: 0; height: 42px; }.v2-source-search > button { width: 100%; }.v2-source-candidates { top: 61px; right: 14px; }.v2-source-candidates > button { grid-template-columns: 1fr; gap: 3px; }.v2-source-summary { grid-template-columns: 1fr; }.v2-source-summary article + article, .v2-source-summary article:nth-child(3) { border-top: 1px solid #e7edf4; border-left: 0; }.v2-source-audit > header { height: auto; align-items: flex-start; flex-direction: column; gap: 3px; padding-block: 7px; }.v2-source-audit li { grid-template-columns: 35px minmax(0,1fr); }.v2-source-audit li em { grid-column: 2; }
.v2-mileage-page { gap: 10px; padding: 12px 8px 18px; }
.v2-mileage-heading { align-items: flex-start; flex-direction: row; gap: 10px; }