diff --git a/client/src/components/AnalysisPanel.tsx b/client/src/components/AnalysisPanel.tsx
index b3b90fd..17eb807 100644
--- a/client/src/components/AnalysisPanel.tsx
+++ b/client/src/components/AnalysisPanel.tsx
@@ -2,8 +2,8 @@ import { useState, useEffect, useMemo, useRef } from 'react';
import { trpc } from '@/lib/trpc';
import { useAuth } from '@/_core/hooks/useAuth';
import { BarChart2, Ruler, Zap, Play, Trash2, ChevronDown, ChevronRight, RefreshCw, Flame, Box, Layers, Crosshair, Cpu, Timer, Square, Maximize2, FileSpreadsheet, Image as ImageIcon } from 'lucide-react';
-import GenericResultView, { filterVisibleMeasurements, formatValue, normalizeOverlay3D, numberArrayFromUnknown, statusClass, statusLabel, type Overlay3D } from './GenericResultView';
-import { aggregateDemoFlowResults, type DemoFlowArtifactGroup, type DemoFlowStatusNotice } from './demoFlowAggregation';
+import GenericResultView, { filterVisibleMeasurements, formatValue, normalizeOverlay3D, numberArrayFromUnknown, statusClass, type Overlay3D } from './GenericResultView';
+import { aggregateDemoFlowResults, demoFlowStatusLabel, type DemoFlowArtifactGroup, type DemoFlowStatusNotice } from './demoFlowAggregation';
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from './ui/dialog';
@@ -937,7 +937,7 @@ export default function AnalysisPanel({ taskId, onReplay, onViewSmoothHeatmap, o
}
- {row.measurement.status === 'info' ? '参考' : statusLabel(row.measurement)}
+ {demoFlowStatusLabel(row.measurement)}
|
diff --git a/client/src/components/demoFlowAggregation.test.ts b/client/src/components/demoFlowAggregation.test.ts
index fb2b075..a917416 100644
--- a/client/src/components/demoFlowAggregation.test.ts
+++ b/client/src/components/demoFlowAggregation.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
-import { aggregateDemoFlowResults, type DemoFlowSourceResult } from './demoFlowAggregation';
+import { aggregateDemoFlowResults, demoFlowStatusLabel, type DemoFlowSourceResult } from './demoFlowAggregation';
function result(id: number, index: number, status: string, resultData: Record): DemoFlowSourceResult {
return { id, type: 'plugin', pluginId: `plugin-${id}`, status, resultData: { demoFlowIndex: index, ...resultData } };
@@ -65,6 +65,47 @@ describe('aggregateDemoFlowResults', () => {
expect(model.tableRows).toHaveLength(4);
});
+ it('过滤全流程指定的中间指标,同时保持其他有效测量项的原顺序', () => {
+ const model = aggregateDemoFlowResults([
+ result(10, 1, 'completed', {
+ measurements: [
+ { name: '车体长度', value: 100, status: 'pass' },
+ { name: '前后端平移差', value: 0.1, status: 'pass' },
+ { name: '车体宽度', value: 20, status: 'warning' },
+ { name: 'ICP fitness', value: 0.98, status: 'pass' },
+ { name: '配准 RMSE', value: 0.02, status: 'pass' },
+ { name: '车体高度', value: 30, status: 'fail' },
+ ],
+ }),
+ ], nameOf);
+
+ expect(model.measurementRows.map((row) => row.measurement.name)).toEqual([
+ '车体长度', '车体宽度', '车体高度',
+ ]);
+ });
+
+ it('全流程结果使用统一结论文案,不采用算法自定义文案', () => {
+ expect(demoFlowStatusLabel({ status: 'pass' })).toBe('合格');
+ expect(demoFlowStatusLabel({ status: 'warning' })).toBe('警告');
+ expect(demoFlowStatusLabel({ status: 'fail' })).toBe('超差');
+ expect(demoFlowStatusLabel({ status: 'info' })).toBe('参考');
+ expect(demoFlowStatusLabel({})).toBe('参考');
+
+ const model = aggregateDemoFlowResults([
+ result(10, 1, 'completed', {
+ measurements: [
+ { name: '通过项', value: 1, status: 'pass', passLabel: '通过' },
+ { name: '警告项', value: 2, status: 'warning', warningLabel: '部分成功' },
+ { name: '失败项', value: 3, status: 'fail', failLabel: '失败' },
+ ],
+ }),
+ ], nameOf);
+
+ expect(model.measurementRows.map((row) => demoFlowStatusLabel(row.measurement))).toEqual([
+ '合格', '警告', '超差',
+ ]);
+ });
+
it('全部为参考项时进入空测量结果状态,且不生成算法分组行', () => {
const model = aggregateDemoFlowResults([
result(10, 1, 'completed', {
diff --git a/client/src/components/demoFlowAggregation.ts b/client/src/components/demoFlowAggregation.ts
index ea7765d..38fb0ad 100644
--- a/client/src/components/demoFlowAggregation.ts
+++ b/client/src/components/demoFlowAggregation.ts
@@ -1,5 +1,11 @@
import { filterVisibleMeasurements, type Measurement, type PluginResultLike } from './GenericResultView';
+const DEMO_FLOW_HIDDEN_MEASUREMENT_NAMES = new Set([
+ '前后端平移差',
+ 'ICP fitness',
+ '配准 RMSE',
+]);
+
export type DemoFlowSourceResult = {
id: number;
type: string;
@@ -96,6 +102,24 @@ function hasOverlay(value: PluginResultLike['overlay3d']) {
return Boolean(value && value.kind !== 'none');
}
+export function filterDemoFlowMeasurements(measurements: readonly Measurement[]): Measurement[] {
+ return filterVisibleMeasurements(measurements)
+ .filter((measurement) => !DEMO_FLOW_HIDDEN_MEASUREMENT_NAMES.has(measurement.name));
+}
+
+export function demoFlowStatusLabel(measurement: Pick): string {
+ switch (measurement.status) {
+ case 'pass':
+ return '合格';
+ case 'warning':
+ return '警告';
+ case 'fail':
+ return '超差';
+ default:
+ return '参考';
+ }
+}
+
export function aggregateDemoFlowResults(
results: DemoFlowSourceResult[],
getAlgorithmName: (result: DemoFlowSourceResult) => string,
@@ -113,7 +137,7 @@ export function aggregateDemoFlowResults(
const data = (asRecord(result.resultData) ?? {}) as PluginResultLike & Record;
const sourceAlgorithmId = result.pluginId ?? (typeof data.pluginId === 'string' ? data.pluginId : result.type);
const algorithmName = getAlgorithmName(result);
- const measurements = filterVisibleMeasurements(Array.isArray(data.measurements) ? data.measurements : []);
+ const measurements = filterDemoFlowMeasurements(Array.isArray(data.measurements) ? data.measurements : []);
if (measurements.length > 0 && options.includeAlgorithmGroups) {
tableRows.push({ kind: 'algorithm', sourceAlgorithmId, algorithmName, resultId: result.id, flowIndex: index });