fix: 完成系统向智能体数据链路切换
- 切换工作台、聊天历史、资源候选与公共调用到 Agent - 加固资源绑定、删除保护及发布运行并发控制 - 隔离旧 Bot 专属服务和组件并保留兼容入口
This commit is contained in:
@@ -28,7 +28,8 @@ import ShowJson from '#/components/json/ShowJson.vue';
|
||||
interface Props {
|
||||
allowRegenerate?: boolean;
|
||||
allowVariantSwitch?: boolean;
|
||||
bot: any;
|
||||
assistant?: any;
|
||||
bot?: any;
|
||||
messages: ChatTimeTimelineItem[];
|
||||
regenerateDisabled?: boolean;
|
||||
switchingRoundIds?: string[];
|
||||
@@ -54,7 +55,7 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
function getAssistantAvatar() {
|
||||
return props.bot.icon || defaultAssistantAvatar;
|
||||
return props.assistant?.icon || props.bot?.icon || defaultAssistantAvatar;
|
||||
}
|
||||
function getUserAvatar() {
|
||||
return store.userInfo?.avatar || defaultUserAvatar;
|
||||
@@ -1,3 +1,3 @@
|
||||
export { default as ChatBubbleList } from './bubbleList.vue';
|
||||
export { default as ChatBubbleList } from '../chat-timeline/ChatBubbleList.vue';
|
||||
export { default as ChatContainer } from './container.vue';
|
||||
export { default as ChatSender } from './sender.vue';
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
import { tryit } from 'radash';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import { ChatBubbleList } from '#/components/chat';
|
||||
import ChatBubbleList from '#/components/chat-timeline/ChatBubbleList.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -58,7 +58,10 @@ const messagePage = ref({
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
const variantSwitchController = createChatVariantSwitchController<any, ChatTimeTimelineItem>({
|
||||
const variantSwitchController = createChatVariantSwitchController<
|
||||
any,
|
||||
ChatTimeTimelineItem
|
||||
>({
|
||||
mapRecords: (records) => ChatTimeHistoryMapper.fromHistoryRecords(records),
|
||||
onError: () => ElMessage.error('答案版本切换失败'),
|
||||
onStateChange: () => {
|
||||
@@ -78,7 +81,11 @@ const filteredSessions = computed(() => {
|
||||
const title = String(item.title || '').toLowerCase();
|
||||
const preview = String(item.lastMessagePreview || '').toLowerCase();
|
||||
const assistantName = String(item.assistantName || '').toLowerCase();
|
||||
return title.includes(keyword) || preview.includes(keyword) || assistantName.includes(keyword);
|
||||
return (
|
||||
title.includes(keyword) ||
|
||||
preview.includes(keyword) ||
|
||||
assistantName.includes(keyword)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -99,19 +106,20 @@ watch(
|
||||
messageList.value = [];
|
||||
return;
|
||||
}
|
||||
if (!currentSession.value || String(currentSession.value.id) !== String(sessionId)) {
|
||||
if (
|
||||
!currentSession.value ||
|
||||
String(currentSession.value.id) !== String(sessionId)
|
||||
) {
|
||||
await openSession(String(sessionId));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
async function fetchAssistants() {
|
||||
const [, res] = await tryit(api.get)('/userCenter/bot/list', {
|
||||
params: { status: 1 },
|
||||
});
|
||||
const [, res] = await tryit(api.get)('/userCenter/agent/list');
|
||||
if (res?.errorCode === 0) {
|
||||
assistantList.value = (res.data || []).map((item: any) => ({
|
||||
label: item.title,
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
}
|
||||
@@ -135,7 +143,9 @@ async function fetchSessions() {
|
||||
|
||||
async function openSession(sessionId: string | number) {
|
||||
drawerLoading.value = true;
|
||||
const [, summaryRes] = await tryit(api.get)(`/userCenter/chatHistory/sessions/${sessionId}`);
|
||||
const [, summaryRes] = await tryit(api.get)(
|
||||
`/userCenter/chatHistory/sessions/${sessionId}`,
|
||||
);
|
||||
if (summaryRes?.errorCode !== 0) {
|
||||
drawerLoading.value = false;
|
||||
return;
|
||||
@@ -306,9 +316,12 @@ async function renameSession(session: any) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
const [, res] = await tryit(api.post)(`/userCenter/chatHistory/sessions/${session.id}/rename`, {
|
||||
title: value,
|
||||
});
|
||||
const [, res] = await tryit(api.post)(
|
||||
`/userCenter/chatHistory/sessions/${session.id}/rename`,
|
||||
{
|
||||
title: value,
|
||||
},
|
||||
);
|
||||
if (res?.errorCode === 0) {
|
||||
ElMessage.success('重命名成功');
|
||||
if (currentSession.value?.id === session.id) {
|
||||
@@ -323,16 +336,21 @@ function deleteSession(session: any) {
|
||||
type: 'warning',
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
}).then(async () => {
|
||||
const [, res] = await tryit(api.post)(`/userCenter/chatHistory/sessions/${session.id}/delete`, {});
|
||||
if (res?.errorCode === 0) {
|
||||
ElMessage.success('删除成功');
|
||||
if (currentSession.value?.id === session.id) {
|
||||
closeDrawer();
|
||||
})
|
||||
.then(async () => {
|
||||
const [, res] = await tryit(api.post)(
|
||||
`/userCenter/chatHistory/sessions/${session.id}/delete`,
|
||||
{},
|
||||
);
|
||||
if (res?.errorCode === 0) {
|
||||
ElMessage.success('删除成功');
|
||||
if (currentSession.value?.id === session.id) {
|
||||
closeDrawer();
|
||||
}
|
||||
await fetchSessions();
|
||||
}
|
||||
await fetchSessions();
|
||||
}
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
function formatTime(value?: string) {
|
||||
@@ -350,7 +368,12 @@ function formatTime(value?: string) {
|
||||
<template>
|
||||
<ElContainer class="bg-background-deep h-full">
|
||||
<ElHeader class="!h-auto !px-8 !pb-0 !pt-8">
|
||||
<ElSpace direction="vertical" :size="20" alignment="flex-start" class="w-full">
|
||||
<ElSpace
|
||||
direction="vertical"
|
||||
:size="20"
|
||||
alignment="flex-start"
|
||||
class="w-full"
|
||||
>
|
||||
<div>
|
||||
<h1 class="text-2xl font-medium">聊天历史</h1>
|
||||
<p class="text-foreground/60 mt-2 text-sm">
|
||||
@@ -377,7 +400,9 @@ function formatTime(value?: string) {
|
||||
</ElHeader>
|
||||
|
||||
<ElMain class="!px-8 !pb-8">
|
||||
<div class="bg-background border-border min-h-full rounded-2xl border p-5">
|
||||
<div
|
||||
class="bg-background border-border min-h-full rounded-2xl border p-5"
|
||||
>
|
||||
<div v-if="filteredSessions.length > 0" class="flex flex-col gap-3">
|
||||
<button
|
||||
v-for="item in filteredSessions"
|
||||
@@ -387,27 +412,48 @@ function formatTime(value?: string) {
|
||||
>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="truncate text-base font-medium">{{ item.title || '未命名会话' }}</span>
|
||||
<ElTag size="small" effect="plain">{{ item.assistantName || '聊天助理' }}</ElTag>
|
||||
<span class="truncate text-base font-medium">{{
|
||||
item.title || '未命名会话'
|
||||
}}</span>
|
||||
<ElTag size="small" effect="plain">{{
|
||||
item.assistantName || '聊天助理'
|
||||
}}</ElTag>
|
||||
</div>
|
||||
<div class="text-foreground/65 mt-2 line-clamp-2 text-sm">
|
||||
{{ item.lastMessagePreview || '暂无消息内容' }}
|
||||
</div>
|
||||
<div class="text-foreground/50 mt-3 flex flex-wrap items-center gap-4 text-xs">
|
||||
<div
|
||||
class="text-foreground/50 mt-3 flex flex-wrap items-center gap-4 text-xs"
|
||||
>
|
||||
<span>最近发送人:{{ item.lastSenderName || '未知' }}</span>
|
||||
<span>消息数:{{ item.messageCount || 0 }}</span>
|
||||
<span>活跃时间:{{ formatTime(item.lastMessageAt || item.accessAt) }}</span>
|
||||
<span
|
||||
>活跃时间:{{
|
||||
formatTime(item.lastMessageAt || item.accessAt)
|
||||
}}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<ElButton link :icon="Edit" @click.stop="renameSession(item)">重命名</ElButton>
|
||||
<ElButton link type="danger" :icon="Delete" @click.stop="deleteSession(item)">删除</ElButton>
|
||||
<ElButton link :icon="Edit" @click.stop="renameSession(item)"
|
||||
>重命名</ElButton
|
||||
>
|
||||
<ElButton
|
||||
link
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
@click.stop="deleteSession(item)"
|
||||
>删除</ElButton
|
||||
>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<ElEmpty v-else description="暂无聊天历史" />
|
||||
|
||||
<div class="mt-6 flex justify-end" v-if="pageState.total > queryParams.pageSize">
|
||||
<div
|
||||
class="mt-6 flex justify-end"
|
||||
v-if="pageState.total > queryParams.pageSize"
|
||||
>
|
||||
<ElPagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
@@ -429,15 +475,23 @@ function formatTime(value?: string) {
|
||||
@close="closeDrawer"
|
||||
>
|
||||
<div v-loading="drawerLoading" class="flex h-full flex-col">
|
||||
<div class="border-border mb-4 flex items-center justify-between rounded-2xl border px-4 py-3">
|
||||
<div
|
||||
class="border-border mb-4 flex items-center justify-between rounded-2xl border px-4 py-3"
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<div class="truncate text-base font-medium">{{ currentSession?.title || '聊天详情' }}</div>
|
||||
<div class="truncate text-base font-medium">
|
||||
{{ currentSession?.title || '聊天详情' }}
|
||||
</div>
|
||||
<div class="text-foreground/55 mt-1 text-sm">
|
||||
{{ currentSession?.assistantName || '聊天助理' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-foreground/50 text-xs">
|
||||
{{ formatTime(currentSession?.lastMessageAt || currentSession?.accessAt) }}
|
||||
{{
|
||||
formatTime(
|
||||
currentSession?.lastMessageAt || currentSession?.accessAt,
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -453,7 +507,7 @@ function formatTime(value?: string) {
|
||||
</ElButton>
|
||||
</div>
|
||||
<ChatBubbleList
|
||||
:bot="{ icon: '', title: currentSession?.assistantName || '' }"
|
||||
:assistant="{ icon: '', title: currentSession?.assistantName || '' }"
|
||||
:messages="messageList"
|
||||
allow-variant-switch
|
||||
:switching-round-ids="currentSwitchingRoundIds()"
|
||||
|
||||
Reference in New Issue
Block a user