From ae09cf358ebf2262a28e0fb93be43eb75ebdbd67 Mon Sep 17 00:00:00 2001 From: "mula.liu" Date: Tue, 4 Aug 2026 09:31:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=A1=B9=E7=9B=AE=E5=BA=93?= =?UTF-8?q?=E5=90=91=E9=87=8F=E5=8C=96=E5=8F=8A=E9=97=AE=E7=AD=94=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/chat.py | 4 ++- frontend/src/pages/Chat/Chat.css | 44 +++++++++++++++----------------- frontend/src/pages/Chat/Chat.jsx | 28 +++++++++++++++++++- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/backend/app/api/v1/chat.py b/backend/app/api/v1/chat.py index c354fc1..a474ab1 100644 --- a/backend/app/api/v1/chat.py +++ b/backend/app/api/v1/chat.py @@ -268,7 +268,9 @@ def _compact_cited_refs(answer: str, retrieved_docs): "citation_id": new_id, "file_path": file_path, "anchor_text": doc.get("anchor_text") or "", - "excerpt": doc.get("excerpt") or doc.get("content") or doc.get("anchor_text") or "", + # 优先使用命中文档的上下文片段(命中点前后扩展),避免分块边界 + # 的短文本(如文档末尾残余块)导致引用预览内容过少 + "excerpt": doc.get("content") or doc.get("excerpt") or doc.get("anchor_text") or "", }) old_to_new[old_id] = new_id diff --git a/frontend/src/pages/Chat/Chat.css b/frontend/src/pages/Chat/Chat.css index f1b3a99..7f7088a 100644 --- a/frontend/src/pages/Chat/Chat.css +++ b/frontend/src/pages/Chat/Chat.css @@ -410,7 +410,8 @@ vertical-align: super; color: #1677ff; font-weight: 600; - margin: 0 1px; + margin: 0 3px; + padding: 0 1px; cursor: pointer; } @@ -578,7 +579,7 @@ .chat-citation-preview { display: flex; flex-direction: column; - gap: 8px; + gap: 10px; max-width: 460px; } @@ -592,7 +593,7 @@ overflow: auto; word-break: break-word; line-height: 1.65; - padding: 10px; + padding: 12px 14px; border: 1px solid var(--border-color); border-radius: 8px; background: color-mix(in srgb, var(--border-color) 10%, transparent); @@ -646,13 +647,11 @@ } .chat-shell .chat-composer-shell { - margin: 0 24px 24px; + margin: 0 24px 12px; } .chat-new-composer { - min-height: 150px; - padding-top: 10px; - padding-bottom: 10px; + margin-bottom: 12px; } .chat-composer-input { @@ -697,18 +696,18 @@ } .chat-composer-plus { - width: 44px; - height: 44px; - min-width: 44px; + width: 32px; + height: 32px; + min-width: 32px; border: 1px solid #f0f0f0; border-radius: 50%; background: #fff; - box-shadow: 0 6px 18px rgba(15, 23, 42, 0.08); + box-shadow: 0 2px 8px rgba(15, 23, 42, 0.06); color: var(--text-color-secondary); display: inline-flex; align-items: center; justify-content: center; - font-size: 24px; + font-size: 16px; cursor: pointer; flex-shrink: 0; } @@ -778,21 +777,19 @@ } .chat-send-button { - width: 40px !important; - height: 40px !important; - min-width: 40px !important; + width: 32px !important; + height: 32px !important; + min-width: 32px !important; border: 1px solid #bebebe !important; background: #d1d1d1 !important; color: #fff !important; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.28); - font-size: 24px !important; + font-size: 14px !important; line-height: 1 !important; - transform: scale(1.08); - transform-origin: center; } .chat-send-button .anticon { - font-size: 22px; + font-size: 15px; } .chat-send-button:not(:disabled):hover { @@ -885,10 +882,9 @@ body.dark .chat-search-highlight { } .chat-send-button { - width: 48px !important; - height: 48px !important; - min-width: 48px !important; - font-size: 24px !important; - transform: scale(1.08); + width: 40px !important; + height: 40px !important; + min-width: 40px !important; + font-size: 18px !important; } } diff --git a/frontend/src/pages/Chat/Chat.jsx b/frontend/src/pages/Chat/Chat.jsx index 7e28c16..436eb30 100644 --- a/frontend/src/pages/Chat/Chat.jsx +++ b/frontend/src/pages/Chat/Chat.jsx @@ -38,6 +38,7 @@ import 'highlight.js/styles/github.css' import { createChatSession, deleteChatMessage, deleteChatSession, getChatMessages, getChatSessions, searchChatMessages, sendChatMessageStream, updateChatSessionTitle } from '@/api/chat' import { getMyProjects } from '@/api/project' import { getLLMModelConfigs } from '@/api/llmModelConfigs' +import useUserStore from '@/stores/userStore' import './Chat.css' const { TextArea } = Input @@ -208,6 +209,7 @@ function MessageActions({ content, onCopy, onDelete }) { function Chat() { const navigate = useNavigate() const location = useLocation() + const { user: currentUser } = useUserStore() const [searchParams, setSearchParams] = useSearchParams() const [sessions, setSessions] = useState([]) const [projects, setProjects] = useState([]) @@ -232,6 +234,7 @@ function Chat() { const [renameSession, setRenameSession] = useState(null) const [renameTitle, setRenameTitle] = useState('') const messageRefs = useRef(new Map()) + const messagesEndRef = useRef(null) const skipNextOpenSessionRef = useRef(null) const searchRequestIdRef = useRef(0) const newMode = location.pathname === '/chat/new' @@ -252,6 +255,19 @@ function Chat() { const canCreateSession = Boolean(newQuestion.trim() && currentProject && currentModel) const canSendMessage = Boolean(inputValue.trim() && currentSession) + // 与全站侧边栏/个人资料一致的用户头像:avatar 字段是相对路径时转换为 API 端点 + const userAvatarUrl = useMemo(() => { + const avatar = currentUser?.avatar + if (!avatar) return null + if (avatar.startsWith('http')) return avatar + const parts = avatar.split('/') + if (parts.length >= 3) { + return `/api/v1/auth/avatar/${parts[0]}/${parts[2]}` + } + return null + }, [currentUser]) + const userDisplayName = currentUser?.nickname || currentUser?.username + const groupedSessions = useMemo(() => { const groups = [] const groupMap = new Map() @@ -353,6 +369,11 @@ function Chat() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [sessionId, sessions.length, newMode]) + // 新会话打开或消息生成/更新时,自动滚动到对话底部 + useEffect(() => { + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' }) + }, [messages, currentSession]) + useEffect(() => { const target = searchParams.get('message_id') if (!target) return @@ -874,11 +895,16 @@ function Chat() { /> )} - {isUser && } />} + {isUser && ( + + {userDisplayName?.[0]?.toUpperCase() || 'U'} + + )} ) }) )} +