ForcePilot/web/src/components/RefsComponent.vue

186 lines
4.5 KiB
Vue
Raw Normal View History

2024-08-25 20:29:24 +08:00
<template>
<div class="refs" v-if="showRefs">
<div class="tags">
<span class="item btn" @click="likeThisResponse(msg)"><LikeOutlined /></span>
<span class="item btn" @click="dislikeThisResponse(msg)"><DislikeOutlined /></span>
<span v-if="showKey('model') && getModelName(msg)" class="item" @click="console.log(msg)">
<BulbOutlined /> {{ getModelName(msg) }}
2025-05-09 23:48:17 +08:00
</span>
2024-09-18 21:03:12 +08:00
<span
2025-04-02 13:00:25 +08:00
v-if="showKey('copy')"
class="item btn" @click="copyText(msg.content)" title="复制"><CopyOutlined /></span>
<span
v-if="showKey('regenerate')"
class="item btn" @click="regenerateMessage()" title="重新生成"><ReloadOutlined /></span>
<span
2025-04-27 18:59:38 +08:00
v-if="isLatestMessage && showKey('subGraph') && hasSubGraphData(msg)"
2024-09-18 21:03:12 +08:00
class="item btn"
2025-04-27 18:59:38 +08:00
@click="openGlobalRefs('graph')"
2024-09-18 21:03:12 +08:00
>
2025-02-24 22:56:13 +08:00
<DeploymentUnitOutlined /> 关系图
2024-09-18 21:03:12 +08:00
</span>
<span
class="item btn"
2025-04-27 18:59:38 +08:00
v-if="isLatestMessage && showKey('webSearch') && msg.refs?.web_search.results.length > 0"
@click="openGlobalRefs('webSearch')"
>
<GlobalOutlined /> 网页搜索 {{ msg.refs.web_search?.results.length }}
</span>
2025-04-27 18:59:38 +08:00
<span
class="item btn"
v-if="isLatestMessage && showKey('knowledgeBase') && hasKnowledgeBaseData(msg)"
@click="openGlobalRefs('knowledgeBase')"
2024-08-25 20:29:24 +08:00
>
2025-04-27 18:59:38 +08:00
<FileTextOutlined /> 知识库
2024-08-25 20:29:24 +08:00
</span>
</div>
</div>
</template>
<script setup>
2025-04-27 18:59:38 +08:00
import { ref, computed } from 'vue'
2024-09-18 21:03:12 +08:00
import { useClipboard } from '@vueuse/core'
import { message } from 'ant-design-vue'
2024-08-25 20:29:24 +08:00
import {
GlobalOutlined,
FileTextOutlined,
2024-09-18 21:03:12 +08:00
CopyOutlined,
2025-02-24 22:56:13 +08:00
DeploymentUnitOutlined,
BulbOutlined,
ReloadOutlined,
LikeOutlined,
DislikeOutlined,
2024-08-25 20:29:24 +08:00
} from '@ant-design/icons-vue'
2025-04-27 18:59:38 +08:00
const emit = defineEmits(['retry', 'openRefs']);
2024-08-25 20:29:24 +08:00
const props = defineProps({
message: Object,
2025-04-02 13:00:25 +08:00
showRefs: {
type: [Array, Boolean],
default: () => false
2025-04-27 18:59:38 +08:00
},
isLatestMessage: {
type: Boolean,
default: false
2025-04-02 13:00:25 +08:00
}
2024-08-25 20:29:24 +08:00
})
2024-09-18 21:03:12 +08:00
const msg = ref(props.message)
// 使用 useClipboard 实现复制功能
const { copy, isSupported } = useClipboard()
2025-04-02 13:00:25 +08:00
const showKey = (key) => {
if (props.showRefs === true) {
return true
}
return props.showRefs.includes(key)
}
2024-09-18 21:03:12 +08:00
// 定义 copy 方法
const copyText = async (text) => {
if (isSupported) {
try {
await copy(text)
message.success('文本已复制到剪贴板')
} catch (error) {
console.error('复制失败:', error)
message.error('复制失败,请手动复制')
}
} else {
console.warn('浏览器不支持自动复制')
message.warning('浏览器不支持自动复制,请手动复制')
}
}
const showRefs = computed(() => {
// 如果只是为了显示模型信息,不需要检查状态
if (props.showRefs && Array.isArray(props.showRefs) && props.showRefs.includes('model')) {
return true;
}
// 原有的逻辑
return (msg.value.role=='received' || msg.value.role=='assistant') && msg.value.status=='finished';
})
2024-09-18 21:03:12 +08:00
2025-04-27 18:59:38 +08:00
// 打开全局refs抽屉
const openGlobalRefs = (type) => {
emit('openRefs', {
type,
refs: msg.value.refs
})
}
2024-09-18 21:03:12 +08:00
const hasSubGraphData = (msg) => {
return msg.refs &&
msg.refs.graph_base &&
msg.refs.graph_base.results.nodes.length > 0;
}
2025-04-27 18:59:38 +08:00
const hasKnowledgeBaseData = (msg) => {
return msg.refs &&
msg.refs.knowledge_base &&
msg.refs.knowledge_base.results.length > 0;
2024-09-18 21:03:12 +08:00
}
// 添加重新生成方法
2025-03-30 20:46:26 +08:00
const regenerateMessage = () => {
emit('retry')
}
// 获取模型名称
const getModelName = (msg) => {
// 优先检查 response_metadata.model_name
if (msg.response_metadata?.model_name) {
return msg.response_metadata.model_name;
}
// 兼容旧格式 meta.server_model_name
if (msg.meta?.server_model_name) {
return msg.meta.server_model_name;
}
return null;
}
const likeThisResponse = (msg) => {
console.log(msg)
}
const dislikeThisResponse = (msg) => {
console.log(msg)
}
2024-08-25 20:29:24 +08:00
</script>
<style lang="less" scoped>
.refs {
display: flex;
margin-bottom: 20px;
margin-top: 10px;
2024-09-28 00:41:02 +08:00
color: var(--gray-500);
2025-02-23 16:38:56 +08:00
font-size: 13px;
2024-08-25 20:29:24 +08:00
gap: 10px;
.item {
background: var(--gray-50);
2025-02-23 16:38:56 +08:00
color: var(--gray-700);
2024-08-25 20:29:24 +08:00
padding: 2px 8px;
border-radius: 8px;
2025-02-23 16:38:56 +08:00
font-size: 13px;
2024-09-28 00:41:02 +08:00
user-select: none;
2024-09-18 21:03:12 +08:00
&.btn {
cursor: pointer;
&:hover {
background: var(--gray-100);
2024-09-18 21:03:12 +08:00
}
&:active {
background: var(--gray-200);
2024-09-18 21:03:12 +08:00
}
}
2024-08-25 20:29:24 +08:00
}
.tags {
display: flex;
2024-09-06 12:54:17 +08:00
flex-wrap: wrap;
2024-08-25 20:29:24 +08:00
gap: 10px;
}
}
2024-09-18 21:03:12 +08:00
</style>