index.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <template>
  2. <div class="flex w-full h-full overflow-hidden">
  3. <div class="flex-1 flex flex-col">
  4. <div
  5. class="h-32px shrink-0 px-12px flex items-center justify-between border border-solid border-gray-200"
  6. @click="onClick"
  7. >
  8. <span class="text-12px">日志</span>
  9. <IconButton :icon="open ? 'lucide:chevron-down' : 'lucide:chevron-up'" link></IconButton>
  10. </div>
  11. <div class="flex-1 text-12px p-12px overflow-auto">
  12. <div v-if="executions.length === 0" class="text-gray-400">
  13. 暂无运行日志,点击运行节点后查看。
  14. </div>
  15. <el-table v-else :data="executions" row-key="runnerKey" size="small" border class="w-full">
  16. <el-table-column type="expand" width="48">
  17. <template #default="scope">
  18. <div class="p-8px">
  19. <el-table
  20. :data="scope.row.nodes"
  21. row-key="nodeId"
  22. size="small"
  23. border
  24. class="w-full"
  25. >
  26. <el-table-column prop="nodeName" label="节点名称" min-width="160" />
  27. <el-table-column prop="nodeType" label="类型" width="120" />
  28. <el-table-column label="状态" width="100">
  29. <template #default="{ row }">
  30. <el-tag :type="statusTagType(row.status)" size="small">
  31. {{ statusText(row.status) }}
  32. </el-tag>
  33. </template>
  34. </el-table-column>
  35. <el-table-column prop="lastUpdateTime" label="最后时间" width="180" />
  36. <el-table-column label="详情" min-width="260">
  37. <template #default="{ row }">
  38. <el-tabs type="border-card" class="w-full">
  39. <el-tab-pane label="输入">
  40. <pre
  41. class="bg-#f7f7f7 rounded p-6px whitespace-pre-wrap break-all max-h-160px overflow-auto"
  42. >{{ formatJson(row.track?.input_variable) }}
  43. </pre
  44. >
  45. </el-tab-pane>
  46. <el-tab-pane label="输出">
  47. <pre
  48. class="bg-#f7f7f7 rounded p-6px whitespace-pre-wrap break-all max-h-160px overflow-auto"
  49. >{{ formatJson(row.track?.output_variable) }}
  50. </pre
  51. >
  52. </el-tab-pane>
  53. </el-tabs>
  54. </template>
  55. </el-table-column>
  56. </el-table>
  57. </div>
  58. </template>
  59. </el-table-column>
  60. <el-table-column type="index" label="#" width="48" />
  61. <el-table-column prop="runnerKey" label="运行ID" min-width="220" />
  62. <el-table-column label="状态" width="100">
  63. <template #default="{ row }">
  64. <el-tag :type="statusTagType(row.status)" size="small">
  65. {{ statusText(row.status) }}
  66. </el-tag>
  67. </template>
  68. </el-table-column>
  69. <el-table-column prop="startedAt" label="开始时间" width="180" />
  70. <el-table-column prop="finishedAt" label="结束时间" width="180" />
  71. <el-table-column label="节点数" width="80">
  72. <template #default="{ row }">
  73. {{ row.nodes?.length || 0 }}
  74. </template>
  75. </el-table-column>
  76. </el-table>
  77. </div>
  78. </div>
  79. </div>
  80. </template>
  81. <script setup lang="ts">
  82. import { computed, ref } from 'vue'
  83. import { IconButton } from '@repo/ui'
  84. import { useRunnerStore, type NodeStatus, type RunnerStatus } from '@/store/modules/runner.store'
  85. const emit = defineEmits<{
  86. toggle: [open: boolean]
  87. }>()
  88. const open = ref(false)
  89. const runnerStore = useRunnerStore()
  90. const executions = computed(() => runnerStore.executions)
  91. const onClick = () => {
  92. open.value = !open.value
  93. emit('toggle', open.value)
  94. }
  95. const formatJson = (value: unknown) => {
  96. if (value === null || value === undefined) return '-'
  97. try {
  98. return JSON.stringify(value, null, 2)
  99. } catch {
  100. return String(value)
  101. }
  102. }
  103. const statusText = (status: NodeStatus | RunnerStatus) => {
  104. if (status === 'running') return '运行中'
  105. if (status === 'success') return '运行成功'
  106. if (status === 'finished') return '运行完成'
  107. if (status === 'failed') return '运行失败'
  108. if (status === 'error') return '运行异常'
  109. return '就绪'
  110. }
  111. const statusTagType = (
  112. status: NodeStatus | RunnerStatus
  113. ): 'info' | 'success' | 'warning' | 'danger' => {
  114. if (status === 'running') return 'warning'
  115. if (status === 'success' || status === 'finished') return 'success'
  116. if (status === 'failed' || status === 'error') return 'danger'
  117. return 'info'
  118. }
  119. </script>