Merge pull request 'fix: 修复空会话返回 null 导致前端崩溃的问题' (#194) from develop into v2
All checks were successful
Deploy / deploy (push) Successful in 43s
All checks were successful
Deploy / deploy (push) Successful in 43s
Reviewed-on: http://8.161.227.145:3000/XEngineers/CamTalk/pulls/194
This commit was merged in pull request #194.
This commit is contained in:
@@ -273,6 +273,9 @@ func (h *ConversationHandler) GetMessages(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
count, _ := h.msgRepo.GetMessageCount(c.Request.Context(), sessionID)
|
count, _ := h.msgRepo.GetMessageCount(c.Request.Context(), sessionID)
|
||||||
|
if messages == nil {
|
||||||
|
messages = []store.StoredMessage{}
|
||||||
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"messages": messages,
|
"messages": messages,
|
||||||
"total": count,
|
"total": count,
|
||||||
@@ -314,6 +317,9 @@ func (h *ConversationHandler) GetMessages(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
messages := allMessages[start:]
|
messages := allMessages[start:]
|
||||||
|
|
||||||
|
if messages == nil {
|
||||||
|
messages = []models.Message{}
|
||||||
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"messages": messages,
|
"messages": messages,
|
||||||
"total": total,
|
"total": total,
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ func (r *PgMessageRepository) queryMessages(ctx context.Context, query string, a
|
|||||||
}
|
}
|
||||||
defer pgxRows.Close()
|
defer pgxRows.Close()
|
||||||
|
|
||||||
var messages []StoredMessage
|
messages := make([]StoredMessage, 0)
|
||||||
for pgxRows.Next() {
|
for pgxRows.Next() {
|
||||||
var m StoredMessage
|
var m StoredMessage
|
||||||
if err := pgxRows.Scan(&m.ID, &m.SessionID, &m.Role, &m.Content, &m.TokensUsed, &m.CreatedAt); err != nil {
|
if err := pgxRows.Scan(&m.ID, &m.SessionID, &m.Role, &m.Content, &m.TokensUsed, &m.CreatedAt); err != nil {
|
||||||
|
|||||||
@@ -217,7 +217,15 @@ body {
|
|||||||
background: rgba(10, 10, 15, 0.45);
|
background: rgba(10, 10, 15, 0.45);
|
||||||
backdrop-filter: blur(3px);
|
backdrop-filter: blur(3px);
|
||||||
-webkit-backdrop-filter: blur(3px);
|
-webkit-backdrop-filter: blur(3px);
|
||||||
animation: fadeIn 0.2s ease;
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 0.3s var(--transition-smooth);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-backdrop--visible {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
@@ -232,13 +240,18 @@ body {
|
|||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
border-right: 1px solid var(--color-border);
|
border-right: 1px solid var(--color-border);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
animation: slideInLeft 0.3s var(--transition-smooth);
|
|
||||||
box-shadow: 8px 0 40px rgba(10, 10, 15, 0.4);
|
box-shadow: 8px 0 40px rgba(10, 10, 15, 0.4);
|
||||||
|
transition: transform 0.3s var(--transition-smooth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slideInLeft {
|
.sidebar--collapsed {
|
||||||
from { transform: translateX(-100%); }
|
transform: translateX(-100%);
|
||||||
to { transform: translateX(0); }
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar--open {
|
||||||
|
transform: translateX(0);
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar--collapsed {
|
.sidebar--collapsed {
|
||||||
|
|||||||
@@ -118,8 +118,6 @@ export function SessionSidebar({
|
|||||||
return groups;
|
return groups;
|
||||||
}, [sessions, searchQuery]);
|
}, [sessions, searchQuery]);
|
||||||
|
|
||||||
if (!open) return null;
|
|
||||||
|
|
||||||
const groupLabels: Record<TimeGroup, string> = {
|
const groupLabels: Record<TimeGroup, string> = {
|
||||||
today: t("sidebar.today"),
|
today: t("sidebar.today"),
|
||||||
yesterday: t("sidebar.yesterday"),
|
yesterday: t("sidebar.yesterday"),
|
||||||
@@ -128,8 +126,11 @@ export function SessionSidebar({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="sidebar-backdrop" onClick={onClose} />
|
<div
|
||||||
<div className="sidebar">
|
className={`sidebar-backdrop ${open ? 'sidebar-backdrop--visible' : ''}`}
|
||||||
|
onClick={onClose}
|
||||||
|
/>
|
||||||
|
<div className={`sidebar ${open ? 'sidebar--open' : 'sidebar--collapsed'}`}>
|
||||||
{/* 头部:新建 + 收起 */}
|
{/* 头部:新建 + 收起 */}
|
||||||
<div className="sidebar__header">
|
<div className="sidebar__header">
|
||||||
<button className="sidebar__new-btn" onClick={onNewSession}>
|
<button className="sidebar__new-btn" onClick={onNewSession}>
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export function useSessionList(accessToken?: string | null) {
|
|||||||
try {
|
try {
|
||||||
const res = await listConversations(accessToken);
|
const res = await listConversations(accessToken);
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
const list = res.data.conversations.map(toSessionSummary);
|
const list = (res.data.conversations || []).map(toSessionSummary);
|
||||||
setSessions(list);
|
setSessions(list);
|
||||||
// 恢复上次选中的会话(如果仍然存在)
|
// 恢复上次选中的会话(如果仍然存在)
|
||||||
const lastId = localStorage.getItem(LAST_ACTIVE_KEY);
|
const lastId = localStorage.getItem(LAST_ACTIVE_KEY);
|
||||||
@@ -193,7 +193,7 @@ export function useSessionList(accessToken?: string | null) {
|
|||||||
try {
|
try {
|
||||||
const res = await getConversationMessages(accessToken, sessionId);
|
const res = await getConversationMessages(accessToken, sessionId);
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
return res.data.messages.map(toChatMessage);
|
return (res.data.messages || []).map(toChatMessage);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("[SessionList] 加载消息失败:", err);
|
console.error("[SessionList] 加载消息失败:", err);
|
||||||
|
|||||||
Reference in New Issue
Block a user