feat: ASRX hybrid pipeline, identity history, worker fixes, checkpoint system
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-sm font-semibold text-gray-300">身分泳道圖 V2</h3>
|
||||
<span class="text-xs text-gray-500">{{ identities.length }} identities</span>
|
||||
</div>
|
||||
<div class="relative overflow-x-auto" ref="scrollRef">
|
||||
<svg :width="svgW" :height="rowH * identities.length + 30" class="block">
|
||||
<!-- time axis -->
|
||||
<line x1="80" :y1="rowH * identities.length + 5" :x2="svgW" :y2="rowH * identities.length + 5" stroke="#4b5563" stroke-width="1" />
|
||||
<g v-for="t in ticks" :key="t">
|
||||
<line :x1="xPos(t)" :y1="rowH * identities.length + 1" :x2="xPos(t)" :y2="rowH * identities.length + 5" stroke="#6b7280" stroke-width="1" />
|
||||
<text :x="xPos(t)" :y="rowH * identities.length + 16" fill="#9ca3af" font-size="9" text-anchor="middle">{{ t }}s</text>
|
||||
</g>
|
||||
<!-- swimlanes -->
|
||||
<g v-for="(ident, i) in identities" :key="ident.name">
|
||||
<text x="4" :y="rowH * i + rowH / 2 + 5" fill="#d1d5db" font-size="11" class="select-none">{{ ident.name }}</text>
|
||||
<rect x="78" :y="rowH * i + 4" width="2" :height="rowH - 8" fill="#374151" rx="2" />
|
||||
<rect
|
||||
v-for="seg in ident.segments" :key="seg.start"
|
||||
:x="xPos(seg.start)" :y="rowH * i + 6"
|
||||
:width="Math.max(2, xPos(seg.end) - xPos(seg.start))"
|
||||
:height="rowH - 12"
|
||||
:fill="ident.color"
|
||||
:opacity="0.7"
|
||||
rx="3"
|
||||
class="cursor-pointer hover:opacity-100"
|
||||
@click="$emit('selectTrace', seg.trace_id)"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
identities: SwimlaneIdentity[]
|
||||
totalDuration: number
|
||||
}>()
|
||||
|
||||
defineEmits<{ selectTrace: [traceId: number] }>()
|
||||
|
||||
export interface SwimlaneSegment {
|
||||
trace_id: number
|
||||
start: number
|
||||
end: number
|
||||
face_count: number
|
||||
}
|
||||
|
||||
export interface SwimlaneIdentity {
|
||||
name: string
|
||||
color: string
|
||||
segments: SwimlaneSegment[]
|
||||
}
|
||||
|
||||
const rowH = 28
|
||||
const labelW = 80
|
||||
const padR = 20
|
||||
|
||||
const svgW = computed(() => {
|
||||
const dur = props.totalDuration || 6000
|
||||
return Math.max(500, labelW + dur / 8)
|
||||
})
|
||||
|
||||
function xPos(sec: number): number {
|
||||
const dur = props.totalDuration || 6000
|
||||
return labelW + (sec / dur) * (svgW.value - labelW - padR)
|
||||
}
|
||||
|
||||
const ticks = computed(() => {
|
||||
const dur = props.totalDuration || 6000
|
||||
const step = Math.max(30, Math.round(dur / 6 / 30) * 30)
|
||||
const tks: number[] = []
|
||||
for (let t = 0; t <= dur; t += step) tks.push(t)
|
||||
return tks
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user