From e27d5513ed71788011f05adc418c57bd1da96c3f Mon Sep 17 00:00:00 2001 From: lingniu Date: Sun, 5 Jul 2026 15:46:32 +0800 Subject: [PATCH] feat(platform): add customer question shortcuts --- .../apps/web/src/pages/Dashboard.tsx | 53 +++++++++++++++++++ .../apps/web/src/styles/global.css | 48 +++++++++++++++++ .../apps/web/src/test/App.test.tsx | 6 +++ 3 files changed, 107 insertions(+) diff --git a/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx b/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx index f3ceef0d..2d4a5e8e 100644 --- a/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx @@ -1426,6 +1426,43 @@ export function Dashboard({ onClick: () => onOpenQuality() } ]; + const customerQuestionActions = [ + { + question: '这辆车现在在哪里?', + answer: `${commandLocatedCount.toLocaleString()} 辆有可用坐标`, + action: '打开地图', + color: commandLocatedCount > 0 ? 'green' as const : 'orange' as const, + onClick: () => onOpenMap({ online: 'online' }) + }, + { + question: '这段时间跑了多少公里?', + answer: dayRangeText(timeMonitorScopeValue.dateFrom, timeMonitorScopeValue.dateTo), + action: '查里程', + color: 'blue' as const, + onClick: openTimeMonitorMileage + }, + { + question: '能不能回放轨迹?', + answer: `${formatCount(summary?.activeToday)} 辆今日活跃`, + action: '轨迹回放', + color: 'blue' as const, + onClick: openTimeMonitorHistory + }, + { + question: '数据能导出给客户吗?', + answer: `${formatCount(summary?.frameToday)} 条今日证据`, + action: '查询导出', + color: 'blue' as const, + onClick: openTimeMonitorRaw + }, + { + question: '哪些车需要马上处理?', + answer: highPriorityIssue ? `${qualityIssueLabel(highPriorityIssue.issueType)} / ${priorityIssueVehicleLabel(highPriorityIssue)}` : '暂无高优先级告警', + action: '告警事件', + color: (summary?.issueVehicles ?? 0) > 0 ? 'orange' as const : 'green' as const, + onClick: () => onOpenQuality(highPriorityIssue?.issueType ? { issueType: highPriorityIssue.issueType } : {}) + } + ]; const customerNextActions = [ { level: (summary?.issueVehicles ?? 0) > 0 ? '优先' : '巡检', @@ -1537,6 +1574,22 @@ export function Dashboard({ ))} + 客户常问 +
+ {customerQuestionActions.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 b45fec54..f59358c6 100644 --- a/vehicle-data-platform/apps/web/src/styles/global.css +++ b/vehicle-data-platform/apps/web/src/styles/global.css @@ -559,6 +559,54 @@ body { line-height: 18px; } +.vp-fleet-question-grid { + display: grid; + gap: 8px; +} + +.vp-fleet-question-item { + min-height: 58px; + padding: 10px 12px; + border: 1px solid rgba(22, 100, 255, 0.14); + border-radius: var(--vp-radius); + background: #ffffff; + color: inherit; + text-align: left; + cursor: pointer; + font: inherit; + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 5px 10px; + align-items: start; +} + +.vp-fleet-question-item:hover, +.vp-fleet-question-item:focus-visible { + border-color: rgba(22, 100, 255, 0.42); + background: #f5f9ff; + outline: none; +} + +.vp-fleet-question-item strong { + color: var(--vp-text); + font-size: 13px; + line-height: 19px; +} + +.vp-fleet-question-item span { + grid-column: 1 / 2; + color: var(--vp-text-muted); + font-size: 12px; + line-height: 18px; + word-break: break-word; +} + +.vp-fleet-question-item .semi-tag { + grid-column: 2 / 3; + grid-row: 1 / span 2; + align-self: center; +} + .vp-fleet-monitor-time { padding: 12px; border: 1px solid rgba(0, 164, 184, 0.22); 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 a64215b5..a3ed6570 100644 --- a/vehicle-data-platform/apps/web/src/test/App.test.tsx +++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx @@ -811,6 +811,12 @@ test('dashboard exposes vehicle data center capability matrix', async () => { expect(screen.getByRole('button', { name: '客户车辆工作流 统计查询 统计查询' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: '客户车辆工作流 数据交付 历史导出' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: '客户车辆工作流 告警通知 告警事件' })).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.getByRole('button', { name: '客户常问 哪些车需要马上处理? 告警事件' })).toBeInTheDocument(); expect(screen.getByText('来源只作为可信度证据,不作为客户主导航。')).toBeInTheDocument(); expect(screen.getByText('同一时间窗会同步用于轨迹回放、统计查询、历史查询和告警复盘。')).toBeInTheDocument(); expect(screen.getByText('车辆服务指挥台')).toBeInTheDocument();