mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
fix(wiki): JobStageBar terminal state — badge sync, pulse stop, line coloring
Three bugs fixed: 1. Badge stays "processing" after job completes: pollJobs() never called fetchRawMaterials() when a job reached terminal status, so raw.processingStatus stayed processing in the store. Fix: detect terminal job status in pollJobs, trigger fetchRawMaterials to sync. 2. "Completed" dot pulses instead of solid: dotClass() treated completed the same as in-progress (target === cur → active). Fix: add isTerminal computed (includes completed), return done for all dots at or before the terminal position — no pulse animation. 3. Stage label stays orange at terminal: same cause — active class applied regardless of terminal state. Fix: use done class for terminal labels (green instead of orange). Also: v-if on JobStageBar now shows for terminal status jobs (not just stage !== queued), so completed/failed stage bars remain visible.
This commit is contained in:
parent
0301d5628e
commit
55a7eb96dc
@ -15,7 +15,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="stage-labels">
|
||||
<span v-for="stage in stages" :key="stage.key" class="stage-label" :class="{ active: stage.key === currentStage }">
|
||||
<span v-for="stage in stages" :key="stage.key" class="stage-label" :class="{ active: stage.key === currentStage && !isTerminal, done: stage.key === currentStage && isTerminal }">
|
||||
{{ t(`wiki.jobStage.${stage.key}`) }}
|
||||
</span>
|
||||
</div>
|
||||
@ -96,7 +96,12 @@ const currentStage = computed(() => {
|
||||
return stageMapping[raw] ?? raw
|
||||
})
|
||||
|
||||
// True when backend status indicates a terminal failure (dots should not pulse)
|
||||
// True when the job has reached any terminal state (dots should not pulse)
|
||||
const isTerminal = computed(() =>
|
||||
props.status === 'completed' || props.status === 'failed' || props.status === 'partial' || props.status === 'cancelled'
|
||||
)
|
||||
|
||||
// True specifically for failure terminals (dots show red instead of done)
|
||||
const isTerminalFailure = computed(() =>
|
||||
props.status === 'failed' || props.status === 'partial' || props.status === 'cancelled'
|
||||
)
|
||||
@ -117,11 +122,16 @@ function dotClass(key: string) {
|
||||
const target = stageIndex(key)
|
||||
if (cur < 0) return 'pending' // unknown stage → all pending
|
||||
if (isTerminalFailure.value) {
|
||||
// Terminal failure: all dots before the failure point are done, the failure point is failed
|
||||
// Terminal failure: dots before failure point are done, failure point is red
|
||||
if (target < cur) return 'done'
|
||||
if (target === cur) return 'failed'
|
||||
return 'pending'
|
||||
}
|
||||
if (isTerminal.value) {
|
||||
// Successful terminal (completed): all dots up to and including current are done (no pulse)
|
||||
if (target <= cur) return 'done'
|
||||
return 'pending'
|
||||
}
|
||||
if (target < cur) return 'done'
|
||||
if (target === cur) return 'active'
|
||||
return 'pending'
|
||||
@ -202,6 +212,7 @@ const elapsed = computed(() => {
|
||||
flex: 1;
|
||||
}
|
||||
.stage-label.active { color: var(--mc-primary); font-weight: 600; }
|
||||
.stage-label.done { color: var(--mc-success, #5a8a5a); font-weight: 600; }
|
||||
|
||||
.stage-info {
|
||||
display: flex;
|
||||
|
||||
@ -91,9 +91,9 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- RFC-033: Job stage bar — only show when job has progressed past 'queued' -->
|
||||
<!-- RFC-033: Job stage bar — show when job has progressed past 'queued' or reached terminal -->
|
||||
<JobStageBar
|
||||
v-if="rawJobs[raw.id] && rawJobs[raw.id].stage !== 'queued'"
|
||||
v-if="rawJobs[raw.id] && (rawJobs[raw.id].stage !== 'queued' || rawJobs[raw.id].status !== 'queued')"
|
||||
:stage="rawJobs[raw.id].stage"
|
||||
:status="rawJobs[raw.id].status"
|
||||
:current-model="rawJobs[raw.id].currentModelName ?? (rawJobs[raw.id].currentModelId ? `Model #${rawJobs[raw.id].currentModelId}` : undefined)"
|
||||
@ -288,19 +288,37 @@ onBeforeUnmount(() => {
|
||||
const rawJobs = reactive<Record<number, WikiProcessingJob>>({})
|
||||
let jobPoller: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const TERMINAL_STATUSES = new Set(['completed', 'failed', 'partial', 'cancelled'])
|
||||
|
||||
async function pollJobs() {
|
||||
if (!store.currentKB) return
|
||||
const kbId = store.currentKB.id
|
||||
const processingRaws = store.rawMaterials.filter(
|
||||
r => r.processingStatus === 'processing' || r.processingStatus === 'pending'
|
||||
)
|
||||
let anyTerminal = false
|
||||
for (const raw of processingRaws) {
|
||||
try {
|
||||
const res: any = await wikiApi.getWikiJobs(store.currentKB.id, raw.id)
|
||||
const res: any = await wikiApi.getWikiJobs(kbId, raw.id)
|
||||
const list = res.data || res || []
|
||||
if (list.length > 0) rawJobs[raw.id] = list[0]
|
||||
if (list.length > 0) {
|
||||
const job = list[0]
|
||||
rawJobs[raw.id] = job
|
||||
if (TERMINAL_STATUSES.has(job.status)) {
|
||||
anyTerminal = true
|
||||
}
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
if (processingRaws.length > 0) {
|
||||
// When any job reaches terminal, refresh raw materials to sync status badges
|
||||
if (anyTerminal) {
|
||||
await store.fetchRawMaterials(kbId)
|
||||
}
|
||||
// Continue polling while there are still processing/pending raws
|
||||
const stillActive = store.rawMaterials.some(
|
||||
r => r.processingStatus === 'processing' || r.processingStatus === 'pending'
|
||||
)
|
||||
if (stillActive) {
|
||||
jobPoller = setTimeout(pollJobs, 3000)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user