feat: 添加 Pipeline Progress API 支持

新增功能:
1. Pipeline Phases 配置
   - loadPipelinePhases() 函数
   - 调用 GET /api/v1/pipeline/phases
   - 缓存配置(静态,不常变化)

2. File Progress API
   - loadFileProgress() 函数
   - 调用 GET /api/v1/file/{uuid}/progress
   - 返回详细的阶段和处理器进度

3. 类型定义
   - PipelinePhasesConfig
   - FileProgressDetail
   - PhaseProgressDetail
   - ProcessorProgressDetail

4. loadPipelineStats() 增强
   - 优先使用新的 progress API
   - 自动降级到旧 API
   - 支持阶段进度计算

API Endpoints:
GET /api/v1/pipeline/phases
GET /api/v1/file/{uuid}/progress

返回格式:
{
  "file_uuid": "...",
  "overall_progress": 0.75,
  "current_phase": "tkg_nodes",
  "phases": {
    "processors": {
      "status": "completed",
      "progress": 1.0,
      "processors": {...}
    }
  }
}

用途:
- LibraryView 显示文件处理进度
- 实时更新 Pipeline 状态
- 支持阶段级进度显示

状态: ✅ 编译通过
This commit is contained in:
2026-10-14 20:15:24 +08:00
parent 3e7eba0741
commit 86832229a9

View File

@@ -84,9 +84,50 @@ export interface PipelineStage {
export interface PipelineStats {
overall_progress: number
current_phase?: string | null
stages: PipelineStage[]
}
// Pipeline Phases 配置
export interface PhaseProcessor {
name: string
weight: number
depends_on?: string[]
}
export interface PipelinePhase {
name: string
weight: number
processors: PhaseProcessor[]
}
export interface PipelinePhasesConfig {
phases: PipelinePhase[]
}
// Pipeline Progress API (new)
export interface ProcessorProgressDetail {
name: string
status: 'pending' | 'running' | 'completed' | 'failed'
progress: number
message?: string
}
export interface PhaseProgressDetail {
status: string
progress: number
processors: Record<string, ProcessorProgressDetail>
}
export interface FileProgressDetail {
file_uuid: string
overall_progress: number
current_phase: string | null
phases: Record<string, PhaseProgressDetail>
}
export const pipelinePhasesCache = ref<PipelinePhasesConfig | null>(null)
export interface SystemStats {
cpu_used_percent: number
memory_used_percent: number
@@ -991,6 +1032,43 @@ export async function syncAllProcessingFiles(): Promise<void> {
}
}
export async function loadPipelinePhases(force = false): Promise<PipelinePhasesConfig | null> {
if (!force && pipelinePhasesCache.value) return pipelinePhasesCache.value
try {
const resp = await fetch('/api/v1/pipeline/phases')
if (!resp.ok) {
console.warn('Pipeline phases API failed:', resp.status)
return null
}
const data: PipelinePhasesConfig = await resp.json()
pipelinePhasesCache.value = data
return data
} catch (e) {
console.error('loadPipelinePhases failed:', e)
return null
}
}
export async function loadFileProgress(fileUuid: string): Promise<FileProgressDetail | null> {
if (!fileUuid) return null
try {
const resp = await fetch(`/api/v1/file/${fileUuid}/progress`)
if (!resp.ok) {
console.warn('File progress API failed:', resp.status)
return null
}
const data: FileProgressDetail = await resp.json()
return data
} catch (e) {
console.error('loadFileProgress failed:', e)
return null
}
}
export async function loadPipelineStats(fileUuid: string, force = false): Promise<PipelineStats | null> {
if (!fileUuid) return null
if (!force && pipelineStatsCache.value[fileUuid]) return pipelineStatsCache.value[fileUuid]
@@ -998,6 +1076,38 @@ export async function loadPipelineStats(fileUuid: string, force = false): Promis
loadingPipelineStats.add(fileUuid)
try {
// Try new progress API first
const progressData = await loadFileProgress(fileUuid)
if (progressData && progressData.overall_progress !== undefined) {
const stages: PipelineStage[] = []
// Convert phases to stages
if (progressData.phases) {
const phasesConfig = await loadPipelinePhases()
const phaseWeights = phasesConfig?.phases || []
for (const [phaseName, phaseData] of Object.entries(progressData.phases)) {
const config = phaseWeights.find(p => p.name === phaseName)
stages.push({
name: phaseName,
weight: config?.weight || 0.1,
progress: phaseData.progress || 0,
status: phaseData.status as any || 'pending'
})
}
}
const pipelineStats: PipelineStats = {
overall_progress: progressData.overall_progress,
current_phase: progressData.current_phase,
stages
}
pipelineStatsCache.value = { ...pipelineStatsCache.value, [fileUuid]: pipelineStats }
return pipelineStats
}
// Fallback to old API
const data: any = await apiCall('get_pipeline_stats', { fileUuid })
const stages = data.stages || []