路由更新

This commit is contained in:
Wenjie Zhang 2025-03-29 19:14:03 +08:00
parent 27e44f26c8
commit 21dffc0f9a
3 changed files with 227 additions and 77 deletions

View File

@ -9,7 +9,8 @@ const router = createRouter({
path: '/',
name: 'main',
component: BlankLayout,
children: [ {
children: [
{
path: '',
name: 'Home',
component: () => import('../views/HomeView.vue'),
@ -49,6 +50,11 @@ const router = createRouter({
}
]
},
{
path: '/agent/:agent_id',
name: 'AgentSinglePage',
component: () => import('../views/AgentView.vue'),
},
{
path: '/graph',
name: 'graph',

View File

@ -3,7 +3,7 @@
<div class="chat">
<div class="chat-header">
<div class="header__left">
<a-dropdown>
<a-dropdown v-if="!useSingleMode">
<div class="current-agent nav-btn">
<RobotOutlined />&nbsp;
<span v-if="currentAgent">{{ currentAgent.name }}</span>
@ -17,6 +17,11 @@
</a-menu>
</template>
</a-dropdown>
<div v-else class="current-agent nav-btn">
<RobotOutlined />&nbsp;
<span v-if="currentAgent">{{ currentAgent.name }}</span>
<span v-else>加载中...</span>
</div>
</div>
<div class="header__right">
<div class="newchat nav-btn" @click="resetThread" :disabled="isProcessing">
@ -53,7 +58,7 @@
<div v-if="toolCall" class="tool-call-display" :class="{ 'is-collapsed': !expandedToolCalls.has(toolCall.id) }">
<div class="tool-header" @click="toggleToolCall(toolCall.id)">
<span v-if="!toolCall.toolResultMsg">
<ThunderboltOutlined /> &nbsp;
<LoadingOutlined /> &nbsp;
<span>正在调用工具: </span>
<span class="tool-name">{{ toolCall.function.name }}</span>
</span>
@ -107,11 +112,12 @@
</template>
<script setup>
import { ref, reactive, onMounted, watch, nextTick } from 'vue';
import { ref, reactive, onMounted, watch, nextTick, computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import {
MenuOutlined, RobotOutlined, SendOutlined, LoadingOutlined,
RobotOutlined, SendOutlined, LoadingOutlined,
ThunderboltOutlined, ReloadOutlined, CheckCircleOutlined,
DownOutlined, RightOutlined, PlusCircleOutlined
PlusCircleOutlined
} from '@ant-design/icons-vue';
import { Marked } from 'marked';
import { markedHighlight } from 'marked-highlight';
@ -121,6 +127,11 @@ import hljs from 'highlight.js';
import MessageInputComponent from '@/components/MessageInputComponent.vue'
import MessageComponent from '@/components/MessageComponent.vue'
// ========= agent id ====================
const route = useRoute();
const router = useRouter();
const useSingleMode = computed(() => !!route.params.agent_id);
// ==================== ====================
// Markdown
@ -171,7 +182,7 @@ const renderMarkdown = (text) => {
return marked.parse(text);
};
//
// TODO:
const scrollToBottom = async () => {
await nextTick();
if (!messagesContainer.value) return;
@ -276,6 +287,7 @@ const prepareMessageHistory = (msgs) => {
//
const selectAgent = (agentName) => {
if (useSingleMode.value) return; //
currentAgent.value = agents.value[agentName];
messages.value = [];
threadId.value = null;
@ -638,78 +650,54 @@ const fetchAgents = async () => {
}
};
// localStorage
const loadState = () => {
//
const savedAgent = localStorage.getItem('agent-current-agent');
if (savedAgent && agents.value[savedAgent]) {
currentAgent.value = agents.value[savedAgent];
}
//
const savedOptions = localStorage.getItem('agent-options');
if (savedOptions) {
Object.assign(options, JSON.parse(savedOptions));
}
//
const savedMessages = localStorage.getItem('agent-messages');
if (savedMessages) {
messages.value = JSON.parse(savedMessages);
}
// 线ID
const savedThreadId = localStorage.getItem('agent-thread-id');
if (savedThreadId) {
threadId.value = savedThreadId;
}
};
// localStorage
const saveState = () => {
//
if (currentAgent.value) {
localStorage.setItem('agent-current-agent', currentAgent.value.name);
}
//
localStorage.setItem('agent-options', JSON.stringify(options));
//
localStorage.setItem('agent-messages', JSON.stringify(messages.value));
// 线ID
if (threadId.value) {
localStorage.setItem('agent-thread-id', threadId.value);
} else {
localStorage.removeItem('agent-thread-id');
}
};
//
watch([currentAgent, options, messages, threadId], () => {
saveState();
}, { deep: true });
//
onMounted(async () => {
//
await fetchAgents();
//
loadState();
//
if (messages.value.length > 0) {
messages.value = prepareMessageHistory(messages.value);
}
});
//
watch(messages, () => {
scrollToBottom();
}, { deep: true });
//
onMounted(async () => {
try {
console.log("组件挂载");
//
await fetchAgents();
//
console.log("单页面模式:", useSingleMode.value);
console.log("路由参数:", route.params.agent_id);
console.log("智能体列表:", Object.keys(agents.value));
// - 使 Vue Router
// 使 setTimeout
setTimeout(async () => {
await loadAgentData();
console.log("初始化后消息数量:", messages.value.length);
}, 10);
} catch (error) {
console.error("组件挂载出错:", error);
}
});
//
watch(() => route.params.agent_id, async (newAgentId, oldAgentId) => {
try {
console.log("路由参数变化", oldAgentId, "->", newAgentId);
//
if (oldAgentId !== newAgentId) {
//
messages.value = [];
threadId.value = null;
resetStatusSteps();
//
await loadAgentData();
}
} catch (error) {
console.error('路由参数变化处理出错:', error);
}
}, { immediate: true });
//
const handleMetadata = (data) => {
// 线ID
@ -740,6 +728,161 @@ const toggleToolCall = (toolCallId) => {
expandedToolCalls.value.add(toolCallId);
}
};
// localStorage
const loadState = () => {
try {
//
const storagePrefix = useSingleMode.value ?
(route.params.agent_id ? `agent-single-${route.params.agent_id}` : null) :
'agent-multi';
if (!storagePrefix) {
console.error('无法确定存储前缀agent_id缺失');
return;
}
console.log("loadState with prefix:", storagePrefix);
//
if (useSingleMode.value) {
// loadAgentData
} else {
//
const savedAgent = localStorage.getItem(`${storagePrefix}-current-agent`);
if (savedAgent && agents.value && agents.value[savedAgent]) {
currentAgent.value = agents.value[savedAgent];
}
}
//
const savedOptions = localStorage.getItem(`${storagePrefix}-options`);
if (savedOptions) {
try {
Object.assign(options, JSON.parse(savedOptions));
} catch (e) {
console.error('解析选项数据出错:', e);
}
}
//
const savedMessages = localStorage.getItem(`${storagePrefix}-messages`);
if (savedMessages) {
try {
const parsedMessages = JSON.parse(savedMessages);
console.log(`加载消息历史 (${storagePrefix}):`, parsedMessages ? parsedMessages.length : 0);
if (Array.isArray(parsedMessages)) {
messages.value = parsedMessages;
}
//
console.log(`消息历史加载后数量:`, messages.value.length);
} catch (e) {
console.error('解析消息历史出错:', e);
}
}
// 线ID
const savedThreadId = localStorage.getItem(`${storagePrefix}-thread-id`);
if (savedThreadId) {
threadId.value = savedThreadId;
console.log(`加载线程ID (${storagePrefix}):`, threadId.value);
}
} catch (error) {
console.error('从localStorage加载状态出错:', error);
}
};
// localStorage
const saveState = () => {
try {
//
if (!currentAgent.value) {
console.log("当前没有选中智能体,跳过保存");
return;
}
// - agent_id
let prefix = 'agent-multi';
if (useSingleMode.value) {
if (route.params.agent_id) {
prefix = `agent-single-${route.params.agent_id}`;
} else {
console.error("保存状态时缺少agent_id");
return; //
}
}
console.log("saveState with prefix:", prefix);
//
if (!useSingleMode.value && currentAgent.value) {
localStorage.setItem(`${prefix}-current-agent`, currentAgent.value.name);
}
//
localStorage.setItem(`${prefix}-options`, JSON.stringify(options));
//
if (messages.value && messages.value.length > 0) {
console.log(`保存消息历史 (${prefix}):`, messages.value.length);
localStorage.setItem(`${prefix}-messages`, JSON.stringify(messages.value));
} else {
localStorage.removeItem(`${prefix}-messages`);
}
// 线ID
if (threadId.value) {
localStorage.setItem(`${prefix}-thread-id`, threadId.value);
console.log(`保存线程ID (${prefix}):`, threadId.value);
} else {
localStorage.removeItem(`${prefix}-thread-id`);
}
} catch (error) {
console.error('保存状态到localStorage出错:', error);
}
};
//
const loadAgentData = async () => {
try {
//
if (Object.keys(agents.value).length === 0) {
await fetchAgents();
}
//
if (useSingleMode.value && route.params.agent_id) {
const agentId = route.params.agent_id;
if (agents.value && agents.value[agentId]) {
currentAgent.value = agents.value[agentId];
console.log("设置当前智能体", currentAgent.value.name);
} else {
console.error("未找到指定的智能体:", agentId);
}
}
// - currentAgent
loadState();
//
if (messages.value && messages.value.length > 0) {
console.log("处理消息历史:", messages.value.length);
messages.value = prepareMessageHistory(messages.value);
}
} catch (error) {
console.error('加载智能体数据出错:', error);
}
};
//
watch([currentAgent, options, messages, threadId], () => {
try {
saveState();
} catch (error) {
console.error('保存状态时出错:', error);
}
}, { deep: true });
</script>
<style lang="less" scoped>
@ -750,6 +893,7 @@ const toggleToolCall = (toolCallId) => {
width: 100%;
height: 100%;
position: relative;
min-height: 100vh;
}
.chat {

View File

@ -6,7 +6,7 @@
>
</HeaderComponent>
<div class="tools-grid">
<div v-for="tool in tools" :key="tool.id" class="tool-card" @click="navigateToTool(tool.name)">
<div v-for="tool in tools" :key="tool.id" class="tool-card" @click="navigateToTool(tool.url)">
<div class="tool-header">
<h3>{{ tool.title }}</h3>
</div>
@ -48,8 +48,8 @@ const getTools = () => {
});
};
const navigateToTool = (toolName) => {
router.push(`/tools/${toolName}`);
const navigateToTool = (toolUrl) => {
router.push(toolUrl);
};
onMounted(() => {