feat(web): refine alert notification workspace

This commit is contained in:
lingniu
2026-07-20 05:41:45 +08:00
parent 843690cc71
commit 2c09fd7cf0
3 changed files with 82 additions and 6 deletions

View File

@@ -150,7 +150,7 @@ test('clears old alert rows and inspector evidence when the event scope changes'
expect(screen.getByLabelText('告警中心工作区').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument(); expect(screen.getByLabelText('告警中心工作区').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument();
expect(screen.getByRole('heading', { level: 5, name: '告警处置工作台' })).toBeInTheDocument(); expect(screen.getByRole('heading', { level: 5, name: '告警处置工作台' })).toBeInTheDocument();
expect(screen.getByText('核验事件证据、治理规则并追踪通知状态')).toBeInTheDocument(); expect(screen.getByText('核验事件证据、治理规则并追踪通知状态')).toBeInTheDocument();
expect(screen.getByText('可处置事件')).toBeInTheDocument(); expect(screen.getByText('具备处置权限')).toBeInTheDocument();
expect(screen.queryByRole('heading', { level: 2, name: '告警中心' })).not.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-inspector')).not.toBeInTheDocument();
expect(view.container.querySelector('.v2-alert-workspace')).not.toHaveClass('is-inspector-open'); expect(view.container.querySelector('.v2-alert-workspace')).not.toHaveClass('is-inspector-open');
@@ -326,7 +326,7 @@ test('uses one focused Semi bottom SideSheet for the complete mobile event filte
render(<QueryClientProvider client={client}><MemoryRouter future={ROUTER_FUTURE} initialEntries={['/alerts']}><AlertsPage /></MemoryRouter></QueryClientProvider>); render(<QueryClientProvider client={client}><MemoryRouter future={ROUTER_FUTURE} initialEntries={['/alerts']}><AlertsPage /></MemoryRouter></QueryClientProvider>);
await screen.findByText('当前筛选条件没有告警事件'); await screen.findByText('当前筛选条件没有告警事件');
const trigger = screen.getByRole('button', { name: /修改事件筛选/ }); const trigger = screen.getByRole('button', { name: '打开告警筛选:全部告警' });
expect(trigger).toHaveAttribute('aria-expanded', 'false'); expect(trigger).toHaveAttribute('aria-expanded', 'false');
fireEvent.click(trigger); fireEvent.click(trigger);
@@ -346,7 +346,7 @@ test('uses one focused Semi bottom SideSheet for the complete mobile event filte
fireEvent.click(within(dialog).getByRole('button', { name: '应用并查询' })); fireEvent.click(within(dialog).getByRole('button', { name: '应用并查询' }));
await waitFor(() => expect(mocks.alertEventsV2).toHaveBeenLastCalledWith(expect.objectContaining({ protocol: 'JT808' }), expect.anything())); await waitFor(() => expect(mocks.alertEventsV2).toHaveBeenLastCalledWith(expect.objectContaining({ protocol: 'JT808' }), expect.anything()));
expect(screen.getByRole('button', { name: /修改事件筛选:已启用 1 项/ })).toHaveAttribute('aria-expanded', 'false'); expect(screen.getByRole('button', { name: '打开告警筛选:已启用 1 项' })).toHaveAttribute('aria-expanded', 'false');
}); });
test('keeps mobile rule selection focused and opens editing in a Semi bottom SideSheet', async () => { test('keeps mobile rule selection focused and opens editing in a Semi bottom SideSheet', async () => {

View File

@@ -284,12 +284,13 @@ function EventWorkspace({ filters, draft, setDraft, setFilters, rules, unread, e
return <> return <>
{mobileLayout ? <div className="v2-alert-mobile-discovery"> {mobileLayout ? <div className="v2-alert-mobile-discovery">
<MobileFilterToggle <MobileFilterToggle
title="事件筛选" title="筛选告警"
summary={activeFilterCount ? `已启用 ${activeFilterCount}` : '全部告警'} summary={activeFilterCount ? `已启用 ${activeFilterCount}` : '全部告警'}
expanded={mobileFiltersOpen} expanded={mobileFiltersOpen}
controls="v2-alert-mobile-filters" controls="v2-alert-mobile-filters"
expandedLabel="关闭" expandedLabel="关闭"
collapsedLabel="修改" collapsedLabel="筛选"
ariaLabel={`${mobileFiltersOpen ? '关闭' : '打开'}告警筛选:${activeFilterCount ? `已启用 ${activeFilterCount}` : '全部告警'}`}
onToggle={() => setFiltersCollapsed((value) => !value)} onToggle={() => setFiltersCollapsed((value) => !value)}
/> />
<MobileFilterSheet <MobileFilterSheet
@@ -640,7 +641,7 @@ export default function AlertsPage() {
description="核验事件证据、治理规则并追踪通知状态" description="核验事件证据、治理规则并追踪通知状态"
status={unread ? `${unread.toLocaleString('zh-CN')} 条未读` : '通知已读'} status={unread ? `${unread.toLocaleString('zh-CN')} 条未读` : '通知已读'}
statusColor={unread ? 'orange' : 'green'} statusColor={unread ? 'orange' : 'green'}
meta={<Typography.Text type="tertiary">{operator ? '可处置事件' : '只读查看'}</Typography.Text>} meta={<Typography.Text type="tertiary">{operator ? '具备处置权限' : '仅限查看'}</Typography.Text>}
actions={<SegmentedTabs className="v2-alert-tabs" variant="filled" ariaLabel="告警中心分类" value={activeTab} items={tabs} onChange={setTab} />} actions={<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 !== 'notifications' && rules.isError ? <InlineError message={rules.error.message} onRetry={() => rules.refetch()} /> : null}

View File

@@ -9431,6 +9431,81 @@
padding-inline: 7px; padding-inline: 7px;
} }
@media (min-width: 681px) {
.v2-alert-notification-list {
padding: 0 10px 10px;
}
.v2-alert-notification-cards.semi-card-group {
overflow: hidden;
grid-template-columns: minmax(0, 1fr);
gap: 0;
border: 1px solid #e1e8f0;
border-radius: 10px;
background: #fff;
}
.v2-alert-notification-card.semi-card {
display: grid;
min-height: 64px;
grid-template-columns: minmax(248px, .72fr) minmax(0, 1.7fr);
border: 0;
border-bottom: 1px solid #e8edf3;
border-radius: 0;
box-shadow: none;
contain-intrinsic-size: auto 64px;
transition: background-color .16s ease;
}
.v2-alert-notification-card.semi-card:last-child {
border-bottom: 0;
}
.v2-alert-notification-card.semi-card:hover {
background: #f8fbff;
}
.v2-alert-notification-card.is-unread.semi-card {
box-shadow: inset 3px 0 #2f78e8;
}
.v2-alert-notification-card > .semi-card-header {
min-height: 64px;
border-right: 1px solid #edf1f5;
border-bottom: 0;
padding: 8px 12px;
}
.v2-alert-notification-card > .semi-card-body {
display: grid;
min-height: 64px;
grid-template-columns: minmax(0, 1fr) 138px;
}
.v2-alert-notification-content {
display: -webkit-box;
min-height: 64px;
overflow: hidden;
align-content: center;
margin: 0;
padding: 12px 14px;
line-height: 1.45;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.v2-alert-notification-card > .semi-card-body > footer {
min-height: 64px;
justify-content: center;
align-items: flex-end;
flex-direction: column;
gap: 2px;
border-top: 0;
border-left: 1px solid #edf1f5;
padding: 7px 9px;
}
}
.v2-alert-notification-pagination { .v2-alert-notification-pagination {
display: flex; display: flex;
min-height: 48px; min-height: 48px;