refine Semi UI alert workspace

This commit is contained in:
lingniu
2026-07-18 03:13:34 +08:00
parent bb3820bfaa
commit 91db15ebde
4 changed files with 686 additions and 11 deletions

View File

@@ -123,9 +123,12 @@ test('clears old alert rows and inspector evidence when the event scope changes'
const view = render(<QueryClientProvider client={client}><MemoryRouter future={ROUTER_FUTURE} initialEntries={['/alerts?keyword=OLDVIN']}><AlertsPage /></MemoryRouter></QueryClientProvider>);
expect((await screen.findAllByText('旧告警车牌')).length).toBeGreaterThan(0);
for (const className of ['v2-alert-filter-card', 'v2-alert-kpis-card', 'v2-alert-table-card']) {
for (const className of ['v2-alert-filter-card', 'v2-alert-kpis-card', 'v2-alert-context-card', 'v2-alert-table-card']) {
expect(view.container.querySelector(`.${className}.semi-card`)).toBeInTheDocument();
}
expect(view.container.querySelector('.v2-alert-navigation')).toBeInTheDocument();
expect(screen.getByText('可处置事件')).toBeInTheDocument();
expect(screen.queryByRole('heading', { level: 2, name: '告警中心' })).not.toBeInTheDocument();
expect(view.container.querySelector('.v2-alert-inspector')).not.toBeInTheDocument();
expect(view.container.querySelector('.v2-alert-workspace')).not.toHaveClass('is-inspector-open');
expect(view.container.querySelectorAll('.v2-alert-kpis .v2-metric-action')).toHaveLength(4);

View File

@@ -8,7 +8,6 @@ import type { AlertEvent, AlertNotification, AlertQuery, AlertRule, AlertRuleInp
import { actionLabels, alertValue, canAct, formatAlertTime, operatorLabels, ruleCondition, severityLabels, statusLabels, thresholdText } from '../domain/alert';
import { InlineError, PanelEmpty, PanelLoading } from '../shared/AsyncState';
import { MetricActionButton } from '../shared/MetricActionButton';
import { PageHeader } from '../shared/PageHeader';
import { SegmentedTabs } from '../shared/SegmentedTabs';
import { TablePagination } from '../shared/TablePagination';
import { WorkspacePanelHeader } from '../shared/WorkspacePanelHeader';
@@ -197,8 +196,8 @@ function EventWorkspace({ filters, draft, setDraft, setFilters, rules, unread, e
</form>
</WorkspaceFilterPanel>
{summary.isError ? <InlineError message={summary.error instanceof Error ? summary.error.message : '告警汇总读取失败'} onRetry={() => summary.refetch()} /> : null}
<Card className="v2-alert-kpis-card" bodyStyle={{ padding: 0 }}>
<section className="v2-alert-kpis">{[
<Card className="v2-alert-kpis-card v2-alert-context-card" bodyStyle={{ padding: 0 }}>
<section className="v2-alert-kpis" aria-label="活跃告警概览">{[
{ label: '活跃告警', value: sums?.active, tone: 'active', status: '' },
{ label: '未处理', value: sums?.unprocessed, tone: 'unprocessed', status: 'unprocessed' },
{ label: '处理中', value: sums?.processing, tone: 'processing', status: 'processing' },
@@ -218,7 +217,12 @@ function EventWorkspace({ filters, draft, setDraft, setFilters, rules, unread, e
{events.isError ? <InlineError message={events.error instanceof Error ? events.error.message : '告警事件读取失败'} onRetry={() => events.refetch()} /> : null}
<div className={`v2-alert-workspace${selectedID && !mobileLayout ? ' is-inspector-open' : ''}`}>
<Card className="v2-alert-table-card" bodyStyle={{ padding: 0 }}>
<WorkspacePanelHeader title="告警事件" meta={`${(events.data?.total ?? 0).toLocaleString('zh-CN')}`} actions={<Button theme="borderless" icon={<IconRefresh />} onClick={() => Promise.all([events.refetch(), summary.refetch(), ...(selectedID ? [detail.refetch()] : [])])}></Button>} />
<WorkspacePanelHeader
title="告警事件"
description="点击事件查看触发证据、处理进度与处置动作"
meta={`${(events.data?.total ?? 0).toLocaleString('zh-CN')}`}
actions={<Button theme="borderless" icon={<IconRefresh />} loading={events.isFetching} onClick={() => Promise.all([events.refetch(), summary.refetch(), ...(selectedID ? [detail.refetch()] : [])])}></Button>}
/>
<div className="v2-alert-table-scroll">
{mobileLayout
? <div className="v2-alert-mobile-list">{rows.map((event) => <Card key={event.id} className={`v2-alert-mobile-card${selectedID === event.id ? ' is-selected' : ''}`} bodyStyle={{ padding: 0 }}><Button theme="borderless" type="tertiary" className="v2-alert-mobile-action" aria-pressed={selectedID === event.id} aria-expanded={selectedID === event.id} aria-label={`查看 ${event.plate || event.vin} ${event.ruleName} 告警详情`} onClick={() => setSelection({ scope: eventScope, id: event.id })}><span className="v2-alert-mobile-card-content"><header><strong>{event.plate || '未绑定车牌'}</strong><span><SeverityTag severity={event.severity} /><StatusTag status={event.status} /></span></header><p>{event.ruleName}</p><dl><div><dt></dt><dd>{formatAlertTime(event.triggeredAt)}</dd></div><div><dt></dt><dd>{event.protocol || '—'}</dd></div><div><dt></dt><dd>{alertValue(event)}</dd></div><div><dt></dt><dd>{thresholdText(event)}</dd></div></dl><footer><IconChevronRight /></footer></span></Button></Card>)}</div>
@@ -406,5 +410,5 @@ export default function AlertsPage() {
const setTab = (next: Tab) => { setTabState(next); const copy = new URLSearchParams(params); copy.set('tab', next); setParams(copy, { replace: true }); };
const setFilters = (next: Filters) => { setFilterState(next); const copy = new URLSearchParams(); if (tab !== 'events') copy.set('tab', tab); Object.entries(next).forEach(([key, value]) => { if (value) copy.set(key, value); }); setParams(copy, { replace: true }); };
const tabs = [{ key: 'events' as const, label: '告警事件', icon: <IconAlarm /> }, ...(admin ? [{ key: 'rules' as const, label: '规则配置' }] : []), { key: 'notifications' as const, label: '站内通知', icon: <IconBell />, count: unread || undefined }];
return <div className="v2-alert-page"><PageHeader title="告警中心" description="统一监控车辆运行异常,串联触发证据、处理进度与通知状态。" status={unread ? `${unread} 条未读` : '通知已读'} statusColor={unread ? 'orange' : 'green'} meta={<Typography.Text type="tertiary">{operator ? '可处置事件' : '只读查看'}</Typography.Text>} /><SegmentedTabs className="v2-alert-tabs" variant="filled" ariaLabel="告警中心分类" value={activeTab} items={tabs} onChange={setTab} />{activeTab !== 'notifications' && rules.isError ? <InlineError message={rules.error.message} onRetry={() => rules.refetch()} /> : null}{activeTab === 'rules' && metrics.isError ? <InlineError message={metrics.error.message} onRetry={() => metrics.refetch()} /> : null}{activeTab === 'events' ? <EventWorkspace filters={filters} draft={eventDraft} setDraft={setEventDraft} setFilters={setFilters} rules={rules.data ?? []} unread={unread} editable={operator} onTab={setTab} /> : activeTab === 'rules' ? <RulesWorkspace rules={rules.data ?? []} metrics={metrics.data?.metrics ?? []} /> : <NotificationsWorkspace editable={operator} notifications={notifications} />}</div>;
return <div className="v2-alert-page"><div className="v2-alert-navigation"><SegmentedTabs className="v2-alert-tabs" variant="filled" ariaLabel="告警中心分类" value={activeTab} items={tabs} onChange={setTab} /><div className="v2-alert-navigation-meta"><Typography.Text type="tertiary">{operator ? '可处置事件' : '只读查看'}</Typography.Text><Tag color={unread ? 'orange' : 'green'} type="light" size="small">{unread ? `${unread.toLocaleString('zh-CN')} 条未读` : '通知已读'}</Tag></div></div>{activeTab !== 'notifications' && rules.isError ? <InlineError message={rules.error.message} onRetry={() => rules.refetch()} /> : null}{activeTab === 'rules' && metrics.isError ? <InlineError message={metrics.error.message} onRetry={() => metrics.refetch()} /> : null}{activeTab === 'events' ? <EventWorkspace filters={filters} draft={eventDraft} setDraft={setEventDraft} setFilters={setFilters} rules={rules.data ?? []} unread={unread} editable={operator} onTab={setTab} /> : activeTab === 'rules' ? <RulesWorkspace rules={rules.data ?? []} metrics={metrics.data?.metrics ?? []} /> : <NotificationsWorkspace editable={operator} notifications={notifications} />}</div>;
}

View File

@@ -55,11 +55,11 @@ describe('V2 production entry', () => {
expect(source).toContain("from '@douyinfe/semi-ui'");
expect(source).toContain('<Button');
}
for (const name of ['VehiclePage', 'AlertsPage', 'AccessPage', 'UsersPage', 'OperationsPage']) {
for (const name of ['VehiclePage', 'AccessPage', 'UsersPage', 'OperationsPage']) {
expect(corePageSources[name]).toContain("from '../shared/PageHeader'");
expect(corePageSources[name]).toContain('<PageHeader');
}
for (const name of ['HistoryPage', 'StatisticsPage']) {
for (const name of ['AlertsPage', 'HistoryPage', 'StatisticsPage']) {
expect(corePageSources[name]).not.toContain("from '../shared/PageHeader'");
expect(corePageSources[name]).not.toContain('<PageHeader');
}
@@ -150,10 +150,10 @@ describe('V2 production entry', () => {
expect(corePageSources.AlertsPage).toContain('<TextArea');
expect(corePageSources.AlertsPage).toContain('<Radio');
expect(corePageSources.AlertsPage).toContain('<Card key={event.id} className={`v2-alert-mobile-card');
for (const surface of ['v2-alert-kpis-card', 'v2-alert-table-card']) {
expect(corePageSources.AlertsPage).toContain(`<Card className="${surface}"`);
}
expect(corePageSources.AlertsPage).toContain('<Card className="v2-alert-kpis-card v2-alert-context-card"');
expect(corePageSources.AlertsPage).toContain('<Card className="v2-alert-table-card"');
expect(corePageSources.AlertsPage).toContain('<Card className={`v2-alert-inspector');
expect(corePageSources.AlertsPage).toContain('className="v2-alert-navigation"');
expect(corePageSources.AlertsPage).toContain('<SideSheet\n className="v2-alert-filter-sidesheet"');
expect(corePageSources.AlertsPage).toContain('<SideSheet\n className="v2-alert-detail-sidesheet"');
expect(corePageSources.AlertsPage).toContain('className="v2-alert-event-table"');

View File

@@ -5835,3 +5835,671 @@
padding: 11px;
}
}
/*
* Semi UI alert workspace — list first, evidence on demand.
* The shell already owns the page title, so the route begins with one compact
* command rail and reserves the remaining height for the operational list.
*/
.v2-alert-page {
gap: 9px;
padding: 12px 18px 16px;
background: #f6f8fb;
}
.v2-alert-navigation {
display: flex;
min-height: 46px;
flex: 0 0 auto;
align-items: center;
justify-content: space-between;
gap: 14px;
overflow: hidden;
border: 1px solid #dce4ed;
border-radius: 10px;
background: #fff;
padding: 4px 8px 4px 4px;
box-shadow: 0 3px 12px rgba(31, 53, 80, .04);
}
.v2-alert-navigation .v2-alert-tabs.v2-segmented-tabs {
width: auto;
min-height: 36px;
flex: 0 1 auto;
grid-auto-columns: minmax(126px, 1fr);
border: 0;
border-radius: 7px;
background: #f2f5f9;
padding: 3px;
box-shadow: none;
}
.v2-alert-navigation .v2-alert-tabs.v2-segmented-tabs > .semi-button {
min-height: 32px;
border-radius: 6px;
font-size: 12px;
}
.v2-alert-navigation-meta {
display: flex;
min-width: 0;
align-items: center;
justify-content: flex-end;
gap: 9px;
white-space: nowrap;
}
.v2-alert-navigation-meta > .semi-typography {
color: #7d899a;
font-size: 11px;
}
.v2-alert-navigation-meta > .semi-tag {
min-height: 24px;
border-radius: 6px;
font-size: 10px;
}
.v2-alert-filter-card.semi-card,
.v2-alert-context-card.semi-card,
.v2-alert-table-card.semi-card,
.v2-alert-inspector.semi-card,
.v2-alert-rule-list.semi-card,
.v2-alert-rule-editor.semi-card,
.v2-alert-notifications.semi-card {
border-color: #dce4ed;
border-radius: 9px;
box-shadow: 0 3px 14px rgba(31, 53, 80, .045);
}
.v2-alert-filter-card.semi-card {
overflow: visible;
}
.v2-alert-filter-card > .semi-card-body > .v2-workspace-filter-heading {
display: none;
}
.v2-alert-filter.v2-alert-filter-primary {
min-height: 60px;
grid-template-columns: minmax(250px, 1.45fr) minmax(122px, .62fr) minmax(136px, .68fr) auto auto auto;
gap: 8px;
padding: 9px 11px;
}
.v2-alert-filter.v2-alert-filter-primary label {
gap: 4px;
font-size: 10px;
}
.v2-alert-filter.v2-alert-filter-primary label > div,
.v2-alert-filter.v2-alert-filter-primary .semi-select,
.v2-alert-filter.v2-alert-filter-primary .semi-input-wrapper,
.v2-alert-filter.v2-alert-filter-primary > .semi-button {
min-height: 34px;
border-radius: 7px;
}
.v2-alert-filter.v2-alert-filter-primary .semi-input,
.v2-alert-filter.v2-alert-filter-primary .semi-select-selection-text,
.v2-alert-filter.v2-alert-filter-primary > .semi-button {
font-size: 12px;
}
.v2-alert-context-card.semi-card {
min-height: 64px;
flex: 0 0 auto;
overflow: hidden;
}
.v2-alert-context-card > .semi-card-body {
display: grid;
height: 100%;
grid-template-columns: minmax(0, 1fr) 278px;
}
.v2-alert-context-card .v2-alert-kpis,
.v2-alert-context-card .v2-alert-kpis .v2-metric-action-content {
min-height: 64px;
}
.v2-alert-context-card .v2-alert-kpis small {
font-size: 10px;
}
.v2-alert-context-card .v2-alert-kpis strong {
margin-top: 5px;
font-size: 19px;
}
.v2-alert-context-card .v2-alert-secondary-states {
padding: 6px;
gap: 4px;
}
.v2-alert-context-card .v2-alert-secondary-states > .semi-button {
border-radius: 6px;
padding: 5px 6px;
}
.v2-alert-context-card .v2-alert-secondary-states span {
font-size: 9px;
}
.v2-alert-context-card .v2-alert-secondary-states b {
font-size: 14px;
}
.v2-alert-workspace {
min-height: 0;
flex: 1 1 0;
gap: 9px;
}
.v2-alert-workspace.is-inspector-open {
grid-template-columns: minmax(680px, 1fr) 370px;
}
.v2-alert-table-card > .semi-card-body > .v2-workspace-panel-header {
min-height: 48px;
padding: 7px 12px;
}
.v2-alert-table-card .v2-workspace-panel-copy {
gap: 1px;
}
.v2-alert-table-card .v2-workspace-panel-copy > h5.semi-typography {
font-size: 14px;
}
.v2-alert-table-card .v2-workspace-panel-copy > .semi-typography {
color: #8793a4;
font-size: 9px;
}
.v2-alert-table-card .v2-workspace-panel-actions > .semi-button {
min-height: 30px;
border-radius: 6px;
font-size: 11px;
}
.v2-alert-table-scroll {
scrollbar-color: #aebdce transparent;
scrollbar-width: thin;
}
.v2-alert-table-scroll::-webkit-scrollbar {
width: 10px;
height: 10px;
}
.v2-alert-table-scroll::-webkit-scrollbar-thumb {
border: 2px solid transparent;
border-radius: 999px;
background: #aebdce;
background-clip: padding-box;
}
.v2-alert-table-scroll .v2-alert-event-table.semi-table-wrapper .semi-table-thead > .semi-table-row > .semi-table-row-head {
height: 38px;
background: #f7f9fc;
font-size: 10px;
}
.v2-alert-table-scroll .v2-alert-event-table.semi-table-wrapper .semi-table-tbody > .semi-table-row > .semi-table-row-cell {
height: 46px;
padding: 6px 9px;
font-size: 11px;
}
.v2-alert-table-card > .semi-card-body > footer {
min-height: 42px;
padding: 5px 10px;
}
.v2-alert-table-card > .semi-card-body > footer button,
.v2-alert-table-card > .semi-card-body > footer select {
height: 28px;
font-size: 11px;
}
.v2-alert-inspector.semi-card {
background: #f7f9fc;
}
.v2-alert-inspector > .semi-card-body {
display: flex;
height: 100%;
min-height: 0;
flex-direction: column;
}
.v2-alert-inspector > .semi-card-body > .v2-alert-inspector-heading {
min-height: 58px;
padding: 8px 11px;
}
.v2-alert-inspector-content {
min-height: 0;
flex: 1 1 auto;
gap: 0;
overflow: auto;
padding: 0 10px 10px;
}
.v2-alert-inspector-content > .v2-alert-detail-card.semi-card {
flex: 0 0 auto;
overflow: visible;
}
.v2-alert-detail-card.semi-card {
border-width: 0 0 1px;
border-color: #e4e9f0;
border-radius: 0;
background: transparent;
box-shadow: none;
}
.v2-alert-detail-card > .semi-card-header {
min-height: 40px;
border-bottom: 0;
padding: 0 2px;
}
.v2-alert-detail-card > .semi-card-body {
border: 1px solid #e1e7ef;
border-radius: 7px;
background: #fff;
}
.v2-alert-detail-card.v2-alert-progress-card > .semi-card-body,
.v2-alert-detail-card.v2-alert-disposition-card > .semi-card-body {
padding: 10px !important;
}
.v2-alert-inspector > .semi-card-body > .v2-alert-links {
min-height: 46px;
padding: 6px 10px;
}
.v2-alert-inspector > .semi-card-body > .v2-alert-links a {
min-height: 32px;
}
.v2-alert-rules {
min-height: 0;
flex: 1 1 0;
grid-template-columns: minmax(300px, 340px) minmax(600px, 1fr);
gap: 9px;
}
.v2-alert-rule-list.semi-card,
.v2-alert-rule-editor.semi-card {
overflow: hidden;
}
.v2-alert-rule-list > .semi-card-body,
.v2-alert-rule-editor > .semi-card-body,
.v2-alert-rule-editor-form {
height: 100%;
min-height: 0;
}
.v2-alert-rule-list > .semi-card-body,
.v2-alert-rule-editor-form {
display: flex;
flex-direction: column;
}
.v2-alert-rule-items,
.v2-alert-rule-editor-form {
min-height: 0;
}
.v2-alert-rule-items {
flex: 1 1 auto;
overflow: auto;
}
.v2-alert-rule-editor-form {
overflow: auto;
}
.v2-alert-rule-list > .semi-card-body > .v2-alert-rule-list-heading,
.v2-alert-rule-editor-form > .v2-alert-rule-editor-heading {
min-height: 56px;
padding: 8px 12px;
}
.v2-alert-rule-item.semi-button {
min-height: 68px;
padding: 8px 11px;
}
.v2-alert-rule-copy > small {
margin-top: 5px;
}
.v2-alert-rule-templates {
padding: 11px 12px;
}
.v2-alert-template-card.semi-button {
min-height: 72px;
padding: 9px;
}
.v2-rule-form-grid {
gap: 11px 13px;
padding: 13px 14px 16px;
}
.v2-alert-rule-editor-form > footer {
position: sticky;
z-index: 3;
bottom: 0;
min-height: 56px;
background: rgba(255, 255, 255, .97);
padding: 8px 14px;
backdrop-filter: blur(10px);
}
.v2-alert-notifications.semi-card {
min-height: 0;
flex: 1 1 0;
overflow: hidden;
}
.v2-alert-notifications > .semi-card-body {
display: grid;
height: 100%;
min-height: 0;
max-height: none;
grid-template-rows: 54px minmax(0, 1fr) auto;
overflow: hidden;
}
.v2-alert-notifications > .semi-card-body > .v2-workspace-panel-header {
min-height: 54px;
padding: 8px 12px;
}
.v2-alert-notification-list {
min-height: 0;
overflow: auto;
padding: 9px;
}
.v2-alert-notification-cards.semi-card-group {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 9px;
}
.v2-alert-channel-card.semi-card {
border-width: 1px 0 0;
border-radius: 0;
box-shadow: none;
}
.v2-alert-channel-card > .semi-card-header {
min-height: 34px;
padding: 0 12px;
}
.v2-alert-channel-descriptions.semi-descriptions {
padding: 5px 9px 8px;
}
.v2-alert-channel-descriptions table {
width: 100%;
}
.v2-alert-channel-descriptions tbody {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 6px;
}
.v2-alert-channel-descriptions tr {
display: flex;
min-width: 0;
min-height: 32px;
align-items: center;
justify-content: space-between;
gap: 6px;
border: 1px solid #e4e9f0;
border-radius: 6px;
background: #fafbfd;
padding: 4px 7px;
}
.v2-alert-channel-descriptions .semi-descriptions-item {
min-height: 0;
padding: 0;
}
.v2-alert-channel-descriptions .semi-descriptions-item-th {
width: auto;
padding-right: 0;
}
@media (max-width: 1180px) and (min-width: 681px) {
.v2-alert-filter.v2-alert-filter-primary {
grid-template-columns: minmax(220px, 1fr) 120px 130px auto auto auto;
}
.v2-alert-filter.v2-alert-filter-primary > .semi-button {
padding-inline: 9px;
}
}
@media (max-width: 900px) and (min-width: 681px) {
.v2-alert-page {
height: 100%;
min-height: 0;
overflow: hidden;
}
.v2-alert-workspace {
display: grid;
min-height: 0;
flex: 1 1 0;
}
.v2-alert-table-card {
min-height: 0;
}
}
@media (max-width: 680px) {
.v2-alert-page {
gap: 8px;
overflow: auto;
padding: 8px 7px 16px;
}
.v2-alert-navigation {
position: sticky;
z-index: 8;
top: 0;
min-height: 46px;
border-radius: 9px;
padding: 3px;
}
.v2-alert-navigation .v2-alert-tabs.v2-segmented-tabs {
position: static;
width: 100%;
min-height: 38px;
grid-auto-columns: minmax(104px, 1fr);
overflow-x: auto;
}
.v2-alert-navigation .v2-alert-tabs.v2-segmented-tabs > .semi-button {
min-height: 32px;
padding-inline: 7px;
font-size: 10px;
}
.v2-alert-navigation-meta {
display: none;
}
.v2-alert-filter-card > .semi-card-body > .v2-workspace-filter-heading {
display: flex;
}
.v2-alert-filter.v2-alert-filter-primary {
min-height: 0;
grid-template-columns: 1fr 1fr;
gap: 8px;
padding: 9px;
}
.v2-alert-filter.v2-alert-filter-primary label:first-child {
grid-column: 1 / -1;
}
.v2-alert-filter.v2-alert-filter-primary > .semi-button {
min-height: 40px;
}
.v2-alert-filter.v2-alert-filter-primary > .v2-secondary-button {
display: none;
}
.v2-alert-context-card.semi-card {
min-height: 0;
}
.v2-alert-context-card > .semi-card-body {
display: block;
}
.v2-alert-context-card .v2-alert-kpis {
min-height: 88px;
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.v2-alert-context-card .v2-alert-kpis .v2-metric-action,
.v2-alert-context-card .v2-alert-kpis .v2-metric-action-content {
min-height: 44px;
}
.v2-alert-context-card .v2-alert-secondary-states {
border-top: 1px solid #e4e9f0;
border-left: 0;
padding: 4px;
}
.v2-alert-context-card .v2-alert-secondary-states > .semi-button {
min-height: 40px;
padding: 3px 5px;
}
.v2-alert-table-card {
min-height: 460px;
}
.v2-alert-table-card > .semi-card-body > .v2-workspace-panel-header {
min-height: 58px;
align-items: flex-start;
padding: 8px;
}
.v2-alert-table-card .v2-workspace-panel-copy > .semi-typography {
display: none;
}
.v2-alert-mobile-list {
gap: 7px;
padding: 7px;
}
.v2-alert-mobile-card-content {
padding: 11px;
}
.v2-alert-mobile-card-content p {
margin: 6px 0;
}
.v2-alert-mobile-card-content dl {
gap: 6px 10px;
padding-top: 7px;
}
.v2-alert-mobile-card-content dl > div {
display: grid;
min-width: 0;
min-height: 24px;
grid-template-columns: auto minmax(0, 1fr);
align-items: center;
gap: 6px;
}
.v2-alert-mobile-card-content dd {
min-width: 0;
margin: 0;
overflow: hidden;
text-align: right;
text-overflow: ellipsis;
white-space: nowrap;
}
.v2-alert-mobile-card-content footer {
margin-top: 6px;
}
.v2-alert-rules {
display: flex;
flex: none;
flex-direction: column;
overflow: visible;
}
.v2-alert-rule-list {
max-height: 270px;
}
.v2-alert-rule-editor.semi-card,
.v2-alert-rule-editor-form {
overflow: visible;
}
.v2-alert-rule-editor-form > footer {
position: static;
}
.v2-alert-notifications.semi-card {
min-height: 540px;
flex: none;
}
.v2-alert-notification-cards.semi-card-group {
grid-template-columns: 1fr;
}
.v2-alert-channel-descriptions tbody {
display: table-row-group;
}
.v2-alert-channel-descriptions tr {
display: table-row;
min-height: initial;
border: 0;
background: transparent;
padding: 0;
}
.v2-alert-channel-descriptions .semi-descriptions-item {
min-height: 32px;
padding: 4px 0;
}
.v2-alert-channel-descriptions .semi-descriptions-item-th {
width: 135px;
padding-right: 10px;
}
}