fix(v2): reviewer bugfixes — scroll, block-status, NaN guard, dead code cleanup
This commit is contained in:
@@ -15,6 +15,8 @@ import IrisChat from '../../components/dashboard/v2/IrisChat.vue'
|
||||
import type { ChatMessage } from '../../components/dashboard/v2/types'
|
||||
import TaskStrip from '../../components/dashboard/v2/TaskStrip.vue'
|
||||
import type { TaskItem } from '../../components/dashboard/v2/types'
|
||||
import AgentDetailModal from '../../components/dashboard/v2/AgentDetailModal.vue'
|
||||
import type { AgentDetail, ThinkingItem } from '../../components/dashboard/v2/types'
|
||||
import { mockAgents, extraAgentPool } from '../../composables/useFlowLayout'
|
||||
import type { AgentNodeData } from '../../composables/useFlowLayout'
|
||||
|
||||
@@ -25,8 +27,108 @@ const enteringIds = ref<string[]>([])
|
||||
|
||||
const agentPool = ref<AgentNodeData[]>(extraAgentPool)
|
||||
|
||||
/* ── Agent Detail Modal State ──────────────────────── */
|
||||
const selectedAgentId = ref<string | null>(null)
|
||||
const modalOpen = computed(() => selectedAgentId.value !== null)
|
||||
|
||||
const agentOrder = computed(() => agents.value.map(a => a.id))
|
||||
|
||||
const availableModels = [
|
||||
{ id: 'deepseek-v4-flash', alias: 'Deepseek V4 Flash' },
|
||||
{ id: 'deepseek-v4-pro', alias: 'Deepseek V4 Pro' },
|
||||
{ id: 'gpt-4o', alias: 'GPT-4o' },
|
||||
{ id: 'claude-35-sonnet', alias: 'Claude 3.5 Sonnet' },
|
||||
]
|
||||
|
||||
/**
|
||||
* Erzeugt simulierte Thinking-Items aus einem AgentNodeData.think-String.
|
||||
*/
|
||||
function buildThinkingItems(data: AgentNodeData): ThinkingItem[] {
|
||||
if (!data.think) return []
|
||||
|
||||
const now = new Date()
|
||||
const ts = (ago: number) => {
|
||||
const d = new Date(now.getTime() - ago * 1000)
|
||||
return d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' })
|
||||
}
|
||||
|
||||
// Aus dem think-String mehrere simulierte Items erzeugen
|
||||
const items: ThinkingItem[] = []
|
||||
const sentences = data.think.split(/[.…!?]+/).filter(s => s.trim().length > 5)
|
||||
|
||||
if (sentences.length >= 2) {
|
||||
items.push({ type: 'thought', text: sentences[0].trim() + '.', ts: ts(30) })
|
||||
items.push({ type: 'action', text: sentences[1].trim() + '…', ts: ts(18) })
|
||||
if (sentences.length >= 3) {
|
||||
items.push({ type: 'result', text: sentences[sentences.length - 1].trim() + '.', ts: ts(3) })
|
||||
} else {
|
||||
items.push({ type: 'result', text: 'Verarbeitung abgeschlossen.', ts: ts(3) })
|
||||
}
|
||||
} else if (sentences.length === 1) {
|
||||
items.push({ type: 'thought', text: sentences[0].trim(), ts: ts(15) })
|
||||
items.push({ type: 'action', text: 'Analysiere Daten und erstelle nächsten Schritt…', ts: ts(6) })
|
||||
} else {
|
||||
items.push({ type: 'thought', text: data.think, ts: ts(10) })
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
/**
|
||||
* Konvertiert AgentNodeData → AgentDetail für das Modal.
|
||||
*/
|
||||
function buildAgentDetail(data: AgentNodeData): AgentDetail {
|
||||
// Aus tokens/cost die numerischen Werte extrahieren
|
||||
const tokenNum = parseFloat(data.tokens?.replace(/[^0-9.]/g, '') || '0')
|
||||
const tokenMultiplier = data.tokens?.includes('M') ? 1_000_000 : data.tokens?.includes('k') ? 1_000 : 1
|
||||
const tokensToday = Math.round(tokenNum * tokenMultiplier)
|
||||
|
||||
const costNum = parseFloat(data.cost || '0')
|
||||
|
||||
const progress = data.progress || 0
|
||||
|
||||
return {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
role: data.role,
|
||||
model: data.model,
|
||||
status: data.status === 'block' ? 'idle' : data.status,
|
||||
tokensToday,
|
||||
costToday: costNum,
|
||||
workload: progress,
|
||||
uptime: data.elapsed || '—',
|
||||
lastActive: data.elapsed !== '—' ? 'Vor ' + data.elapsed : 'Nicht aktiv',
|
||||
activeTaskCount: data.task ? 1 : 0,
|
||||
thinking: buildThinkingItems(data),
|
||||
availableModels,
|
||||
}
|
||||
}
|
||||
|
||||
const selectedAgent = computed<AgentDetail | null>(() => {
|
||||
if (!selectedAgentId.value) return null
|
||||
const data = agents.value.find(a => a.id === selectedAgentId.value)
|
||||
if (!data) return null
|
||||
return buildAgentDetail(data)
|
||||
})
|
||||
|
||||
function handleSelect(id: string) {
|
||||
console.log('[FlowBoard] selected agent:', id)
|
||||
selectedAgentId.value = id
|
||||
}
|
||||
|
||||
function handleCloseModal() {
|
||||
selectedAgentId.value = null
|
||||
}
|
||||
|
||||
function handleAgentSelect(id: string) {
|
||||
// Zum nächsten/vorherigen Agenten springen (Pfeiltasten)
|
||||
selectedAgentId.value = id
|
||||
}
|
||||
|
||||
function handleChangeModel(agentId: string, modelId: string) {
|
||||
const agent = agents.value.find(a => a.id === agentId)
|
||||
if (agent) {
|
||||
agent.model = modelId
|
||||
}
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
@@ -62,8 +164,9 @@ const todayCost = computed(() => {
|
||||
})
|
||||
const todayTokens = computed(() => {
|
||||
const total = agents.value.reduce((s, a) => {
|
||||
const v = a.tokens?.replace(/[^0-9.]/g, '')
|
||||
return v ? s + parseFloat(v) : s
|
||||
const raw = a.tokens?.replace(/[^0-9.]/g, '') || '0'
|
||||
const v = parseFloat(raw)
|
||||
return Number.isFinite(v) ? s + v : s
|
||||
}, 0)
|
||||
return total >= 1000 ? Math.round(total / 1000) + 'k' : Math.round(total) + ''
|
||||
})
|
||||
@@ -213,6 +316,16 @@ const tasks = ref<TaskItem[]>([
|
||||
@send="handleChatSend"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Agent Detail Modal -->
|
||||
<AgentDetailModal
|
||||
v-if="modalOpen && selectedAgent"
|
||||
:agent="selectedAgent"
|
||||
:agent-order="agentOrder"
|
||||
@close="handleCloseModal"
|
||||
@select="handleAgentSelect"
|
||||
@change-model="handleChangeModel"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user