feat: 实现四阶段进度显示

问题:
- 当前进度显示使用旧的处理器列表
- 显示了所有独立的处理步骤,而不是分阶段

解决方案:
- 将处理步骤聚合到四个主要阶段
- 实现阶段级进度计算
- 更新阶段名称显示

四阶段结构:
1. Processors (30%)
   - 包含所有处理器 (ASR, FACE, OCR, etc.)

2. Knowledge Graph (35%)
   - tkg_nodes
   - tkg_edges

3. Moment Extraction (6%)
   - vlm_summary
   - scene_vlm
   - moment_chunks

4. Integration (29%)
   - rule1_ingestion
   - rule2_ingestion
   - face_tracing
   - face_dedup

实现细节:
- loadPipelineStats() 中添加阶段聚合逻辑
- 根据步骤权重计算阶段进度
- 根据步骤状态确定阶段状态
- formatStageName() 更新阶段名称映射

进度计算:
- 阶段进度 = 加权平均步骤进度
- 阶段状态 = 优先级: failed > completed > running > pending
- 总体进度 = 加权阶段进度之和

显示效果:
- ✗ Processors: 0%
- ✓ Knowledge Graph: 100%
- ✗ Moment Extraction: 33%
- ✗ Integration: 50%

优势:
- 更清晰的阶段划分
- 更好的进度概览
- 更符合实际处理流程
This commit is contained in:
2026-10-14 20:23:42 +08:00
parent 86832229a9
commit f298626487
2 changed files with 61 additions and 19 deletions

View File

@@ -1112,31 +1112,69 @@ export async function loadPipelineStats(fileUuid: string, force = false): Promis
const stages = data.stages || []
const WEIGHT_MAP: Record<string, number> = {
processors: 0.30,
rule1_ingestion: 0.05,
face_tracing: 0.05,
face_dedup: 0.10,
tkg_nodes: 0.20,
tkg_edges: 0.15,
rule2_ingestion: 0.10,
vlm_summary: 0.03,
scene_vlm: 0.03,
moment_chunks: 0.01
// Map individual steps to phases
const phaseMap: Record<string, {
weight: number
steps: string[]
}> = {
processors: {
weight: 0.30,
steps: ['processors']
},
knowledge_graph: {
weight: 0.35,
steps: ['tkg_nodes', 'tkg_edges']
},
moment_extraction: {
weight: 0.06,
steps: ['vlm_summary', 'scene_vlm', 'moment_chunks']
},
integration: {
weight: 0.29,
steps: ['rule1_ingestion', 'rule2_ingestion', 'face_tracing', 'face_dedup']
}
}
const mappedStages = stages.map((s: any) => ({
name: s.name,
weight: WEIGHT_MAP[s.name] ?? s.weight ?? 0,
progress: s.progress || 0,
status: s.status || 'pending'
}))
// Aggregate steps into phases
const aggregatedStages: PipelineStage[] = []
const calculatedProgress = mappedStages.reduce((sum, s) => sum + s.weight * s.progress, 0)
for (const [phaseName, phaseConfig] of Object.entries(phaseMap)) {
const phaseSteps = stages.filter((s: any) => phaseConfig.steps.includes(s.name))
if (phaseSteps.length > 0) {
// Calculate phase progress from steps
const totalWeight = phaseSteps.reduce((sum: number, s: any) => sum + (s.weight || 0), 0)
const weightedProgress = phaseSteps.reduce((sum: number, s: any) => {
const stepWeight = s.weight || 0
return sum + stepWeight * (s.progress || 0)
}, 0)
const phaseProgress = totalWeight > 0 ? weightedProgress / totalWeight : 0
// Determine phase status
const allCompleted = phaseSteps.every((s: any) => s.status === 'completed')
const anyRunning = phaseSteps.some((s: any) => s.status === 'running')
const anyFailed = phaseSteps.some((s: any) => s.status === 'failed')
let phaseStatus: 'pending' | 'running' | 'completed' | 'failed' = 'pending'
if (anyFailed) phaseStatus = 'failed'
else if (allCompleted) phaseStatus = 'completed'
else if (anyRunning) phaseStatus = 'running'
aggregatedStages.push({
name: phaseName,
weight: phaseConfig.weight,
progress: phaseProgress,
status: phaseStatus
})
}
}
const calculatedProgress = aggregatedStages.reduce((sum, s) => sum + s.weight * s.progress, 0)
const pipelineStats: PipelineStats = {
overall_progress: calculatedProgress,
stages: mappedStages
stages: aggregatedStages
}
console.log('[loadPipelineStats]', fileUuid, pipelineStats)

View File

@@ -1179,6 +1179,10 @@ function getStageIcon(status: string): string {
function formatStageName(name: string): string {
const names: Record<string, string> = {
processors: 'Processors',
knowledge_graph: 'Knowledge Graph',
moment_extraction: 'Moment Extraction',
integration: 'Integration',
// Keep old names for backward compatibility
rule1_ingestion: 'Rule1 Ingestion',
face_tracing: 'Face Tracing',
face_dedup: 'Face Dedup',