feat: add streaming chat and evidence workspace

This commit is contained in:
gqt
2026-07-13 12:00:01 +08:00
parent 52e14986d4
commit 6e3f4b8d04
11 changed files with 370 additions and 3 deletions
+81
View File
@@ -139,6 +139,79 @@ a { color: inherit; text-decoration: none; }
.detail-pagination { padding-top: 9px; display: flex; align-items: center; justify-content: center; gap: 10px; color: #84908b; border-top: 1px solid var(--line); font-size: .65rem; }
.evidence-drawer { position: fixed; inset: 0 0 0 auto; z-index: 51; width: min(390px, 92vw); background: #f0f3f1; box-shadow: -24px 0 80px rgba(0,0,0,.2); animation: drawer-in .25s ease; }
.session-rail { min-height: 0; margin-top: 14px; display: flex; flex: 1; flex-direction: column; }
.new-session { width: 100%; justify-content: flex-start; }
.session-rail .nav-label { margin-top: 18px; }
.session-list { min-height: 0; display: grid; align-content: start; gap: 4px; overflow-y: auto; scrollbar-width: thin; }
.session-item { display: grid; grid-template-columns: minmax(0, 1fr) 30px; align-items: center; border-radius: 7px; color: #aebdb7; }
.session-item > button:first-child { min-width: 0; padding: 8px 7px; color: inherit; border: 0; background: transparent; text-align: left; cursor: pointer; }
.session-item strong, .session-item span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.session-item strong { font-size: .68rem; font-weight: 650; }
.session-item span { margin-top: 3px; color: #748b82; font-size: .56rem; }
.session-item .button { width: 28px; height: 28px; opacity: 0; color: #91a49d; }
.session-item:hover { background: rgba(255,255,255,.05); }
.session-item:hover .button { opacity: 1; }
.session-item--active { color: white; background: var(--forest-2); box-shadow: inset 3px 0 var(--ember); }
.session-empty { margin: 8px; color: #70867d; font-size: .62rem; }
.chat-workspace { display: grid; grid-template-columns: minmax(500px, 1fr) 330px; min-height: 100vh; }
.chat-main { min-width: 0; height: 100vh; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; background: rgba(250,250,247,.82); }
.chat-header { min-height: 78px; padding: 20px clamp(20px, 3vw, 38px); display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--line); background: rgba(255,255,255,.62); backdrop-filter: blur(12px); }
.chat-header h1 { margin: 5px 0 0; font-family: "Songti SC", Georgia, serif; font-size: 1.35rem; font-weight: 600; }
.evidence-trigger { display: none; }
.conversation-scroll { min-height: 0; padding: 26px clamp(20px, 4vw, 54px); overflow-y: auto; scroll-behavior: smooth; }
.chat-empty { min-height: 100%; display: grid; place-content: center; justify-items: center; text-align: center; }
.chat-empty > div { width: 57px; height: 57px; margin-bottom: 19px; display: grid; place-items: center; color: var(--ember); border: 1px solid #ddc9bd; border-radius: 50%; background: white; box-shadow: 0 16px 45px rgba(39,55,49,.08); }
.chat-empty h2 { margin: 8px 0 7px; font-family: "Songti SC", Georgia, serif; font-size: 1.45rem; font-weight: 600; }
.chat-empty > span { max-width: 360px; color: #7e8a85; font-size: .75rem; line-height: 1.7; }
.message-list, .streaming-turn { display: grid; gap: 21px; }
.streaming-turn { margin-top: 21px; }
.message { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 10px; align-items: start; animation: page-enter .25s ease both; }
.message--user { margin-left: clamp(20px, 15%, 110px); grid-template-columns: minmax(0, 1fr); }
.message--user .message-body { justify-self: end; max-width: 82%; padding: 10px 13px; border-radius: 12px 12px 3px 12px; background: #e2ebe7; }
.message--user .message-avatar { display: none; }
.message-avatar { width: 28px; height: 28px; display: grid; place-items: center; color: white; border-radius: 50%; background: var(--ember); box-shadow: 0 5px 14px rgba(172,86,53,.18); }
.message-body { min-width: 0; color: #374943; }
.message-body header { margin: 2px 0 7px; display: flex; align-items: baseline; gap: 8px; }
.message-body header strong { font-size: .72rem; }
.message-body header time { color: #929c98; font-size: .58rem; }
.message-body p { margin: 0; white-space: pre-wrap; font-size: .82rem; line-height: 1.82; }
.answer-copy { font-family: "Songti SC", Georgia, serif; }
.citation { display: inline-flex; margin: 0 2px; padding: 1px 5px; color: #a75435; border: 1px solid #dfc1af; border-radius: 4px; background: #fff5ef; cursor: pointer; font-family: "Avenir Next", sans-serif; font-size: .62rem; font-weight: 800; vertical-align: .08em; }
.citation--deleted { color: #8d9692; border-color: #d9dddb; background: #f0f1ee; cursor: default; }
.failed-message { display: flex; align-items: center; gap: 7px; color: var(--danger); }
.research-state { display: flex; align-items: center; gap: 8px; color: #73827c; font-family: "Avenir Next", sans-serif; font-size: .72rem !important; }
.typing-cursor { display: inline-block; width: 2px; height: 1em; margin-left: 3px; background: var(--ember); animation: blink .8s step-end infinite; vertical-align: -.12em; }
.pulse { color: var(--ember); animation: pulse 1.2s ease-in-out infinite; }
.chat-composer { position: relative; margin: 0 clamp(20px, 4vw, 54px) 20px; padding: 10px 10px 24px 13px; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 9px; border: 1px solid #cdd7d2; border-radius: 11px; background: white; box-shadow: 0 10px 35px rgba(37,54,47,.08); }
.chat-composer textarea { width: 100%; min-height: 45px; max-height: 140px; padding: 5px 0; resize: none; color: var(--ink); border: 0; outline: 0; background: transparent; font-size: .8rem; line-height: 1.55; }
.chat-composer textarea::placeholder { color: #9aa4a0; }
.chat-composer small { position: absolute; bottom: 7px; left: 13px; color: #a0aaa6; font-size: .54rem; }
.evidence-desktop { min-width: 0; border-left: 1px solid var(--line); background: #f0f3f1; }
.evidence-panel { height: 100vh; padding: 22px 17px 16px; display: flex; flex-direction: column; overflow: hidden; }
.evidence-header { min-height: 47px; display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: start; gap: 7px; }
.evidence-header h2 { margin: 5px 0 0; font-family: "Songti SC", Georgia, serif; font-size: 1.15rem; font-weight: 600; }
.evidence-header > span { margin-top: 7px; color: #82908a; font-size: .62rem; }
.evidence-empty { flex: 1; display: grid; place-content: center; justify-items: center; gap: 7px; color: #85918c; text-align: center; }
.evidence-empty svg { margin-bottom: 4px; color: var(--ember); }
.evidence-empty strong { color: var(--ink); font-family: "Songti SC", Georgia, serif; }
.evidence-empty span { max-width: 220px; font-size: .68rem; line-height: 1.6; }
.source-list { max-height: 42%; margin: 16px 0 11px; display: grid; align-content: start; gap: 7px; overflow-y: auto; }
.source-card { width: 100%; padding: 10px; display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 7px; color: #52625c; border: 1px solid #d8dfdb; border-radius: 8px; background: rgba(255,255,255,.64); cursor: pointer; text-align: left; }
.source-card > svg { margin-top: 1px; color: var(--ember); }
.source-card strong, .source-card small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.source-card strong { color: #354a42; font-size: .68rem; }
.source-card small { margin-top: 4px; color: #89948f; font-size: .58rem; }
.source-card--active { border-color: #d2a78e; background: white; box-shadow: inset 3px 0 var(--ember), 0 6px 20px rgba(41,58,51,.05); }
.source-detail { min-height: 0; flex: 1; padding: 14px; overflow-y: auto; color: #e7efeb; border-radius: 10px; background: var(--forest); }
.source-detail header { display: flex; justify-content: space-between; gap: 10px; }
.source-detail header strong { font-size: .68rem; }
.source-detail header span { color: #9fb1aa; font-size: .57rem; }
.source-detail p { margin: 12px 0 0; white-space: pre-wrap; color: #d8e2de; font-family: "Songti SC", Georgia, serif; font-size: .72rem; line-height: 1.85; }
@keyframes blink { 50% { opacity: 0; } }
@keyframes pulse { 50% { opacity: .45; transform: scale(.92); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes drawer-in { from { transform: translateX(100%); } }
@@ -160,6 +233,9 @@ a { color: inherit; text-decoration: none; }
.documents-workspace { display: block; }
.documents-detail-desktop { display: none; }
.detail-trigger { display: inline-flex; }
.chat-workspace { display: block; }
.evidence-desktop { display: none; }
.evidence-trigger { display: inline-flex; }
}
@media (max-width: 640px) {
@@ -172,6 +248,11 @@ a { color: inherit; text-decoration: none; }
.document-row { grid-template-columns: 40px minmax(0, 1fr); padding-right: 38px; }
.document-row .status { grid-column: 2; justify-self: start; }
.row-actions { grid-column: 2; }
.chat-main { height: calc(100vh - 58px); }
.chat-header { padding: 14px 16px; }
.conversation-scroll { padding: 20px 16px; }
.chat-composer { margin: 0 12px 12px; }
.message--user { margin-left: 16px; }
}
@media (prefers-reduced-motion: reduce) {