diff --git a/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx b/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx
index 85d61e9b..7f11fe06 100644
--- a/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx
+++ b/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx
@@ -1044,6 +1044,48 @@ export function Dashboard({
downloadCsv('dashboard-snapshot.csv', buildCsv(dashboardSnapshotColumns, rows));
Toast.success(`已导出 ${rows.length.toLocaleString()} 条驾驶舱摘要`);
};
+ const commandCenterItems = [
+ {
+ title: '全域车辆监控',
+ value: `${formatCount(serviceSummary?.onlineVehicles ?? summary?.onlineVehicles)} 在线`,
+ detail: `有效定位 ${commandLocatedCount.toLocaleString()} 辆,先从地图确认车辆分布、在线状态和最新位置。`,
+ color: 'green' as const,
+ primaryAction: '打开车辆地图',
+ secondaryAction: '在线车辆',
+ onPrimary: () => onOpenMap({ online: 'online' }),
+ onSecondary: () => onOpenVehicles({ online: 'online' })
+ },
+ {
+ title: '异常车辆闭环',
+ value: `${formatCount(summary?.issueVehicles)} 告警`,
+ detail: highPriorityIssue ? `最高优先级:${qualityIssueLabel(highPriorityIssue.issueType)} / ${priorityIssueVehicleLabel(highPriorityIssue)}` : '当前没有高优先级告警,保持实时巡检。',
+ color: (summary?.issueVehicles ?? 0) > 0 ? 'orange' as const : 'green' as const,
+ primaryAction: '告警事件',
+ secondaryAction: '通知规则',
+ onPrimary: () => onOpenQuality(highPriorityIssue?.issueType ? { issueType: highPriorityIssue.issueType } : {}),
+ onSecondary: () => onOpenQuality(highPriorityIssue?.issueType ? { issueType: highPriorityIssue.issueType } : {})
+ },
+ {
+ title: '自定义时间复盘',
+ value: taskTimeMonitorSummary,
+ detail: '一个时间窗贯穿轨迹回放、里程统计、历史查询和告警复盘,适合客户问询与 BI 核对。',
+ color: 'blue' as const,
+ primaryAction: '轨迹复盘',
+ secondaryAction: '里程统计',
+ onPrimary: () => openTimeMonitorHistory(),
+ onSecondary: () => openTimeMonitorMileage()
+ },
+ {
+ title: '数据交付与导出',
+ value: `${formatCount(summary?.frameToday)} 今日数据`,
+ detail: '按车辆、时间、字段裁剪导出位置、原始记录和字段证据,交付给业务或客户复盘。',
+ color: 'blue' as const,
+ primaryAction: '历史导出',
+ secondaryAction: '导出概览',
+ onPrimary: () => openTimeMonitorRaw(),
+ onSecondary: () => exportDashboardSnapshot()
+ }
+ ];
return (
@@ -1086,6 +1128,39 @@ export function Dashboard({
+
+
+ {commandCenterItems.map((item) => (
+
+
+ {item.title}
+ {item.value}
+
+
{item.detail}
+
+
+
+
+
+ ))}
+
+
{customerHeroActions.map((item) => (
diff --git a/vehicle-data-platform/apps/web/src/styles/global.css b/vehicle-data-platform/apps/web/src/styles/global.css
index 7729acce..1181c4fd 100644
--- a/vehicle-data-platform/apps/web/src/styles/global.css
+++ b/vehicle-data-platform/apps/web/src/styles/global.css
@@ -410,6 +410,41 @@ body {
line-height: 26px;
}
+.vp-command-center-grid {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: 12px;
+}
+
+.vp-command-center-item {
+ min-height: 166px;
+ padding: 16px;
+ border: 1px solid var(--vp-border);
+ border-radius: 8px;
+ background: #ffffff;
+ display: grid;
+ align-content: space-between;
+ gap: 12px;
+}
+
+.vp-command-center-head {
+ min-width: 0;
+ display: grid;
+ gap: 8px;
+}
+
+.vp-command-center-head strong {
+ color: var(--vp-text);
+ font-size: 20px;
+ line-height: 26px;
+ word-break: break-word;
+}
+
+.vp-command-center-item .semi-typography {
+ font-size: 13px;
+ line-height: 20px;
+}
+
.vp-customer-task-grid {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
@@ -3176,6 +3211,7 @@ button.vp-realtime-command-item:focus-visible {
.vp-map-ops-readiness,
.vp-map-ops-work,
.vp-time-monitor-grid,
+ .vp-command-center-grid,
.vp-customer-task-grid,
.vp-current-service-board,
.vp-current-service-grid,
diff --git a/vehicle-data-platform/apps/web/src/test/App.test.tsx b/vehicle-data-platform/apps/web/src/test/App.test.tsx
index b1d47e73..b730f0c6 100644
--- a/vehicle-data-platform/apps/web/src/test/App.test.tsx
+++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx
@@ -788,6 +788,15 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
await renderDashboard();
expect(screen.getByText('车辆运营监控台')).toBeInTheDocument();
expect(screen.getByText('先看车辆服务')).toBeInTheDocument();
+ expect(screen.getByText('车辆监控指挥台')).toBeInTheDocument();
+ expect(screen.getByText('全域车辆监控')).toBeInTheDocument();
+ expect(screen.getByText('异常车辆闭环')).toBeInTheDocument();
+ expect(screen.getByText('自定义时间复盘')).toBeInTheDocument();
+ expect(screen.getByText('数据交付与导出')).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '车辆监控指挥台 全域车辆监控 打开车辆地图' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '车辆监控指挥台 异常车辆闭环 告警事件' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '车辆监控指挥台 自定义时间复盘 轨迹复盘' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '车辆监控指挥台 数据交付与导出 历史导出' })).toBeInTheDocument();
expect(screen.getByText('客户常用工作流')).toBeInTheDocument();
expect(screen.getByText('实时车辆地图')).toBeInTheDocument();
expect(screen.getByText('历史数据导出')).toBeInTheDocument();