<template>
  <div class="execution-detail">
    <el-container>
      <el-header>
        <div class="header-content">
          <h1>执行详情</h1>
          <div class="header-actions">
            <el-button @click="handleBack">返回</el-button>
          </div>
        </div>
      </el-header>
      <el-main v-loading="executionStore.loading">
        <el-card v-if="executionStore.currentExecution">
          <template #header>
            <div class="card-header">
              <span>执行信息</span>
              <el-tag :type="getStatusType(executionStore.currentExecution.status)">
                {{ getStatusText(executionStore.currentExecution.status) }}
              </el-tag>
            </div>
          </template>
          
          <el-descriptions :column="2" border>
            <el-descriptions-item label="执行ID">
              {{ executionStore.currentExecution.id }}
            </el-descriptions-item>
            <el-descriptions-item label="工作流ID">
              <span v-if="executionStore.currentExecution.workflow_id">
                <el-link 
                  type="primary" 
                  @click="handleViewWorkflow(executionStore.currentExecution.workflow_id!)"
                >
                  {{ executionStore.currentExecution.workflow_id }}
                </el-link>
              </span>
              <span v-else>-</span>
            </el-descriptions-item>
            <el-descriptions-item label="状态">
              <div style="display: flex; align-items: center; gap: 8px;">
                <el-tag :type="getStatusType(executionStore.currentExecution.status)">
                  {{ getStatusText(executionStore.currentExecution.status) }}
                </el-tag>
                <el-tag 
                  v-if="wsConnected" 
                  type="success" 
                  size="small"
                >
                  <el-icon><Connection /></el-icon>
                  实时连接
                </el-tag>
              </div>
            </el-descriptions-item>
            <el-descriptions-item label="执行时间">
              <span v-if="executionStore.currentExecution.execution_time">
                {{ formatTime(executionStore.currentExecution.execution_time) }}
              </span>
              <span v-else>-</span>
            </el-descriptions-item>
            <el-descriptions-item 
              v-if="(executionStore.currentExecution.status === 'running' || executionStore.currentExecution.status === 'pending') && wsProgress > 0"
              label="执行进度"
              :span="2"
            >
              <el-progress :percentage="wsProgress" :status="executionStore.currentExecution.status === 'running' ? undefined : 'success'" />
            </el-descriptions-item>
            <el-descriptions-item label="创建时间" :span="2">
              {{ formatDate(executionStore.currentExecution.created_at) }}
            </el-descriptions-item>
            <el-descriptions-item 
              v-if="executionStore.currentExecution.error_message || wsError" 
              label="错误信息" 
              :span="2"
            >
              <el-alert
                :title="executionStore.currentExecution.error_message || wsError || '未知错误'"
                type="error"
                :closable="false"
              />
            </el-descriptions-item>
          </el-descriptions>
        </el-card>

        <el-card class="data-card" style="margin-top: 20px">
          <template #header>
            <span>输入数据</span>
          </template>
          <div class="json-viewer">
            <el-tabs v-model="activeTab">
              <el-tab-pane label="树形视图" name="tree">
                <div class="json-tree-viewer">
                  <JsonTreeView :data="executionStore.currentExecution?.input_data || {}" :level="0" />
                </div>
              </el-tab-pane>
              <el-tab-pane label="JSON视图" name="json">
                <pre>{{ formatJSON(executionStore.currentExecution?.input_data) }}</pre>
              </el-tab-pane>
            </el-tabs>
          </div>
        </el-card>

        <el-card 
          v-if="executionStore.currentExecution?.output_data || wsResult" 
          class="data-card" 
          style="margin-top: 20px"
        >
          <template #header>
            <span>输出数据</span>
          </template>
          <div class="json-viewer">
            <el-tabs v-model="activeTab">
              <el-tab-pane label="树形视图" name="tree">
                <div class="json-tree-viewer">
                  <JsonTreeView :data="executionStore.currentExecution?.output_data || wsResult || {}" :level="0" />
                </div>
              </el-tab-pane>
              <el-tab-pane label="JSON视图" name="json">
                <pre>{{ formatJSON(executionStore.currentExecution?.output_data || wsResult) }}</pre>
              </el-tab-pane>
            </el-tabs>
          </div>
        </el-card>

        <el-card 
          v-else-if="executionStore.currentExecution?.status === 'running' || executionStore.currentExecution?.status === 'pending'"
          class="data-card" 
          style="margin-top: 20px"
        >
          <template #header>
            <div style="display: flex; justify-content: space-between; align-items: center;">
              <span>输出数据</span>
              <el-tag v-if="wsConnected" type="success" size="small">
                <el-icon><Connection /></el-icon>
                实时更新中
              </el-tag>
            </div>
          </template>
          <div class="loading-state">
            <el-icon class="is-loading"><Loading /></el-icon>
            <span>执行中，请稍候...</span>
            <div v-if="wsProgress > 0" style="margin-top: 10px; width: 100%;">
              <el-progress :percentage="wsProgress" />
            </div>
          </div>
        </el-card>

        <!-- 执行性能分析卡片 -->
        <el-card v-if="performanceData" class="data-card" style="margin-top: 20px">
          <template #header>
            <span>执行性能分析</span>
          </template>
          
          <div class="performance-analysis">
            <!-- 总执行时间 -->
            <div class="performance-summary">
              <div class="summary-title">总执行时间</div>
              <div class="summary-value">
                {{ formatTime(performanceData.total_execution_time) }}
              </div>
            </div>

            <!-- 节点执行时间对比（柱状图） -->
            <div v-if="performanceData.node_performance && performanceData.node_performance.length > 0" class="performance-chart">
              <h4>节点执行时间对比</h4>
              <div class="bar-chart">
                <div 
                  v-for="node in sortedNodePerformance" 
                  :key="node.node_id"
                  class="bar-item"
                >
                  <div class="bar-label">
                    <span class="node-id">{{ node.node_id }}</span>
                    <span class="node-type">{{ node.node_type }}</span>
                    <span class="node-duration">{{ formatTime(node.total_duration) }}</span>
                  </div>
                  <div class="bar-container">
                    <div 
                      class="bar-fill" 
                      :style="{ width: `${(node.total_duration / maxNodeDuration) * 100}%` }"
                    ></div>
                  </div>
                  <div class="bar-stats">
                    <span>平均: {{ formatTime(node.avg_duration) }}</span>
                    <span>最大: {{ formatTime(node.max_duration) }}</span>
                    <span>执行次数: {{ node.execution_count }}</span>
                  </div>
                </div>
              </div>
            </div>

            <!-- 节点类型性能统计 -->
            <div v-if="performanceData.type_performance && performanceData.type_performance.length > 0" class="performance-chart">
              <h4>节点类型性能统计</h4>
              <div class="type-stats">
                <el-table :data="performanceData.type_performance" size="small" border>
                  <el-table-column prop="node_type" label="节点类型" width="150" />
                  <el-table-column prop="total_duration" label="总耗时" width="120">
                    <template #default="{ row }">
                      {{ formatTime(row.total_duration) }}
                    </template>
                  </el-table-column>
                  <el-table-column prop="avg_duration" label="平均耗时" width="120">
                    <template #default="{ row }">
                      {{ formatTime(row.avg_duration) }}
                    </template>
                  </el-table-column>
                  <el-table-column prop="execution_count" label="执行次数" width="100" />
                  <el-table-column label="占比" width="150">
                    <template #default="{ row }">
                      <el-progress 
                        :percentage="(row.total_duration / performanceData.total_execution_time) * 100"
                        :format="(percentage) => `${percentage.toFixed(1)}%`"
                      />
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </div>

            <!-- 执行时间线 -->
            <div v-if="performanceData.timeline && performanceData.timeline.length > 0" class="performance-chart">
              <h4>执行时间线</h4>
              <div class="timeline-view">
                <el-timeline>
                  <el-timeline-item
                    v-for="(item, index) in performanceData.timeline.slice(0, 20)"
                    :key="index"
                    :timestamp="formatLogTime(item.timestamp)"
                    placement="top"
                  >
                    <el-card>
                      <div class="timeline-item">
                        <div class="timeline-header">
                          <el-tag size="small">{{ item.node_type }}</el-tag>
                          <span class="timeline-node-id">{{ item.node_id }}</span>
                          <span class="timeline-duration">{{ formatTime(item.duration) }}</span>
                        </div>
                        <div class="timeline-message">{{ item.message }}</div>
                      </div>
                    </el-card>
                  </el-timeline-item>
                </el-timeline>
              </div>
            </div>
          </div>
        </el-card>

        <!-- 执行日志卡片 -->
        <el-card class="data-card" style="margin-top: 20px">
          <template #header>
            <div style="display: flex; justify-content: space-between; align-items: center;">
              <span>执行日志</span>
              <div style="display: flex; gap: 10px; align-items: center;">
                <el-select 
                  v-model="logFilter.level" 
                  placeholder="日志级别" 
                  size="small" 
                  style="width: 120px"
                  @change="loadLogs"
                >
                  <el-option label="全部" value="" />
                  <el-option label="INFO" value="INFO" />
                  <el-option label="WARN" value="WARN" />
                  <el-option label="ERROR" value="ERROR" />
                  <el-option label="DEBUG" value="DEBUG" />
                </el-select>
                <el-select 
                  v-model="logFilter.node_id" 
                  placeholder="节点筛选" 
                  size="small" 
                  style="width: 150px"
                  @change="loadLogs"
                >
                  <el-option label="全部节点" value="" />
                  <el-option 
                    v-for="node in nodeList" 
                    :key="node.id" 
                    :label="node.label || node.id" 
                    :value="node.id" 
                  />
                </el-select>
                <el-button size="small" @click="loadLogs">
                  <el-icon><Refresh /></el-icon>
                  刷新
                </el-button>
                <el-button 
                  size="small" 
                  :type="autoRefresh ? 'primary' : 'default'"
                  @click="toggleAutoRefresh"
                >
                  <el-icon><VideoPlay v-if="!autoRefresh" /><VideoPause v-else /></el-icon>
                  {{ autoRefresh ? '停止' : '自动刷新' }}
                </el-button>
              </div>
            </div>
          </template>
          
          <!-- 日志统计 -->
          <div v-if="logSummary" class="log-summary">
            <el-tag type="info">总计: {{ logSummary.total_logs || 0 }}</el-tag>
            <el-tag type="success">INFO: {{ logSummary.level_stats?.INFO || 0 }}</el-tag>
            <el-tag type="warning">WARN: {{ logSummary.level_stats?.WARN || 0 }}</el-tag>
            <el-tag type="danger">ERROR: {{ logSummary.level_stats?.ERROR || 0 }}</el-tag>
            <el-tag v-if="logSummary.level_stats?.DEBUG">DEBUG: {{ logSummary.level_stats.DEBUG }}</el-tag>
          </div>

          <!-- 日志列表 -->
          <div class="log-viewer" ref="logViewerRef">
            <div 
              v-for="log in logs" 
              :key="log.id" 
              :class="['log-item', `log-${log.level.toLowerCase()}`]"
            >
              <div class="log-header">
                <span class="log-time">{{ formatLogTime(log.timestamp) }}</span>
                <el-tag :type="getLogLevelType(log.level)" size="small">{{ log.level }}</el-tag>
                <span v-if="log.node_id" class="log-node">
                  <el-icon><Connection /></el-icon>
                  {{ log.node_id }}
                </span>
                <span v-if="log.node_type" class="log-node-type">{{ log.node_type }}</span>
                <span v-if="log.duration" class="log-duration">{{ formatTime(log.duration) }}</span>
              </div>
              <div class="log-message">{{ log.message }}</div>
              <div v-if="log.data" class="log-data">
                <el-collapse>
                  <el-collapse-item title="查看详情" :name="log.id">
                    <pre>{{ formatJSON(log.data) }}</pre>
                  </el-collapse-item>
                </el-collapse>
              </div>
            </div>
            <div v-if="logs.length === 0" class="log-empty">
              <el-empty description="暂无日志" :image-size="80" />
            </div>
          </div>
        </el-card>
      </el-main>
    </el-container>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, h, defineComponent, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useExecutionStore } from '@/stores/execution'
import { ElMessage } from 'element-plus'
import { Loading, Connection, ArrowDown, ArrowRight, Refresh, VideoPlay, VideoPause } from '@element-plus/icons-vue'
import { useWebSocket } from '@/composables/useWebSocket'
import api from '@/api'

const activeTab = ref('tree')
const logs = ref<any[]>([])
const logSummary = ref<any>(null)
const performanceData = ref<any>(null)
const logViewerRef = ref<HTMLElement>()
const autoRefresh = ref(false)
const autoRefreshTimer = ref<number | null>(null)
const logFilter = ref({
  level: '',
  node_id: ''
})
const nodeList = ref<any[]>([])

const router = useRouter()
const route = useRoute()
const executionStore = useExecutionStore()

const executionId = route.params.id as string

// 使用WebSocket实时更新
const {
  status: wsStatus,
  progress: wsProgress,
  result: wsResult,
  error: wsError,
  executionTime: wsExecutionTime,
  connected: wsConnected,
  connect: wsConnect,
  disconnect: wsDisconnect
} = useWebSocket(executionId)

onMounted(async () => {
  await loadExecution(executionId)
  
  // 如果执行还在进行中，建立WebSocket连接
  if (executionStore.currentExecution?.status === 'running' || 
      executionStore.currentExecution?.status === 'pending') {
    wsConnect()
  }
  
  // 加载执行日志
  await loadLogs()
  await loadLogSummary()
  await loadPerformanceData()
  
  // 如果执行还在进行中，自动刷新日志
  if (executionStore.currentExecution?.status === 'running' || 
      executionStore.currentExecution?.status === 'pending') {
    autoRefresh.value = true
    startAutoRefresh()
  }
})

onUnmounted(() => {
  stopAutoRefresh()
  wsDisconnect()
})

// 监听WebSocket状态变化，更新store
watch([wsStatus, wsResult, wsError, wsExecutionTime], () => {
  if (executionStore.currentExecution) {
    if (wsStatus.value) {
      executionStore.currentExecution.status = wsStatus.value
    }
    if (wsResult.value) {
      executionStore.currentExecution.output_data = wsResult.value
    }
    if (wsError.value) {
      executionStore.currentExecution.error_message = wsError.value
    }
    if (wsExecutionTime.value !== null) {
      executionStore.currentExecution.execution_time = wsExecutionTime.value
    }
  }
})

const loadExecution = async (id: string) => {
  try {
    await executionStore.fetchExecution(id)
  } catch (error: any) {
    ElMessage.error(error.response?.data?.detail || '获取执行详情失败')
  }
}

const handleBack = () => {
  router.push('/executions')
}

const handleViewWorkflow = (workflowId: string) => {
  router.push(`/workflow/${workflowId}`)
}

const getStatusType = (status: string) => {
  const map: Record<string, string> = {
    pending: 'info',
    running: 'warning',
    completed: 'success',
    failed: 'danger'
  }
  return map[status] || 'info'
}

const getStatusText = (status: string) => {
  const map: Record<string, string> = {
    pending: '等待中',
    running: '执行中',
    completed: '已完成',
    failed: '失败'
  }
  return map[status] || status
}

const formatTime = (ms: number) => {
  if (ms < 1000) {
    return `${ms}ms`
  } else if (ms < 60000) {
    return `${(ms / 1000).toFixed(2)}s`
  } else {
    return `${(ms / 60000).toFixed(2)}min`
  }
}

const formatDate = (dateStr: string) => {
  if (!dateStr) return '-'
  const date = new Date(dateStr)
  return date.toLocaleString('zh-CN')
}

// JSON树形展示组件（使用递归组件）
const JsonTreeView = defineComponent({
  name: 'JsonTreeView',
  props: {
    data: {
      type: [Object, Array, String, Number, Boolean, null],
      required: true
    },
    level: {
      type: Number,
      default: 0
    }
  },
  setup(props) {
    const isExpanded = ref(props.level < 2)
    
    const getType = (val: any) => {
      if (val === null) return 'null'
      if (Array.isArray(val)) return 'array'
      return typeof val
    }
    
    const formatValue = (val: any) => {
      if (val === null) return 'null'
      if (typeof val === 'string') return `"${val}"`
      if (typeof val === 'boolean') return val ? 'true' : 'false'
      return String(val)
    }
    
    const toggleExpand = () => {
      isExpanded.value = !isExpanded.value
    }
    
    return () => {
      const { data, level } = props
      const type = getType(data)
      
      if (type === 'object' || type === 'array') {
        return h('div', { class: 'json-tree-item', style: { paddingLeft: level * 20 + 'px' } }, [
          h('div', { class: 'json-tree-node', onClick: toggleExpand }, [
            h('span', { class: 'json-tree-toggle' }, [
              h(isExpanded.value ? ArrowDown : ArrowRight)
            ]),
            h('span', { class: 'json-tree-bracket' }, type === 'array' ? '[' : '{'),
            h('span', { class: 'json-tree-count' }, `${type === 'array' ? data.length : Object.keys(data).length} 项`)
          ]),
          isExpanded.value && h('div', { class: 'json-tree-children' }, [
            type === 'object' 
              ? Object.entries(data).map(([key, value]) => 
                  h('div', { key, class: 'json-tree-item' }, [
                    h('span', { class: 'json-tree-key' }, `"${key}": `),
                    h(JsonTreeView, { data: value, level: level + 1 })
                  ])
                )
              : data.map((item: any, index: number) =>
                  h('div', { key: index, class: 'json-tree-item' }, [
                    h('span', { class: 'json-tree-key' }, `[${index}]: `),
                    h(JsonTreeView, { data: item, level: level + 1 })
                  ])
                ),
            h('div', { class: 'json-tree-close' }, type === 'array' ? ']' : '}')
          ])
        ])
      } else {
        return h('div', { class: 'json-tree-item', style: { paddingLeft: level * 20 + 'px' } }, [
          h('div', { class: 'json-tree-value' }, [
            h('span', { class: 'json-tree-type' }, type),
            h('span', { class: 'json-tree-content' }, formatValue(data))
          ])
        ])
      }
    }
  }
})

const formatJSON = (data: any) => {
  if (!data) return '暂无数据'
  try {
    return JSON.stringify(data, null, 2)
  } catch {
    return String(data)
  }
}

// 加载执行日志
const loadLogs = async () => {
  try {
    const params: any = {
      skip: 0,
      limit: 1000
    }
    if (logFilter.value.level) {
      params.level = logFilter.value.level
    }
    if (logFilter.value.node_id) {
      params.node_id = logFilter.value.node_id
    }
    
    const response = await api.get(`/execution-logs/executions/${executionId}`, { params })
    logs.value = response.data || []
    
    // 自动滚动到底部
    await nextTick()
    scrollToBottom()
  } catch (error: any) {
    console.error('加载执行日志失败:', error)
  }
}

// 加载日志摘要
const loadLogSummary = async () => {
  try {
    const response = await api.get(`/execution-logs/executions/${executionId}/summary`)
    logSummary.value = response.data
    
    // 提取节点列表
    if (response.data.node_stats) {
      nodeList.value = response.data.node_stats.map((stat: any) => ({
        id: stat.node_id,
        label: `${stat.node_type || '节点'} (${stat.node_id})`
      }))
    }
  } catch (error: any) {
    console.error('加载日志摘要失败:', error)
  }
}

// 加载性能分析数据
const loadPerformanceData = async () => {
  try {
    const response = await api.get(`/execution-logs/executions/${executionId}/performance`)
    performanceData.value = response.data
  } catch (error: any) {
    console.error('加载性能分析数据失败:', error)
  }
}

// 计算属性：按执行时间排序的节点性能数据
const sortedNodePerformance = computed(() => {
  if (!performanceData.value?.node_performance) return []
  return [...performanceData.value.node_performance].sort((a: any, b: any) => 
    (b.total_duration || 0) - (a.total_duration || 0)
  )
})

// 计算属性：最大节点执行时间（用于柱状图比例）
const maxNodeDuration = computed(() => {
  if (!performanceData.value?.node_performance || performanceData.value.node_performance.length === 0) {
    return 1
  }
  return Math.max(...performanceData.value.node_performance.map((n: any) => n.total_duration || 0), 1)
})

// 格式化日志时间
const formatLogTime = (timestamp: string) => {
  if (!timestamp) return '-'
  const date = new Date(timestamp)
  return date.toLocaleString('zh-CN', { 
    year: 'numeric', 
    month: '2-digit', 
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    fractionalSecondDigits: 3
  })
}

// 获取日志级别类型
const getLogLevelType = (level: string) => {
  const map: Record<string, string> = {
    INFO: 'success',
    WARN: 'warning',
    ERROR: 'danger',
    DEBUG: 'info'
  }
  return map[level] || 'info'
}

// 自动刷新
const startAutoRefresh = () => {
  if (autoRefreshTimer.value) return
  autoRefreshTimer.value = window.setInterval(() => {
    if (autoRefresh.value) {
      loadLogs()
      loadLogSummary()
    }
  }, 2000) // 每2秒刷新一次
}

const stopAutoRefresh = () => {
  if (autoRefreshTimer.value) {
    clearInterval(autoRefreshTimer.value)
    autoRefreshTimer.value = null
  }
}

const toggleAutoRefresh = () => {
  autoRefresh.value = !autoRefresh.value
  if (autoRefresh.value) {
    startAutoRefresh()
  } else {
    stopAutoRefresh()
  }
}

// 滚动到底部
const scrollToBottom = () => {
  if (logViewerRef.value) {
    logViewerRef.value.scrollTop = logViewerRef.value.scrollHeight
  }
}

// 监听执行状态变化，自动开启/关闭自动刷新
watch(() => executionStore.currentExecution?.status, (newStatus) => {
  if (newStatus === 'running' || newStatus === 'pending') {
    if (!autoRefresh.value) {
      autoRefresh.value = true
      startAutoRefresh()
    }
  } else {
    if (autoRefresh.value) {
      autoRefresh.value = false
      stopAutoRefresh()
    }
  }
})
</script>

<style scoped>
.execution-detail {
  width: 100%;
  height: 100vh;
}

.el-header {
  background-color: #409eff;
  color: white;
  padding: 0 20px;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 100%;
}

.el-header h1 {
  margin: 0;
  font-size: 24px;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 15px;
}

.el-main {
  padding: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: bold;
  font-size: 18px;
}

.data-card {
  margin-top: 20px;
}

.json-viewer {
  background-color: #f5f5f5;
  padding: 15px;
  border-radius: 4px;
  overflow-x: auto;
}

.json-viewer pre {
  margin: 0;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
  color: #333;
}

.loading-state {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px;
  gap: 10px;
  color: #909399;
}

.json-tree-viewer {
  padding: 10px;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.8;
  min-height: 100px;
}

.json-tree-item {
  margin: 2px 0;
}

.json-tree-node {
  display: flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  user-select: none;
  padding: 2px 0;
}

.json-tree-node:hover {
  background-color: #f0f0f0;
  border-radius: 3px;
}

.json-tree-toggle {
  display: inline-flex;
  align-items: center;
  color: #409eff;
  width: 16px;
}

.json-tree-bracket {
  color: #909399;
  font-weight: bold;
}

.json-tree-count {
  color: #909399;
  font-size: 12px;
  margin-left: 5px;
}

.json-tree-key {
  color: #409eff;
  font-weight: 500;
}

.json-tree-value {
  display: inline;
}

.json-tree-type {
  color: #67c23a;
  font-size: 12px;
  margin-right: 5px;
  padding: 2px 6px;
  background: #f0f9ff;
  border-radius: 3px;
}

.json-tree-content {
  color: #333;
}

.json-tree-children {
  margin-left: 10px;
  border-left: 1px dashed #ddd;
  padding-left: 10px;
}

.json-tree-close {
  color: #909399;
  font-weight: bold;
  margin-left: 16px;
}

.log-summary {
  display: flex;
  gap: 10px;
  margin-bottom: 15px;
  padding: 10px;
  background: #f5f5f5;
  border-radius: 4px;
  flex-wrap: wrap;
}

.log-viewer {
  max-height: 600px;
  overflow-y: auto;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 10px;
  background: #fafafa;
}

.log-item {
  margin-bottom: 10px;
  padding: 10px;
  background: white;
  border-radius: 4px;
  border-left: 4px solid #ddd;
}

.log-item.log-info {
  border-left-color: #409eff;
}

.log-item.log-warn {
  border-left-color: #e6a23c;
}

.log-item.log-error {
  border-left-color: #f56c6c;
}

.log-item.log-debug {
  border-left-color: #909399;
}

.log-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 5px;
  font-size: 12px;
  color: #666;
}

.log-time {
  font-weight: 500;
  color: #333;
}

.log-node {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #409eff;
}

.log-node-type {
  color: #909399;
  font-size: 11px;
}

.log-duration {
  color: #67c23a;
  font-weight: 500;
}

.log-message {
  color: #333;
  line-height: 1.6;
  word-break: break-word;
}

.log-data {
  margin-top: 8px;
}

.log-data pre {
  margin: 0;
  padding: 8px;
  background: #f5f5f5;
  border-radius: 4px;
  font-size: 12px;
  overflow-x: auto;
}

.log-empty {
  text-align: center;
  padding: 40px;
  color: #909399;
}

/* 性能分析样式 */
.performance-analysis {
  padding: 20px 0;
}

.performance-summary {
  margin-bottom: 30px;
  padding: 20px;
  background: #f5f7fa;
  border-radius: 8px;
  text-align: center;
}

.summary-title {
  font-size: 14px;
  color: #909399;
  margin-bottom: 10px;
}

.summary-value {
  font-size: 32px;
  font-weight: 600;
  color: #409eff;
}

.performance-chart {
  margin-bottom: 30px;
}

.performance-chart h4 {
  margin: 0 0 15px 0;
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

/* 柱状图样式 */
.bar-chart {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.bar-item {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.bar-label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
}

.bar-label .node-id {
  font-weight: 600;
  color: #303133;
  min-width: 120px;
}

.bar-label .node-type {
  padding: 2px 8px;
  background: #e4e7ed;
  border-radius: 4px;
  font-size: 12px;
  color: #606266;
}

.bar-label .node-duration {
  margin-left: auto;
  font-weight: 600;
  color: #409eff;
}

.bar-container {
  width: 100%;
  height: 24px;
  background: #f0f2f5;
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}

.bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #409eff 0%, #66b1ff 100%);
  border-radius: 4px;
  transition: width 0.3s ease;
  min-width: 2px;
}

.bar-stats {
  display: flex;
  gap: 15px;
  font-size: 12px;
  color: #909399;
}

.bar-stats span {
  display: flex;
  align-items: center;
}

/* 类型统计表格样式 */
.type-stats {
  margin-top: 15px;
}

/* 时间线样式 */
.timeline-view {
  margin-top: 15px;
  max-height: 500px;
  overflow-y: auto;
}

.timeline-item {
  padding: 10px 0;
}

.timeline-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.timeline-node-id {
  font-weight: 600;
  color: #303133;
}

.timeline-duration {
  margin-left: auto;
  font-weight: 600;
  color: #409eff;
}

.timeline-message {
  font-size: 13px;
  color: #606266;
  margin-top: 5px;
}
</style>
