feat: 支持聊天对话搜索 #37

This commit is contained in:
digua
2026-01-30 23:59:23 +08:00
committed by digua
parent 51ed4a9f53
commit 3804b0b2a4
4 changed files with 68 additions and 27 deletions
+58 -19
View File
@@ -40,6 +40,27 @@ const deleteTarget = ref<AnalysisSession | null>(null)
// 版本号
const version = ref('')
// 搜索相关状态
const showSearch = ref(false)
const searchQuery = ref('')
// 过滤后的会话列表
const filteredSortedSessions = computed(() => {
if (!searchQuery.value.trim()) {
return sortedSessions.value
}
const query = searchQuery.value.toLowerCase().trim()
return sortedSessions.value.filter((s) => s.name.toLowerCase().includes(query))
})
// 切换搜索框显示
function toggleSearch() {
showSearch.value = !showSearch.value
if (!showSearch.value) {
searchQuery.value = ''
}
}
// 加载会话列表和版本号
onMounted(async () => {
sessionStore.loadSessions()
@@ -204,29 +225,40 @@ function getSessionAvatar(session: AnalysisSession): string | null {
<!-- 新建分析 -->
<SidebarButton icon="i-heroicons-plus" :title="t('sidebar.newAnalysis')" @click="handleImport" />
<!-- 工具 -->
<!-- <SidebarButton
icon="i-heroicons-wrench-screwdriver"
:title="t('sidebar.tools')"
:active="route.name === 'tools'"
@click="router.push({ name: 'tools' })"
/> -->
</div>
<!-- Session List -->
<div class="flex-1 relative min-h-0 flex flex-col">
<!-- 聊天记录标题 - 固定在顶部不随列表滚动 -->
<UTooltip
v-if="!isCollapsed && sessions.length > 0"
:text="t('sidebar.tooltip.hint')"
:popper="{ placement: 'right' }"
>
<div class="px-7 mb-2 flex items-center gap-1">
<div class="text-sm font-medium text-gray-500">{{ t('sidebar.chatHistory') }}</div>
<UIcon name="i-heroicons-question-mark-circle" class="size-3.5 text-gray-400" />
<div v-if="!isCollapsed && sessions.length > 0" class="px-4 mb-2">
<div class="flex items-center justify-between">
<UTooltip :text="t('sidebar.tooltip.hint')" :popper="{ placement: 'right' }">
<div class="flex items-center gap-1 pl-3">
<div class="text-sm font-medium text-gray-500">{{ t('sidebar.chatHistory') }}</div>
<UIcon name="i-heroicons-question-mark-circle" class="size-3.5 text-gray-400" />
</div>
</UTooltip>
<UTooltip :text="t('sidebar.tooltip.search')" :popper="{ placement: 'right' }">
<UButton
:icon="showSearch ? 'i-heroicons-x-mark' : 'i-heroicons-magnifying-glass'"
color="neutral"
variant="ghost"
size="xs"
@click="toggleSearch"
/>
</UTooltip>
</div>
</UTooltip>
<!-- 搜索框 -->
<div v-if="showSearch" class="mt-2">
<UInput
v-model="searchQuery"
:placeholder="t('sidebar.searchPlaceholder')"
icon="i-heroicons-magnifying-glass"
size="sm"
autofocus
/>
</div>
</div>
<!-- 聊天记录列表 - 可滚动区域滚动条贴边 -->
<div class="flex-1 overflow-y-auto">
@@ -234,9 +266,14 @@ function getSessionAvatar(session: AnalysisSession): string | null {
{{ t('sidebar.noRecords') }}
</div>
<!-- 搜索无结果 -->
<div v-else-if="filteredSortedSessions.length === 0 && searchQuery.trim() && !isCollapsed" class="py-8 text-center text-sm text-gray-500">
{{ t('sidebar.noSearchResult') }}
</div>
<div class="space-y-1 pb-8" :class="[isCollapsed ? '' : 'px-4']">
<UTooltip
v-for="session in sortedSessions"
v-for="session in filteredSortedSessions"
:key="session.id"
:text="isCollapsed ? session.name : ''"
:popper="{ placement: 'right' }"
@@ -248,7 +285,9 @@ function getSessionAvatar(session: AnalysisSession): string | null {
route.params.id === session.id && !isCollapsed
? 'bg-primary-100 text-gray-900 dark:bg-primary-900/30 dark:text-primary-100'
: 'text-gray-700 dark:text-gray-200 hover:bg-gray-200/60 dark:hover:bg-gray-800',
isCollapsed ? 'justify-center cursor-pointer h-13 w-13 rounded-full ml-3.5' : 'cursor-pointer w-full rounded-full',
isCollapsed
? 'justify-center cursor-pointer h-13 w-13 rounded-full ml-3.5'
: 'cursor-pointer w-full rounded-full',
]"
@click="router.push({ name: getSessionRouteName(session), params: { id: session.id } })"
>
+4 -1
View File
@@ -4,6 +4,8 @@
"tools": "Tools",
"chatHistory": "Chat History",
"noRecords": "No records",
"searchPlaceholder": "Search conversation name",
"noSearchResult": "No matching chat records found",
"contextMenu": {
"rename": "Rename",
"pin": "Pin",
@@ -21,7 +23,8 @@
"tooltip": {
"expand": "Expand sidebar",
"collapse": "Collapse sidebar",
"hint": "Right-click to rename or delete"
"hint": "Right-click to rename or delete",
"search": "Search chat records"
},
"sessionInfo": "{count} messages · {time}",
"footer": {
+5 -2
View File
@@ -2,8 +2,10 @@
"brand": "ChatLab",
"newAnalysis": "分析新聊天",
"tools": "实用工具",
"chatHistory": "聊天记录",
"chatHistory": "聊天对话",
"noRecords": "暂无记录",
"searchPlaceholder": "搜索对话名称",
"noSearchResult": "未找到匹配的聊天记录",
"contextMenu": {
"rename": "重命名",
"pin": "置顶",
@@ -21,7 +23,8 @@
"tooltip": {
"expand": "展开侧边栏",
"collapse": "收起侧边栏",
"hint": "右键可删除或重命名聊天记录"
"hint": "右键可删除或重命名聊天记录",
"search": "搜索聊天记录"
},
"sessionInfo": "{count} 条消息 · {time}",
"footer": {
+1 -5
View File
@@ -9,11 +9,7 @@ const { t } = useI18n()
<template>
<div class="flex h-full flex-col bg-white pt-8 dark:bg-[var(--color-page-dark)]">
<!-- Header -->
<PageHeader
:title="t('tools.title')"
:description="t('tools.description')"
icon="i-heroicons-rectangle-stack"
/>
<PageHeader :title="t('tools.title')" :description="t('tools.description')" icon="i-heroicons-rectangle-stack" />
<!-- Content -->
<div class="flex-1 overflow-auto p-6">