Files
QuestionProject/ai_knowledge_base_v2/apps/admin-web/src/components/AiLogDetailDrawer.vue

126 lines
4.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ElMessage } from "element-plus";
import { ref, watch } from "vue";
import { api } from "../services/api";
import type { AiLogRecord } from "../types/api";
const props = defineProps<{ modelValue: boolean; logId: number | null }>();
const emit = defineEmits<{ "update:modelValue": [value: boolean] }>();
const detail = ref<AiLogRecord | null>(null);
const loading = ref(false);
watch(
() => [props.modelValue, props.logId] as const,
async ([open, logId]) => {
if (!open || !logId) return;
detail.value = null;
loading.value = true;
try {
detail.value = await api.aiLogDetail(logId);
} catch (error) {
ElMessage.error(
error instanceof Error ? error.message : "AI 请求详情加载失败",
);
} finally {
loading.value = false;
}
},
);
function formatMoney(value?: number | null, currency = "CNY") {
if (typeof value !== "number") return "-";
return `${currency || "CNY"} ${value.toFixed(6)}`;
}
</script>
<template>
<el-drawer
:model-value="modelValue"
size="820px"
title="AI 请求详情"
@update:model-value="emit('update:modelValue', $event)"
>
<div v-loading="loading">
<template v-if="detail">
<section class="chat-summary">
<div>
<span>请求ID</span><strong>{{ detail.id }}</strong>
</div>
<div>
<span>会话ID</span><strong>{{ detail.sessionId || "-" }}</strong>
</div>
<div>
<span>消息ID</span><strong>{{ detail.messageId || "-" }}</strong>
</div>
<div>
<span>用户ID</span><strong>{{ detail.userId || "-" }}</strong>
</div>
<div>
<span>模型</span><strong>{{ detail.modelName || "-" }}</strong>
</div>
<div>
<span>状态</span><strong>{{ detail.status }}</strong>
</div>
</section>
<section class="audit-detail-grid">
<span>知识库{{ detail.knowledgeIds || "-" }}</span
><span>命中数{{ detail.retrieveCount }}</span
><span>片段数{{ detail.retrievedChunks?.length || 0 }}</span
><span>输入 Token{{ detail.inputToken || "-" }}</span
><span>输出 Token{{ detail.outputToken || "-" }}</span
><span> Token{{ detail.totalToken || "-" }}</span
><span
>估算成本{{
formatMoney(detail.estimatedCost, detail.currency || "CNY")
}}</span
><span>问题类型{{ detail.questionType || "-" }}</span
><span>知识命中{{ detail.knowledgeHit ? "是" : "否" }}</span
><span>路由原因{{ detail.routeReason || "-" }}</span
><span>耗时{{ detail.costMs || "-" }}ms</span
><span>时间{{ detail.createdAt }}</span>
</section>
<p v-if="detail.errorMessage" class="error-text">
{{ detail.errorMessage }}
</p>
<h3 class="detail-title">召回知识片段</h3>
<section v-if="detail.retrievedChunks?.length" class="retrieval-chunks">
<article
v-for="chunk in detail.retrievedChunks"
:key="`${detail.id}-${chunk.index}`"
class="retrieval-chunk"
>
<div class="chunk-head">
<strong
>片段 {{ chunk.index }}/{{
detail.retrievedChunks.length
}}</strong
><span>{{ chunk.knowledgeName || "未知知识库" }}</span
><span v-if="chunk.knowledgeId"
>知识库ID{{ chunk.knowledgeId }}</span
>
</div>
<div class="chunk-title">{{ chunk.title || "未命名片段" }}</div>
<pre>{{ chunk.content }}</pre>
<a
v-if="chunk.sourceUrl"
:href="chunk.sourceUrl"
target="_blank"
rel="noreferrer"
>查看来源</a
>
</article>
</section>
<el-empty
v-else
description="本条请求未保存召回片段"
:image-size="72"
/>
<h3 class="detail-title">完整 Prompt</h3>
<pre class="prompt-preview">{{
detail.prompt || "无 Prompt 记录"
}}</pre>
</template>
</div>
</el-drawer>
</template>