feat(页面): 重构聊天页面头部并集成标签管理
- 重构 Header 布局为两行结构 - 第一行:标题 + 操作按钮(思考、摘要、分享、导出) - 第二行:助手信息 + 标签管理器 - 添加渐变分隔线增强视觉层次 - 优化操作按钮样式统一为圆角方形 - 菜单文字汉化(Rename -> 重命名,Delete -> 删除)
This commit is contained in:
parent
bbe07e203e
commit
e7de47d0d9
@ -14,6 +14,7 @@ import { LinkPreviewModal } from '@/components/features/LinkPreviewModal';
|
|||||||
import { ExportDropdown } from '@/components/features/ExportDropdown';
|
import { ExportDropdown } from '@/components/features/ExportDropdown';
|
||||||
import { ShareModal } from '@/components/features/ShareModal';
|
import { ShareModal } from '@/components/features/ShareModal';
|
||||||
import { SummaryButton } from '@/components/features/SummaryGenerator';
|
import { SummaryButton } from '@/components/features/SummaryGenerator';
|
||||||
|
import { TagManager } from '@/components/features/Tags';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { useConversation, useConversations } from '@/hooks/useConversations';
|
import { useConversation, useConversations } from '@/hooks/useConversations';
|
||||||
import { useStreamChat, type ChatMessage } from '@/hooks/useStreamChat';
|
import { useStreamChat, type ChatMessage } from '@/hooks/useStreamChat';
|
||||||
@ -457,10 +458,10 @@ export default function ChatPage({ params }: PageProps) {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{/* 固定顶部 Header */}
|
{/* 固定顶部 Header */}
|
||||||
<header className="px-4 py-2 flex flex-col gap-1 border-b border-[var(--color-border)] bg-[var(--color-bg-primary)] sticky top-0 z-10">
|
<header className="flex flex-col border-b border-[var(--color-border)] bg-[var(--color-bg-primary)] sticky top-0 z-10">
|
||||||
{/* 第一行:标题和操作按钮 */}
|
{/* 第一行:标题 + 操作按钮 */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between gap-4 px-4 py-2">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3 flex-shrink-0">
|
||||||
<SidebarToggle onClick={() => setSidebarOpen(!sidebarOpen)} />
|
<SidebarToggle onClick={() => setSidebarOpen(!sidebarOpen)} />
|
||||||
|
|
||||||
{/* 标题区域 - 可点击显示下拉菜单 */}
|
{/* 标题区域 - 可点击显示下拉菜单 */}
|
||||||
@ -509,7 +510,7 @@ export default function ChatPage({ params }: PageProps) {
|
|||||||
<div className="relative" ref={titleMenuRef}>
|
<div className="relative" ref={titleMenuRef}>
|
||||||
<button
|
<button
|
||||||
onClick={() => setTitleMenuOpen(!titleMenuOpen)}
|
onClick={() => setTitleMenuOpen(!titleMenuOpen)}
|
||||||
className="flex items-center gap-1 text-base font-medium text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)] px-2 py-1 rounded-lg transition-colors max-w-[300px]"
|
className="flex items-center gap-1 text-base font-medium text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)] px-2 py-1 rounded-[4px] transition-colors max-w-[320px]"
|
||||||
>
|
>
|
||||||
<span className="truncate">{conversation?.title || 'New Chat'}</span>
|
<span className="truncate">{conversation?.title || 'New Chat'}</span>
|
||||||
<ChevronDown size={16} className={cn(
|
<ChevronDown size={16} className={cn(
|
||||||
@ -520,76 +521,87 @@ export default function ChatPage({ params }: PageProps) {
|
|||||||
|
|
||||||
{/* 下拉菜单 */}
|
{/* 下拉菜单 */}
|
||||||
{titleMenuOpen && (
|
{titleMenuOpen && (
|
||||||
<div className="absolute left-0 top-full mt-1 bg-[var(--color-bg-primary)] border border-[var(--color-border)] rounded-lg shadow-lg py-1 z-20 min-w-[140px]">
|
<div className="absolute left-0 top-full mt-1 bg-[var(--color-bg-primary)] border border-[var(--color-border)] rounded-[4px] shadow-lg py-1 z-20 min-w-[140px]">
|
||||||
<button
|
<button
|
||||||
onClick={handleStartRename}
|
onClick={handleStartRename}
|
||||||
className="w-full px-3 py-2 text-left text-sm text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-hover)] flex items-center gap-2"
|
className="w-full px-3 py-2 text-left text-sm text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-hover)] flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<Pencil size={14} />
|
<Pencil size={14} />
|
||||||
Rename
|
重命名
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleDeleteConversation}
|
onClick={handleDeleteConversation}
|
||||||
className="w-full px-3 py-2 text-left text-sm text-red-500 hover:bg-[var(--color-bg-hover)] flex items-center gap-2"
|
className="w-full px-3 py-2 text-left text-sm text-red-500 hover:bg-[var(--color-bg-hover)] flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<Trash2 size={14} />
|
<Trash2 size={14} />
|
||||||
Delete
|
删除
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
|
{/* 右侧操作按钮 */}
|
||||||
|
<div className="flex items-center gap-1 flex-shrink-0">
|
||||||
{/* 思考模式开关 - 只在非 Codex 模型时显示 */}
|
{/* 思考模式开关 - 只在非 Codex 模型时显示 */}
|
||||||
{!selectedModelId.toLowerCase().includes('codex') && (
|
{!selectedModelId.toLowerCase().includes('codex') && (
|
||||||
|
<button
|
||||||
|
onClick={handleThinkingToggle}
|
||||||
|
className={cn(
|
||||||
|
'flex items-center gap-2 px-3 py-1.5 text-sm rounded-[4px] transition-colors',
|
||||||
|
enableThinking
|
||||||
|
? 'bg-[var(--color-primary-light)] text-[var(--color-primary)]'
|
||||||
|
: 'text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-hover)]'
|
||||||
|
)}
|
||||||
|
title={enableThinking ? '关闭思考模式' : '开启思考模式'}
|
||||||
|
>
|
||||||
|
<Clock size={16} />
|
||||||
|
<span>思考</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 智能摘要按钮 */}
|
||||||
|
<SummaryButton
|
||||||
|
conversationId={chatId}
|
||||||
|
messages={messages.map(m => ({
|
||||||
|
role: m.role,
|
||||||
|
content: m.content,
|
||||||
|
}))}
|
||||||
|
hasSummary={!!conversation?.summary}
|
||||||
|
existingSummary={conversation?.summary}
|
||||||
|
/>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handleThinkingToggle}
|
onClick={() => setShareModalOpen(true)}
|
||||||
className={cn(
|
className="flex items-center gap-2 px-3 py-1.5 text-sm text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-hover)] rounded-[4px] transition-colors"
|
||||||
'flex items-center gap-2 px-3 py-1.5 text-sm rounded-lg transition-colors',
|
title="分享对话"
|
||||||
enableThinking
|
|
||||||
? 'bg-[var(--color-primary-light)] text-[var(--color-primary)]'
|
|
||||||
: 'text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-hover)]'
|
|
||||||
)}
|
|
||||||
title={enableThinking ? '关闭思考模式' : '开启思考模式'}
|
|
||||||
>
|
>
|
||||||
<Clock size={16} />
|
<Share2 size={16} />
|
||||||
<span>思考</span>
|
<span>分享</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
<ExportDropdown
|
||||||
|
conversationId={chatId}
|
||||||
{/* 智能摘要按钮 */}
|
conversationTitle={conversation?.title || '新对话'}
|
||||||
<SummaryButton
|
disabled={isStreaming}
|
||||||
conversationId={chatId}
|
/>
|
||||||
messages={messages.map(m => ({
|
|
||||||
role: m.role,
|
|
||||||
content: m.content,
|
|
||||||
}))}
|
|
||||||
hasSummary={!!conversation?.summary}
|
|
||||||
existingSummary={conversation?.summary}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={() => setShareModalOpen(true)}
|
|
||||||
className="flex items-center gap-2 px-3 py-1.5 text-sm text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-hover)] rounded-lg transition-colors"
|
|
||||||
title="分享对话"
|
|
||||||
>
|
|
||||||
<Share2 size={16} />
|
|
||||||
<span>分享</span>
|
|
||||||
</button>
|
|
||||||
<ExportDropdown
|
|
||||||
conversationId={chatId}
|
|
||||||
conversationTitle={conversation?.title || '新对话'}
|
|
||||||
disabled={isStreaming}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 第二行:助手信息 */}
|
{/* 渐变分隔线 */}
|
||||||
<div className="pl-12">
|
<div className="h-px mx-4" style={{ background: 'linear-gradient(90deg, transparent, var(--color-border), transparent)' }} />
|
||||||
|
|
||||||
|
{/* 第二行:助手信息 + 标签管理 */}
|
||||||
|
<div className="flex items-center justify-between gap-4 px-4 py-2 pl-[60px]">
|
||||||
|
{/* 左侧:助手信息 */}
|
||||||
<ChatHeaderInfo
|
<ChatHeaderInfo
|
||||||
assistant={conversation?.assistant || null}
|
assistant={conversation?.assistant || null}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* 右侧:标签管理区域 */}
|
||||||
|
{conversation && !isNewChat && (
|
||||||
|
<TagManager conversationId={chatId} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user