feat: 样式优化

This commit is contained in:
digua
2025-12-03 01:58:38 +08:00
parent f33ac3c30a
commit 9f08005086
4 changed files with 114 additions and 81 deletions
+29 -4
View File
@@ -13,8 +13,9 @@ defineProps<{
// 子 Tab 配置
const subTabs = [
{ id: 'chat-explorer', label: '对话式探索', icon: 'i-heroicons-chat-bubble-left-ellipsis' },
{ id: 'lab', label: '实验室', icon: 'i-heroicons-beaker' },
{ id: 'manual', label: '手动分析', icon: 'i-heroicons-adjustments-horizontal' },
{ id: 'manual', label: '筛选分析', icon: 'i-heroicons-adjustments-horizontal' },
{ id: 'sql', label: 'AI SQL', icon: 'i-heroicons-beaker' },
{ id: 'mbti', label: 'MBTI检测仪', icon: 'i-heroicons-heart' },
]
const activeSubTab = ref('chat-explorer')
@@ -50,14 +51,38 @@ const activeSubTab = ref('chat-explorer')
</div>
</div>
<!-- 手动分析 - 暂未实现 -->
<!-- 筛选分析 - 暂未实现 -->
<div v-else-if="activeSubTab === 'manual'" class="flex h-full items-center justify-center p-6">
<div
class="flex h-full w-full items-center justify-center rounded-xl border-2 border-dashed border-gray-300 bg-gray-50 dark:border-gray-700 dark:bg-gray-900/50"
>
<div class="text-center">
<UIcon name="i-heroicons-adjustments-horizontal" class="mx-auto h-12 w-12 text-gray-400" />
<p class="mt-3 text-sm font-medium text-gray-600 dark:text-gray-400">手动分析功能开发中</p>
<p class="mt-3 text-sm font-medium text-gray-600 dark:text-gray-400">筛选分析功能开发中</p>
<p class="mt-1 text-xs text-gray-400">敬请期待...</p>
</div>
</div>
</div>
<!-- AI SQL -->
<div v-else-if="activeSubTab === 'sql'" class="flex h-full items-center justify-center p-6">
<div
class="flex h-full w-full items-center justify-center rounded-xl border-2 border-dashed border-gray-300 bg-gray-50 dark:border-gray-700 dark:bg-gray-900/50"
>
<div class="text-center">
<UIcon name="i-heroicons-beaker" class="mx-auto h-12 w-12 text-gray-400" />
<p class="mt-3 text-sm font-medium text-gray-600 dark:text-gray-400">开发中</p>
<p class="mt-1 text-xs text-gray-400">敬请期待...</p>
</div>
</div>
</div>
<!-- MBTI检测仪 -->
<div v-else-if="activeSubTab === 'mbti'" class="flex h-full items-center justify-center p-6">
<div
class="flex h-full w-full items-center justify-center rounded-xl border-2 border-dashed border-gray-300 bg-gray-50 dark:border-gray-700 dark:bg-gray-900/50"
>
<div class="text-center">
<UIcon name="i-heroicons-beaker" class="mx-auto h-12 w-12 text-gray-400" />
<p class="mt-3 text-sm font-medium text-gray-600 dark:text-gray-400">开发中</p>
<p class="mt-1 text-xs text-gray-400">敬请期待...</p>
</div>
</div>
+51 -50
View File
@@ -71,9 +71,9 @@ function generateWelcomeMessage() {
return `👋 你好!我是 AI 助手,可以帮你探索「${props.sessionName}」的聊天记录。
你可以这样问我:
- "帮我找一下群里讨论买房的记录"
- "大家最近聊了什么有趣的话题"
- "谁是群里最活跃的人"
- 大家最近聊了什么有趣的话题
- 谁是群里最活跃的人
- 帮我找一下群里讨论买房的记录
${configHint}`
}
@@ -152,9 +152,9 @@ watch(
</script>
<template>
<div class="relative flex h-full overflow-hidden px-4">
<div class="flex h-full overflow-hidden">
<!-- 左侧对话记录列表 -->
<div class="absolute left-0 top-0 h-full w-64 p-4">
<div class="w-64 shrink-0 border-r border-gray-200 bg-gray-50/50 dark:border-gray-800 dark:bg-gray-900/50">
<ConversationList
ref="conversationListRef"
:session-id="sessionId"
@@ -167,45 +167,11 @@ watch(
</div>
<!-- 中间对话区域 -->
<div class="flex h-full flex-1 justify-center pl-64 pr-80">
<div
class="flex min-w-0 flex-1 max-w-3xl flex-col overflow-hidden rounded-xl bg-white shadow-sm dark:bg-gray-900"
>
<!-- 对话区域头部 -->
<div class="shrink-0 flex items-center justify-between border-b border-gray-200 px-4 py-3 dark:border-gray-800">
<div class="flex items-center gap-2">
<UIcon name="i-heroicons-sparkles" class="h-5 w-5 text-violet-500" />
<span class="font-medium text-gray-900 dark:text-white">AI 对话探索</span>
</div>
<div class="flex items-center gap-2">
<!-- 配置状态指示 -->
<div
v-if="!isCheckingConfig"
class="flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs"
:class="[
hasLLMConfig
? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400'
: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',
]"
>
<span class="h-2 w-2 rounded-full" :class="[hasLLMConfig ? 'bg-green-500' : 'bg-amber-500']" />
{{ hasLLMConfig ? '已配置' : '未配置' }}
</div>
<UButton
icon="i-heroicons-cog-6-tooth"
color="gray"
variant="ghost"
size="sm"
@click="showConfigModal = true"
>
配置
</UButton>
</div>
</div>
<div class="flex h-full flex-1">
<div class="flex min-w-[480px] flex-1 flex-col overflow-hidden">
<!-- 消息列表 -->
<div ref="messagesContainer" class="min-h-0 flex-1 overflow-y-auto p-4">
<div class="mx-auto space-y-4">
<div class="mx-auto max-w-3xl space-y-4">
<ChatMessage
v-for="msg in messages"
:key="msg.id"
@@ -238,18 +204,53 @@ watch(
</div>
</div>
<!-- 输入框 -->
<ChatInput
:disabled="isAIThinking"
:status="isAIThinking ? (isLoadingSource ? 'submitted' : 'streaming') : 'ready'"
@send="handleSend"
/>
<!-- 输入框区域 -->
<div class="p-4 pt-0">
<div class="mx-auto max-w-3xl">
<ChatInput
:disabled="isAIThinking"
:status="isAIThinking ? (isLoadingSource ? 'submitted' : 'streaming') : 'ready'"
@send="handleSend"
/>
<!-- 底部状态栏 -->
<div class="mt-2 flex items-center justify-between px-1">
<div class="flex items-center gap-2 text-xs text-gray-400">
<UIcon name="i-heroicons-sparkles" class="h-3.5 w-3.5" />
<span>AI 对话探索</span>
</div>
<div class="flex items-center gap-3">
<!-- 配置状态指示 -->
<div
v-if="!isCheckingConfig"
class="flex items-center gap-1.5 text-xs transition-colors"
:class="[hasLLMConfig ? 'text-gray-400' : 'text-amber-500 font-medium']"
>
<span class="h-1.5 w-1.5 rounded-full" :class="[hasLLMConfig ? 'bg-green-500' : 'bg-amber-500']" />
{{ hasLLMConfig ? '服务已连接' : '未配置 AI 服务' }}
</div>
<button
class="flex items-center gap-1 text-xs text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 transition-colors"
@click="showConfigModal = true"
>
<UIcon name="i-heroicons-cog-6-tooth" class="h-3.5 w-3.5" />
<span>配置</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧数据源面板限制高度 -->
<!-- 右侧数据源面板 -->
<Transition name="slide-fade">
<div v-if="sourceMessages.length > 0 && !isSourcePanelCollapsed" class="absolute right-0 top-0 h-full w-80 p-4">
<div
v-if="sourceMessages.length > 0 && !isSourcePanelCollapsed"
class="w-80 shrink-0 border-l border-gray-200 bg-gray-50/50 p-4 dark:border-gray-800 dark:bg-gray-900/50"
>
<DataSourcePanel
:messages="sourceMessages"
:keywords="currentKeywords"
+33 -26
View File
@@ -113,38 +113,46 @@ defineExpose({
</script>
<template>
<div class="flex h-full w-64 flex-col rounded-xl bg-white shadow-sm dark:bg-gray-900">
<div class="flex h-full w-64 flex-col">
<!-- 头部 -->
<div class="flex items-center justify-between border-b border-gray-200 px-4 py-3 dark:border-gray-800">
<div class="flex items-center gap-2">
<UIcon name="i-heroicons-chat-bubble-left-right" class="h-5 w-5 text-gray-500" />
<span class="font-medium text-gray-900 dark:text-white">对话记录</span>
</div>
<UButton icon="i-heroicons-plus" color="primary" variant="soft" size="xs" @click="emit('create')">新对话</UButton>
<div class="flex items-center justify-between px-2 py-4">
<span class="text-xs font-semibold tracking-wider text-gray-400 uppercase">History</span>
<UButton
icon="i-heroicons-plus"
color="gray"
variant="ghost"
size="xs"
class="text-gray-500 hover:text-gray-900 dark:hover:text-white"
@click="emit('create')"
/>
</div>
<!-- 对话列表 -->
<div class="flex-1 overflow-y-auto">
<div class="flex-1 overflow-y-auto px-2">
<!-- 加载中 -->
<div v-if="isLoading" class="flex items-center justify-center py-8">
<UIcon name="i-heroicons-arrow-path" class="h-6 w-6 animate-spin text-gray-400" />
<UIcon name="i-heroicons-arrow-path" class="h-5 w-5 animate-spin text-gray-400" />
</div>
<!-- 空状态 -->
<div v-else-if="conversations.length === 0" class="flex flex-col items-center justify-center py-8 text-center">
<UIcon name="i-heroicons-chat-bubble-left-ellipsis" class="h-10 w-10 text-gray-300 dark:text-gray-600" />
<p class="mt-2 text-sm text-gray-500">暂无对话</p>
<p class="text-xs text-gray-400">点击"新对话"开始</p>
<div v-else-if="conversations.length === 0" class="flex flex-col items-center justify-center py-12 text-center">
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-gray-50 dark:bg-gray-800">
<UIcon name="i-heroicons-chat-bubble-left" class="h-6 w-6 text-gray-300 dark:text-gray-600" />
</div>
<p class="mt-3 text-xs text-gray-400">暂无历史记录</p>
<UButton class="mt-2" size="xs" variant="link" color="primary" @click="emit('create')">开始新对话</UButton>
</div>
<!-- 对话列表 -->
<div v-else class="p-2 space-y-1">
<div v-else class="space-y-0.5">
<div
v-for="conv in conversations"
:key="conv.id"
class="group relative rounded-lg px-3 py-2.5 transition-colors cursor-pointer"
class="group relative rounded-lg px-3 py-2.5 transition-all cursor-pointer"
:class="[
activeId === conv.id ? 'bg-violet-50 dark:bg-violet-900/20' : 'hover:bg-gray-50 dark:hover:bg-gray-800/50',
activeId === conv.id
? 'bg-gray-100 text-gray-900 dark:bg-gray-800 dark:text-white'
: 'text-gray-600 hover:bg-gray-50 dark:text-gray-400 dark:hover:bg-gray-800/50',
]"
@click="emit('select', conv.id)"
>
@@ -152,8 +160,9 @@ defineExpose({
<template v-if="editingId === conv.id">
<input
v-model="editingTitle"
class="w-full rounded border border-gray-300 px-2 py-1 text-sm dark:border-gray-600 dark:bg-gray-800"
class="w-full rounded border-none bg-white px-2 py-1 text-sm shadow-sm ring-1 ring-gray-200 focus:ring-2 focus:ring-primary-500 dark:bg-gray-900 dark:ring-gray-700"
placeholder="输入标题..."
autoFocus
@blur="saveTitle(conv.id)"
@keyup.enter="saveTitle(conv.id)"
@click.stop
@@ -164,22 +173,18 @@ defineExpose({
<template v-else>
<div class="flex items-start justify-between gap-2">
<div class="min-w-0 flex-1">
<p
class="truncate text-sm font-medium"
:class="[
activeId === conv.id ? 'text-violet-700 dark:text-violet-400' : 'text-gray-900 dark:text-white',
]"
>
<p class="truncate text-sm font-medium">
{{ getTitle(conv) }}
</p>
<p class="mt-0.5 text-xs text-gray-400">
<p class="mt-1 text-[10px] text-gray-400 opacity-80">
{{ formatTime(conv.updatedAt) }}
</p>
</div>
<!-- 操作按钮 -->
<div
class="flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100"
class="flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100"
:class="{ 'opacity-100': activeId === conv.id }"
@click.stop
>
<UButton
@@ -187,13 +192,15 @@ defineExpose({
color="gray"
variant="ghost"
size="2xs"
class="text-gray-400 hover:text-gray-700 dark:hover:text-gray-200"
@click="startEditing(conv)"
/>
<UButton
icon="i-heroicons-trash"
color="red"
color="gray"
variant="ghost"
size="2xs"
class="text-gray-400 hover:text-red-500 dark:hover:text-red-400"
@click="handleDelete(conv.id)"
/>
</div>
+1 -1
View File
@@ -39,7 +39,7 @@ const tabs = [
{ id: 'quotes', label: '群语录', icon: 'i-heroicons-chat-bubble-bottom-center-text' },
{ id: 'relationships', label: '群关系', icon: 'i-heroicons-heart' },
{ id: 'timeline', label: '群趋势', icon: 'i-heroicons-chart-bar' },
{ id: 'ai', label: 'AI', icon: 'i-heroicons-sparkles' },
{ id: 'ai', label: 'AI实验室', icon: 'i-heroicons-sparkles' },
]
const activeTab = ref((route.query.tab as string) || 'overview')