From 40fd7fe0098e0b1dfa8aed20ee0e03074ce080fb Mon Sep 17 00:00:00 2001 From: lingniu Date: Mon, 20 Jul 2026 02:22:05 +0800 Subject: [PATCH] feat(web): unify governance workspace identity --- .../apps/web/src/v2/pages/AccessPage.test.tsx | 4 +- .../apps/web/src/v2/pages/AccessPage.tsx | 4 +- .../apps/web/src/v2/pages/AlertsPage.test.tsx | 4 +- .../apps/web/src/v2/pages/AlertsPage.tsx | 2 + .../apps/web/src/v2/styles/workspace.css | 164 ++++++++++++++++++ 5 files changed, 175 insertions(+), 3 deletions(-) diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.test.tsx index f1a9f91a..50e85024 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.test.tsx @@ -51,7 +51,9 @@ test('removes old access rows immediately when the vehicle filter scope changes' expect(await screen.findByText('旧接入车牌')).toBeInTheDocument(); expect(screen.getByRole('heading', { name: '接入健康工作台', level: 5 })).toBeInTheDocument(); - expect(screen.getByLabelText('接入管理操作')).toHaveClass('v2-workspace-command-bar', 'v2-access-command-bar'); + expect(screen.getByLabelText('接入管理操作')).toHaveClass('v2-workspace-command-bar', 'v2-access-command-bar', 'has-identity'); + expect(screen.getByLabelText('接入管理操作')).toHaveTextContent('来源治理'); + expect(screen.getByLabelText('接入管理操作').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument(); expect(view.container.querySelector('.v2-access-discovery-shell')).toBeInTheDocument(); for (const className of ['v2-access-filter-card-v3', 'v2-access-table-v3']) { expect(view.container.querySelector(`.${className}.semi-card`)).toBeInTheDocument(); diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.tsx index fd50500e..c67325aa 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.tsx @@ -1,4 +1,4 @@ -import { IconChevronDown, IconChevronRight, IconClose, IconDownload, IconMore, IconRefresh, IconSave, IconSearch, IconSetting } from '@douyinfe/semi-icons'; +import { IconChevronDown, IconChevronRight, IconClose, IconConnectionPoint1, IconDownload, IconMore, IconRefresh, IconSave, IconSearch, IconSetting } from '@douyinfe/semi-icons'; import { Button, Card, CardGroup, Collapse, Descriptions, Dropdown, Empty, Input, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { FormEvent, KeyboardEvent, memo, useCallback, useEffect, useMemo, useState } from 'react'; @@ -433,6 +433,8 @@ export default function AccessPage() { } title="接入健康工作台" description={mobileLayout ? summary ? `截至 ${compactTime(summary.asOf)} · ${summary.totalVehicles.toLocaleString('zh-CN')} 辆主车辆` : '正在读取最新接入状态' diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx index b2af0377..1f2587de 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx @@ -145,7 +145,9 @@ test('clears old alert rows and inspector evidence when the event scope changes' expect(view.container.querySelector(`.${className}.semi-card`)).toBeInTheDocument(); } expect(view.container.querySelector('.v2-alert-navigation')).toBeInTheDocument(); - expect(screen.getByLabelText('告警中心工作区')).toHaveClass('v2-workspace-command-bar', 'v2-alert-command-bar'); + expect(screen.getByLabelText('告警中心工作区')).toHaveClass('v2-workspace-command-bar', 'v2-alert-command-bar', 'has-identity'); + expect(screen.getByLabelText('告警中心工作区')).toHaveTextContent('主动告警'); + expect(screen.getByLabelText('告警中心工作区').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument(); expect(screen.getByRole('heading', { level: 5, name: '告警处置工作台' })).toBeInTheDocument(); expect(screen.getByText('核验事件证据、治理规则并追踪通知状态')).toBeInTheDocument(); expect(screen.getByText('可处置事件')).toBeInTheDocument(); diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx index 078bbfa1..7dbe5bc1 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx @@ -631,6 +631,8 @@ export default function AlertsPage() { } title="告警处置工作台" description="核验事件证据、治理规则并追踪通知状态" status={unread ? `${unread.toLocaleString('zh-CN')} 条未读` : '通知已读'} diff --git a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css index 607e803b..27c2d885 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css @@ -26885,3 +26885,167 @@ display: none; } } + +/* + * Governance identity convergence. + * Alert handling and source governance now share the same quiet identity + * language as vehicle, trajectory and evidence workspaces without competing + * with their queue, tabs or difference list. + */ +.v2-alert-command-bar.has-identity.v2-workspace-command-bar { + min-height: 60px; + background: + radial-gradient(circle at 8% -90%, rgba(245, 158, 11, .1), transparent 48%), + linear-gradient(108deg, #fff 0%, #fffdf9 52%, #fbfdff 100%); + padding: 7px 8px 7px 11px; +} + +.v2-alert-command-bar.has-identity .v2-workspace-command-copy { + max-width: 340px; + flex: 1 1 250px; + gap: 9px; +} + +.v2-alert-command-bar.has-identity .v2-workspace-command-icon.semi-avatar { + width: 34px; + height: 34px; + flex-basis: 34px; + border-color: rgba(230, 126, 34, .13); + border-radius: 10px; + background: linear-gradient(145deg, #fff6e8 0%, #ffefd7 100%); + color: #d97706; + box-shadow: inset 0 1px rgba(255, 255, 255, .9), 0 5px 14px rgba(217, 119, 6, .07); +} + +.v2-alert-command-bar.has-identity .v2-workspace-command-stack { + gap: 0; +} + +.v2-alert-command-bar.has-identity .v2-workspace-command-eyebrow { + color: #9a7b52; + font-size: 7px; + line-height: 10px; +} + +.v2-alert-command-bar.has-identity .v2-workspace-command-title { + color: #334155; + font-size: 14px; + font-weight: 760; + line-height: 18px; +} + +.v2-alert-command-bar.has-identity .v2-workspace-command-description { + max-width: 280px; + color: #8793a3; + font-size: 9px; + line-height: 12px; +} + +.v2-alert-command-bar.has-identity .v2-workspace-command-actions > .semi-tag { + border-color: rgba(217, 119, 6, .1); + background: #fff6e8; + color: #b86505; +} + +.v2-access-discovery-shell > .v2-access-command-bar.has-identity { + min-height: 58px; + background: + radial-gradient(circle at 91% -100%, rgba(18, 104, 243, .1), transparent 43%), + linear-gradient(105deg, #fff 0%, #fbfdff 100%); + padding: 8px 10px 8px 12px; +} + +.v2-access-command-bar.has-identity .v2-workspace-command-copy { + min-width: 260px; +} + +.v2-access-command-bar.has-identity .v2-workspace-command-icon.semi-avatar { + width: 34px; + height: 34px; + flex-basis: 34px; + border-radius: 10px; + font-size: 14px; +} + +.v2-access-command-bar.has-identity .v2-workspace-command-stack { + gap: 0; +} + +.v2-access-command-bar.has-identity .v2-workspace-command-title { + color: #263a52; + font-size: 14px; + font-weight: 760; + line-height: 18px; +} + +.v2-access-command-bar.has-identity .v2-workspace-command-description { + color: #8290a3; + font-size: 9px; + line-height: 12px; +} + +.v2-access-command-bar.has-identity .v2-workspace-command-actions > .semi-tag { + border-color: rgba(18, 104, 243, .08); + background: #eef5ff; + color: #245da8; +} + +@media (min-width: 681px) and (max-width: 980px) { + .v2-alert-command-bar.has-identity .v2-workspace-command-copy { + max-width: 250px; + } + + .v2-alert-command-bar.has-identity .v2-workspace-command-description, + .v2-access-command-bar.has-identity .v2-workspace-command-description { + display: none; + } + + .v2-access-command-bar.has-identity .v2-workspace-command-copy { + min-width: 200px; + } +} + +@media (max-width: 680px) { + .v2-alert-command-bar.has-identity .v2-workspace-command-copy { + display: none; + } + + .v2-alert-command-bar.has-identity.v2-workspace-command-bar { + min-height: 50px; + background: #fff; + padding: 4px; + } + + .v2-access-discovery-shell > .v2-access-command-bar.has-identity { + min-height: 56px; + padding: 6px 7px 6px 9px; + } + + .v2-access-command-bar.has-identity .v2-workspace-command-copy { + min-width: 0; + gap: 7px; + } + + .v2-access-command-bar.has-identity .v2-workspace-command-icon.semi-avatar { + width: 31px; + height: 31px; + flex-basis: 31px; + border-radius: 9px; + font-size: 13px; + } + + .v2-access-command-bar.has-identity .v2-workspace-command-eyebrow { + font-size: 7px; + line-height: 9px; + } + + .v2-access-command-bar.has-identity .v2-workspace-command-title { + font-size: 12px; + line-height: 15px; + } + + .v2-access-command-bar.has-identity .v2-workspace-command-description, + .v2-access-command-bar.has-identity .v2-workspace-command-meta { + display: none; + } +}