refine Semi UI operations workspace
This commit is contained in:
@@ -63,6 +63,7 @@ test('renders reconciliation queue, loads evidence on demand and records review
|
|||||||
expect(screen.getByLabelText('运维质量操作')).toHaveClass('v2-workspace-command-bar', 'v2-ops-command-bar');
|
expect(screen.getByLabelText('运维质量操作')).toHaveClass('v2-workspace-command-bar', 'v2-ops-command-bar');
|
||||||
expect(screen.getByRole('tab', { name: '差异处置', selected: true })).toHaveClass('semi-button');
|
expect(screen.getByRole('tab', { name: '差异处置', selected: true })).toHaveClass('semi-button');
|
||||||
expect(screen.getByRole('tabpanel', { name: '差异处置' })).toBeInTheDocument();
|
expect(screen.getByRole('tabpanel', { name: '差异处置' })).toBeInTheDocument();
|
||||||
|
expect(document.querySelector('.v2-ops-page')).toHaveClass('is-reconciliation');
|
||||||
expect(screen.queryByText('先选择一辆车')).not.toBeInTheDocument();
|
expect(screen.queryByText('先选择一辆车')).not.toBeInTheDocument();
|
||||||
expect(screen.getByText('数据差异中心').closest('.semi-card')).toHaveClass('v2-reconcile-center');
|
expect(screen.getByText('数据差异中心').closest('.semi-card')).toHaveClass('v2-reconcile-center');
|
||||||
expect(screen.getByText('数据差异中心').closest('.v2-workspace-panel-header')).toHaveClass('v2-reconcile-heading');
|
expect(screen.getByText('数据差异中心').closest('.v2-workspace-panel-header')).toHaveClass('v2-reconcile-heading');
|
||||||
@@ -118,6 +119,7 @@ test('renders only the compact mobile reconciliation surface and defers secondar
|
|||||||
|
|
||||||
expect(await screen.findByText('多来源实时位置漂移')).toBeInTheDocument();
|
expect(await screen.findByText('多来源实时位置漂移')).toBeInTheDocument();
|
||||||
expect(document.querySelector('.v2-reconcile-mobile-card.semi-card')).toBeInTheDocument();
|
expect(document.querySelector('.v2-reconcile-mobile-card.semi-card')).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('region', { name: '差异队列,可上下滚动' })).toHaveAttribute('tabindex', '0');
|
||||||
expect(document.querySelector('.v2-reconcile-table.semi-table-wrapper')).not.toBeInTheDocument();
|
expect(document.querySelector('.v2-reconcile-table.semi-table-wrapper')).not.toBeInTheDocument();
|
||||||
expect(mocks.reconciliationIssues).toHaveBeenCalledWith(expect.objectContaining({ limit: 20 }), expect.any(AbortSignal));
|
expect(mocks.reconciliationIssues).toHaveBeenCalledWith(expect.objectContaining({ limit: 20 }), expect.any(AbortSignal));
|
||||||
const mobileIssueAction = screen.getByRole('button', { name: '查看 粤A00001 差异证据' });
|
const mobileIssueAction = screen.getByRole('button', { name: '查看 粤A00001 差异证据' });
|
||||||
@@ -137,6 +139,7 @@ test('renders only the compact mobile reconciliation surface and defers secondar
|
|||||||
|
|
||||||
expect(screen.queryByText('近 30 天趋势')).not.toBeInTheDocument();
|
expect(screen.queryByText('近 30 天趋势')).not.toBeInTheDocument();
|
||||||
fireEvent.click(screen.getByRole('button', { name: '30 天趋势' }));
|
fireEvent.click(screen.getByRole('button', { name: '30 天趋势' }));
|
||||||
|
expect(await screen.findByRole('dialog', { name: '30 天差异趋势' })).toBeInTheDocument();
|
||||||
const trend = screen.getByText('近 30 天趋势').closest('.v2-reconcile-trend');
|
const trend = screen.getByText('近 30 天趋势').closest('.v2-reconcile-trend');
|
||||||
expect(trend).toBeInTheDocument();
|
expect(trend).toBeInTheDocument();
|
||||||
expect(screen.getByText(/最近运行/)).toBeInTheDocument();
|
expect(screen.getByText(/最近运行/)).toBeInTheDocument();
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ export default function OperationsPage() {
|
|||||||
const capacityIssueCount = data?.capacityFindings.length ?? 0;
|
const capacityIssueCount = data?.capacityFindings.length ?? 0;
|
||||||
const healthIssueCount = linkIssueCount + runtimeIssueCount + capacityIssueCount + Number((data?.kafkaLag ?? 0) > 0);
|
const healthIssueCount = linkIssueCount + runtimeIssueCount + capacityIssueCount + Number((data?.kafkaLag ?? 0) > 0);
|
||||||
const overallStatus = !data ? 'unknown' : healthIssueCount > 0 ? 'warning' : 'ok';
|
const overallStatus = !data ? 'unknown' : healthIssueCount > 0 ? 'warning' : 'ok';
|
||||||
return <div className="v2-ops-page">
|
return <div className={`v2-ops-page is-${workspace}`}>
|
||||||
<WorkspaceCommandBar
|
<WorkspaceCommandBar
|
||||||
className="v2-ops-command-bar"
|
className="v2-ops-command-bar"
|
||||||
ariaLabel="运维质量操作"
|
ariaLabel="运维质量操作"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Button, Card, Empty, Input, RadioGroup, Select, SideSheet, Spin, Table,
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useDeferredValue, useEffect, useMemo, useState } from 'react';
|
import { useDeferredValue, useEffect, useMemo, useState } from 'react';
|
||||||
import { api } from '../../api/client';
|
import { api } from '../../api/client';
|
||||||
import type { ReconciliationIssue } from '../../api/types';
|
import type { ReconciliationIssue, ReconciliationSummary } from '../../api/types';
|
||||||
import { InlineError } from '../shared/AsyncState';
|
import { InlineError } from '../shared/AsyncState';
|
||||||
import { MobileFilterToggle } from '../shared/MobileFilterToggle';
|
import { MobileFilterToggle } from '../shared/MobileFilterToggle';
|
||||||
import { TablePagination } from '../shared/TablePagination';
|
import { TablePagination } from '../shared/TablePagination';
|
||||||
@@ -77,6 +77,34 @@ function evidenceValue(value: unknown) {
|
|||||||
return JSON.stringify(value, null, 2);
|
return JSON.stringify(value, null, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ReconciliationTrend({ data, maxTrend, onClose }: {
|
||||||
|
data?: ReconciliationSummary;
|
||||||
|
maxTrend: number;
|
||||||
|
onClose: () => void;
|
||||||
|
}) {
|
||||||
|
return <Card className="v2-reconcile-trend" bodyStyle={{ padding: 0 }}>
|
||||||
|
<WorkspacePanelHeader
|
||||||
|
variant="compact"
|
||||||
|
title="近 30 天趋势"
|
||||||
|
meta={`最近运行 ${fmt(data?.lastRunAt)}`}
|
||||||
|
actions={<Button
|
||||||
|
className="v2-reconcile-trend-toggle"
|
||||||
|
theme="borderless"
|
||||||
|
type="tertiary"
|
||||||
|
size="small"
|
||||||
|
icon={<IconChevronUp />}
|
||||||
|
aria-label="收起趋势"
|
||||||
|
aria-expanded
|
||||||
|
aria-controls="v2-reconcile-trend"
|
||||||
|
onClick={onClose}
|
||||||
|
>收起</Button>}
|
||||||
|
/>
|
||||||
|
<div>{data?.trend.slice(-14).map((item) => <article key={item.date}><time>{item.date.slice(5)}</time><div title={`存量 ${item.active},新增 ${item.new},恢复 ${item.recovered}`}><i className="is-active" style={{ width: `${Math.max(2, item.active / maxTrend * 100)}%` }} /><i className="is-new" style={{ width: `${Math.max(0, item.new / maxTrend * 100)}%` }} /><i className="is-recovered" style={{ width: `${Math.max(0, item.recovered / maxTrend * 100)}%` }} /></div><b>{item.active}</b></article>)}</div>
|
||||||
|
{!data?.trend.length ? <p>完成首次每日检测后显示趋势。</p> : null}
|
||||||
|
<footer><span><i className="is-active" />存量</span><span><i className="is-new" />新增</span><span><i className="is-recovered" />恢复</span></footer>
|
||||||
|
</Card>;
|
||||||
|
}
|
||||||
|
|
||||||
function ReconciliationDetail({ issue, onClose, sheet = false }: { issue: ReconciliationIssue; onClose: () => void; sheet?: boolean }) {
|
function ReconciliationDetail({ issue, onClose, sheet = false }: { issue: ReconciliationIssue; onClose: () => void; sheet?: boolean }) {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [status, setStatus] = useState(issue.status === 'recovered' ? 'pending' : issue.status);
|
const [status, setStatus] = useState(issue.status === 'recovered' ? 'pending' : issue.status);
|
||||||
@@ -148,6 +176,7 @@ export default function ReconciliationCenter() {
|
|||||||
const [trendExpanded, setTrendExpanded] = useState(false);
|
const [trendExpanded, setTrendExpanded] = useState(false);
|
||||||
const closeDetail = () => setSelectedID('');
|
const closeDetail = () => setSelectedID('');
|
||||||
useSideSheetA11y(mobileLayout && Boolean(selectedID), '.v2-reconcile-detail-sidesheet', 'v2-reconcile-detail-sheet', '差异证据与处置', '关闭差异详情');
|
useSideSheetA11y(mobileLayout && Boolean(selectedID), '.v2-reconcile-detail-sidesheet', 'v2-reconcile-detail-sheet', '差异证据与处置', '关闭差异详情');
|
||||||
|
useSideSheetA11y(mobileLayout && trendExpanded, '.v2-reconcile-trend-sidesheet', 'v2-reconcile-trend-sheet', '30 天差异趋势', '关闭 30 天差异趋势');
|
||||||
useEffect(() => setOffset(0), [deferredKeyword, mobileLayout, ruleCode, severity, status]);
|
useEffect(() => setOffset(0), [deferredKeyword, mobileLayout, ruleCode, severity, status]);
|
||||||
|
|
||||||
const summary = useQuery({
|
const summary = useQuery({
|
||||||
@@ -266,7 +295,12 @@ export default function ReconciliationCenter() {
|
|||||||
]} />
|
]} />
|
||||||
</div>
|
</div>
|
||||||
{issues.isError ? <InlineError message={issues.error.message} onRetry={() => issues.refetch()} /> : null}
|
{issues.isError ? <InlineError message={issues.error.message} onRetry={() => issues.refetch()} /> : null}
|
||||||
<div className="v2-reconcile-table-wrap">
|
<div
|
||||||
|
className="v2-reconcile-table-wrap is-scroll-region"
|
||||||
|
role="region"
|
||||||
|
aria-label="差异队列,可上下滚动"
|
||||||
|
tabIndex={0}
|
||||||
|
>
|
||||||
{!mobileLayout ? <Table className="v2-reconcile-table" columns={columns} dataSource={issueRows} rowKey="id" pagination={false} scroll={{ x: 934 }} onRow={(item) => item ? detailTriggerRow({
|
{!mobileLayout ? <Table className="v2-reconcile-table" columns={columns} dataSource={issueRows} rowKey="id" pagination={false} scroll={{ x: 934 }} onRow={(item) => item ? detailTriggerRow({
|
||||||
className: selectedID === item.id ? 'is-selected' : '',
|
className: selectedID === item.id ? 'is-selected' : '',
|
||||||
expanded: selectedID === item.id,
|
expanded: selectedID === item.id,
|
||||||
@@ -275,7 +309,12 @@ export default function ReconciliationCenter() {
|
|||||||
onOpen: () => setSelectedID(item.id)
|
onOpen: () => setSelectedID(item.id)
|
||||||
}) : ({})} /> : <div className="v2-reconcile-mobile-list">{issueRows.map((item) => <Card key={item.id} className={`v2-reconcile-mobile-card${selectedID === item.id ? ' is-selected' : ''}`} bodyStyle={{ padding: 0 }}>
|
}) : ({})} /> : <div className="v2-reconcile-mobile-list">{issueRows.map((item) => <Card key={item.id} className={`v2-reconcile-mobile-card${selectedID === item.id ? ' is-selected' : ''}`} bodyStyle={{ padding: 0 }}>
|
||||||
<Button theme="borderless" type="tertiary" className="v2-reconcile-mobile-action" aria-pressed={selectedID === item.id} aria-expanded={selectedID === item.id} aria-label={`查看 ${item.plate || item.title} 差异证据`} onClick={() => setSelectedID(item.id)}>
|
<Button theme="borderless" type="tertiary" className="v2-reconcile-mobile-action" aria-pressed={selectedID === item.id} aria-expanded={selectedID === item.id} aria-label={`查看 ${item.plate || item.title} 差异证据`} onClick={() => setSelectedID(item.id)}>
|
||||||
<span className="v2-reconcile-mobile-content"><header><span><ReconciliationSeverityTag severity={item.severity} /><ReconciliationStatusTag status={item.status} /></span><small>{fmt(item.lastSeenAt)}</small></header><strong>{item.title}</strong><p>{ruleLabel(item.ruleCode)} · 命中 {item.occurrenceCount.toLocaleString('zh-CN')} 次</p><dl><div><dt>车辆</dt><dd>{item.plate || '非单车差异'}</dd></div><div><dt>来源</dt><dd>{[item.protocolA, item.protocolB].filter(Boolean).join(' / ') || '平台口径'}</dd></div></dl><footer>查看证据与处置<IconChevronRight /></footer></span>
|
<span className="v2-reconcile-mobile-content">
|
||||||
|
<header><strong>{item.plate || '平台级差异'}</strong><span><ReconciliationSeverityTag severity={item.severity} /><ReconciliationStatusTag status={item.status} /></span></header>
|
||||||
|
<p>{item.title}</p>
|
||||||
|
<span className="v2-reconcile-mobile-meta"><span>{[item.protocolA, item.protocolB].filter(Boolean).join(' / ') || '平台口径'}</span><time>{fmt(item.lastSeenAt)}</time></span>
|
||||||
|
<footer><span>{ruleLabel(item.ruleCode)} · 命中 {item.occurrenceCount.toLocaleString('zh-CN')} 次</span><span>证据与处置<IconChevronRight /></span></footer>
|
||||||
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Card>)}</div>}
|
</Card>)}</div>}
|
||||||
{issues.isPending ? <div className="v2-reconcile-loading" role="status"><Spin size="middle" tip="正在读取差异队列…" /></div> : null}
|
{issues.isPending ? <div className="v2-reconcile-loading" role="status"><Spin size="middle" tip="正在读取差异队列…" /></div> : null}
|
||||||
@@ -283,27 +322,7 @@ export default function ReconciliationCenter() {
|
|||||||
</div>
|
</div>
|
||||||
<footer className="v2-reconcile-pagination"><TablePagination page={currentPage} totalPages={totalPages} info={`共 ${(page?.total ?? 0).toLocaleString('zh-CN')} 条 · 本页 ${activeCount} 条活跃`} onPageChange={(next) => setOffset((next - 1) * pageSize)} /></footer>
|
<footer className="v2-reconcile-pagination"><TablePagination page={currentPage} totalPages={totalPages} info={`共 ${(page?.total ?? 0).toLocaleString('zh-CN')} 条 · 本页 ${activeCount} 条活跃`} onPageChange={(next) => setOffset((next - 1) * pageSize)} /></footer>
|
||||||
</div>
|
</div>
|
||||||
{trendExpanded ? <div id="v2-reconcile-trend" className="v2-reconcile-trend-slot"><Card className="v2-reconcile-trend" bodyStyle={{ padding: 0 }}>
|
{trendExpanded && !mobileLayout ? <div id="v2-reconcile-trend" className="v2-reconcile-trend-slot"><ReconciliationTrend data={data} maxTrend={maxTrend} onClose={() => setTrendExpanded(false)} /></div> : null}
|
||||||
<WorkspacePanelHeader
|
|
||||||
variant="compact"
|
|
||||||
title="近 30 天趋势"
|
|
||||||
meta={`最近运行 ${fmt(data?.lastRunAt)}`}
|
|
||||||
actions={<Button
|
|
||||||
className="v2-reconcile-trend-toggle"
|
|
||||||
theme="borderless"
|
|
||||||
type="tertiary"
|
|
||||||
size="small"
|
|
||||||
icon={<IconChevronUp />}
|
|
||||||
aria-label="收起趋势"
|
|
||||||
aria-expanded
|
|
||||||
aria-controls="v2-reconcile-trend"
|
|
||||||
onClick={() => setTrendExpanded(false)}
|
|
||||||
>收起</Button>}
|
|
||||||
/>
|
|
||||||
<><div>{data?.trend.slice(-14).map((item) => <article key={item.date}><time>{item.date.slice(5)}</time><div title={`存量 ${item.active},新增 ${item.new},恢复 ${item.recovered}`}><i className="is-active" style={{ width: `${Math.max(2, item.active / maxTrend * 100)}%` }} /><i className="is-new" style={{ width: `${Math.max(0, item.new / maxTrend * 100)}%` }} /><i className="is-recovered" style={{ width: `${Math.max(0, item.recovered / maxTrend * 100)}%` }} /></div><b>{item.active}</b></article>)}</div>
|
|
||||||
{!data?.trend.length ? <p>完成首次每日检测后显示趋势。</p> : null}
|
|
||||||
<footer><span><i className="is-active" />存量</span><span><i className="is-new" />新增</span><span><i className="is-recovered" />恢复</span></footer></>
|
|
||||||
</Card></div> : null}
|
|
||||||
{!mobileLayout ? detailPanel : null}
|
{!mobileLayout ? detailPanel : null}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -317,5 +336,16 @@ export default function ReconciliationCenter() {
|
|||||||
>
|
>
|
||||||
{mobileLayout ? detailPanel : null}
|
{mobileLayout ? detailPanel : null}
|
||||||
</SideSheet>
|
</SideSheet>
|
||||||
|
<SideSheet
|
||||||
|
className="v2-reconcile-trend-sidesheet"
|
||||||
|
visible={mobileLayout && trendExpanded}
|
||||||
|
width="100%"
|
||||||
|
aria-label="30 天差异趋势"
|
||||||
|
title="30 天差异趋势"
|
||||||
|
footer={null}
|
||||||
|
onCancel={() => setTrendExpanded(false)}
|
||||||
|
>
|
||||||
|
{mobileLayout && trendExpanded ? <div id="v2-reconcile-trend"><ReconciliationTrend data={data} maxTrend={maxTrend} onClose={() => setTrendExpanded(false)} /></div> : null}
|
||||||
|
</SideSheet>
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7824,3 +7824,389 @@
|
|||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Semi UI operations queue: one fixed workbench with an independently scrolling evidence list. */
|
||||||
|
.v2-ops-workspace.is-reconciliation {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-workspace.is-reconciliation > .v2-reconcile-center.semi-card {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-center > .semi-card-body {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-heading,
|
||||||
|
.v2-reconcile-overview,
|
||||||
|
.v2-reconcile-pagination {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-layout,
|
||||||
|
.v2-reconcile-layout.is-trend-open {
|
||||||
|
height: auto !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
flex: 1 1 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-main {
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-table-wrap.is-scroll-region {
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1 1 0;
|
||||||
|
overflow: auto;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
scrollbar-gutter: stable;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-table-wrap.is-scroll-region:focus-visible {
|
||||||
|
outline: 2px solid rgba(18, 104, 243, .34);
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-pagination {
|
||||||
|
min-height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-trend-sidesheet .semi-sidesheet-body {
|
||||||
|
overflow: auto;
|
||||||
|
background: #f6f8fb;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-trend-sidesheet .v2-reconcile-trend.semi-card {
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #dce5ef;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 8px 26px rgba(31, 53, 80, .07);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
.v2-ops-page.is-reconciliation {
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-page.is-reconciliation > .v2-ops-command-bar,
|
||||||
|
.v2-ops-page.is-reconciliation > .v2-ops-tabs {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-page.is-reconciliation > .v2-ops-workspace.is-reconciliation {
|
||||||
|
display: block;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1 1 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-heading.v2-workspace-panel-header {
|
||||||
|
min-height: 54px;
|
||||||
|
padding: 7px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-heading > .v2-workspace-panel-actions {
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-heading > .v2-workspace-panel-actions > .semi-button {
|
||||||
|
min-height: 38px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview {
|
||||||
|
height: 68px;
|
||||||
|
grid-template-columns: minmax(0, 4fr) minmax(66px, 1fr);
|
||||||
|
gap: 0;
|
||||||
|
border-bottom: 1px solid #e3eaf2;
|
||||||
|
background: #fff;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview > .v2-reconcile-kpis {
|
||||||
|
height: 67px;
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
gap: 0;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview .v2-reconcile-kpi-card.semi-card {
|
||||||
|
height: 67px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview .v2-reconcile-kpi-card + .v2-reconcile-kpi-card {
|
||||||
|
border-left: 1px solid #e6ebf2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview .v2-reconcile-kpi-card > .semi-card-body {
|
||||||
|
display: grid;
|
||||||
|
height: 67px;
|
||||||
|
min-height: 0;
|
||||||
|
align-content: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 6px 4px !important;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview .v2-reconcile-kpi-card.is-active {
|
||||||
|
background: #f2f7ff;
|
||||||
|
box-shadow: inset 0 -3px #1f6feb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview .v2-reconcile-kpi-card small {
|
||||||
|
overflow: hidden;
|
||||||
|
color: #75849a;
|
||||||
|
font-size: 8px;
|
||||||
|
font-weight: 650;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview .v2-reconcile-kpi-card strong {
|
||||||
|
margin: 0;
|
||||||
|
color: #263b52;
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-overview .v2-reconcile-kpi-card span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-sla.semi-card {
|
||||||
|
height: 67px;
|
||||||
|
border: 0;
|
||||||
|
border-left: 1px solid #e6ebf2;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-sla > .semi-card-body {
|
||||||
|
display: grid;
|
||||||
|
height: 67px;
|
||||||
|
min-height: 0;
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
align-content: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 6px 4px !important;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-sla span {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-sla span small,
|
||||||
|
.v2-reconcile-sla p {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-sla .semi-tag {
|
||||||
|
min-height: 20px;
|
||||||
|
padding-inline: 6px;
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-sla strong {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 2;
|
||||||
|
justify-self: center;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-layout,
|
||||||
|
.v2-reconcile-layout.is-trend-open {
|
||||||
|
display: flex;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1 1 0;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-main {
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1 1 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-main > .v2-mobile-filter-toggle {
|
||||||
|
width: calc(100% - 12px);
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-toolbar {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-table-wrap.is-scroll-region {
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1 1 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: auto;
|
||||||
|
touch-action: pan-y;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-table-wrap.is-scroll-region::-webkit-scrollbar {
|
||||||
|
width: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-table-wrap.is-scroll-region::-webkit-scrollbar-thumb {
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #9cacc0;
|
||||||
|
background-clip: padding-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-list {
|
||||||
|
gap: 6px;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-card.semi-card {
|
||||||
|
border-radius: 9px;
|
||||||
|
contain-intrinsic-size: auto 118px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-action.semi-button {
|
||||||
|
min-height: 116px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content {
|
||||||
|
gap: 5px;
|
||||||
|
padding: 8px 9px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content > header {
|
||||||
|
min-width: 0;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content > header > strong {
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #243a52;
|
||||||
|
font-size: 13px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content > header > span {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-card :is(.v2-reconcile-severity, .v2-reconcile-status).semi-tag {
|
||||||
|
min-height: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding-inline: 5px;
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content > p {
|
||||||
|
overflow: hidden;
|
||||||
|
color: #43576e;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 650;
|
||||||
|
line-height: 15px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-meta {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
color: #7b899a;
|
||||||
|
font-size: 8px;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-meta > span {
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-meta > time {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content > footer {
|
||||||
|
min-height: 27px;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content > footer > span {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content > footer > span:first-child {
|
||||||
|
overflow: hidden;
|
||||||
|
color: #75859a;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-mobile-content > footer > span:last-child {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
color: var(--v2-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-pagination {
|
||||||
|
min-height: 50px;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0;
|
||||||
|
padding: 5px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-pagination .v2-table-pagination-info {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-pagination .v2-table-pagination-controls {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-pagination .v2-table-pagination-button.semi-button,
|
||||||
|
.v2-reconcile-pagination .v2-table-pagination-current {
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-trend-sidesheet .semi-sidesheet-inner {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user