2025-10-29 10:22:14 +08:00
|
|
|
<script setup lang="ts">
|
|
|
|
|
import type { IExecuteRawResponse } from '@/api'
|
|
|
|
|
import { computed } from 'vue'
|
|
|
|
|
import MarkdownIt from 'markdown-it'
|
|
|
|
|
import DOMPurify from 'dompurify'
|
|
|
|
|
import Iod from './Iod.vue'
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
executePlans: IExecuteRawResponse[]
|
|
|
|
|
nodeId?: string
|
|
|
|
|
actionId?: string
|
|
|
|
|
}>()
|
|
|
|
|
|
|
|
|
|
const md = new MarkdownIt({
|
|
|
|
|
html: true,
|
|
|
|
|
linkify: true,
|
|
|
|
|
typographer: true,
|
|
|
|
|
})
|
|
|
|
|
|
2025-10-31 18:42:31 +08:00
|
|
|
function sanitize(str?: string) {
|
|
|
|
|
if (!str) {
|
|
|
|
|
return ''
|
|
|
|
|
}
|
|
|
|
|
const html = md.render(str)
|
|
|
|
|
return DOMPurify.sanitize(html)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface Data {
|
|
|
|
|
Description: string
|
|
|
|
|
Content: string
|
|
|
|
|
LogNodeType: string
|
|
|
|
|
}
|
|
|
|
|
const data = computed<Data | null>(() => {
|
2025-10-29 10:22:14 +08:00
|
|
|
for (const result of props.executePlans) {
|
2025-10-31 18:42:31 +08:00
|
|
|
if (result.NodeId === props.nodeId) {
|
|
|
|
|
// LogNodeType 为 object直接渲染Content
|
|
|
|
|
if (result.LogNodeType === 'object') {
|
|
|
|
|
return {
|
|
|
|
|
Description: props.nodeId,
|
|
|
|
|
Content: sanitize(result.content),
|
|
|
|
|
LogNodeType: result.LogNodeType,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!result.ActionHistory) {
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-29 10:22:14 +08:00
|
|
|
for (const action of result.ActionHistory) {
|
|
|
|
|
if (action.ID === props.actionId) {
|
2025-10-31 18:42:31 +08:00
|
|
|
return {
|
|
|
|
|
Description: action.Description,
|
|
|
|
|
Content: sanitize(action.Action_Result),
|
|
|
|
|
LogNodeType: result.LogNodeType,
|
|
|
|
|
}
|
2025-10-29 10:22:14 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div v-if="data" class="card-item w-full pl-[56px] pr-[41px]">
|
|
|
|
|
<!-- 分割线 -->
|
2025-10-31 18:42:31 +08:00
|
|
|
<div v-if="data.LogNodeType !== 'object'" class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
|
|
|
|
<div
|
|
|
|
|
v-if="data.Description"
|
|
|
|
|
class="text-[16px] flex items-center gap-1 text-[var(--color-text-secondary)] mb-1"
|
|
|
|
|
>
|
2025-10-29 10:22:14 +08:00
|
|
|
{{ data.Description }}
|
2025-10-31 18:42:31 +08:00
|
|
|
<Iod v-if="data.LogNodeType !== 'object'"/>
|
2025-10-29 10:22:14 +08:00
|
|
|
</div>
|
2025-10-31 18:42:31 +08:00
|
|
|
<div class="rounded-[8px] p-[15px] text-[14px] bg-[var(--color-bg-quaternary)]">
|
|
|
|
|
<div
|
|
|
|
|
class="markdown-content max-h-[240px] overflow-y-auto max-w-full"
|
|
|
|
|
v-html="data.Content"
|
|
|
|
|
></div>
|
2025-10-29 10:22:14 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.card-item + .card-item {
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
}
|
2025-10-31 18:42:31 +08:00
|
|
|
.markdown-content {
|
|
|
|
|
:deep(code) {
|
|
|
|
|
display: block;
|
|
|
|
|
width: 100px;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(pre) {
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-29 10:22:14 +08:00
|
|
|
</style>
|