|
81 | 81 | </div> |
82 | 82 | <div class="chat-box" :class="{ 'wide-screen': meta.wideScreen, 'font-smaller': meta.fontSize === 'smaller', 'font-larger': meta.fontSize === 'larger' }"> |
83 | 83 | <MessageComponent |
84 | | - v-for="message in conv.messages" |
| 84 | + v-for="(message, index) in conv.messages" |
85 | 85 | :message="message" |
86 | 86 | :key="message.id" |
87 | 87 | :is-processing="isStreaming" |
88 | | - :show-refs="true" |
| 88 | + :show-refs="['copy', 'regenerate', 'subGraph', 'webSearch', 'knowledgeBase']" |
| 89 | + :is-latest-message="isLatestMessage(index)" |
89 | 90 | @retry="retryMessage(message.id)" |
90 | 91 | @retryStoppedMessage="retryStoppedMessage(message.id)" |
| 92 | + @openRefs="handleOpenRefs" |
91 | 93 | > |
92 | 94 | </MessageComponent> |
93 | 95 | </div> |
|
142 | 144 | <p class="note">请注意辨别内容的可靠性 By {{ configStore.config?.model_provider }}: {{ configStore.config?.model_name }}</p> |
143 | 145 | </div> |
144 | 146 | </div> |
| 147 | + <!-- 添加全局Refs侧边栏 --> |
| 148 | + <RefsSidebar |
| 149 | + ref="refsSidebarRef" |
| 150 | + :visible="refsSidebarVisible" |
| 151 | + :latestRefs="currentRefs" |
| 152 | + @update:visible="refsSidebarVisible = $event" |
| 153 | + /> |
145 | 154 | </div> |
146 | 155 | </template> |
147 | 156 |
|
@@ -178,6 +187,7 @@ import { useConfigStore } from '@/stores/config' |
178 | 187 | import { message } from 'ant-design-vue' |
179 | 188 | import MessageInputComponent from '@/components/MessageInputComponent.vue' |
180 | 189 | import MessageComponent from '@/components/MessageComponent.vue' |
| 190 | +import RefsSidebar from '@/components/RefsSidebar.vue' |
181 | 191 |
|
182 | 192 | const props = defineProps({ |
183 | 193 | conv: Object, |
@@ -222,6 +232,41 @@ const meta = reactive(JSON.parse(localStorage.getItem('meta')) || { |
222 | 232 | wideScreen: false, |
223 | 233 | }) |
224 | 234 |
|
| 235 | +// 添加全局refs状态 |
| 236 | +const refsSidebarVisible = ref(false) |
| 237 | +const currentRefs = ref({}) |
| 238 | +
|
| 239 | +// 处理打开refs侧边栏 |
| 240 | +const handleOpenRefs = ({ type, refs }) => { |
| 241 | + console.log('ChatComponent handleOpenRefs called with type:', type); |
| 242 | + console.log('Refs data structure:', JSON.stringify(refs)); |
| 243 | +
|
| 244 | + // 先更新引用数据,确保数据在设置标签页之前已更新 |
| 245 | + currentRefs.value = Object.assign({}, refs); |
| 246 | +
|
| 247 | + // 强制在下一个tick更新,确保数据已经被正确应用 |
| 248 | + nextTick(() => { |
| 249 | + // 显示抽屉 |
| 250 | + refsSidebarVisible.value = true; |
| 251 | +
|
| 252 | + // 再次检查引用是否正确 |
| 253 | + console.log('Updated refs data:', JSON.stringify(currentRefs.value)); |
| 254 | +
|
| 255 | + // 根据type自动选择标签页 |
| 256 | + if (refsSidebarRef.value) { |
| 257 | + console.log('Setting active tab to:', type); |
| 258 | + // 延迟50毫秒设置标签页,确保抽屉已打开 |
| 259 | + setTimeout(() => { |
| 260 | + refsSidebarRef.value.setActiveTab(type); |
| 261 | + }, 50); |
| 262 | + } else { |
| 263 | + console.error('refsSidebarRef is not available'); |
| 264 | + } |
| 265 | + }); |
| 266 | +} |
| 267 | +
|
| 268 | +// 添加对RefsSidebar的ref |
| 269 | +const refsSidebarRef = ref(null) |
225 | 270 |
|
226 | 271 | const consoleMsg = (msg) => console.log(msg) |
227 | 272 | onClickOutside(panel, () => setTimeout(() => opts.showPanel = false, 30)) |
@@ -358,6 +403,11 @@ const updateMessage = (info) => { |
358 | 403 | propertiesToUpdate.forEach(prop => { |
359 | 404 | if (info[prop] != null && (typeof info[prop] !== 'string' || info[prop] !== '')) { |
360 | 405 | msg[prop] = info[prop]; |
| 406 | +
|
| 407 | + // 如果更新了refs,同时更新全局refs |
| 408 | + if (prop === 'refs' && info.refs) { |
| 409 | + currentRefs.value = info.refs; |
| 410 | + } |
361 | 411 | } |
362 | 412 | }); |
363 | 413 |
|
@@ -446,6 +496,12 @@ const fetchChatResponse = (user_input, cur_res_id) => { |
446 | 496 | console.log(msg) |
447 | 497 | groupRefs(cur_res_id); |
448 | 498 | updateMessage({showThinking: "no", id: cur_res_id}); |
| 499 | + // 更新全局refs为最新消息的refs |
| 500 | + if (msg && msg.refs) { |
| 501 | + // 深拷贝refs以确保不会出现引用问题 |
| 502 | + currentRefs.value = JSON.parse(JSON.stringify(msg.refs)); |
| 503 | + console.log('Updated currentRefs on response completion:', currentRefs.value); |
| 504 | + } |
449 | 505 | isStreaming.value = false; |
450 | 506 | if (conv.value.messages.length === 2) { renameTitle(); } |
451 | 507 | return; |
@@ -571,6 +627,11 @@ onMounted(() => { |
571 | 627 | const parsedMeta = JSON.parse(storedMeta); |
572 | 628 | Object.assign(meta, parsedMeta); |
573 | 629 | } |
| 630 | +
|
| 631 | + // 检查refsSidebarRef是否正确挂载 |
| 632 | + nextTick(() => { |
| 633 | + console.log('Is refsSidebarRef mounted?', !!refsSidebarRef.value); |
| 634 | + }); |
574 | 635 | }); |
575 | 636 |
|
576 | 637 | onUnmounted(() => { |
@@ -642,6 +703,26 @@ const selectModel = (provider, name) => { |
642 | 703 | configStore.setConfigValue('model_name', name) |
643 | 704 | // message.success(`已切换到模型: ${name} | ${provider}`) |
644 | 705 | } |
| 706 | +
|
| 707 | +// 判断是否是最新的助手消息 |
| 708 | +const isLatestMessage = (index) => { |
| 709 | + // 找到最后一条助手消息的索引 |
| 710 | + const lastAssistantMsgIndex = findLastIndex(conv.value.messages, |
| 711 | + msg => (msg.role === 'received' || msg.role === 'assistant') && msg.status === 'finished'); |
| 712 | +
|
| 713 | + // 如果当前索引等于最后一条助手消息的索引,则为最新消息 |
| 714 | + return index === lastAssistantMsgIndex; |
| 715 | +} |
| 716 | +
|
| 717 | +// 辅助函数:从后向前查找满足条件的元素索引 |
| 718 | +const findLastIndex = (array, predicate) => { |
| 719 | + for (let i = array.length - 1; i >= 0; i--) { |
| 720 | + if (predicate(array[i])) { |
| 721 | + return i; |
| 722 | + } |
| 723 | + } |
| 724 | + return -1; |
| 725 | +} |
645 | 726 | </script> |
646 | 727 |
|
647 | 728 | <style lang="less" scoped> |
|
0 commit comments