feat(chat): 支持流式回复与用户节点导航

This commit is contained in:
2026-06-05 00:11:53 +08:00
parent 84e045f5ab
commit 7ab5aad938
8 changed files with 676 additions and 15 deletions

View File

@@ -470,14 +470,47 @@ input:focus {
display: grid;
grid-template-rows: minmax(0, 1fr) auto;
min-height: 0;
height: calc(100vh - 60px);
background: #ffffff;
overflow: hidden;
}
.chat-scroll {
.chat-scroll-wrap {
position: relative;
min-height: 0;
padding: 32px min(6vw, 64px) 24px;
height: 100%;
}
.chat-scroll {
height: 100%;
min-height: 0;
padding: 32px 104px 24px min(6vw, 64px);
overflow-y: auto;
scroll-behavior: smooth;
scrollbar-width: thin;
scrollbar-color: #c4cfdd #f4f7fb;
}
.chat-scroll::-webkit-scrollbar {
width: 12px;
}
.chat-scroll::-webkit-scrollbar-track {
background: #f4f7fb;
}
.chat-scroll::-webkit-scrollbar-thumb {
border: 3px solid #f4f7fb;
border-radius: 999px;
background: #c4cfdd;
}
.chat-scroll::-webkit-scrollbar-thumb:hover {
background: #a9b8ca;
}
.hidden {
display: none;
}
.conversation-header,
@@ -533,10 +566,92 @@ input:focus {
margin: 0;
}
.message-bubble.streaming {
position: relative;
}
.message-bubble.streaming::after {
content: "";
display: inline-block;
width: 8px;
height: 18px;
margin-left: 6px;
border-radius: 999px;
background: var(--accent);
vertical-align: middle;
animation: pulse-caret 0.9s ease-in-out infinite;
}
.message,
.conversation-header {
scroll-margin-top: 20px;
}
.user-mark {
background: #dbe7ff;
}
.node-rail {
position: absolute;
top: 28px;
right: 28px;
bottom: 28px;
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
width: 28px;
pointer-events: none;
}
.node-rail-line {
position: absolute;
top: 10px;
bottom: 10px;
left: 50%;
width: 2px;
transform: translateX(-50%);
background: linear-gradient(180deg, #eef3fa 0%, #d6dfeb 100%);
border-radius: 999px;
}
.node-anchor {
position: relative;
z-index: 1;
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
border-radius: 999px;
text-decoration: none;
pointer-events: auto;
}
.node-dot {
width: 12px;
height: 12px;
border: 2px solid #d8e0eb;
border-radius: 999px;
background: #f5f8fc;
transition: transform 140ms ease, background 140ms ease, border-color 140ms ease;
}
.node-anchor:hover .node-dot {
transform: scale(1.08);
border-color: #9eb5df;
}
.node-anchor.active .node-dot {
border-color: var(--accent);
background: var(--accent);
}
.node-anchor.latest .node-dot {
background: #7f8da3;
border-color: #7f8da3;
}
.composer-wrap {
padding: 18px 24px 24px;
border-top: 1px solid var(--line);
@@ -604,6 +719,11 @@ input:focus {
font-weight: 700;
}
.send-button:disabled {
background: #a8bee8;
cursor: wait;
}
.sr-only {
position: absolute;
width: 1px;
@@ -693,6 +813,18 @@ input:focus {
.conversation-header {
flex-direction: column;
}
.chat-stage {
height: calc(100vh - 88px);
}
.chat-scroll {
padding-right: 72px;
}
.node-rail {
right: 14px;
}
}
@media (max-width: 640px) {
@@ -738,4 +870,37 @@ input:focus {
.send-button {
width: 100%;
}
.chat-shell {
padding: 0;
}
.chat-stage {
height: calc(100vh - 126px);
}
.chat-scroll {
padding-right: 44px;
}
.node-rail {
right: 8px;
gap: 10px;
width: 20px;
}
.node-dot {
width: 10px;
height: 10px;
}
}
@keyframes pulse-caret {
0%,
100% {
opacity: 0.25;
}
50% {
opacity: 1;
}
}